antenna-fyi 1.2.19 → 1.2.21

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  // antenna CLI command handlers
2
2
 
3
- import { scan, getProfile, setProfile, accept, checkMatches, checkin, createBindToken, discover, createEvent, endEvent, eventCheckin, joinEvent, eventScan, pass as passUser, uploadEventImage, getClient } from "./core.js";
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
5
  import { existsSync, mkdirSync, copyFileSync, readFileSync } from "fs";
6
6
  import { join, dirname, extname } from "path";
@@ -177,7 +177,7 @@ export async function handleEvent(f) {
177
177
  return;
178
178
  }
179
179
 
180
- if (f.create || (!f.join && !f.scan && !f.end && f.name)) {
180
+ if (f.create || (!f.join && !f.scan && !f.end && !f.update && !f.approve && !f.reject && !f['add-host'] && f.name)) {
181
181
  if (!f.name) return console.error("Usage: antenna event --create --name 'AI Meetup' [--desc 'description'] [--og-image 'url'] [--requires-approval] [--screening-questions 'Q1|Q2']");
182
182
  const result = await createEvent({ name: f.name, device_id: f.id || null, lat: f.lat ? +f.lat : undefined, lng: f.lng ? +f.lng : undefined, description: f.desc || undefined, og_image: f['og-image'] || undefined, requires_approval: f['requires-approval'] === true || f['requires-approval'] === 'true' || undefined, screening_questions: f['screening-questions'] ? f['screening-questions'].split('|') : undefined });
183
183
  console.log(`\n🎉 Event created!\n`);
@@ -192,9 +192,18 @@ export async function handleEvent(f) {
192
192
  if (!f.code || !f.id) return console.error("Usage: antenna event --join --code abc123 --id telegram:123");
193
193
  const result = await joinEvent({ code: f.code, device_id: f.id, lat: f.lat ? +f.lat : undefined, lng: f.lng ? +f.lng : undefined, application_context: f['application-context'] || undefined });
194
194
  if (result.joined) {
195
- console.log(`\n✅ Joined "${result.name}" (${result.code})\n`);
195
+ if (result.status === 'pending') {
196
+ console.log(`\n🟡 申请已提交,等待主办方审批\n`);
197
+ } else {
198
+ console.log(`\n✅ Joined "${result.event}"\n`);
199
+ if (result.checked_in) console.log(` 自动签到 ✅\n`);
200
+ }
201
+ } else if (result.needs_screening) {
202
+ console.log(`\n📝 这个活动需要审批。请回答以下问题:`);
203
+ (result.screening_questions || []).forEach((q, i) => console.log(` ${i + 1}. ${q}`));
204
+ console.log(`\n回答后用 --application-context '你的回答' 重新 join\n`);
196
205
  } else {
197
- console.log(`\n❌ ${result.error}\n`);
206
+ console.log(`\n❌ ${result.error || result.message}\n`);
198
207
  }
199
208
  return;
200
209
  }
@@ -216,6 +225,50 @@ export async function handleEvent(f) {
216
225
  return;
217
226
  }
218
227
 
228
+ if (f.approve) {
229
+ if (!f.code || !f.id || !f.ref) return console.error("Usage: antenna event --approve --code abc123 --id telegram:123 --ref 1");
230
+ const result = await approveParticipant({ code: f.code, device_id: f.id, ref: f.ref });
231
+ if (result.approved) {
232
+ console.log("\n✅ Participant approved\n");
233
+ } else {
234
+ console.log(`\n❌ ${result.error}\n`);
235
+ }
236
+ return;
237
+ }
238
+
239
+ if (f.reject) {
240
+ if (!f.code || !f.id || !f.ref) return console.error("Usage: antenna event --reject --code abc123 --id telegram:123 --ref 1");
241
+ const result = await rejectParticipant({ code: f.code, device_id: f.id, ref: f.ref });
242
+ if (result.rejected) {
243
+ console.log("\n✅ Participant rejected\n");
244
+ } else {
245
+ console.log(`\n❌ ${result.error}\n`);
246
+ }
247
+ return;
248
+ }
249
+
250
+ if (f.update) {
251
+ if (!f.code || !f.id) return console.error("Usage: antenna event --update --code abc123 --id telegram:123 [--name 'New Name'] [--desc 'New desc']");
252
+ const result = await updateEvent({ code: f.code, device_id: f.id, name: f.name, description: f.desc, og_image: f['og-image'], lat: f.lat ? +f.lat : undefined, lng: f.lng ? +f.lng : undefined, starts_at: f['starts-at'], ends_at: f['ends-at'] });
253
+ if (result.updated) {
254
+ console.log("\n✅ Event updated\n");
255
+ } else {
256
+ console.log(`\n❌ ${result.error}\n`);
257
+ }
258
+ return;
259
+ }
260
+
261
+ if (f['add-host']) {
262
+ if (!f.code || !f.id || !f.ref) return console.error("Usage: antenna event --add-host --code abc123 --id telegram:123 --ref 1");
263
+ const result = await addCohost({ code: f.code, device_id: f.id, ref: f.ref });
264
+ if (result.added) {
265
+ console.log("\n✅ Co-host added\n");
266
+ } else {
267
+ console.log(`\n❌ ${result.error}\n`);
268
+ }
269
+ return;
270
+ }
271
+
219
272
  console.log(`Usage:
220
273
  antenna event --create --name 'AI Meetup' [--id telegram:123] [--desc 'description'] [--og-image 'url'] [--requires-approval] [--screening-questions 'Q1|Q2']
221
274
  antenna event --join --code abc123 --id telegram:123
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antenna-fyi",
3
- "version": "1.2.19",
3
+ "version": "1.2.21",
4
4
  "description": "Antenna — nearby people discovery. CLI + MCP server + OpenClaw skill & plugin, all in one package.",
5
5
  "type": "module",
6
6
  "bin": {
package/skill/EVENTS.md CHANGED
@@ -82,11 +82,17 @@ Generate a GPS link for setting event location.
82
82
  ## Agent Behavior
83
83
 
84
84
  ### When someone says "create an event"
85
- 1. Ask for event name (required) and description (optional)
86
- 2. **Ask if participants need approval** ("Do you want to review and approve participants before they join?"). If yes, ask what screening questions to include.
87
- 3. Call `antenna_event_create` with `requires_approval` and `screening_questions` if applicable
88
- 4. If no GPS provided, call `antenna_bind(purpose="event", event_code=CODE)` and send the link
89
- 5. Share the event URL with the user
85
+ Collect the following info through conversation (ask one by one, don't dump all at once):
86
+ 1. **Event name** (required) "活动叫什么名字?"
87
+ 2. **Description** "简单描述一下这个活动?"
88
+ 3. **Time** "什么时候开始?大概多长?" (convert to starts_at / ends_at ISO strings)
89
+ 4. **Location** "活动在哪里?" If user gives an address, geocode it. If vague, generate a bind link after creation.
90
+ 5. **Approval** — "需要审批参与者吗?" If yes:
91
+ 6. **Screening questions** — "你想问报名者什么问题?" Collect as a list.
92
+
93
+ Then call `antenna_event_create` with all collected info.
94
+ If no GPS, call `antenna_bind(purpose="event", event_code=CODE)` and send the link.
95
+ Share the event URL with the user.
90
96
 
91
97
  ### When someone shares an event link
92
98
  1. Extract the code from `antenna.fyi/events/CODE`
package/skill/SKILL.md CHANGED
@@ -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