@openacp/cli 0.2.14 → 0.2.16
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/dist/cli.js +1 -1
- package/dist/{main-PB2TMO3M.js → main-C4QWS4PK.js} +2 -2
- package/dist/setup-5RQ7YLYW.js +343 -0
- package/dist/setup-5RQ7YLYW.js.map +1 -0
- package/package.json +2 -1
- package/dist/setup-4EBTX2NJ.js +0 -255
- package/dist/setup-4EBTX2NJ.js.map +0 -1
- /package/dist/{main-PB2TMO3M.js.map → main-C4QWS4PK.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -18,7 +18,7 @@ async function startServer() {
|
|
|
18
18
|
const configManager = new ConfigManager();
|
|
19
19
|
const configExists = await configManager.exists();
|
|
20
20
|
if (!configExists) {
|
|
21
|
-
const { runSetup } = await import("./setup-
|
|
21
|
+
const { runSetup } = await import("./setup-5RQ7YLYW.js");
|
|
22
22
|
const shouldStart = await runSetup(configManager);
|
|
23
23
|
if (!shouldStart) process.exit(0);
|
|
24
24
|
}
|
|
@@ -89,4 +89,4 @@ if (isDirectExecution) {
|
|
|
89
89
|
export {
|
|
90
90
|
startServer
|
|
91
91
|
};
|
|
92
|
-
//# sourceMappingURL=main-
|
|
92
|
+
//# sourceMappingURL=main-C4QWS4PK.js.map
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
// src/core/setup.ts
|
|
2
|
+
import { execFileSync } from "child_process";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
import { input, select } from "@inquirer/prompts";
|
|
6
|
+
var c = {
|
|
7
|
+
reset: "\x1B[0m",
|
|
8
|
+
bold: "\x1B[1m",
|
|
9
|
+
dim: "\x1B[2m",
|
|
10
|
+
green: "\x1B[32m",
|
|
11
|
+
yellow: "\x1B[33m",
|
|
12
|
+
red: "\x1B[31m",
|
|
13
|
+
cyan: "\x1B[36m",
|
|
14
|
+
white: "\x1B[37m"
|
|
15
|
+
};
|
|
16
|
+
var ok = (msg) => `${c.green}${c.bold}\u2713${c.reset} ${c.green}${msg}${c.reset}`;
|
|
17
|
+
var warn = (msg) => `${c.yellow}\u26A0 ${msg}${c.reset}`;
|
|
18
|
+
var fail = (msg) => `${c.red}\u2717 ${msg}${c.reset}`;
|
|
19
|
+
var step = (n, title) => `
|
|
20
|
+
${c.cyan}${c.bold}[${n}/3]${c.reset} ${c.bold}${title}${c.reset}
|
|
21
|
+
`;
|
|
22
|
+
var dim = (msg) => `${c.dim}${msg}${c.reset}`;
|
|
23
|
+
async function validateBotToken(token) {
|
|
24
|
+
try {
|
|
25
|
+
const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);
|
|
26
|
+
const data = await res.json();
|
|
27
|
+
if (data.ok && data.result) {
|
|
28
|
+
return {
|
|
29
|
+
ok: true,
|
|
30
|
+
botName: data.result.first_name,
|
|
31
|
+
botUsername: data.result.username
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return { ok: false, error: data.description || "Invalid token" };
|
|
35
|
+
} catch (err) {
|
|
36
|
+
return { ok: false, error: err.message };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function validateChatId(token, chatId) {
|
|
40
|
+
try {
|
|
41
|
+
const res = await fetch(`https://api.telegram.org/bot${token}/getChat`, {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: { "Content-Type": "application/json" },
|
|
44
|
+
body: JSON.stringify({ chat_id: chatId })
|
|
45
|
+
});
|
|
46
|
+
const data = await res.json();
|
|
47
|
+
if (!data.ok || !data.result) {
|
|
48
|
+
return { ok: false, error: data.description || "Invalid chat ID" };
|
|
49
|
+
}
|
|
50
|
+
if (data.result.type !== "supergroup") {
|
|
51
|
+
return {
|
|
52
|
+
ok: false,
|
|
53
|
+
error: `Chat is "${data.result.type}", must be a supergroup`
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
ok: true,
|
|
58
|
+
title: data.result.title,
|
|
59
|
+
isForum: data.result.is_forum === true
|
|
60
|
+
};
|
|
61
|
+
} catch (err) {
|
|
62
|
+
return { ok: false, error: err.message };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function promptManualChatId() {
|
|
66
|
+
return input({
|
|
67
|
+
message: "Supergroup chat ID (e.g. -1001234567890):",
|
|
68
|
+
validate: (val) => {
|
|
69
|
+
const n = Number(val.trim());
|
|
70
|
+
if (isNaN(n) || !Number.isInteger(n)) return "Chat ID must be an integer";
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
}).then((val) => Number(val.trim()));
|
|
74
|
+
}
|
|
75
|
+
async function detectChatId(token) {
|
|
76
|
+
let lastUpdateId = 0;
|
|
77
|
+
try {
|
|
78
|
+
const clearRes = await fetch(
|
|
79
|
+
`https://api.telegram.org/bot${token}/getUpdates?offset=-1`
|
|
80
|
+
);
|
|
81
|
+
const clearData = await clearRes.json();
|
|
82
|
+
if (clearData.ok && clearData.result?.length) {
|
|
83
|
+
lastUpdateId = clearData.result[clearData.result.length - 1].update_id;
|
|
84
|
+
}
|
|
85
|
+
} catch {
|
|
86
|
+
}
|
|
87
|
+
console.log("");
|
|
88
|
+
console.log(` ${c.bold}If you don't have a supergroup yet:${c.reset}`);
|
|
89
|
+
console.log(dim(" 1. Open Telegram \u2192 New Group \u2192 add your bot"));
|
|
90
|
+
console.log(dim(" 2. Group Settings \u2192 convert to Supergroup"));
|
|
91
|
+
console.log(dim(" 3. Enable Topics in group settings"));
|
|
92
|
+
console.log("");
|
|
93
|
+
console.log(` ${c.bold}Then send "hi" in the group.${c.reset}`);
|
|
94
|
+
console.log(
|
|
95
|
+
dim(
|
|
96
|
+
` Listening... press ${c.reset}${c.yellow}m${c.reset}${c.dim} to enter ID manually`
|
|
97
|
+
)
|
|
98
|
+
);
|
|
99
|
+
console.log("");
|
|
100
|
+
const MAX_ATTEMPTS = 120;
|
|
101
|
+
const POLL_INTERVAL = 1e3;
|
|
102
|
+
let cancelled = false;
|
|
103
|
+
const onKeypress = (data) => {
|
|
104
|
+
const key = data.toString();
|
|
105
|
+
if (key === "m" || key === "M") {
|
|
106
|
+
cancelled = true;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
if (process.stdin.isTTY) {
|
|
110
|
+
process.stdin.setRawMode(true);
|
|
111
|
+
process.stdin.resume();
|
|
112
|
+
process.stdin.on("data", onKeypress);
|
|
113
|
+
}
|
|
114
|
+
const cleanup = () => {
|
|
115
|
+
if (process.stdin.isTTY) {
|
|
116
|
+
process.stdin.removeListener("data", onKeypress);
|
|
117
|
+
process.stdin.setRawMode(false);
|
|
118
|
+
process.stdin.pause();
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
try {
|
|
122
|
+
for (let i = 0; i < MAX_ATTEMPTS; i++) {
|
|
123
|
+
if (cancelled) {
|
|
124
|
+
cleanup();
|
|
125
|
+
return promptManualChatId();
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
const offset = lastUpdateId ? lastUpdateId + 1 : 0;
|
|
129
|
+
const res = await fetch(
|
|
130
|
+
`https://api.telegram.org/bot${token}/getUpdates?offset=${offset}&timeout=1`
|
|
131
|
+
);
|
|
132
|
+
const data = await res.json();
|
|
133
|
+
if (!data.ok || !data.result?.length) {
|
|
134
|
+
await new Promise((r) => setTimeout(r, POLL_INTERVAL));
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const groups = /* @__PURE__ */ new Map();
|
|
138
|
+
for (const update of data.result) {
|
|
139
|
+
lastUpdateId = update.update_id;
|
|
140
|
+
const chat = update.message?.chat ?? update.my_chat_member?.chat;
|
|
141
|
+
if (chat && (chat.type === "supergroup" || chat.type === "group")) {
|
|
142
|
+
groups.set(chat.id, chat.title ?? String(chat.id));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (groups.size === 1) {
|
|
146
|
+
const [id, title] = [...groups.entries()][0];
|
|
147
|
+
console.log(
|
|
148
|
+
ok(`Group detected: ${c.bold}${title}${c.reset}${c.green} (${id})`)
|
|
149
|
+
);
|
|
150
|
+
cleanup();
|
|
151
|
+
return id;
|
|
152
|
+
}
|
|
153
|
+
if (groups.size > 1) {
|
|
154
|
+
cleanup();
|
|
155
|
+
const choices = [...groups.entries()].map(([id, title]) => ({
|
|
156
|
+
name: `${title} (${id})`,
|
|
157
|
+
value: id
|
|
158
|
+
}));
|
|
159
|
+
return select({
|
|
160
|
+
message: "Multiple groups found. Pick one:",
|
|
161
|
+
choices
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
} catch {
|
|
165
|
+
}
|
|
166
|
+
await new Promise((r) => setTimeout(r, POLL_INTERVAL));
|
|
167
|
+
}
|
|
168
|
+
console.log(warn("Timed out waiting for messages."));
|
|
169
|
+
cleanup();
|
|
170
|
+
return promptManualChatId();
|
|
171
|
+
} catch (err) {
|
|
172
|
+
cleanup();
|
|
173
|
+
throw err;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
var KNOWN_AGENTS = [
|
|
177
|
+
{ name: "claude", commands: ["claude-agent-acp"] }
|
|
178
|
+
];
|
|
179
|
+
function commandExists(cmd) {
|
|
180
|
+
try {
|
|
181
|
+
execFileSync("which", [cmd], { stdio: "pipe" });
|
|
182
|
+
return true;
|
|
183
|
+
} catch {
|
|
184
|
+
}
|
|
185
|
+
let dir = process.cwd();
|
|
186
|
+
while (true) {
|
|
187
|
+
const binPath = path.join(dir, "node_modules", ".bin", cmd);
|
|
188
|
+
if (fs.existsSync(binPath)) return true;
|
|
189
|
+
const parent = path.dirname(dir);
|
|
190
|
+
if (parent === dir) break;
|
|
191
|
+
dir = parent;
|
|
192
|
+
}
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
async function detectAgents() {
|
|
196
|
+
const found = [];
|
|
197
|
+
for (const agent of KNOWN_AGENTS) {
|
|
198
|
+
const available = [];
|
|
199
|
+
for (const cmd of agent.commands) {
|
|
200
|
+
if (commandExists(cmd)) {
|
|
201
|
+
available.push(cmd);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (available.length > 0) {
|
|
205
|
+
found.push({ name: agent.name, command: available[0] });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return found;
|
|
209
|
+
}
|
|
210
|
+
async function validateAgentCommand(command) {
|
|
211
|
+
try {
|
|
212
|
+
execFileSync("which", [command], { stdio: "pipe" });
|
|
213
|
+
return true;
|
|
214
|
+
} catch {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async function setupTelegram() {
|
|
219
|
+
console.log(step(1, "Telegram Bot"));
|
|
220
|
+
let botToken = "";
|
|
221
|
+
while (true) {
|
|
222
|
+
botToken = await input({
|
|
223
|
+
message: "Bot token (from @BotFather):",
|
|
224
|
+
validate: (val) => val.trim().length > 0 || "Token cannot be empty"
|
|
225
|
+
});
|
|
226
|
+
botToken = botToken.trim();
|
|
227
|
+
const result = await validateBotToken(botToken);
|
|
228
|
+
if (result.ok) {
|
|
229
|
+
console.log(ok(`Connected to @${result.botUsername}`));
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
console.log(fail(result.error));
|
|
233
|
+
const action = await select({
|
|
234
|
+
message: "What to do?",
|
|
235
|
+
choices: [
|
|
236
|
+
{ name: "Re-enter token", value: "retry" },
|
|
237
|
+
{ name: "Use as-is (skip validation)", value: "skip" }
|
|
238
|
+
]
|
|
239
|
+
});
|
|
240
|
+
if (action === "skip") break;
|
|
241
|
+
}
|
|
242
|
+
console.log(step(2, "Group Chat"));
|
|
243
|
+
const chatId = await detectChatId(botToken);
|
|
244
|
+
return {
|
|
245
|
+
enabled: true,
|
|
246
|
+
botToken,
|
|
247
|
+
chatId,
|
|
248
|
+
notificationTopicId: null,
|
|
249
|
+
assistantTopicId: null
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
async function setupAgents() {
|
|
253
|
+
const detected = await detectAgents();
|
|
254
|
+
const agents = {};
|
|
255
|
+
if (detected.length > 0) {
|
|
256
|
+
for (const agent of detected) {
|
|
257
|
+
agents[agent.name] = { command: agent.command, args: [], env: {} };
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
agents["claude"] = { command: "claude-agent-acp", args: [], env: {} };
|
|
261
|
+
}
|
|
262
|
+
const defaultAgent = Object.keys(agents)[0];
|
|
263
|
+
const agentCmd = agents[defaultAgent].command;
|
|
264
|
+
console.log(
|
|
265
|
+
ok(`Agent: ${c.bold}${defaultAgent}${c.reset}${c.green} (${agentCmd})`)
|
|
266
|
+
);
|
|
267
|
+
return { agents, defaultAgent };
|
|
268
|
+
}
|
|
269
|
+
async function setupWorkspace() {
|
|
270
|
+
console.log(step(3, "Workspace"));
|
|
271
|
+
const baseDir = await input({
|
|
272
|
+
message: "Base directory for workspaces:",
|
|
273
|
+
default: "~/openacp-workspace",
|
|
274
|
+
validate: (val) => val.trim().length > 0 || "Path cannot be empty"
|
|
275
|
+
});
|
|
276
|
+
return { baseDir: baseDir.trim().replace(/^['"]|['"]$/g, "") };
|
|
277
|
+
}
|
|
278
|
+
function printWelcomeBanner() {
|
|
279
|
+
console.log(`
|
|
280
|
+
${c.cyan}${c.bold} \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
281
|
+
\u2551 Welcome to OpenACP \u2551
|
|
282
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D${c.reset}
|
|
283
|
+
`);
|
|
284
|
+
}
|
|
285
|
+
async function runSetup(configManager) {
|
|
286
|
+
printWelcomeBanner();
|
|
287
|
+
try {
|
|
288
|
+
const telegram = await setupTelegram();
|
|
289
|
+
const { agents, defaultAgent } = await setupAgents();
|
|
290
|
+
const workspace = await setupWorkspace();
|
|
291
|
+
const security = {
|
|
292
|
+
allowedUserIds: [],
|
|
293
|
+
maxConcurrentSessions: 5,
|
|
294
|
+
sessionTimeoutMinutes: 60
|
|
295
|
+
};
|
|
296
|
+
const config = {
|
|
297
|
+
channels: { telegram },
|
|
298
|
+
agents,
|
|
299
|
+
defaultAgent,
|
|
300
|
+
workspace,
|
|
301
|
+
security,
|
|
302
|
+
logging: {
|
|
303
|
+
level: "info",
|
|
304
|
+
logDir: "~/.openacp/logs",
|
|
305
|
+
maxFileSize: "10m",
|
|
306
|
+
maxFiles: 7,
|
|
307
|
+
sessionLogRetentionDays: 30
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
try {
|
|
311
|
+
await configManager.writeNew(config);
|
|
312
|
+
} catch (writeErr) {
|
|
313
|
+
console.log(
|
|
314
|
+
fail(`Could not save config: ${writeErr.message}`)
|
|
315
|
+
);
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
console.log("");
|
|
319
|
+
console.log(
|
|
320
|
+
ok(`Config saved to ${c.bold}${configManager.getConfigPath()}`)
|
|
321
|
+
);
|
|
322
|
+
console.log(ok("Starting OpenACP..."));
|
|
323
|
+
console.log("");
|
|
324
|
+
return true;
|
|
325
|
+
} catch (err) {
|
|
326
|
+
if (err.name === "ExitPromptError") {
|
|
327
|
+
console.log(dim("\nSetup cancelled."));
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
throw err;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
export {
|
|
334
|
+
detectAgents,
|
|
335
|
+
runSetup,
|
|
336
|
+
setupAgents,
|
|
337
|
+
setupTelegram,
|
|
338
|
+
setupWorkspace,
|
|
339
|
+
validateAgentCommand,
|
|
340
|
+
validateBotToken,
|
|
341
|
+
validateChatId
|
|
342
|
+
};
|
|
343
|
+
//# sourceMappingURL=setup-5RQ7YLYW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/setup.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { input, select } from \"@inquirer/prompts\";\nimport type { Config, ConfigManager } from \"./config.js\";\n\n// --- ANSI colors ---\n\nconst c = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n dim: \"\\x1b[2m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n red: \"\\x1b[31m\",\n cyan: \"\\x1b[36m\",\n white: \"\\x1b[37m\",\n};\n\nconst ok = (msg: string) =>\n `${c.green}${c.bold}✓${c.reset} ${c.green}${msg}${c.reset}`;\nconst warn = (msg: string) => `${c.yellow}⚠ ${msg}${c.reset}`;\nconst fail = (msg: string) => `${c.red}✗ ${msg}${c.reset}`;\nconst step = (n: number, title: string) =>\n `\\n${c.cyan}${c.bold}[${n}/3]${c.reset} ${c.bold}${title}${c.reset}\\n`;\nconst dim = (msg: string) => `${c.dim}${msg}${c.reset}`;\n\n// --- Telegram validation ---\n\nexport async function validateBotToken(\n token: string,\n): Promise<\n | { ok: true; botName: string; botUsername: string }\n | { ok: false; error: string }\n> {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);\n const data = (await res.json()) as {\n ok: boolean;\n result?: { first_name: string; username: string };\n description?: string;\n };\n if (data.ok && data.result) {\n return {\n ok: true,\n botName: data.result.first_name,\n botUsername: data.result.username,\n };\n }\n return { ok: false, error: data.description || \"Invalid token\" };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n\nexport async function validateChatId(\n token: string,\n chatId: number,\n): Promise<\n { ok: true; title: string; isForum: boolean } | { ok: false; error: string }\n> {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getChat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ chat_id: chatId }),\n });\n const data = (await res.json()) as {\n ok: boolean;\n result?: { title: string; type: string; is_forum?: boolean };\n description?: string;\n };\n if (!data.ok || !data.result) {\n return { ok: false, error: data.description || \"Invalid chat ID\" };\n }\n if (data.result.type !== \"supergroup\") {\n return {\n ok: false,\n error: `Chat is \"${data.result.type}\", must be a supergroup`,\n };\n }\n return {\n ok: true,\n title: data.result.title,\n isForum: data.result.is_forum === true,\n };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n\n// --- Chat ID auto-detection ---\n\nfunction promptManualChatId(): Promise<number> {\n return input({\n message: \"Supergroup chat ID (e.g. -1001234567890):\",\n validate: (val) => {\n const n = Number(val.trim());\n if (isNaN(n) || !Number.isInteger(n)) return \"Chat ID must be an integer\";\n return true;\n },\n }).then((val) => Number(val.trim()));\n}\n\nasync function detectChatId(token: string): Promise<number> {\n // Clear old updates\n let lastUpdateId = 0;\n try {\n const clearRes = await fetch(\n `https://api.telegram.org/bot${token}/getUpdates?offset=-1`,\n );\n const clearData = (await clearRes.json()) as {\n ok: boolean;\n result?: Array<{ update_id: number }>;\n };\n if (clearData.ok && clearData.result?.length) {\n lastUpdateId = clearData.result[clearData.result.length - 1].update_id;\n }\n } catch {\n // ignore\n }\n\n console.log(\"\");\n console.log(` ${c.bold}If you don't have a supergroup yet:${c.reset}`);\n console.log(dim(\" 1. Open Telegram → New Group → add your bot\"));\n console.log(dim(\" 2. Group Settings → convert to Supergroup\"));\n console.log(dim(\" 3. Enable Topics in group settings\"));\n console.log(\"\");\n console.log(` ${c.bold}Then send \"hi\" in the group.${c.reset}`);\n console.log(\n dim(\n ` Listening... press ${c.reset}${c.yellow}m${c.reset}${c.dim} to enter ID manually`,\n ),\n );\n console.log(\"\");\n\n const MAX_ATTEMPTS = 120;\n const POLL_INTERVAL = 1000;\n\n // Listen for 'm' keypress to switch to manual\n let cancelled = false;\n const onKeypress = (data: Buffer) => {\n const key = data.toString();\n if (key === \"m\" || key === \"M\") {\n cancelled = true;\n }\n };\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n process.stdin.resume();\n process.stdin.on(\"data\", onKeypress);\n }\n\n const cleanup = () => {\n if (process.stdin.isTTY) {\n process.stdin.removeListener(\"data\", onKeypress);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n }\n };\n\n try {\n for (let i = 0; i < MAX_ATTEMPTS; i++) {\n if (cancelled) {\n cleanup();\n return promptManualChatId();\n }\n\n try {\n const offset = lastUpdateId ? lastUpdateId + 1 : 0;\n const res = await fetch(\n `https://api.telegram.org/bot${token}/getUpdates?offset=${offset}&timeout=1`,\n );\n const data = (await res.json()) as {\n ok: boolean;\n result?: Array<{\n update_id: number;\n message?: {\n chat: { id: number; title?: string; type: string };\n };\n my_chat_member?: {\n chat: { id: number; title?: string; type: string };\n };\n }>;\n };\n\n if (!data.ok || !data.result?.length) {\n await new Promise((r) => setTimeout(r, POLL_INTERVAL));\n continue;\n }\n\n const groups = new Map<number, string>();\n for (const update of data.result) {\n lastUpdateId = update.update_id;\n const chat = update.message?.chat ?? update.my_chat_member?.chat;\n if (chat && (chat.type === \"supergroup\" || chat.type === \"group\")) {\n groups.set(chat.id, chat.title ?? String(chat.id));\n }\n }\n\n if (groups.size === 1) {\n const [id, title] = [...groups.entries()][0];\n console.log(\n ok(`Group detected: ${c.bold}${title}${c.reset}${c.green} (${id})`),\n );\n cleanup();\n return id;\n }\n\n if (groups.size > 1) {\n cleanup();\n const choices = [...groups.entries()].map(([id, title]) => ({\n name: `${title} (${id})`,\n value: id,\n }));\n return select({\n message: \"Multiple groups found. Pick one:\",\n choices,\n });\n }\n } catch {\n // Network error, retry\n }\n await new Promise((r) => setTimeout(r, POLL_INTERVAL));\n }\n\n console.log(warn(\"Timed out waiting for messages.\"));\n cleanup();\n return promptManualChatId();\n } catch (err) {\n cleanup();\n throw err;\n }\n}\n\n// --- Agent detection ---\n\nconst KNOWN_AGENTS: Array<{ name: string; commands: string[] }> = [\n { name: \"claude\", commands: [\"claude-agent-acp\"] },\n];\n\nfunction commandExists(cmd: string): boolean {\n try {\n execFileSync(\"which\", [cmd], { stdio: \"pipe\" });\n return true;\n } catch {\n // not in PATH\n }\n let dir = process.cwd();\n while (true) {\n const binPath = path.join(dir, \"node_modules\", \".bin\", cmd);\n if (fs.existsSync(binPath)) return true;\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return false;\n}\n\nexport async function detectAgents(): Promise<\n Array<{ name: string; command: string }>\n> {\n const found: Array<{ name: string; command: string }> = [];\n for (const agent of KNOWN_AGENTS) {\n const available: string[] = [];\n for (const cmd of agent.commands) {\n if (commandExists(cmd)) {\n available.push(cmd);\n }\n }\n if (available.length > 0) {\n found.push({ name: agent.name, command: available[0] });\n }\n }\n return found;\n}\n\nexport async function validateAgentCommand(command: string): Promise<boolean> {\n try {\n execFileSync(\"which\", [command], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\n\n// --- Setup steps ---\n\nexport async function setupTelegram(): Promise<Config[\"channels\"][string]> {\n console.log(step(1, \"Telegram Bot\"));\n\n let botToken = \"\";\n\n while (true) {\n botToken = await input({\n message: \"Bot token (from @BotFather):\",\n validate: (val) => val.trim().length > 0 || \"Token cannot be empty\",\n });\n botToken = botToken.trim();\n\n const result = await validateBotToken(botToken);\n if (result.ok) {\n console.log(ok(`Connected to @${result.botUsername}`));\n break;\n }\n console.log(fail(result.error));\n const action = await select({\n message: \"What to do?\",\n choices: [\n { name: \"Re-enter token\", value: \"retry\" },\n { name: \"Use as-is (skip validation)\", value: \"skip\" },\n ],\n });\n if (action === \"skip\") break;\n }\n\n console.log(step(2, \"Group Chat\"));\n\n const chatId = await detectChatId(botToken);\n\n return {\n enabled: true,\n botToken,\n chatId,\n notificationTopicId: null,\n assistantTopicId: null,\n };\n}\n\nexport async function setupAgents(): Promise<{\n agents: Config[\"agents\"];\n defaultAgent: string;\n}> {\n const detected = await detectAgents();\n const agents: Config[\"agents\"] = {};\n\n if (detected.length > 0) {\n for (const agent of detected) {\n agents[agent.name] = { command: agent.command, args: [], env: {} };\n }\n } else {\n agents[\"claude\"] = { command: \"claude-agent-acp\", args: [], env: {} };\n }\n\n const defaultAgent = Object.keys(agents)[0];\n const agentCmd = agents[defaultAgent].command;\n console.log(\n ok(`Agent: ${c.bold}${defaultAgent}${c.reset}${c.green} (${agentCmd})`),\n );\n\n return { agents, defaultAgent };\n}\n\nexport async function setupWorkspace(): Promise<{ baseDir: string }> {\n console.log(step(3, \"Workspace\"));\n\n const baseDir = await input({\n message: \"Base directory for workspaces:\",\n default: \"~/openacp-workspace\",\n validate: (val) => val.trim().length > 0 || \"Path cannot be empty\",\n });\n\n return { baseDir: baseDir.trim().replace(/^['\"]|['\"]$/g, \"\") };\n}\n\n// --- Orchestrator ---\n\nfunction printWelcomeBanner(): void {\n console.log(`\n${c.cyan}${c.bold} ╔══════════════════════════════╗\n ║ Welcome to OpenACP ║\n ╚══════════════════════════════╝${c.reset}\n`);\n}\n\nexport async function runSetup(configManager: ConfigManager): Promise<boolean> {\n printWelcomeBanner();\n\n try {\n const telegram = await setupTelegram();\n const { agents, defaultAgent } = await setupAgents();\n const workspace = await setupWorkspace();\n const security = {\n allowedUserIds: [] as string[],\n maxConcurrentSessions: 5,\n sessionTimeoutMinutes: 60,\n };\n\n const config: Config = {\n channels: { telegram },\n agents,\n defaultAgent,\n workspace,\n security,\n logging: {\n level: \"info\",\n logDir: \"~/.openacp/logs\",\n maxFileSize: \"10m\",\n maxFiles: 7,\n sessionLogRetentionDays: 30,\n },\n };\n\n try {\n await configManager.writeNew(config);\n } catch (writeErr) {\n console.log(\n fail(`Could not save config: ${(writeErr as Error).message}`),\n );\n return false;\n }\n\n console.log(\"\");\n console.log(\n ok(`Config saved to ${c.bold}${configManager.getConfigPath()}`),\n );\n console.log(ok(\"Starting OpenACP...\"));\n console.log(\"\");\n\n return true;\n } catch (err) {\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(dim(\"\\nSetup cancelled.\"));\n return false;\n }\n throw err;\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openacp/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.16",
|
|
4
4
|
"description": "Self-hosted bridge for AI coding agents via ACP protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@agentclientprotocol/sdk": "^0.16.0",
|
|
26
26
|
"@inquirer/prompts": "^8.3.2",
|
|
27
|
+
"@zed-industries/claude-agent-acp": "^0.22.2",
|
|
27
28
|
"grammy": "^1.30.0",
|
|
28
29
|
"nanoid": "^5.0.0",
|
|
29
30
|
"pino": "^10.3.1",
|
package/dist/setup-4EBTX2NJ.js
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
// src/core/setup.ts
|
|
2
|
-
import { execFileSync } from "child_process";
|
|
3
|
-
import * as fs from "fs";
|
|
4
|
-
import * as path from "path";
|
|
5
|
-
import { input, select } from "@inquirer/prompts";
|
|
6
|
-
async function validateBotToken(token) {
|
|
7
|
-
try {
|
|
8
|
-
const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);
|
|
9
|
-
const data = await res.json();
|
|
10
|
-
if (data.ok && data.result) {
|
|
11
|
-
return { ok: true, botName: data.result.first_name, botUsername: data.result.username };
|
|
12
|
-
}
|
|
13
|
-
return { ok: false, error: data.description || "Invalid token" };
|
|
14
|
-
} catch (err) {
|
|
15
|
-
return { ok: false, error: err.message };
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
async function validateChatId(token, chatId) {
|
|
19
|
-
try {
|
|
20
|
-
const res = await fetch(`https://api.telegram.org/bot${token}/getChat`, {
|
|
21
|
-
method: "POST",
|
|
22
|
-
headers: { "Content-Type": "application/json" },
|
|
23
|
-
body: JSON.stringify({ chat_id: chatId })
|
|
24
|
-
});
|
|
25
|
-
const data = await res.json();
|
|
26
|
-
if (!data.ok || !data.result) {
|
|
27
|
-
return { ok: false, error: data.description || "Invalid chat ID" };
|
|
28
|
-
}
|
|
29
|
-
if (data.result.type !== "supergroup") {
|
|
30
|
-
return { ok: false, error: `Chat is "${data.result.type}", must be a supergroup` };
|
|
31
|
-
}
|
|
32
|
-
return { ok: true, title: data.result.title, isForum: data.result.is_forum === true };
|
|
33
|
-
} catch (err) {
|
|
34
|
-
return { ok: false, error: err.message };
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
var KNOWN_AGENTS = [
|
|
38
|
-
{ name: "claude", commands: ["claude-agent-acp", "claude-code", "claude"] },
|
|
39
|
-
{ name: "codex", commands: ["codex"] }
|
|
40
|
-
];
|
|
41
|
-
function commandExists(cmd) {
|
|
42
|
-
try {
|
|
43
|
-
execFileSync("which", [cmd], { stdio: "pipe" });
|
|
44
|
-
return true;
|
|
45
|
-
} catch {
|
|
46
|
-
}
|
|
47
|
-
let dir = process.cwd();
|
|
48
|
-
while (true) {
|
|
49
|
-
const binPath = path.join(dir, "node_modules", ".bin", cmd);
|
|
50
|
-
if (fs.existsSync(binPath)) return true;
|
|
51
|
-
const parent = path.dirname(dir);
|
|
52
|
-
if (parent === dir) break;
|
|
53
|
-
dir = parent;
|
|
54
|
-
}
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
async function detectAgents() {
|
|
58
|
-
const found = [];
|
|
59
|
-
for (const agent of KNOWN_AGENTS) {
|
|
60
|
-
const available = [];
|
|
61
|
-
for (const cmd of agent.commands) {
|
|
62
|
-
if (commandExists(cmd)) {
|
|
63
|
-
available.push(cmd);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (available.length > 0) {
|
|
67
|
-
const preferred = available[0];
|
|
68
|
-
found.push({ name: agent.name, command: preferred });
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return found;
|
|
72
|
-
}
|
|
73
|
-
async function validateAgentCommand(command) {
|
|
74
|
-
try {
|
|
75
|
-
execFileSync("which", [command], { stdio: "pipe" });
|
|
76
|
-
return true;
|
|
77
|
-
} catch {
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
async function setupTelegram() {
|
|
82
|
-
console.log("\n--- Step 1: Telegram Setup ---\n");
|
|
83
|
-
let botToken = "";
|
|
84
|
-
let botUsername = "";
|
|
85
|
-
let botName = "";
|
|
86
|
-
while (true) {
|
|
87
|
-
botToken = await input({
|
|
88
|
-
message: "Telegram bot token (from @BotFather):",
|
|
89
|
-
validate: (val) => val.trim().length > 0 || "Token cannot be empty"
|
|
90
|
-
});
|
|
91
|
-
botToken = botToken.trim();
|
|
92
|
-
console.log("Validating bot token...");
|
|
93
|
-
const result = await validateBotToken(botToken);
|
|
94
|
-
if (result.ok) {
|
|
95
|
-
botUsername = result.botUsername;
|
|
96
|
-
botName = result.botName;
|
|
97
|
-
console.log(`\u2713 Bot "${botName}" (@${botUsername}) connected`);
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
console.log(`\u2717 Validation failed: ${result.error}`);
|
|
101
|
-
const action = await select({
|
|
102
|
-
message: "What would you like to do?",
|
|
103
|
-
choices: [
|
|
104
|
-
{ name: "Re-enter token", value: "retry" },
|
|
105
|
-
{ name: "Skip validation (use token as-is)", value: "skip" }
|
|
106
|
-
]
|
|
107
|
-
});
|
|
108
|
-
if (action === "skip") break;
|
|
109
|
-
}
|
|
110
|
-
let chatId = 0;
|
|
111
|
-
while (true) {
|
|
112
|
-
const chatIdStr = await input({
|
|
113
|
-
message: "Telegram supergroup chat ID (e.g. -1001234567890):",
|
|
114
|
-
validate: (val) => {
|
|
115
|
-
const n = Number(val.trim());
|
|
116
|
-
if (isNaN(n) || !Number.isInteger(n)) return "Chat ID must be an integer";
|
|
117
|
-
return true;
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
chatId = Number(chatIdStr.trim());
|
|
121
|
-
console.log("Validating chat ID...");
|
|
122
|
-
const result = await validateChatId(botToken, chatId);
|
|
123
|
-
if (result.ok) {
|
|
124
|
-
if (!result.isForum) {
|
|
125
|
-
console.log(`\u26A0 Warning: "${result.title}" does not have Topics enabled.`);
|
|
126
|
-
console.log(" Please enable Topics in group settings \u2192 Topics \u2192 Enable.");
|
|
127
|
-
} else {
|
|
128
|
-
console.log(`\u2713 Connected to "${result.title}" (Topics enabled)`);
|
|
129
|
-
}
|
|
130
|
-
break;
|
|
131
|
-
}
|
|
132
|
-
console.log(`\u2717 Validation failed: ${result.error}`);
|
|
133
|
-
if (result.error.includes("must be a supergroup")) {
|
|
134
|
-
console.log(" Tip: Create a Supergroup in Telegram, then enable Topics in group settings.");
|
|
135
|
-
}
|
|
136
|
-
const action = await select({
|
|
137
|
-
message: "What would you like to do?",
|
|
138
|
-
choices: [
|
|
139
|
-
{ name: "Re-enter chat ID", value: "retry" },
|
|
140
|
-
{ name: "Skip validation (use chat ID as-is)", value: "skip" }
|
|
141
|
-
]
|
|
142
|
-
});
|
|
143
|
-
if (action === "skip") break;
|
|
144
|
-
}
|
|
145
|
-
return {
|
|
146
|
-
enabled: true,
|
|
147
|
-
botToken,
|
|
148
|
-
chatId,
|
|
149
|
-
notificationTopicId: null,
|
|
150
|
-
assistantTopicId: null
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
async function setupAgents() {
|
|
154
|
-
console.log("\n--- Step 2: Agent Setup ---\n");
|
|
155
|
-
console.log("Detecting agents in PATH...");
|
|
156
|
-
const detected = await detectAgents();
|
|
157
|
-
const agents = {};
|
|
158
|
-
if (detected.length > 0) {
|
|
159
|
-
for (const agent of detected) {
|
|
160
|
-
agents[agent.name] = { command: agent.command, args: [], env: {} };
|
|
161
|
-
}
|
|
162
|
-
console.log(`Found: ${detected.map((a) => `${a.name} (${a.command})`).join(", ")}`);
|
|
163
|
-
} else {
|
|
164
|
-
agents["claude"] = { command: "claude-agent-acp", args: [], env: {} };
|
|
165
|
-
console.log("No agents detected. Using default: claude (claude-agent-acp)");
|
|
166
|
-
}
|
|
167
|
-
const defaultAgent = Object.keys(agents)[0];
|
|
168
|
-
console.log(`Default agent: ${defaultAgent}`);
|
|
169
|
-
return { agents, defaultAgent };
|
|
170
|
-
}
|
|
171
|
-
async function setupWorkspace() {
|
|
172
|
-
console.log("\n--- Step 3: Workspace Setup ---\n");
|
|
173
|
-
const baseDir = await input({
|
|
174
|
-
message: "Workspace base directory:",
|
|
175
|
-
default: "~/openacp-workspace",
|
|
176
|
-
validate: (val) => val.trim().length > 0 || "Path cannot be empty"
|
|
177
|
-
});
|
|
178
|
-
return { baseDir: baseDir.trim() };
|
|
179
|
-
}
|
|
180
|
-
function printWelcomeBanner() {
|
|
181
|
-
console.log(`
|
|
182
|
-
\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\u2510
|
|
183
|
-
\u2502 \u2502
|
|
184
|
-
\u2502 Welcome to OpenACP! \u2502
|
|
185
|
-
\u2502 \u2502
|
|
186
|
-
\u2502 Let's set up your configuration. \u2502
|
|
187
|
-
\u2502 \u2502
|
|
188
|
-
\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\u2518
|
|
189
|
-
`);
|
|
190
|
-
}
|
|
191
|
-
function printConfigSummary(config) {
|
|
192
|
-
console.log("\n--- Configuration Summary ---\n");
|
|
193
|
-
console.log("Telegram:");
|
|
194
|
-
const tg = config.channels.telegram;
|
|
195
|
-
if (tg) {
|
|
196
|
-
const token = String(tg.botToken || "");
|
|
197
|
-
console.log(` Bot token: ${token.slice(0, 8)}...${token.slice(-4)}`);
|
|
198
|
-
console.log(` Chat ID: ${tg.chatId}`);
|
|
199
|
-
}
|
|
200
|
-
console.log("\nAgents:");
|
|
201
|
-
for (const [name, agent] of Object.entries(config.agents)) {
|
|
202
|
-
const marker = name === config.defaultAgent ? " (default)" : "";
|
|
203
|
-
console.log(` ${name}: ${agent.command}${marker}`);
|
|
204
|
-
}
|
|
205
|
-
console.log(`
|
|
206
|
-
Workspace: ${config.workspace.baseDir}`);
|
|
207
|
-
}
|
|
208
|
-
async function runSetup(configManager) {
|
|
209
|
-
printWelcomeBanner();
|
|
210
|
-
try {
|
|
211
|
-
const telegram = await setupTelegram();
|
|
212
|
-
const { agents, defaultAgent } = await setupAgents();
|
|
213
|
-
const workspace = await setupWorkspace();
|
|
214
|
-
const security = { allowedUserIds: [], maxConcurrentSessions: 5, sessionTimeoutMinutes: 60 };
|
|
215
|
-
const config = {
|
|
216
|
-
channels: { telegram },
|
|
217
|
-
agents,
|
|
218
|
-
defaultAgent,
|
|
219
|
-
workspace,
|
|
220
|
-
security,
|
|
221
|
-
logging: { level: "info", logDir: "~/.openacp/logs", maxFileSize: "10m", maxFiles: 7, sessionLogRetentionDays: 30 }
|
|
222
|
-
};
|
|
223
|
-
printConfigSummary(config);
|
|
224
|
-
try {
|
|
225
|
-
await configManager.writeNew(config);
|
|
226
|
-
} catch (writeErr) {
|
|
227
|
-
console.error(`
|
|
228
|
-
\u2717 Failed to write config to ${configManager.getConfigPath()}`);
|
|
229
|
-
console.error(` Error: ${writeErr.message}`);
|
|
230
|
-
console.error(" Check that you have write permissions to this path.");
|
|
231
|
-
return false;
|
|
232
|
-
}
|
|
233
|
-
console.log(`
|
|
234
|
-
\u2713 Config saved to ${configManager.getConfigPath()}`);
|
|
235
|
-
console.log("Starting OpenACP...\n");
|
|
236
|
-
return true;
|
|
237
|
-
} catch (err) {
|
|
238
|
-
if (err.name === "ExitPromptError") {
|
|
239
|
-
console.log("\nSetup cancelled.");
|
|
240
|
-
return false;
|
|
241
|
-
}
|
|
242
|
-
throw err;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
export {
|
|
246
|
-
detectAgents,
|
|
247
|
-
runSetup,
|
|
248
|
-
setupAgents,
|
|
249
|
-
setupTelegram,
|
|
250
|
-
setupWorkspace,
|
|
251
|
-
validateAgentCommand,
|
|
252
|
-
validateBotToken,
|
|
253
|
-
validateChatId
|
|
254
|
-
};
|
|
255
|
-
//# sourceMappingURL=setup-4EBTX2NJ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/setup.ts"],"sourcesContent":["import { execFileSync } from 'node:child_process'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { input, select } from '@inquirer/prompts'\nimport type { Config, ConfigManager } from './config.js'\n\n// --- Telegram validation ---\n\nexport async function validateBotToken(token: string): Promise<\n { ok: true; botName: string; botUsername: string } | { ok: false; error: string }\n> {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getMe`)\n const data = await res.json() as { ok: boolean; result?: { first_name: string; username: string }; description?: string }\n if (data.ok && data.result) {\n return { ok: true, botName: data.result.first_name, botUsername: data.result.username }\n }\n return { ok: false, error: data.description || 'Invalid token' }\n } catch (err) {\n return { ok: false, error: (err as Error).message }\n }\n}\n\nexport async function validateChatId(token: string, chatId: number): Promise<\n { ok: true; title: string; isForum: boolean } | { ok: false; error: string }\n> {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getChat`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ chat_id: chatId }),\n })\n const data = await res.json() as {\n ok: boolean\n result?: { title: string; type: string; is_forum?: boolean }\n description?: string\n }\n if (!data.ok || !data.result) {\n return { ok: false, error: data.description || 'Invalid chat ID' }\n }\n if (data.result.type !== 'supergroup') {\n return { ok: false, error: `Chat is \"${data.result.type}\", must be a supergroup` }\n }\n return { ok: true, title: data.result.title, isForum: data.result.is_forum === true }\n } catch (err) {\n return { ok: false, error: (err as Error).message }\n }\n}\n\n// --- Agent detection ---\n\n// Commands listed in priority order — first match wins per agent\nconst KNOWN_AGENTS: Array<{ name: string; commands: string[] }> = [\n { name: 'claude', commands: ['claude-agent-acp', 'claude-code', 'claude'] },\n { name: 'codex', commands: ['codex'] },\n]\n\nfunction commandExists(cmd: string): boolean {\n // Check system PATH\n try {\n execFileSync('which', [cmd], { stdio: 'pipe' })\n return true\n } catch {\n // not in PATH\n }\n // Check node_modules/.bin (walks up from cwd)\n let dir = process.cwd()\n while (true) {\n const binPath = path.join(dir, 'node_modules', '.bin', cmd)\n if (fs.existsSync(binPath)) return true\n const parent = path.dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n return false\n}\n\nexport async function detectAgents(): Promise<Array<{ name: string; command: string }>> {\n const found: Array<{ name: string; command: string }> = []\n for (const agent of KNOWN_AGENTS) {\n // Find all available commands for this agent (PATH + node_modules/.bin)\n const available: string[] = []\n for (const cmd of agent.commands) {\n if (commandExists(cmd)) {\n available.push(cmd)\n }\n }\n if (available.length > 0) {\n // Prefer claude-agent-acp over claude/claude-code (priority order)\n const preferred = available[0]\n found.push({ name: agent.name, command: preferred })\n }\n }\n return found\n}\n\nexport async function validateAgentCommand(command: string): Promise<boolean> {\n try {\n execFileSync('which', [command], { stdio: 'pipe' })\n return true\n } catch {\n return false\n }\n}\n\n// --- Setup steps ---\n\nexport async function setupTelegram(): Promise<Config['channels'][string]> {\n console.log('\\n--- Step 1: Telegram Setup ---\\n')\n\n let botToken = ''\n let botUsername = ''\n let botName = ''\n\n while (true) {\n botToken = await input({\n message: 'Telegram bot token (from @BotFather):',\n validate: (val) => val.trim().length > 0 || 'Token cannot be empty',\n })\n botToken = botToken.trim()\n\n console.log('Validating bot token...')\n const result = await validateBotToken(botToken)\n if (result.ok) {\n botUsername = result.botUsername\n botName = result.botName\n console.log(`✓ Bot \"${botName}\" (@${botUsername}) connected`)\n break\n }\n console.log(`✗ Validation failed: ${result.error}`)\n const action = await select({\n message: 'What would you like to do?',\n choices: [\n { name: 'Re-enter token', value: 'retry' },\n { name: 'Skip validation (use token as-is)', value: 'skip' },\n ],\n })\n if (action === 'skip') break\n }\n\n let chatId = 0\n\n while (true) {\n const chatIdStr = await input({\n message: 'Telegram supergroup chat ID (e.g. -1001234567890):',\n validate: (val) => {\n const n = Number(val.trim())\n if (isNaN(n) || !Number.isInteger(n)) return 'Chat ID must be an integer'\n return true\n },\n })\n chatId = Number(chatIdStr.trim())\n\n console.log('Validating chat ID...')\n const result = await validateChatId(botToken, chatId)\n if (result.ok) {\n if (!result.isForum) {\n console.log(`⚠ Warning: \"${result.title}\" does not have Topics enabled.`)\n console.log(' Please enable Topics in group settings → Topics → Enable.')\n } else {\n console.log(`✓ Connected to \"${result.title}\" (Topics enabled)`)\n }\n break\n }\n console.log(`✗ Validation failed: ${result.error}`)\n if (result.error.includes('must be a supergroup')) {\n console.log(' Tip: Create a Supergroup in Telegram, then enable Topics in group settings.')\n }\n const action = await select({\n message: 'What would you like to do?',\n choices: [\n { name: 'Re-enter chat ID', value: 'retry' },\n { name: 'Skip validation (use chat ID as-is)', value: 'skip' },\n ],\n })\n if (action === 'skip') break\n }\n\n return {\n enabled: true,\n botToken,\n chatId,\n notificationTopicId: null,\n assistantTopicId: null,\n }\n}\n\nexport async function setupAgents(): Promise<{ agents: Config['agents']; defaultAgent: string }> {\n console.log('\\n--- Step 2: Agent Setup ---\\n')\n\n console.log('Detecting agents in PATH...')\n const detected = await detectAgents()\n\n const agents: Config['agents'] = {}\n\n if (detected.length > 0) {\n for (const agent of detected) {\n agents[agent.name] = { command: agent.command, args: [], env: {} }\n }\n console.log(`Found: ${detected.map(a => `${a.name} (${a.command})`).join(', ')}`)\n } else {\n // Fallback to claude-agent-acp as default\n agents['claude'] = { command: 'claude-agent-acp', args: [], env: {} }\n console.log('No agents detected. Using default: claude (claude-agent-acp)')\n }\n\n const defaultAgent = Object.keys(agents)[0]\n console.log(`Default agent: ${defaultAgent}`)\n\n return { agents, defaultAgent }\n}\n\nexport async function setupWorkspace(): Promise<{ baseDir: string }> {\n console.log('\\n--- Step 3: Workspace Setup ---\\n')\n\n const baseDir = await input({\n message: 'Workspace base directory:',\n default: '~/openacp-workspace',\n validate: (val) => val.trim().length > 0 || 'Path cannot be empty',\n })\n\n return { baseDir: baseDir.trim() }\n}\n\n// --- Orchestrator ---\n\nfunction printWelcomeBanner(): void {\n console.log(`\n┌──────────────────────────────────────┐\n│ │\n│ Welcome to OpenACP! │\n│ │\n│ Let's set up your configuration. │\n│ │\n└──────────────────────────────────────┘\n`)\n}\n\nfunction printConfigSummary(config: Config): void {\n console.log('\\n--- Configuration Summary ---\\n')\n\n console.log('Telegram:')\n const tg = config.channels.telegram as Record<string, any> | undefined\n if (tg) {\n const token = String(tg.botToken || '')\n console.log(` Bot token: ${token.slice(0, 8)}...${token.slice(-4)}`)\n console.log(` Chat ID: ${tg.chatId}`)\n }\n\n console.log('\\nAgents:')\n for (const [name, agent] of Object.entries(config.agents)) {\n const marker = name === config.defaultAgent ? ' (default)' : ''\n console.log(` ${name}: ${agent.command}${marker}`)\n }\n\n console.log(`\\nWorkspace: ${config.workspace.baseDir}`)\n}\n\nexport async function runSetup(configManager: ConfigManager): Promise<boolean> {\n printWelcomeBanner()\n\n try {\n const telegram = await setupTelegram()\n const { agents, defaultAgent } = await setupAgents()\n const workspace = await setupWorkspace()\n const security = { allowedUserIds: [] as string[], maxConcurrentSessions: 5, sessionTimeoutMinutes: 60 }\n\n const config: Config = {\n channels: { telegram },\n agents,\n defaultAgent,\n workspace,\n security,\n logging: { level: 'info', logDir: '~/.openacp/logs', maxFileSize: '10m', maxFiles: 7, sessionLogRetentionDays: 30 },\n }\n\n printConfigSummary(config)\n\n try {\n await configManager.writeNew(config)\n } catch (writeErr) {\n console.error(`\\n✗ Failed to write config to ${configManager.getConfigPath()}`)\n console.error(` Error: ${(writeErr as Error).message}`)\n console.error(' Check that you have write permissions to this path.')\n return false\n }\n console.log(`\\n✓ Config saved to ${configManager.getConfigPath()}`)\n console.log('Starting OpenACP...\\n')\n\n return true\n } catch (err) {\n // Ctrl+C from inquirer throws ExitPromptError\n if ((err as Error).name === 'ExitPromptError') {\n console.log('\\nSetup cancelled.')\n return false\n }\n throw err\n }\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|