antenna-openclaw-plugin 1.2.23 → 1.2.25

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/index.ts CHANGED
@@ -100,9 +100,18 @@ function extractWords(profile: Partial<Profile>): string[] {
100
100
  return text.split(/[\s,,。.!!??、;;::]+/).filter((w) => w.length > 1);
101
101
  }
102
102
 
103
- function deriveDeviceId(senderId: string, channel: string): string {
103
+ function deriveDeviceId(senderId: string, channel: string, chatId?: string): string {
104
104
  const id = `${channel}:${senderId}`;
105
105
  _knownDeviceIds.add(id);
106
+ if (chatId) {
107
+ _channelContext.set(id, chatId);
108
+ // Persist to DB async
109
+ try {
110
+ const cfg = getConfig(api);
111
+ const sb = getSupabase(cfg);
112
+ sb.rpc("upsert_profile", { p_device_id: id, p_last_chat_id: chatId }).then(() => {}).catch(() => {});
113
+ } catch {}
114
+ }
106
115
  return id;
107
116
  }
108
117
 
@@ -256,14 +265,15 @@ export default function register(api: any) {
256
265
  lng: { type: "number", description: "Longitude (optional if location was shared via web)" },
257
266
  radius_m: { type: "number", description: "Search radius in meters (default 500, max 1000)" },
258
267
  sender_id: { type: "string", description: "The sender's user ID (from message context)" },
259
- channel: { type: "string", description: "The channel name (telegram, whatsapp, etc.)" },
268
+ channel: { type: "string", description: "The channel name" },
269
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
260
270
  },
261
271
  required: ["sender_id", "channel"],
262
272
  },
