imtoagent 0.3.4 → 0.3.5
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 +97 -97
- package/bin/imtoagent-real +96 -96
- package/bin/imtoagent.cjs +1 -1
- package/index.ts +106 -106
- package/modules/agent/claude-adapter.ts +6 -6
- package/modules/agent/claude.ts +6 -6
- package/modules/agent/codex-adapter.ts +13 -13
- package/modules/agent/codex-exec-server.ts +11 -11
- package/modules/agent/codex.ts +29 -29
- package/modules/agent/opencode-adapter.ts +17 -17
- package/modules/agent/opencode.ts +10 -10
- package/modules/capabilities.ts +33 -33
- package/modules/cli/setup.ts +164 -164
- package/modules/core/config.ts +5 -5
- package/modules/core/error.ts +8 -8
- package/modules/core/runtime.ts +10 -10
- package/modules/core/session.ts +4 -4
- package/modules/core/stats.ts +14 -14
- package/modules/core/types.ts +7 -7
- package/modules/im/feishu.ts +56 -56
- package/modules/im/telegram.ts +23 -23
- package/modules/im/wechat.ts +54 -54
- package/modules/im/wecom.ts +50 -50
- package/modules/media/feishu-inbound-adapter.ts +4 -4
- package/modules/media/resolver.ts +11 -11
- package/modules/media/telegram-inbound-adapter.ts +8 -8
- package/modules/prompt-builder.ts +12 -12
- package/modules/proxy/anthropic-proxy.ts +31 -31
- package/modules/proxy/codex-proxy.ts +18 -18
- package/modules/utils/backend-check.ts +12 -12
- package/modules/utils/paths.ts +8 -8
- package/package.json +1 -1
- package/scripts/postinstall.cjs +10 -10
- package/scripts/postinstall.ts +13 -13
- package/templates/soul.template/identity.md +5 -5
- package/templates/soul.template/profile.md +7 -7
- package/templates/soul.template/rules.md +5 -5
- package/templates/soul.template/skills.md +2 -2
- package/templates/soul.template/workspace.md +3 -3
package/bin/imtoagent-real
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// ================================================================
|
|
3
|
-
// imtoagent CLI —
|
|
3
|
+
// imtoagent CLI — global command entry point
|
|
4
4
|
// ================================================================
|
|
5
|
-
// npm install -g imtoagent
|
|
6
|
-
// imtoagent setup —
|
|
7
|
-
// imtoagent start —
|
|
8
|
-
// imtoagent stop —
|
|
9
|
-
// imtoagent status —
|
|
10
|
-
// imtoagent restore —
|
|
11
|
-
// imtoagent daemon —
|
|
5
|
+
// Available after npm install -g imtoagent:
|
|
6
|
+
// imtoagent setup — interactive setup wizard
|
|
7
|
+
// imtoagent start — start gateway in background
|
|
8
|
+
// imtoagent stop — stop gateway
|
|
9
|
+
// imtoagent status — check running status
|
|
10
|
+
// imtoagent restore — hot reload
|
|
11
|
+
// imtoagent daemon — foreground daemon (auto-restart + logs)
|
|
12
12
|
// ================================================================
|
|
13
13
|
|
|
14
14
|
import * as fs from 'fs';
|
|
@@ -18,7 +18,7 @@ import { getDataDir } from '../modules/utils/paths';
|
|
|
18
18
|
const PID_FILE = '/tmp/imtoagent.pid';
|
|
19
19
|
|
|
20
20
|
// ================================================================
|
|
21
|
-
//
|
|
21
|
+
// Command dispatch
|
|
22
22
|
// ================================================================
|
|
23
23
|
const command = process.argv[2];
|
|
24
24
|
|
|
@@ -42,19 +42,19 @@ switch (command) {
|
|
|
42
42
|
await cmdDaemon();
|
|
43
43
|
break;
|
|
44
44
|
case undefined: {
|
|
45
|
-
//
|
|
45
|
+
// No command → auto-enter setup if not configured, show help otherwise
|
|
46
46
|
const dataDir = getDataDir();
|
|
47
47
|
const configPath = path.join(dataDir, 'config.json');
|
|
48
48
|
let needsSetup = !fs.existsSync(configPath);
|
|
49
49
|
if (!needsSetup) {
|
|
50
50
|
try {
|
|
51
51
|
const raw = fs.readFileSync(configPath, 'utf-8');
|
|
52
|
-
//
|
|
52
|
+
// If config still has YOUR_ placeholders, setup is incomplete
|
|
53
53
|
needsSetup = /YOUR_[A-Z_]+/.test(raw);
|
|
54
54
|
} catch { needsSetup = true; }
|
|
55
55
|
}
|
|
56
56
|
if (needsSetup) {
|
|
57
|
-
console.log('👋
|
|
57
|
+
console.log('👋 Welcome to imtoagent! Please run setup first.\n');
|
|
58
58
|
await cmdSetup();
|
|
59
59
|
} else {
|
|
60
60
|
printHelp();
|
|
@@ -67,7 +67,7 @@ switch (command) {
|
|
|
67
67
|
printHelp();
|
|
68
68
|
break;
|
|
69
69
|
default:
|
|
70
|
-
console.error(`❌
|
|
70
|
+
console.error(`❌ Unknown command: ${command}`);
|
|
71
71
|
printHelp();
|
|
72
72
|
process.exit(1);
|
|
73
73
|
}
|
|
@@ -77,22 +77,22 @@ switch (command) {
|
|
|
77
77
|
// ================================================================
|
|
78
78
|
function printHelp() {
|
|
79
79
|
console.log(`
|
|
80
|
-
imtoagent — IM ↔ Agent
|
|
80
|
+
imtoagent — IM ↔ Agent Unified Gateway
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
imtoagent setup
|
|
84
|
-
imtoagent start
|
|
85
|
-
imtoagent stop
|
|
86
|
-
imtoagent status
|
|
87
|
-
imtoagent restore
|
|
88
|
-
imtoagent daemon
|
|
82
|
+
Usage:
|
|
83
|
+
imtoagent setup Interactive setup wizard
|
|
84
|
+
imtoagent start Start gateway in background
|
|
85
|
+
imtoagent stop Stop gateway
|
|
86
|
+
imtoagent status Check running status
|
|
87
|
+
imtoagent restore Hot reload
|
|
88
|
+
imtoagent daemon Foreground daemon (auto-restart + logs, for launchd/systemd)
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
Data directory: ${getDataDir()}
|
|
91
91
|
`);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
// ================================================================
|
|
95
|
-
// setup —
|
|
95
|
+
// setup — interactive wizard
|
|
96
96
|
// ================================================================
|
|
97
97
|
async function cmdSetup() {
|
|
98
98
|
const { runSetupWizard } = await import('../modules/cli/setup');
|
|
@@ -100,32 +100,32 @@ async function cmdSetup() {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
// ================================================================
|
|
103
|
-
// start —
|
|
103
|
+
// start — launch in background
|
|
104
104
|
// ================================================================
|
|
105
105
|
async function cmdStart() {
|
|
106
|
-
//
|
|
106
|
+
// Check if already running
|
|
107
107
|
if (fs.existsSync(PID_FILE)) {
|
|
108
108
|
const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim());
|
|
109
109
|
try {
|
|
110
110
|
process.kill(pid, 0);
|
|
111
|
-
console.error(`❌
|
|
112
|
-
console.error(`
|
|
111
|
+
console.error(`❌ Gateway already running (PID=${pid})`);
|
|
112
|
+
console.error(` Run "imtoagent stop" to stop first`);
|
|
113
113
|
process.exit(1);
|
|
114
114
|
} catch {
|
|
115
|
-
//
|
|
115
|
+
// Stale PID file, clean up
|
|
116
116
|
fs.unlinkSync(PID_FILE);
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
//
|
|
120
|
+
// Check if config exists
|
|
121
121
|
const dataDir = getDataDir();
|
|
122
122
|
const configPath = path.join(dataDir, 'config.json');
|
|
123
123
|
if (!fs.existsSync(configPath)) {
|
|
124
|
-
console.error('❌
|
|
124
|
+
console.error('❌ No config file found. Please run "imtoagent setup" first');
|
|
125
125
|
process.exit(1);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
//
|
|
128
|
+
// Check if configured backends are installed
|
|
129
129
|
try {
|
|
130
130
|
const { checkBackend } = await import('../modules/utils/backend-check');
|
|
131
131
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
@@ -139,22 +139,22 @@ async function cmdStart() {
|
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
if (missingBackends.length > 0) {
|
|
142
|
-
console.error(`\n⚠️
|
|
142
|
+
console.error(`\n⚠️ The following backends are configured but not installed, messages will fail after gateway starts:`);
|
|
143
143
|
for (const b of missingBackends) {
|
|
144
144
|
console.error(` ❌ ${b}`);
|
|
145
145
|
}
|
|
146
|
-
console.error(`\
|
|
147
|
-
//
|
|
146
|
+
console.error(`\nPlease install the missing backends, or run "imtoagent setup" to reconfigure.\n`);
|
|
147
|
+
// Don't force exit, let user start gateway and install backends later
|
|
148
148
|
}
|
|
149
149
|
} catch {
|
|
150
|
-
//
|
|
150
|
+
// Check failure doesn't block startup
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
console.log('🚀
|
|
154
|
-
console.log(`
|
|
155
|
-
console.log(`
|
|
153
|
+
console.log('🚀 Starting imtoagent gateway...');
|
|
154
|
+
console.log(` Data directory: ${dataDir}`);
|
|
155
|
+
console.log(` Config file: ${configPath}`);
|
|
156
156
|
|
|
157
|
-
//
|
|
157
|
+
// Launch in background using Bun.spawn
|
|
158
158
|
const pkgDir = path.resolve(import.meta.dirname, '..');
|
|
159
159
|
const indexFile = path.join(pkgDir, 'index.ts');
|
|
160
160
|
|
|
@@ -166,14 +166,14 @@ async function cmdStart() {
|
|
|
166
166
|
});
|
|
167
167
|
|
|
168
168
|
fs.writeFileSync(PID_FILE, String(child.pid));
|
|
169
|
-
console.log(`✅
|
|
169
|
+
console.log(`✅ Gateway started (PID=${child.pid})`);
|
|
170
170
|
|
|
171
|
-
//
|
|
171
|
+
// Redirect background logs to logs/
|
|
172
172
|
const logsDir = path.join(dataDir, 'logs');
|
|
173
173
|
if (!fs.existsSync(logsDir)) fs.mkdirSync(logsDir, { recursive: true });
|
|
174
174
|
const logFile = path.join(logsDir, 'imtoagent.log');
|
|
175
175
|
|
|
176
|
-
//
|
|
176
|
+
// Start log collection
|
|
177
177
|
(async () => {
|
|
178
178
|
const logStream = fs.createWriteStream(logFile, { flags: 'a' });
|
|
179
179
|
for await (const chunk of child.stdout as any) {
|
|
@@ -192,13 +192,13 @@ async function cmdStart() {
|
|
|
192
192
|
}
|
|
193
193
|
})().catch(() => {});
|
|
194
194
|
|
|
195
|
-
//
|
|
195
|
+
// Wait for startup verification (check PID survives 5s)
|
|
196
196
|
await new Promise(r => setTimeout(r, 3000));
|
|
197
197
|
try {
|
|
198
198
|
process.kill(child.pid, 0);
|
|
199
|
-
console.log('✅
|
|
199
|
+
console.log('✅ Gateway is running');
|
|
200
200
|
} catch {
|
|
201
|
-
console.error('❌
|
|
201
|
+
console.error('❌ Gateway failed to start, check logs:');
|
|
202
202
|
if (fs.existsSync(logFile)) {
|
|
203
203
|
console.log(fs.readFileSync(logFile, 'utf-8').slice(-2000));
|
|
204
204
|
}
|
|
@@ -208,21 +208,21 @@ async function cmdStart() {
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
// ================================================================
|
|
211
|
-
// stop —
|
|
211
|
+
// stop — stop gateway
|
|
212
212
|
// ================================================================
|
|
213
213
|
async function cmdStop() {
|
|
214
214
|
if (!fs.existsSync(PID_FILE)) {
|
|
215
|
-
console.log('ℹ️
|
|
215
|
+
console.log('ℹ️ Gateway is not running');
|
|
216
216
|
return;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim());
|
|
220
220
|
try {
|
|
221
221
|
process.kill(pid, 0);
|
|
222
|
-
console.log(`⏹
|
|
222
|
+
console.log(`⏹ Stopping gateway (PID=${pid})...`);
|
|
223
223
|
process.kill(pid, 'SIGTERM');
|
|
224
224
|
|
|
225
|
-
//
|
|
225
|
+
// Wait for process to exit
|
|
226
226
|
for (let i = 0; i < 20; i++) {
|
|
227
227
|
try {
|
|
228
228
|
process.kill(pid, 0);
|
|
@@ -232,108 +232,108 @@ async function cmdStop() {
|
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
//
|
|
235
|
+
// Check if still running
|
|
236
236
|
try {
|
|
237
237
|
process.kill(pid, 0);
|
|
238
|
-
console.log('⚠️
|
|
238
|
+
console.log('⚠️ Process not responding, force killing...');
|
|
239
239
|
process.kill(pid, 'SIGKILL');
|
|
240
240
|
} catch {
|
|
241
|
-
console.log('✅
|
|
241
|
+
console.log('✅ Gateway stopped');
|
|
242
242
|
}
|
|
243
243
|
} catch {
|
|
244
|
-
console.log('ℹ️
|
|
244
|
+
console.log('ℹ️ Gateway not running (stale PID file cleaned up)');
|
|
245
245
|
}
|
|
246
246
|
|
|
247
247
|
try { fs.unlinkSync(PID_FILE); } catch {}
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
// ================================================================
|
|
251
|
-
// status —
|
|
251
|
+
// status — status check
|
|
252
252
|
// ================================================================
|
|
253
253
|
async function cmdStatus() {
|
|
254
254
|
const dataDir = getDataDir();
|
|
255
255
|
|
|
256
|
-
console.log(`\n📊 imtoagent
|
|
257
|
-
console.log(`
|
|
256
|
+
console.log(`\n📊 imtoagent Status`);
|
|
257
|
+
console.log(` Data directory: ${dataDir}`);
|
|
258
258
|
|
|
259
|
-
//
|
|
259
|
+
// Process status
|
|
260
260
|
if (fs.existsSync(PID_FILE)) {
|
|
261
261
|
const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim());
|
|
262
262
|
try {
|
|
263
263
|
process.kill(pid, 0);
|
|
264
|
-
console.log(`
|
|
264
|
+
console.log(` Process: ✅ Running (PID=${pid})`);
|
|
265
265
|
} catch {
|
|
266
|
-
console.log(`
|
|
266
|
+
console.log(` Process: ❌ Stopped (PID=${pid} does not exist)`);
|
|
267
267
|
}
|
|
268
268
|
} else {
|
|
269
|
-
console.log(`
|
|
269
|
+
console.log(` Process: ⏸ Not running`);
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
//
|
|
272
|
+
// Config file
|
|
273
273
|
const configPath = path.join(dataDir, 'config.json');
|
|
274
274
|
if (fs.existsSync(configPath)) {
|
|
275
275
|
try {
|
|
276
276
|
const cfg = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
277
277
|
const bots = cfg.bots || [];
|
|
278
|
-
console.log(`
|
|
278
|
+
console.log(` Config: ✅ Configured (${bots.length} Bot(s))`);
|
|
279
279
|
for (const bot of bots) {
|
|
280
280
|
console.log(` - ${bot.name} (${bot.backend})`);
|
|
281
281
|
}
|
|
282
282
|
} catch {
|
|
283
|
-
console.log(`
|
|
283
|
+
console.log(` Config: ❌ Parse error`);
|
|
284
284
|
}
|
|
285
285
|
} else {
|
|
286
|
-
console.log(`
|
|
286
|
+
console.log(` Config: ❌ Not found (run "imtoagent setup")`);
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
//
|
|
289
|
+
// Log file
|
|
290
290
|
const logFile = path.join(dataDir, 'logs', 'imtoagent.log');
|
|
291
291
|
if (fs.existsSync(logFile)) {
|
|
292
292
|
const stats = fs.statSync(logFile);
|
|
293
293
|
const size = stats.size > 1024 * 1024
|
|
294
294
|
? (stats.size / (1024 * 1024)).toFixed(1) + ' MB'
|
|
295
295
|
: (stats.size / 1024).toFixed(1) + ' KB';
|
|
296
|
-
console.log(`
|
|
296
|
+
console.log(` Log: ${size} (${logFile})`);
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
console.log();
|
|
300
300
|
}
|
|
301
301
|
|
|
302
302
|
// ================================================================
|
|
303
|
-
// restore —
|
|
303
|
+
// restore — hot reload
|
|
304
304
|
// ================================================================
|
|
305
305
|
async function cmdRestore() {
|
|
306
306
|
if (!fs.existsSync(PID_FILE)) {
|
|
307
|
-
console.error('❌
|
|
307
|
+
console.error('❌ Gateway is not running, cannot hot reload');
|
|
308
308
|
process.exit(1);
|
|
309
309
|
}
|
|
310
310
|
|
|
311
311
|
const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim());
|
|
312
|
-
console.log(`🔄
|
|
312
|
+
console.log(`🔄 Sending SIGHUP to gateway (PID=${pid})...`);
|
|
313
313
|
try {
|
|
314
314
|
process.kill(pid, 'SIGHUP');
|
|
315
|
-
console.log('✅
|
|
315
|
+
console.log('✅ Hot reload signal sent');
|
|
316
316
|
} catch (e: any) {
|
|
317
|
-
console.error(`❌
|
|
317
|
+
console.error(`❌ Failed to send: ${e.message}`);
|
|
318
318
|
process.exit(1);
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
321
|
|
|
322
322
|
// ================================================================
|
|
323
|
-
// daemon —
|
|
323
|
+
// daemon — foreground daemon mode (auto-restart + logs + graceful shutdown)
|
|
324
324
|
// ================================================================
|
|
325
|
-
//
|
|
326
|
-
// -
|
|
327
|
-
// -
|
|
328
|
-
// -
|
|
329
|
-
// -
|
|
325
|
+
// Design:
|
|
326
|
+
// - Runs in foreground, managed by launchd / systemd etc.
|
|
327
|
+
// - Auto-restarts on crash (exponential backoff, max 30s)
|
|
328
|
+
// - Graceful shutdown on SIGTERM/SIGINT, no restart
|
|
329
|
+
// - Logs written to ~/.imtoagent/logs/imtoagent.log
|
|
330
330
|
// ================================================================
|
|
331
331
|
async function cmdDaemon(): Promise<void> {
|
|
332
332
|
const dataDir = getDataDir();
|
|
333
333
|
const configPath = path.join(dataDir, 'config.json');
|
|
334
334
|
|
|
335
335
|
if (!fs.existsSync(configPath)) {
|
|
336
|
-
console.error('❌
|
|
336
|
+
console.error('❌ No config file found. Please run "imtoagent setup" first');
|
|
337
337
|
process.exit(1);
|
|
338
338
|
}
|
|
339
339
|
|
|
@@ -344,33 +344,33 @@ async function cmdDaemon(): Promise<void> {
|
|
|
344
344
|
const pkgDir = path.resolve(import.meta.dirname, '..');
|
|
345
345
|
const indexFile = path.join(pkgDir, 'index.ts');
|
|
346
346
|
|
|
347
|
-
console.log(`🛡 imtoagent
|
|
348
|
-
console.log(`
|
|
349
|
-
console.log(`
|
|
350
|
-
console.log(`
|
|
347
|
+
console.log(`🛡 imtoagent Daemon Mode`);
|
|
348
|
+
console.log(` Data directory: ${dataDir}`);
|
|
349
|
+
console.log(` Log file: ${logFile}`);
|
|
350
|
+
console.log(` Press Ctrl+C to stop\n`);
|
|
351
351
|
|
|
352
|
-
//
|
|
352
|
+
// Graceful shutdown flag
|
|
353
353
|
let shuttingDown = false;
|
|
354
354
|
|
|
355
355
|
const shutdown = () => {
|
|
356
356
|
if (shuttingDown) return;
|
|
357
357
|
shuttingDown = true;
|
|
358
|
-
console.log('\n🛑
|
|
358
|
+
console.log('\n🛑 Received stop signal, shutting down...');
|
|
359
359
|
};
|
|
360
360
|
|
|
361
361
|
process.on('SIGTERM', shutdown);
|
|
362
362
|
process.on('SIGINT', shutdown);
|
|
363
363
|
|
|
364
364
|
let retryDelay = 0;
|
|
365
|
-
const MAX_RETRY_DELAY = 30_000; // 30s
|
|
365
|
+
const MAX_RETRY_DELAY = 30_000; // 30s cap
|
|
366
366
|
|
|
367
367
|
while (!shuttingDown) {
|
|
368
|
-
//
|
|
368
|
+
// No delay on first run, exponential backoff after
|
|
369
369
|
if (retryDelay > 0) {
|
|
370
|
-
console.log(`
|
|
370
|
+
console.log(` Waiting ${retryDelay / 1000}s before restart...`);
|
|
371
371
|
await new Promise<void>(resolve => {
|
|
372
372
|
const timer = setTimeout(resolve, retryDelay);
|
|
373
|
-
//
|
|
373
|
+
// Exit immediately if shutdown signal received during wait
|
|
374
374
|
const check = setInterval(() => {
|
|
375
375
|
if (shuttingDown) {
|
|
376
376
|
clearTimeout(timer);
|
|
@@ -393,9 +393,9 @@ async function cmdDaemon(): Promise<void> {
|
|
|
393
393
|
|
|
394
394
|
const childPid = child.pid;
|
|
395
395
|
fs.writeFileSync(PID_FILE, String(childPid));
|
|
396
|
-
console.log(`[${new Date().toISOString()}] 🚀
|
|
396
|
+
console.log(`[${new Date().toISOString()}] 🚀 Starting gateway (PID=${childPid})`);
|
|
397
397
|
|
|
398
|
-
//
|
|
398
|
+
// Log collection
|
|
399
399
|
const pumpStdout = (async () => {
|
|
400
400
|
for await (const chunk of child.stdout as any) {
|
|
401
401
|
const line = new TextDecoder().decode(chunk);
|
|
@@ -412,7 +412,7 @@ async function cmdDaemon(): Promise<void> {
|
|
|
412
412
|
}
|
|
413
413
|
})().catch(() => {});
|
|
414
414
|
|
|
415
|
-
//
|
|
415
|
+
// Wait for child process to exit
|
|
416
416
|
const exitCode = await child.exited;
|
|
417
417
|
await Promise.allSettled([pumpStdout, pumpStderr]);
|
|
418
418
|
logStream.end();
|
|
@@ -421,17 +421,17 @@ async function cmdDaemon(): Promise<void> {
|
|
|
421
421
|
|
|
422
422
|
if (shuttingDown) break;
|
|
423
423
|
|
|
424
|
-
//
|
|
424
|
+
// Determine if restart needed
|
|
425
425
|
if (exitCode === 0) {
|
|
426
|
-
console.log(`[${new Date().toISOString()}] ⏹
|
|
426
|
+
console.log(`[${new Date().toISOString()}] ⏹ Gateway exited cleanly (code=0), not restarting`);
|
|
427
427
|
break;
|
|
428
428
|
}
|
|
429
429
|
|
|
430
|
-
//
|
|
430
|
+
// Crash → exponential backoff restart
|
|
431
431
|
retryDelay = retryDelay === 0 ? 3_000 : Math.min(retryDelay * 2, MAX_RETRY_DELAY);
|
|
432
|
-
console.log(`[${new Date().toISOString()}] ⚠️
|
|
432
|
+
console.log(`[${new Date().toISOString()}] ⚠️ Gateway crashed (code=${exitCode}), restarting in ${retryDelay / 1000}s`);
|
|
433
433
|
}
|
|
434
434
|
|
|
435
|
-
console.log('👋
|
|
435
|
+
console.log('👋 Daemon stopped');
|
|
436
436
|
}
|
|
437
437
|
|
package/bin/imtoagent.cjs
CHANGED
|
@@ -25,7 +25,7 @@ for (var i = 0; i < candidates.length; i++) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
if (!bunPath) {
|
|
28
|
-
console.error("❌ bun
|
|
28
|
+
console.error("❌ bun not found, please install: https://bun.sh");
|
|
29
29
|
console.error(" curl -fsSL https://bun.sh/install | bash");
|
|
30
30
|
process.exit(1);
|
|
31
31
|
}
|