@suzuke/agend 0.0.1 → 1.0.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 +557 -1
- package/README.zh-TW.md +504 -0
- package/dist/access-path.d.ts +7 -0
- package/dist/access-path.js +12 -0
- package/dist/access-path.js.map +1 -0
- package/dist/approval/approval-server.d.ts +30 -0
- package/dist/approval/approval-server.js +156 -0
- package/dist/approval/approval-server.js.map +1 -0
- package/dist/approval/tmux-prompt-detector.d.ts +34 -0
- package/dist/approval/tmux-prompt-detector.js +264 -0
- package/dist/approval/tmux-prompt-detector.js.map +1 -0
- package/dist/backend/approval-strategy.d.ts +14 -0
- package/dist/backend/approval-strategy.js +2 -0
- package/dist/backend/approval-strategy.js.map +1 -0
- package/dist/backend/claude-code.d.ts +13 -0
- package/dist/backend/claude-code.js +114 -0
- package/dist/backend/claude-code.js.map +1 -0
- package/dist/backend/codex.d.ts +10 -0
- package/dist/backend/codex.js +58 -0
- package/dist/backend/codex.js.map +1 -0
- package/dist/backend/factory.d.ts +2 -0
- package/dist/backend/factory.js +19 -0
- package/dist/backend/factory.js.map +1 -0
- package/dist/backend/gemini-cli.d.ts +10 -0
- package/dist/backend/gemini-cli.js +68 -0
- package/dist/backend/gemini-cli.js.map +1 -0
- package/dist/backend/hook-based-approval.d.ts +20 -0
- package/dist/backend/hook-based-approval.js +41 -0
- package/dist/backend/hook-based-approval.js.map +1 -0
- package/dist/backend/index.d.ts +6 -0
- package/dist/backend/index.js +6 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/opencode.d.ts +10 -0
- package/dist/backend/opencode.js +63 -0
- package/dist/backend/opencode.js.map +1 -0
- package/dist/backend/types.d.ts +26 -0
- package/dist/backend/types.js +2 -0
- package/dist/backend/types.js.map +1 -0
- package/dist/channel/access-manager.d.ts +18 -0
- package/dist/channel/access-manager.js +149 -0
- package/dist/channel/access-manager.js.map +1 -0
- package/dist/channel/adapters/discord.d.ts +45 -0
- package/dist/channel/adapters/discord.js +366 -0
- package/dist/channel/adapters/discord.js.map +1 -0
- package/dist/channel/adapters/telegram.d.ts +58 -0
- package/dist/channel/adapters/telegram.js +569 -0
- package/dist/channel/adapters/telegram.js.map +1 -0
- package/dist/channel/attachment-handler.d.ts +15 -0
- package/dist/channel/attachment-handler.js +55 -0
- package/dist/channel/attachment-handler.js.map +1 -0
- package/dist/channel/factory.d.ts +12 -0
- package/dist/channel/factory.js +38 -0
- package/dist/channel/factory.js.map +1 -0
- package/dist/channel/ipc-bridge.d.ts +26 -0
- package/dist/channel/ipc-bridge.js +170 -0
- package/dist/channel/ipc-bridge.js.map +1 -0
- package/dist/channel/mcp-server.d.ts +10 -0
- package/dist/channel/mcp-server.js +196 -0
- package/dist/channel/mcp-server.js.map +1 -0
- package/dist/channel/mcp-tools.d.ts +909 -0
- package/dist/channel/mcp-tools.js +346 -0
- package/dist/channel/mcp-tools.js.map +1 -0
- package/dist/channel/message-bus.d.ts +17 -0
- package/dist/channel/message-bus.js +86 -0
- package/dist/channel/message-bus.js.map +1 -0
- package/dist/channel/message-queue.d.ts +39 -0
- package/dist/channel/message-queue.js +248 -0
- package/dist/channel/message-queue.js.map +1 -0
- package/dist/channel/tool-router.d.ts +6 -0
- package/dist/channel/tool-router.js +69 -0
- package/dist/channel/tool-router.js.map +1 -0
- package/dist/channel/tool-tracker.d.ts +13 -0
- package/dist/channel/tool-tracker.js +58 -0
- package/dist/channel/tool-tracker.js.map +1 -0
- package/dist/channel/types.d.ts +116 -0
- package/dist/channel/types.js +2 -0
- package/dist/channel/types.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +782 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +85 -0
- package/dist/config.js.map +1 -0
- package/dist/container-manager.d.ts +24 -0
- package/dist/container-manager.js +148 -0
- package/dist/container-manager.js.map +1 -0
- package/dist/context-guardian.d.ts +29 -0
- package/dist/context-guardian.js +123 -0
- package/dist/context-guardian.js.map +1 -0
- package/dist/cost-guard.d.ts +21 -0
- package/dist/cost-guard.js +113 -0
- package/dist/cost-guard.js.map +1 -0
- package/dist/daemon-entry.d.ts +1 -0
- package/dist/daemon-entry.js +29 -0
- package/dist/daemon-entry.js.map +1 -0
- package/dist/daemon.d.ts +88 -0
- package/dist/daemon.js +820 -0
- package/dist/daemon.js.map +1 -0
- package/dist/daily-summary.d.ts +13 -0
- package/dist/daily-summary.js +55 -0
- package/dist/daily-summary.js.map +1 -0
- package/dist/db.d.ts +10 -0
- package/dist/db.js +43 -0
- package/dist/db.js.map +1 -0
- package/dist/event-log.d.ts +22 -0
- package/dist/event-log.js +66 -0
- package/dist/event-log.js.map +1 -0
- package/dist/export-import.d.ts +2 -0
- package/dist/export-import.js +110 -0
- package/dist/export-import.js.map +1 -0
- package/dist/fleet-context.d.ts +36 -0
- package/dist/fleet-context.js +4 -0
- package/dist/fleet-context.js.map +1 -0
- package/dist/fleet-manager.d.ts +115 -0
- package/dist/fleet-manager.js +1742 -0
- package/dist/fleet-manager.js.map +1 -0
- package/dist/fleet-system-prompt.d.ts +11 -0
- package/dist/fleet-system-prompt.js +60 -0
- package/dist/fleet-system-prompt.js.map +1 -0
- package/dist/hang-detector.d.ts +16 -0
- package/dist/hang-detector.js +53 -0
- package/dist/hang-detector.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/install-recorder.d.ts +30 -0
- package/dist/install-recorder.js +159 -0
- package/dist/install-recorder.js.map +1 -0
- package/dist/logger.d.ts +3 -0
- package/dist/logger.js +63 -0
- package/dist/logger.js.map +1 -0
- package/dist/meeting/orchestrator.d.ts +30 -0
- package/dist/meeting/orchestrator.js +355 -0
- package/dist/meeting/orchestrator.js.map +1 -0
- package/dist/meeting/prompt-builder.d.ts +12 -0
- package/dist/meeting/prompt-builder.js +96 -0
- package/dist/meeting/prompt-builder.js.map +1 -0
- package/dist/meeting/role-assigner.d.ts +2 -0
- package/dist/meeting/role-assigner.js +25 -0
- package/dist/meeting/role-assigner.js.map +1 -0
- package/dist/meeting/types.d.ts +21 -0
- package/dist/meeting/types.js +2 -0
- package/dist/meeting/types.js.map +1 -0
- package/dist/meeting-manager.d.ts +10 -0
- package/dist/meeting-manager.js +38 -0
- package/dist/meeting-manager.js.map +1 -0
- package/dist/memory-layer.d.ts +13 -0
- package/dist/memory-layer.js +44 -0
- package/dist/memory-layer.js.map +1 -0
- package/dist/plugin/agend/.claude-plugin/plugin.json +5 -0
- package/dist/plugin/agend/.mcp.json +9 -0
- package/dist/plugin/ccd-channel/.claude-plugin/plugin.json +5 -0
- package/dist/plugin/ccd-channel/.mcp.json +9 -0
- package/dist/process-manager.d.ts +31 -0
- package/dist/process-manager.js +264 -0
- package/dist/process-manager.js.map +1 -0
- package/dist/scheduler/db.d.ts +16 -0
- package/dist/scheduler/db.js +132 -0
- package/dist/scheduler/db.js.map +1 -0
- package/dist/scheduler/db.test.d.ts +1 -0
- package/dist/scheduler/db.test.js +92 -0
- package/dist/scheduler/db.test.js.map +1 -0
- package/dist/scheduler/index.d.ts +4 -0
- package/dist/scheduler/index.js +4 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/scheduler/scheduler.d.ts +25 -0
- package/dist/scheduler/scheduler.js +119 -0
- package/dist/scheduler/scheduler.js.map +1 -0
- package/dist/scheduler/scheduler.test.d.ts +1 -0
- package/dist/scheduler/scheduler.test.js +119 -0
- package/dist/scheduler/scheduler.test.js.map +1 -0
- package/dist/scheduler/types.d.ts +47 -0
- package/dist/scheduler/types.js +7 -0
- package/dist/scheduler/types.js.map +1 -0
- package/dist/service-installer.d.ts +14 -0
- package/dist/service-installer.js +91 -0
- package/dist/service-installer.js.map +1 -0
- package/dist/setup-wizard.d.ts +14 -0
- package/dist/setup-wizard.js +517 -0
- package/dist/setup-wizard.js.map +1 -0
- package/dist/stt.d.ts +10 -0
- package/dist/stt.js +33 -0
- package/dist/stt.js.map +1 -0
- package/dist/tmux-manager.d.ts +22 -0
- package/dist/tmux-manager.js +131 -0
- package/dist/tmux-manager.js.map +1 -0
- package/dist/topic-commands.d.ts +22 -0
- package/dist/topic-commands.js +176 -0
- package/dist/topic-commands.js.map +1 -0
- package/dist/transcript-monitor.d.ts +21 -0
- package/dist/transcript-monitor.js +149 -0
- package/dist/transcript-monitor.js.map +1 -0
- package/dist/types.d.ts +153 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/webhook-emitter.d.ts +15 -0
- package/dist/webhook-emitter.js +41 -0
- package/dist/webhook-emitter.js.map +1 -0
- package/package.json +60 -4
- package/templates/launchd.plist.ejs +29 -0
- package/templates/systemd.service.ejs +15 -0
- package/index.js +0 -1
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
import { createInterface } from "node:readline/promises";
|
|
2
|
+
import { writeFileSync, mkdirSync, existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { stdin, stdout } from "node:process";
|
|
6
|
+
import { execSync } from "node:child_process";
|
|
7
|
+
const DATA_DIR = join(homedir(), ".agend");
|
|
8
|
+
const FLEET_CONFIG_PATH = join(DATA_DIR, "fleet.yaml");
|
|
9
|
+
const ENV_PATH = join(DATA_DIR, ".env");
|
|
10
|
+
// ── Helpers ──────────────────────────────────────────────
|
|
11
|
+
export function validateBotToken(token) {
|
|
12
|
+
return /^\d+:[A-Za-z0-9_-]{30,}$/.test(token);
|
|
13
|
+
}
|
|
14
|
+
export async function verifyBotToken(token) {
|
|
15
|
+
try {
|
|
16
|
+
const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);
|
|
17
|
+
const data = await res.json();
|
|
18
|
+
if (data.ok && data.result?.username) {
|
|
19
|
+
return { valid: true, username: data.result.username };
|
|
20
|
+
}
|
|
21
|
+
return { valid: false, username: null };
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return { valid: false, username: null };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function bold(s) {
|
|
28
|
+
return `\x1b[1m${s}\x1b[0m`;
|
|
29
|
+
}
|
|
30
|
+
function dim(s) {
|
|
31
|
+
return `\x1b[2m${s}\x1b[0m`;
|
|
32
|
+
}
|
|
33
|
+
function green(s) {
|
|
34
|
+
return `\x1b[32m${s}\x1b[0m`;
|
|
35
|
+
}
|
|
36
|
+
function red(s) {
|
|
37
|
+
return `\x1b[31m${s}\x1b[0m`;
|
|
38
|
+
}
|
|
39
|
+
function yellow(s) {
|
|
40
|
+
return `\x1b[33m${s}\x1b[0m`;
|
|
41
|
+
}
|
|
42
|
+
function cyan(s) {
|
|
43
|
+
return `\x1b[36m${s}\x1b[0m`;
|
|
44
|
+
}
|
|
45
|
+
function step(n, total, label) {
|
|
46
|
+
console.log(`\n${cyan(`[${n}/${total}]`)} ${bold(label)}`);
|
|
47
|
+
}
|
|
48
|
+
/** Ask a question; retry until validator passes. Empty → default. */
|
|
49
|
+
async function ask(rl, prompt, opts = {}) {
|
|
50
|
+
const suffix = opts.default != null ? ` ${dim(`[${opts.default}]`)}` : "";
|
|
51
|
+
for (;;) {
|
|
52
|
+
const raw = await rl.question(` ${prompt}${suffix}: `);
|
|
53
|
+
const value = raw.trim() || opts.default || "";
|
|
54
|
+
if (opts.validate) {
|
|
55
|
+
const err = opts.validate(value);
|
|
56
|
+
if (err) {
|
|
57
|
+
console.log(` ${red(err)}`);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** Ask a yes/no question. */
|
|
65
|
+
async function confirm(rl, prompt, defaultYes = true) {
|
|
66
|
+
const hint = defaultYes ? "Y/n" : "y/N";
|
|
67
|
+
const raw = await rl.question(` ${prompt} (${hint}): `);
|
|
68
|
+
const v = raw.trim().toLowerCase();
|
|
69
|
+
if (v === "")
|
|
70
|
+
return defaultYes;
|
|
71
|
+
return v === "y" || v === "yes";
|
|
72
|
+
}
|
|
73
|
+
/** Ask user to pick from numbered options. Returns 0-based index. */
|
|
74
|
+
async function choose(rl, prompt, options, defaultIndex = 0) {
|
|
75
|
+
console.log(` ${prompt}`);
|
|
76
|
+
for (let i = 0; i < options.length; i++) {
|
|
77
|
+
const marker = i === defaultIndex ? cyan("→") : " ";
|
|
78
|
+
const hint = options[i].hint ? ` ${dim(options[i].hint)}` : "";
|
|
79
|
+
console.log(` ${marker} ${i + 1}. ${options[i].label}${hint}`);
|
|
80
|
+
}
|
|
81
|
+
for (;;) {
|
|
82
|
+
const raw = await rl.question(` Pick ${dim(`[${defaultIndex + 1}]`)}: `);
|
|
83
|
+
const v = raw.trim();
|
|
84
|
+
if (v === "")
|
|
85
|
+
return defaultIndex;
|
|
86
|
+
const n = parseInt(v, 10);
|
|
87
|
+
if (n >= 1 && n <= options.length)
|
|
88
|
+
return n - 1;
|
|
89
|
+
console.log(` ${red(`Enter 1-${options.length}`)}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function expandHome(p) {
|
|
93
|
+
if (p.startsWith("~/"))
|
|
94
|
+
return join(homedir(), p.slice(2));
|
|
95
|
+
if (p === "~")
|
|
96
|
+
return homedir();
|
|
97
|
+
return resolve(p);
|
|
98
|
+
}
|
|
99
|
+
export function checkPrerequisites() {
|
|
100
|
+
let claude = false;
|
|
101
|
+
let claudeVersion = "";
|
|
102
|
+
let tmux = false;
|
|
103
|
+
let tmuxVersion = "";
|
|
104
|
+
try {
|
|
105
|
+
claudeVersion = execSync("claude --version", { stdio: "pipe" }).toString().trim();
|
|
106
|
+
claude = true;
|
|
107
|
+
}
|
|
108
|
+
catch { /* not installed */ }
|
|
109
|
+
try {
|
|
110
|
+
tmuxVersion = execSync("tmux -V", { stdio: "pipe" }).toString().trim();
|
|
111
|
+
tmux = true;
|
|
112
|
+
}
|
|
113
|
+
catch { /* not installed */ }
|
|
114
|
+
return { claude, claudeVersion, tmux, tmuxVersion };
|
|
115
|
+
}
|
|
116
|
+
// ── Main wizard ──────────────────────────────────────────
|
|
117
|
+
export async function runSetupWizard() {
|
|
118
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
119
|
+
console.log(`\n${bold("Claude Channel Daemon — Setup")}\n`);
|
|
120
|
+
const TOTAL_STEPS = 9;
|
|
121
|
+
// ── Step 1: Prerequisites ──
|
|
122
|
+
step(1, TOTAL_STEPS, "Checking prerequisites");
|
|
123
|
+
const prereq = checkPrerequisites();
|
|
124
|
+
if (prereq.claude) {
|
|
125
|
+
console.log(` ${green("✓")} Claude Code ${dim(prereq.claudeVersion)}`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
console.log(` ${red("✗")} Claude Code not found`);
|
|
129
|
+
console.log(` Install: ${dim("https://docs.anthropic.com/en/docs/claude-code")}`);
|
|
130
|
+
rl.close();
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
if (prereq.tmux) {
|
|
134
|
+
console.log(` ${green("✓")} tmux ${dim(prereq.tmuxVersion)}`);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
console.log(` ${red("✗")} tmux not found`);
|
|
138
|
+
console.log(` macOS: ${dim("brew install tmux")}`);
|
|
139
|
+
console.log(` Linux: ${dim("apt install tmux / dnf install tmux")}`);
|
|
140
|
+
rl.close();
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
// Detect existing config
|
|
144
|
+
if (existsSync(FLEET_CONFIG_PATH)) {
|
|
145
|
+
console.log(`\n ${yellow("⚠")} Existing config found: ${dim(FLEET_CONFIG_PATH)}`);
|
|
146
|
+
const overwrite = await confirm(rl, "Overwrite with new config?", false);
|
|
147
|
+
if (!overwrite) {
|
|
148
|
+
console.log(" Setup cancelled.");
|
|
149
|
+
rl.close();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// ── Step 2: Bot token ──
|
|
154
|
+
step(2, TOTAL_STEPS, "Telegram Bot Token");
|
|
155
|
+
console.log(` ${dim("Get one from @BotFather on Telegram")}`);
|
|
156
|
+
// Check if env var already set
|
|
157
|
+
let tokenEnvName = "AGEND_BOT_TOKEN";
|
|
158
|
+
let token = "";
|
|
159
|
+
let botUsername = "";
|
|
160
|
+
// Check existing .env for token
|
|
161
|
+
if (existsSync(ENV_PATH)) {
|
|
162
|
+
const envContent = readFileSync(ENV_PATH, "utf-8");
|
|
163
|
+
const match = envContent.match(/^([A-Z_]+)=(\d+:[A-Za-z0-9_-]{30,})/m);
|
|
164
|
+
if (match) {
|
|
165
|
+
const maskedToken = match[2].slice(0, 10) + "...";
|
|
166
|
+
console.log(` ${dim(`Found existing token in .env: ${match[1]}=${maskedToken}`)}`);
|
|
167
|
+
const reuse = await confirm(rl, "Use existing token?");
|
|
168
|
+
if (reuse) {
|
|
169
|
+
tokenEnvName = match[1];
|
|
170
|
+
token = match[2];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (!token) {
|
|
175
|
+
token = await ask(rl, "Bot Token", {
|
|
176
|
+
validate: (v) => validateBotToken(v) ? null : "Invalid format. Expected: 123456789:ABC...",
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
console.log(` Verifying with Telegram API...`);
|
|
180
|
+
const verification = await verifyBotToken(token);
|
|
181
|
+
if (!verification.valid) {
|
|
182
|
+
console.log(` ${red("✗")} Token rejected by Telegram. Check your token.`);
|
|
183
|
+
rl.close();
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
botUsername = verification.username;
|
|
187
|
+
console.log(` ${green("✓")} @${botUsername}`);
|
|
188
|
+
tokenEnvName = await ask(rl, "Env variable name for token", {
|
|
189
|
+
default: tokenEnvName,
|
|
190
|
+
validate: (v) => /^[A-Z_][A-Z0-9_]*$/.test(v) ? null : "Must be uppercase with underscores (e.g., AGEND_BOT_TOKEN)",
|
|
191
|
+
});
|
|
192
|
+
// ── Step 3: Mode ──
|
|
193
|
+
step(3, TOTAL_STEPS, "Channel Mode");
|
|
194
|
+
const mode = "topic";
|
|
195
|
+
let groupId;
|
|
196
|
+
{
|
|
197
|
+
console.log();
|
|
198
|
+
console.log(` ${dim("To get the group ID:")}`);
|
|
199
|
+
console.log(` ${dim("1. Add the bot to a Telegram group with Forum Topics enabled")}`);
|
|
200
|
+
console.log(` ${dim("2. Send a message in the group")}`);
|
|
201
|
+
console.log(` ${dim("3. Forward it to @userinfobot or check the update JSON")}`);
|
|
202
|
+
console.log(` ${dim(" Group IDs are negative numbers, e.g., -1001234567890")}`);
|
|
203
|
+
console.log();
|
|
204
|
+
const gidStr = await ask(rl, "Group ID", {
|
|
205
|
+
validate: (v) => {
|
|
206
|
+
const n = parseInt(v, 10);
|
|
207
|
+
if (isNaN(n))
|
|
208
|
+
return "Must be a number";
|
|
209
|
+
if (n >= 0)
|
|
210
|
+
return "Group IDs are negative (e.g., -1001234567890)";
|
|
211
|
+
return null;
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
groupId = parseInt(gidStr, 10);
|
|
215
|
+
}
|
|
216
|
+
// ── Step 4: Access control ──
|
|
217
|
+
step(4, TOTAL_STEPS, "Access Control");
|
|
218
|
+
const accessIndex = await choose(rl, "Who can interact with the bot?", [
|
|
219
|
+
{ label: "Locked", hint: "only whitelisted Telegram user IDs" },
|
|
220
|
+
{ label: "Pairing", hint: "anyone with a pairing code can join" },
|
|
221
|
+
], 0);
|
|
222
|
+
const accessMode = accessIndex === 0 ? "locked" : "pairing";
|
|
223
|
+
const allowedUsers = [];
|
|
224
|
+
if (accessMode === "locked") {
|
|
225
|
+
console.log();
|
|
226
|
+
console.log(` ${dim("Your Telegram user ID — send /start to @userinfobot to find it")}`);
|
|
227
|
+
const uidStr = await ask(rl, "Your Telegram user ID", {
|
|
228
|
+
validate: (v) => {
|
|
229
|
+
const n = parseInt(v, 10);
|
|
230
|
+
return isNaN(n) || n <= 0 ? "Must be a positive number" : null;
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
allowedUsers.push(parseInt(uidStr, 10));
|
|
234
|
+
let addMore = await confirm(rl, "Add another user?", false);
|
|
235
|
+
while (addMore) {
|
|
236
|
+
const uid = await ask(rl, "User ID", {
|
|
237
|
+
validate: (v) => {
|
|
238
|
+
const n = parseInt(v, 10);
|
|
239
|
+
return isNaN(n) || n <= 0 ? "Must be a positive number" : null;
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
allowedUsers.push(parseInt(uid, 10));
|
|
243
|
+
addMore = await confirm(rl, "Add another user?", false);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// ── Step 5: Project roots ──
|
|
247
|
+
step(5, TOTAL_STEPS, "Project Roots");
|
|
248
|
+
console.log(` ${dim("Directories containing your projects (for auto-bind browsing)")}`);
|
|
249
|
+
console.log(` ${dim("When a new topic is created, the bot shows projects from these dirs")}`);
|
|
250
|
+
console.log();
|
|
251
|
+
const projectRoots = [];
|
|
252
|
+
let addRoot = true;
|
|
253
|
+
while (addRoot) {
|
|
254
|
+
const root = await ask(rl, projectRoots.length === 0 ? "Project root" : "Another root", {
|
|
255
|
+
default: projectRoots.length === 0 ? "~/Projects" : undefined,
|
|
256
|
+
validate: (v) => {
|
|
257
|
+
const expanded = expandHome(v);
|
|
258
|
+
if (!existsSync(expanded))
|
|
259
|
+
return `Directory not found: ${expanded}`;
|
|
260
|
+
return null;
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
// Store with ~ for readability
|
|
264
|
+
const expanded = expandHome(root);
|
|
265
|
+
const homePrefix = homedir();
|
|
266
|
+
const display = expanded.startsWith(homePrefix)
|
|
267
|
+
? "~" + expanded.slice(homePrefix.length)
|
|
268
|
+
: expanded;
|
|
269
|
+
projectRoots.push(display);
|
|
270
|
+
console.log(` ${green("+")} ${display}`);
|
|
271
|
+
addRoot = await confirm(rl, "Add another root?", false);
|
|
272
|
+
}
|
|
273
|
+
// ── Step 6: Initial instance ──
|
|
274
|
+
step(6, TOTAL_STEPS, "Initial Instances");
|
|
275
|
+
if (mode === "topic") {
|
|
276
|
+
console.log(` ${dim("In topic mode, instances auto-bind to new forum topics.")}`);
|
|
277
|
+
console.log(` ${dim("You can pre-configure instances now, or let the bot handle it.")}`);
|
|
278
|
+
}
|
|
279
|
+
const instances = [];
|
|
280
|
+
const addInstance = await confirm(rl, "Pre-configure an instance now?", false);
|
|
281
|
+
if (addInstance) {
|
|
282
|
+
let more = true;
|
|
283
|
+
while (more) {
|
|
284
|
+
const name = await ask(rl, "Instance name", {
|
|
285
|
+
validate: (v) => {
|
|
286
|
+
if (v.length === 0)
|
|
287
|
+
return "Name required";
|
|
288
|
+
if (!/^[a-zA-Z0-9._-]+$/.test(v) && !/^[\u4e00-\u9fff\u3400-\u4dbf]+$/.test(v)) {
|
|
289
|
+
// Allow alphanumeric, dots, hyphens, underscores, or CJK chars
|
|
290
|
+
}
|
|
291
|
+
if (instances.some((i) => i.name === v))
|
|
292
|
+
return "Name already used";
|
|
293
|
+
return null;
|
|
294
|
+
},
|
|
295
|
+
});
|
|
296
|
+
const workDir = await ask(rl, "Working directory", {
|
|
297
|
+
validate: (v) => {
|
|
298
|
+
const expanded = expandHome(v);
|
|
299
|
+
if (!existsSync(expanded)) {
|
|
300
|
+
return `Not found: ${expanded} — create it first or auto-create on bind`;
|
|
301
|
+
}
|
|
302
|
+
return null;
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
let topicId;
|
|
306
|
+
if (mode === "topic") {
|
|
307
|
+
const tid = await ask(rl, "Topic ID (leave empty to auto-bind later)", {
|
|
308
|
+
default: "",
|
|
309
|
+
});
|
|
310
|
+
if (tid)
|
|
311
|
+
topicId = parseInt(tid, 10);
|
|
312
|
+
}
|
|
313
|
+
const expanded = expandHome(workDir);
|
|
314
|
+
instances.push({ name, workDir: expanded, topicId });
|
|
315
|
+
console.log(` ${green("+")} ${name} → ${expanded}${topicId ? ` (topic #${topicId})` : ""}`);
|
|
316
|
+
more = await confirm(rl, "Add another instance?", false);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// ── Step 7: Fleet Defaults ──
|
|
320
|
+
step(7, TOTAL_STEPS, "Fleet Defaults");
|
|
321
|
+
let costGuardLimit = 0;
|
|
322
|
+
let costGuardTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
323
|
+
const enableCostGuard = await confirm(rl, "Enable cost guard (daily spending limit)?", false);
|
|
324
|
+
if (enableCostGuard) {
|
|
325
|
+
const limitStr = await ask(rl, "Daily limit (USD)", {
|
|
326
|
+
default: "50",
|
|
327
|
+
validate: (v) => {
|
|
328
|
+
const n = parseFloat(v);
|
|
329
|
+
return isNaN(n) || n <= 0 ? "Must be a positive number" : null;
|
|
330
|
+
},
|
|
331
|
+
});
|
|
332
|
+
costGuardLimit = parseFloat(limitStr);
|
|
333
|
+
costGuardTimezone = await ask(rl, "Timezone", {
|
|
334
|
+
default: costGuardTimezone,
|
|
335
|
+
validate: (v) => {
|
|
336
|
+
try {
|
|
337
|
+
Intl.DateTimeFormat(undefined, { timeZone: v });
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
return `Invalid timezone: "${v}". Use IANA format (e.g. Asia/Taipei, America/New_York)`;
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
let dailySummaryHour = 21;
|
|
347
|
+
const enableSummary = await confirm(rl, "Enable daily summary report?", true);
|
|
348
|
+
if (enableSummary) {
|
|
349
|
+
const hourStr = await ask(rl, "Summary hour (0-23, local time)", {
|
|
350
|
+
default: "21",
|
|
351
|
+
validate: (v) => {
|
|
352
|
+
const n = parseInt(v, 10);
|
|
353
|
+
return isNaN(n) || n < 0 || n > 23 ? "Must be 0-23" : null;
|
|
354
|
+
},
|
|
355
|
+
});
|
|
356
|
+
dailySummaryHour = parseInt(hourStr, 10);
|
|
357
|
+
}
|
|
358
|
+
// ── Step 8: Voice Transcription (Groq) ──
|
|
359
|
+
step(8, TOTAL_STEPS, "Voice Transcription");
|
|
360
|
+
let groqApiKey = "";
|
|
361
|
+
// Check existing .env for GROQ_API_KEY
|
|
362
|
+
if (existsSync(ENV_PATH)) {
|
|
363
|
+
const existingEnv = readFileSync(ENV_PATH, "utf-8");
|
|
364
|
+
const groqMatch = existingEnv.match(/^GROQ_API_KEY=(gsk_\S+)/m);
|
|
365
|
+
if (groqMatch) {
|
|
366
|
+
const masked = groqMatch[1].slice(0, 8) + "..." + groqMatch[1].slice(-4);
|
|
367
|
+
console.log(` ${dim(`Found existing key: ${masked}`)}`);
|
|
368
|
+
const keep = await confirm(rl, "Keep existing Groq API key?");
|
|
369
|
+
if (keep)
|
|
370
|
+
groqApiKey = groqMatch[1];
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
if (!groqApiKey) {
|
|
374
|
+
const enableVoice = await confirm(rl, "Enable voice transcription (Groq Whisper)?", false);
|
|
375
|
+
if (enableVoice) {
|
|
376
|
+
console.log(` ${dim("Get a key from https://console.groq.com/keys")}`);
|
|
377
|
+
groqApiKey = await ask(rl, "Groq API Key", {
|
|
378
|
+
validate: (v) => v.startsWith("gsk_") ? null : "Must start with gsk_",
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
// ── Step 9: Summary ──
|
|
383
|
+
step(9, TOTAL_STEPS, "Summary");
|
|
384
|
+
console.log();
|
|
385
|
+
console.log(` ${bold("Bot:")} @${botUsername}`);
|
|
386
|
+
console.log(` ${bold("Token env:")} ${tokenEnvName}`);
|
|
387
|
+
console.log(` ${bold("Mode:")} ${mode}${groupId ? ` (group: ${groupId})` : ""}`);
|
|
388
|
+
console.log(` ${bold("Access:")} ${accessMode}${allowedUsers.length > 0 ? ` — users: ${allowedUsers.join(", ")}` : ""}`);
|
|
389
|
+
console.log(` ${bold("Roots:")} ${projectRoots.join(", ") || dim("(none)")}`);
|
|
390
|
+
if (instances.length > 0) {
|
|
391
|
+
console.log(` ${bold("Instances:")}`);
|
|
392
|
+
for (const inst of instances) {
|
|
393
|
+
console.log(` ${inst.name} → ${inst.workDir}${inst.topicId ? ` #${inst.topicId}` : ""}`);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
console.log(` ${bold("Instances:")} ${dim("(none — will auto-create from topics)")}`);
|
|
398
|
+
}
|
|
399
|
+
if (costGuardLimit > 0) {
|
|
400
|
+
console.log(` ${bold("Cost guard:")} $${costGuardLimit}/day (${costGuardTimezone})`);
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
console.log(` ${bold("Cost guard:")} ${dim("disabled")}`);
|
|
404
|
+
}
|
|
405
|
+
console.log(` ${bold("Daily sum.:")} ${enableSummary ? `${dailySummaryHour}:00` : dim("disabled")}`);
|
|
406
|
+
console.log(` ${bold("Voice:")} ${groqApiKey ? green("enabled (Groq Whisper)") : dim("disabled")}`);
|
|
407
|
+
console.log();
|
|
408
|
+
const proceed = await confirm(rl, "Write config?");
|
|
409
|
+
if (!proceed) {
|
|
410
|
+
console.log(" Setup cancelled.");
|
|
411
|
+
rl.close();
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
// ── Write files ──
|
|
415
|
+
mkdirSync(DATA_DIR, { recursive: true });
|
|
416
|
+
// .env — merge with existing, don't clobber other vars
|
|
417
|
+
let envContent = "";
|
|
418
|
+
if (existsSync(ENV_PATH)) {
|
|
419
|
+
envContent = readFileSync(ENV_PATH, "utf-8");
|
|
420
|
+
// Remove old token line with same env name
|
|
421
|
+
envContent = envContent
|
|
422
|
+
.split("\n")
|
|
423
|
+
.filter((line) => !line.startsWith(`${tokenEnvName}=`) && !(groqApiKey && line.startsWith("GROQ_API_KEY=")))
|
|
424
|
+
.join("\n");
|
|
425
|
+
if (envContent && !envContent.endsWith("\n"))
|
|
426
|
+
envContent += "\n";
|
|
427
|
+
}
|
|
428
|
+
envContent += `${tokenEnvName}=${token}\n`;
|
|
429
|
+
if (groqApiKey)
|
|
430
|
+
envContent += `GROQ_API_KEY=${groqApiKey}\n`;
|
|
431
|
+
writeFileSync(ENV_PATH, envContent);
|
|
432
|
+
console.log(` ${green("✓")} ${ENV_PATH}`);
|
|
433
|
+
// fleet.yaml
|
|
434
|
+
const yaml = await import("js-yaml");
|
|
435
|
+
const fleetData = {};
|
|
436
|
+
if (projectRoots.length > 0) {
|
|
437
|
+
fleetData.project_roots = projectRoots;
|
|
438
|
+
}
|
|
439
|
+
fleetData.channel = {
|
|
440
|
+
type: "telegram",
|
|
441
|
+
mode,
|
|
442
|
+
bot_token_env: tokenEnvName,
|
|
443
|
+
...(groupId != null ? { group_id: groupId } : {}),
|
|
444
|
+
access: {
|
|
445
|
+
mode: accessMode,
|
|
446
|
+
...(allowedUsers.length > 0 ? { allowed_users: allowedUsers } : {}),
|
|
447
|
+
},
|
|
448
|
+
};
|
|
449
|
+
fleetData.defaults = {
|
|
450
|
+
restart_policy: {
|
|
451
|
+
max_retries: 10,
|
|
452
|
+
backoff: "exponential",
|
|
453
|
+
reset_after: 300,
|
|
454
|
+
},
|
|
455
|
+
log_level: "info",
|
|
456
|
+
...(costGuardLimit > 0 ? {
|
|
457
|
+
cost_guard: {
|
|
458
|
+
daily_limit_usd: costGuardLimit,
|
|
459
|
+
warn_at_percentage: 80,
|
|
460
|
+
timezone: costGuardTimezone,
|
|
461
|
+
},
|
|
462
|
+
} : {}),
|
|
463
|
+
...(enableSummary ? {
|
|
464
|
+
daily_summary: {
|
|
465
|
+
enabled: true,
|
|
466
|
+
hour: dailySummaryHour,
|
|
467
|
+
minute: 0,
|
|
468
|
+
},
|
|
469
|
+
} : {}),
|
|
470
|
+
};
|
|
471
|
+
const instancesObj = {};
|
|
472
|
+
for (const inst of instances) {
|
|
473
|
+
instancesObj[inst.name] = {
|
|
474
|
+
working_directory: inst.workDir,
|
|
475
|
+
...(inst.topicId != null ? { topic_id: inst.topicId } : {}),
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
fleetData.instances = instancesObj;
|
|
479
|
+
writeFileSync(FLEET_CONFIG_PATH, yaml.dump(fleetData, { lineWidth: 120 }));
|
|
480
|
+
console.log(` ${green("✓")} ${FLEET_CONFIG_PATH}`);
|
|
481
|
+
// ── System service (optional) ──
|
|
482
|
+
console.log();
|
|
483
|
+
const installSvc = await confirm(rl, "Install as system service?", false);
|
|
484
|
+
if (installSvc) {
|
|
485
|
+
const { installService, detectPlatform } = await import("./service-installer.js");
|
|
486
|
+
const svcPath = installService({
|
|
487
|
+
label: "com.agend.fleet",
|
|
488
|
+
execPath: process.argv[1],
|
|
489
|
+
path: process.env.PATH,
|
|
490
|
+
workingDirectory: DATA_DIR,
|
|
491
|
+
logPath: join(DATA_DIR, "fleet.log"),
|
|
492
|
+
});
|
|
493
|
+
console.log(` ${green("✓")} ${svcPath}`);
|
|
494
|
+
const plat = detectPlatform();
|
|
495
|
+
if (plat === "macos") {
|
|
496
|
+
console.log(` Run: ${dim(`launchctl load ${svcPath}`)}`);
|
|
497
|
+
}
|
|
498
|
+
else {
|
|
499
|
+
console.log(` Run: ${dim("systemctl --user enable --now ccd")}`);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
// ── Done ──
|
|
503
|
+
console.log(`\n${green("✓")} ${bold("Setup complete!")}`);
|
|
504
|
+
console.log(` Bot: @${botUsername}`);
|
|
505
|
+
console.log(` Config: ${FLEET_CONFIG_PATH}`);
|
|
506
|
+
console.log();
|
|
507
|
+
console.log(` Start the fleet:`);
|
|
508
|
+
console.log(` ${dim("ccd fleet start")}`);
|
|
509
|
+
if (mode === "topic") {
|
|
510
|
+
console.log();
|
|
511
|
+
console.log(` ${dim("Create a new topic in the group — the bot will auto-detect it")}`);
|
|
512
|
+
console.log(` ${dim("and let you bind it to a project.")}`);
|
|
513
|
+
}
|
|
514
|
+
console.log();
|
|
515
|
+
rl.close();
|
|
516
|
+
}
|
|
517
|
+
//# sourceMappingURL=setup-wizard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-wizard.js","sourceRoot":"","sources":["../src/setup-wizard.ts"],"names":[],"mappings":"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"}
|
package/dist/stt.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface SttResult {
|
|
2
|
+
text: string;
|
|
3
|
+
language?: string;
|
|
4
|
+
duration?: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Transcribe audio using Groq Whisper API.
|
|
8
|
+
* Supports OGG, MP3, WAV, FLAC, M4A, WEBM.
|
|
9
|
+
*/
|
|
10
|
+
export declare function transcribe(filePath: string, apiKey: string, model?: string): Promise<SttResult>;
|
package/dist/stt.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { basename } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Transcribe audio using Groq Whisper API.
|
|
5
|
+
* Supports OGG, MP3, WAV, FLAC, M4A, WEBM.
|
|
6
|
+
*/
|
|
7
|
+
export async function transcribe(filePath, apiKey, model = "whisper-large-v3-turbo") {
|
|
8
|
+
const fileBuffer = readFileSync(filePath);
|
|
9
|
+
// Telegram voice files use .oga extension; Groq expects .ogg
|
|
10
|
+
let fileName = basename(filePath);
|
|
11
|
+
if (fileName.endsWith(".oga")) {
|
|
12
|
+
fileName = fileName.replace(/\.oga$/, ".ogg");
|
|
13
|
+
}
|
|
14
|
+
const formData = new FormData();
|
|
15
|
+
formData.append("file", new Blob([fileBuffer], { type: "audio/ogg" }), fileName);
|
|
16
|
+
formData.append("model", model);
|
|
17
|
+
const res = await fetch("https://api.groq.com/openai/v1/audio/transcriptions", {
|
|
18
|
+
method: "POST",
|
|
19
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
20
|
+
body: formData,
|
|
21
|
+
});
|
|
22
|
+
if (!res.ok) {
|
|
23
|
+
const errText = await res.text();
|
|
24
|
+
throw new Error(`Groq STT failed (${res.status}): ${errText}`);
|
|
25
|
+
}
|
|
26
|
+
const data = (await res.json());
|
|
27
|
+
return {
|
|
28
|
+
text: data.text,
|
|
29
|
+
language: data.language,
|
|
30
|
+
duration: data.duration,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=stt.js.map
|
package/dist/stt.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stt.js","sourceRoot":"","sources":["../src/stt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAQrC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,QAAgB,EAChB,MAAc,EACd,KAAK,GAAG,wBAAwB;IAEhC,MAAM,UAAU,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC1C,6DAA6D;IAC7D,IAAI,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9B,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;IACjF,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAEhC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,qDAAqD,EAAE;QAC7E,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,EAAE,EAAE;QAC9C,IAAI,EAAE,QAAQ;KACf,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,CAAC,MAAM,MAAM,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA2D,CAAC;IAC1F,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare class TmuxManager {
|
|
2
|
+
private sessionName;
|
|
3
|
+
private windowId;
|
|
4
|
+
constructor(sessionName: string, windowId: string);
|
|
5
|
+
static ensureSession(name: string): Promise<void>;
|
|
6
|
+
static sessionExists(name: string): Promise<boolean>;
|
|
7
|
+
static killSession(name: string): Promise<void>;
|
|
8
|
+
static listWindows(sessionName: string): Promise<Array<{
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
}>>;
|
|
12
|
+
createWindow(command: string, cwd: string, windowName?: string): Promise<string>;
|
|
13
|
+
killWindow(): Promise<void>;
|
|
14
|
+
isWindowAlive(): Promise<boolean>;
|
|
15
|
+
sendKeys(text: string): Promise<boolean>;
|
|
16
|
+
sendSpecialKey(key: "Enter" | "Escape" | "Up" | "Down"): Promise<boolean>;
|
|
17
|
+
/** Paste text via bracketed paste (safe for CLIs with single-char hotkeys like Gemini's '!') */
|
|
18
|
+
pasteText(text: string): Promise<boolean>;
|
|
19
|
+
pipeOutput(logPath: string): Promise<void>;
|
|
20
|
+
capturePane(): Promise<string>;
|
|
21
|
+
getWindowId(): string;
|
|
22
|
+
}
|