openclaw-telegram-manager 1.0.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,6 +25,8 @@ npx openclaw-telegram-manager setup
25
25
 
26
26
  That's it. The setup script installs the plugin, patches your config, creates the workspace, and restarts the OpenClaw gateway. It's idempotent — running it twice won't break anything.
27
27
 
28
+ **Security warnings during install:** OpenClaw's automatic scanner may flag `child_process` and `process.env` usage. These are expected — the setup script calls `openclaw --version`, `openclaw plugins install`, and `openclaw gateway restart`, and reads `process.env` for config directory detection. No data is sent externally.
29
+
28
30
  Once that's done, head to your Telegram group:
29
31
 
30
32
  1. Open any topic
@@ -92,6 +94,14 @@ The first person to run `/topic init` automatically becomes admin.
92
94
 
93
95
  See [SECURITY.md](SECURITY.md) for reporting vulnerabilities.
94
96
 
97
+ ## Uninstalling
98
+
99
+ ```bash
100
+ npx openclaw-telegram-manager uninstall
101
+ ```
102
+
103
+ This removes the plugin extension files, the `$include` reference from `openclaw.json`, and the generated include file, then restarts the gateway. Workspace data (your topic capsules) is kept — the command prints the path if you want to remove it manually.
104
+
95
105
  ## Contributing
96
106
 
97
107
  See [CONTRIBUTING.md](CONTRIBUTING.md).
package/dist/setup.js CHANGED
@@ -3,97 +3,143 @@ import * as fs from 'node:fs';
3
3
  import * as path from 'node:path';
4
4
  import * as crypto from 'node:crypto';
5
5
  import { execSync } from 'node:child_process';
6
- import * as readline from 'node:readline';
7
6
  // ── Constants ──────────────────────────────────────────────────────────
7
+ const PLUGIN_NAME = 'openclaw-telegram-manager';
8
+ const PLUGIN_VERSION = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf-8')).version;
8
9
  const MIN_OPENCLAW_VERSION = '2026.1.0';
9
10
  const INCLUDE_FILENAME = 'telegram-manager.generated.groups.json5';
10
11
  const REGISTRY_FILENAME = 'topics.json';
