@a2hmarket/a2hmarket 2026.3.19
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 +45 -0
- package/openclaw.plugin.json +11 -0
- package/package.json +42 -0
- package/skill/HEARTBEAT.md +35 -0
- package/skill/SKILL.md +93 -0
- package/skill/references/inbox.md +165 -0
- package/skill/references/playbooks/browsing.md +158 -0
- package/skill/references/playbooks/negotiation.md +163 -0
- package/skill/references/playbooks/onboarding.md +35 -0
- package/skill/references/playbooks/reporting.md +101 -0
- package/skill/references/playbooks/shopping.md +155 -0
- package/skill/references/playbooks/stall.md +202 -0
- package/skill/references/tools.md +349 -0
- package/src/a2a-protocol.ts +192 -0
- package/src/api/inbox.ts +221 -0
- package/src/api/order.ts +69 -0
- package/src/api/profile.ts +27 -0
- package/src/api/send.ts +134 -0
- package/src/api/works.ts +82 -0
- package/src/api-client.ts +251 -0
- package/src/commands/cmd-setup.ts +167 -0
- package/src/commands/cmd-status.ts +56 -0
- package/src/credentials.ts +36 -0
- package/src/hooks/before-agent-start.ts +83 -0
- package/src/service/lease-client.ts +118 -0
- package/src/service/mqtt-listener.ts +419 -0
- package/src/session-cache.ts +73 -0
- package/src/tools/index.ts +14 -0
- package/src/tools/tool-inbox.ts +149 -0
- package/src/tools/tool-order.ts +210 -0
- package/src/tools/tool-profile.ts +40 -0
- package/src/tools/tool-send.ts +81 -0
- package/src/tools/tool-works.ts +240 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
|
3
|
+
import { pullEvents, ackEvent, getEvent, historyByPeer } from "../api/inbox.js";
|
|
4
|
+
|
|
5
|
+
export function registerInboxTools(api: OpenClawPluginApi): void {
|
|
6
|
+
api.registerTool(
|
|
7
|
+
{
|
|
8
|
+
name: "inbox_pull",
|
|
9
|
+
label: "Inbox Pull",
|
|
10
|
+
description:
|
|
11
|
+
"Pull unread messages from the A2HMarket inbox. Returns a list of pending messages from other agents.",
|
|
12
|
+
parameters: Type.Object({
|
|
13
|
+
limit: Type.Optional(
|
|
14
|
+
Type.Number({ description: "Max messages to pull (default: 10, max: 50)" }),
|
|
15
|
+
),
|
|
16
|
+
cursor: Type.Optional(
|
|
17
|
+
Type.Number({ description: "Sequence cursor for pagination (default: 0)" }),
|
|
18
|
+
),
|
|
19
|
+
peerId: Type.Optional(
|
|
20
|
+
Type.String({ description: "Filter messages from a specific agent ID" }),
|
|
21
|
+
),
|
|
22
|
+
}),
|
|
23
|
+
execute(_toolCallId, params) {
|
|
24
|
+
const { limit = 10, cursor = 0, peerId } = params as {
|
|
25
|
+
limit?: number;
|
|
26
|
+
cursor?: number;
|
|
27
|
+
peerId?: string;
|
|
28
|
+
};
|
|
29
|
+
const safeLimit = Math.min(Math.max(1, limit), 50);
|
|
30
|
+
|
|
31
|
+
const result = pullEvents("default", cursor, safeLimit, peerId);
|
|
32
|
+
|
|
33
|
+
const items = result.events;
|
|
34
|
+
const messages = items.map((ev) => ({
|
|
35
|
+
event_id: ev.event_id,
|
|
36
|
+
peer_id: ev.peer_id,
|
|
37
|
+
preview: ev.preview,
|
|
38
|
+
payload: ev.payload,
|
|
39
|
+
created_at: ev.created_at,
|
|
40
|
+
}));
|
|
41
|
+
const text =
|
|
42
|
+
items.length === 0
|
|
43
|
+
? "No new messages."
|
|
44
|
+
: `${items.length} message(s) (cursor: ${result.cursor}):\n${JSON.stringify(messages, null, 2)}`;
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
content: [{ type: "text", text }],
|
|
48
|
+
details: {
|
|
49
|
+
ok: true,
|
|
50
|
+
count: items.length,
|
|
51
|
+
cursor: result.cursor,
|
|
52
|
+
messages,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{ name: "inbox_pull" },
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
api.registerTool(
|
|
61
|
+
{
|
|
62
|
+
name: "inbox_ack",
|
|
63
|
+
label: "Inbox Ack",
|
|
64
|
+
description:
|
|
65
|
+
"Acknowledge (mark as processed) a message in the A2HMarket inbox. Always call this after reading a message.",
|
|
66
|
+
parameters: Type.Object({
|
|
67
|
+
eventId: Type.String({ description: "The event ID of the message to acknowledge" }),
|
|
68
|
+
}),
|
|
69
|
+
execute(_toolCallId, params) {
|
|
70
|
+
const { eventId } = params as { eventId: string };
|
|
71
|
+
|
|
72
|
+
const result = ackEvent("default", eventId);
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
content: [{ type: "text", text: `Message ${eventId} acknowledged.` }],
|
|
76
|
+
details: { ok: true, eventId, ackedAt: result.acked_at },
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
{ name: "inbox_ack" },
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
api.registerTool(
|
|
84
|
+
{
|
|
85
|
+
name: "inbox_get",
|
|
86
|
+
label: "Inbox Get",
|
|
87
|
+
description:
|
|
88
|
+
"Get the full payload of a single inbox message by event ID. Use this after inbox_pull to inspect attachment metadata, payment QR URLs, or other detailed fields not included in the preview.",
|
|
89
|
+
parameters: Type.Object({
|
|
90
|
+
eventId: Type.String({ description: "The event ID of the message to retrieve" }),
|
|
91
|
+
}),
|
|
92
|
+
execute(_toolCallId, params) {
|
|
93
|
+
const { eventId } = params as { eventId: string };
|
|
94
|
+
|
|
95
|
+
const ev = getEvent(eventId);
|
|
96
|
+
if (!ev) {
|
|
97
|
+
return {
|
|
98
|
+
content: [{ type: "text", text: `Event not found: ${eventId}` }],
|
|
99
|
+
details: { ok: false, error: `event not found: ${eventId}` },
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
content: [{ type: "text", text: `Event ${eventId}:\n${JSON.stringify(ev, null, 2)}` }],
|
|
105
|
+
details: { ok: true, event: ev },
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
{ name: "inbox_get" },
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
api.registerTool(
|
|
113
|
+
{
|
|
114
|
+
name: "inbox_history",
|
|
115
|
+
label: "Inbox History",
|
|
116
|
+
description:
|
|
117
|
+
"Query message history with a specific peer agent. Returns received (inbound) messages only — outbound messages are not stored in the inbox queue and cannot be retrieved here.",
|
|
118
|
+
parameters: Type.Object({
|
|
119
|
+
peerId: Type.String({ description: "The peer agent ID to fetch history for" }),
|
|
120
|
+
page: Type.Optional(Type.Number({ description: "Page number (1-based, default: 1)" })),
|
|
121
|
+
limit: Type.Optional(
|
|
122
|
+
Type.Number({ description: "Messages per page (default: 20, max: 100)" }),
|
|
123
|
+
),
|
|
124
|
+
}),
|
|
125
|
+
execute(_toolCallId, params) {
|
|
126
|
+
const { peerId, page = 1, limit = 20 } = params as {
|
|
127
|
+
peerId: string;
|
|
128
|
+
page?: number;
|
|
129
|
+
limit?: number;
|
|
130
|
+
};
|
|
131
|
+
const safeLimit = Math.min(Math.max(1, limit), 100);
|
|
132
|
+
const safePage = Math.max(1, page);
|
|
133
|
+
|
|
134
|
+
const result = historyByPeer(peerId, safePage, safeLimit);
|
|
135
|
+
|
|
136
|
+
const text =
|
|
137
|
+
result.items.length === 0
|
|
138
|
+
? `No message history found with peer ${peerId}.`
|
|
139
|
+
: `${result.total} message(s) with ${peerId} (page ${safePage}, showing ${result.items.length}):\n${JSON.stringify(result, null, 2)}`;
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
content: [{ type: "text", text }],
|
|
143
|
+
details: { ok: true, ...result },
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
{ name: "inbox_history" },
|
|
148
|
+
);
|
|
149
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
|
3
|
+
import { createApiClient } from "../api-client.js";
|
|
4
|
+
import { orderCreate, orderGet, orderAction, orderList } from "../api/order.js";
|
|
5
|
+
import type { OrderAction } from "../api/order.js";
|
|
6
|
+
|
|
7
|
+
// Valid order actions (underscore variant for tool input, hyphen variant for API)
|
|
8
|
+
const ORDER_ACTIONS = [
|
|
9
|
+
"confirm",
|
|
10
|
+
"reject",
|
|
11
|
+
"cancel",
|
|
12
|
+
"confirm_received",
|
|
13
|
+
"confirm_service_completed",
|
|
14
|
+
] as const;
|
|
15
|
+
|
|
16
|
+
type ToolOrderAction = (typeof ORDER_ACTIONS)[number];
|
|
17
|
+
|
|
18
|
+
/** Convert tool action (underscores) to API action (hyphens). */
|
|
19
|
+
function toApiAction(action: ToolOrderAction): OrderAction {
|
|
20
|
+
return action.replace(/_/g, "-") as OrderAction;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function registerOrderTools(api: OpenClawPluginApi): void {
|
|
24
|
+
api.registerTool(
|
|
25
|
+
{
|
|
26
|
+
name: "order_create",
|
|
27
|
+
label: "Order Create",
|
|
28
|
+
description: "Create a new order on the A2HMarket platform.",
|
|
29
|
+
parameters: Type.Object({
|
|
30
|
+
customerId: Type.String({ description: "Customer agent ID" }),
|
|
31
|
+
title: Type.String({ description: "Order title/description" }),
|
|
32
|
+
priceCent: Type.Number({
|
|
33
|
+
description: "Price in cents (e.g. 9900 = 99.00 yuan)",
|
|
34
|
+
}),
|
|
35
|
+
productId: Type.String({ description: "Product/works ID being ordered" }),
|
|
36
|
+
orderType: Type.Number({
|
|
37
|
+
description:
|
|
38
|
+
"Order type: 2=seller takes buyer demand task, 3=buyer purchases seller existing service",
|
|
39
|
+
}),
|
|
40
|
+
}),
|
|
41
|
+
async execute(_toolCallId, params) {
|
|
42
|
+
const { customerId, title, priceCent, productId, orderType } = params as {
|
|
43
|
+
customerId: string;
|
|
44
|
+
title: string;
|
|
45
|
+
priceCent: number;
|
|
46
|
+
productId: string;
|
|
47
|
+
orderType: number;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const client = createApiClient();
|
|
52
|
+
const result = await orderCreate(client, {
|
|
53
|
+
customerId,
|
|
54
|
+
title,
|
|
55
|
+
content: title,
|
|
56
|
+
price: priceCent,
|
|
57
|
+
productId,
|
|
58
|
+
orderType: orderType as 2 | 3,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const data = result as Record<string, unknown>;
|
|
62
|
+
const orderId = (data?.order_id ?? data?.orderId ?? "unknown") as string;
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
content: [{ type: "text", text: `Order created. Order ID: ${orderId}` }],
|
|
66
|
+
details: { ok: true, orderId, result },
|
|
67
|
+
};
|
|
68
|
+
} catch (err) {
|
|
69
|
+
const errMsg = String(err);
|
|
70
|
+
return {
|
|
71
|
+
content: [{ type: "text", text: `Order creation failed: ${errMsg}` }],
|
|
72
|
+
details: { ok: false, error: errMsg },
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{ name: "order_create" },
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
api.registerTool(
|
|
81
|
+
{
|
|
82
|
+
name: "order_get",
|
|
83
|
+
label: "Order Get",
|
|
84
|
+
description: "Query the details of an order by order ID.",
|
|
85
|
+
parameters: Type.Object({
|
|
86
|
+
orderId: Type.String({ description: "The order ID to look up" }),
|
|
87
|
+
}),
|
|
88
|
+
async execute(_toolCallId, params) {
|
|
89
|
+
const { orderId } = params as { orderId: string };
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
const client = createApiClient();
|
|
93
|
+
const order = await orderGet(client, orderId);
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
content: [{ type: "text", text: `Order ${orderId}:\n${JSON.stringify(order, null, 2)}` }],
|
|
97
|
+
details: { ok: true, order },
|
|
98
|
+
};
|
|
99
|
+
} catch (err) {
|
|
100
|
+
const errMsg = String(err);
|
|
101
|
+
return {
|
|
102
|
+
content: [
|
|
103
|
+
{ type: "text", text: `Failed to get order ${orderId}: ${errMsg}` },
|
|
104
|
+
],
|
|
105
|
+
details: { ok: false, error: errMsg },
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{ name: "order_get" },
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
api.registerTool(
|
|
114
|
+
{
|
|
115
|
+
name: "order_action",
|
|
116
|
+
label: "Order Action",
|
|
117
|
+
description:
|
|
118
|
+
"Perform an action on an order: confirm, reject, cancel, confirm_received, or confirm_service_completed.",
|
|
119
|
+
parameters: Type.Object({
|
|
120
|
+
orderId: Type.String({ description: "The order ID" }),
|
|
121
|
+
action: Type.Unsafe<ToolOrderAction>({
|
|
122
|
+
type: "string",
|
|
123
|
+
enum: [...ORDER_ACTIONS],
|
|
124
|
+
description:
|
|
125
|
+
"Action to perform: confirm | reject | cancel | confirm_received | confirm_service_completed",
|
|
126
|
+
}),
|
|
127
|
+
}),
|
|
128
|
+
async execute(_toolCallId, params) {
|
|
129
|
+
const { orderId, action } = params as {
|
|
130
|
+
orderId: string;
|
|
131
|
+
action: ToolOrderAction;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
const client = createApiClient();
|
|
136
|
+
const result = await orderAction(client, orderId, toApiAction(action));
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
content: [
|
|
140
|
+
{
|
|
141
|
+
type: "text",
|
|
142
|
+
text: `Order ${orderId}: action "${action}" completed successfully.`,
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
details: { ok: true, orderId, action, result },
|
|
146
|
+
};
|
|
147
|
+
} catch (err) {
|
|
148
|
+
const errMsg = String(err);
|
|
149
|
+
return {
|
|
150
|
+
content: [
|
|
151
|
+
{
|
|
152
|
+
type: "text",
|
|
153
|
+
text: `Order action "${action}" failed for order ${orderId}: ${errMsg}`,
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
details: { ok: false, error: errMsg },
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
{ name: "order_action" },
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
api.registerTool(
|
|
165
|
+
{
|
|
166
|
+
name: "order_list",
|
|
167
|
+
label: "Order List",
|
|
168
|
+
description: "List sales or purchase orders on the A2HMarket platform.",
|
|
169
|
+
parameters: Type.Object({
|
|
170
|
+
kind: Type.Unsafe<"sales" | "purchase">({
|
|
171
|
+
type: "string",
|
|
172
|
+
enum: ["sales", "purchase"],
|
|
173
|
+
description: "Order list type: sales=as seller, purchase=as buyer",
|
|
174
|
+
}),
|
|
175
|
+
page: Type.Optional(Type.Number({ description: "Page number (1-based, default: 1)" })),
|
|
176
|
+
pageSize: Type.Optional(Type.Number({ description: "Page size (default: 10)" })),
|
|
177
|
+
status: Type.Optional(Type.String({ description: "Filter by order status" })),
|
|
178
|
+
}),
|
|
179
|
+
async execute(_toolCallId, params) {
|
|
180
|
+
const { kind, page, pageSize, status } = params as {
|
|
181
|
+
kind: "sales" | "purchase";
|
|
182
|
+
page?: number;
|
|
183
|
+
pageSize?: number;
|
|
184
|
+
status?: string;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
const client = createApiClient();
|
|
189
|
+
const result = await orderList(client, kind, {
|
|
190
|
+
page: page ?? 1,
|
|
191
|
+
pageSize: pageSize ?? 10,
|
|
192
|
+
status,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
content: [{ type: "text", text: `${kind} orders:\n${JSON.stringify(result, null, 2)}` }],
|
|
197
|
+
details: { ok: true, result },
|
|
198
|
+
};
|
|
199
|
+
} catch (err) {
|
|
200
|
+
const errMsg = String(err);
|
|
201
|
+
return {
|
|
202
|
+
content: [{ type: "text", text: `Order list failed: ${errMsg}` }],
|
|
203
|
+
details: { ok: false, error: errMsg },
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
{ name: "order_list" },
|
|
209
|
+
);
|
|
210
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
|
3
|
+
import { createApiClient } from "../api-client.js";
|
|
4
|
+
import { profileGet } from "../api/profile.js";
|
|
5
|
+
|
|
6
|
+
export function registerProfileTool(api: OpenClawPluginApi): void {
|
|
7
|
+
api.registerTool(
|
|
8
|
+
{
|
|
9
|
+
name: "profile_get",
|
|
10
|
+
label: "Profile Get",
|
|
11
|
+
description: "Get your own A2HMarket agent profile information.",
|
|
12
|
+
parameters: Type.Object({}),
|
|
13
|
+
async execute(_toolCallId, _params) {
|
|
14
|
+
try {
|
|
15
|
+
const client = createApiClient();
|
|
16
|
+
const profile = await profileGet(client);
|
|
17
|
+
|
|
18
|
+
const nickname = profile.nickname ?? "unknown";
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
content: [
|
|
22
|
+
{
|
|
23
|
+
type: "text",
|
|
24
|
+
text: `Profile (${nickname}):\n${JSON.stringify(profile, null, 2)}`,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
details: { ok: true, profile },
|
|
28
|
+
};
|
|
29
|
+
} catch (err) {
|
|
30
|
+
const errMsg = String(err);
|
|
31
|
+
return {
|
|
32
|
+
content: [{ type: "text", text: `Failed to get profile: ${errMsg}` }],
|
|
33
|
+
details: { ok: false, error: errMsg },
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
{ name: "profile_get" },
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
|
3
|
+
import { readCredentials } from "../credentials.js";
|
|
4
|
+
import { sendMessage } from "../api/send.js";
|
|
5
|
+
|
|
6
|
+
export function registerSendTool(api: OpenClawPluginApi): void {
|
|
7
|
+
api.registerTool(
|
|
8
|
+
{
|
|
9
|
+
name: "send_message",
|
|
10
|
+
label: "Send Message",
|
|
11
|
+
description:
|
|
12
|
+
"Send an A2A message to another agent on the A2HMarket platform.",
|
|
13
|
+
parameters: Type.Object({
|
|
14
|
+
targetAgentId: Type.String({
|
|
15
|
+
description: "The target agent ID (e.g. ag_xxx)",
|
|
16
|
+
}),
|
|
17
|
+
text: Type.String({
|
|
18
|
+
description: "The message text to send",
|
|
19
|
+
}),
|
|
20
|
+
attachmentUrl: Type.Optional(
|
|
21
|
+
Type.String({ description: "Optional attachment URL" }),
|
|
22
|
+
),
|
|
23
|
+
paymentQr: Type.Optional(
|
|
24
|
+
Type.String({ description: "Payment QR code image URL" }),
|
|
25
|
+
),
|
|
26
|
+
}),
|
|
27
|
+
async execute(_toolCallId, params) {
|
|
28
|
+
const { targetAgentId, text, attachmentUrl, paymentQr } = params as {
|
|
29
|
+
targetAgentId: string;
|
|
30
|
+
text: string;
|
|
31
|
+
attachmentUrl?: string;
|
|
32
|
+
paymentQr?: string;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const creds = readCredentials();
|
|
36
|
+
if (!creds) {
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: "A2HMarket not configured. Run: openclaw a2h setup",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
details: { ok: false, error: "not_configured" },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const result = await sendMessage(creds, {
|
|
50
|
+
targetAgentId,
|
|
51
|
+
text,
|
|
52
|
+
attachmentUrl,
|
|
53
|
+
paymentQr,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
content: [
|
|
58
|
+
{
|
|
59
|
+
type: "text",
|
|
60
|
+
text: `Message sent to ${targetAgentId}. Message ID: ${result.message_id}`,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
details: { ok: true, messageId: result.message_id },
|
|
64
|
+
};
|
|
65
|
+
} catch (err) {
|
|
66
|
+
const errMsg = String(err);
|
|
67
|
+
return {
|
|
68
|
+
content: [
|
|
69
|
+
{
|
|
70
|
+
type: "text",
|
|
71
|
+
text: `Failed to send message to ${targetAgentId}: ${errMsg}`,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
details: { ok: false, error: errMsg },
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{ name: "send_message" },
|
|
80
|
+
);
|
|
81
|
+
}
|