antenna-openclaw-plugin 1.3.22 → 1.3.24
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 +87 -0
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -722,6 +722,93 @@ export default function register(api: any) {
|
|
|
722
722
|
},
|
|
723
723
|
});
|
|
724
724
|
|
|
725
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
726
|
+
// Tool: antenna_initial_recommendations
|
|
727
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
728
|
+
api.registerTool({
|
|
729
|
+
name: "antenna_initial_recommendations",
|
|
730
|
+
description:
|
|
731
|
+
"Get initial recommendations for a new user — 2-3 people most similar to them. One-time only, does NOT consume daily discover quota. Use right after profile creation in onboarding.",
|
|
732
|
+
parameters: {
|
|
733
|
+
type: "object",
|
|
734
|
+
properties: {
|
|
735
|
+
sender_id: { type: "string", description: "The sender's user ID" },
|
|
736
|
+
channel: { type: "string", description: "The channel name" },
|
|
737
|
+
chat_id: { type: "string", description: "REQUIRED for notifications. Pass the chat/channel ID from your message context so Antenna can send you match and event notifications." },
|
|
738
|
+
},
|
|
739
|
+
required: ["sender_id", "channel", "chat_id"],
|
|
740
|
+
},
|
|
741
|
+
async execute(_id: string, params: any) {
|
|
742
|
+
const cfg = getConfig(api);
|
|
743
|
+
const supabase = getSupabase(cfg);
|
|
744
|
+
const deviceId = deriveDeviceId(params.sender_id, params.channel, params.chat_id);
|
|
745
|
+
|
|
746
|
+
const { data: results, error } = await supabase.rpc("initial_recommendations", {
|
|
747
|
+
p_device_id: deviceId,
|
|
748
|
+
p_limit: 3,
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
if (error) return ok({ error: error.message });
|
|
752
|
+
|
|
753
|
+
if (!results || results.length === 0) {
|
|
754
|
+
return ok({
|
|
755
|
+
count: 0,
|
|
756
|
+
profiles: [],
|
|
757
|
+
initial: true,
|
|
758
|
+
message: "暂时没有推荐,等有更多人加入!",
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
const _refMap: Record<string, string> = {};
|
|
763
|
+
|
|
764
|
+
// Get my profile for match reason generation
|
|
765
|
+
const { data: myProfile } = await supabase.rpc("get_profile", { p_device_id: deviceId });
|
|
766
|
+
const myLines = myProfile ? [myProfile.line1, myProfile.line2, myProfile.line3].filter(Boolean).join(". ") : "";
|
|
767
|
+
|
|
768
|
+
const profiles = [];
|
|
769
|
+
for (let i = 0; i < results.length; i++) {
|
|
770
|
+
const p = results[i] as any;
|
|
771
|
+
const ref = String(i + 1);
|
|
772
|
+
_refMap[ref] = p.device_id;
|
|
773
|
+
|
|
774
|
+
const theirLines = [p.line1, p.line2, p.line3].filter(Boolean).join(". ");
|
|
775
|
+
let match_reason: string | null = null;
|
|
776
|
+
|
|
777
|
+
if (myLines && theirLines) {
|
|
778
|
+
try {
|
|
779
|
+
const supabaseUrl = cfg.supabaseUrl || BUILTIN_SUPABASE_URL;
|
|
780
|
+
const supabaseKey = cfg.supabaseKey || BUILTIN_SUPABASE_ANON_KEY;
|
|
781
|
+
const res = await fetch(`${supabaseUrl}/functions/v1/generate-match-reason`, {
|
|
782
|
+
method: "POST",
|
|
783
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${supabaseKey}` },
|
|
784
|
+
body: JSON.stringify({ my_lines: myLines, their_lines: theirLines }),
|
|
785
|
+
});
|
|
786
|
+
if (res.ok) {
|
|
787
|
+
const data = await res.json();
|
|
788
|
+
match_reason = data?.reason || null;
|
|
789
|
+
}
|
|
790
|
+
} catch { /* best effort */ }
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
profiles.push({ ref, emoji: p.emoji || "👤", name: p.display_name || "匿名", personal_description: p.line1, looking_for: p.line2, conversation_style: p.line3, more_information: p.matching_context || null, profile_slug: p.profile_slug || null, match_reason });
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
// Persist refs + log recommendations
|
|
797
|
+
(api as any)._antennaRefMap = { ...(api as any)._antennaRefMap, ..._refMap };
|
|
798
|
+
try {
|
|
799
|
+
await supabase.rpc("save_scan_refs", { p_owner: deviceId, p_refs: _refMap });
|
|
800
|
+
} catch { /* best effort */ }
|
|
801
|
+
for (const p of results) {
|
|
802
|
+
await supabase.rpc("log_recommendation", { p_device_id: deviceId, p_recommended_id: (p as any).device_id });
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
return ok({
|
|
806
|
+
count: profiles.length, profiles, initial: true,
|
|
807
|
+
message: "这是你的首次推荐——基于你的名片,这几个人跟你最匹配。",
|
|
808
|
+
});
|
|
809
|
+
},
|
|
810
|
+
});
|
|
811
|
+
|
|
725
812
|
// ═══════════════════════════════════════════════════════════════════
|
|
726
813
|
// Tool: antenna_event_create
|
|
727
814
|
// ═══════════════════════════════════════════════════════════════════
|