trc-8004-sdk 0.1.0b1__py3-none-any.whl
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.
- sdk/__init__.py +123 -0
- sdk/agent_protocol_client.py +180 -0
- sdk/agent_sdk.py +1549 -0
- sdk/chain_utils.py +278 -0
- sdk/cli.py +549 -0
- sdk/client.py +202 -0
- sdk/contract_adapter.py +489 -0
- sdk/exceptions.py +652 -0
- sdk/retry.py +509 -0
- sdk/signer.py +284 -0
- sdk/utils.py +163 -0
- trc_8004_sdk-0.1.0b1.dist-info/METADATA +411 -0
- trc_8004_sdk-0.1.0b1.dist-info/RECORD +16 -0
- trc_8004_sdk-0.1.0b1.dist-info/WHEEL +5 -0
- trc_8004_sdk-0.1.0b1.dist-info/entry_points.txt +2 -0
- trc_8004_sdk-0.1.0b1.dist-info/top_level.txt +1 -0
sdk/cli.py
ADDED
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
TRC-8004 CLI 工具
|
|
4
|
+
|
|
5
|
+
提供快速创建 Agent 项目的脚手架命令。
|
|
6
|
+
|
|
7
|
+
使用方式:
|
|
8
|
+
trc8004 init my-agent # 创建新 Agent 项目
|
|
9
|
+
trc8004 init my-agent --port 8200
|
|
10
|
+
trc8004 register # 注册 Agent 到链上
|
|
11
|
+
trc8004 test # 测试 Agent 连通性
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
import os
|
|
16
|
+
import sys
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# ============ 模板定义 ============
|
|
21
|
+
|
|
22
|
+
AGENT_TEMPLATE = '''#!/usr/bin/env python3
|
|
23
|
+
"""
|
|
24
|
+
{name} - 基于 TRC-8004 框架的 Agent
|
|
25
|
+
|
|
26
|
+
启动:
|
|
27
|
+
python app.py
|
|
28
|
+
|
|
29
|
+
测试:
|
|
30
|
+
curl http://localhost:{port}/.well-known/agent-card.json
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
import json
|
|
34
|
+
import os
|
|
35
|
+
import time
|
|
36
|
+
import uuid
|
|
37
|
+
from typing import Any, Dict
|
|
38
|
+
|
|
39
|
+
from fastapi import FastAPI
|
|
40
|
+
from fastapi.responses import JSONResponse
|
|
41
|
+
from agent_protocol import Agent, Step, Task, router
|
|
42
|
+
|
|
43
|
+
# ============ 配置 ============
|
|
44
|
+
|
|
45
|
+
AGENT_NAME = os.getenv("AGENT_NAME", "{name}")
|
|
46
|
+
AGENT_PORT = int(os.getenv("AGENT_PORT", "{port}"))
|
|
47
|
+
PAYMENT_ADDRESS = os.getenv("PAYMENT_ADDRESS", "TYourPaymentAddress")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# ============ Agent 实例 ============
|
|
51
|
+
|
|
52
|
+
agent = Agent()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _normalize_input(value: Any) -> Dict[str, Any]:
|
|
56
|
+
"""规范化输入"""
|
|
57
|
+
if isinstance(value, dict):
|
|
58
|
+
return value
|
|
59
|
+
if isinstance(value, str):
|
|
60
|
+
try:
|
|
61
|
+
return json.loads(value)
|
|
62
|
+
except Exception:
|
|
63
|
+
return {{"text": value}}
|
|
64
|
+
return {{}}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# ============ Agent Card ============
|
|
68
|
+
|
|
69
|
+
AGENT_CARD = {{
|
|
70
|
+
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
|
|
71
|
+
"name": AGENT_NAME,
|
|
72
|
+
"description": "{description}",
|
|
73
|
+
"version": "0.1.0",
|
|
74
|
+
"url": f"http://localhost:{{AGENT_PORT}}",
|
|
75
|
+
"endpoints": [
|
|
76
|
+
{{"name": "A2A", "endpoint": f"http://localhost:{{AGENT_PORT}}", "version": "0.3.0"}},
|
|
77
|
+
{{"name": "agentWallet", "endpoint": f"eip155:1:{{PAYMENT_ADDRESS}}"}}
|
|
78
|
+
],
|
|
79
|
+
"capabilities": {{"streaming": False, "pushNotifications": False}},
|
|
80
|
+
"defaultInputModes": ["application/json"],
|
|
81
|
+
"defaultOutputModes": ["application/json"],
|
|
82
|
+
"skills": [
|
|
83
|
+
{{
|
|
84
|
+
"id": "hello",
|
|
85
|
+
"name": "Say Hello",
|
|
86
|
+
"description": "返回问候消息",
|
|
87
|
+
"inputSchema": {{
|
|
88
|
+
"type": "object",
|
|
89
|
+
"properties": {{"name": {{"type": "string"}}}},
|
|
90
|
+
}}
|
|
91
|
+
}},
|
|
92
|
+
{{
|
|
93
|
+
"id": "echo",
|
|
94
|
+
"name": "Echo Message",
|
|
95
|
+
"description": "回显输入消息",
|
|
96
|
+
"inputSchema": {{
|
|
97
|
+
"type": "object",
|
|
98
|
+
"properties": {{"message": {{"type": "string"}}}},
|
|
99
|
+
"required": ["message"]
|
|
100
|
+
}}
|
|
101
|
+
}}
|
|
102
|
+
],
|
|
103
|
+
"tags": {tags}
|
|
104
|
+
}}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# ============ REST Endpoints ============
|
|
108
|
+
|
|
109
|
+
@router.get("/.well-known/agent-card.json")
|
|
110
|
+
def agent_card() -> JSONResponse:
|
|
111
|
+
return JSONResponse(content=AGENT_CARD)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@router.get("/health")
|
|
115
|
+
def health() -> JSONResponse:
|
|
116
|
+
return JSONResponse(content={{"status": "healthy", "agent": AGENT_NAME}})
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# ============ A2A Handlers ============
|
|
120
|
+
|
|
121
|
+
async def task_handler(task: Task) -> None:
|
|
122
|
+
print(f"📥 Task created: {{task.task_id}}")
|
|
123
|
+
await Agent.db.create_step(task_id=task.task_id)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
async def step_handler(step: Step) -> Step:
|
|
127
|
+
payload = _normalize_input(step.input)
|
|
128
|
+
skill = payload.get("skill") or payload.get("action")
|
|
129
|
+
args = payload.get("args", payload)
|
|
130
|
+
|
|
131
|
+
# ========== 在这里添加你的技能 ==========
|
|
132
|
+
|
|
133
|
+
if skill == "hello":
|
|
134
|
+
name = args.get("name", "World")
|
|
135
|
+
result = {{"message": f"Hello, {{name}}!", "timestamp": int(time.time())}}
|
|
136
|
+
step.output = json.dumps(result, ensure_ascii=False)
|
|
137
|
+
step.is_last = True
|
|
138
|
+
return step
|
|
139
|
+
|
|
140
|
+
if skill == "echo":
|
|
141
|
+
message = args.get("message", "")
|
|
142
|
+
result = {{"echo": message, "length": len(message)}}
|
|
143
|
+
step.output = json.dumps(result, ensure_ascii=False)
|
|
144
|
+
step.is_last = True
|
|
145
|
+
return step
|
|
146
|
+
|
|
147
|
+
# 默认响应
|
|
148
|
+
result = {{
|
|
149
|
+
"error": "UNKNOWN_SKILL" if skill else "NO_SKILL",
|
|
150
|
+
"available": ["hello", "echo"],
|
|
151
|
+
"usage": {{"skill": "hello", "args": {{"name": "Alice"}}}}
|
|
152
|
+
}}
|
|
153
|
+
step.output = json.dumps(result, ensure_ascii=False)
|
|
154
|
+
step.is_last = True
|
|
155
|
+
return step
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
Agent.setup_agent(task_handler, step_handler)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
if __name__ == "__main__":
|
|
162
|
+
print(f"""
|
|
163
|
+
╔═══════════════════════════════════════════════════════════╗
|
|
164
|
+
║ {name:^53} ║
|
|
165
|
+
╠═══════════════════════════════════════════════════════════╣
|
|
166
|
+
║ Port: {{AGENT_PORT}} ║
|
|
167
|
+
║ Card: http://localhost:{{AGENT_PORT}}/.well-known/agent-card.json
|
|
168
|
+
╚═══════════════════════════════════════════════════════════╝
|
|
169
|
+
""")
|
|
170
|
+
Agent.start(port=AGENT_PORT, router=router)
|
|
171
|
+
'''
|
|
172
|
+
|
|
173
|
+
PYPROJECT_TEMPLATE = '''[project]
|
|
174
|
+
name = "{name}"
|
|
175
|
+
version = "0.1.0"
|
|
176
|
+
description = "{description}"
|
|
177
|
+
requires-python = ">=3.11"
|
|
178
|
+
|
|
179
|
+
dependencies = [
|
|
180
|
+
"fastapi>=0.115.0",
|
|
181
|
+
"uvicorn[standard]>=0.30.0",
|
|
182
|
+
"agent-protocol>=1.0.0",
|
|
183
|
+
"httpx>=0.27.0",
|
|
184
|
+
"python-dotenv>=1.0.1",
|
|
185
|
+
]
|
|
186
|
+
|
|
187
|
+
[project.optional-dependencies]
|
|
188
|
+
sdk = ["trc-8004-sdk"]
|
|
189
|
+
test = ["pytest>=8.0.0"]
|
|
190
|
+
|
|
191
|
+
[tool.uv]
|
|
192
|
+
package = true
|
|
193
|
+
|
|
194
|
+
[build-system]
|
|
195
|
+
requires = ["setuptools>=68"]
|
|
196
|
+
build-backend = "setuptools.build_meta"
|
|
197
|
+
'''
|
|
198
|
+
|
|
199
|
+
ENV_TEMPLATE = '''# Agent 配置
|
|
200
|
+
AGENT_NAME={name}
|
|
201
|
+
AGENT_PORT={port}
|
|
202
|
+
PAYMENT_ADDRESS=TYourPaymentAddress
|
|
203
|
+
|
|
204
|
+
# TRC-8004 SDK 配置 (可选)
|
|
205
|
+
# TRON_RPC_URL=https://nile.trongrid.io
|
|
206
|
+
# TRON_PRIVATE_KEY=your_hex_private_key
|
|
207
|
+
# IDENTITY_REGISTRY=TIdentityRegistryAddress
|
|
208
|
+
# VALIDATION_REGISTRY=TValidationRegistryAddress
|
|
209
|
+
# REPUTATION_REGISTRY=TReputationRegistryAddress
|
|
210
|
+
|
|
211
|
+
# Central Service (可选)
|
|
212
|
+
# CENTRAL_SERVICE_URL=http://localhost:8001
|
|
213
|
+
'''
|
|
214
|
+
|
|
215
|
+
README_TEMPLATE = '''# {name}
|
|
216
|
+
|
|
217
|
+
基于 TRC-8004 框架的 Agent。
|
|
218
|
+
|
|
219
|
+
## 快速开始
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
# 安装依赖
|
|
223
|
+
uv sync # 或 pip install -e .
|
|
224
|
+
|
|
225
|
+
# 启动 Agent
|
|
226
|
+
python app.py
|
|
227
|
+
|
|
228
|
+
# 测试
|
|
229
|
+
curl http://localhost:{port}/.well-known/agent-card.json
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## 技能列表
|
|
233
|
+
|
|
234
|
+
| 技能 ID | 名称 | 描述 |
|
|
235
|
+
|---------|------|------|
|
|
236
|
+
| `hello` | Say Hello | 返回问候消息 |
|
|
237
|
+
| `echo` | Echo Message | 回显输入消息 |
|
|
238
|
+
|
|
239
|
+
## 调用示例
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
# 1. 创建任务
|
|
243
|
+
curl -X POST http://localhost:{port}/ap/v1/agent/tasks \\
|
|
244
|
+
-H "Content-Type: application/json" \\
|
|
245
|
+
-d '{{"input": {{"skill": "hello", "args": {{"name": "Alice"}}}}}}'
|
|
246
|
+
|
|
247
|
+
# 2. 执行步骤 (使用返回的 task_id)
|
|
248
|
+
curl -X POST http://localhost:{port}/ap/v1/agent/tasks/TASK_ID/steps \\
|
|
249
|
+
-H "Content-Type: application/json" \\
|
|
250
|
+
-d '{{}}'
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## 添加新技能
|
|
254
|
+
|
|
255
|
+
编辑 `app.py` 中的 `step_handler` 函数:
|
|
256
|
+
|
|
257
|
+
```python
|
|
258
|
+
if skill == "my_new_skill":
|
|
259
|
+
# 你的逻辑
|
|
260
|
+
result = {{"data": "..."}}
|
|
261
|
+
step.output = json.dumps(result)
|
|
262
|
+
step.is_last = True
|
|
263
|
+
return step
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
然后在 `AGENT_CARD["skills"]` 中添加技能声明。
|
|
267
|
+
|
|
268
|
+
## 注册到 Central Service
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
curl -X POST http://localhost:8001/admin/agents \\
|
|
272
|
+
-H "Content-Type: application/json" \\
|
|
273
|
+
-d '{{
|
|
274
|
+
"address": "{name_lower}",
|
|
275
|
+
"name": "{name}",
|
|
276
|
+
"url": "http://localhost:{port}",
|
|
277
|
+
"tags": {tags}
|
|
278
|
+
}}'
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## 链上注册 (可选)
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
from sdk import AgentSDK
|
|
285
|
+
|
|
286
|
+
sdk = AgentSDK(private_key="...", identity_registry="...")
|
|
287
|
+
tx_id = sdk.register_agent(token_uri="https://your-domain/{name_lower}.json")
|
|
288
|
+
```
|
|
289
|
+
'''
|
|
290
|
+
|
|
291
|
+
TEST_TEMPLATE = '''"""
|
|
292
|
+
{name} 单元测试
|
|
293
|
+
"""
|
|
294
|
+
|
|
295
|
+
import pytest
|
|
296
|
+
from fastapi.testclient import TestClient
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
@pytest.fixture
|
|
300
|
+
def client():
|
|
301
|
+
from app import router
|
|
302
|
+
from fastapi import FastAPI
|
|
303
|
+
app = FastAPI()
|
|
304
|
+
app.include_router(router)
|
|
305
|
+
return TestClient(app)
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def test_agent_card(client):
|
|
309
|
+
resp = client.get("/.well-known/agent-card.json")
|
|
310
|
+
assert resp.status_code == 200
|
|
311
|
+
data = resp.json()
|
|
312
|
+
assert data["name"] == "{name}"
|
|
313
|
+
assert "skills" in data
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def test_health(client):
|
|
317
|
+
resp = client.get("/health")
|
|
318
|
+
assert resp.status_code == 200
|
|
319
|
+
assert resp.json()["status"] == "healthy"
|
|
320
|
+
'''
|
|
321
|
+
|
|
322
|
+
GITIGNORE_TEMPLATE = '''__pycache__/
|
|
323
|
+
*.py[cod]
|
|
324
|
+
.venv/
|
|
325
|
+
.env
|
|
326
|
+
*.db
|
|
327
|
+
*.log
|
|
328
|
+
.pytest_cache/
|
|
329
|
+
'''
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
# ============ CLI 命令 ============
|
|
333
|
+
|
|
334
|
+
def cmd_init(args):
|
|
335
|
+
"""初始化新 Agent 项目"""
|
|
336
|
+
name = args.name
|
|
337
|
+
port = args.port
|
|
338
|
+
tags = args.tags.split(",") if args.tags else ["custom"]
|
|
339
|
+
description = args.description or f"{name} - TRC-8004 Agent"
|
|
340
|
+
|
|
341
|
+
# 创建目录
|
|
342
|
+
project_dir = Path(name.lower().replace(" ", "-").replace("_", "-"))
|
|
343
|
+
if project_dir.exists():
|
|
344
|
+
print(f"❌ 目录已存在: {project_dir}")
|
|
345
|
+
return 1
|
|
346
|
+
|
|
347
|
+
project_dir.mkdir(parents=True)
|
|
348
|
+
tests_dir = project_dir / "tests"
|
|
349
|
+
tests_dir.mkdir()
|
|
350
|
+
|
|
351
|
+
# 生成文件
|
|
352
|
+
files = {
|
|
353
|
+
"app.py": AGENT_TEMPLATE.format(
|
|
354
|
+
name=name, port=port, description=description, tags=tags
|
|
355
|
+
),
|
|
356
|
+
"pyproject.toml": PYPROJECT_TEMPLATE.format(
|
|
357
|
+
name=name.lower().replace(" ", "-"), description=description
|
|
358
|
+
),
|
|
359
|
+
".env.example": ENV_TEMPLATE.format(name=name, port=port),
|
|
360
|
+
"README.md": README_TEMPLATE.format(
|
|
361
|
+
name=name, port=port, tags=tags, name_lower=name.lower().replace(" ", "-")
|
|
362
|
+
),
|
|
363
|
+
".gitignore": GITIGNORE_TEMPLATE,
|
|
364
|
+
"tests/__init__.py": "",
|
|
365
|
+
"tests/test_agent.py": TEST_TEMPLATE.format(name=name),
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
for filename, content in files.items():
|
|
369
|
+
filepath = project_dir / filename
|
|
370
|
+
filepath.parent.mkdir(parents=True, exist_ok=True)
|
|
371
|
+
filepath.write_text(content)
|
|
372
|
+
|
|
373
|
+
print(f"""
|
|
374
|
+
✅ Agent 项目创建成功!
|
|
375
|
+
|
|
376
|
+
📁 {project_dir}/
|
|
377
|
+
├── app.py # Agent 主程序
|
|
378
|
+
├── pyproject.toml # 项目配置
|
|
379
|
+
├── .env.example # 环境变量模板
|
|
380
|
+
├── README.md # 文档
|
|
381
|
+
└── tests/ # 测试
|
|
382
|
+
|
|
383
|
+
🚀 下一步:
|
|
384
|
+
cd {project_dir}
|
|
385
|
+
cp .env.example .env
|
|
386
|
+
uv sync # 或 pip install -e .
|
|
387
|
+
python app.py
|
|
388
|
+
|
|
389
|
+
📖 文档: {project_dir}/README.md
|
|
390
|
+
""")
|
|
391
|
+
return 0
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
def cmd_test(args):
|
|
395
|
+
"""测试 Agent 连通性"""
|
|
396
|
+
import urllib.request
|
|
397
|
+
import json as json_module
|
|
398
|
+
|
|
399
|
+
url = args.url.rstrip("/")
|
|
400
|
+
|
|
401
|
+
print(f"🔍 测试 Agent: {url}")
|
|
402
|
+
|
|
403
|
+
# 测试 agent-card
|
|
404
|
+
try:
|
|
405
|
+
card_url = f"{url}/.well-known/agent-card.json"
|
|
406
|
+
with urllib.request.urlopen(card_url, timeout=5) as resp:
|
|
407
|
+
card = json_module.loads(resp.read())
|
|
408
|
+
print(f"✅ Agent Card: {card.get('name', 'Unknown')}")
|
|
409
|
+
print(f" Skills: {[s['id'] for s in card.get('skills', [])]}")
|
|
410
|
+
print(f" Tags: {card.get('tags', [])}")
|
|
411
|
+
except Exception as e:
|
|
412
|
+
print(f"❌ Agent Card 获取失败: {e}")
|
|
413
|
+
return 1
|
|
414
|
+
|
|
415
|
+
# 测试 health
|
|
416
|
+
try:
|
|
417
|
+
health_url = f"{url}/health"
|
|
418
|
+
with urllib.request.urlopen(health_url, timeout=5) as resp:
|
|
419
|
+
health = json_module.loads(resp.read())
|
|
420
|
+
print(f"✅ Health: {health.get('status', 'unknown')}")
|
|
421
|
+
except Exception as e:
|
|
422
|
+
print(f"⚠️ Health 端点不可用: {e}")
|
|
423
|
+
|
|
424
|
+
print("\n✅ Agent 连通性测试通过!")
|
|
425
|
+
return 0
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
def cmd_register(args):
|
|
429
|
+
"""注册 Agent 到链上"""
|
|
430
|
+
import json as json_module
|
|
431
|
+
|
|
432
|
+
print("🔗 注册 Agent 到链上...")
|
|
433
|
+
|
|
434
|
+
# 检查环境变量
|
|
435
|
+
required = ["TRON_PRIVATE_KEY", "IDENTITY_REGISTRY"]
|
|
436
|
+
missing = [k for k in required if not os.getenv(k)]
|
|
437
|
+
if missing:
|
|
438
|
+
print(f"❌ 缺少环境变量: {', '.join(missing)}")
|
|
439
|
+
print("\n请设置以下环境变量:")
|
|
440
|
+
print(" export TRON_PRIVATE_KEY=your_hex_private_key")
|
|
441
|
+
print(" export IDENTITY_REGISTRY=TIdentityRegistryAddress")
|
|
442
|
+
return 1
|
|
443
|
+
|
|
444
|
+
try:
|
|
445
|
+
from sdk import AgentSDK
|
|
446
|
+
except ImportError:
|
|
447
|
+
print("❌ 请先安装 SDK: pip install trc-8004-sdk")
|
|
448
|
+
return 1
|
|
449
|
+
|
|
450
|
+
sdk = AgentSDK(
|
|
451
|
+
private_key=os.getenv("TRON_PRIVATE_KEY"),
|
|
452
|
+
rpc_url=os.getenv("TRON_RPC_URL", "https://nile.trongrid.io"),
|
|
453
|
+
network=os.getenv("TRON_NETWORK", "tron:nile"),
|
|
454
|
+
identity_registry=os.getenv("IDENTITY_REGISTRY"),
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
# 加载 metadata
|
|
458
|
+
metadata = None
|
|
459
|
+
|
|
460
|
+
# 优先从 agent-card.json 加载
|
|
461
|
+
if args.card:
|
|
462
|
+
card_path = Path(args.card)
|
|
463
|
+
if not card_path.exists():
|
|
464
|
+
print(f"❌ Agent Card 文件不存在: {card_path}")
|
|
465
|
+
return 1
|
|
466
|
+
try:
|
|
467
|
+
with open(card_path) as f:
|
|
468
|
+
card = json_module.load(f)
|
|
469
|
+
metadata = AgentSDK.extract_metadata_from_card(card)
|
|
470
|
+
print(f"📋 从 Agent Card 提取 metadata:")
|
|
471
|
+
for m in metadata:
|
|
472
|
+
value_preview = m["value"][:50] + "..." if len(m["value"]) > 50 else m["value"]
|
|
473
|
+
print(f" - {m['key']}: {value_preview}")
|
|
474
|
+
except Exception as e:
|
|
475
|
+
print(f"❌ 解析 Agent Card 失败: {e}")
|
|
476
|
+
return 1
|
|
477
|
+
elif args.metadata:
|
|
478
|
+
# 从 JSON 字符串加载
|
|
479
|
+
try:
|
|
480
|
+
raw = json_module.loads(args.metadata)
|
|
481
|
+
if isinstance(raw, dict):
|
|
482
|
+
metadata = [{"key": k, "value": v} for k, v in raw.items()]
|
|
483
|
+
elif isinstance(raw, list):
|
|
484
|
+
metadata = raw
|
|
485
|
+
print(f"📋 使用自定义 metadata: {[m['key'] for m in metadata]}")
|
|
486
|
+
except Exception as e:
|
|
487
|
+
print(f"❌ 解析 metadata JSON 失败: {e}")
|
|
488
|
+
return 1
|
|
489
|
+
elif args.name:
|
|
490
|
+
# 简单模式:只设置 name
|
|
491
|
+
metadata = [{"key": "name", "value": args.name}]
|
|
492
|
+
print(f"📋 使用简单 metadata: name={args.name}")
|
|
493
|
+
|
|
494
|
+
try:
|
|
495
|
+
tx_id = sdk.register_agent(
|
|
496
|
+
token_uri=args.token_uri or "",
|
|
497
|
+
metadata=metadata,
|
|
498
|
+
)
|
|
499
|
+
print(f"\n✅ 注册成功!")
|
|
500
|
+
print(f" 交易 ID: {tx_id}")
|
|
501
|
+
if metadata:
|
|
502
|
+
print(f" Metadata 数量: {len(metadata)}")
|
|
503
|
+
except Exception as e:
|
|
504
|
+
print(f"❌ 注册失败: {e}")
|
|
505
|
+
return 1
|
|
506
|
+
|
|
507
|
+
return 0
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
def main():
|
|
511
|
+
parser = argparse.ArgumentParser(
|
|
512
|
+
prog="trc8004",
|
|
513
|
+
description="TRC-8004 CLI 工具",
|
|
514
|
+
)
|
|
515
|
+
subparsers = parser.add_subparsers(dest="command", help="可用命令")
|
|
516
|
+
|
|
517
|
+
# init 命令
|
|
518
|
+
init_parser = subparsers.add_parser("init", help="创建新 Agent 项目")
|
|
519
|
+
init_parser.add_argument("name", help="Agent 名称")
|
|
520
|
+
init_parser.add_argument("--port", "-p", type=int, default=8100, help="端口号 (默认 8100)")
|
|
521
|
+
init_parser.add_argument("--tags", "-t", help="标签,逗号分隔 (默认 custom)")
|
|
522
|
+
init_parser.add_argument("--description", "-d", help="Agent 描述")
|
|
523
|
+
|
|
524
|
+
# test 命令
|
|
525
|
+
test_parser = subparsers.add_parser("test", help="测试 Agent 连通性")
|
|
526
|
+
test_parser.add_argument("--url", "-u", default="http://localhost:8100", help="Agent URL")
|
|
527
|
+
|
|
528
|
+
# register 命令
|
|
529
|
+
reg_parser = subparsers.add_parser("register", help="注册 Agent 到链上")
|
|
530
|
+
reg_parser.add_argument("--token-uri", "-t", help="Token URI (可选)")
|
|
531
|
+
reg_parser.add_argument("--card", "-c", help="Agent Card JSON 文件路径 (自动提取 metadata)")
|
|
532
|
+
reg_parser.add_argument("--metadata", "-m", help="Metadata JSON 字符串")
|
|
533
|
+
reg_parser.add_argument("--name", "-n", help="Agent 名称 (简单模式)")
|
|
534
|
+
|
|
535
|
+
args = parser.parse_args()
|
|
536
|
+
|
|
537
|
+
if args.command == "init":
|
|
538
|
+
return cmd_init(args)
|
|
539
|
+
elif args.command == "test":
|
|
540
|
+
return cmd_test(args)
|
|
541
|
+
elif args.command == "register":
|
|
542
|
+
return cmd_register(args)
|
|
543
|
+
else:
|
|
544
|
+
parser.print_help()
|
|
545
|
+
return 0
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
if __name__ == "__main__":
|
|
549
|
+
sys.exit(main())
|