@team-semicolon/semo-cli 4.4.2 → 4.4.3

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.
@@ -50,6 +50,7 @@ const chalk_1 = __importDefault(require("chalk"));
50
50
  const ora_1 = __importDefault(require("ora"));
51
51
  const fs = __importStar(require("fs"));
52
52
  const path = __importStar(require("path"));
53
+ const os = __importStar(require("os"));
53
54
  const database_1 = require("../database");
54
55
  const sessions_1 = require("./sessions");
55
56
  const audit_1 = require("./audit");
@@ -140,6 +141,27 @@ function getAllFileMtimes(dir, depth = 0) {
140
141
  return times;
141
142
  }
142
143
  // ============================================================
144
+ // Gateway status detection
145
+ // ============================================================
146
+ async function detectGatewayStatus(botId) {
147
+ const configPath = path.join(os.homedir(), `.openclaw-${botId}`, 'openclaw.json');
148
+ if (!fs.existsSync(configPath))
149
+ return 'offline';
150
+ try {
151
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
152
+ const port = config?.gateway?.port;
153
+ if (!port)
154
+ return 'offline';
155
+ const res = await fetch(`http://127.0.0.1:${port}/`, {
156
+ signal: AbortSignal.timeout(1000),
157
+ });
158
+ return res.ok ? 'online' : 'offline';
159
+ }
160
+ catch {
161
+ return 'offline';
162
+ }
163
+ }
164
+ // ============================================================
143
165
  // Command registration
144
166
  // ============================================================
145
167
  function registerBotsCommands(program) {
@@ -324,16 +346,28 @@ function registerBotsCommands(program) {
324
346
  const errors = [];
325
347
  try {
326
348
  await client.query("BEGIN");
349
+ // Detect gateway status for all bots in parallel
350
+ const statusMap = new Map();
351
+ const statusResults = await Promise.all(bots.map(async (bot) => ({
352
+ botId: bot.botId,
353
+ status: await detectGatewayStatus(bot.botId),
354
+ })));
355
+ for (const { botId, status } of statusResults) {
356
+ statusMap.set(botId, status);
357
+ }
358
+ const onlineCount = statusResults.filter(r => r.status === 'online').length;
359
+ spinner.text = `${bots.length}개 봇 DB 반영 중... (게이트웨이: ${onlineCount}개 online)`;
327
360
  for (const bot of bots) {
328
361
  try {
362
+ const detectedStatus = statusMap.get(bot.botId) || 'offline';
329
363
  await client.query(`INSERT INTO semo.bot_status
330
364
  (bot_id, name, emoji, role, status, last_active, workspace_path, synced_at)
331
- VALUES ($1, $2, $3, $4, 'offline', $5, $6, NOW())
365
+ VALUES ($1, $2, $3, $4, $7, $5, $6, NOW())
332
366
  ON CONFLICT (bot_id) DO UPDATE SET
333
367
  name = COALESCE(EXCLUDED.name, semo.bot_status.name),
334
368
  emoji = COALESCE(EXCLUDED.emoji, semo.bot_status.emoji),
335
369
  role = COALESCE(EXCLUDED.role, semo.bot_status.role),
336
- status = semo.bot_status.status,
370
+ status = EXCLUDED.status,
337
371
  last_active = CASE
338
372
  WHEN EXCLUDED.last_active IS NOT NULL
339
373
  AND (semo.bot_status.last_active IS NULL
@@ -349,6 +383,7 @@ function registerBotsCommands(program) {
349
383
  bot.role,
350
384
  bot.lastActive?.toISOString() || null,
351
385
  bot.workspacePath,
386
+ detectedStatus,
352
387
  ]);
353
388
  upserted++;
354
389
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-semicolon/semo-cli",
3
- "version": "4.4.2",
3
+ "version": "4.4.3",
4
4
  "description": "SEMO CLI - AI Agent Orchestration Framework Installer",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -9,6 +9,7 @@
9
9
  },
10
10
  "scripts": {
11
11
  "build": "tsc",
12
+ "postbuild": "xattr -cr dist/ 2>/dev/null || true",
12
13
  "start": "node dist/index.js",
13
14
  "dev": "ts-node src/index.ts"
14
15
  },