11
- // ── Main ──────────────────────────────────────────────────────────────
12
- async function main() {
13
- console.log('openclaw-telegram-manager setup');
14
- console.log('================================\n');
15
- // Step 1: Check OpenClaw version
12
+ const PLUGIN_FILES = ['openclaw.plugin.json', 'src', 'skills', 'package.json'];
13
+ // ── Colors (zero dependencies, respects NO_COLOR / non-TTY) ──────────
14
+ const useColor = process.stdout.isTTY === true &&
15
+ !process.env['NO_COLOR'] &&
16
+ process.env['TERM'] !== 'dumb';
17
+ const c = {
18
+ reset: useColor ? '\x1b[0m' : '',
19
+ bold: useColor ? '\x1b[1m' : '',
20
+ dim: useColor ? '\x1b[2m' : '',
21
+ green: useColor ? '\x1b[32m' : '',
22
+ yellow: useColor ? '\x1b[33m' : '',
23
+ red: useColor ? '\x1b[31m' : '',
24
+ cyan: useColor ? '\x1b[36m' : '',
25
+ magenta: useColor ? '\x1b[35m' : '',
26
+ };
27
+ // ── Logging helpers ───────────────────────────────────────────────────
28
+ function ok(msg) {
29
+ console.log(` ${c.green}✓${c.reset} ${msg}`);
30
+ }
31
+ function warn(msg) {
32
+ console.warn(` ${c.yellow}⚠${c.reset} ${c.yellow}${msg}${c.reset}`);
33
+ }
34
+ function fail(msg) {
35
+ console.error(` ${c.red}✗${c.reset} ${c.red}${msg}${c.reset}`);
36
+ }
37
+ function info(msg) {
38
+ console.log(` ${c.dim}${msg}${c.reset}`);
39
+ }
40
+ function banner(title, subtitle) {
41
+ console.log('');
42
+ console.log(` ${c.cyan}◆${c.reset} ${c.bold}${title}${c.reset}${subtitle ? ` ${c.dim}${subtitle}${c.reset}` : ''}`);
43
+ console.log(` ${c.dim}│${c.reset}`);
44
+ }
45
+ function footer(msg) {
46
+ console.log(` ${c.dim}│${c.reset}`);
47
+ console.log(` ${c.green}◆${c.reset} ${c.bold}${msg}${c.reset}`);
48
+ console.log('');
49
+ }
50
+ // ── Entry point ───────────────────────────────────────────────────────
51
+ const command = process.argv[2] ?? 'setup';
52
+ if (command === 'setup') {
53
+ runSetup().catch((err) => {
54
+ console.error('Setup failed:', err instanceof Error ? err.message : String(err));
55
+ process.exit(1);
56
+ });
57
+ }
58
+ else if (command === 'uninstall') {
59
+ runUninstall().catch((err) => {
60
+ console.error('Uninstall failed:', err instanceof Error ? err.message : String(err));
61
+ process.exit(1);
62
+ });
63
+ }
64
+ else {
65
+ console.error(`Unknown command: ${command}`);
66
+ console.error(`Usage: ${PLUGIN_NAME} [setup|uninstall]`);
67
+ process.exit(1);
68
+ }
69
+ // ── Setup ─────────────────────────────────────────────────────────────
70
+ async function runSetup() {
71
+ banner(PLUGIN_NAME, `v${PLUGIN_VERSION}`);
16
72
  const version = checkOpenClawVersion();
17
- console.log(`[1/11] OpenClaw version: ${version}`);
18
- // Step 2: Locate config directory
73
+ ok(`OpenClaw ${c.dim}${version}${c.reset}`);
19
74
  const configDir = locateConfigDir();
20
- console.log(`[2/11] Config directory: ${configDir}`);
21
- // Step 3: Check directory permissions
22
75
  checkDirPermissions(configDir);
23
- console.log('[3/11] Directory permissions checked');
24
- // Step 4: Install plugin
25
- installPlugin();
26
- console.log('[4/11] Plugin installation checked');
27
- // Step 5: Patch openclaw.json with $include reference
76
+ ok(`Config ${c.dim}${configDir}${c.reset}`);
77
+ installPlugin(configDir);
28
78
  patchConfig(configDir);
29
- console.log('[5/11] Config patched with $include reference');
30
- // Step 6: Create workspace directory structure
31
- const workspaceDir = path.join(configDir, 'workspace');
32
- const projectsDir = path.join(workspaceDir, 'projects');
79
+ const projectsDir = path.join(configDir, 'workspace', 'projects');
33
80
  ensureDir(projectsDir);
34
- console.log(`[6/11] Workspace directory: ${projectsDir}`);
35
- // Step 7: Initialize empty registry
36
81
  initRegistry(projectsDir);
37
- console.log('[7/11] Registry initialized');
38
- // Step 8: Create empty generated include
39
82
  createEmptyInclude(configDir);
40
- console.log('[8/11] Empty include file created');
41
- // Step 9: Optional cron setup
42
- const isInteractive = process.stdin.isTTY === true;
43
- const setupCron = isInteractive ? await promptYesNo('Set up daily doctor cron job? [Y/n] ') : true;
44
- if (setupCron) {
45
- const groupId = isInteractive
46
- ? await promptInput('Enter your Telegram group ID (e.g., -1003731538650): ')
47
- : '';
48
- setupDoctorCron(configDir, groupId);
49
- console.log('[9/11] Doctor cron job configured');
83
+ ok('Workspace ready');
84
+ triggerRestart();
85
+ ok('Gateway restarted');
86
+ footer('Setup complete');
87
+ console.log(` ${c.dim}Next steps:${c.reset}`);
88
+ console.log(` ${c.dim}1.${c.reset} Open any Telegram forum topic`);
89
+ console.log(` ${c.dim}2.${c.reset} Type ${c.cyan}/topic init${c.reset}`);
90
+ console.log(` ${c.dim}3.${c.reset} The topic will be registered and a capsule created`);
91
+ console.log('');
92
+ }
93
+ // ── Uninstall ─────────────────────────────────────────────────────────
94
+ async function runUninstall() {
95
+ banner(PLUGIN_NAME, 'uninstall');
96
+ const configDir = locateConfigDir();
97
+ ok(`Config ${c.dim}${configDir}${c.reset}`);
98
+ unpatchConfig(configDir);
99
+ removeFile(path.join(configDir, INCLUDE_FILENAME));
100
+ removePluginDir(configDir);
101
+ ok('Plugin files removed');
102
+ triggerRestart();
103
+ ok('Gateway restarted');
104
+ const projectsDir = path.join(configDir, 'workspace', 'projects');
105
+ if (fs.existsSync(projectsDir)) {
106
+ info('Workspace data kept: ' + projectsDir);
107
+ info('To remove: rm -rf ' + projectsDir);
50
108
  }
51
- else {
52
- console.log('[9/11] Skipped cron setup');
53
- }
54
- // Step 10: Trigger gateway restart
55
- triggerRestart(configDir);
56
- console.log('[10/11] Gateway restart triggered');
57
- // Step 11: Print summary
58
- printSummary(configDir, projectsDir);
59
- console.log('[11/11] Setup complete!\n');
109
+ footer('Uninstall complete');
60
110
  }
61
- // ── Step implementations ──────────────────────────────────────────────
111
+ // ── Setup step implementations ────────────────────────────────────────
62
112
  function checkOpenClawVersion() {
63
113
  let version;
64
114
  try {
65
115
  version = execSync('openclaw --version', { encoding: 'utf-8' }).trim();
66
116
  }
67
117
  catch {
68
- console.error('Error: OpenClaw not found. Please install OpenClaw (>=2026.1.0) first.');
118
+ fail('OpenClaw not found. Install OpenClaw (>=2026.1.0) first.');
69
119
  process.exit(1);
70
120
  }
71
- // Extract version number (e.g., "openclaw 2026.2.0" -> "2026.2.0")
72
121
  const match = version.match(/(\d+\.\d+\.\d+)/);
73
122
  if (!match) {
74
- console.warn(`Warning: Could not parse OpenClaw version from "${version}". Proceeding anyway.`);
123
+ warn(`Could not parse version from "${version}". Proceeding anyway.`);
75
124
  return version;
76
125
  }
77
126
  const versionStr = match[1];
78
127
  if (compareVersions(versionStr, MIN_OPENCLAW_VERSION) < 0) {
79
- console.error(`Error: OpenClaw ${versionStr} found, but openclaw-telegram-manager requires >=${MIN_OPENCLAW_VERSION}. Please upgrade.`);
128
+ fail(`OpenClaw ${versionStr} found, requires >=${MIN_OPENCLAW_VERSION}. Please upgrade.`);
80
129
  process.exit(1);
81
130
  }
82
131
  return versionStr;
83
132
  }
84
133
  function locateConfigDir() {
85
- // Check environment variable
86
134
  const envDir = process.env['OPENCLAW_CONFIG_DIR'];
87
135
  if (envDir && fs.existsSync(envDir)) {
88
136
  return path.resolve(envDir);
89
137
  }
90
- // Check default location
91
138
  const homeDir = process.env['HOME'] ?? process.env['USERPROFILE'] ?? '';
92
139
  const defaultDir = path.join(homeDir, '.openclaw');
93
140
  if (fs.existsSync(defaultDir)) {
94
141
  return defaultDir;
95
142
  }
96
- // Walk up from cwd looking for openclaw.json
97
143
  let dir = process.cwd();
98
144
  while (dir !== path.dirname(dir)) {
99
145
  if (fs.existsSync(path.join(dir, 'openclaw.json'))) {
@@ -101,7 +147,7 @@ function locateConfigDir() {
101
147
  }
102
148
  dir = path.dirname(dir);
103
149
  }
104
- console.error('Error: Could not find OpenClaw config directory. Set $OPENCLAW_CONFIG_DIR or ensure ~/.openclaw/ exists.');
150
+ fail('Could not find OpenClaw config directory. Set $OPENCLAW_CONFIG_DIR or ensure ~/.openclaw/ exists.');
105
151
  process.exit(1);
106
152
  }
107
153
  function checkDirPermissions(dir) {
@@ -109,94 +155,90 @@ function checkDirPermissions(dir) {
109
155
  const stat = fs.statSync(dir);
110
156
  const mode = stat.mode;
111
157
  const permissions = (mode & 0o777).toString(8);
112
- // Check for world-writable or group-writable
113
158
  if (mode & 0o002) {
114
- console.warn(`Warning: ${dir} is world-writable (${permissions}). Consider restricting to owner-only (chmod 700).`);
159
+ warn(`${dir} is world-writable (${permissions}). Consider chmod 700.`);
115
160
  }
116
161
  else if (mode & 0o020) {
117
- console.warn(`Warning: ${dir} is group-writable (${permissions}). Consider restricting to owner-only (chmod 700).`);
162
+ warn(`${dir} is group-writable (${permissions}). Consider chmod 700.`);
118
163
  }
119
164
  }
120
165
  catch {
121
- console.warn(`Warning: Could not check permissions for ${dir}.`);
166
+ warn(`Could not check permissions for ${dir}.`);
122
167
  }
123
168
  }
124
- function installPlugin() {
125
- try {
126
- // Check if already installed
127
- const result = execSync('openclaw plugins list', { encoding: 'utf-8' });
128
- if (result.includes('openclaw-telegram-manager')) {
129
- console.log(' Plugin already installed, skipping.');
130
- return;
131
- }
169
+ function installPlugin(configDir) {
170
+ const extDir = path.join(configDir, 'extensions', PLUGIN_NAME);
171
+ if (fs.existsSync(path.join(extDir, 'openclaw.plugin.json'))) {
172
+ ok('Plugin already installed');
173
+ return;
132
174
  }
133
- catch {
134
- // plugins list might not be available, try installing anyway
175
+ const pkgRoot = findPackageRoot();
176
+ if (pkgRoot) {
177
+ fs.mkdirSync(extDir, { recursive: true });
178
+ for (const entry of PLUGIN_FILES) {
179
+ const src = path.join(pkgRoot, entry);
180
+ if (!fs.existsSync(src))
181
+ continue;
182
+ copyRecursive(src, path.join(extDir, entry));
183
+ }
184
+ installDeps(extDir);
185
+ ok('Plugin installed');
186
+ return;
135
187
  }
136
188
  try {
137
- execSync('openclaw plugins install openclaw-telegram-manager', {
189
+ execSync(`openclaw plugins install ${PLUGIN_NAME}`, {
138
190
  encoding: 'utf-8',
139
191
  stdio: 'inherit',
140
192
  });
193
+ ok('Plugin installed');
141
194
  }
142
195
  catch {
143
- console.warn(' Warning: Could not install plugin via `openclaw plugins install`. You may need to install manually.');
196
+ warn('Could not install plugin. You may need to install manually.');
144
197
  }
145
198
  }
146
199
  function patchConfig(configDir) {
147
200
  const configPath = path.join(configDir, 'openclaw.json');
148
201
  if (!fs.existsSync(configPath)) {
149
- console.warn(` Warning: ${configPath} not found. Skipping config patch.`);
202
+ warn(`${configPath} not found. Skipping config patch.`);
150
203
  return;
151
204
  }
152
205
  let content;
153
206
  try {
154
207
  content = fs.readFileSync(configPath, 'utf-8');
155
208
  }
156
- catch (err) {
157
- console.warn(` Warning: Could not read ${configPath}. Skipping config patch.`);
209
+ catch {
210
+ warn(`Could not read ${configPath}. Skipping config patch.`);
158
211
  return;
159
212
  }
160
- // Check if $include reference already exists
161
213
  if (content.includes(INCLUDE_FILENAME)) {
162
- console.log(' $include reference already present, skipping.');
214
+ ok('Config already patched');
163
215
  return;
164
216
  }
165
- // Parse as JSON (OpenClaw config may be JSON or JSON5)
166
217
  let config;
167
218
  try {
168
219
  config = JSON.parse(content);
169
220
  }
170
221
  catch {
171
- // Try a more lenient approach: just check for the string and warn
172
- console.warn(' Warning: Could not parse openclaw.json as JSON. Please manually add the $include reference.');
173
- console.warn(` Add to channels.telegram.groups: { "$include": "./${INCLUDE_FILENAME}" }`);
222
+ warn('Could not parse openclaw.json. Please manually add the $include reference.');
223
+ info(`Add to channels.telegram.groups: { "$include": "./${INCLUDE_FILENAME}" }`);
174
224
  return;
175
225
  }
176
- // Ensure path exists: channels.telegram.groups
177
226
  if (!config['channels'])
178
227
  config['channels'] = {};
179
228
  const channels = config['channels'];
180
229
  if (!channels['telegram'])
181
230
  channels['telegram'] = {};
182
231
  const telegram = channels['telegram'];
183
- // Set groups to $include
184
232
  telegram['groups'] = { $include: `./${INCLUDE_FILENAME}` };
185
- // Backup and write
186
233
  const bakPath = configPath + '.bak';
187
234
  fs.copyFileSync(configPath, bakPath);
188
235
  const newContent = JSON.stringify(config, null, 2) + '\n';
189
236
  fs.writeFileSync(configPath, newContent, { mode: 0o600 });
190
- }
191
- function ensureDir(dir) {
192
- if (!fs.existsSync(dir)) {
193
- fs.mkdirSync(dir, { recursive: true });
194
- }
237
+ ok('Config patched');
195
238
  }
196
239
  function initRegistry(projectsDir) {
197
240
  const registryPath = path.join(projectsDir, REGISTRY_FILENAME);
198
241
  if (fs.existsSync(registryPath)) {
199
- console.log(' Registry already exists, skipping initialization.');
200
242
  return;
201
243
  }
202
244
  const callbackSecret = crypto.randomBytes(32).toString('hex');
@@ -215,7 +257,6 @@ function initRegistry(projectsDir) {
215
257
  function createEmptyInclude(configDir) {
216
258
  const includePath = path.join(configDir, INCLUDE_FILENAME);
217
259
  if (fs.existsSync(includePath)) {
218
- console.log(' Include file already exists, skipping.');
219
260
  return;
220
261
  }
221
262
  const content = [
@@ -225,45 +266,60 @@ function createEmptyInclude(configDir) {
225
266
  ].join('\n');
226
267
  fs.writeFileSync(includePath, content, { mode: 0o600 });
227
268
  }
228
- function setupDoctorCron(configDir, groupId) {
229
- const cronDir = path.join(configDir, 'cron');
230
- ensureDir(cronDir);
231
- const cronJobPath = path.join(cronDir, 'topic-doctor-daily.json');
232
- if (fs.existsSync(cronJobPath)) {
233
- console.log(' Cron job already exists, skipping.');
269
+ // ── Uninstall step implementations ────────────────────────────────────
270
+ function unpatchConfig(configDir) {
271
+ const configPath = path.join(configDir, 'openclaw.json');
272
+ const bakPath = configPath + '.bak';
273
+ if (!fs.existsSync(configPath)) {
234
274
  return;
235
275
  }
236
- const target = groupId
237
- ? `${groupId}:topic:1`
238
- : '-100XXXXXXXXXX:topic:1';
239
- const cronJob = {
240
- name: 'topic-doctor-daily',
241
- schedule: { kind: 'cron', expr: '0 9 * * *', tz: 'UTC' },
242
- sessionTarget: 'isolated',
243
- payload: {
244
- kind: 'agentTurn',
245
- message: 'Run topic doctor health checks on all registered topics. Check the registry at projects/topics.json and evaluate each eligible topic. Post per-topic reports with inline keyboards. If any topic\'s thread returns an API error (deleted/migrated), log it and continue to the next topic.',
246
- timeoutSeconds: 300,
247
- },
248
- delivery: {
249
- mode: 'announce',
250
- channel: 'telegram',
251
- to: target,
252
- bestEffort: true,
253
- },
254
- enabled: true,
255
- deleteAfterRun: false,
256
- };
257
- fs.writeFileSync(cronJobPath, JSON.stringify(cronJob, null, 2) + '\n', {
258
- mode: 0o600,
259
- });
260
- if (!groupId) {
261
- console.warn(' Warning: No group ID provided. Edit the cron job at:');
262
- console.warn(` ${cronJobPath}`);
263
- console.warn(' Replace -100XXXXXXXXXX with your actual group ID.');
276
+ let content;
277
+ try {
278
+ content = fs.readFileSync(configPath, 'utf-8');
279
+ }
280
+ catch {
281
+ warn(`Could not read ${configPath}.`);
282
+ return;
283
+ }
284
+ if (!content.includes(INCLUDE_FILENAME)) {
285
+ return;
286
+ }
287
+ let config;
288
+ try {
289
+ config = JSON.parse(content);
290
+ }
291
+ catch {
292
+ warn('Could not parse openclaw.json. Please manually remove the $include reference.');
293
+ return;
294
+ }
295
+ const channels = config['channels'];
296
+ const telegram = channels?.['telegram'];
297
+ if (telegram) {
298
+ delete telegram['groups'];
299
+ if (Object.keys(telegram).length === 0)
300
+ delete channels['telegram'];
301
+ if (Object.keys(channels).length === 0)
302
+ delete config['channels'];
303
+ }
304
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
305
+ // Clean up stale backup from install time
306
+ if (fs.existsSync(bakPath)) {
307
+ fs.unlinkSync(bakPath);
308
+ }
309
+ }
310
+ function removeFile(filePath) {
311
+ if (fs.existsSync(filePath)) {
312
+ fs.unlinkSync(filePath);
313
+ }
314
+ }
315
+ function removePluginDir(configDir) {
316
+ const extDir = path.join(configDir, 'extensions', PLUGIN_NAME);
317
+ if (fs.existsSync(extDir)) {
318
+ fs.rmSync(extDir, { recursive: true });
264
319
  }
265
320
  }
266
- function triggerRestart(configDir) {
321
+ // ── Shared helpers ────────────────────────────────────────────────────
322
+ function triggerRestart() {
267
323
  try {
268
324
  execSync('openclaw gateway restart', {
269
325
  encoding: 'utf-8',
@@ -271,24 +327,14 @@ function triggerRestart(configDir) {
271
327
  });
272
328
  }
273
329
  catch {
274
- console.warn(' Warning: Could not restart gateway. Run `openclaw gateway restart` manually.');
330
+ warn('Could not restart gateway. Run `openclaw gateway restart` manually.');
275
331
  }
276
332
  }
277
- function printSummary(configDir, projectsDir) {
278
- console.log('\n================================');
279
- console.log('Setup complete!\n');
280
- console.log('What was done:');
281
- console.log(` - Config directory: ${configDir}`);
282
- console.log(` - Projects directory: ${projectsDir}`);
283
- console.log(` - Registry: ${path.join(projectsDir, REGISTRY_FILENAME)}`);
284
- console.log(` - Include: ${path.join(configDir, INCLUDE_FILENAME)}`);
285
- console.log('\nNext steps:');
286
- console.log(' 1. Go to any Telegram forum topic');
287
- console.log(' 2. Type /topic init');
288
- console.log(' 3. The topic will be registered and a capsule created');
289
- console.log('\nFor help: /topic help');
333
+ function ensureDir(dir) {
334
+ if (!fs.existsSync(dir)) {
335
+ fs.mkdirSync(dir, { recursive: true });
336
+ }
290
337
  }
291
- // ── Helpers ───────────────────────────────────────────────────────────
292
338
  function compareVersions(a, b) {
293
339
  const aParts = a.split('.').map(Number);
294
340
  const bParts = b.split('.').map(Number);
@@ -300,34 +346,39 @@ function compareVersions(a, b) {
300
346
  }
301
347
  return 0;
302
348
  }
303
- function promptYesNo(question) {
304
- return new Promise((resolve) => {
305
- const rl = readline.createInterface({
306
- input: process.stdin,
307
- output: process.stdout,
308
- });
309
- rl.question(question, (answer) => {
310
- rl.close();
311
- const normalized = answer.trim().toLowerCase();
312
- resolve(normalized === '' || normalized === 'y' || normalized === 'yes');
349
+ function installDeps(dir) {
350
+ try {
351
+ execSync('npm install --production --ignore-scripts', {
352
+ cwd: dir,
353
+ encoding: 'utf-8',
354
+ stdio: 'pipe',
355
+ timeout: 60_000,
313
356
  });
314
- });
357
+ }
358
+ catch {
359
+ warn('Could not install dependencies. Run `npm install --production` in ' + dir);
360
+ }
315
361
  }
316
- function promptInput(question) {
317
- return new Promise((resolve) => {
318
- const rl = readline.createInterface({
319
- input: process.stdin,
320
- output: process.stdout,
321
- });
322
- rl.question(question, (answer) => {
323
- rl.close();
324
- resolve(answer.trim());
325
- });
326
- });
362
+ function findPackageRoot() {
363
+ let dir = path.dirname(new URL(import.meta.url).pathname);
364
+ for (let i = 0; i < 5; i++) {
365
+ if (fs.existsSync(path.join(dir, 'openclaw.plugin.json'))) {
366
+ return dir;
367
+ }
368
+ dir = path.dirname(dir);
369
+ }
370
+ return null;
371
+ }
372
+ function copyRecursive(src, dest) {
373
+ const stat = fs.statSync(src);
374
+ if (stat.isDirectory()) {
375
+ fs.mkdirSync(dest, { recursive: true });
376
+ for (const entry of fs.readdirSync(src)) {
377
+ copyRecursive(path.join(src, entry), path.join(dest, entry));
378
+ }
379
+ }
380
+ else {
381
+ fs.copyFileSync(src, dest);
382
+ }
327
383
  }
328
- // ── Entry point ───────────────────────────────────────────────────────
329
- main().catch((err) => {
330
- console.error('Setup failed:', err instanceof Error ? err.message : String(err));
331
- process.exit(1);
332
- });
333
384
  //# sourceMappingURL=setup.js.map
package/dist/setup.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,10 @@
3
3
  "name": "Telegram Topic Manager",
4
4
  "version": "1.0.0",
5
5
  "description": "Deterministic Telegram forum topic management for OpenClaw",
6
- "license": "MIT",
7
- "slotType": "tool",
8
- "entry": "./src/index.ts"
6
+ "configSchema": {
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "properties": {}
10
+ },
11
+ "skills": ["./skills"]
9
12
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-telegram-manager",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "description": "Deterministic Telegram forum topic management for OpenClaw",
6
6
  "license": "MIT",
package/src/setup.ts CHANGED
@@ -4,101 +4,161 @@ import * as fs from 'node:fs';
4
4
  import * as path from 'node:path';
5
5
  import * as crypto from 'node:crypto';
6
6
  import { execSync } from 'node:child_process';
7
- import * as readline from 'node:readline';
8
7
 
9
8
  // ── Constants ──────────────────────────────────────────────────────────
10
9
 
10
+ const PLUGIN_NAME = 'openclaw-telegram-manager';
11
+ const PLUGIN_VERSION: string = JSON.parse(
12
+ fs.readFileSync(new URL('../package.json', import.meta.url), 'utf-8'),
13
+ ).version;
11
14
  const MIN_OPENCLAW_VERSION = '2026.1.0';
12
15
  const INCLUDE_FILENAME = 'telegram-manager.generated.groups.json5';
13
16
  const REGISTRY_FILENAME = 'topics.json';
17
+ const PLUGIN_FILES = ['openclaw.plugin.json', 'src', 'skills', 'package.json'];
18
+
19
+ // ── Colors (zero dependencies, respects NO_COLOR / non-TTY) ──────────
20
+
21
+ const useColor =
22
+ process.stdout.isTTY === true &&
23
+ !process.env['NO_COLOR'] &&
24
+ process.env['TERM'] !== 'dumb';
25
+
26
+ const c = {
27
+ reset: useColor ? '\x1b[0m' : '',
28
+ bold: useColor ? '\x1b[1m' : '',
29
+ dim: useColor ? '\x1b[2m' : '',
30
+ green: useColor ? '\x1b[32m' : '',
31
+ yellow: useColor ? '\x1b[33m' : '',
32
+ red: useColor ? '\x1b[31m' : '',
33
+ cyan: useColor ? '\x1b[36m' : '',
34
+ magenta: useColor ? '\x1b[35m' : '',
35
+ };
36
+
37
+ // ── Logging helpers ───────────────────────────────────────────────────
38
+
39
+ function ok(msg: string): void {
40
+ console.log(` ${c.green}✓${c.reset} ${msg}`);
41
+ }
42
+ function warn(msg: string): void {
43
+ console.warn(` ${c.yellow}⚠${c.reset} ${c.yellow}${msg}${c.reset}`);
44
+ }
45
+ function fail(msg: string): void {
46
+ console.error(` ${c.red}✗${c.reset} ${c.red}${msg}${c.reset}`);
47
+ }
48
+ function info(msg: string): void {
49
+ console.log(` ${c.dim}${msg}${c.reset}`);
50
+ }
51
+
52
+ function banner(title: string, subtitle?: string): void {
53
+ console.log('');
54
+ console.log(` ${c.cyan}◆${c.reset} ${c.bold}${title}${c.reset}${subtitle ? ` ${c.dim}${subtitle}${c.reset}` : ''}`);
55
+ console.log(` ${c.dim}│${c.reset}`);
56
+ }
57
+
58
+ function footer(msg: string): void {
59
+ console.log(` ${c.dim}│${c.reset}`);
60
+ console.log(` ${c.green}◆${c.reset} ${c.bold}${msg}${c.reset}`);
61
+ console.log('');
62
+ }
14
63
 
15
- // ── Main ──────────────────────────────────────────────────────────────
64
+ // ── Entry point ───────────────────────────────────────────────────────
16
65
 
17
- async function main(): Promise<void> {
18
- console.log('openclaw-telegram-manager setup');
19
- console.log('================================\n');
66
+ const command = process.argv[2] ?? 'setup';
67
+
68
+ if (command === 'setup') {
69
+ runSetup().catch((err) => {
70
+ console.error('Setup failed:', err instanceof Error ? err.message : String(err));
71
+ process.exit(1);
72
+ });
73
+ } else if (command === 'uninstall') {
74
+ runUninstall().catch((err) => {
75
+ console.error('Uninstall failed:', err instanceof Error ? err.message : String(err));
76
+ process.exit(1);
77
+ });
78
+ } else {
79
+ console.error(`Unknown command: ${command}`);
80
+ console.error(`Usage: ${PLUGIN_NAME} [setup|uninstall]`);
81
+ process.exit(1);
82
+ }
83
+
84
+ // ── Setup ─────────────────────────────────────────────────────────────
85
+
86
+ async function runSetup(): Promise<void> {
87
+ banner(PLUGIN_NAME, `v${PLUGIN_VERSION}`);
20
88
 
21
- // Step 1: Check OpenClaw version
22
89
  const version = checkOpenClawVersion();
23
- console.log(`[1/11] OpenClaw version: ${version}`);
90
+ ok(`OpenClaw ${c.dim}${version}${c.reset}`);
24
91
 
25
- // Step 2: Locate config directory
26
92
  const configDir = locateConfigDir();
27
- console.log(`[2/11] Config directory: ${configDir}`);
28
-
29
- // Step 3: Check directory permissions
30
93
  checkDirPermissions(configDir);
31
- console.log('[3/11] Directory permissions checked');
32
-
33
- // Step 4: Install plugin
34
- installPlugin();
35
- console.log('[4/11] Plugin installation checked');
94
+ ok(`Config ${c.dim}${configDir}${c.reset}`);
36
95
 
37
- // Step 5: Patch openclaw.json with $include reference
96
+ installPlugin(configDir);
38
97
  patchConfig(configDir);
39
- console.log('[5/11] Config patched with $include reference');
40
98
 
41
- // Step 6: Create workspace directory structure
42
- const workspaceDir = path.join(configDir, 'workspace');
43
- const projectsDir = path.join(workspaceDir, 'projects');
99
+ const projectsDir = path.join(configDir, 'workspace', 'projects');
44
100
  ensureDir(projectsDir);
45
- console.log(`[6/11] Workspace directory: ${projectsDir}`);
46
-
47
- // Step 7: Initialize empty registry
48
101
  initRegistry(projectsDir);
49
- console.log('[7/11] Registry initialized');
50
-
51
- // Step 8: Create empty generated include
52
102
  createEmptyInclude(configDir);
53
- console.log('[8/11] Empty include file created');
54
-
55
- // Step 9: Optional cron setup
56
- const isInteractive = process.stdin.isTTY === true;
57
- const setupCron = isInteractive ? await promptYesNo('Set up daily doctor cron job? [Y/n] ') : true;
58
- if (setupCron) {
59
- const groupId = isInteractive
60
- ? await promptInput('Enter your Telegram group ID (e.g., -1003731538650): ')
61
- : '';
62
- setupDoctorCron(configDir, groupId);
63
- console.log('[9/11] Doctor cron job configured');
64
- } else {
65
- console.log('[9/11] Skipped cron setup');
66
- }
103
+ ok('Workspace ready');
67
104
 
68
- // Step 10: Trigger gateway restart
69
- triggerRestart(configDir);
70
- console.log('[10/11] Gateway restart triggered');
105
+ triggerRestart();
106
+ ok('Gateway restarted');
71
107
 
72
- // Step 11: Print summary
73
- printSummary(configDir, projectsDir);
74
- console.log('[11/11] Setup complete!\n');
108
+ footer('Setup complete');
109
+
110
+ console.log(` ${c.dim}Next steps:${c.reset}`);
111
+ console.log(` ${c.dim}1.${c.reset} Open any Telegram forum topic`);
112
+ console.log(` ${c.dim}2.${c.reset} Type ${c.cyan}/topic init${c.reset}`);
113
+ console.log(` ${c.dim}3.${c.reset} The topic will be registered and a capsule created`);
114
+ console.log('');
75
115
  }
76
116
 
77
- // ── Step implementations ──────────────────────────────────────────────
117
+ // ── Uninstall ─────────────────────────────────────────────────────────
118
+
119
+ async function runUninstall(): Promise<void> {
120
+ banner(PLUGIN_NAME, 'uninstall');
121
+
122
+ const configDir = locateConfigDir();
123
+ ok(`Config ${c.dim}${configDir}${c.reset}`);
124
+
125
+ unpatchConfig(configDir);
126
+ removeFile(path.join(configDir, INCLUDE_FILENAME));
127
+ removePluginDir(configDir);
128
+ ok('Plugin files removed');
129
+
130
+ triggerRestart();
131
+ ok('Gateway restarted');
132
+
133
+ const projectsDir = path.join(configDir, 'workspace', 'projects');
134
+ if (fs.existsSync(projectsDir)) {
135
+ info('Workspace data kept: ' + projectsDir);
136
+ info('To remove: rm -rf ' + projectsDir);
137
+ }
138
+
139
+ footer('Uninstall complete');
140
+ }
141
+
142
+ // ── Setup step implementations ────────────────────────────────────────
78
143
 
79
144
  function checkOpenClawVersion(): string {
80
145
  let version: string;
81
146
  try {
82
147
  version = execSync('openclaw --version', { encoding: 'utf-8' }).trim();
83
148
  } catch {
84
- console.error(
85
- 'Error: OpenClaw not found. Please install OpenClaw (>=2026.1.0) first.',
86
- );
149
+ fail('OpenClaw not found. Install OpenClaw (>=2026.1.0) first.');
87
150
  process.exit(1);
88
151
  }
89
152
 
90
- // Extract version number (e.g., "openclaw 2026.2.0" -> "2026.2.0")
91
153
  const match = version.match(/(\d+\.\d+\.\d+)/);
92
154
  if (!match) {
93
- console.warn(`Warning: Could not parse OpenClaw version from "${version}". Proceeding anyway.`);
155
+ warn(`Could not parse version from "${version}". Proceeding anyway.`);
94
156
  return version;
95
157
  }
96
158
 
97
159
  const versionStr = match[1]!;
98
160
  if (compareVersions(versionStr, MIN_OPENCLAW_VERSION) < 0) {
99
- console.error(
100
- `Error: OpenClaw ${versionStr} found, but openclaw-telegram-manager requires >=${MIN_OPENCLAW_VERSION}. Please upgrade.`,
101
- );
161
+ fail(`OpenClaw ${versionStr} found, requires >=${MIN_OPENCLAW_VERSION}. Please upgrade.`);
102
162
  process.exit(1);
103
163
  }
104
164
 
@@ -106,20 +166,17 @@ function checkOpenClawVersion(): string {
106
166
  }
107
167
 
108
168
  function locateConfigDir(): string {
109
- // Check environment variable
110
169
  const envDir = process.env['OPENCLAW_CONFIG_DIR'];
111
170
  if (envDir && fs.existsSync(envDir)) {
112
171
  return path.resolve(envDir);
113
172
  }
114
173
 
115
- // Check default location
116
174
  const homeDir = process.env['HOME'] ?? process.env['USERPROFILE'] ?? '';
117
175
  const defaultDir = path.join(homeDir, '.openclaw');
118
176
  if (fs.existsSync(defaultDir)) {
119
177
  return defaultDir;
120
178
  }
121
179
 
122
- // Walk up from cwd looking for openclaw.json
123
180
  let dir = process.cwd();
124
181
  while (dir !== path.dirname(dir)) {
125
182
  if (fs.existsSync(path.join(dir, 'openclaw.json'))) {
@@ -128,9 +185,7 @@ function locateConfigDir(): string {
128
185
  dir = path.dirname(dir);
129
186
  }
130
187
 
131
- console.error(
132
- 'Error: Could not find OpenClaw config directory. Set $OPENCLAW_CONFIG_DIR or ensure ~/.openclaw/ exists.',
133
- );
188
+ fail('Could not find OpenClaw config directory. Set $OPENCLAW_CONFIG_DIR or ensure ~/.openclaw/ exists.');
134
189
  process.exit(1);
135
190
  }
136
191
 
@@ -140,42 +195,45 @@ function checkDirPermissions(dir: string): void {
140
195
  const mode = stat.mode;
141
196
  const permissions = (mode & 0o777).toString(8);
142
197
 
143
- // Check for world-writable or group-writable
144
198
  if (mode & 0o002) {
145
- console.warn(
146
- `Warning: ${dir} is world-writable (${permissions}). Consider restricting to owner-only (chmod 700).`,
147
- );
199
+ warn(`${dir} is world-writable (${permissions}). Consider chmod 700.`);
148
200
  } else if (mode & 0o020) {
149
- console.warn(
150
- `Warning: ${dir} is group-writable (${permissions}). Consider restricting to owner-only (chmod 700).`,
151
- );
201
+ warn(`${dir} is group-writable (${permissions}). Consider chmod 700.`);
152
202
  }
153
203
  } catch {
154
- console.warn(`Warning: Could not check permissions for ${dir}.`);
204
+ warn(`Could not check permissions for ${dir}.`);
155
205
  }
156
206
  }
157
207
 
158
- function installPlugin(): void {
159
- try {
160
- // Check if already installed
161
- const result = execSync('openclaw plugins list', { encoding: 'utf-8' });
162
- if (result.includes('openclaw-telegram-manager')) {
163
- console.log(' Plugin already installed, skipping.');
164
- return;
208
+ function installPlugin(configDir: string): void {
209
+ const extDir = path.join(configDir, 'extensions', PLUGIN_NAME);
210
+
211
+ if (fs.existsSync(path.join(extDir, 'openclaw.plugin.json'))) {
212
+ ok('Plugin already installed');
213
+ return;
214
+ }
215
+
216
+ const pkgRoot = findPackageRoot();
217
+ if (pkgRoot) {
218
+ fs.mkdirSync(extDir, { recursive: true });
219
+ for (const entry of PLUGIN_FILES) {
220
+ const src = path.join(pkgRoot, entry);
221
+ if (!fs.existsSync(src)) continue;
222
+ copyRecursive(src, path.join(extDir, entry));
165
223
  }
166
- } catch {
167
- // plugins list might not be available, try installing anyway
224
+ installDeps(extDir);
225
+ ok('Plugin installed');
226
+ return;
168
227
  }
169
228
 
170
229
  try {
171
- execSync('openclaw plugins install openclaw-telegram-manager', {
230
+ execSync(`openclaw plugins install ${PLUGIN_NAME}`, {
172
231
  encoding: 'utf-8',
173
232
  stdio: 'inherit',
174
233
  });
234
+ ok('Plugin installed');
175
235
  } catch {
176
- console.warn(
177
- ' Warning: Could not install plugin via `openclaw plugins install`. You may need to install manually.',
178
- );
236
+ warn('Could not install plugin. You may need to install manually.');
179
237
  }
180
238
  }
181
239
 
@@ -183,66 +241,52 @@ function patchConfig(configDir: string): void {
183
241
  const configPath = path.join(configDir, 'openclaw.json');
184
242
 
185
243
  if (!fs.existsSync(configPath)) {
186
- console.warn(` Warning: ${configPath} not found. Skipping config patch.`);
244
+ warn(`${configPath} not found. Skipping config patch.`);
187
245
  return;
188
246
  }
189
247
 
190
248
  let content: string;
191
249
  try {
192
250
  content = fs.readFileSync(configPath, 'utf-8');
193
- } catch (err) {
194
- console.warn(` Warning: Could not read ${configPath}. Skipping config patch.`);
251
+ } catch {
252
+ warn(`Could not read ${configPath}. Skipping config patch.`);
195
253
  return;
196
254
  }
197
255
 
198
- // Check if $include reference already exists
199
256
  if (content.includes(INCLUDE_FILENAME)) {
200
- console.log(' $include reference already present, skipping.');
257
+ ok('Config already patched');
201
258
  return;
202
259
  }
203
260
 
204
- // Parse as JSON (OpenClaw config may be JSON or JSON5)
205
261
  let config: Record<string, unknown>;
206
262
  try {
207
263
  config = JSON.parse(content) as Record<string, unknown>;
208
264
  } catch {
209
- // Try a more lenient approach: just check for the string and warn
210
- console.warn(
211
- ' Warning: Could not parse openclaw.json as JSON. Please manually add the $include reference.',
212
- );
213
- console.warn(` Add to channels.telegram.groups: { "$include": "./${INCLUDE_FILENAME}" }`);
265
+ warn('Could not parse openclaw.json. Please manually add the $include reference.');
266
+ info(`Add to channels.telegram.groups: { "$include": "./${INCLUDE_FILENAME}" }`);
214
267
  return;
215
268
  }
216
269
 
217
- // Ensure path exists: channels.telegram.groups
218
270
  if (!config['channels']) config['channels'] = {};
219
271
  const channels = config['channels'] as Record<string, unknown>;
220
272
 
221
273
  if (!channels['telegram']) channels['telegram'] = {};
222
274
  const telegram = channels['telegram'] as Record<string, unknown>;
223
275
 
224
- // Set groups to $include
225
276
  telegram['groups'] = { $include: `./${INCLUDE_FILENAME}` };
226
277
 
227
- // Backup and write
228
278
  const bakPath = configPath + '.bak';
229
279
  fs.copyFileSync(configPath, bakPath);
230
280
 
231
281
  const newContent = JSON.stringify(config, null, 2) + '\n';
232
282
  fs.writeFileSync(configPath, newContent, { mode: 0o600 });
233
- }
234
-
235
- function ensureDir(dir: string): void {
236
- if (!fs.existsSync(dir)) {
237
- fs.mkdirSync(dir, { recursive: true });
238
- }
283
+ ok('Config patched');
239
284
  }
240
285
 
241
286
  function initRegistry(projectsDir: string): void {
242
287
  const registryPath = path.join(projectsDir, REGISTRY_FILENAME);
243
288
 
244
289
  if (fs.existsSync(registryPath)) {
245
- console.log(' Registry already exists, skipping initialization.');
246
290
  return;
247
291
  }
248
292
 
@@ -265,7 +309,6 @@ function createEmptyInclude(configDir: string): void {
265
309
  const includePath = path.join(configDir, INCLUDE_FILENAME);
266
310
 
267
311
  if (fs.existsSync(includePath)) {
268
- console.log(' Include file already exists, skipping.');
269
312
  return;
270
313
  }
271
314
 
@@ -278,84 +321,84 @@ function createEmptyInclude(configDir: string): void {
278
321
  fs.writeFileSync(includePath, content, { mode: 0o600 });
279
322
  }
280
323
 
281
- function setupDoctorCron(configDir: string, groupId: string): void {
282
- const cronDir = path.join(configDir, 'cron');
283
- ensureDir(cronDir);
324
+ // ── Uninstall step implementations ────────────────────────────────────
284
325
 
285
- const cronJobPath = path.join(cronDir, 'topic-doctor-daily.json');
326
+ function unpatchConfig(configDir: string): void {
327
+ const configPath = path.join(configDir, 'openclaw.json');
328
+ const bakPath = configPath + '.bak';
286
329
 
287
- if (fs.existsSync(cronJobPath)) {
288
- console.log(' Cron job already exists, skipping.');
330
+ if (!fs.existsSync(configPath)) {
289
331
  return;
290
332
  }
291
333
 
292
- const target = groupId
293
- ? `${groupId}:topic:1`
294
- : '-100XXXXXXXXXX:topic:1';
295
-
296
- const cronJob = {
297
- name: 'topic-doctor-daily',
298
- schedule: { kind: 'cron', expr: '0 9 * * *', tz: 'UTC' },
299
- sessionTarget: 'isolated',
300
- payload: {
301
- kind: 'agentTurn',
302
- message:
303
- 'Run topic doctor health checks on all registered topics. Check the registry at projects/topics.json and evaluate each eligible topic. Post per-topic reports with inline keyboards. If any topic\'s thread returns an API error (deleted/migrated), log it and continue to the next topic.',
304
- timeoutSeconds: 300,
305
- },
306
- delivery: {
307
- mode: 'announce',
308
- channel: 'telegram',
309
- to: target,
310
- bestEffort: true,
311
- },
312
- enabled: true,
313
- deleteAfterRun: false,
314
- };
334
+ let content: string;
335
+ try {
336
+ content = fs.readFileSync(configPath, 'utf-8');
337
+ } catch {
338
+ warn(`Could not read ${configPath}.`);
339
+ return;
340
+ }
315
341
 
316
- fs.writeFileSync(cronJobPath, JSON.stringify(cronJob, null, 2) + '\n', {
317
- mode: 0o600,
318
- });
342
+ if (!content.includes(INCLUDE_FILENAME)) {
343
+ return;
344
+ }
345
+
346
+ let config: Record<string, unknown>;
347
+ try {
348
+ config = JSON.parse(content) as Record<string, unknown>;
349
+ } catch {
350
+ warn('Could not parse openclaw.json. Please manually remove the $include reference.');
351
+ return;
352
+ }
353
+
354
+ const channels = config['channels'] as Record<string, unknown> | undefined;
355
+ const telegram = channels?.['telegram'] as Record<string, unknown> | undefined;
356
+ if (telegram) {
357
+ delete telegram['groups'];
358
+ if (Object.keys(telegram).length === 0) delete channels!['telegram'];
359
+ if (Object.keys(channels!).length === 0) delete config['channels'];
360
+ }
361
+
362
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
363
+
364
+ // Clean up stale backup from install time
365
+ if (fs.existsSync(bakPath)) {
366
+ fs.unlinkSync(bakPath);
367
+ }
368
+ }
369
+
370
+ function removeFile(filePath: string): void {
371
+ if (fs.existsSync(filePath)) {
372
+ fs.unlinkSync(filePath);
373
+ }
374
+ }
319
375
 
320
- if (!groupId) {
321
- console.warn(
322
- ' Warning: No group ID provided. Edit the cron job at:',
323
- );
324
- console.warn(` ${cronJobPath}`);
325
- console.warn(' Replace -100XXXXXXXXXX with your actual group ID.');
376
+ function removePluginDir(configDir: string): void {
377
+ const extDir = path.join(configDir, 'extensions', PLUGIN_NAME);
378
+ if (fs.existsSync(extDir)) {
379
+ fs.rmSync(extDir, { recursive: true });
326
380
  }
327
381
  }
328
382
 
329
- function triggerRestart(configDir: string): void {
383
+ // ── Shared helpers ────────────────────────────────────────────────────
384
+
385
+ function triggerRestart(): void {
330
386
  try {
331
387
  execSync('openclaw gateway restart', {
332
388
  encoding: 'utf-8',
333
389
  timeout: 10_000,
334
390
  });
335
391
  } catch {
336
- console.warn(
337
- ' Warning: Could not restart gateway. Run `openclaw gateway restart` manually.',
338
- );
392
+ warn('Could not restart gateway. Run `openclaw gateway restart` manually.');
339
393
  }
340
394
  }
341
395
 
342
- function printSummary(configDir: string, projectsDir: string): void {
343
- console.log('\n================================');
344
- console.log('Setup complete!\n');
345
- console.log('What was done:');
346
- console.log(` - Config directory: ${configDir}`);
347
- console.log(` - Projects directory: ${projectsDir}`);
348
- console.log(` - Registry: ${path.join(projectsDir, REGISTRY_FILENAME)}`);
349
- console.log(` - Include: ${path.join(configDir, INCLUDE_FILENAME)}`);
350
- console.log('\nNext steps:');
351
- console.log(' 1. Go to any Telegram forum topic');
352
- console.log(' 2. Type /topic init');
353
- console.log(' 3. The topic will be registered and a capsule created');
354
- console.log('\nFor help: /topic help');
396
+ function ensureDir(dir: string): void {
397
+ if (!fs.existsSync(dir)) {
398
+ fs.mkdirSync(dir, { recursive: true });
399
+ }
355
400
  }
356
401
 
357
- // ── Helpers ───────────────────────────────────────────────────────────
358
-
359
402
  function compareVersions(a: string, b: string): number {
360
403
  const aParts = a.split('.').map(Number);
361
404
  const bParts = b.split('.').map(Number);
@@ -367,36 +410,38 @@ function compareVersions(a: string, b: string): number {
367
410
  return 0;
368
411
  }
369
412
 
370
- function promptYesNo(question: string): Promise<boolean> {
371
- return new Promise((resolve) => {
372
- const rl = readline.createInterface({
373
- input: process.stdin,
374
- output: process.stdout,
375
- });
376
- rl.question(question, (answer) => {
377
- rl.close();
378
- const normalized = answer.trim().toLowerCase();
379
- resolve(normalized === '' || normalized === 'y' || normalized === 'yes');
413
+ function installDeps(dir: string): void {
414
+ try {
415
+ execSync('npm install --production --ignore-scripts', {
416
+ cwd: dir,
417
+ encoding: 'utf-8',
418
+ stdio: 'pipe',
419
+ timeout: 60_000,
380
420
  });
381
- });
421
+ } catch {
422
+ warn('Could not install dependencies. Run `npm install --production` in ' + dir);
423
+ }
382
424
  }
383
425
 
384
- function promptInput(question: string): Promise<string> {
385
- return new Promise((resolve) => {
386
- const rl = readline.createInterface({
387
- input: process.stdin,
388
- output: process.stdout,
389
- });
390
- rl.question(question, (answer) => {
391
- rl.close();
392
- resolve(answer.trim());
393
- });
394
- });
426
+ function findPackageRoot(): string | null {
427
+ let dir = path.dirname(new URL(import.meta.url).pathname);
428
+ for (let i = 0; i < 5; i++) {
429
+ if (fs.existsSync(path.join(dir, 'openclaw.plugin.json'))) {
430
+ return dir;
431
+ }
432
+ dir = path.dirname(dir);
433
+ }
434
+ return null;
395
435
  }
396
436
 
397
- // ── Entry point ───────────────────────────────────────────────────────
398
-
399
- main().catch((err) => {
400
- console.error('Setup failed:', err instanceof Error ? err.message : String(err));
401
- process.exit(1);
402
- });
437
+ function copyRecursive(src: string, dest: string): void {
438
+ const stat = fs.statSync(src);
439
+ if (stat.isDirectory()) {
440
+ fs.mkdirSync(dest, { recursive: true });
441
+ for (const entry of fs.readdirSync(src)) {
442
+ copyRecursive(path.join(src, entry), path.join(dest, entry));
443
+ }
444
+ } else {
445
+ fs.copyFileSync(src, dest);
446
+ }
447
+ }