chainlesschain 0.51.0 → 0.66.0
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/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AppLayout-Rvi759IS.js → AppLayout-6SPt_8Y_.js} +1 -1
- package/src/assets/web-panel/assets/{Dashboard-DBhFxXYQ.js → Dashboard-Br7kCwKJ.js} +2 -2
- package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +1 -0
- package/src/assets/web-panel/assets/{index-uL0cZ8N_.js → index-tN-8TosE.js} +2 -2
- package/src/assets/web-panel/index.html +2 -2
- package/src/commands/agent-network.js +785 -0
- package/src/commands/automation.js +654 -0
- package/src/commands/dao.js +565 -0
- package/src/commands/did-v2.js +620 -0
- package/src/commands/economy.js +578 -0
- package/src/commands/evolution.js +391 -0
- package/src/commands/hmemory.js +442 -0
- package/src/commands/perf.js +433 -0
- package/src/commands/pipeline.js +449 -0
- package/src/commands/plugin-ecosystem.js +517 -0
- package/src/commands/sandbox.js +401 -0
- package/src/commands/social.js +311 -0
- package/src/commands/sso.js +798 -0
- package/src/commands/workflow.js +320 -0
- package/src/commands/zkp.js +227 -1
- package/src/index.js +21 -0
- package/src/lib/agent-economy.js +479 -0
- package/src/lib/agent-network.js +1121 -0
- package/src/lib/automation-engine.js +948 -0
- package/src/lib/dao-governance.js +569 -0
- package/src/lib/did-v2-manager.js +1127 -0
- package/src/lib/evolution-system.js +453 -0
- package/src/lib/hierarchical-memory.js +481 -0
- package/src/lib/perf-tuning.js +734 -0
- package/src/lib/pipeline-orchestrator.js +928 -0
- package/src/lib/plugin-ecosystem.js +1109 -0
- package/src/lib/sandbox-v2.js +306 -0
- package/src/lib/social-graph-analytics.js +707 -0
- package/src/lib/sso-manager.js +841 -0
- package/src/lib/workflow-engine.js +454 -1
- package/src/lib/zkp-engine.js +249 -20
- package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +0 -1
package/src/commands/economy.js
CHANGED
|
@@ -21,6 +21,31 @@ import {
|
|
|
21
21
|
recordContribution,
|
|
22
22
|
getContributions,
|
|
23
23
|
distributeRevenue,
|
|
24
|
+
// Phase 85 V2
|
|
25
|
+
PAYMENT_TYPE,
|
|
26
|
+
CHANNEL_STATUS,
|
|
27
|
+
RESOURCE_TYPE,
|
|
28
|
+
NFT_STATUS,
|
|
29
|
+
priceServiceV2,
|
|
30
|
+
getPriceModel,
|
|
31
|
+
payV2,
|
|
32
|
+
openChannelV2,
|
|
33
|
+
activateChannel,
|
|
34
|
+
initiateSettlement,
|
|
35
|
+
closeChannelV2,
|
|
36
|
+
disputeChannel,
|
|
37
|
+
listChannelsV2,
|
|
38
|
+
listResourceV2,
|
|
39
|
+
mintNFTV2,
|
|
40
|
+
listNFT,
|
|
41
|
+
buyNFT,
|
|
42
|
+
burnNFT,
|
|
43
|
+
getNFTStatus,
|
|
44
|
+
recordTaskContribution,
|
|
45
|
+
getTaskContributions,
|
|
46
|
+
distributeRevenueV2,
|
|
47
|
+
listDistributions,
|
|
48
|
+
getEconomyStatsV2,
|
|
24
49
|
} from "../lib/agent-economy.js";
|
|
25
50
|
|
|
26
51
|
export function registerEconomyCommand(program) {
|
|
@@ -372,4 +397,557 @@ export function registerEconomyCommand(program) {
|
|
|
372
397
|
process.exit(1);
|
|
373
398
|
}
|
|
374
399
|
});
|
|
400
|
+
|
|
401
|
+
// ═════════════════════════════════════════════════════════════════
|
|
402
|
+
// Phase 85 — Agent Economy 2.0 subcommands
|
|
403
|
+
// ═════════════════════════════════════════════════════════════════
|
|
404
|
+
|
|
405
|
+
economy
|
|
406
|
+
.command("payment-types")
|
|
407
|
+
.description("List PAYMENT_TYPE enum values (Phase 85)")
|
|
408
|
+
.option("--json", "Output as JSON")
|
|
409
|
+
.action((options) => {
|
|
410
|
+
const v = Object.values(PAYMENT_TYPE);
|
|
411
|
+
if (options.json) console.log(JSON.stringify(v, null, 2));
|
|
412
|
+
else v.forEach((x) => logger.log(` ${chalk.cyan(x)}`));
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
economy
|
|
416
|
+
.command("channel-statuses")
|
|
417
|
+
.description("List CHANNEL_STATUS enum values (Phase 85)")
|
|
418
|
+
.option("--json", "Output as JSON")
|
|
419
|
+
.action((options) => {
|
|
420
|
+
const v = Object.values(CHANNEL_STATUS);
|
|
421
|
+
if (options.json) console.log(JSON.stringify(v, null, 2));
|
|
422
|
+
else v.forEach((x) => logger.log(` ${chalk.cyan(x)}`));
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
economy
|
|
426
|
+
.command("resource-types")
|
|
427
|
+
.description("List RESOURCE_TYPE enum values (Phase 85)")
|
|
428
|
+
.option("--json", "Output as JSON")
|
|
429
|
+
.action((options) => {
|
|
430
|
+
const v = Object.values(RESOURCE_TYPE);
|
|
431
|
+
if (options.json) console.log(JSON.stringify(v, null, 2));
|
|
432
|
+
else v.forEach((x) => logger.log(` ${chalk.cyan(x)}`));
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
economy
|
|
436
|
+
.command("nft-statuses")
|
|
437
|
+
.description("List NFT_STATUS enum values (Phase 85)")
|
|
438
|
+
.option("--json", "Output as JSON")
|
|
439
|
+
.action((options) => {
|
|
440
|
+
const v = Object.values(NFT_STATUS);
|
|
441
|
+
if (options.json) console.log(JSON.stringify(v, null, 2));
|
|
442
|
+
else v.forEach((x) => logger.log(` ${chalk.cyan(x)}`));
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
economy
|
|
446
|
+
.command("price-v2")
|
|
447
|
+
.description("Set a service price with payment-type model (Phase 85)")
|
|
448
|
+
.argument("<service-id>", "Service ID")
|
|
449
|
+
.argument("<payment-type>", "per_call|per_token|per_minute|flat_rate")
|
|
450
|
+
.argument("<rate>", "Unit rate")
|
|
451
|
+
.option("--json", "Output as JSON")
|
|
452
|
+
.action(async (serviceId, paymentType, rate, options) => {
|
|
453
|
+
try {
|
|
454
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
455
|
+
const db = ctx.db.getDatabase();
|
|
456
|
+
const m = priceServiceV2(db, {
|
|
457
|
+
serviceId,
|
|
458
|
+
paymentType,
|
|
459
|
+
rate: parseFloat(rate),
|
|
460
|
+
});
|
|
461
|
+
if (options.json) console.log(JSON.stringify(m, null, 2));
|
|
462
|
+
else
|
|
463
|
+
logger.log(
|
|
464
|
+
`${chalk.green("✓")} priced ${chalk.cyan(serviceId)} as ${paymentType}@${rate}`,
|
|
465
|
+
);
|
|
466
|
+
await shutdown();
|
|
467
|
+
} catch (err) {
|
|
468
|
+
logger.error(`Failed: ${err.message}`);
|
|
469
|
+
process.exit(1);
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
economy
|
|
474
|
+
.command("price-get")
|
|
475
|
+
.description("Get a service's price model (Phase 85)")
|
|
476
|
+
.argument("<service-id>", "Service ID")
|
|
477
|
+
.option("--json", "Output as JSON")
|
|
478
|
+
.action(async (serviceId, options) => {
|
|
479
|
+
try {
|
|
480
|
+
await bootstrap({ verbose: program.opts().verbose });
|
|
481
|
+
const m = getPriceModel(serviceId);
|
|
482
|
+
if (options.json) console.log(JSON.stringify(m, null, 2));
|
|
483
|
+
else if (!m) logger.info("No price model.");
|
|
484
|
+
else
|
|
485
|
+
logger.log(
|
|
486
|
+
`${chalk.cyan(m.serviceId)} ${m.paymentType}@${chalk.yellow(m.rate)}`,
|
|
487
|
+
);
|
|
488
|
+
await shutdown();
|
|
489
|
+
} catch (err) {
|
|
490
|
+
logger.error(`Failed: ${err.message}`);
|
|
491
|
+
process.exit(1);
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
economy
|
|
496
|
+
.command("pay-v2")
|
|
497
|
+
.description(
|
|
498
|
+
"Pay for a priced service (computes amount from usage) (Phase 85)",
|
|
499
|
+
)
|
|
500
|
+
.argument("<from>", "From agent ID")
|
|
501
|
+
.argument("<to>", "To agent ID")
|
|
502
|
+
.argument("<service-id>", "Service ID")
|
|
503
|
+
.option("--tokens <n>", "Token count (for per_token)", parseInt)
|
|
504
|
+
.option("--minutes <n>", "Minute count (for per_minute)", parseFloat)
|
|
505
|
+
.option("--calls <n>", "Call count (for per_call)", parseInt)
|
|
506
|
+
.option("--json", "Output as JSON")
|
|
507
|
+
.action(async (from, to, serviceId, options) => {
|
|
508
|
+
try {
|
|
509
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
510
|
+
const db = ctx.db.getDatabase();
|
|
511
|
+
const r = payV2(db, {
|
|
512
|
+
fromAgentId: from,
|
|
513
|
+
toAgentId: to,
|
|
514
|
+
serviceId,
|
|
515
|
+
tokens: options.tokens,
|
|
516
|
+
minutes: options.minutes,
|
|
517
|
+
calls: options.calls,
|
|
518
|
+
});
|
|
519
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
520
|
+
else
|
|
521
|
+
logger.log(
|
|
522
|
+
`${chalk.green("✓")} paid ${chalk.yellow(r.amount)} via ${r.paymentType}`,
|
|
523
|
+
);
|
|
524
|
+
await shutdown();
|
|
525
|
+
} catch (err) {
|
|
526
|
+
logger.error(`Failed: ${err.message}`);
|
|
527
|
+
process.exit(1);
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
economy
|
|
532
|
+
.command("channel-open-v2")
|
|
533
|
+
.description("Open a two-sided channel (Phase 85)")
|
|
534
|
+
.argument("<party-a>", "Party A ID")
|
|
535
|
+
.argument("<party-b>", "Party B ID")
|
|
536
|
+
.option("--deposit-a <n>", "Deposit from party A", parseFloat)
|
|
537
|
+
.option("--deposit-b <n>", "Deposit from party B", parseFloat)
|
|
538
|
+
.option("--json", "Output as JSON")
|
|
539
|
+
.action(async (a, b, options) => {
|
|
540
|
+
try {
|
|
541
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
542
|
+
const db = ctx.db.getDatabase();
|
|
543
|
+
const ch = openChannelV2(db, {
|
|
544
|
+
partyA: a,
|
|
545
|
+
partyB: b,
|
|
546
|
+
depositA: options.depositA || 0,
|
|
547
|
+
depositB: options.depositB || 0,
|
|
548
|
+
});
|
|
549
|
+
if (options.json) console.log(JSON.stringify(ch, null, 2));
|
|
550
|
+
else
|
|
551
|
+
logger.log(
|
|
552
|
+
`${chalk.green("✓")} channel ${chalk.cyan(ch.id)} opened (${ch.balanceA}↔${ch.balanceB})`,
|
|
553
|
+
);
|
|
554
|
+
await shutdown();
|
|
555
|
+
} catch (err) {
|
|
556
|
+
logger.error(`Failed: ${err.message}`);
|
|
557
|
+
process.exit(1);
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
economy
|
|
562
|
+
.command("channel-activate")
|
|
563
|
+
.description("OPEN → ACTIVE (Phase 85)")
|
|
564
|
+
.argument("<id>", "Channel ID")
|
|
565
|
+
.option("--json", "Output as JSON")
|
|
566
|
+
.action(async (id, options) => {
|
|
567
|
+
try {
|
|
568
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
569
|
+
const db = ctx.db.getDatabase();
|
|
570
|
+
const r = activateChannel(db, id);
|
|
571
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
572
|
+
else logger.log(`${chalk.green("✓ Active")} ${chalk.cyan(id)}`);
|
|
573
|
+
await shutdown();
|
|
574
|
+
} catch (err) {
|
|
575
|
+
logger.error(`Failed: ${err.message}`);
|
|
576
|
+
process.exit(1);
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
economy
|
|
581
|
+
.command("channel-settle")
|
|
582
|
+
.description("ACTIVE → SETTLING with final balances (Phase 85)")
|
|
583
|
+
.argument("<id>", "Channel ID")
|
|
584
|
+
.requiredOption("--final-a <n>", "Final balance A", parseFloat)
|
|
585
|
+
.requiredOption("--final-b <n>", "Final balance B", parseFloat)
|
|
586
|
+
.option("--json", "Output as JSON")
|
|
587
|
+
.action(async (id, options) => {
|
|
588
|
+
try {
|
|
589
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
590
|
+
const db = ctx.db.getDatabase();
|
|
591
|
+
const r = initiateSettlement(db, id, {
|
|
592
|
+
finalBalanceA: options.finalA,
|
|
593
|
+
finalBalanceB: options.finalB,
|
|
594
|
+
});
|
|
595
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
596
|
+
else
|
|
597
|
+
logger.log(
|
|
598
|
+
`${chalk.green("✓ Settling")} ${chalk.cyan(id)} a=${r.balanceA} b=${r.balanceB}`,
|
|
599
|
+
);
|
|
600
|
+
await shutdown();
|
|
601
|
+
} catch (err) {
|
|
602
|
+
logger.error(`Failed: ${err.message}`);
|
|
603
|
+
process.exit(1);
|
|
604
|
+
}
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
economy
|
|
608
|
+
.command("channel-close-v2")
|
|
609
|
+
.description("Close channel and release locked funds (Phase 85)")
|
|
610
|
+
.argument("<id>", "Channel ID")
|
|
611
|
+
.option("--json", "Output as JSON")
|
|
612
|
+
.action(async (id, options) => {
|
|
613
|
+
try {
|
|
614
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
615
|
+
const db = ctx.db.getDatabase();
|
|
616
|
+
const r = closeChannelV2(db, id);
|
|
617
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
618
|
+
else logger.log(`${chalk.green("✓ Closed")} ${chalk.cyan(id)}`);
|
|
619
|
+
await shutdown();
|
|
620
|
+
} catch (err) {
|
|
621
|
+
logger.error(`Failed: ${err.message}`);
|
|
622
|
+
process.exit(1);
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
economy
|
|
627
|
+
.command("channel-dispute")
|
|
628
|
+
.description("Mark channel DISPUTED (Phase 85)")
|
|
629
|
+
.argument("<id>", "Channel ID")
|
|
630
|
+
.option("--reason <r>", "Dispute reason", "dispute")
|
|
631
|
+
.option("--json", "Output as JSON")
|
|
632
|
+
.action(async (id, options) => {
|
|
633
|
+
try {
|
|
634
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
635
|
+
const db = ctx.db.getDatabase();
|
|
636
|
+
const r = disputeChannel(db, id, options.reason);
|
|
637
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
638
|
+
else
|
|
639
|
+
logger.log(
|
|
640
|
+
`${chalk.red("⚠ Disputed")} ${chalk.cyan(id)} reason=${options.reason}`,
|
|
641
|
+
);
|
|
642
|
+
await shutdown();
|
|
643
|
+
} catch (err) {
|
|
644
|
+
logger.error(`Failed: ${err.message}`);
|
|
645
|
+
process.exit(1);
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
economy
|
|
650
|
+
.command("channels-v2")
|
|
651
|
+
.description("List channels with optional status/party filter (Phase 85)")
|
|
652
|
+
.option("-s, --status <s>", "Filter by status")
|
|
653
|
+
.option("-p, --party <id>", "Filter by party")
|
|
654
|
+
.option("--json", "Output as JSON")
|
|
655
|
+
.action(async (options) => {
|
|
656
|
+
try {
|
|
657
|
+
await bootstrap({ verbose: program.opts().verbose });
|
|
658
|
+
const r = listChannelsV2({
|
|
659
|
+
status: options.status,
|
|
660
|
+
party: options.party,
|
|
661
|
+
});
|
|
662
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
663
|
+
else if (r.length === 0) logger.info("No channels.");
|
|
664
|
+
else
|
|
665
|
+
r.forEach((c) =>
|
|
666
|
+
logger.log(
|
|
667
|
+
` ${chalk.cyan(c.id)} ${c.partyA}↔${c.partyB} ${chalk.yellow(c.status)}`,
|
|
668
|
+
),
|
|
669
|
+
);
|
|
670
|
+
await shutdown();
|
|
671
|
+
} catch (err) {
|
|
672
|
+
logger.error(`Failed: ${err.message}`);
|
|
673
|
+
process.exit(1);
|
|
674
|
+
}
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
economy
|
|
678
|
+
.command("market-list-v2")
|
|
679
|
+
.description("List a resource with validated RESOURCE_TYPE (Phase 85)")
|
|
680
|
+
.argument("<seller>", "Seller ID")
|
|
681
|
+
.argument("<resource-type>", "compute|storage|model|data|skill")
|
|
682
|
+
.argument("<price>", "Price per unit")
|
|
683
|
+
.option("--name <n>", "Display name")
|
|
684
|
+
.option("--available <n>", "Available quantity", parseInt, 1)
|
|
685
|
+
.option("--json", "Output as JSON")
|
|
686
|
+
.action(async (seller, resourceType, price, options) => {
|
|
687
|
+
try {
|
|
688
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
689
|
+
const db = ctx.db.getDatabase();
|
|
690
|
+
const r = listResourceV2(db, {
|
|
691
|
+
sellerId: seller,
|
|
692
|
+
resourceType,
|
|
693
|
+
price: parseFloat(price),
|
|
694
|
+
name: options.name,
|
|
695
|
+
available: options.available,
|
|
696
|
+
});
|
|
697
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
698
|
+
else
|
|
699
|
+
logger.log(
|
|
700
|
+
`${chalk.green("✓")} listing ${chalk.cyan(r.id)} ${resourceType}@${price}`,
|
|
701
|
+
);
|
|
702
|
+
await shutdown();
|
|
703
|
+
} catch (err) {
|
|
704
|
+
logger.error(`Failed: ${err.message}`);
|
|
705
|
+
process.exit(1);
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
economy
|
|
710
|
+
.command("nft-mint-v2")
|
|
711
|
+
.description("Mint NFT with royalty tracking (Phase 85)")
|
|
712
|
+
.argument("<owner>", "Owner ID")
|
|
713
|
+
.argument("<asset-type>", "Asset type")
|
|
714
|
+
.option("--royalty <pct>", "Royalty percent (0-50)", parseFloat, 0)
|
|
715
|
+
.option("--metadata <json>", "Metadata JSON")
|
|
716
|
+
.option("--json", "Output as JSON")
|
|
717
|
+
.action(async (owner, assetType, options) => {
|
|
718
|
+
try {
|
|
719
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
720
|
+
const db = ctx.db.getDatabase();
|
|
721
|
+
const n = mintNFTV2(db, {
|
|
722
|
+
owner,
|
|
723
|
+
assetType,
|
|
724
|
+
royaltyPercent: options.royalty,
|
|
725
|
+
metadata: options.metadata ? JSON.parse(options.metadata) : {},
|
|
726
|
+
});
|
|
727
|
+
if (options.json) console.log(JSON.stringify(n, null, 2));
|
|
728
|
+
else
|
|
729
|
+
logger.log(
|
|
730
|
+
`${chalk.green("✓ Minted")} ${chalk.cyan(n.id)} ${assetType} royalty=${n.royaltyPercent}%`,
|
|
731
|
+
);
|
|
732
|
+
await shutdown();
|
|
733
|
+
} catch (err) {
|
|
734
|
+
logger.error(`Failed: ${err.message}`);
|
|
735
|
+
process.exit(1);
|
|
736
|
+
}
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
economy
|
|
740
|
+
.command("nft-list")
|
|
741
|
+
.description("List NFT for sale at a price (Phase 85)")
|
|
742
|
+
.argument("<id>", "NFT ID")
|
|
743
|
+
.argument("<price>", "Listing price")
|
|
744
|
+
.option("--json", "Output as JSON")
|
|
745
|
+
.action(async (id, price, options) => {
|
|
746
|
+
try {
|
|
747
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
748
|
+
const db = ctx.db.getDatabase();
|
|
749
|
+
const r = listNFT(db, id, parseFloat(price));
|
|
750
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
751
|
+
else
|
|
752
|
+
logger.log(`${chalk.green("✓ Listed")} ${chalk.cyan(id)}@${price}`);
|
|
753
|
+
await shutdown();
|
|
754
|
+
} catch (err) {
|
|
755
|
+
logger.error(`Failed: ${err.message}`);
|
|
756
|
+
process.exit(1);
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
economy
|
|
761
|
+
.command("nft-buy")
|
|
762
|
+
.description("Buy a listed NFT (Phase 85)")
|
|
763
|
+
.argument("<id>", "NFT ID")
|
|
764
|
+
.argument("<buyer>", "Buyer ID")
|
|
765
|
+
.option("--json", "Output as JSON")
|
|
766
|
+
.action(async (id, buyer, options) => {
|
|
767
|
+
try {
|
|
768
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
769
|
+
const db = ctx.db.getDatabase();
|
|
770
|
+
const r = buyNFT(db, id, buyer);
|
|
771
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
772
|
+
else
|
|
773
|
+
logger.log(
|
|
774
|
+
`${chalk.green("✓ Sold")} ${chalk.cyan(id)} → ${buyer} for ${r.price} (royalty ${r.royalty})`,
|
|
775
|
+
);
|
|
776
|
+
await shutdown();
|
|
777
|
+
} catch (err) {
|
|
778
|
+
logger.error(`Failed: ${err.message}`);
|
|
779
|
+
process.exit(1);
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
economy
|
|
784
|
+
.command("nft-burn")
|
|
785
|
+
.description("Burn an NFT (Phase 85)")
|
|
786
|
+
.argument("<id>", "NFT ID")
|
|
787
|
+
.option("--json", "Output as JSON")
|
|
788
|
+
.action(async (id, options) => {
|
|
789
|
+
try {
|
|
790
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
791
|
+
const db = ctx.db.getDatabase();
|
|
792
|
+
const r = burnNFT(db, id);
|
|
793
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
794
|
+
else logger.log(`${chalk.red("🔥 Burned")} ${chalk.cyan(id)}`);
|
|
795
|
+
await shutdown();
|
|
796
|
+
} catch (err) {
|
|
797
|
+
logger.error(`Failed: ${err.message}`);
|
|
798
|
+
process.exit(1);
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
economy
|
|
803
|
+
.command("nft-status")
|
|
804
|
+
.description("Get NFT status (Phase 85)")
|
|
805
|
+
.argument("<id>", "NFT ID")
|
|
806
|
+
.option("--json", "Output as JSON")
|
|
807
|
+
.action(async (id, options) => {
|
|
808
|
+
try {
|
|
809
|
+
await bootstrap({ verbose: program.opts().verbose });
|
|
810
|
+
const s = getNFTStatus(id);
|
|
811
|
+
if (options.json) console.log(JSON.stringify(s, null, 2));
|
|
812
|
+
else if (!s) logger.info("No NFT found.");
|
|
813
|
+
else
|
|
814
|
+
logger.log(
|
|
815
|
+
`${chalk.cyan(id)} ${chalk.yellow(s.status)} royalty=${s.royaltyPercent}%`,
|
|
816
|
+
);
|
|
817
|
+
await shutdown();
|
|
818
|
+
} catch (err) {
|
|
819
|
+
logger.error(`Failed: ${err.message}`);
|
|
820
|
+
process.exit(1);
|
|
821
|
+
}
|
|
822
|
+
});
|
|
823
|
+
|
|
824
|
+
economy
|
|
825
|
+
.command("contribute-task")
|
|
826
|
+
.description("Record a weighted task contribution (Phase 85)")
|
|
827
|
+
.argument("<task-id>", "Task ID")
|
|
828
|
+
.argument("<agent-id>", "Agent ID")
|
|
829
|
+
.option("--weight <w>", "Weight", parseFloat, 1)
|
|
830
|
+
.option("--json", "Output as JSON")
|
|
831
|
+
.action(async (taskId, agentId, options) => {
|
|
832
|
+
try {
|
|
833
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
834
|
+
const db = ctx.db.getDatabase();
|
|
835
|
+
const r = recordTaskContribution(db, {
|
|
836
|
+
taskId,
|
|
837
|
+
agentId,
|
|
838
|
+
weight: options.weight,
|
|
839
|
+
});
|
|
840
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
841
|
+
else
|
|
842
|
+
logger.log(
|
|
843
|
+
`${chalk.green("✓")} ${chalk.cyan(agentId)} → ${taskId} weight=${options.weight}`,
|
|
844
|
+
);
|
|
845
|
+
await shutdown();
|
|
846
|
+
} catch (err) {
|
|
847
|
+
logger.error(`Failed: ${err.message}`);
|
|
848
|
+
process.exit(1);
|
|
849
|
+
}
|
|
850
|
+
});
|
|
851
|
+
|
|
852
|
+
economy
|
|
853
|
+
.command("contributions-task")
|
|
854
|
+
.description("List contributions for a task (Phase 85)")
|
|
855
|
+
.argument("<task-id>", "Task ID")
|
|
856
|
+
.option("--json", "Output as JSON")
|
|
857
|
+
.action(async (taskId, options) => {
|
|
858
|
+
try {
|
|
859
|
+
await bootstrap({ verbose: program.opts().verbose });
|
|
860
|
+
const r = getTaskContributions(taskId);
|
|
861
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
862
|
+
else if (r.length === 0) logger.info("No contributions.");
|
|
863
|
+
else
|
|
864
|
+
r.forEach((c) =>
|
|
865
|
+
logger.log(` ${chalk.cyan(c.agentId)} weight=${c.weight}`),
|
|
866
|
+
);
|
|
867
|
+
await shutdown();
|
|
868
|
+
} catch (err) {
|
|
869
|
+
logger.error(`Failed: ${err.message}`);
|
|
870
|
+
process.exit(1);
|
|
871
|
+
}
|
|
872
|
+
});
|
|
873
|
+
|
|
874
|
+
economy
|
|
875
|
+
.command("distribute-v2")
|
|
876
|
+
.description("Distribute revenue across task contributors (Phase 85)")
|
|
877
|
+
.argument("<task-id>", "Task ID")
|
|
878
|
+
.argument("<total>", "Total amount to distribute")
|
|
879
|
+
.option("--json", "Output as JSON")
|
|
880
|
+
.action(async (taskId, total, options) => {
|
|
881
|
+
try {
|
|
882
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
883
|
+
const db = ctx.db.getDatabase();
|
|
884
|
+
const r = distributeRevenueV2(db, { taskId, total: parseFloat(total) });
|
|
885
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
886
|
+
else {
|
|
887
|
+
logger.log(chalk.bold(`Distributed ${total} for task ${taskId}:`));
|
|
888
|
+
r.shares.forEach((s) =>
|
|
889
|
+
logger.log(
|
|
890
|
+
` ${chalk.cyan(s.agentId)} share=${chalk.yellow(s.share.toFixed(2))} balance=${s.newBalance.toFixed(2)}`,
|
|
891
|
+
),
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
await shutdown();
|
|
895
|
+
} catch (err) {
|
|
896
|
+
logger.error(`Failed: ${err.message}`);
|
|
897
|
+
process.exit(1);
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
|
|
901
|
+
economy
|
|
902
|
+
.command("distributions")
|
|
903
|
+
.description("List distribution records (Phase 85)")
|
|
904
|
+
.option("-t, --task <id>", "Filter by task ID")
|
|
905
|
+
.option("--json", "Output as JSON")
|
|
906
|
+
.action(async (options) => {
|
|
907
|
+
try {
|
|
908
|
+
await bootstrap({ verbose: program.opts().verbose });
|
|
909
|
+
const r = listDistributions({ taskId: options.task });
|
|
910
|
+
if (options.json) console.log(JSON.stringify(r, null, 2));
|
|
911
|
+
else if (r.length === 0) logger.info("No distributions.");
|
|
912
|
+
else
|
|
913
|
+
r.forEach((d) =>
|
|
914
|
+
logger.log(
|
|
915
|
+
` ${chalk.cyan(d.id.slice(0, 8))} task=${d.taskId} total=${chalk.yellow(d.total)} shares=${d.shares.length}`,
|
|
916
|
+
),
|
|
917
|
+
);
|
|
918
|
+
await shutdown();
|
|
919
|
+
} catch (err) {
|
|
920
|
+
logger.error(`Failed: ${err.message}`);
|
|
921
|
+
process.exit(1);
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
|
|
925
|
+
economy
|
|
926
|
+
.command("stats-v2")
|
|
927
|
+
.description("Extended economy stats (Phase 85)")
|
|
928
|
+
.option("--json", "Output as JSON")
|
|
929
|
+
.action(async (options) => {
|
|
930
|
+
try {
|
|
931
|
+
await bootstrap({ verbose: program.opts().verbose });
|
|
932
|
+
const s = getEconomyStatsV2();
|
|
933
|
+
if (options.json) console.log(JSON.stringify(s, null, 2));
|
|
934
|
+
else {
|
|
935
|
+
logger.log(chalk.bold("Economy stats (Phase 85):"));
|
|
936
|
+
logger.log(` accounts: ${chalk.cyan(s.totalAccounts)}`);
|
|
937
|
+
logger.log(` channels: ${chalk.cyan(s.totalChannels)}`);
|
|
938
|
+
for (const [k, v] of Object.entries(s.channelsByStatus))
|
|
939
|
+
logger.log(` ${k}: ${v}`);
|
|
940
|
+
logger.log(` listings: ${chalk.cyan(s.totalListings)}`);
|
|
941
|
+
logger.log(` NFTs: ${chalk.cyan(s.totalNFTs)}`);
|
|
942
|
+
for (const [k, v] of Object.entries(s.nftByStatus))
|
|
943
|
+
logger.log(` ${k}: ${v}`);
|
|
944
|
+
logger.log(` price models: ${chalk.cyan(s.priceModels)}`);
|
|
945
|
+
logger.log(` distributions: ${chalk.cyan(s.distributions)}`);
|
|
946
|
+
}
|
|
947
|
+
await shutdown();
|
|
948
|
+
} catch (err) {
|
|
949
|
+
logger.error(`Failed: ${err.message}`);
|
|
950
|
+
process.exit(1);
|
|
951
|
+
}
|
|
952
|
+
});
|
|
375
953
|
}
|