@lawrenceliang-btc/atel-sdk 1.1.17 → 1.1.19
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 +137 -119
- package/package.json +1 -1
package/bin/atel.mjs
CHANGED
|
@@ -3681,23 +3681,25 @@ ${callbackFailed}
|
|
|
3681
3681
|
if (localAction.ok && !localAction.skipped) {
|
|
3682
3682
|
// Guard: if agent hook already submitted via its own shell command during execution,
|
|
3683
3683
|
// the milestone status will have changed. Re-check before double-submitting.
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
const
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
}
|
|
3684
|
+
const guardCmd = localAction.action?.command;
|
|
3685
|
+
const needsGuard = ['milestone_rejected', 'milestone_verified', 'milestone_plan_confirmed'].includes(hookEvent)
|
|
3686
|
+
&& Array.isArray(guardCmd) && guardCmd[0] === 'atel' && guardCmd[1] === 'milestone-submit' && guardCmd[2];
|
|
3687
|
+
const guardCheck = needsGuard
|
|
3688
|
+
? fetch(`${PLATFORM_URL}/trade/v1/order/${guardCmd[2]}/milestones`, { signal: AbortSignal.timeout(8000) })
|
|
3689
|
+
.then(r => r.ok ? r.json() : null)
|
|
3690
|
+
.then(state => {
|
|
3691
|
+
if (!state) return false;
|
|
3692
|
+
const idx = Number.parseInt(String(guardCmd[3]), 10);
|
|
3693
|
+
const ms = Array.isArray(state?.milestones) ? state.milestones.find(m => m.index === idx) : null;
|
|
3694
|
+
return ms && ms.status === 'submitted';
|
|
3695
|
+
})
|
|
3696
|
+
.catch(() => false)
|
|
3697
|
+
: Promise.resolve(false);
|
|
3698
|
+
guardCheck.then(alreadySubmitted => {
|
|
3699
|
+
if (alreadySubmitted) {
|
|
3700
|
+
log({ event: 'agent_cmd_done', eventType: hookEvent, mode: 'already_submitted_by_agent', dedupeKey: hookKey });
|
|
3701
|
+
finishHook();
|
|
3702
|
+
return;
|
|
3701
3703
|
}
|
|
3702
3704
|
executeRecommendedActionDirect(hookEvent, localAction.action, hookCwd || process.cwd(), hookKey)
|
|
3703
3705
|
.then((execResult) => {
|
|
@@ -3713,6 +3715,8 @@ ${callbackFailed}
|
|
|
3713
3715
|
finishHook();
|
|
3714
3716
|
});
|
|
3715
3717
|
return;
|
|
3718
|
+
}); // guardCheck.then
|
|
3719
|
+
return;
|
|
3716
3720
|
}
|
|
3717
3721
|
|
|
3718
3722
|
log({ event: 'agent_cmd_done', eventType: hookEvent, stdout: summarizeAgentOutput(stdout, 300) });
|
|
@@ -5267,108 +5271,68 @@ async function cmdResult(taskId, resultJson) {
|
|
|
5267
5271
|
|
|
5268
5272
|
async function cmdCheck(targetDid, riskLevel, options) {
|
|
5269
5273
|
const risk = riskLevel || 'low';
|
|
5270
|
-
const chainMode = options?.chain || !!process.env.ATEL_SOLANA_RPC_URL;
|
|
5271
5274
|
const policy = loadPolicy();
|
|
5272
5275
|
const tp = policy.trustPolicy || DEFAULT_POLICY.trustPolicy;
|
|
5276
|
+
const RISK_THRESHOLDS = { low: 0, medium: 30, high: 50, critical: 75 };
|
|
5273
5277
|
|
|
5274
|
-
console.log(JSON.stringify({ event: 'checking_trust', did: targetDid, risk
|
|
5278
|
+
console.log(JSON.stringify({ event: 'checking_trust', did: targetDid, risk }));
|
|
5279
|
+
|
|
5280
|
+
// 1. Fetch agent profile from Platform (primary source of truth)
|
|
5281
|
+
let platformAgent = null;
|
|
5282
|
+
let platformScore = null;
|
|
5283
|
+
let platformReachable = true;
|
|
5284
|
+
try {
|
|
5285
|
+
const r = await fetch(`${ATEL_PLATFORM}/registry/v1/agent/${encodeURIComponent(targetDid)}`, { signal: AbortSignal.timeout(5000) });
|
|
5286
|
+
if (r.ok) {
|
|
5287
|
+
platformAgent = await r.json();
|
|
5288
|
+
platformScore = platformAgent.trustScore;
|
|
5289
|
+
}
|
|
5290
|
+
} catch {
|
|
5291
|
+
platformReachable = false;
|
|
5292
|
+
}
|
|
5275
5293
|
|
|
5276
|
-
//
|
|
5277
|
-
let
|
|
5278
|
-
let agentName = null;
|
|
5279
|
-
let peerWallets = null;
|
|
5294
|
+
// 2. Fetch trust history from Platform
|
|
5295
|
+
let trustEvents = [];
|
|
5280
5296
|
try {
|
|
5281
|
-
const r = await fetch(`${
|
|
5297
|
+
const r = await fetch(`${ATEL_PLATFORM}/registry/v1/agent/${encodeURIComponent(targetDid)}/trust-history`, { signal: AbortSignal.timeout(5000) });
|
|
5282
5298
|
if (r.ok) {
|
|
5283
5299
|
const d = await r.json();
|
|
5284
|
-
|
|
5285
|
-
agentName = d.name;
|
|
5286
|
-
if (d.wallets) peerWallets = d.wallets;
|
|
5300
|
+
trustEvents = d.events || [];
|
|
5287
5301
|
}
|
|
5288
5302
|
} catch {}
|
|
5289
5303
|
|
|
5290
|
-
//
|
|
5304
|
+
// 3. Local interaction history (secondary/fallback)
|
|
5291
5305
|
const localHistoryFile = resolve(ATEL_DIR, 'trust-history.json');
|
|
5292
5306
|
let history = {};
|
|
5293
5307
|
try { history = JSON.parse(readFileSync(localHistoryFile, 'utf-8')); } catch {}
|
|
5294
5308
|
const agentHistory = history[targetDid] || { tasks: 0, successes: 0, failures: 0, lastSeen: null, proofs: [] };
|
|
5309
|
+
const localScore = computeTrustScore(agentHistory);
|
|
5295
5310
|
|
|
5296
|
-
//
|
|
5297
|
-
let
|
|
5298
|
-
|
|
5299
|
-
const
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
const
|
|
5308
|
-
|
|
5309
|
-
}
|
|
5310
|
-
history[targetDid] = agentHistory;
|
|
5311
|
-
try { writeFileSync(localHistoryFile, JSON.stringify(history, null, 2)); } catch {}
|
|
5312
|
-
}
|
|
5313
|
-
|
|
5314
|
-
// 3b. Query peer's wallet addresses on all three chains
|
|
5315
|
-
if (peerWallets) {
|
|
5316
|
-
console.log(JSON.stringify({ event: 'querying_chain_history', wallets: peerWallets }));
|
|
5317
|
-
|
|
5318
|
-
// Solana
|
|
5319
|
-
if (peerWallets.solana) {
|
|
5320
|
-
try {
|
|
5321
|
-
const rpcUrl = process.env.ATEL_SOLANA_RPC_URL || 'https://api.mainnet-beta.solana.com';
|
|
5322
|
-
const provider = new SolanaAnchorProvider({ rpcUrl });
|
|
5323
|
-
const records = await provider.queryByWallet(peerWallets.solana, { limit: 100, filterDid: targetDid });
|
|
5324
|
-
chainResults.solana = { wallet: peerWallets.solana, records: records.length, asExecutor: records.filter(r => r.executorDid === targetDid).length, asRequester: records.filter(r => r.requesterDid === targetDid).length };
|
|
5325
|
-
chainResults.totalRecords += records.length;
|
|
5326
|
-
chainResults.matchingDid += records.length;
|
|
5327
|
-
} catch (e) { chainResults.solana = { error: e.message }; }
|
|
5328
|
-
}
|
|
5329
|
-
|
|
5330
|
-
// Base
|
|
5331
|
-
if (peerWallets.base) {
|
|
5332
|
-
try {
|
|
5333
|
-
const { BaseAnchorProvider } = await import('@lawrenceliang-btc/atel-sdk');
|
|
5334
|
-
const baseRpc = process.env.ATEL_BASE_RPC_URL || 'https://mainnet.base.org';
|
|
5335
|
-
const provider = new BaseAnchorProvider({ rpcUrl: baseRpc });
|
|
5336
|
-
const explorerApi = process.env.ATEL_BASE_EXPLORER_API || 'https://api.basescan.org/api';
|
|
5337
|
-
const apiKey = process.env.ATEL_BASE_EXPLORER_KEY;
|
|
5338
|
-
const records = await provider.queryByWallet(peerWallets.base, explorerApi, apiKey, { limit: 100, filterDid: targetDid });
|
|
5339
|
-
chainResults.base = { wallet: peerWallets.base, records: records.length, asExecutor: records.filter(r => r.executorDid === targetDid).length, asRequester: records.filter(r => r.requesterDid === targetDid).length };
|
|
5340
|
-
chainResults.totalRecords += records.length;
|
|
5341
|
-
chainResults.matchingDid += records.length;
|
|
5342
|
-
} catch (e) { chainResults.base = { error: e.message }; }
|
|
5343
|
-
}
|
|
5344
|
-
|
|
5345
|
-
// BSC
|
|
5346
|
-
if (peerWallets.bsc) {
|
|
5347
|
-
try {
|
|
5348
|
-
const { BSCAnchorProvider } = await import('@lawrenceliang-btc/atel-sdk');
|
|
5349
|
-
const bscRpc = process.env.ATEL_BSC_RPC_URL || 'https://bsc-dataseed.binance.org';
|
|
5350
|
-
const provider = new BSCAnchorProvider({ rpcUrl: bscRpc });
|
|
5351
|
-
const explorerApi = process.env.ATEL_BSC_EXPLORER_API || 'https://api.bscscan.com/api';
|
|
5352
|
-
const apiKey = process.env.ATEL_BSC_EXPLORER_KEY;
|
|
5353
|
-
const records = await provider.queryByWallet(peerWallets.bsc, explorerApi, apiKey, { limit: 100, filterDid: targetDid });
|
|
5354
|
-
chainResults.bsc = { wallet: peerWallets.bsc, records: records.length, asExecutor: records.filter(r => r.executorDid === targetDid).length, asRequester: records.filter(r => r.requesterDid === targetDid).length };
|
|
5355
|
-
chainResults.totalRecords += records.length;
|
|
5356
|
-
chainResults.matchingDid += records.length;
|
|
5357
|
-
} catch (e) { chainResults.bsc = { error: e.message }; }
|
|
5311
|
+
// 4. Local TrustGraph info (supplementary)
|
|
5312
|
+
let graphInfo = null;
|
|
5313
|
+
try {
|
|
5314
|
+
const saved = JSON.parse(readFileSync(resolve(ATEL_DIR, 'trust-graph.json'), 'utf-8'));
|
|
5315
|
+
if (saved.interactions) {
|
|
5316
|
+
const tg = new TrustGraph();
|
|
5317
|
+
for (const i of saved.interactions) tg.recordInteraction(i);
|
|
5318
|
+
const directConns = saved.interactions.filter(
|
|
5319
|
+
i => i.from === targetDid || i.to === targetDid
|
|
5320
|
+
);
|
|
5321
|
+
if (directConns.length > 0) {
|
|
5322
|
+
const stats = tg.getStats();
|
|
5323
|
+
graphInfo = { directConnections: directConns.length, stats };
|
|
5358
5324
|
}
|
|
5359
5325
|
}
|
|
5326
|
+
} catch {}
|
|
5360
5327
|
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
const computedScore = computeTrustScore(agentHistory);
|
|
5366
|
-
const trustLevel = computeTrustLevel(computedScore);
|
|
5328
|
+
// 5. Determine effective score: Platform is primary, local is fallback
|
|
5329
|
+
const effectiveScore = platformScore !== null ? platformScore : localScore;
|
|
5330
|
+
const scoreSource = platformScore !== null ? 'platform' : 'local';
|
|
5331
|
+
const trustLevel = computeTrustLevel(effectiveScore);
|
|
5367
5332
|
|
|
5368
|
-
//
|
|
5369
|
-
const threshold = tp.riskThresholds?.[risk] ?? 0;
|
|
5370
|
-
const
|
|
5371
|
-
const isNewAgent = agentHistory.tasks === 0;
|
|
5333
|
+
// 6. Apply trust policy (allow/deny decision)
|
|
5334
|
+
const threshold = RISK_THRESHOLDS[risk] ?? (tp.riskThresholds?.[risk] ?? 0);
|
|
5335
|
+
const isNewAgent = platformAgent === null && agentHistory.tasks === 0;
|
|
5372
5336
|
let decision = 'allow';
|
|
5373
5337
|
let reason = '';
|
|
5374
5338
|
|
|
@@ -5387,28 +5351,82 @@ async function cmdCheck(targetDid, riskLevel, options) {
|
|
|
5387
5351
|
reason = `Score ${effectiveScore} meets threshold ${threshold} for ${risk} risk`;
|
|
5388
5352
|
}
|
|
5389
5353
|
|
|
5354
|
+
// 7. Build human-readable output
|
|
5355
|
+
const lines = [];
|
|
5356
|
+
lines.push(`Trust Check: ${targetDid}`);
|
|
5357
|
+
if (platformAgent?.name) lines.push(` Name: ${platformAgent.name}`);
|
|
5358
|
+
lines.push(` Platform Score: ${effectiveScore} / 100${scoreSource === 'local' ? ' (fallback: local)' : ''}`);
|
|
5359
|
+
lines.push(` Decision: ${decision} (threshold: ${threshold} for ${risk} risk)`);
|
|
5360
|
+
if (reason) lines.push(` Reason: ${reason}`);
|
|
5361
|
+
|
|
5362
|
+
// Recent events from Platform
|
|
5363
|
+
if (trustEvents.length > 0) {
|
|
5364
|
+
lines.push(` Recent Events:`);
|
|
5365
|
+
for (const ev of trustEvents.slice(0, 10)) {
|
|
5366
|
+
const delta = ev.scoreDelta >= 0 ? `+${ev.scoreDelta}` : `${ev.scoreDelta}`;
|
|
5367
|
+
const date = ev.createdAt ? ev.createdAt.split('T')[0] : '';
|
|
5368
|
+
const ref = ev.referenceId || '';
|
|
5369
|
+
lines.push(` ${delta.padEnd(8)} ${ev.eventType.padEnd(22)} ${ref.padEnd(16)} ${date}`);
|
|
5370
|
+
}
|
|
5371
|
+
if (trustEvents.length > 10) lines.push(` ... and ${trustEvents.length - 10} more`);
|
|
5372
|
+
}
|
|
5373
|
+
|
|
5374
|
+
// Stats from Platform
|
|
5375
|
+
if (platformAgent?.stats) {
|
|
5376
|
+
const s = platformAgent.stats;
|
|
5377
|
+
const successPct = s.successRate != null ? `${Math.round(s.successRate * 100)}%` : 'n/a';
|
|
5378
|
+
lines.push(` Stats: ${s.totalTasks} tasks, ${successPct} success${s.avgRating ? `, avg rating: ${s.avgRating.toFixed(1)}` : ''}`);
|
|
5379
|
+
} else if (agentHistory.tasks > 0) {
|
|
5380
|
+
const successPct = agentHistory.tasks > 0 ? `${Math.round((agentHistory.successes / agentHistory.tasks) * 100)}%` : 'n/a';
|
|
5381
|
+
lines.push(` Stats: ${agentHistory.tasks} tasks, ${successPct} success (local)`);
|
|
5382
|
+
}
|
|
5383
|
+
|
|
5384
|
+
// Verified & Certification from Platform
|
|
5385
|
+
if (platformAgent) {
|
|
5386
|
+
lines.push(` Verified: ${platformAgent.verified || false}`);
|
|
5387
|
+
if (platformAgent.certification) {
|
|
5388
|
+
lines.push(` Certification: ${platformAgent.certification.level} (since ${platformAgent.certification.since})`);
|
|
5389
|
+
}
|
|
5390
|
+
if (platformAgent.boost?.active) {
|
|
5391
|
+
lines.push(` Boost: ${platformAgent.boost.tier} (active)`);
|
|
5392
|
+
}
|
|
5393
|
+
}
|
|
5394
|
+
|
|
5395
|
+
// Local TrustGraph supplementary info
|
|
5396
|
+
if (graphInfo) {
|
|
5397
|
+
lines.push(` Local Graph: ${graphInfo.directConnections} direct connection${graphInfo.directConnections !== 1 ? 's' : ''}`);
|
|
5398
|
+
}
|
|
5399
|
+
|
|
5400
|
+
// Fallback warning
|
|
5401
|
+
if (!platformReachable) {
|
|
5402
|
+
lines.push(` Warning: Platform unreachable, using local score as fallback`);
|
|
5403
|
+
}
|
|
5404
|
+
|
|
5405
|
+
// Print human-readable output
|
|
5406
|
+
console.log(lines.join('\n'));
|
|
5407
|
+
|
|
5408
|
+
// Also emit structured JSON for machine consumption
|
|
5390
5409
|
const output = {
|
|
5391
5410
|
did: targetDid,
|
|
5392
|
-
name:
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
policy: { risk, threshold, decision, reason },
|
|
5411
|
+
name: platformAgent?.name || null,
|
|
5412
|
+
score: effectiveScore,
|
|
5413
|
+
scoreSource,
|
|
5414
|
+
level: trustLevel.level,
|
|
5415
|
+
levelName: trustLevel.name,
|
|
5416
|
+
decision,
|
|
5417
|
+
risk,
|
|
5418
|
+
threshold,
|
|
5419
|
+
reason,
|
|
5420
|
+
verified: platformAgent?.verified || false,
|
|
5421
|
+
certification: platformAgent?.certification || null,
|
|
5422
|
+
stats: platformAgent?.stats || null,
|
|
5423
|
+
recentEvents: trustEvents.slice(0, 10),
|
|
5424
|
+
localGraph: graphInfo,
|
|
5425
|
+
platformReachable,
|
|
5408
5426
|
};
|
|
5409
|
-
if (
|
|
5410
|
-
|
|
5411
|
-
|
|
5427
|
+
if (localScore > 0 && scoreSource === 'platform') {
|
|
5428
|
+
output.localScore = localScore;
|
|
5429
|
+
}
|
|
5412
5430
|
console.log(JSON.stringify(output, null, 2));
|
|
5413
5431
|
}
|
|
5414
5432
|
|