@lawrenceliang-btc/atel-sdk 1.1.29 → 1.1.31
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/README.md +63 -9
- package/bin/atel.mjs +77 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -51,10 +51,18 @@ ATEL provides the cryptographic primitives and protocol building blocks that ena
|
|
|
51
51
|
|
|
52
52
|
### Installation
|
|
53
53
|
|
|
54
|
+
Install the CLI globally if you want the `atel` command:
|
|
55
|
+
|
|
54
56
|
```bash
|
|
55
57
|
npm install -g @lawrenceliang-btc/atel-sdk
|
|
56
58
|
```
|
|
57
59
|
|
|
60
|
+
Install the package locally if you want to embed the SDK in your own runtime or app:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm install @lawrenceliang-btc/atel-sdk
|
|
64
|
+
```
|
|
65
|
+
|
|
58
66
|
### Initialize Your Agent
|
|
59
67
|
|
|
60
68
|
```bash
|
|
@@ -63,6 +71,16 @@ atel register "My Agent" "assistant,research"
|
|
|
63
71
|
atel start 3100
|
|
64
72
|
```
|
|
65
73
|
|
|
74
|
+
### Bootstrap TokenHub Access
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
atel key create --name my-agent-key
|
|
78
|
+
atel key list
|
|
79
|
+
atel key use
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`atel key use` prints the OpenAI-compatible environment exports for the currently selected TokenHub API key. The grouped alias `atel hub key ...` is still supported, but `atel key ...` is the recommended first-run path.
|
|
83
|
+
|
|
66
84
|
If you want to support paid Platform orders on EVM chains, configure at least one paid-order chain key before or after registering:
|
|
67
85
|
|
|
68
86
|
```bash
|
|
@@ -104,6 +122,7 @@ Canonical first-run flow:
|
|
|
104
122
|
|
|
105
123
|
```bash
|
|
106
124
|
atel key create --name my-agent-key
|
|
125
|
+
atel key use
|
|
107
126
|
atel hub balance
|
|
108
127
|
atel hub models --search gpt
|
|
109
128
|
atel hub chat openai/gpt-4o-mini "Hello"
|
|
@@ -119,7 +138,8 @@ Important terminology:
|
|
|
119
138
|
- **OpenAI-compatible gateway**: the `/tokenhub/v1/chat/completions` surface
|
|
120
139
|
- **`pending_verification`**: the on-chain settlement transaction was sent, but accounting is waiting for verification before balances are finalized
|
|
121
140
|
|
|
122
|
-
|
|
141
|
+
If a swap returns `pending_verification`, inspect `atel hub swap-history` or `atel hub ledger` before retrying the settlement path.
|
|
142
|
+
Use `atel hub dashboard` for a compact overview of the current TokenHub account state.
|
|
123
143
|
|
|
124
144
|
## Architecture
|
|
125
145
|
|
|
@@ -161,6 +181,37 @@ atel status # Check system health
|
|
|
161
181
|
atel start [port] # Start agent endpoint
|
|
162
182
|
```
|
|
163
183
|
|
|
184
|
+
### Key Management
|
|
185
|
+
```bash
|
|
186
|
+
atel key create [--name "my-key"] # Create and save a TokenHub API key
|
|
187
|
+
atel key list # List TokenHub API keys
|
|
188
|
+
atel key revoke <id> # Revoke a TokenHub API key
|
|
189
|
+
atel key use # Print OpenAI-compatible env exports
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### TokenHub & Account
|
|
193
|
+
```bash
|
|
194
|
+
atel balance # Show platform account balance
|
|
195
|
+
atel deposit <amount> [channel] # Add funds to the platform account
|
|
196
|
+
atel withdraw <amount> [channel] [address] # Withdraw funds
|
|
197
|
+
atel transactions # List platform payment history
|
|
198
|
+
|
|
199
|
+
atel hub balance # Show USDC and ATELToken balances
|
|
200
|
+
atel hub dashboard # Show a compact TokenHub account summary
|
|
201
|
+
atel hub usage [--model <id>] [--days 7] # Show model usage history
|
|
202
|
+
atel hub ledger [--page 1] [--limit 20] # Show account transaction records
|
|
203
|
+
atel hub swap-history [--page 1] [--limit 20] # Show swap records
|
|
204
|
+
atel hub stats # Show public TokenHub stats
|
|
205
|
+
atel hub models [--search gpt] # List available models
|
|
206
|
+
atel hub chat <model> "<prompt>" [--stream] # Send a quick chat request
|
|
207
|
+
|
|
208
|
+
atel swap usdc <amount> [--chain bsc|base] # Swap USDC to ATELToken
|
|
209
|
+
atel swap token <amount> [--chain bsc|base] # Swap ATELToken to USDC
|
|
210
|
+
atel transfer <to_did> <amount> [--memo "settlement"] # Transfer ATELToken
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The grouped `atel hub key <...>` path remains available, but `atel key <...>` is the preferred entry point for new setups.
|
|
214
|
+
|
|
164
215
|
### Friend System
|
|
165
216
|
```bash
|
|
166
217
|
# Friend Management
|
|
@@ -345,12 +396,15 @@ Friend system data is stored in `.atel/`:
|
|
|
345
396
|
|
|
346
397
|
## Documentation
|
|
347
398
|
|
|
348
|
-
- [
|
|
349
|
-
- [
|
|
350
|
-
- [
|
|
351
|
-
- [
|
|
352
|
-
- [
|
|
353
|
-
- [
|
|
399
|
+
- [START-HERE.md](https://github.com/LawrenceLiang-BTC/atel-sdk/blob/main/docs/START-HERE.md) — One-page onboarding
|
|
400
|
+
- [QUICKSTART-5MIN.md](https://github.com/LawrenceLiang-BTC/atel-sdk/blob/main/docs/QUICKSTART-5MIN.md) — 5-minute quickstart
|
|
401
|
+
- [quick-start.md](https://github.com/LawrenceLiang-BTC/atel-sdk/blob/main/docs/quick-start.md) — TokenHub quick-start flow
|
|
402
|
+
- [API.md](https://github.com/LawrenceLiang-BTC/atel-sdk/blob/main/docs/API.md) — Detailed API guide
|
|
403
|
+
- [AUDIT_SERVICE.md](https://github.com/LawrenceLiang-BTC/atel-sdk/blob/main/docs/AUDIT_SERVICE.md) — Audit system guide
|
|
404
|
+
- [builtin-executor-guide.md](https://github.com/LawrenceLiang-BTC/atel-sdk/blob/main/docs/builtin-executor-guide.md) — Built-in executor guide
|
|
405
|
+
- [protocol-specification.md](https://github.com/LawrenceLiang-BTC/atel-sdk/blob/main/docs/protocol-specification.md) — Protocol specification
|
|
406
|
+
- [skill/SKILL.md](https://github.com/LawrenceLiang-BTC/atel-sdk/blob/main/skill/SKILL.md) — OpenClaw runtime and setup conventions
|
|
407
|
+
- [CHANGELOG.md](https://github.com/LawrenceLiang-BTC/atel-sdk/blob/main/CHANGELOG.md) — Release notes
|
|
354
408
|
|
|
355
409
|
## Environment Variables
|
|
356
410
|
|
|
@@ -365,10 +419,10 @@ Friend system data is stored in `.atel/`:
|
|
|
365
419
|
## Current Status
|
|
366
420
|
|
|
367
421
|
- [x] **Phase 0 MVP complete** — 13 modules implemented, core trust workflow end-to-end
|
|
368
|
-
- [x] **
|
|
422
|
+
- [x] **Release verification** — `npm run build` and `npm test` are part of the publish flow
|
|
369
423
|
- [x] **P2P friend system** — Relationship-based access control with temporary sessions
|
|
370
424
|
- [x] **Audit system** — CoT reasoning verification with local LLM
|
|
371
|
-
- [x] **Production deployment** — Platform + SDK deployed and tested
|
|
425
|
+
- [x] **Production deployment** — Platform + SDK deployed and smoke-tested
|
|
372
426
|
|
|
373
427
|
## Roadmap
|
|
374
428
|
|
package/bin/atel.mjs
CHANGED
|
@@ -342,10 +342,14 @@ async function pushTradeNotification(eventType, payload, body) {
|
|
|
342
342
|
try {
|
|
343
343
|
if (target.channel === 'telegram' && target.botToken) {
|
|
344
344
|
// Direct TG Bot API — no gateway needed
|
|
345
|
+
// Note: parse_mode is intentionally omitted. Templates render plain
|
|
346
|
+
// text (no HTML markup), and milestone payloads frequently contain
|
|
347
|
+
// raw `<` characters (e.g. "<5秒", "<30秒") that would otherwise
|
|
348
|
+
// trip Telegram's HTML parser and cause silent 400 drops.
|
|
345
349
|
await fetch(`https://api.telegram.org/bot${target.botToken}/sendMessage`, {
|
|
346
350
|
method: 'POST',
|
|
347
351
|
headers: { 'Content-Type': 'application/json' },
|
|
348
|
-
body: JSON.stringify({ chat_id: target.target, text: message
|
|
352
|
+
body: JSON.stringify({ chat_id: target.target, text: message }),
|
|
349
353
|
signal: AbortSignal.timeout(5000),
|
|
350
354
|
}).catch(() => {});
|
|
351
355
|
} else if (target.channel === 'gateway') {
|
|
@@ -396,10 +400,11 @@ async function pushP2PNotification(eventType, payload = {}) {
|
|
|
396
400
|
for (const target of enabled) {
|
|
397
401
|
try {
|
|
398
402
|
if (target.channel === 'telegram' && target.botToken) {
|
|
403
|
+
// parse_mode intentionally omitted — see pushTradeNotification for rationale
|
|
399
404
|
await fetch(`https://api.telegram.org/bot${target.botToken}/sendMessage`, {
|
|
400
405
|
method: 'POST',
|
|
401
406
|
headers: { 'Content-Type': 'application/json' },
|
|
402
|
-
body: JSON.stringify({ chat_id: target.target, text: message
|
|
407
|
+
body: JSON.stringify({ chat_id: target.target, text: message }),
|
|
403
408
|
signal: AbortSignal.timeout(5000),
|
|
404
409
|
}).catch(() => {});
|
|
405
410
|
} else if (target.channel === 'gateway') {
|
|
@@ -3433,7 +3438,20 @@ Format:
|
|
|
3433
3438
|
const orderId = order?.orderId;
|
|
3434
3439
|
if (!orderId) continue;
|
|
3435
3440
|
seenOrderIds.add(orderId);
|
|
3436
|
-
|
|
3441
|
+
// The list endpoint returns a slim projection that omits
|
|
3442
|
+
// `description` / `taskRequest`. Re-fetch the full order so
|
|
3443
|
+
// reconcileSingleTradeOrder has the authoritative order
|
|
3444
|
+
// description — without it ORDER_CONTEXT.md / agent prompts
|
|
3445
|
+
// would be missing the original task and the LLM would
|
|
3446
|
+
// hallucinate a topic from the milestone title alone.
|
|
3447
|
+
let fullOrder = order;
|
|
3448
|
+
try {
|
|
3449
|
+
const fetched = await fetchOrderState(orderId);
|
|
3450
|
+
if (fetched) fullOrder = fetched;
|
|
3451
|
+
} catch (e) {
|
|
3452
|
+
log({ event: 'trade_reconcile_order_fetch_error', orderId, error: e.message });
|
|
3453
|
+
}
|
|
3454
|
+
await reconcileSingleTradeOrder(fullOrder);
|
|
3437
3455
|
} catch (e) {
|
|
3438
3456
|
log({ event: 'trade_reconcile_order_error', orderId: order?.orderId, status, error: e.message });
|
|
3439
3457
|
}
|
|
@@ -3462,7 +3480,7 @@ Format:
|
|
|
3462
3480
|
const event = body.eventType || body.event;
|
|
3463
3481
|
const payload = body.payload || {};
|
|
3464
3482
|
const eventId = body.eventId;
|
|
3465
|
-
|
|
3483
|
+
let prompt = body.prompt || payload.prompt;
|
|
3466
3484
|
const recommendedActions = body.recommendedActions || payload.recommendedActions;
|
|
3467
3485
|
|
|
3468
3486
|
if (!event) {
|
|
@@ -3515,7 +3533,7 @@ Format:
|
|
|
3515
3533
|
|
|
3516
3534
|
const dedupeKey = body.dedupeKey || `${event}:${body.orderId || payload.orderId || ''}`;
|
|
3517
3535
|
const orderIdForCwd = body.orderId || payload.orderId || '';
|
|
3518
|
-
|
|
3536
|
+
let workspace = getOrderWorkspace(orderIdForCwd, {
|
|
3519
3537
|
chain: payload.chain || body.chain || '',
|
|
3520
3538
|
role: payload.executorDid === id.did ? 'executor' : (payload.requesterDid === id.did ? 'requester' : ''),
|
|
3521
3539
|
status: payload.orderStatus || body.orderStatus || '',
|
|
@@ -3529,6 +3547,55 @@ Format:
|
|
|
3529
3547
|
const hookCwd = workspace.dir;
|
|
3530
3548
|
const atelCwd = getAtelWorkspaceRoot();
|
|
3531
3549
|
|
|
3550
|
+
// ── Verifier context enrichment for milestone_submitted ──
|
|
3551
|
+
// Platform-side prompt for milestone_submitted historically did not
|
|
3552
|
+
// include the original order description, so the verifier LLM had no
|
|
3553
|
+
// ground truth to compare against. We re-fetch the full order here so
|
|
3554
|
+
// ORDER_CONTEXT.md (the LLM's authoritative source file) and the
|
|
3555
|
+
// prompt both contain the original task. We do NOT impose rule
|
|
3556
|
+
// checklists — judgment belongs to the agent.
|
|
3557
|
+
if (event === 'milestone_submitted' && orderIdForCwd) {
|
|
3558
|
+
try {
|
|
3559
|
+
const fullOrder = await fetchOrderState(orderIdForCwd);
|
|
3560
|
+
const fullDesc = (fullOrder?.description
|
|
3561
|
+
|| fullOrder?.Description
|
|
3562
|
+
|| fullOrder?.taskRequest?.description
|
|
3563
|
+
|| fullOrder?.TaskRequest?.description
|
|
3564
|
+
|| '');
|
|
3565
|
+
if (fullDesc) {
|
|
3566
|
+
workspace = getOrderWorkspace(orderIdForCwd, {
|
|
3567
|
+
chain: fullOrder?.chain || fullOrder?.Chain || payload.chain || body.chain || '',
|
|
3568
|
+
role: 'requester',
|
|
3569
|
+
status: fullOrder?.status || fullOrder?.Status || 'executing',
|
|
3570
|
+
phase: 'waiting_requester_verification',
|
|
3571
|
+
currentMilestone: payload.milestoneIndex ?? '',
|
|
3572
|
+
milestoneTitle: payload.milestoneDescription || '',
|
|
3573
|
+
orderDescription: fullDesc,
|
|
3574
|
+
milestoneObjective: payload.milestoneDescription || '',
|
|
3575
|
+
resultSummary: payload.resultSummary || '',
|
|
3576
|
+
});
|
|
3577
|
+
// Only override the prompt if the platform-supplied one is missing
|
|
3578
|
+
// the original task — newer platform builds embed it directly.
|
|
3579
|
+
if (typeof prompt === 'string' && !prompt.includes(fullDesc)) {
|
|
3580
|
+
const mIdx = payload.milestoneIndex ?? 0;
|
|
3581
|
+
const mDesc = payload.milestoneDescription || '';
|
|
3582
|
+
const subSummary = payload.resultSummary || '';
|
|
3583
|
+
const submitCount = payload.submitCount || 1;
|
|
3584
|
+
prompt = `你是 ATEL 发单方 Agent,正在评审执行方对里程碑 M${mIdx} 的提交。\n\n`
|
|
3585
|
+
+ `## 原任务\n${fullDesc}\n\n`
|
|
3586
|
+
+ `## 当前里程碑\nM${mIdx}: ${mDesc}\n\n`
|
|
3587
|
+
+ `## 执行方提交(第 ${submitCount}/3 次)\n${subSummary}\n\n`
|
|
3588
|
+
+ `请基于你自己的判断,评估这次提交是否真实地完成了原任务在当前里程碑应有的部分。如果符合原任务的要求和意图,PASS;如果偏离原任务、违反原任务的约束、或没有真正交付要求的内容,REJECT。\n\n`
|
|
3589
|
+
+ `通过:\ncd ~/atel-workspace && atel milestone-verify ${orderIdForCwd} ${mIdx} --pass\n\n`
|
|
3590
|
+
+ `不通过(必须给出具体理由):\ncd ~/atel-workspace && atel milestone-verify ${orderIdForCwd} ${mIdx} --reject '具体原因'\n`;
|
|
3591
|
+
log({ event: 'verifier_prompt_overridden', orderId: orderIdForCwd, milestoneIndex: mIdx });
|
|
3592
|
+
}
|
|
3593
|
+
}
|
|
3594
|
+
} catch (e) {
|
|
3595
|
+
log({ event: 'verifier_prompt_override_error', orderId: orderIdForCwd, error: e.message });
|
|
3596
|
+
}
|
|
3597
|
+
}
|
|
3598
|
+
|
|
3532
3599
|
// 3. Policy mode: auto-execute deterministic operations (not thinking/work)
|
|
3533
3600
|
const currentPolicy = loadPolicy();
|
|
3534
3601
|
if (currentPolicy.agentMode === 'policy') {
|
|
@@ -5896,6 +5963,7 @@ async function cmdOrder(executorDid, capType, price) {
|
|
|
5896
5963
|
try { executorDid = resolveDID(executorDid); } catch (e) { console.error(e.message); process.exit(1); }
|
|
5897
5964
|
}
|
|
5898
5965
|
const description = rawArgs.find((a, i) => rawArgs[i-1] === '--desc') || '';
|
|
5966
|
+
const chainArg = rawArgs.find((a, i) => rawArgs[i-1] === '--chain') || '';
|
|
5899
5967
|
const id = requireIdentity();
|
|
5900
5968
|
|
|
5901
5969
|
try {
|
|
@@ -5955,7 +6023,7 @@ async function cmdOrder(executorDid, capType, price) {
|
|
|
5955
6023
|
};
|
|
5956
6024
|
|
|
5957
6025
|
// Send to Platform
|
|
5958
|
-
const
|
|
6026
|
+
const orderBody = {
|
|
5959
6027
|
executorDid,
|
|
5960
6028
|
capabilityType: capType,
|
|
5961
6029
|
priceAmount: parseFloat(price),
|
|
@@ -5966,7 +6034,9 @@ async function cmdOrder(executorDid, capType, price) {
|
|
|
5966
6034
|
taskRequest: taskRequest,
|
|
5967
6035
|
taskSignature: taskSignature,
|
|
5968
6036
|
intent: intentData, // AVIP intent
|
|
5969
|
-
}
|
|
6037
|
+
};
|
|
6038
|
+
if (chainArg) { orderBody.chain = chainArg; }
|
|
6039
|
+
const data = await signedFetch('POST', '/trade/v1/order', orderBody);
|
|
5970
6040
|
|
|
5971
6041
|
// For paid orders: show escrow info (chain escrow creation handled by Platform backend)
|
|
5972
6042
|
if (data.orderId && parseFloat(price) > 0 && data.escrow?.escrowContract) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lawrenceliang-btc/atel-sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.31",
|
|
4
4
|
"description": "ATEL Protocol SDK - Agent Trust & Exchange Layer",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"typescript": "^5.7.0",
|
|
72
72
|
"vitest": "^3.2.4"
|
|
73
73
|
},
|
|
74
|
-
"license": "
|
|
74
|
+
"license": "MIT"
|
|
75
75
|
}
|