263
273
  async execute(_id: string, params: any) {
264
274
  const cfg = getConfig(api);
265
275
  const supabase = getSupabase(cfg);
266
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
276
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
267
277
  const radius = params.radius_m ?? cfg.defaultRadiusM ?? 500;
268
278
 
269
279
  if (isRateLimited(deviceId)) {
@@ -370,6 +380,7 @@ export default function register(api: any) {
370
380
  action: { type: "string", enum: ["get", "set"], description: "'get' to view profile, 'set' to update it" },
371
381
  sender_id: { type: "string", description: "The sender's user ID" },
372
382
  channel: { type: "string", description: "The channel name" },
383
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
373
384
  display_name: { type: "string", description: "Display name" },
374
385
  emoji: { type: "string", description: "Profile emoji" },
375
386
  line1: { type: "string", description: "First line (who you are / what you do)" },
@@ -382,7 +393,7 @@ export default function register(api: any) {
382
393
  async execute(_id: string, params: any) {
383
394
  const cfg = getConfig(api);
384
395
  const supabase = getSupabase(cfg);
385
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
396
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
386
397
 
387
398
  if (params.action === "get") {
388
399
  const { data, error } = await supabase.rpc("get_profile", { p_device_id: deviceId });
@@ -428,6 +439,7 @@ export default function register(api: any) {
428
439
  lng: { type: "number", description: "Longitude" },
429
440
  sender_id: { type: "string", description: "The sender's user ID" },
430
441
  channel: { type: "string", description: "The channel name" },
442
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
431
443
  place_name: { type: "string", description: "Optional: name of the place (for confirmation message)" },
432
444
  },
433
445
  required: ["lat", "lng", "sender_id", "channel"],
@@ -435,7 +447,7 @@ export default function register(api: any) {
435
447
  async execute(_id: string, params: any) {
436
448
  const cfg = getConfig(api);
437
449
  const supabase = getSupabase(cfg);
438
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
450
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
439
451
  const fuzzy = fuzzyCoords(params.lat, params.lng);
440
452
 
441
453
  // Check if user has a profile first
@@ -473,6 +485,7 @@ export default function register(api: any) {
473
485
  properties: {
474
486
  sender_id: { type: "string" },
475
487
  channel: { type: "string" },
488
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
476
489
  ref: { type: "string", description: "Ref number from scan results (e.g. '1')" },
477
490
  target_device_id: { type: "string", description: "Device ID (use ref instead when possible)" },
478
491
  contact_info: { type: "string", description: "Optional contact info to share" },
@@ -482,7 +495,7 @@ export default function register(api: any) {
482
495
  async execute(_id: string, params: any) {
483
496
  const cfg = getConfig(api);
484
497
  const supabase = getSupabase(cfg);
485
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
498
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
486
499
 
487
500
  // Resolve ref to device_id — try DB first, then memory fallback
488
501
  let targetId = params.target_device_id;
@@ -549,6 +562,7 @@ export default function register(api: any) {
549
562
  properties: {
550
563
  sender_id: { type: "string", description: "The sender's user ID" },
551
564
  channel: { type: "string", description: "The channel name" },
565
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
552
566
  purpose: { type: "string", description: "'profile' (default) or 'event'" },
553
567
  event_code: { type: "string", description: "Event code (required when purpose=event)" },
554
568
  },
@@ -557,7 +571,7 @@ export default function register(api: any) {
557
571
  async execute(_id: string, params: any) {
558
572
  const cfg = getConfig(api);
559
573
  const supabase = getSupabase(cfg);
560
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
574
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
561
575
 
562
576
  const { data, error } = await supabase.rpc("create_bind_token", {
563
577
  p_device_id: deviceId,
@@ -591,13 +605,14 @@ export default function register(api: any) {
591
605
  properties: {
592
606
  sender_id: { type: "string", description: "The sender's user ID" },
593
607
  channel: { type: "string", description: "The channel name" },
608
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
594
609
  },
595
610
  required: ["sender_id", "channel"],
596
611
  },
597
612
  async execute(_id: string, params: any) {
598
613
  const cfg = getConfig(api);
599
614
  const supabase = getSupabase(cfg);
600
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
615
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
601
616
 
602
617
  const { data: globalData } = await supabase.rpc("global_discover", {
603
618
  p_device_id: deviceId, p_limit: 1,
@@ -671,6 +686,7 @@ export default function register(api: any) {
671
686
  name: { type: "string", description: "Event name" },
672
687
  sender_id: { type: "string" },
673
688
  channel: { type: "string" },
689
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
674
690
  lat: { type: "number", description: "Event latitude" },
675
691
  lng: { type: "number", description: "Event longitude" },
676
692
  starts_at: { type: "string", description: "Start time ISO" },
@@ -685,7 +701,7 @@ export default function register(api: any) {
685
701
  async execute(_id: string, params: any) {
686
702
  const cfg = getConfig(api);
687
703
  const supabase = getSupabase(cfg);
688
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
704
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
689
705
  const { data, error } = await supabase.rpc("create_event", {
690
706
  p_name: params.name,
691
707
  p_lat: params.lat || null,
@@ -715,13 +731,14 @@ export default function register(api: any) {
715
731
  code: { type: "string", description: "Event code" },
716
732
  sender_id: { type: "string" },
717
733
  channel: { type: "string" },
734
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
718
735
  },
719
736
  required: ["code", "sender_id", "channel"],
720
737
  },
721
738
  async execute(_id: string, params: any) {
722
739
  const cfg = getConfig(api);
723
740
  const supabase = getSupabase(cfg);
724
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
741
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
725
742
  const { data, error } = await supabase.rpc("end_event", {
726
743
  p_code: params.code,
727
744
  p_device_id: deviceId,
@@ -743,6 +760,7 @@ export default function register(api: any) {
743
760
  code: { type: "string", description: "Event code" },
744
761
  sender_id: { type: "string" },
745
762
  channel: { type: "string" },
763
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
746
764
  lat: { type: "number", description: "Latitude (optional, for auto-checkin)" },
747
765
  lng: { type: "number", description: "Longitude (optional, for auto-checkin)" },
748
766
  application_context: { type: "string", description: "Application context from screening conversation" },
@@ -752,7 +770,7 @@ export default function register(api: any) {
752
770
  async execute(_id: string, params: any) {
753
771
  const cfg = getConfig(api);
754
772
  const supabase = getSupabase(cfg);
755
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
773
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
756
774
 
757
775
  // Profile gate
758
776
  const { data: profile } = await supabase.rpc("get_profile", { p_device_id: deviceId });
@@ -827,13 +845,14 @@ export default function register(api: any) {
827
845
  code: { type: "string", description: "Event code" },
828
846
  sender_id: { type: "string" },
829
847
  channel: { type: "string" },
848
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
830
849
  },
831
850
  required: ["code", "sender_id", "channel"],
832
851
  },
833
852
  async execute(_id: string, params: any) {
834
853
  const cfg = getConfig(api);
835
854
  const supabase = getSupabase(cfg);
836
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
855
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
837
856
 
838
857
  const { data, error } = await supabase.rpc("event_participants_list", { p_code: params.code, p_device_id: deviceId });
839
858
  if (error) return ok({ error: error.message });
@@ -864,6 +883,7 @@ export default function register(api: any) {
864
883
  properties: {
865
884
  sender_id: { type: "string", description: "The sender's user ID" },
866
885
  channel: { type: "string", description: "The channel name" },
886
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
867
887
  ref: { type: "string", description: "Ref number from scan/discover results" },
868
888
  target_device_id: { type: "string", description: "Device ID (use ref instead when possible)" },
869
889
  },
@@ -872,7 +892,7 @@ export default function register(api: any) {
872
892
  async execute(_id: string, params: any) {
873
893
  const cfg = getConfig(api);
874
894
  const supabase = getSupabase(cfg);
875
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
895
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
876
896
 
877
897
  let targetId = params.target_device_id;
878
898
  if (!targetId && params.ref) {
@@ -900,6 +920,7 @@ export default function register(api: any) {
900
920
  code: { type: "string", description: "Event code" },
901
921
  sender_id: { type: "string" },
902
922
  channel: { type: "string" },
923
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
903
924
  lat: { type: "number", description: "Latitude (optional)" },
904
925
  lng: { type: "number", description: "Longitude (optional)" },
905
926
  },
@@ -908,7 +929,7 @@ export default function register(api: any) {
908
929
  async execute(_id: string, params: any) {
909
930
  const cfg = getConfig(api);
910
931
  const supabase = getSupabase(cfg);
911
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
932
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
912
933
  const fuzzy = (params.lat != null && params.lng != null) ? fuzzyCoords(params.lat, params.lng) : { lat: null, lng: null };
913
934
  const { data, error } = await supabase.rpc("event_checkin", {
914
935
  p_code: params.code,
@@ -960,13 +981,14 @@ export default function register(api: any) {
960
981
  properties: {
961
982
  sender_id: { type: "string" },
962
983
  channel: { type: "string" },
984
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
963
985
  },
964
986
  required: ["sender_id", "channel"],
965
987
  },
966
988
  async execute(_id: string, params: any) {
967
989
  const cfg = getConfig(api);
968
990
  const supabase = getSupabase(cfg);
969
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
991
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
970
992
 
971
993
  const { data: allMatches } = await supabase.rpc("get_my_matches", { p_device_id: deviceId });
972
994
 
@@ -1042,6 +1064,7 @@ export default function register(api: any) {
1042
1064
  code: { type: "string", description: "Event code" },
1043
1065
  sender_id: { type: "string" },
1044
1066
  channel: { type: "string" },
1067
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
1045
1068
  name: { type: "string", description: "New event name" },
1046
1069
  description: { type: "string", description: "New event description" },
1047
1070
  og_image: { type: "string", description: "New OG image URL" },
@@ -1055,7 +1078,7 @@ export default function register(api: any) {
1055
1078
  async execute(_id: string, params: any) {
1056
1079
  const cfg = getConfig(api);
1057
1080
  const supabase = getSupabase(cfg);
1058
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
1081
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
1059
1082
  const { data, error } = await supabase.rpc("update_event", {
1060
1083
  p_code: params.code, p_device_id: deviceId,
1061
1084
  p_name: params.name || null, p_description: params.description || null,
@@ -1079,6 +1102,7 @@ export default function register(api: any) {
1079
1102
  code: { type: "string", description: "Event code" },
1080
1103
  sender_id: { type: "string" },
1081
1104
  channel: { type: "string" },
1105
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
1082
1106
  ref: { type: "string", description: "Ref number of the participant to approve" },
1083
1107
  },
1084
1108
  required: ["code", "sender_id", "channel", "ref"],
@@ -1086,7 +1110,7 @@ export default function register(api: any) {
1086
1110
  async execute(_id: string, params: any) {
1087
1111
  const cfg = getConfig(api);
1088
1112
  const supabase = getSupabase(cfg);
1089
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
1113
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
1090
1114
  const { data, error } = await supabase.rpc("approve_participant", {
1091
1115
  p_code: params.code, p_device_id: deviceId, p_target_ref: params.ref,
1092
1116
  });
@@ -1107,6 +1131,7 @@ export default function register(api: any) {
1107
1131
  code: { type: "string", description: "Event code" },
1108
1132
  sender_id: { type: "string" },
1109
1133
  channel: { type: "string" },
1134
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
1110
1135
  ref: { type: "string", description: "Ref number of the participant to reject" },
1111
1136
  },
1112
1137
  required: ["code", "sender_id", "channel", "ref"],
@@ -1114,7 +1139,7 @@ export default function register(api: any) {
1114
1139
  async execute(_id: string, params: any) {
1115
1140
  const cfg = getConfig(api);
1116
1141
  const supabase = getSupabase(cfg);
1117
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
1142
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
1118
1143
  const { data, error } = await supabase.rpc("reject_participant", {
1119
1144
  p_code: params.code, p_device_id: deviceId, p_target_ref: params.ref,
1120
1145
  });
@@ -1135,6 +1160,7 @@ export default function register(api: any) {
1135
1160
  code: { type: "string", description: "Event code" },
1136
1161
  sender_id: { type: "string" },
1137
1162
  channel: { type: "string" },
1163
+ chat_id: { type: "string", description: "Chat/channel ID for notifications (from message context)" },
1138
1164
  ref: { type: "string", description: "Ref number of the participant to make co-host" },
1139
1165
  },
1140
1166
  required: ["code", "sender_id", "channel", "ref"],
@@ -1142,7 +1168,7 @@ export default function register(api: any) {
1142
1168
  async execute(_id: string, params: any) {
1143
1169
  const cfg = getConfig(api);
1144
1170
  const supabase = getSupabase(cfg);
1145
- const deviceId = deriveDeviceId(params.sender_id, params.channel);
1171
+ const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
1146
1172
  const { data, error } = await supabase.rpc("add_cohost", {
1147
1173
  p_code: params.code, p_device_id: deviceId, p_target_ref: params.ref,
1148
1174
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antenna-openclaw-plugin",
3
- "version": "1.2.23",
3
+ "version": "1.2.25",
4
4
  "description": "Antenna — agent-mediated nearby people discovery for OpenClaw",
5
5
  "openclaw": {
6
6
  "extensions": ["./index.ts"]
@@ -12,6 +12,7 @@ You have access to Antenna for location-based social discovery.
12
12
  - If you have Antenna plugin tools registered (antenna_scan, antenna_profile, etc.) — use them directly.
13
13
  - If not, use CLI: `antenna <command> [flags]`. Example: `antenna scan --id telegram:123`. The CLI supports all the same features.
14
14
  - All tool names map to CLI commands: `antenna_scan` → `antenna scan`, `antenna_event_create` → `antenna event --create`, etc.
15
+ - **Always pass `chat_id`** when calling any Antenna tool. This is the chat/channel ID from your message context (e.g. Discord channel ID, Telegram chat ID). Antenna uses it to send you notifications about matches and event approvals.
15
16
 
16
17
  ## Onboarding — 装上之后主动引导
17
18
 
@@ -59,6 +60,16 @@ cron 设完后,问用户一句:
59
60
  用户说要 → cron 每天调 `antenna_discover` 推送。
60
61
  用户说不要 → 只在 scan 没人时 fallback。
61
62
 
63
+ **第六步:启动实时通知**
64
+
65
+ onboarding 完成后,启动 `antenna watch` 后台进程,实时接收匹配通知和活动审批通知:
66
+ ```
67
+ antenna watch --id <device_id> &
68
+ ```
69
+ 这会保持一个 WebSocket 连接,有新匹配或活动审批变更时立即通知。比 cron 更实时。
70
+
71
+ 如果 exec 不支持后台进程,cron 是 fallback。
72
+
62
73
  ## When to use
63
74
 
64
75
  - **首次安装后**: 主动开始 onboarding(名片 → 位置)