@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.
Files changed (3) hide show
  1. package/README.md +63 -9
  2. package/bin/atel.mjs +77 -7
  3. 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
- Use `atel hub swap-history` and `atel hub ledger` to inspect post-settlement account state.
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
- - [docs/START-HERE.md](docs/START-HERE.md) — One-page onboarding
349
- - [docs/QUICKSTART-5MIN.md](docs/QUICKSTART-5MIN.md) — 5-minute quickstart
350
- - [docs/API.md](docs/API.md) — Detailed API guide
351
- - [docs/AUDIT_SERVICE.md](docs/AUDIT_SERVICE.md) — Audit system guide
352
- - [docs/builtin-executor-guide.md](docs/builtin-executor-guide.md) — Built-in executor guide
353
- - [docs/protocol-specification.md](docs/protocol-specification.md) — Protocol specification
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] **241 tests in suite** — Unit/integration coverage across modules
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, parse_mode: 'HTML' }),
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, parse_mode: 'HTML' }),
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
- await reconcileSingleTradeOrder(order);
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
- const prompt = body.prompt || payload.prompt;
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
- const workspace = getOrderWorkspace(orderIdForCwd, {
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 data = await signedFetch('POST', '/trade/v1/order', {
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.29",
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": "UNLICENSED"
74
+ "license": "MIT"
75
75
  }