antenna-openclaw-plugin 1.2.20 → 1.2.22

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
@@ -124,24 +124,35 @@ function cronJobId(deviceA: string, deviceB: string): string {
124
124
  }
125
125
 
126
126
  /** Send a real-time notification to a user via openclaw message send */
127
- function notifyUser(
127
+ async function notifyUser(
128
128
  channel: string,
129
129
  userId: string,
130
130
  message: string,
131
131
  logger: any,
132
- ): void {
132
+ ): Promise<void> {
133
133
  const deviceId = `${channel}:${userId}`;
134
- const chatId = _channelContext.get(deviceId);
134
+ let chatId = _channelContext.get(deviceId);
135
+
136
+ // Fallback: read from DB if not in memory
137
+ if (!chatId) {
138
+ try {
139
+ const cfg = getConfig(api);
140
+ const sb = getSupabase(cfg);
141
+ const { data } = await sb.rpc("get_profile", { p_device_id: deviceId });
142
+ if (data?.last_chat_id) {
143
+ chatId = data.last_chat_id;
144
+ _channelContext.set(deviceId, chatId);
145
+ }
146
+ } catch {}
147
+ }
135
148
 
136
149
  try {
137
150
  if (chatId) {
138
- // Use message send with known chat context
139
151
  execSync(
140
152
  `openclaw message send --channel ${channel} --target ${chatId} -m ${JSON.stringify(message)}`,
141
153
  { timeout: 30_000, encoding: "utf-8" },
142
154
  );
143
155
  } else {
144
- // Fallback: try deliver
145
156
  execSync(
146
157
  `openclaw agent` +
147
158
  ` --message ${JSON.stringify(message)}` +
@@ -156,6 +167,12 @@ function notifyUser(
156
167
  logger.warn(`Antenna: notify failed for ${channel}:${userId}: ${err.message}`);
157
168
  }
158
169
  }
170
+ }
171
+ logger.info(`Antenna: notified ${channel}:${userId} (chat=${chatId || 'deliver'})`);
172
+ } catch (err: any) {
173
+ logger.warn(`Antenna: notify failed for ${channel}:${userId}: ${err.message}`);
174
+ }
175
+ }
159
176
 
160
177
  function startFollowUpCron(
161
178
  deviceId: string,
@@ -1412,6 +1429,12 @@ export default function register(api: any) {
1412
1429
  const deviceId = `${ch}:${senderId}`;
1413
1430
  _channelContext.set(deviceId, chatId);
1414
1431
  _knownDeviceIds.add(deviceId);
1432
+ // Persist to DB
1433
+ try {
1434
+ const cfg = getConfig(api);
1435
+ const sb = getSupabase(cfg);
1436
+ sb.rpc("upsert_profile", { p_device_id: deviceId, p_last_chat_id: chatId }).then(() => {}).catch(() => {});
1437
+ } catch {}
1415
1438
  }
1416
1439
 
1417
1440
  // --- Auto-scan on location ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antenna-openclaw-plugin",
3
- "version": "1.2.20",
3
+ "version": "1.2.22",
4
4
  "description": "Antenna — agent-mediated nearby people discovery for OpenClaw",
5
5
  "openclaw": {
6
6
  "extensions": ["./index.ts"]
@@ -365,3 +365,41 @@ Add a co-host to the event. Only creator can add.
365
365
  - `code`: event code
366
366
  - `sender_id`, `channel`: from context
367
367
  - `ref`: participant ref number to promote to co-host
368
+
369
+ ---
370
+
371
+ ## Part 2: Event Behavior Guide
372
+
373
+ ### Creating an event
374
+ Collect info through conversation (ask one by one, don't dump all at once):
375
+ 1. **Event name** (required) — "活动叫什么名字?"
376
+ 2. **Description** — "简单描述一下这个活动?"
377
+ 3. **Time** — "什么时候开始?大概多长?" (convert to starts_at / ends_at ISO strings)
378
+ 4. **Location** — "活动在哪里?" If user gives an address, geocode it. If vague, generate a bind link after creation.
379
+ 5. **Approval** — "需要审批参与者吗?" If yes:
380
+ 6. **Screening questions** — "你想问报名者什么问题?" Collect as a list.
381
+
382
+ Then call `antenna_event_create` with all collected info.
383
+ If no GPS, call `antenna_bind(purpose="event", event_code=CODE)` and send the link.
384
+ Share the event URL with the user.
385
+
386
+ ### Joining an event
387
+ 1. Extract the code from `antenna.fyi/events/CODE`
388
+ 2. Call `antenna_event_join(code)` — this checks everything:
389
+ - If no profile → "Create a profile first"
390
+ - If event requires approval and no `application_context` provided → returns `needs_screening: true` + `screening_questions`
391
+ - If screening questions returned: **ask the user each question**, collect answers, then call `antenna_event_join(code, application_context="answers")` again
392
+ - If `status: pending` → "waiting for organizer approval"
393
+ - If `status: active` → user is in! Auto check-in if event started + GPS within 1km.
394
+
395
+ ### Scanning an event
396
+ 1. Call `antenna_event_scan(code)`
397
+ 2. Hosts see pending participants with `application_context` (screening answers)
398
+ 3. Recommend who to meet based on user's interests
399
+ 4. Creator/co-host appears with organizer badge
400
+
401
+ ### Approving/rejecting participants
402
+ Only creator or co-host can approve/reject:
403
+ - `antenna_event_approve(code, ref)` → participant becomes active
404
+ - `antenna_event_reject(code, ref)` → participant is rejected
405
+ - Notifications are sent automatically to the applicant