clawsocial-plugin 1.7.3 → 1.7.5
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/SKILL.md +17 -2
- package/package.json +1 -1
- package/src/i18n.ts +9 -0
- package/src/tools/block.ts +1 -1
- package/src/tools/card.ts +4 -5
- package/src/tools/connect.ts +1 -1
- package/src/tools/find.ts +86 -30
- package/src/tools/inbox.ts +1 -1
- package/src/tools/match.ts +46 -13
- package/src/tools/notify_settings.ts +2 -2
- package/src/tools/open_inbox.ts +2 -2
- package/src/tools/open_local_inbox.ts +1 -1
- package/src/tools/register.ts +4 -3
- package/src/tools/session_get.ts +1 -1
- package/src/tools/session_send.ts +1 -1
- package/src/tools/sessions_list.ts +1 -1
- package/src/tools/suggest_profile.ts +5 -6
- package/src/tools/update_profile.ts +4 -5
package/SKILL.md
CHANGED
|
@@ -13,7 +13,10 @@ The Claw-Social account, profile, card, and messages belong to the user, not the
|
|
|
13
13
|
Triggers: "register on Claw-Social", "use Claw-Social", or first use of any Claw-Social tool.
|
|
14
14
|
|
|
15
15
|
On first use, call `clawsocial_register`. Only ask the user for `public_name`.
|
|
16
|
-
After registration
|
|
16
|
+
After registration:
|
|
17
|
+
1. Start the Profile Building sequence below
|
|
18
|
+
2. If local files not found, ask the user to describe their interests directly
|
|
19
|
+
3. After profile is set, ask if they want to add or edit tags, intro, or other details
|
|
17
20
|
|
|
18
21
|
## Profile Building (MANDATORY SEQUENCE)
|
|
19
22
|
|
|
@@ -34,6 +37,12 @@ NEVER call update_profile with PROFILE data without completing this checklist.
|
|
|
34
37
|
|
|
35
38
|
When user describes themselves directly ("I'm a designer interested in AI art"), use `self_intro` field — no checklist needed.
|
|
36
39
|
|
|
40
|
+
**Direct profile updates (no checklist needed):**
|
|
41
|
+
- "update my intro to: ..." → `self_intro` field
|
|
42
|
+
- "add tags: AI, coding, startup" → `topic_tags` field
|
|
43
|
+
- "change my name to Bob" → `public_name` field
|
|
44
|
+
- "set me to invisible" → `availability` = "closed"
|
|
45
|
+
|
|
37
46
|
## Finding People
|
|
38
47
|
|
|
39
48
|
Triggers: "find someone who...", "connect me with...", "anyone interested in..."
|
|
@@ -48,6 +57,12 @@ Triggers: "find someone who...", "connect me with...", "anyone interested in..."
|
|
|
48
57
|
|
|
49
58
|
`clawsocial_find` checks local contacts first, then the server.
|
|
50
59
|
|
|
60
|
+
When showing search results, include for each candidate:
|
|
61
|
+
- **name** and **match score**
|
|
62
|
+
- **self_intro** (their self-description) — separate from match_reason
|
|
63
|
+
- **match_reason** (why they match your search)
|
|
64
|
+
- **topic tags** and **completeness**
|
|
65
|
+
|
|
51
66
|
## Connecting
|
|
52
67
|
|
|
53
68
|
Before connecting, ALWAYS:
|
|
@@ -85,4 +100,4 @@ Triggers: "open my inbox", "any new messages", "check my sessions"
|
|
|
85
100
|
|
|
86
101
|
Triggers: "generate my card", "share my card", "show my Claw-Social card"
|
|
87
102
|
|
|
88
|
-
Call `clawsocial_get_card` to generate the user's profile card. The card represents the user, not the AI agent.
|
|
103
|
+
Call `clawsocial_get_card` to generate the user's profile card. The card represents the user, not the AI agent. Display the card text exactly as returned — do not reformat or summarize. Share it so the user can send it to others.
|
package/package.json
CHANGED
package/src/i18n.ts
CHANGED
|
@@ -102,6 +102,15 @@ const strings = {
|
|
|
102
102
|
local_unknown_err: { zh: "未知错误", en: "Unknown error" },
|
|
103
103
|
local_started: { zh: "本地收件箱已启动", en: "Local inbox started" },
|
|
104
104
|
|
|
105
|
+
// ── Display formatting (match / find results) ──────────────────
|
|
106
|
+
display_self_intro: { zh: "自我介绍", en: "Self-intro" },
|
|
107
|
+
display_profile: { zh: "画像", en: "Profile" },
|
|
108
|
+
display_match_reason: { zh: "匹配原因", en: "Match reason" },
|
|
109
|
+
display_tags: { zh: "标签", en: "Tags" },
|
|
110
|
+
display_completeness: { zh: "完整度", en: "Completeness" },
|
|
111
|
+
display_contact: { zh: "已连接", en: "contact" },
|
|
112
|
+
display_empty: { zh: "—", en: "—" },
|
|
113
|
+
|
|
105
114
|
// ── Tools ──────────────────────────────────────────────────────
|
|
106
115
|
tools_not_registered: { zh: "尚未注册 Claw-Social,请先使用 clawsocial_register 注册。",
|
|
107
116
|
en: "Not registered on Claw-Social. Use clawsocial_register first." },
|
package/src/tools/block.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { t } from "../i18n.js";
|
|
|
7
7
|
export function createBlockTool(): AnyAgentTool {
|
|
8
8
|
return {
|
|
9
9
|
name: "clawsocial_block",
|
|
10
|
-
label: "
|
|
10
|
+
label: "Claw-Social Block",
|
|
11
11
|
description:
|
|
12
12
|
"Block an agent. They will no longer be able to contact you, and any existing session is closed. Call when the user explicitly says they don't want to hear from someone.",
|
|
13
13
|
parameters: Type.Object({
|
package/src/tools/card.ts
CHANGED
|
@@ -5,12 +5,11 @@ import api from "../api.js";
|
|
|
5
5
|
export function createCardTool(): AnyAgentTool {
|
|
6
6
|
return {
|
|
7
7
|
name: "clawsocial_get_card",
|
|
8
|
-
label: "
|
|
8
|
+
label: "Claw-Social Profile Card",
|
|
9
9
|
description:
|
|
10
|
-
"Generate
|
|
11
|
-
"The card represents the user
|
|
12
|
-
"
|
|
13
|
-
"Also automatically called after clawsocial_update_profile to show the updated card.",
|
|
10
|
+
"Generate the user's Claw-Social profile card for sharing. " +
|
|
11
|
+
"The card represents the user, not the AI agent. " +
|
|
12
|
+
"Display the returned card text exactly as-is — do not reformat, summarize, or add commentary.",
|
|
14
13
|
parameters: Type.Object({}),
|
|
15
14
|
async execute(_id: string, _params: Record<string, unknown>) {
|
|
16
15
|
const res = await api.getCard();
|
package/src/tools/connect.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { upsertSession, upsertContact } from "../store.js";
|
|
|
6
6
|
export function createConnectTool(serverUrl: string): AnyAgentTool {
|
|
7
7
|
return {
|
|
8
8
|
name: "clawsocial_connect",
|
|
9
|
-
label: "
|
|
9
|
+
label: "Claw-Social Connect",
|
|
10
10
|
description:
|
|
11
11
|
"Send a connection request. Requires target_agent_id (UUID) and intro_message. " +
|
|
12
12
|
"Can be used after clawsocial_find/clawsocial_match (use agent_id from results), " +
|
package/src/tools/find.ts
CHANGED
|
@@ -2,15 +2,70 @@ 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
|
+
|
|
7
|
+
interface DisplayEntry {
|
|
8
|
+
agent_id: string;
|
|
9
|
+
public_name: string;
|
|
10
|
+
self_intro: string;
|
|
11
|
+
profile: string;
|
|
12
|
+
topic_tags: string[];
|
|
13
|
+
is_contact: boolean;
|
|
14
|
+
session_id?: string;
|
|
15
|
+
match_reason?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function formatResults(entries: DisplayEntry[]): string {
|
|
19
|
+
return entries
|
|
20
|
+
.map((c, i) => {
|
|
21
|
+
const label = c.is_contact ? ` [${t("display_contact")}]` : "";
|
|
22
|
+
const selfIntro = c.self_intro || t("display_empty");
|
|
23
|
+
const profile = c.profile || t("display_empty");
|
|
24
|
+
const tags = c.topic_tags?.length
|
|
25
|
+
? c.topic_tags.map(tag => `#${tag}`).join(" ")
|
|
26
|
+
: t("display_empty");
|
|
27
|
+
|
|
28
|
+
const lines = [
|
|
29
|
+
`${i + 1}. ${c.public_name}${label}`,
|
|
30
|
+
` ${t("display_self_intro")}: ${selfIntro}`,
|
|
31
|
+
` ${t("display_profile")}: ${profile}`,
|
|
32
|
+
` ${t("display_tags")}: ${tags}`,
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
if (c.match_reason) {
|
|
36
|
+
lines.splice(3, 0, ` ${t("display_match_reason")}: ${c.match_reason}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return lines.join("\n");
|
|
40
|
+
})
|
|
41
|
+
.join("\n\n");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function toDisplayEntry(
|
|
45
|
+
c: { agent_id: string; public_name?: string; name?: string; topic_tags?: string[]; self_intro?: string; profile?: string; match_reason?: string; session_id?: string },
|
|
46
|
+
isContact: boolean,
|
|
47
|
+
): DisplayEntry {
|
|
48
|
+
return {
|
|
49
|
+
agent_id: c.agent_id,
|
|
50
|
+
public_name: (c.public_name || c.name || "") as string,
|
|
51
|
+
self_intro: c.self_intro || "",
|
|
52
|
+
profile: c.profile || "",
|
|
53
|
+
topic_tags: c.topic_tags || [],
|
|
54
|
+
is_contact: isContact,
|
|
55
|
+
session_id: c.session_id,
|
|
56
|
+
match_reason: c.match_reason,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
5
59
|
|
|
6
60
|
export function createFindTool(): AnyAgentTool {
|
|
7
61
|
return {
|
|
8
62
|
name: "clawsocial_find",
|
|
9
|
-
label: "
|
|
63
|
+
label: "Claw-Social Find Person",
|
|
10
64
|
description:
|
|
11
65
|
"Find a specific person by name or agent_id. Use when the user wants to locate a specific person " +
|
|
12
|
-
"(e.g. 'find Alice', '
|
|
13
|
-
"For broad interest-based discovery
|
|
66
|
+
"(e.g. 'find Alice', 'find Bob who does AI'). Checks local contacts first, then searches the server. " +
|
|
67
|
+
"For broad interest-based discovery, use clawsocial_match instead. " +
|
|
68
|
+
"Display the `display` field as-is.",
|
|
14
69
|
parameters: Type.Object({
|
|
15
70
|
name: Type.Optional(Type.String({ description: "Name search (supports partial match)" })),
|
|
16
71
|
agent_id: Type.Optional(Type.String({ description: "Exact agent ID lookup" })),
|
|
@@ -30,11 +85,19 @@ export function createFindTool(): AnyAgentTool {
|
|
|
30
85
|
const contacts = readContacts();
|
|
31
86
|
const local = contacts.find(c => c.agent_id === agentId);
|
|
32
87
|
if (local) {
|
|
33
|
-
|
|
88
|
+
const entry = toDisplayEntry(local, true);
|
|
89
|
+
return ok({
|
|
90
|
+
display: formatResults([entry]),
|
|
91
|
+
results: [{ index: 1, agent_id: entry.agent_id, public_name: entry.public_name, is_contact: true, session_id: local.session_id }],
|
|
92
|
+
});
|
|
34
93
|
}
|
|
35
94
|
try {
|
|
36
95
|
const agent = await api.getAgent(agentId);
|
|
37
|
-
|
|
96
|
+
const entry = toDisplayEntry(agent, false);
|
|
97
|
+
return ok({
|
|
98
|
+
display: formatResults([entry]),
|
|
99
|
+
results: [{ index: 1, agent_id: entry.agent_id, public_name: entry.public_name, is_contact: false }],
|
|
100
|
+
});
|
|
38
101
|
} catch {
|
|
39
102
|
return notFound(`Agent ${agentId} not found`);
|
|
40
103
|
}
|
|
@@ -46,54 +109,47 @@ export function createFindTool(): AnyAgentTool {
|
|
|
46
109
|
if (interest && localMatches.length > 1) {
|
|
47
110
|
const kw = interest.toLowerCase();
|
|
48
111
|
const filtered = localMatches.filter(c =>
|
|
49
|
-
c.topic_tags?.some(
|
|
112
|
+
c.topic_tags?.some(tag => tag.toLowerCase().includes(kw)) ||
|
|
50
113
|
c.profile?.toLowerCase().includes(kw)
|
|
51
114
|
);
|
|
52
115
|
if (filtered.length > 0) localMatches = filtered;
|
|
53
116
|
}
|
|
54
117
|
|
|
55
118
|
// 2. search server (with intent for semantic sorting)
|
|
56
|
-
let
|
|
119
|
+
let serverEntries: DisplayEntry[] = [];
|
|
57
120
|
try {
|
|
58
121
|
const res = await api.searchByName(name!, interest);
|
|
59
|
-
|
|
60
|
-
agent_id: c.agent_id,
|
|
61
|
-
public_name: c.public_name,
|
|
62
|
-
topic_tags: c.topic_tags,
|
|
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 } : {}),
|
|
67
|
-
}));
|
|
122
|
+
serverEntries = (res.candidates || []).map(c => toDisplayEntry(c, false));
|
|
68
123
|
} catch { /* fall back to local results when server is unreachable */ }
|
|
69
124
|
|
|
70
125
|
// 3. merge and deduplicate (local first)
|
|
71
126
|
const localIds = new Set(localMatches.map(c => c.agent_id));
|
|
127
|
+
const localEntries = localMatches.map(c => toDisplayEntry(c, true));
|
|
72
128
|
const merged = [
|
|
73
|
-
...
|
|
74
|
-
...
|
|
129
|
+
...localEntries,
|
|
130
|
+
...serverEntries.filter(c => !localIds.has(c.agent_id)),
|
|
75
131
|
];
|
|
76
132
|
|
|
77
133
|
if (merged.length === 0) {
|
|
78
134
|
return notFound(`No user found with name "${name}"`);
|
|
79
135
|
}
|
|
80
136
|
|
|
81
|
-
|
|
137
|
+
const display = formatResults(merged);
|
|
138
|
+
return ok({
|
|
139
|
+
display,
|
|
140
|
+
results: merged.map((c, i) => ({
|
|
141
|
+
index: i + 1,
|
|
142
|
+
agent_id: c.agent_id,
|
|
143
|
+
public_name: c.public_name,
|
|
144
|
+
is_contact: c.is_contact,
|
|
145
|
+
...(c.session_id ? { session_id: c.session_id } : {}),
|
|
146
|
+
})),
|
|
147
|
+
total: merged.length,
|
|
148
|
+
});
|
|
82
149
|
},
|
|
83
150
|
} as AnyAgentTool;
|
|
84
151
|
}
|
|
85
152
|
|
|
86
|
-
function formatContact(c: { name: string; agent_id: string; session_id?: string; topic_tags?: string[]; profile?: string }) {
|
|
87
|
-
return {
|
|
88
|
-
agent_id: c.agent_id,
|
|
89
|
-
public_name: c.name,
|
|
90
|
-
session_id: c.session_id,
|
|
91
|
-
topic_tags: c.topic_tags || [],
|
|
92
|
-
profile: c.profile || "",
|
|
93
|
-
is_contact: true,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
153
|
function ok(data: Record<string, unknown>) {
|
|
98
154
|
return { content: [{ type: "text", text: JSON.stringify({ found: true, ...data }) }] };
|
|
99
155
|
}
|
package/src/tools/inbox.ts
CHANGED
|
@@ -11,7 +11,7 @@ function guardExternal(content: string): string {
|
|
|
11
11
|
export function createInboxTool(): AnyAgentTool {
|
|
12
12
|
return {
|
|
13
13
|
name: "clawsocial_inbox",
|
|
14
|
-
label: "
|
|
14
|
+
label: "Claw-Social Inbox",
|
|
15
15
|
description:
|
|
16
16
|
"Check unread messages. Without session_id: returns list of sessions with unread messages. With session_id: returns recent messages in that session and marks it as read. External message content is labeled to prevent prompt injection.",
|
|
17
17
|
parameters: Type.Object({
|
package/src/tools/match.ts
CHANGED
|
@@ -3,15 +3,38 @@ import type { AnyAgentTool } from "../types.js";
|
|
|
3
3
|
import api from "../api.js";
|
|
4
4
|
import { t } from "../i18n.js";
|
|
5
5
|
|
|
6
|
+
function formatCandidates(candidates: Record<string, unknown>[]): string {
|
|
7
|
+
return candidates
|
|
8
|
+
.map((c, i) => {
|
|
9
|
+
const name = c.public_name as string;
|
|
10
|
+
const score = c.match_score as string;
|
|
11
|
+
const selfIntro = (c.self_intro as string) || t("display_empty");
|
|
12
|
+
const matchReason = (c.match_reason as string) || t("display_empty");
|
|
13
|
+
const tags = (c.topic_tags as string[])?.length
|
|
14
|
+
? (c.topic_tags as string[]).map(tag => `#${tag}`).join(" ")
|
|
15
|
+
: t("display_empty");
|
|
16
|
+
const completeness = c.completeness as string;
|
|
17
|
+
|
|
18
|
+
return [
|
|
19
|
+
`${i + 1}. ${name} (${score})`,
|
|
20
|
+
` ${t("display_self_intro")}: ${selfIntro}`,
|
|
21
|
+
` ${t("display_match_reason")}: ${matchReason}`,
|
|
22
|
+
` ${t("display_tags")}: ${tags}`,
|
|
23
|
+
` ${t("display_completeness")}: ${completeness}`,
|
|
24
|
+
].join("\n");
|
|
25
|
+
})
|
|
26
|
+
.join("\n\n");
|
|
27
|
+
}
|
|
28
|
+
|
|
6
29
|
export function createMatchTool(): AnyAgentTool {
|
|
7
30
|
return {
|
|
8
31
|
name: "clawsocial_match",
|
|
9
|
-
label: "
|
|
32
|
+
label: "Claw-Social Match",
|
|
10
33
|
description:
|
|
11
|
-
"Discover
|
|
12
|
-
"Use when the user describes
|
|
13
|
-
"For
|
|
14
|
-
"
|
|
34
|
+
"Discover people by interest using semantic search. " +
|
|
35
|
+
"Use when the user describes interests (e.g. 'find people into AI'). " +
|
|
36
|
+
"For a specific person by name, use clawsocial_find. " +
|
|
37
|
+
"Display the `display` field as-is. Get explicit approval before connecting.",
|
|
15
38
|
parameters: Type.Object({
|
|
16
39
|
interest: Type.String({ description: "Natural language description of what kind of person or topic to find" }),
|
|
17
40
|
}),
|
|
@@ -33,18 +56,28 @@ export function createMatchTool(): AnyAgentTool {
|
|
|
33
56
|
};
|
|
34
57
|
}
|
|
35
58
|
|
|
59
|
+
const candidates = res.candidates.map((c, i) => ({
|
|
60
|
+
index: i + 1,
|
|
61
|
+
agent_id: c.agent_id,
|
|
62
|
+
public_name: c.public_name,
|
|
63
|
+
match_score: Math.round(c.match_score * 100) + "%",
|
|
64
|
+
topic_tags: c.topic_tags,
|
|
65
|
+
completeness: Math.round((c.completeness_score ?? 0.1) * 100) + "%",
|
|
66
|
+
self_intro: c.self_intro || "",
|
|
67
|
+
profile: c.profile || "",
|
|
68
|
+
match_reason: c.match_reason || "",
|
|
69
|
+
}));
|
|
70
|
+
|
|
71
|
+
const display = formatCandidates(candidates);
|
|
72
|
+
|
|
36
73
|
const result = {
|
|
37
|
-
|
|
74
|
+
display,
|
|
75
|
+
candidates: candidates.map(c => ({
|
|
76
|
+
index: c.index,
|
|
38
77
|
agent_id: c.agent_id,
|
|
39
78
|
public_name: c.public_name,
|
|
40
|
-
topic_tags: c.topic_tags,
|
|
41
|
-
match_score: Math.round(c.match_score * 100) + "%",
|
|
42
|
-
completeness: Math.round((c.completeness_score ?? 0.1) * 100) + "%",
|
|
43
|
-
...(c.self_intro ? { self_intro: c.self_intro } : {}),
|
|
44
|
-
...(c.profile ? { profile: c.profile } : {}),
|
|
45
|
-
...(c.match_reason ? { match_reason: c.match_reason } : {}),
|
|
46
79
|
})),
|
|
47
|
-
total:
|
|
80
|
+
total: candidates.length,
|
|
48
81
|
query_intent: interest,
|
|
49
82
|
};
|
|
50
83
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
@@ -12,9 +12,9 @@ function modeDesc(mode: NotifyMode): string {
|
|
|
12
12
|
export function createNotifySettingsTool(): AnyAgentTool {
|
|
13
13
|
return {
|
|
14
14
|
name: "clawsocial_notify_settings",
|
|
15
|
-
label: "
|
|
15
|
+
label: "Claw-Social Notify Settings",
|
|
16
16
|
description:
|
|
17
|
-
"View or change
|
|
17
|
+
"View or change Claw-Social notification mode. Use when the user asks to adjust notification preferences, turn off notifications, etc.",
|
|
18
18
|
parameters: Type.Object({
|
|
19
19
|
mode: Type.Optional(
|
|
20
20
|
Type.Union(
|
package/src/tools/open_inbox.ts
CHANGED
|
@@ -6,9 +6,9 @@ import { t } from "../i18n.js";
|
|
|
6
6
|
export function createOpenInboxTool(): AnyAgentTool {
|
|
7
7
|
return {
|
|
8
8
|
name: "clawsocial_open_inbox",
|
|
9
|
-
label: "
|
|
9
|
+
label: "Claw-Social Open Inbox",
|
|
10
10
|
description:
|
|
11
|
-
"Generate a one-time login link to open the
|
|
11
|
+
"Generate a one-time login link to open the Claw-Social inbox in a browser. The link is valid for 15 minutes and can only be used once. Call this when the user asks to open their inbox or check messages.",
|
|
12
12
|
parameters: Type.Object({}),
|
|
13
13
|
async execute(_id: string, _params: Record<string, unknown>) {
|
|
14
14
|
const data = await api.openInboxToken();
|
|
@@ -6,7 +6,7 @@ import { t } from "../i18n.js";
|
|
|
6
6
|
export function createOpenLocalInboxTool(): AnyAgentTool {
|
|
7
7
|
return {
|
|
8
8
|
name: "clawsocial_open_local_inbox",
|
|
9
|
-
label: "
|
|
9
|
+
label: "Claw-Social Open Local Inbox",
|
|
10
10
|
description:
|
|
11
11
|
"Start the local inbox web UI and return its URL. The local inbox shows complete message history (no time limit) and supports replying. Only accessible from this machine. Call when the user wants to view full message history or open the local inbox.",
|
|
12
12
|
parameters: Type.Object({}),
|
package/src/tools/register.ts
CHANGED
|
@@ -8,11 +8,12 @@ import { t } from "../i18n.js";
|
|
|
8
8
|
export function createRegisterTool(): AnyAgentTool {
|
|
9
9
|
return {
|
|
10
10
|
name: "clawsocial_register",
|
|
11
|
-
label: "
|
|
11
|
+
label: "Claw-Social Register",
|
|
12
12
|
description:
|
|
13
|
-
"Register on
|
|
13
|
+
"Register on Claw-Social. The account belongs to the user, not the AI agent. " +
|
|
14
|
+
"Only ask for public_name. After registration, call clawsocial_suggest_profile to build the user's interest profile.",
|
|
14
15
|
parameters: Type.Object({
|
|
15
|
-
public_name: Type.String({ description: "The user's chosen display name on
|
|
16
|
+
public_name: Type.String({ description: "The user's chosen display name on Claw-Social" }),
|
|
16
17
|
language_pref: Type.Optional(
|
|
17
18
|
Type.Unsafe<"zh" | "en">({
|
|
18
19
|
type: "string",
|
package/src/tools/session_get.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { t, formatDateTime } from "../i18n.js";
|
|
|
6
6
|
export function createSessionGetTool(serverUrl: string): AnyAgentTool {
|
|
7
7
|
return {
|
|
8
8
|
name: "clawsocial_session_get",
|
|
9
|
-
label: "
|
|
9
|
+
label: "Claw-Social View Session",
|
|
10
10
|
description:
|
|
11
11
|
"Get recent messages of a specific session. Supports exact session_id or fuzzy partner_name match.",
|
|
12
12
|
parameters: Type.Object({
|
|
@@ -7,7 +7,7 @@ import { t } from "../i18n.js";
|
|
|
7
7
|
export function createSessionSendTool(): AnyAgentTool {
|
|
8
8
|
return {
|
|
9
9
|
name: "clawsocial_session_send",
|
|
10
|
-
label: "
|
|
10
|
+
label: "Claw-Social Send Message",
|
|
11
11
|
description:
|
|
12
12
|
"Send a message in an active session on behalf of the user. Call when the user explicitly provides reply content. Pass the content verbatim — do not paraphrase.",
|
|
13
13
|
parameters: Type.Object({
|
|
@@ -6,7 +6,7 @@ import { t, formatDateTime } from "../i18n.js";
|
|
|
6
6
|
export function createSessionsListTool(serverUrl: string): AnyAgentTool {
|
|
7
7
|
return {
|
|
8
8
|
name: "clawsocial_sessions_list",
|
|
9
|
-
label: "
|
|
9
|
+
label: "Claw-Social Sessions List",
|
|
10
10
|
description:
|
|
11
11
|
"List all active sessions. Call when the user asks about their conversations or checks /sessions.",
|
|
12
12
|
parameters: Type.Object({}),
|
|
@@ -33,13 +33,12 @@ function readLocalFiles(): LocalFiles {
|
|
|
33
33
|
export function createSuggestProfileTool(): AnyAgentTool {
|
|
34
34
|
return {
|
|
35
35
|
name: "clawsocial_suggest_profile",
|
|
36
|
-
label: "
|
|
36
|
+
label: "Claw-Social Suggest Profile",
|
|
37
37
|
description:
|
|
38
|
-
"Read
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"NEVER update the profile silently.",
|
|
38
|
+
"Read local workspace files and draft a privacy-safe interest profile. " +
|
|
39
|
+
"This is the ONLY way to set the profile field on clawsocial_update_profile. " +
|
|
40
|
+
"Flow: 1) call this tool, 2) show the COMPLETE draft to the user, 3) call update_profile ONLY after the user confirms. " +
|
|
41
|
+
"NEVER skip showing the draft.",
|
|
43
42
|
parameters: Type.Object({}),
|
|
44
43
|
async execute(_id: string, _params: Record<string, unknown>) {
|
|
45
44
|
const files = readLocalFiles();
|
|
@@ -7,12 +7,11 @@ import { t } from "../i18n.js";
|
|
|
7
7
|
export function createUpdateProfileTool(): AnyAgentTool {
|
|
8
8
|
return {
|
|
9
9
|
name: "clawsocial_update_profile",
|
|
10
|
-
label: "
|
|
10
|
+
label: "Claw-Social Update Profile",
|
|
11
11
|
description:
|
|
12
|
-
"Update the user's
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"Never write from the AI agent's perspective (e.g. never say 'I am a lobster' or 'my owner likes...').",
|
|
12
|
+
"Update the user's Claw-Social profile. The profile represents the user, not the AI agent — write from the user's perspective. " +
|
|
13
|
+
"For self_intro/topic_tags/public_name/availability: call directly. " +
|
|
14
|
+
"For the profile field: NEVER set it directly — ONLY use content confirmed by the user from clawsocial_suggest_profile.",
|
|
16
15
|
parameters: Type.Object({
|
|
17
16
|
self_intro: Type.Optional(
|
|
18
17
|
Type.String({
|