antenna-fyi 1.2.25 → 1.2.27
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/lib/cli.js +59 -17
- package/lib/hermes-plugin/schemas.py +9 -9
- package/package.json +1 -1
- package/skill/SKILL.md +2 -0
package/lib/cli.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import { scan, getProfile, setProfile, accept, checkMatches, checkin, createBindToken, discover, createEvent, endEvent, eventCheckin, joinEvent, eventScan, pass as passUser, uploadEventImage, updateEvent, approveParticipant, rejectParticipant, addCohost, getClient } from "./core.js";
|
|
4
4
|
import { createInterface } from "readline";
|
|
5
|
-
import { existsSync, mkdirSync, copyFileSync, readFileSync } from "fs";
|
|
5
|
+
import { existsSync, mkdirSync, copyFileSync, readFileSync, writeFileSync, unlinkSync } from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import os from "os";
|
|
6
8
|
import { join, dirname, extname } from "path";
|
|
7
9
|
import { fileURLToPath } from "url";
|
|
8
10
|
import { homedir } from "os";
|
|
@@ -334,9 +336,21 @@ export async function handleSetup(f) {
|
|
|
334
336
|
|
|
335
337
|
export async function handleStatus(f) {
|
|
336
338
|
const supabaseUrl = process.env.ANTENNA_SUPABASE_URL || process.env.ANTENNA_URL || "https://bcudjloikmpcqwcptuyd.supabase.co";
|
|
337
|
-
console.log("📡 Antenna Status\n");
|
|
339
|
+
console.log("\n📡 Antenna Status\n");
|
|
338
340
|
console.log(` Supabase URL: ${supabaseUrl}`);
|
|
339
341
|
|
|
342
|
+
// Check watch process
|
|
343
|
+
const pidFile = path.join(os.homedir(), '.antenna', 'watch.pid');
|
|
344
|
+
try {
|
|
345
|
+
if (existsSync(pidFile)) {
|
|
346
|
+
const pid = parseInt(readFileSync(pidFile, 'utf8').trim());
|
|
347
|
+
try { process.kill(pid, 0); console.log(` Watch: ✅ running (PID ${pid})`); }
|
|
348
|
+
catch { console.log(' Watch: ❌ stale PID file (process dead)'); }
|
|
349
|
+
} else {
|
|
350
|
+
console.log(' Watch: ❌ not running');
|
|
351
|
+
}
|
|
352
|
+
} catch { console.log(' Watch: ❌ not running'); }
|
|
353
|
+
|
|
340
354
|
if (f.id) {
|
|
341
355
|
const profile = await getProfile({ device_id: f.id });
|
|
342
356
|
if (profile) {
|
|
@@ -466,6 +480,17 @@ export async function handleWatch(f) {
|
|
|
466
480
|
process.exit(1);
|
|
467
481
|
}
|
|
468
482
|
|
|
483
|
+
// Write PID file for health check
|
|
484
|
+
const pidDir = path.join(os.homedir(), '.antenna');
|
|
485
|
+
const pidFile = path.join(pidDir, 'watch.pid');
|
|
486
|
+
try {
|
|
487
|
+
if (!existsSync(pidDir)) mkdirSync(pidDir, { recursive: true });
|
|
488
|
+
writeFileSync(pidFile, String(process.pid));
|
|
489
|
+
} catch {}
|
|
490
|
+
process.on('exit', () => { try { unlinkSync(pidFile); } catch {} });
|
|
491
|
+
process.on('SIGINT', () => { try { unlinkSync(pidFile); } catch {} process.exit(0); });
|
|
492
|
+
process.on('SIGTERM', () => { try { unlinkSync(pidFile); } catch {} process.exit(0); });
|
|
493
|
+
|
|
469
494
|
const sb = getClient();
|
|
470
495
|
const notified = new Set();
|
|
471
496
|
|
|
@@ -490,19 +515,36 @@ export async function handleWatch(f) {
|
|
|
490
515
|
} catch { /* hermes not installed */ }
|
|
491
516
|
}
|
|
492
517
|
|
|
493
|
-
|
|
518
|
+
// Force stdout blocking mode for non-TTY environments (Hermes exec)
|
|
519
|
+
try { if (process.stdout._handle) process.stdout._handle.setBlocking(true); } catch {}
|
|
520
|
+
|
|
521
|
+
// Log to file as fallback
|
|
522
|
+
const logDir = path.join(os.homedir(), '.antenna');
|
|
523
|
+
const logFile = path.join(logDir, 'watch.log');
|
|
524
|
+
try { if (!existsSync(logDir)) mkdirSync(logDir, { recursive: true }); } catch {}
|
|
525
|
+
const logStream = await import('fs').then(fs => fs.createWriteStream(logFile, { flags: 'a' }));
|
|
526
|
+
const _log = (msg) => {
|
|
527
|
+
const line = `[${new Date().toISOString()}] ${msg}`;
|
|
528
|
+
console.log(msg);
|
|
529
|
+
try { logStream.write(line + '\n'); } catch {}
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
_log(`📡 Watching for new matches for ${id}...`);
|
|
494
533
|
if (pushMethod === "openclaw") {
|
|
495
|
-
|
|
534
|
+
_log(` 🔗 Detected OpenClaw — will push notifications to your channel.`);
|
|
496
535
|
} else if (pushMethod === "hermes") {
|
|
497
|
-
|
|
536
|
+
_log(` 🔗 Detected Hermes — will push notifications to your channel.`);
|
|
498
537
|
} else {
|
|
499
|
-
|
|
538
|
+
_log(` ℹ️ No agent framework detected — notifications will print here.`);
|
|
500
539
|
}
|
|
501
|
-
|
|
540
|
+
_log(` Press Ctrl+C to stop.\n`);
|
|
541
|
+
|
|
542
|
+
// Keep process alive (prevent exit when backgrounded)
|
|
543
|
+
process.stdin.resume();
|
|
502
544
|
|
|
503
545
|
// Push notification helper
|
|
504
546
|
async function pushNotify(message) {
|
|
505
|
-
|
|
547
|
+
_log(message); // always print to terminal
|
|
506
548
|
|
|
507
549
|
if (pushMethod === "openclaw") {
|
|
508
550
|
try {
|
|
@@ -536,22 +578,22 @@ export async function handleWatch(f) {
|
|
|
536
578
|
// Initial check
|
|
537
579
|
const initial = await checkMatches({ device_id: id });
|
|
538
580
|
if (initial.mutual_matches?.length) {
|
|
539
|
-
|
|
581
|
+
_log(`🎉 You have ${initial.mutual_matches.length} mutual match(es)!`);
|
|
540
582
|
for (const m of initial.mutual_matches) {
|
|
541
583
|
const key = `mutual:${m.device_id}`;
|
|
542
584
|
notified.add(key);
|
|
543
|
-
|
|
585
|
+
_log(` ${m.emoji || "👤"} ${m.name}${m.their_contact ? " — contact: " + m.their_contact : ""}`);
|
|
544
586
|
}
|
|
545
|
-
|
|
587
|
+
_log();
|
|
546
588
|
}
|
|
547
589
|
if (initial.incoming_accepts?.length) {
|
|
548
|
-
|
|
590
|
+
_log(`📩 ${initial.incoming_accepts.length} person(s) want to meet you!`);
|
|
549
591
|
for (const m of initial.incoming_accepts) {
|
|
550
592
|
const key = `incoming:${m.device_id}`;
|
|
551
593
|
notified.add(key);
|
|
552
|
-
|
|
594
|
+
_log(` ${m.emoji || "👤"} ${m.name} — ${m.line1 || ""}`);
|
|
553
595
|
}
|
|
554
|
-
|
|
596
|
+
_log();
|
|
555
597
|
}
|
|
556
598
|
|
|
557
599
|
// Subscribe to realtime changes on matches table
|
|
@@ -607,9 +649,9 @@ export async function handleWatch(f) {
|
|
|
607
649
|
)
|
|
608
650
|
.subscribe((status) => {
|
|
609
651
|
if (status === "SUBSCRIBED") {
|
|
610
|
-
|
|
652
|
+
_log("✅ Connected — listening for matches in real-time.");
|
|
611
653
|
} else if (status === "CHANNEL_ERROR" || status === "TIMED_OUT") {
|
|
612
|
-
|
|
654
|
+
_log(`⚠️ Connection issue (${status}), retrying...`);
|
|
613
655
|
}
|
|
614
656
|
});
|
|
615
657
|
|
|
@@ -653,7 +695,7 @@ export async function handleWatch(f) {
|
|
|
653
695
|
)
|
|
654
696
|
.subscribe((status) => {
|
|
655
697
|
if (status === "SUBSCRIBED") {
|
|
656
|
-
|
|
698
|
+
_log("✅ Connected — listening for event notifications.");
|
|
657
699
|
}
|
|
658
700
|
});
|
|
659
701
|
|
|
@@ -44,7 +44,7 @@ PROFILE_SCHEMA = {
|
|
|
44
44
|
},
|
|
45
45
|
"sender_id": {"type": "string"},
|
|
46
46
|
"channel": {"type": "string"},
|
|
47
|
-
"chat_id": {"type": "string", "description": "
|
|
47
|
+
"chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."},
|
|
48
48
|
"display_name": {"type": "string", "description": "Display name"},
|
|
49
49
|
"emoji": {"type": "string", "description": "Profile emoji"},
|
|
50
50
|
"line1": {"type": "string", "description": "Who you are / what you do"},
|
|
@@ -67,7 +67,7 @@ ACCEPT_SCHEMA = {
|
|
|
67
67
|
"properties": {
|
|
68
68
|
"sender_id": {"type": "string"},
|
|
69
69
|
"channel": {"type": "string"},
|
|
70
|
-
"chat_id": {"type": "string", "description": "
|
|
70
|
+
"chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."},
|
|
71
71
|
"ref": {
|
|
72
72
|
"type": "string",
|
|
73
73
|
"description": "Ref number from scan results (e.g. '1')",
|
|
@@ -97,7 +97,7 @@ CHECKIN_SCHEMA = {
|
|
|
97
97
|
"lng": {"type": "number", "description": "Longitude"},
|
|
98
98
|
"sender_id": {"type": "string"},
|
|
99
99
|
"channel": {"type": "string"},
|
|
100
|
-
"chat_id": {"type": "string", "description": "
|
|
100
|
+
"chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."},
|
|
101
101
|
"place_name": {
|
|
102
102
|
"type": "string",
|
|
103
103
|
"description": "Name of the place (optional)",
|
|
@@ -117,7 +117,7 @@ CHECK_MATCHES_SCHEMA = {
|
|
|
117
117
|
"properties": {
|
|
118
118
|
"sender_id": {"type": "string"},
|
|
119
119
|
"channel": {"type": "string"},
|
|
120
|
-
"chat_id": {"type": "string", "description": "
|
|
120
|
+
"chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."},
|
|
121
121
|
},
|
|
122
122
|
"required": ["sender_id", "channel"],
|
|
123
123
|
},
|
|
@@ -133,7 +133,7 @@ BIND_SCHEMA = {
|
|
|
133
133
|
"properties": {
|
|
134
134
|
"sender_id": {"type": "string"},
|
|
135
135
|
"channel": {"type": "string"},
|
|
136
|
-
"chat_id": {"type": "string", "description": "
|
|
136
|
+
"chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."},
|
|
137
137
|
"purpose": {"type": "string", "description": "'profile' (default) or 'event'"},
|
|
138
138
|
"event_code": {"type": "string", "description": "Event code (when purpose=event)"},
|
|
139
139
|
},
|
|
@@ -287,7 +287,7 @@ EVENT_UPDATE_SCHEMA = {
|
|
|
287
287
|
"code": {"type": "string"},
|
|
288
288
|
"sender_id": {"type": "string"},
|
|
289
289
|
"channel": {"type": "string"},
|
|
290
|
-
"chat_id": {"type": "string", "description": "
|
|
290
|
+
"chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."},
|
|
291
291
|
"name": {"type": "string"},
|
|
292
292
|
"description": {"type": "string"},
|
|
293
293
|
"og_image": {"type": "string"},
|
|
@@ -309,7 +309,7 @@ EVENT_APPROVE_SCHEMA = {
|
|
|
309
309
|
"code": {"type": "string"},
|
|
310
310
|
"sender_id": {"type": "string"},
|
|
311
311
|
"channel": {"type": "string"},
|
|
312
|
-
"chat_id": {"type": "string", "description": "
|
|
312
|
+
"chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."},
|
|
313
313
|
"ref": {"type": "string"},
|
|
314
314
|
},
|
|
315
315
|
"required": ["code", "sender_id", "channel", "ref"],
|
|
@@ -325,7 +325,7 @@ EVENT_REJECT_SCHEMA = {
|
|
|
325
325
|
"code": {"type": "string"},
|
|
326
326
|
"sender_id": {"type": "string"},
|
|
327
327
|
"channel": {"type": "string"},
|
|
328
|
-
"chat_id": {"type": "string", "description": "
|
|
328
|
+
"chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."},
|
|
329
329
|
"ref": {"type": "string"},
|
|
330
330
|
},
|
|
331
331
|
"required": ["code", "sender_id", "channel", "ref"],
|
|
@@ -341,7 +341,7 @@ EVENT_ADD_HOST_SCHEMA = {
|
|
|
341
341
|
"code": {"type": "string"},
|
|
342
342
|
"sender_id": {"type": "string"},
|
|
343
343
|
"channel": {"type": "string"},
|
|
344
|
-
"chat_id": {"type": "string", "description": "
|
|
344
|
+
"chat_id": {"type": "string", "description": "REQUIRED for notifications. Pass chat/channel ID from message context."},
|
|
345
345
|
"ref": {"type": "string"},
|
|
346
346
|
},
|
|
347
347
|
"required": ["code", "sender_id", "channel", "ref"],
|
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -68,6 +68,8 @@ antenna watch --id <device_id> &
|
|
|
68
68
|
```
|
|
69
69
|
这会保持一个 WebSocket 连接,有新匹配或活动审批变更时立即通知。比 cron 更实时。
|
|
70
70
|
|
|
71
|
+
**Health check:** 每次对话开始时,跑 `antenna status --id <device_id>` 检查 watch 是否在跑。如果显示 "Watch: ❌ not running",重新启动 `antenna watch --id <device_id> &`。
|
|
72
|
+
|
|
71
73
|
如果 exec 不支持后台进程,cron 是 fallback。
|
|
72
74
|
|
|
73
75
|
## When to use
|