@a2hmarket/a2hmarket 0.5.0 → 0.5.2
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/package.json +1 -1
- package/skills/a2hmarket/SKILL.md +2 -0
- package/src/agent-service.ts +39 -3
- package/src/feishu-notify.ts +39 -2
package/package.json
CHANGED
|
@@ -66,6 +66,8 @@ A2H Market 是一个人类和 AI Agent 都可以使用的 AI 交易市场。你
|
|
|
66
66
|
1. **直接调用工具** — 使用 `a2h_*` 工具完成任务,不要用 web search
|
|
67
67
|
2. **用中文回复** — 除非用户用其他语言
|
|
68
68
|
3. **搜索要灵活** — 精确关键词没结果时,尝试更宽泛的词
|
|
69
|
+
4. **消息元数据** — 收到的消息末尾可能附带 `[orderId: xxx]` 等元数据,用于关联订单
|
|
70
|
+
5. **查询支付** — 用 `a2h_payment_status`(传 order_id)查询支付状态;用 `a2h_order_get`(传 order_id)查询订单详情
|
|
69
71
|
4. **按需读取 Playbook** — 进入具体场景时再读对应的操作剧本
|
|
70
72
|
|
|
71
73
|
## 场景路由:读哪个 Playbook
|
package/src/agent-service.ts
CHANGED
|
@@ -19,7 +19,7 @@ import { MqttTokenClient } from "./mqtt-token.js";
|
|
|
19
19
|
import { createSendTransport } from "./mqtt-transport.js";
|
|
20
20
|
import { buildEnvelope, signEnvelope } from "./protocol.js";
|
|
21
21
|
import { getA2HRuntime } from "./runtime.js";
|
|
22
|
-
import { sendFeishuCard, buildA2HNotifyCard } from "./feishu-notify.js";
|
|
22
|
+
import { sendFeishuCard, buildA2HNotifyCard, buildPaymentCard } from "./feishu-notify.js";
|
|
23
23
|
import { recordCardPeer } from "./reply-bridge.js";
|
|
24
24
|
|
|
25
25
|
// ── MQTT Send Helper ─────────────────────────────────────────────────────
|
|
@@ -138,6 +138,20 @@ export async function startAgentService(ctx: AgentServiceContext): Promise<void>
|
|
|
138
138
|
// ② Dispatch to OpenClaw Agent via Channel Plugin SDK
|
|
139
139
|
// Agent has full access to a2h_* tools
|
|
140
140
|
// Session is per-peer: agent:main:a2hmarket:direct:{senderId}
|
|
141
|
+
|
|
142
|
+
// Build enriched body with structured context from payload
|
|
143
|
+
let enrichedBody = event.text;
|
|
144
|
+
const meta: string[] = [];
|
|
145
|
+
if (event.payload.orderId) meta.push(`[orderId: ${event.payload.orderId}]`);
|
|
146
|
+
if (event.payload.payment_qr) meta.push(`[payment_qr: ${event.payload.payment_qr}]`);
|
|
147
|
+
if (event.payload.attachment) {
|
|
148
|
+
const att = event.payload.attachment as Record<string, unknown>;
|
|
149
|
+
meta.push(`[attachment: ${att.name ?? att.url ?? "file"}]`);
|
|
150
|
+
}
|
|
151
|
+
if (meta.length > 0) {
|
|
152
|
+
enrichedBody = `${event.text}\n\n--- 消息元数据 ---\n${meta.join("\n")}`;
|
|
153
|
+
}
|
|
154
|
+
|
|
141
155
|
try {
|
|
142
156
|
await dispatchInboundDirectDmWithRuntime({
|
|
143
157
|
cfg: ctx.cfg,
|
|
@@ -150,7 +164,7 @@ export async function startAgentService(ctx: AgentServiceContext): Promise<void>
|
|
|
150
164
|
senderAddress: `a2hmarket:${event.senderId}`,
|
|
151
165
|
recipientAddress: `a2hmarket:${creds.agentId}`,
|
|
152
166
|
conversationLabel: event.senderId,
|
|
153
|
-
rawBody:
|
|
167
|
+
rawBody: enrichedBody,
|
|
154
168
|
messageId: event.messageId,
|
|
155
169
|
timestamp: Date.now(),
|
|
156
170
|
commandAuthorized: true,
|
|
@@ -182,7 +196,29 @@ export async function startAgentService(ctx: AgentServiceContext): Promise<void>
|
|
|
182
196
|
}
|
|
183
197
|
|
|
184
198
|
// ④ Custom notification: notify human about the reply
|
|
185
|
-
|
|
199
|
+
// If reply contains a Stripe checkout URL, send a dedicated payment card
|
|
200
|
+
const paymentUrlMatch = formatted.match(/(https:\/\/checkout\.stripe\.com\S+)/);
|
|
201
|
+
if (paymentUrlMatch) {
|
|
202
|
+
const feishu = resolveFeishuConfig();
|
|
203
|
+
if (feishu) {
|
|
204
|
+
const paymentCard = buildPaymentCard({
|
|
205
|
+
peerId: event.senderId,
|
|
206
|
+
orderId: event.messageId ?? "unknown",
|
|
207
|
+
paymentUrl: paymentUrlMatch[1],
|
|
208
|
+
agentId: creds.agentId,
|
|
209
|
+
});
|
|
210
|
+
sendFeishuCard({
|
|
211
|
+
appId: feishu.appId,
|
|
212
|
+
appSecret: feishu.appSecret,
|
|
213
|
+
target: feishu.target,
|
|
214
|
+
...paymentCard,
|
|
215
|
+
})
|
|
216
|
+
.then((msgId) => notifyLog.info(`feishu payment card sent: ${msgId}`))
|
|
217
|
+
.catch((err) => notifyLog.error(`feishu payment card failed: ${err.message}`));
|
|
218
|
+
}
|
|
219
|
+
} else {
|
|
220
|
+
notifyHumanCard("reply", event.senderId, formatted.slice(0, 500), creds.agentId, notifyLog);
|
|
221
|
+
}
|
|
186
222
|
},
|
|
187
223
|
|
|
188
224
|
onRecordError: (err) => {
|
package/src/feishu-notify.ts
CHANGED
|
@@ -114,7 +114,7 @@ export async function sendFeishuCard(params: FeishuNotifyParams): Promise<string
|
|
|
114
114
|
* Build a standard A2H Market notification card.
|
|
115
115
|
*/
|
|
116
116
|
export function buildA2HNotifyCard(params: {
|
|
117
|
-
type: "inbound" | "reply" | "approval";
|
|
117
|
+
type: "inbound" | "reply" | "approval" | "payment" | "payment_complete";
|
|
118
118
|
peerId: string;
|
|
119
119
|
content: string;
|
|
120
120
|
agentId?: string;
|
|
@@ -123,14 +123,27 @@ export function buildA2HNotifyCard(params: {
|
|
|
123
123
|
inbound: "📩 A2H Market · 收到消息",
|
|
124
124
|
reply: "🤖 A2H Market · 已自动回复",
|
|
125
125
|
approval: "🔔 A2H Market · 需要确认",
|
|
126
|
+
payment: "💳 A2H Market · 待支付",
|
|
127
|
+
payment_complete: "✅ A2H Market · 支付完成",
|
|
126
128
|
};
|
|
127
129
|
|
|
128
130
|
const colors = {
|
|
129
131
|
inbound: "blue",
|
|
130
132
|
reply: "green",
|
|
131
133
|
approval: "orange",
|
|
134
|
+
payment: "orange",
|
|
135
|
+
payment_complete: "green",
|
|
132
136
|
};
|
|
133
137
|
|
|
138
|
+
// For reply cards, make payment URLs clickable
|
|
139
|
+
let displayContent = params.content;
|
|
140
|
+
if (params.type === "reply") {
|
|
141
|
+
displayContent = displayContent.replace(
|
|
142
|
+
/(https:\/\/checkout\.stripe\.com\S+)/g,
|
|
143
|
+
"[👉 点击支付]($1)",
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
134
147
|
const elements: FeishuCardElement[] = [
|
|
135
148
|
{
|
|
136
149
|
tag: "markdown",
|
|
@@ -138,7 +151,7 @@ export function buildA2HNotifyCard(params: {
|
|
|
138
151
|
},
|
|
139
152
|
{
|
|
140
153
|
tag: "markdown",
|
|
141
|
-
content:
|
|
154
|
+
content: displayContent,
|
|
142
155
|
},
|
|
143
156
|
];
|
|
144
157
|
|
|
@@ -155,3 +168,27 @@ export function buildA2HNotifyCard(params: {
|
|
|
155
168
|
elements,
|
|
156
169
|
};
|
|
157
170
|
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Build a dedicated payment card with order details and a clickable payment button.
|
|
174
|
+
*/
|
|
175
|
+
export function buildPaymentCard(params: {
|
|
176
|
+
peerId: string;
|
|
177
|
+
orderId: string;
|
|
178
|
+
amount?: number;
|
|
179
|
+
currency?: string;
|
|
180
|
+
paymentUrl: string;
|
|
181
|
+
agentId?: string;
|
|
182
|
+
}): { title: string; titleColor: string; elements: FeishuCardElement[] } {
|
|
183
|
+
return {
|
|
184
|
+
title: "💳 A2H Market · 待支付",
|
|
185
|
+
titleColor: "orange",
|
|
186
|
+
elements: [
|
|
187
|
+
{ tag: "markdown", content: `**订单**: \`${params.orderId}\`` },
|
|
188
|
+
{ tag: "markdown", content: `**金额**: ${params.amount ? (params.amount / 100).toFixed(2) : "?"} ${params.currency?.toUpperCase() ?? "USD"}` },
|
|
189
|
+
{ tag: "markdown", content: `**来自**: \`${params.peerId}\`` },
|
|
190
|
+
{ tag: "markdown", content: `---\n**[👉 点击支付](${params.paymentUrl})**` },
|
|
191
|
+
...(params.agentId ? [{ tag: "markdown", content: `\n*Agent: ${params.agentId}*` }] : []),
|
|
192
|
+
],
|
|
193
|
+
};
|
|
194
|
+
}
|