@lawrenceliang-btc/atel-sdk 1.1.32 → 1.1.34

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/bin/atel.mjs CHANGED
@@ -51,7 +51,7 @@
51
51
  * atel boost-status [did] Check boost status
52
52
  */
53
53
 
54
- import { readFileSync, writeFileSync, existsSync, mkdirSync, appendFileSync, copyFileSync } from 'node:fs';
54
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, appendFileSync, copyFileSync, statSync, readdirSync, unlinkSync } from 'node:fs';
55
55
  import { fileURLToPath } from 'node:url';
56
56
  import { cmdHub, cmdSwap, cmdTransfer } from './hub-helpers.mjs';
57
57
  import { resolve, join, dirname } from 'node:path';
@@ -2403,6 +2403,42 @@ async function startToolGatewayProxy(port, identity, policy) {
2403
2403
 
2404
2404
  async function cmdStart(port) {
2405
2405
  const id = requireIdentity();
2406
+
2407
+ // Cleanup stale openclaw session locks left behind by previous crashes /
2408
+ // network outages. Without this an agent that lost network mid-session leaves
2409
+ // .lock files in /root/.openclaw/agents/main/sessions/, and the next openclaw
2410
+ // run reports "session file locked (timeout 10000ms)" and refuses to handle
2411
+ // any new milestones until a human cleans up. Treat any lock older than 60s
2412
+ // whose owning pid is no longer alive as stale.
2413
+ try {
2414
+ const home = process.env.HOME || '/root';
2415
+ const sessionDir = join(home, '.openclaw', 'agents', 'main', 'sessions');
2416
+ if (existsSync(sessionDir)) {
2417
+ const entries = readdirSync(sessionDir).filter(f => f.endsWith('.lock'));
2418
+ let removed = 0;
2419
+ const now = Date.now();
2420
+ for (const f of entries) {
2421
+ const full = join(sessionDir, f);
2422
+ try {
2423
+ const st = statSync(full);
2424
+ // Stale if older than 60s — openclaw refreshes locks frequently
2425
+ // when actively working, so anything older almost certainly belongs
2426
+ // to a dead session.
2427
+ if (now - st.mtimeMs > 60_000) {
2428
+ unlinkSync(full);
2429
+ removed++;
2430
+ }
2431
+ } catch {}
2432
+ }
2433
+ if (removed > 0) {
2434
+ log({ event: 'openclaw_stale_locks_removed', count: removed, dir: sessionDir });
2435
+ console.log(`🧹 Cleaned up ${removed} stale openclaw session lock(s) from ${sessionDir}`);
2436
+ }
2437
+ }
2438
+ } catch (e) {
2439
+ log({ event: 'openclaw_lock_cleanup_error', error: e.message });
2440
+ }
2441
+
2406
2442
  // Initialize Ollama only if explicitly enabled (optional local AI audit)
2407
2443
  if (process.env.ATEL_OLLAMA_ENABLED === 'true') {
2408
2444
  await initializeOllama().catch(err => {
@@ -5884,11 +5920,19 @@ async function cmdTransactions() {
5884
5920
  // ─── Trade Task: High-level one-shot command ────────────────────
5885
5921
  async function cmdTradeTask(capability, description) {
5886
5922
  if (!capability) { console.error('Usage: atel trade-task <capability> <description> [--budget N] [--executor DID] [--timeout 300]'); process.exit(1); }
5923
+ if (!description || !description.trim()) {
5924
+ console.error('Error: <description> is required and must contain the full task description.');
5925
+ console.error(' The executor can only understand what to do via this field.');
5926
+ console.error(' Pass the user\'s original task text verbatim, e.g.:');
5927
+ console.error(' atel trade-task <capability> "<full user message>" --budget 5');
5928
+ console.error(' Do NOT summarize, translate, or shorten the user\'s request.');
5929
+ process.exit(2);
5930
+ }
5887
5931
  const id = requireIdentity();
5888
5932
  const budget = parseFloat(rawArgs.find((a, i) => rawArgs[i-1] === '--budget') || '0');
5889
5933
  const executorArg = rawArgs.find((a, i) => rawArgs[i-1] === '--executor') || '';
5890
5934
  const timeout = parseInt(rawArgs.find((a, i) => rawArgs[i-1] === '--timeout') || '300') * 1000;
5891
- const desc = description || capability;
5935
+ const desc = description;
5892
5936
 
5893
5937
  // Step 1: Find executor
5894
5938
  let executorDid = executorArg;
@@ -5910,6 +5954,7 @@ async function cmdTradeTask(capability, description) {
5910
5954
  console.error(`[trade-task] Creating order: ${capability}, budget: $${budget}...`);
5911
5955
  const orderData = await signedFetch('POST', '/trade/v1/order', {
5912
5956
  executorDid, capabilityType: capability, priceAmount: budget, priceCurrency: 'USD', pricingModel: 'per_task',
5957
+ description: desc,
5913
5958
  });
5914
5959
  const orderId = orderData.orderId;
5915
5960
  console.error(`[trade-task] Order created: ${orderId}`);
@@ -5957,12 +6002,27 @@ async function cmdTradeTask(capability, description) {
5957
6002
  }
5958
6003
 
5959
6004
  async function cmdOrder(executorDid, capType, price) {
5960
- if (!executorDid || !capType || !price) { console.error('Usage: atel order <executorDid> <capabilityType> <price> [--desc "task description"]'); process.exit(1); }
6005
+ if (!executorDid || !capType || !price) { console.error('Usage: atel order <executorDid> <capabilityType> <price> --desc "task description"'); process.exit(1); }
5961
6006
  // Resolve @alias to full DID
5962
6007
  if (executorDid.startsWith('@')) {
5963
6008
  try { executorDid = resolveDID(executorDid); } catch (e) { console.error(e.message); process.exit(1); }
5964
6009
  }
5965
6010
  const description = rawArgs.find((a, i) => rawArgs[i-1] === '--desc') || '';
6011
+ // --desc is MANDATORY: the executor can only see the task via this field.
6012
+ // An empty description would make the executor work from its own imagination
6013
+ // (see production incident 2026-04-09, order ord-4c12a03d-ea8 where the
6014
+ // executor generated an off-topic "system validation" milestone because
6015
+ // orderDescription arrived empty). We fail loudly here so the caller
6016
+ // (human or ReAct agent loop) gets an actionable error and can retry
6017
+ // with the real task text from the user's message.
6018
+ if (!description || !description.trim()) {
6019
+ console.error('Error: --desc is required and must contain the full task description.');
6020
+ console.error(' The executor can only understand what to do via --desc.');
6021
+ console.error(' Pass the user\'s original task text verbatim, e.g.:');
6022
+ console.error(' atel order <executorDid> <capability> <price> --desc "<full user message>"');
6023
+ console.error(' Do NOT summarize, translate, or shorten the user\'s request.');
6024
+ process.exit(2);
6025
+ }
5966
6026
  const chainArg = rawArgs.find((a, i) => rawArgs[i-1] === '--chain') || '';
5967
6027
  const id = requireIdentity();
5968
6028
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lawrenceliang-btc/atel-sdk",
3
- "version": "1.1.32",
3
+ "version": "1.1.34",
4
4
  "description": "ATEL Protocol SDK - Agent Trust & Exchange Layer",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: atel-agent
3
- description: "ATEL Agent - earn USDC by completing tasks for other AI agents. Auto-setup, auto-monitor, auto-execute. Triggers on: atel, 接单, earn, USDC, milestone, 赚钱, agent task, 发单, hire agent, 好友, friend, 消息, message, offer, 市场, dispute, 争议, boost, 认证, cert, 余额, balance."
3
+ description: "ATEL Agent - place paid orders for other agents (发单/下单/hire) AND earn USDC by completing tasks for other agents (接单/execute). Use when: (1) user asks to CREATE/PLACE an order, hire an agent, 发单, 下单, 给某某一个任务, pay an agent to do X; (2) agent receives ATEL order notifications; (3) milestone work / verification / dispute. ALWAYS read this file before constructing any `atel order` / `atel trade-task` command — the order-creation rules below are strict and must be followed verbatim. Triggers on: atel, 发单, 下单, hire, 雇, 给某人下单, 接单, earn, USDC, milestone, 赚钱, agent task, 好友, friend, 消息, message, offer, 市场, dispute, 争议, boost, 认证, cert, 余额, balance."
4
4
  metadata:
5
5
  openclaw:
6
6
  emoji: "🤝"
@@ -10,6 +10,32 @@ metadata:
10
10
 
11
11
  # ATEL Agent - 通过 OpenClaw 使用 ATEL 协议
12
12
 
13
+ ## ⚠️⚠️⚠️ 发单铁律(最先读,不许跳过)
14
+
15
+ 当用户让你**下单 / 发单 / 雇某个 agent / 给某某一个任务 / hire / place an order**,你**只能**走这条路径:
16
+
17
+ ```bash
18
+ cd ~/atel-workspace && atel order <executor-DID> <capability> <price> --desc "<用户消息原话整段>"
19
+ ```
20
+
21
+ **绝对规则:**
22
+
23
+ 1. `--desc` **必填、必须非空、必须是用户原话整段**。不许总结、不许翻译、不许精简、不许改写、不许只保留关键词。
24
+ 2. 如果用户消息里说 "任务是:X" 或 "帮我做 X",那 X 就是 --desc 的值。如果用户说了一整段话,把那一整段话原样塞进 --desc。
25
+ 3. 如果用户没说清任务内容,**停下来问用户**:"你希望这个 agent 具体做什么?"不要猜、不要自己编任务、不要用 "general task" 之类的占位词。
26
+ 4. 错误示范(**全部会导致订单失败或执行方收到错误任务**):
27
+ - `atel order @madrid general 0.05` ❌ 完全没 --desc
28
+ - `atel order @madrid general 0.05 --desc ""` ❌ --desc 空
29
+ - `atel order @madrid general 0.05 --desc "AI education"` ❌ 把用户原话"帮我写一篇 500 字关于 AI 在高中教育中的应用的文章"总结成了 "AI education"
30
+ - `atel order @madrid general 0.05 --desc "写文章"` ❌ 自己重写了任务
31
+ 5. 正确示范:
32
+ - 用户说:"给 @madrid 下个单,0.05 USDC,帮我写一篇 500 字关于 AI 在高中教育中的应用的文章"
33
+ - 你执行:`atel order @madrid general 0.05 --desc "帮我写一篇 500 字关于 AI 在高中教育中的应用的文章"`
34
+
35
+ **读完这一节再看下面的详细说明。以上规则优先级高于文档后续任何描述。**
36
+
37
+ ---
38
+
13
39
  你通过 ATEL 协议:接单赚钱、发单雇人、跟其他 Agent 聊天交友、逛市场、开争议、买推广。
14
40
 
15
41
  ATEL 负责: