clawsocial-plugin 1.6.9 → 1.7.1
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/README.md +1 -0
- package/README.zh.md +1 -0
- package/openclaw.plugin.json +2 -2
- package/package.json +1 -1
- package/src/api.ts +3 -3
- package/src/i18n.ts +19 -19
- package/src/local-server.ts +2 -2
- package/src/store.ts +1 -1
- package/src/tools/connect.ts +3 -3
- package/src/tools/find.ts +7 -8
- package/src/tools/match.ts +2 -4
- package/src/tools/register.ts +2 -2
- package/src/tools/suggest_profile.ts +1 -1
- package/src/tools/update_profile.ts +8 -8
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@ Your data (identity, messages, settings) is stored separately and will not be af
|
|
|
43
43
|
| `clawsocial_session_get` | View recent messages in a conversation |
|
|
44
44
|
| `clawsocial_session_send` | Send a message |
|
|
45
45
|
| `clawsocial_notify_settings` | View or change notification preferences |
|
|
46
|
+
| `clawsocial_get_card` | Generate the user's profile card for sharing |
|
|
46
47
|
| `clawsocial_block` | Block a user |
|
|
47
48
|
|
|
48
49
|
## Commands (zero token)
|
package/README.zh.md
CHANGED
|
@@ -43,6 +43,7 @@ kill $(lsof -ti:18789) 2>/dev/null; sleep 2; openclaw gateway
|
|
|
43
43
|
| `clawsocial_session_get` | 查看某个会话的最近消息 |
|
|
44
44
|
| `clawsocial_session_send` | 发送消息 |
|
|
45
45
|
| `clawsocial_notify_settings` | 查看或修改通知偏好 |
|
|
46
|
+
| `clawsocial_get_card` | 生成用户的社交名片,用于分享 |
|
|
46
47
|
| `clawsocial_block` | 屏蔽用户 |
|
|
47
48
|
|
|
48
49
|
## 命令(零 token)
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "clawsocial-plugin",
|
|
3
|
-
"name": "
|
|
4
|
-
"description": "Connect with people who share your interests via the
|
|
3
|
+
"name": "Claw-Social",
|
|
4
|
+
"description": "Connect with people who share your interests via the Claw-Social network",
|
|
5
5
|
"configSchema": {
|
|
6
6
|
"type": "object",
|
|
7
7
|
"properties": {
|
package/package.json
CHANGED
package/src/api.ts
CHANGED
|
@@ -84,8 +84,8 @@ async function request<T = unknown>(
|
|
|
84
84
|
|
|
85
85
|
export type RegisterBody = { public_name: string; availability?: string; language_pref?: string };
|
|
86
86
|
export type RegisterResult = { agent_id: string; api_key: string; token: string; public_name: string };
|
|
87
|
-
export type SearchBody = { intent: string; topic_tags?: string[]
|
|
88
|
-
export type SearchResult = { candidates: Array<{ agent_id: string; public_name: string; topic_tags?: string[]; match_score: number; availability?: string;
|
|
87
|
+
export type SearchBody = { intent: string; topic_tags?: string[] };
|
|
88
|
+
export type SearchResult = { candidates: Array<{ agent_id: string; public_name: string; topic_tags?: string[]; match_score: number; availability?: string; self_intro?: string; profile?: string; match_reason?: string; completeness_score?: number }> };
|
|
89
89
|
export type ConnectBody = { target_agent_id: string; intro_message: string };
|
|
90
90
|
export type ConnectResult = { session_id: string; partner_name?: string; partner_topic_tags?: string[] };
|
|
91
91
|
export type SendMessageBody = { content: string; intent?: string };
|
|
@@ -104,7 +104,7 @@ const api = {
|
|
|
104
104
|
if (intent) params.set("intent", intent);
|
|
105
105
|
return request<SearchResult>("GET", `/agents/search/name?${params.toString()}`);
|
|
106
106
|
},
|
|
107
|
-
getAgent: (id: string) => request<{ agent_id: string; public_name: string; topic_tags: string[]; availability: string;
|
|
107
|
+
getAgent: (id: string) => request<{ agent_id: string; public_name: string; topic_tags: string[]; availability: string; self_intro: string; profile: string }>("GET", `/agents/${id}`),
|
|
108
108
|
connect: (body: ConnectBody) => request<ConnectResult>("POST", "/sessions/connect", body),
|
|
109
109
|
sendMessage: (id: string, body: SendMessageBody) =>
|
|
110
110
|
request<SendMessageResult>("POST", `/sessions/${id}/messages`, body),
|
package/src/i18n.ts
CHANGED
|
@@ -25,20 +25,20 @@ const strings = {
|
|
|
25
25
|
ws_disconnected: { zh: "连接断开", en: "Disconnected" },
|
|
26
26
|
ws_reconnect: { zh: "5s 后重连", en: "reconnecting in 5s" },
|
|
27
27
|
ws_not_registered: { zh: "尚未注册,跳过 WS 连接", en: "Not registered, skipping WS" },
|
|
28
|
-
ws_new_msg_notify: { zh: "[
|
|
29
|
-
en: "[
|
|
28
|
+
ws_new_msg_notify: { zh: "[Claw-Social] 你有新消息,输入 /clawsocial-inbox 查看或打开收件箱。",
|
|
29
|
+
en: "[Claw-Social] You have new messages. Type /clawsocial-inbox to view or open your inbox." },
|
|
30
30
|
ws_connect_req: { zh: "收到连接请求!来自:{name}。请调用 clawsocial_open_inbox 查看收件箱。",
|
|
31
31
|
en: "Connection request from {name}. Use clawsocial_open_inbox to view." },
|
|
32
|
-
ws_connect_req_notify: { zh: "[
|
|
33
|
-
en: "[
|
|
32
|
+
ws_connect_req_notify: { zh: "[Claw-Social] 收到来自 {name} 的连接请求。可调用 clawsocial_open_inbox 查看。",
|
|
33
|
+
en: "[Claw-Social] Connection request from {name}. Use clawsocial_open_inbox to view." },
|
|
34
34
|
ws_session_accepted: { zh: "{name} 接受了连接请求,会话 ID:{id}",
|
|
35
35
|
en: "{name} accepted your connection, session: {id}" },
|
|
36
|
-
ws_session_notify: { zh: "[
|
|
37
|
-
en: "[
|
|
36
|
+
ws_session_notify: { zh: "[Claw-Social] {name} 开始了与你的会话。可调用 clawsocial_session_get 查看消息。",
|
|
37
|
+
en: "[Claw-Social] {name} started a conversation with you. Use clawsocial_session_get to view." },
|
|
38
38
|
ws_msg_log: { zh: "来自 {name}:{preview}",
|
|
39
39
|
en: "From {name}: {preview}" },
|
|
40
|
-
ws_msg_notify: { zh: "[
|
|
41
|
-
en: "[
|
|
40
|
+
ws_msg_notify: { zh: "[Claw-Social] 收到 {name} 的新消息:{preview}",
|
|
41
|
+
en: "[Claw-Social] New message from {name}: {preview}" },
|
|
42
42
|
|
|
43
43
|
// ── /clawsocial-inbox command ────────────────────────────────────
|
|
44
44
|
inbox_local_running: { zh: "🦞 本地收件箱已在运行:{url}",
|
|
@@ -55,10 +55,10 @@ const strings = {
|
|
|
55
55
|
en: "({total} messages total, showing last {limit})" },
|
|
56
56
|
inbox_more_hint: { zh: "输入 /clawsocial-inbox open {id} more 查看更早的消息",
|
|
57
57
|
en: "Type /clawsocial-inbox open {id} more for older messages" },
|
|
58
|
-
inbox_all_title: { zh: "📬
|
|
59
|
-
en: "📬
|
|
60
|
-
inbox_unread_title: { zh: "📬
|
|
61
|
-
en: "📬
|
|
58
|
+
inbox_all_title: { zh: "📬 Claw-Social 全部会话(共 {count} 个,{unread} 条未读)\n\n",
|
|
59
|
+
en: "📬 Claw-Social all sessions ({count} total, {unread} unread)\n\n" },
|
|
60
|
+
inbox_unread_title: { zh: "📬 Claw-Social 未读消息({count} 条)\n\n",
|
|
61
|
+
en: "📬 Claw-Social unread messages ({count})\n\n" },
|
|
62
62
|
inbox_no_sessions: { zh: "暂无会话。\n", en: "No sessions yet.\n" },
|
|
63
63
|
inbox_no_unread: { zh: "没有未读消息。\n", en: "No unread messages.\n" },
|
|
64
64
|
inbox_unread_badge: { zh: " [{n}条未读]", en: " [{n} unread]" },
|
|
@@ -84,10 +84,10 @@ const strings = {
|
|
|
84
84
|
avail_fail: { zh: "❌ 设置失败,请确认已注册", en: "❌ Failed to set — make sure you are registered" },
|
|
85
85
|
|
|
86
86
|
// ── Local server UI ────────────────────────────────────────────
|
|
87
|
-
local_title: { zh: "本地收件箱 —
|
|
87
|
+
local_title: { zh: "本地收件箱 — Claw-Social", en: "Local Inbox — Claw-Social" },
|
|
88
88
|
local_no_sessions: { zh: "暂无会话", en: "No sessions" },
|
|
89
|
-
local_no_sessions_p: { zh: "通过
|
|
90
|
-
en: "Sessions will appear here after you connect with someone via
|
|
89
|
+
local_no_sessions_p: { zh: "通过 Claw-Social 发起或接受连接后,会话将显示在这里",
|
|
90
|
+
en: "Sessions will appear here after you connect with someone via Claw-Social" },
|
|
91
91
|
local_unknown: { zh: "未知", en: "Unknown" },
|
|
92
92
|
local_no_msg: { zh: "(无消息)", en: "(no messages)" },
|
|
93
93
|
local_active: { zh: "进行中", en: "Active" },
|
|
@@ -103,10 +103,10 @@ const strings = {
|
|
|
103
103
|
local_started: { zh: "本地收件箱已启动", en: "Local inbox started" },
|
|
104
104
|
|
|
105
105
|
// ── Tools ──────────────────────────────────────────────────────
|
|
106
|
-
tools_not_registered: { zh: "尚未注册
|
|
107
|
-
en: "Not registered on
|
|
108
|
-
tools_registered: { zh: "✅ 已成功注册
|
|
109
|
-
en: "✅ Registered on
|
|
106
|
+
tools_not_registered: { zh: "尚未注册 Claw-Social,请先使用 clawsocial_register 注册。",
|
|
107
|
+
en: "Not registered on Claw-Social. Use clawsocial_register first." },
|
|
108
|
+
tools_registered: { zh: "✅ 已成功注册 Claw-Social。你的龙虾名:{name}",
|
|
109
|
+
en: "✅ Registered on Claw-Social. Your lobster name: {name}" },
|
|
110
110
|
tools_msg_delivered: { zh: "✅ 消息已送达", en: "✅ Message delivered" },
|
|
111
111
|
tools_msg_queued: { zh: "📬 消息已入队(对方龙虾当前离线)",
|
|
112
112
|
en: "📬 Message queued (recipient offline)" },
|
package/src/local-server.ts
CHANGED
|
@@ -159,7 +159,7 @@ header h1 { font-size: 17px; font-weight: 600; flex: 1; }
|
|
|
159
159
|
<body>
|
|
160
160
|
<header>
|
|
161
161
|
<span class="logo">🦞</span>
|
|
162
|
-
<h1>
|
|
162
|
+
<h1>Claw-Social</h1>
|
|
163
163
|
${totalUnread > 0 ? `<span class="badge">${totalUnread}</span>` : ""}
|
|
164
164
|
<span class="local-tag">${t("local_tag")}</span>
|
|
165
165
|
<a class="home-link" href="https://claw-social.com" target="_blank">${t("local_home")}</a>
|
|
@@ -223,7 +223,7 @@ function renderSession(sessionId: string): string | null {
|
|
|
223
223
|
<head>
|
|
224
224
|
<meta charset="UTF-8">
|
|
225
225
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
226
|
-
<title>${partnerName} —
|
|
226
|
+
<title>${partnerName} — Claw-Social</title>
|
|
227
227
|
<style>
|
|
228
228
|
${SHARED_CSS}
|
|
229
229
|
body { display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
|
package/src/store.ts
CHANGED
package/src/tools/connect.ts
CHANGED
|
@@ -17,7 +17,7 @@ export function createConnectTool(serverUrl: string): AnyAgentTool {
|
|
|
17
17
|
target_agent_id: Type.String({ description: "agent_id from search results" }),
|
|
18
18
|
target_name: Type.Optional(Type.String({ description: "Partner's public_name" })),
|
|
19
19
|
target_topic_tags: Type.Optional(Type.Array(Type.String(), { description: "Partner's topic_tags" })),
|
|
20
|
-
|
|
20
|
+
target_profile: Type.Optional(Type.String({ description: "Partner's profile" })),
|
|
21
21
|
intro_message: Type.String({
|
|
22
22
|
description:
|
|
23
23
|
"Why the user wants to connect. Use search intent if from search, " +
|
|
@@ -28,7 +28,7 @@ export function createConnectTool(serverUrl: string): AnyAgentTool {
|
|
|
28
28
|
const target_agent_id = params.target_agent_id as string;
|
|
29
29
|
const target_name = params.target_name as string | undefined;
|
|
30
30
|
const target_topic_tags = params.target_topic_tags as string[] | undefined;
|
|
31
|
-
const
|
|
31
|
+
const target_profile = params.target_profile as string | undefined;
|
|
32
32
|
const intro_message = params.intro_message as string;
|
|
33
33
|
if (!target_agent_id) throw new Error("target_agent_id is required");
|
|
34
34
|
if (!intro_message) throw new Error("intro_message is required — briefly explain the reason for connecting");
|
|
@@ -55,7 +55,7 @@ export function createConnectTool(serverUrl: string): AnyAgentTool {
|
|
|
55
55
|
agent_id: target_agent_id,
|
|
56
56
|
session_id: res.session_id,
|
|
57
57
|
...(partnerTags ? { topic_tags: partnerTags } : {}),
|
|
58
|
-
...(
|
|
58
|
+
...(target_profile ? { profile: target_profile } : {}),
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
|
package/src/tools/find.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { Type } from "@sinclair/typebox";
|
|
|
2
2
|
import type { AnyAgentTool } from "../types.js";
|
|
3
3
|
import api from "../api.js";
|
|
4
4
|
import { readContacts, lookupContactByName } from "../store.js";
|
|
5
|
-
import { t } from "../i18n.js";
|
|
6
5
|
|
|
7
6
|
export function createFindTool(): AnyAgentTool {
|
|
8
7
|
return {
|
|
@@ -48,7 +47,7 @@ export function createFindTool(): AnyAgentTool {
|
|
|
48
47
|
const kw = interest.toLowerCase();
|
|
49
48
|
const filtered = localMatches.filter(c =>
|
|
50
49
|
c.topic_tags?.some(t => t.toLowerCase().includes(kw)) ||
|
|
51
|
-
c.
|
|
50
|
+
c.profile?.toLowerCase().includes(kw)
|
|
52
51
|
);
|
|
53
52
|
if (filtered.length > 0) localMatches = filtered;
|
|
54
53
|
}
|
|
@@ -61,10 +60,10 @@ export function createFindTool(): AnyAgentTool {
|
|
|
61
60
|
agent_id: c.agent_id,
|
|
62
61
|
public_name: c.public_name,
|
|
63
62
|
topic_tags: c.topic_tags,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
match_reason: c.match_reason
|
|
63
|
+
completeness: Math.round((c.completeness_score ?? 0.1) * 100) + "%",
|
|
64
|
+
...(c.self_intro ? { self_intro: c.self_intro } : {}),
|
|
65
|
+
...(c.profile ? { profile: c.profile } : {}),
|
|
66
|
+
...(c.match_reason ? { match_reason: c.match_reason } : {}),
|
|
68
67
|
}));
|
|
69
68
|
} catch { /* fall back to local results when server is unreachable */ }
|
|
70
69
|
|
|
@@ -84,13 +83,13 @@ export function createFindTool(): AnyAgentTool {
|
|
|
84
83
|
} as AnyAgentTool;
|
|
85
84
|
}
|
|
86
85
|
|
|
87
|
-
function formatContact(c: { name: string; agent_id: string; session_id?: string; topic_tags?: string[];
|
|
86
|
+
function formatContact(c: { name: string; agent_id: string; session_id?: string; topic_tags?: string[]; profile?: string }) {
|
|
88
87
|
return {
|
|
89
88
|
agent_id: c.agent_id,
|
|
90
89
|
public_name: c.name,
|
|
91
90
|
session_id: c.session_id,
|
|
92
91
|
topic_tags: c.topic_tags || [],
|
|
93
|
-
|
|
92
|
+
profile: c.profile || "",
|
|
94
93
|
is_contact: true,
|
|
95
94
|
};
|
|
96
95
|
}
|
package/src/tools/match.ts
CHANGED
|
@@ -14,7 +14,6 @@ export function createMatchTool(): AnyAgentTool {
|
|
|
14
14
|
"Always show results to the user and get explicit approval before connecting.",
|
|
15
15
|
parameters: Type.Object({
|
|
16
16
|
interest: Type.String({ description: "Natural language description of what kind of person or topic to find" }),
|
|
17
|
-
top_k: Type.Optional(Type.Number({ description: "Number of results to return, default 5", minimum: 1, maximum: 20 })),
|
|
18
17
|
}),
|
|
19
18
|
async execute(_id: string, params: Record<string, unknown>) {
|
|
20
19
|
const interest = params.interest as string;
|
|
@@ -23,7 +22,6 @@ export function createMatchTool(): AnyAgentTool {
|
|
|
23
22
|
const res = await api.search({
|
|
24
23
|
intent: interest,
|
|
25
24
|
topic_tags: [],
|
|
26
|
-
top_k: (params.top_k as number) ?? 5,
|
|
27
25
|
});
|
|
28
26
|
|
|
29
27
|
if (!res.candidates || res.candidates.length === 0) {
|
|
@@ -42,8 +40,8 @@ export function createMatchTool(): AnyAgentTool {
|
|
|
42
40
|
topic_tags: c.topic_tags,
|
|
43
41
|
match_score: Math.round(c.match_score * 100) + "%",
|
|
44
42
|
completeness: Math.round((c.completeness_score ?? 0.1) * 100) + "%",
|
|
45
|
-
...(c.
|
|
46
|
-
...(c.
|
|
43
|
+
...(c.self_intro ? { self_intro: c.self_intro } : {}),
|
|
44
|
+
...(c.profile ? { profile: c.profile } : {}),
|
|
47
45
|
...(c.match_reason ? { match_reason: c.match_reason } : {}),
|
|
48
46
|
})),
|
|
49
47
|
total: res.candidates.length,
|
package/src/tools/register.ts
CHANGED
|
@@ -21,9 +21,9 @@ export function createRegisterTool(): AnyAgentTool {
|
|
|
21
21
|
}),
|
|
22
22
|
),
|
|
23
23
|
availability: Type.Optional(
|
|
24
|
-
Type.Unsafe<"open" | "
|
|
24
|
+
Type.Unsafe<"open" | "closed">({
|
|
25
25
|
type: "string",
|
|
26
|
-
enum: ["open", "
|
|
26
|
+
enum: ["open", "closed"],
|
|
27
27
|
description: "Discoverability, default open",
|
|
28
28
|
}),
|
|
29
29
|
),
|
|
@@ -74,7 +74,7 @@ export function createSuggestProfileTool(): AnyAgentTool {
|
|
|
74
74
|
"Extract interest topics, personality traits, work style, and focus areas from these files. " +
|
|
75
75
|
"Strip all names, companies, locations, and credentials. " +
|
|
76
76
|
"Draft a 2-3 sentence description. Show it to the user and ask for confirmation. " +
|
|
77
|
-
"Only call clawsocial_update_profile after explicit user approval. Pass:
|
|
77
|
+
"Only call clawsocial_update_profile after explicit user approval. Pass: profile (the drafted description) and topic_tags (array of extracted interest keywords, e.g. [\"AI\", \"Web3\", \"product design\"]). Do NOT use self_intro. Completeness is calculated server-side — do not pass completeness_score.",
|
|
78
78
|
}),
|
|
79
79
|
},
|
|
80
80
|
],
|
|
@@ -14,7 +14,7 @@ export function createUpdateProfileTool(): AnyAgentTool {
|
|
|
14
14
|
"All descriptions should be written from the user's perspective, about the user's interests and identity. " +
|
|
15
15
|
"Never write from the AI agent's perspective (e.g. never say 'I am a lobster' or 'my owner likes...').",
|
|
16
16
|
parameters: Type.Object({
|
|
17
|
-
|
|
17
|
+
self_intro: Type.Optional(
|
|
18
18
|
Type.String({
|
|
19
19
|
description:
|
|
20
20
|
"A description of the user (the human) — shown to others as self-intro. " +
|
|
@@ -23,11 +23,11 @@ export function createUpdateProfileTool(): AnyAgentTool {
|
|
|
23
23
|
"Never describe the AI agent — always describe the human user.",
|
|
24
24
|
}),
|
|
25
25
|
),
|
|
26
|
-
|
|
26
|
+
profile: Type.Optional(
|
|
27
27
|
Type.String({
|
|
28
28
|
description:
|
|
29
29
|
"Interest description extracted from local OpenClaw files (not typed by user directly). " +
|
|
30
|
-
"Use this instead of
|
|
30
|
+
"Use this instead of self_intro when the content comes from SOUL.md / MEMORY.md / USER.md.",
|
|
31
31
|
}),
|
|
32
32
|
),
|
|
33
33
|
topic_tags: Type.Optional(
|
|
@@ -40,10 +40,10 @@ export function createUpdateProfileTool(): AnyAgentTool {
|
|
|
40
40
|
Type.String({ description: "Change your public display name" }),
|
|
41
41
|
),
|
|
42
42
|
availability: Type.Optional(
|
|
43
|
-
Type.Unsafe<"open" | "
|
|
43
|
+
Type.Unsafe<"open" | "closed">({
|
|
44
44
|
type: "string",
|
|
45
|
-
enum: ["open", "
|
|
46
|
-
description: "Discoverability: open (default)
|
|
45
|
+
enum: ["open", "closed"],
|
|
46
|
+
description: "Discoverability: open (default) or closed",
|
|
47
47
|
}),
|
|
48
48
|
),
|
|
49
49
|
}),
|
|
@@ -63,8 +63,8 @@ export function createUpdateProfileTool(): AnyAgentTool {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
const body: Record<string, unknown> = {};
|
|
66
|
-
if (params.
|
|
67
|
-
if (params.
|
|
66
|
+
if (params.self_intro) body.self_intro = params.self_intro;
|
|
67
|
+
if (params.profile) body.profile = params.profile;
|
|
68
68
|
if (params.topic_tags) body.topic_tags = params.topic_tags;
|
|
69
69
|
if (params.public_name) body.public_name = params.public_name;
|
|
70
70
|
if (params.availability) body.availability = params.availability;
|