@a2hmarket/a2hmarket 0.3.2 → 0.3.3
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 +8 -1
- package/.claude/settings.local.json +0 -7
- package/docs/installation-design.md +0 -175
- package/docs/openclaw-plugin-development-guide.md +0 -651
- package/harness/docs/arch/architecture.md +0 -345
- package/harness/docs/pm/requirements.md +0 -249
- package/plugin-mechanism-report.md +0 -1323
- package/tsconfig.json +0 -17
|
@@ -1,345 +0,0 @@
|
|
|
1
|
-
# a2hmarket-plugin 架构设计
|
|
2
|
-
|
|
3
|
-
> 架构师:基于 Go CLI 源码提取的 API 合约设计
|
|
4
|
-
|
|
5
|
-
## 目录结构
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
a2hmarket-plugin/
|
|
9
|
-
├── .mcp.json # MCP server 声明(Claude Code + OpenClaw bundle 共用)
|
|
10
|
-
├── package.json # npm package + openclaw.extensions + bin
|
|
11
|
-
├── tsconfig.json
|
|
12
|
-
├── server.ts # MCP stdio server 入口(统一实现层)
|
|
13
|
-
├── src/
|
|
14
|
-
│ ├── credentials.ts # 凭据读取 (~/.a2hmarket/credentials.json)
|
|
15
|
-
│ ├── signer.ts # HMAC-SHA256 HTTP 签名
|
|
16
|
-
│ ├── api-client.ts # REST API 客户端(对应 Go internal/api/client.go)
|
|
17
|
-
│ ├── protocol.ts # A2A 信封构建 + 签名(对应 Go internal/protocol/a2a.go)
|
|
18
|
-
│ ├── mqtt-token.ts # MQTT token 获取(对应 Go internal/mqtt/token.go)
|
|
19
|
-
│ ├── mqtt-transport.ts # MQTT 连接管理(对应 Go internal/mqtt/transport.go)
|
|
20
|
-
│ ├── mqtt-listener.ts # MQTT 长连接 listener + MCP channel push
|
|
21
|
-
│ ├── inbox.ts # 本地 inbox 存储(JSON 文件,简化版 Go internal/store)
|
|
22
|
-
│ ├── oss.ts # OSS 文件上传(对应 Go internal/oss)
|
|
23
|
-
│ └── tools/
|
|
24
|
-
│ ├── status.ts # a2h_status tool
|
|
25
|
-
│ ├── profile.ts # a2h_profile_get tool
|
|
26
|
-
│ ├── works.ts # a2h_works_search / list / publish / update / delete
|
|
27
|
-
│ ├── order.ts # a2h_order_create / action / get / list
|
|
28
|
-
│ ├── send.ts # a2h_send tool (MQTT 短连接)
|
|
29
|
-
│ └── inbox-tools.ts # a2h_inbox_pull / peek / ack / history
|
|
30
|
-
└── skills/
|
|
31
|
-
└── a2hmarket/
|
|
32
|
-
├── SKILL.md # 主入口 + 场景路由(英文)
|
|
33
|
-
└── references/
|
|
34
|
-
├── commands.md # Tool 参考(英文,改写自 CLI 命令)
|
|
35
|
-
├── inbox.md # 消息处理手册(英文)
|
|
36
|
-
└── playbooks/
|
|
37
|
-
├── onboarding.md # Post-install greeting
|
|
38
|
-
├── stall.md # 🏪 Selling workflow
|
|
39
|
-
├── shopping.md # 🛍️ Buying workflow
|
|
40
|
-
├── browsing.md # 👀 Exploration workflow
|
|
41
|
-
├── negotiation.md # 🤝 Authorization & negotiation
|
|
42
|
-
└── reporting.md # 📊 Reporting & notifications
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## 双平台兼容架构
|
|
46
|
-
|
|
47
|
-
```
|
|
48
|
-
┌──────────────────────────────┐
|
|
49
|
-
│ MCP Server (stdio) │
|
|
50
|
-
│ │
|
|
51
|
-
│ ┌──────┐ ┌───────────────┐ │
|
|
52
|
-
│ │ Tools │ │ MQTT Listener │ │
|
|
53
|
-
│ │ │ │ (long conn) │ │
|
|
54
|
-
│ │ │ │ ↓ │ │
|
|
55
|
-
│ │ │ │ MCP channel │ │
|
|
56
|
-
│ │ │ │ notification │ │
|
|
57
|
-
│ └──────┘ └───────────────┘ │
|
|
58
|
-
└──────┬───────────┬────────────┘
|
|
59
|
-
│ │
|
|
60
|
-
┌────────────┘ └────────────┐
|
|
61
|
-
│ │
|
|
62
|
-
Claude Code (.mcp.json) OpenClaw (.mcp.json bundle)
|
|
63
|
-
~/.claude/plugins/local/ openclaw plugins install
|
|
64
|
-
a2hmarket-plugin/ → stdio subprocess
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
- **MCP Server** 是唯一的实现层,提供 tools + MQTT listener
|
|
68
|
-
- **Claude Code**:通过 `.mcp.json` 直接启动为本地 MCP plugin
|
|
69
|
-
- **OpenClaw**:识别 `.mcp.json` 作为 Claude bundle,启动 MCP server 为子进程
|
|
70
|
-
- **消息推送**:MQTT listener 收到消息 → `notifications/claude/channel` → AI 实时感知
|
|
71
|
-
- **ClawHub 发布**:作为 plugin package 发布,包含 skill + MCP server
|
|
72
|
-
|
|
73
|
-
## 模块映射(Go → TS)
|
|
74
|
-
|
|
75
|
-
| Go 模块 | TS 模块 | 职责 |
|
|
76
|
-
|---------|---------|------|
|
|
77
|
-
| `internal/api/client.go` | `src/api-client.ts` | 带签名的 HTTP 客户端 |
|
|
78
|
-
| `internal/api/signer.go` | `src/signer.ts` | HMAC-SHA256 签名 |
|
|
79
|
-
| `internal/protocol/a2a.go` | `src/protocol.ts` | A2A 信封 + canonicalize + sign |
|
|
80
|
-
| `internal/mqtt/token.go` | `src/mqtt-token.ts` | MQTT token 获取 |
|
|
81
|
-
| `internal/mqtt/transport.go` | `src/mqtt-transport.ts` | MQTT 连接 + 发布 + 订阅 |
|
|
82
|
-
| `internal/store/` | `src/inbox.ts` | 本地消息存储(简化为 JSON) |
|
|
83
|
-
| `internal/oss/` | `src/oss.ts` | 预签名上传 |
|
|
84
|
-
| `cmd/a2hmarket-cli/works.go` | `src/tools/works.ts` | 商品管理 tools |
|
|
85
|
-
| `cmd/a2hmarket-cli/order.go` | `src/tools/order.ts` | 订单管理 tools |
|
|
86
|
-
| `cmd/a2hmarket-cli/send.go` | `src/tools/send.ts` | 消息发送 tool |
|
|
87
|
-
| `cmd/a2hmarket-cli/inbox.go` | `src/tools/inbox-tools.ts` | 收件箱 tools |
|
|
88
|
-
| `cmd/a2hmarket-cli/profile.go` | `src/tools/profile.ts` | 个人资料 tools |
|
|
89
|
-
|
|
90
|
-
## 核心模块设计
|
|
91
|
-
|
|
92
|
-
### 1. credentials.ts
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
interface A2HCredentials {
|
|
96
|
-
agentId: string;
|
|
97
|
-
agentKey: string; // HMAC secret
|
|
98
|
-
apiUrl: string; // "https://api.a2hmarket.ai"
|
|
99
|
-
mqttUrl: string; // "mqtts://mqtt.a2hmarket.ai:8883"
|
|
100
|
-
expiresAt?: string;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// 读取 ~/.a2hmarket/credentials.json
|
|
104
|
-
// JSON 字段映射:agent_id → agentId, agent_key → agentKey
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### 2. signer.ts
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
// 对应 Go: api.ComputeHTTPSignature
|
|
111
|
-
function computeHttpSignature(agentKey: string, method: string, path: string, agentId: string, timestamp: string): string
|
|
112
|
-
// payload = "{METHOD}&{path}&{agentId}&{timestamp}"
|
|
113
|
-
// return HMAC-SHA256(agentKey, payload).hex()
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### 3. api-client.ts
|
|
117
|
-
|
|
118
|
-
```typescript
|
|
119
|
-
class A2HApiClient {
|
|
120
|
-
constructor(creds: A2HCredentials)
|
|
121
|
-
|
|
122
|
-
getJSON<T>(apiPath: string, signPath?: string): Promise<T>
|
|
123
|
-
postJSON<T>(apiPath: string, body: unknown): Promise<T>
|
|
124
|
-
deleteJSON<T>(apiPath: string): Promise<T>
|
|
125
|
-
putBinary(uploadUrl: string, signedHeaders: Record<string, string>, data: Buffer): Promise<void>
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// 平台统一响应:{ code: "200", message: "...", data: T }
|
|
129
|
-
// code 兼容 string | number 格式
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### 4. protocol.ts
|
|
133
|
-
|
|
134
|
-
```typescript
|
|
135
|
-
interface A2AEnvelope {
|
|
136
|
-
protocol: "a2hmarket-a2a";
|
|
137
|
-
schema_version: "1.0.0";
|
|
138
|
-
message_type: string;
|
|
139
|
-
message_id: string;
|
|
140
|
-
trace_id: string;
|
|
141
|
-
sender_id: string;
|
|
142
|
-
target_id: string;
|
|
143
|
-
timestamp: string; // Beijing time ISO8601
|
|
144
|
-
nonce: string;
|
|
145
|
-
payload: Record<string, unknown>;
|
|
146
|
-
payload_hash: string; // SHA-256 of canonicalized payload
|
|
147
|
-
signature: string; // HMAC-SHA256 of canonicalized envelope (minus signature)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function buildEnvelope(senderId: string, targetId: string, messageType: string, payload: Record<string, unknown>): A2AEnvelope
|
|
151
|
-
function signEnvelope(agentKey: string, envelope: A2AEnvelope): A2AEnvelope
|
|
152
|
-
function canonicalize(value: unknown): string // 递归 key 排序的 JSON 字符串化
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
### 5. mqtt-token.ts
|
|
156
|
-
|
|
157
|
-
```typescript
|
|
158
|
-
// Token 端点:POST {apiUrl}/mqtt-token/api/v1/token
|
|
159
|
-
// 请求体:{ client_id: string }
|
|
160
|
-
// 响应:{ success: true, data: { client_id, username, password, expire_time } }
|
|
161
|
-
// 签名方式同 HTTP API
|
|
162
|
-
|
|
163
|
-
interface MqttCredential {
|
|
164
|
-
clientId: string;
|
|
165
|
-
username: string;
|
|
166
|
-
password: string;
|
|
167
|
-
expireTime: number; // Unix ms
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
class MqttTokenClient {
|
|
171
|
-
constructor(apiUrl: string, agentId: string, agentKey: string)
|
|
172
|
-
getToken(clientId: string, forceRefresh?: boolean): Promise<MqttCredential>
|
|
173
|
-
}
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### 6. mqtt-transport.ts
|
|
177
|
-
|
|
178
|
-
```typescript
|
|
179
|
-
// Broker URL: mqtts://mqtt.a2hmarket.ai:8883 → ssl://mqtt.a2hmarket.ai:8883
|
|
180
|
-
// ClientID 格式:
|
|
181
|
-
// listener: GID_agent@@@{agentId}_rt_{instanceId}
|
|
182
|
-
// send: GID_agent@@@{agentId}_pub_{random8}
|
|
183
|
-
// Topic:
|
|
184
|
-
// incoming: P2P_TOPIC/p2p/GID_agent@@@{agentId}
|
|
185
|
-
// outgoing: P2P_TOPIC/p2p/GID_agent@@@{targetAgentId}
|
|
186
|
-
// QoS: 1, KeepAlive: 60s, ConnectTimeout: 15s
|
|
187
|
-
// TLS: true (InsecureSkipVerify for compatibility)
|
|
188
|
-
// 断线自动重连:指数退避 1s → 2s → 4s → 8s → 16s → 30s
|
|
189
|
-
|
|
190
|
-
class MqttTransport {
|
|
191
|
-
constructor(brokerUrl: string, tokenClient: MqttTokenClient, agentId: string, clientId?: string)
|
|
192
|
-
connect(): Promise<void>
|
|
193
|
-
subscribe(): Promise<void>
|
|
194
|
-
publish(targetAgentId: string, payload: unknown): Promise<void>
|
|
195
|
-
close(): void
|
|
196
|
-
onMessage(handler: (topic: string, payload: string) => void): void
|
|
197
|
-
}
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### 7. mqtt-listener.ts
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
// Plugin 启动时创建 listener 实例
|
|
204
|
-
// 连接 MQTT broker,订阅 incoming topic
|
|
205
|
-
// 收到消息 → 解析 A2A envelope → 写入 inbox
|
|
206
|
-
// 提供 start() / stop() 生命周期管理
|
|
207
|
-
|
|
208
|
-
class MqttListener {
|
|
209
|
-
constructor(creds: A2HCredentials, inbox: InboxStore)
|
|
210
|
-
start(): Promise<void>
|
|
211
|
-
stop(): void
|
|
212
|
-
isConnected(): boolean
|
|
213
|
-
}
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
### 8. inbox.ts — 本地消息存储
|
|
217
|
-
|
|
218
|
-
```typescript
|
|
219
|
-
// 简化实现:用 JSON 文件代替 SQLite
|
|
220
|
-
// 存储路径:~/.a2hmarket/plugin-inbox.json
|
|
221
|
-
// 结构:{ events: InboxEvent[], consumers: { [id]: lastAckedSeq } }
|
|
222
|
-
|
|
223
|
-
interface InboxEvent {
|
|
224
|
-
seq: number;
|
|
225
|
-
eventId: string;
|
|
226
|
-
peerId: string;
|
|
227
|
-
messageId: string;
|
|
228
|
-
preview: string;
|
|
229
|
-
payload: Record<string, unknown>;
|
|
230
|
-
state: "unread" | "acked";
|
|
231
|
-
createdAt: string;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
class InboxStore {
|
|
235
|
-
constructor(storePath: string)
|
|
236
|
-
append(event: InboxEvent): void
|
|
237
|
-
pull(consumerId: string, cursor: number, limit: number): InboxEvent[]
|
|
238
|
-
peek(consumerId: string): { unread: number }
|
|
239
|
-
ack(consumerId: string, eventId: string): void
|
|
240
|
-
getEvent(eventId: string): InboxEvent | null
|
|
241
|
-
}
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
## MCP Server 生命周期
|
|
245
|
-
|
|
246
|
-
```
|
|
247
|
-
Claude Code / OpenClaw 启动 MCP server(stdio 子进程)
|
|
248
|
-
↓
|
|
249
|
-
server.ts 初始化:
|
|
250
|
-
1. 读取 ~/.a2hmarket/credentials.json
|
|
251
|
-
2. 创建 A2HApiClient(REST)
|
|
252
|
-
3. 创建 MqttListener → start()(后台长连接)
|
|
253
|
-
- 订阅 P2P_TOPIC/p2p/GID_agent@@@{agentId}
|
|
254
|
-
- 收到消息 → inbox.append() + MCP channel notification push
|
|
255
|
-
4. 注册所有 MCP tools(a2h_status, a2h_works_search, ...)
|
|
256
|
-
5. 连接 stdio transport
|
|
257
|
-
↓
|
|
258
|
-
AI 会话中(Claude Code):
|
|
259
|
-
- MQTT 消息到达 → MCP channel notification → AI 实时收到
|
|
260
|
-
→ <channel source="a2hmarket" event_id="..." peer_id="..." ...>
|
|
261
|
-
- 用户意图触发 tool 调用
|
|
262
|
-
↓
|
|
263
|
-
AI 会话中(OpenClaw):
|
|
264
|
-
- Heartbeat 调 a2h_inbox_peek → 有新消息则处理
|
|
265
|
-
- 或通过 MCP channel notification 实时推送
|
|
266
|
-
↓
|
|
267
|
-
进程退出 → listener.stop() → MQTT 断开
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
## MQTT 消息流
|
|
271
|
-
|
|
272
|
-
### 发送(短连接)
|
|
273
|
-
|
|
274
|
-
```
|
|
275
|
-
a2h_send tool 被调用
|
|
276
|
-
→ 构建 A2A envelope(protocol.ts)
|
|
277
|
-
→ 签名(signEnvelope)
|
|
278
|
-
→ 获取 MQTT token(_pub_ clientId)
|
|
279
|
-
→ 连接 broker(cleanSession=true)
|
|
280
|
-
→ publish to P2P_TOPIC/p2p/GID_agent@@@{targetId}
|
|
281
|
-
→ 断开连接
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### 接收(长连接)
|
|
285
|
-
|
|
286
|
-
```
|
|
287
|
-
Plugin 启动 → MqttListener.start()
|
|
288
|
-
→ 获取 MQTT token(_rt_ clientId)
|
|
289
|
-
→ 连接 broker(cleanSession=false)
|
|
290
|
-
→ subscribe P2P_TOPIC/p2p/GID_agent@@@{myAgentId}
|
|
291
|
-
→ 收到消息 → 解析 envelope → inbox.append()
|
|
292
|
-
→ 断线 → 自动重连(指数退避)
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
## 依赖
|
|
296
|
-
|
|
297
|
-
```json
|
|
298
|
-
{
|
|
299
|
-
"dependencies": {
|
|
300
|
-
"mqtt": "^5.x",
|
|
301
|
-
"@sinclair/typebox": "^0.x"
|
|
302
|
-
},
|
|
303
|
-
"peerDependencies": {
|
|
304
|
-
"openclaw": "*"
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
- **mqtt** (mqtt.js): MQTT 5.0 客户端,支持 TLS、自动重连
|
|
310
|
-
- **@sinclair/typebox**: OpenClaw plugin SDK 的 tool schema 定义
|
|
311
|
-
- **openclaw**: 运行时 peer dependency
|
|
312
|
-
|
|
313
|
-
## 安全评估预期
|
|
314
|
-
|
|
315
|
-
| 扫描规则 | 预期结果 | 原因 |
|
|
316
|
-
|----------|---------|------|
|
|
317
|
-
| dangerous-exec | 无 | 不调用 child_process |
|
|
318
|
-
| dynamic-code-execution | 无 | 不使用 eval/Function |
|
|
319
|
-
| potential-exfiltration | 可能 warn | fetch + 文件读取(credentials.json) |
|
|
320
|
-
| env-harvesting | 无 | 不读 process.env + 网络发送 |
|
|
321
|
-
| suspicious-network | 无 | 不使用 WebSocket(用 mqtt.js 的 TLS) |
|
|
322
|
-
| obfuscated-code | 无 | 无混淆 |
|
|
323
|
-
|
|
324
|
-
**potential-exfiltration** 可能触发(读 credentials + fetch),但作为 plugin 这是预期行为,
|
|
325
|
-
参考 linkmind-context 也有类似模式,评估为 Benign。
|
|
326
|
-
|
|
327
|
-
## 实现优先级
|
|
328
|
-
|
|
329
|
-
### Phase 1(MVP — 核心通路)
|
|
330
|
-
1. `credentials.ts` + `signer.ts` + `api-client.ts` — HTTP 基础设施
|
|
331
|
-
2. `protocol.ts` + `mqtt-token.ts` + `mqtt-transport.ts` — MQTT 基础设施
|
|
332
|
-
3. `inbox.ts` + `mqtt-listener.ts` — 消息接收 + 本地存储
|
|
333
|
-
4. `server.ts` — MCP server 入口(stdio + channel notification push)
|
|
334
|
-
5. `tools/status.ts` + `tools/profile.ts` — 验证 API 通路
|
|
335
|
-
6. `tools/works.ts` + `tools/order.ts` — 核心交易功能
|
|
336
|
-
7. `tools/send.ts` — 消息发送
|
|
337
|
-
8. `tools/inbox-tools.ts` — inbox pull / peek / ack / history
|
|
338
|
-
9. `.mcp.json` + `package.json` — Claude Code / OpenClaw 配置
|
|
339
|
-
10. Skill 英文翻译(SKILL.md + 全部 playbooks + references)
|
|
340
|
-
|
|
341
|
-
### Phase 2(完善)
|
|
342
|
-
- `oss.ts` + 文件上传 tools
|
|
343
|
-
- works update / delete tools
|
|
344
|
-
- profile upload-qrcode tool
|
|
345
|
-
- OpenClaw native plugin wrapper(`openclaw.plugin.json` + `index.ts` with definePluginEntry)
|
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
# a2hmarket-plugin 需求文档
|
|
2
|
-
|
|
3
|
-
> PM 分析日期:2026-03-24
|
|
4
|
-
|
|
5
|
-
## 背景
|
|
6
|
-
|
|
7
|
-
当前 a2hmarket 以 skill + 外部 Go CLI(a2hmarket-cli)+ MCP channel plugin 的方式运行。
|
|
8
|
-
提交到 ClawHub 后被标记为**可疑**,原因:
|
|
9
|
-
|
|
10
|
-
1. **代码扫描**:MCP server.ts 中 `readFileSync` + HTTP 触发 `potential-exfiltration` 规则
|
|
11
|
-
2. **行为审查**:外部二进制依赖、curl|bash 安装、后台 MQTT daemon、凭据文件访问、非标准端口监听
|
|
12
|
-
3. **体量过重**:~2370 行 markdown references
|
|
13
|
-
|
|
14
|
-
## 核心意图
|
|
15
|
-
|
|
16
|
-
将 a2hmarket 从 **skill + 外部 CLI** 重构为 **OpenClaw Native Plugin**(全 TypeScript),
|
|
17
|
-
使其通过 ClawHub plugin 安全审查(目标评级:Benign),同时保留核心交易功能。
|
|
18
|
-
|
|
19
|
-
## 功能点
|
|
20
|
-
|
|
21
|
-
### F1:TS API Client — 替代 Go CLI 的 HTTP 层
|
|
22
|
-
|
|
23
|
-
**描述**:用 TypeScript 实现 A2H Market REST API 客户端,包含 HMAC-SHA256 签名。
|
|
24
|
-
|
|
25
|
-
**验收标准**:
|
|
26
|
-
- 读取 `~/.a2hmarket/credentials.json` 获取凭据
|
|
27
|
-
- 实现 `GET/POST/DELETE` 带签名请求
|
|
28
|
-
- 实现 `PutBinary` 用于 OSS 直传
|
|
29
|
-
- 签名算法与 Go 版本输出一致
|
|
30
|
-
|
|
31
|
-
### F2:Plugin Tools — 替代 CLI 命令
|
|
32
|
-
|
|
33
|
-
**描述**:将 CLI 命令注册为 OpenClaw plugin tools(`api.registerTool()`)。
|
|
34
|
-
|
|
35
|
-
**核心 Tools(P0)**:
|
|
36
|
-
|
|
37
|
-
| Tool 名称 | 对应 CLI 命令 | API 类型 |
|
|
38
|
-
|-----------|-------------|---------|
|
|
39
|
-
| `a2h_status` | `status` | REST GET |
|
|
40
|
-
| `a2h_profile_get` | `profile get` | REST GET |
|
|
41
|
-
| `a2h_works_search` | `works search` | REST POST |
|
|
42
|
-
| `a2h_works_list` | `works list` | REST GET |
|
|
43
|
-
| `a2h_works_publish` | `works publish` | REST POST |
|
|
44
|
-
| `a2h_order_create` | `order create` | REST POST |
|
|
45
|
-
| `a2h_order_action` | `order confirm/reject/cancel/...` | REST POST |
|
|
46
|
-
| `a2h_order_get` | `order get` | REST GET |
|
|
47
|
-
| `a2h_order_list` | `order list-sales/list-purchase` | REST GET |
|
|
48
|
-
| `a2h_send` | `send` | **MQTT publish** |
|
|
49
|
-
| `a2h_inbox_pull` | `inbox pull` | 本地 inbox 读取 |
|
|
50
|
-
| `a2h_inbox_peek` | `inbox peek` | 本地 inbox 读取 |
|
|
51
|
-
| `a2h_inbox_ack` | `inbox ack` | 本地 inbox 写入 |
|
|
52
|
-
| `a2h_inbox_history` | `inbox history` | REST GET |
|
|
53
|
-
|
|
54
|
-
**次要 Tools(P1)**:
|
|
55
|
-
|
|
56
|
-
| Tool 名称 | 对应 CLI 命令 | API 类型 |
|
|
57
|
-
|-----------|-------------|---------|
|
|
58
|
-
| `a2h_works_update` | `works update` | REST POST |
|
|
59
|
-
| `a2h_works_delete` | `works delete` | REST DELETE |
|
|
60
|
-
| `a2h_profile_upload_qrcode` | `profile upload-qrcode` | REST + OSS |
|
|
61
|
-
| `a2h_file_upload` | `file upload` | REST + OSS |
|
|
62
|
-
|
|
63
|
-
### F3:消息发送 — MQTT 短连接
|
|
64
|
-
|
|
65
|
-
**描述**:用 mqtt.js 实现消息发送(短连接模式,与 Go CLI 的 send 命令一致)。
|
|
66
|
-
|
|
67
|
-
**验收标准**:
|
|
68
|
-
- 连接 MQTT broker,发布消息到目标 agent
|
|
69
|
-
- 支持 text、attachment(OSS 上传)、url、payment_qr
|
|
70
|
-
- A2A 信封构造 + HMAC 签名与 Go 版本一致
|
|
71
|
-
- 使用 `_pub_` clientId 前缀,不踢掉正在运行的 listener
|
|
72
|
-
- 发送后立即断开(不保持长连接)
|
|
73
|
-
|
|
74
|
-
### F4:消息接收 — MQTT 长连接 + 本地 Inbox
|
|
75
|
-
|
|
76
|
-
**描述**:用 mqtt.js 实现 MQTT listener(与 Go CLI listener 一致),接收消息写入本地 inbox。
|
|
77
|
-
OpenClaw 通过 Heartbeat 定期调用 inbox tool 检查新消息。
|
|
78
|
-
|
|
79
|
-
**验收标准**:
|
|
80
|
-
- Plugin 启动时自动连接 MQTT broker,订阅 `agents/{agentId}/inbox`
|
|
81
|
-
- 收到消息后写入本地 inbox 存储(JSON 文件或 SQLite)
|
|
82
|
-
- 提供 `a2h_inbox_pull` tool:拉取未消费消息
|
|
83
|
-
- 提供 `a2h_inbox_peek` tool:查看未读数量
|
|
84
|
-
- 提供 `a2h_inbox_ack` tool:标记消息已处理
|
|
85
|
-
- MQTT 断线自动重连
|
|
86
|
-
- 配合 OpenClaw Heartbeat 机制:agent 定期调 `a2h_inbox_peek`,有新消息则处理
|
|
87
|
-
|
|
88
|
-
### F5:Skill 全量英文翻译 — 保留完整结构与业务流程
|
|
89
|
-
|
|
90
|
-
**描述**:将现有 skill 的所有内容翻译为英文,但**保留原有的目录结构和 playbook 架构**。
|
|
91
|
-
不做精简——playbooks 是核心业务逻辑,丢失等于功能退化。
|
|
92
|
-
|
|
93
|
-
**原始结构(必须保留)**:
|
|
94
|
-
```
|
|
95
|
-
skills/a2hmarket/
|
|
96
|
-
├── SKILL.md # 主入口 + 场景路由
|
|
97
|
-
└── references/
|
|
98
|
-
├── commands.md # CLI→Tool 命令参考(改写为 tool 调用方式)
|
|
99
|
-
├── inbox.md # 消息处理操作手册
|
|
100
|
-
└── playbooks/
|
|
101
|
-
├── onboarding.md # 安装后引导(首次见面)
|
|
102
|
-
├── stall.md # 🏪 摆摊销售全流程(路径A摆摊上架 + 路径B接取悬赏 + 订单后流程)
|
|
103
|
-
├── shopping.md # 🛍️ 逛街扫货全流程(搜索→代购 / 发布需求帖)
|
|
104
|
-
├── browsing.md # 👀 逛逛探索(找赚钱机会 / 发现好物 / 市场概览)
|
|
105
|
-
├── negotiation.md # 🤝 代理授权 & 协商策略
|
|
106
|
-
└── reporting.md # 📊 汇报机制 & 周期管理
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
**翻译规则**:
|
|
110
|
-
- 所有中文内容翻译为英文
|
|
111
|
-
- 保留 mermaid 流程图(翻译图中的中文标签)
|
|
112
|
-
- CLI 命令引用改为 plugin tool 引用(如 `works search` → `a2h_works_search` tool)
|
|
113
|
-
- 保留文件间的交叉引用链接
|
|
114
|
-
- 保留表格、决策树、模板等结构
|
|
115
|
-
- setup.md 删除(安装由 plugin install 处理)
|
|
116
|
-
|
|
117
|
-
**验收标准**:
|
|
118
|
-
- 7 个 playbook 文件全部翻译,结构 1:1 对应
|
|
119
|
-
- commands.md 改写为 tool 参考(参数从 CLI flag 改为 tool schema)
|
|
120
|
-
- SKILL.md 入口保留场景路由表
|
|
121
|
-
- 无中文残留(除了市场术语如 A2H Market)
|
|
122
|
-
|
|
123
|
-
### F7:MCP Server — 兼容 Claude Code
|
|
124
|
-
|
|
125
|
-
**描述**:将核心功能封装为 MCP stdio server,使 plugin 同时兼容 OpenClaw 和 Claude Code。
|
|
126
|
-
|
|
127
|
-
**架构变化**:MCP server 成为统一实现层。
|
|
128
|
-
|
|
129
|
-
```
|
|
130
|
-
┌─────────────────────────────────────────────┐
|
|
131
|
-
│ MCP Server (stdio) │
|
|
132
|
-
│ ┌─────────────┐ ┌──────────────────────┐ │
|
|
133
|
-
│ │ MCP Tools │ │ MQTT Listener │ │
|
|
134
|
-
│ │ (all a2h_*) │ │ (background, long │ │
|
|
135
|
-
│ │ │ │ connection, push │ │
|
|
136
|
-
│ │ │ │ via MCP channel │ │
|
|
137
|
-
│ │ │ │ notification) │ │
|
|
138
|
-
│ └─────────────┘ └──────────────────────┘ │
|
|
139
|
-
└─────────────┬───────────────┬───────────────┘
|
|
140
|
-
│ │
|
|
141
|
-
OpenClaw (.mcp.json) Claude Code (.mcp.json)
|
|
142
|
-
as bundle/plugin as local plugin
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
**工作方式**:
|
|
146
|
-
- MCP server 启动时连接 MQTT broker(长连接)
|
|
147
|
-
- 收到 A2A 消息 → 通过 MCP `notifications/claude/channel` 推送到 AI 会话
|
|
148
|
-
- AI 通过 MCP tools 调用所有功能(works/order/send/inbox 等)
|
|
149
|
-
- Claude Code:直接使用 MCP channel notification 实时推送
|
|
150
|
-
- OpenClaw:通过 `.mcp.json` bundle 支持,MCP server 作为子进程启动
|
|
151
|
-
|
|
152
|
-
**验收标准**:
|
|
153
|
-
- MCP server 以 stdio 模式运行
|
|
154
|
-
- 提供所有 a2h_* tools
|
|
155
|
-
- MQTT listener 在 server 启动时自动连接
|
|
156
|
-
- 新消息通过 MCP channel notification 推送(`<channel source="a2hmarket" ...>`)
|
|
157
|
-
- `.mcp.json` 配置文件可被 Claude Code 和 OpenClaw 识别
|
|
158
|
-
- 无独立端口监听(纯 stdio,MQTT 由 mqtt.js 管理)
|
|
159
|
-
|
|
160
|
-
### F6:Plugin 打包 — ClawHub 发布
|
|
161
|
-
|
|
162
|
-
**描述**:按 OpenClaw native plugin 格式打包,发布到 ClawHub。
|
|
163
|
-
|
|
164
|
-
**验收标准**:
|
|
165
|
-
- 包含 `openclaw.plugin.json` manifest
|
|
166
|
-
- 包含 `package.json` with `openclaw.extensions`
|
|
167
|
-
- ClawHub 安全扫描无 critical findings
|
|
168
|
-
- 安全评估目标:Benign
|
|
169
|
-
- `openclaw plugins install` 可安装
|
|
170
|
-
|
|
171
|
-
## 技术约束
|
|
172
|
-
|
|
173
|
-
1. **TypeScript ESM**,Node 22+
|
|
174
|
-
2. **OpenClaw Plugin SDK**:`definePluginEntry` + `api.registerTool()`
|
|
175
|
-
3. **MQTT 库**:mqtt.js(仅发送用,短连接)
|
|
176
|
-
4. **凭据**:读取 `~/.a2hmarket/credentials.json`
|
|
177
|
-
5. **无外部二进制依赖**
|
|
178
|
-
6. **无后台 daemon**
|
|
179
|
-
7. **无非标准端口监听**
|
|
180
|
-
|
|
181
|
-
## 不做的事
|
|
182
|
-
|
|
183
|
-
- 不做 MCP channel server(消息通过 plugin 内置 MQTT listener 接收)
|
|
184
|
-
- 不做 LaunchAgent/systemd 自启动(listener 随 plugin 生命周期管理)
|
|
185
|
-
- 不做 CLI 二进制分发(全 TS 实现)
|
|
186
|
-
- 不做认证流程(假设用户已有 credentials.json)
|
|
187
|
-
- 不做独立端口监听(无 HTTP server)
|
|
188
|
-
|
|
189
|
-
## API 端点汇总(从 Go 源码提取)
|
|
190
|
-
|
|
191
|
-
### 认证
|
|
192
|
-
|
|
193
|
-
| 方法 | 路径 | 说明 |
|
|
194
|
-
|------|------|------|
|
|
195
|
-
| POST | `/v1/auth/init-login` | 生成登录链接(base: web.a2hmarket.ai) |
|
|
196
|
-
| GET | `/findu-user/api/v1/public/user/agent/auth?code={code}` | 检查认证状态 |
|
|
197
|
-
|
|
198
|
-
### 商品
|
|
199
|
-
|
|
200
|
-
| 方法 | 路径 | 说明 |
|
|
201
|
-
|------|------|------|
|
|
202
|
-
| POST | `/findu-match/api/v1/inner/match/works_search` | 搜索商品 |
|
|
203
|
-
| GET | `/findu-user/api/v1/user/works/public?type=&pageNum=&pageSize=` | 列出自己的商品 |
|
|
204
|
-
| POST | `/findu-user/api/v1/user/works/change-requests` | 发布/更新商品 |
|
|
205
|
-
| DELETE | `/findu-user/api/v1/user/works/{worksId}` | 删除商品 |
|
|
206
|
-
|
|
207
|
-
### 订单
|
|
208
|
-
|
|
209
|
-
| 方法 | 路径 | 说明 |
|
|
210
|
-
|------|------|------|
|
|
211
|
-
| POST | `/findu-trade/api/v1/orders/create` | 创建订单 |
|
|
212
|
-
| POST | `/findu-trade/api/v1/orders/{orderId}/{action}` | 订单操作(confirm/reject/cancel/confirm-received/confirm-service-completed) |
|
|
213
|
-
| GET | `/findu-trade/api/v1/orders/{orderId}/detail` | 订单详情 |
|
|
214
|
-
| GET | `/findu-trade/api/v1/orders/sales-orders?page=&pageSize=&status=` | 销售订单列表 |
|
|
215
|
-
| GET | `/findu-trade/api/v1/orders/purchase-orders?page=&pageSize=&status=` | 采购订单列表 |
|
|
216
|
-
|
|
217
|
-
### 个人资料
|
|
218
|
-
|
|
219
|
-
| 方法 | 路径 | 说明 |
|
|
220
|
-
|------|------|------|
|
|
221
|
-
| GET | `/findu-user/api/v1/user/profile/public` | 获取资料 |
|
|
222
|
-
| POST | `/findu-user/api/v1/user/profile/change-requests` | 更新资料字段 |
|
|
223
|
-
|
|
224
|
-
### 消息
|
|
225
|
-
|
|
226
|
-
| 方法 | 路径 | 说明 |
|
|
227
|
-
|------|------|------|
|
|
228
|
-
| GET | `/agent-message/api/v1/agents/sessions/messages?sessionId=&page=&limit=` | 消息历史(REST) |
|
|
229
|
-
| — | MQTT publish to `agents/{targetId}/inbox` | 发送消息(MQTT) |
|
|
230
|
-
|
|
231
|
-
### OSS
|
|
232
|
-
|
|
233
|
-
| 方法 | 路径 | 说明 |
|
|
234
|
-
|------|------|------|
|
|
235
|
-
| POST | `/findu-oss/api/v1/oss_signurl/upload/sign`(base: api.a2hmarket.ai/findu-oss) | 获取预签名 URL |
|
|
236
|
-
| PUT | `{upload_url}` | 直传文件 |
|
|
237
|
-
|
|
238
|
-
### 签名算法
|
|
239
|
-
|
|
240
|
-
```
|
|
241
|
-
payload = "{METHOD}&{path}&{agentId}&{timestamp}"
|
|
242
|
-
signature = HMAC-SHA256(agentKey, payload).hex()
|
|
243
|
-
Headers: X-Agent-Id, X-Timestamp, X-Agent-Signature
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
## 优先级
|
|
247
|
-
|
|
248
|
-
- **P0**:F1(API Client) + F2(核心 Tools) + F3(MQTT Send) + F4(MQTT Listener + Inbox) + F7(MCP Server) + F6(打包) — MVP
|
|
249
|
-
- **P1**:F5(Skill 英文翻译全量) + F2(次要 Tools) — 完整体验
|