moltlaunch 2.0.0 → 2.0.2

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 (108) hide show
  1. package/README.md +2 -2
  2. package/dist/index.js +18 -18
  3. package/dist/index.js.map +1 -1
  4. package/package.json +6 -2
  5. package/.claude/commands/deploy.md +0 -33
  6. package/.claude/hooks/regenerate-docs.sh +0 -12
  7. package/.claude/settings.json +0 -15
  8. package/.env.example +0 -2
  9. package/.github/workflows/deploy.yml +0 -37
  10. package/ROADMAP.md +0 -29
  11. package/contracts/MandateEscrowV4.sol +0 -281
  12. package/contracts/mocks/MockFlaunchBuyback.sol +0 -24
  13. package/hardhat.config.cjs +0 -29
  14. package/scripts/check-deploy-cost.ts +0 -15
  15. package/scripts/deploy-escrow-v4.ts +0 -81
  16. package/scripts/deploy-escrow.cjs +0 -22
  17. package/scripts/generate-docs.ts +0 -309
  18. package/shared/manifest.json +0 -87
  19. package/site/.vscode/extensions.json +0 -4
  20. package/site/.vscode/launch.json +0 -11
  21. package/site/README.md +0 -43
  22. package/site/astro.config.mjs +0 -21
  23. package/site/functions/agent/[[path]].ts +0 -9
  24. package/site/functions/task/[[path]].ts +0 -9
  25. package/site/index.html.bak +0 -1755
  26. package/site/package-lock.json +0 -6165
  27. package/site/package.json +0 -17
  28. package/site/public/_redirects +0 -1
  29. package/site/public/art/hero.webp +0 -0
  30. package/site/public/favicon.ico +0 -0
  31. package/site/public/favicon.svg +0 -4
  32. package/site/public/logo.png +0 -0
  33. package/site/public/skill.md +0 -276
  34. package/site/src/components/AgentGridCard.astro +0 -97
  35. package/site/src/components/AgentRow.astro +0 -75
  36. package/site/src/components/Footer.astro +0 -71
  37. package/site/src/components/GigCard.astro +0 -36
  38. package/site/src/components/Navbar.astro +0 -93
  39. package/site/src/components/ReviewCard.astro +0 -29
  40. package/site/src/components/SkillPill.astro +0 -19
  41. package/site/src/components/StatusBadge.astro +0 -27
  42. package/site/src/components/TaskEntry.astro +0 -98
  43. package/site/src/layouts/Layout.astro +0 -268
  44. package/site/src/lib/api.ts +0 -342
  45. package/site/src/pages/404.astro +0 -33
  46. package/site/src/pages/admin.astro +0 -445
  47. package/site/src/pages/agent/[...id].astro +0 -678
  48. package/site/src/pages/agents/index.astro +0 -235
  49. package/site/src/pages/dashboard.astro +0 -244
  50. package/site/src/pages/docs.astro +0 -191
  51. package/site/src/pages/how.astro +0 -156
  52. package/site/src/pages/index.astro +0 -226
  53. package/site/src/pages/leaderboard.astro +0 -155
  54. package/site/src/pages/task/[...id].astro +0 -1467
  55. package/site/src/styles/global.css +0 -159
  56. package/site/tailwind.config.mjs +0 -94
  57. package/site/tsconfig.json +0 -5
  58. package/site/wrangler.toml +0 -5
  59. package/src/commands/accept.ts +0 -135
  60. package/src/commands/agents.ts +0 -190
  61. package/src/commands/approve.ts +0 -127
  62. package/src/commands/claim.ts +0 -130
  63. package/src/commands/decline.ts +0 -55
  64. package/src/commands/dispute.ts +0 -92
  65. package/src/commands/earnings.ts +0 -86
  66. package/src/commands/feedback.ts +0 -147
  67. package/src/commands/gig.ts +0 -141
  68. package/src/commands/hire.ts +0 -96
  69. package/src/commands/inbox.ts +0 -135
  70. package/src/commands/message.ts +0 -97
  71. package/src/commands/profile.ts +0 -62
  72. package/src/commands/quote.ts +0 -80
  73. package/src/commands/refund.ts +0 -82
  74. package/src/commands/register.ts +0 -250
  75. package/src/commands/resolve.ts +0 -104
  76. package/src/commands/reviews.ts +0 -78
  77. package/src/commands/revise.ts +0 -65
  78. package/src/commands/submit.ts +0 -123
  79. package/src/commands/tasks.ts +0 -224
  80. package/src/commands/view.ts +0 -122
  81. package/src/commands/wallet.ts +0 -42
  82. package/src/index.ts +0 -285
  83. package/src/lib/agent0.ts +0 -158
  84. package/src/lib/auth.ts +0 -25
  85. package/src/lib/constants.ts +0 -55
  86. package/src/lib/escrow.ts +0 -374
  87. package/src/lib/files.ts +0 -87
  88. package/src/lib/flaunch.ts +0 -277
  89. package/src/lib/mandate.ts +0 -623
  90. package/src/lib/tasks.ts +0 -466
  91. package/src/lib/types.ts +0 -112
  92. package/src/lib/wallet.ts +0 -119
  93. package/src/lib/x402.ts +0 -86
  94. package/test/MandateEscrowV4.test.cjs +0 -568
  95. package/tsconfig.json +0 -19
  96. package/tsup.config.ts +0 -15
  97. package/worker/package-lock.json +0 -1812
  98. package/worker/package.json +0 -18
  99. package/worker/src/agents.ts +0 -755
  100. package/worker/src/auth.ts +0 -126
  101. package/worker/src/files.ts +0 -40
  102. package/worker/src/index.ts +0 -963
  103. package/worker/src/profiles.ts +0 -85
  104. package/worker/src/ratelimit.ts +0 -45
  105. package/worker/src/tasks.ts +0 -498
  106. package/worker/src/types.ts +0 -95
  107. package/worker/tsconfig.json +0 -15
  108. package/worker/wrangler.toml +0 -19
@@ -1,127 +0,0 @@
1
- // mltl approve - Approve submitted work and release payment from escrow (client action)
2
-
3
- import { formatEther } from "viem";
4
- import { loadOrCreateWallet } from "../lib/wallet.js";
5
- import { getTask, completeTask } from "../lib/tasks.js";
6
- import { releaseEscrow, getEscrowDetails, EscrowStatus } from "../lib/escrow.js";
7
- import { APIS } from "../lib/constants.js";
8
-
9
- interface ApproveOptions {
10
- task: string;
11
- json?: boolean;
12
- }
13
-
14
- // Fetch agent from our worker API (no subgraph needed)
15
- async function fetchAgent(agentId: string) {
16
- const res = await fetch(`${APIS.MANDATE}/api/agents/${agentId}`);
17
- if (!res.ok) return null;
18
- const data = await res.json() as { agent?: { name: string; owner: string } };
19
- return data.agent;
20
- }
21
-
22
- export async function approve(options: ApproveOptions): Promise<void> {
23
- const { wallet } = await loadOrCreateWallet();
24
-
25
- if (!options.json) {
26
- console.log("\nApproving work and preparing payment...");
27
- console.log("──────────────────────────────────────────────");
28
- }
29
-
30
- try {
31
- // Get task details
32
- const task = await getTask(options.task);
33
-
34
- if (task.status !== "submitted") {
35
- throw new Error(`Task is ${task.status}, cannot approve (must be submitted)`);
36
- }
37
-
38
- // Verify caller is the client
39
- if (task.clientAddress.toLowerCase() !== wallet.address.toLowerCase()) {
40
- throw new Error("Only the client who created this task can approve it");
41
- }
42
-
43
- // Use the quoted price (set by agent)
44
- if (!task.quotedPriceWei) {
45
- throw new Error("Task has no quoted price");
46
- }
47
-
48
- const priceWei = BigInt(task.quotedPriceWei);
49
- const priceEth = formatEther(priceWei);
50
-
51
- // Get agent's wallet address
52
- const agent = await fetchAgent(task.agentId);
53
- if (!agent) {
54
- throw new Error(`Agent #${task.agentId} not found`);
55
- }
56
-
57
- // The agent's owner address receives payment
58
- const agentOwner = agent.owner;
59
- if (!agentOwner) {
60
- throw new Error("Agent has no owner address");
61
- }
62
-
63
- // Verify escrow exists
64
- const escrow = await getEscrowDetails(task.id);
65
- if (!escrow) {
66
- throw new Error("No escrow found for this task. Was it accepted properly?");
67
- }
68
- if (escrow.status >= EscrowStatus.Released) {
69
- throw new Error("Escrow already released");
70
- }
71
-
72
- if (!options.json) {
73
- console.log(`\nTask ID: ${task.id}`);
74
- console.log(`Agent: ${agent.name || `#${task.agentId}`}`);
75
- console.log(`Agent Owner: ${agentOwner}`);
76
- console.log(`Escrow: ${formatEther(escrow.amount)} ETH (locked)`);
77
- console.log(`\nSubmitted result:\n${task.result}\n`);
78
- console.log("──────────────────────────────────────────────");
79
- console.log("\nReleasing payment from escrow...");
80
- }
81
-
82
- // Release funds from escrow to agent
83
- const txHash = await releaseEscrow(wallet, task.id);
84
-
85
- // Mark task as completed (signed with wallet)
86
- const completedTask = await completeTask(wallet, options.task, txHash);
87
-
88
- if (options.json) {
89
- console.log(
90
- JSON.stringify({
91
- success: true,
92
- task: {
93
- id: completedTask.id,
94
- agentId: completedTask.agentId,
95
- status: completedTask.status,
96
- quotedPriceWei: completedTask.quotedPriceWei,
97
- txHash: completedTask.txHash,
98
- },
99
- payment: {
100
- to: agentOwner,
101
- amount: priceEth,
102
- txHash,
103
- type: "escrow_release",
104
- },
105
- }),
106
- );
107
- return;
108
- }
109
-
110
- console.log("\n✅ Work approved! Payment released from escrow.");
111
- console.log("──────────────────────────────────────────────");
112
- console.log(`\nPayment: ${priceEth} ETH → ${agentOwner}`);
113
- console.log(`TX: ${txHash}`);
114
- console.log("\nDon't forget to leave feedback:");
115
- console.log(` mltl feedback --agent ${task.agentId} --score 90\n`);
116
- } catch (err) {
117
- const errorMsg = err instanceof Error ? err.message : String(err);
118
-
119
- if (options.json) {
120
- console.log(JSON.stringify({ error: errorMsg }));
121
- process.exit(1);
122
- }
123
-
124
- console.error(`\n❌ Failed to approve: ${errorMsg}`);
125
- process.exit(1);
126
- }
127
- }
@@ -1,130 +0,0 @@
1
- // mltl claim - Claim payment after timeout (agent protection)
2
-
3
- import { formatEther } from "viem";
4
- import { loadOrCreateWallet } from "../lib/wallet.js";
5
- import { getTask, completeTask } from "../lib/tasks.js";
6
- import {
7
- releaseAfterTimeout,
8
- getEscrowDetails,
9
- isEscrowTimedOut,
10
- getTimeUntilTimeout,
11
- EscrowStatus,
12
- } from "../lib/escrow.js";
13
-
14
- interface ClaimOptions {
15
- task: string;
16
- json?: boolean;
17
- }
18
-
19
- export async function claim(options: ClaimOptions): Promise<void> {
20
- const { wallet } = await loadOrCreateWallet();
21
-
22
- if (!options.json) {
23
- console.log("\nChecking claim eligibility...");
24
- console.log("──────────────────────────────────────────────");
25
- }
26
-
27
- try {
28
- // Get task details
29
- const task = await getTask(options.task);
30
-
31
- // Get escrow details
32
- const escrow = await getEscrowDetails(options.task);
33
-
34
- if (!escrow) {
35
- throw new Error("No escrow found for this task");
36
- }
37
-
38
- if (escrow.status === EscrowStatus.Released || escrow.status === EscrowStatus.Refunded) {
39
- throw new Error("Payment already released or refunded");
40
- }
41
-
42
- if (escrow.status !== EscrowStatus.Submitted) {
43
- throw new Error("Work not yet submitted. Run 'mltl submit' first.");
44
- }
45
-
46
- if (escrow.status === EscrowStatus.Disputed) {
47
- throw new Error("Task is disputed. Cannot claim until dispute is resolved.");
48
- }
49
-
50
- const priceEth = formatEther(escrow.amount);
51
-
52
- // Check if timeout reached
53
- const timedOut = await isEscrowTimedOut(options.task);
54
-
55
- if (!timedOut) {
56
- const secondsLeft = await getTimeUntilTimeout(options.task);
57
- const hoursLeft = Number(secondsLeft) / 3600;
58
-
59
- if (options.json) {
60
- console.log(
61
- JSON.stringify({
62
- error: "Timeout not reached",
63
- timeRemaining: {
64
- seconds: Number(secondsLeft),
65
- hours: hoursLeft.toFixed(2),
66
- },
67
- }),
68
- );
69
- process.exit(1);
70
- }
71
-
72
- console.log(`\n⏳ Timeout not reached yet.`);
73
- console.log(`\nTime remaining: ${hoursLeft.toFixed(1)} hours`);
74
- console.log(`\nThe client can still approve the work.`);
75
- console.log(`If they don't respond, you can claim after the timeout.\n`);
76
- return;
77
- }
78
-
79
- if (!options.json) {
80
- console.log(`\nTask ID: ${task.id}`);
81
- console.log(`Amount: ${priceEth} ETH`);
82
- console.log(`Status: Timeout reached - claiming payment...`);
83
- }
84
-
85
- // Release after timeout
86
- const txHash = await releaseAfterTimeout(wallet, options.task);
87
-
88
- // Sync completion to worker KV
89
- try {
90
- await completeTask(wallet, options.task, txHash);
91
- } catch {
92
- // Non-fatal: onchain release succeeded, KV sync is best-effort
93
- }
94
-
95
- if (options.json) {
96
- console.log(
97
- JSON.stringify({
98
- success: true,
99
- task: {
100
- id: task.id,
101
- agentId: task.agentId,
102
- },
103
- payment: {
104
- amount: priceEth,
105
- txHash,
106
- type: "timeout_release",
107
- },
108
- }),
109
- );
110
- return;
111
- }
112
-
113
- console.log("\n✅ Payment claimed!");
114
- console.log("──────────────────────────────────────────────");
115
- console.log(`\nAmount: ${priceEth} ETH`);
116
- console.log(`TX: ${txHash}`);
117
- console.log(`\nThe client did not respond within 24 hours.`);
118
- console.log(`Funds have been released to your wallet.\n`);
119
- } catch (err) {
120
- const errorMsg = err instanceof Error ? err.message : String(err);
121
-
122
- if (options.json) {
123
- console.log(JSON.stringify({ error: errorMsg }));
124
- process.exit(1);
125
- }
126
-
127
- console.error(`\n❌ Failed to claim: ${errorMsg}`);
128
- process.exit(1);
129
- }
130
- }
@@ -1,55 +0,0 @@
1
- // mltl decline - Decline a task request (agent action)
2
-
3
- import { loadOrCreateWallet } from "../lib/wallet.js";
4
- import { declineTask, getTask } from "../lib/tasks.js";
5
-
6
- interface DeclineOptions {
7
- task: string;
8
- json?: boolean;
9
- }
10
-
11
- export async function decline(options: DeclineOptions): Promise<void> {
12
- const { wallet } = await loadOrCreateWallet();
13
-
14
- if (!options.json) {
15
- console.log("\nDeclining task...");
16
- }
17
-
18
- try {
19
- // First verify task exists
20
- const taskBefore = await getTask(options.task);
21
-
22
- if (!["requested", "quoted"].includes(taskBefore.status)) {
23
- throw new Error(`Task is ${taskBefore.status}, cannot decline`);
24
- }
25
-
26
- // Decline the task (signed with wallet)
27
- const task = await declineTask(wallet, options.task);
28
-
29
- if (options.json) {
30
- console.log(
31
- JSON.stringify({
32
- success: true,
33
- task: {
34
- id: task.id,
35
- status: task.status,
36
- },
37
- }),
38
- );
39
- return;
40
- }
41
-
42
- console.log(`\n✅ Task ${task.id} declined.`);
43
- console.log("\nThe client will be notified.\n");
44
- } catch (err) {
45
- const errorMsg = err instanceof Error ? err.message : String(err);
46
-
47
- if (options.json) {
48
- console.log(JSON.stringify({ error: errorMsg }));
49
- process.exit(1);
50
- }
51
-
52
- console.error(`\n❌ Failed to decline task: ${errorMsg}`);
53
- process.exit(1);
54
- }
55
- }
@@ -1,92 +0,0 @@
1
- // mltl dispute - Dispute submitted work and freeze timeout (client action)
2
-
3
- import { formatEther } from "viem";
4
- import { loadOrCreateWallet } from "../lib/wallet.js";
5
- import { getTask } from "../lib/tasks.js";
6
- import { getEscrowDetails, getDisputeFee, disputeEscrow, EscrowStatus } from "../lib/escrow.js";
7
- import { signAction } from "../lib/auth.js";
8
- import { APIS } from "../lib/constants.js";
9
-
10
- interface DisputeOptions {
11
- task: string;
12
- json?: boolean;
13
- }
14
-
15
- export async function dispute(options: DisputeOptions): Promise<void> {
16
- const { wallet } = await loadOrCreateWallet();
17
-
18
- if (!options.json) {
19
- console.log("\nDisputing submitted work...");
20
- console.log("──────────────────────────────────────────────");
21
- }
22
-
23
- try {
24
- const task = await getTask(options.task);
25
-
26
- if (task.status !== "submitted") {
27
- throw new Error(`Task is ${task.status}, cannot dispute (must be submitted)`);
28
- }
29
-
30
- if (task.clientAddress.toLowerCase() !== wallet.address.toLowerCase()) {
31
- throw new Error("Only the client who created this task can dispute it");
32
- }
33
-
34
- const escrow = await getEscrowDetails(task.id);
35
- if (!escrow) {
36
- throw new Error("No escrow found for this task");
37
- }
38
- if (escrow.status !== EscrowStatus.Submitted) {
39
- throw new Error("Escrow is not in submitted state");
40
- }
41
-
42
- const feeWei = await getDisputeFee(task.id);
43
- const feeEth = formatEther(feeWei);
44
-
45
- if (!options.json) {
46
- console.log(`\nTask ID: ${task.id}`);
47
- console.log(`Escrow: ${formatEther(escrow.amount)} ETH`);
48
- console.log(`Dispute fee: ${feeEth} ETH (10% of escrow)`);
49
- console.log("\nOpening dispute...");
50
- }
51
-
52
- const txHash = await disputeEscrow(wallet, task.id, feeWei);
53
-
54
- // Sign and notify worker
55
- const { signature, timestamp, nonce } = await signAction(wallet, "dispute", task.id);
56
-
57
- await fetch(`${APIS.MANDATE}/api/tasks/${task.id}/dispute`, {
58
- method: "POST",
59
- headers: { "Content-Type": "application/json" },
60
- body: JSON.stringify({ txHash, signature, timestamp, nonce }),
61
- });
62
-
63
- if (options.json) {
64
- console.log(
65
- JSON.stringify({
66
- success: true,
67
- taskId: task.id,
68
- disputeFee: feeEth,
69
- txHash,
70
- })
71
- );
72
- return;
73
- }
74
-
75
- console.log("\nDispute opened! Timeout is now frozen.");
76
- console.log("──────────────────────────────────────────────");
77
- console.log(`\nFee paid: ${feeEth} ETH`);
78
- console.log(`TX: ${txHash}`);
79
- console.log("\nAn admin will review and resolve the dispute.");
80
- console.log("If you win, you get your escrow + fee back.\n");
81
- } catch (err) {
82
- const errorMsg = err instanceof Error ? err.message : String(err);
83
-
84
- if (options.json) {
85
- console.log(JSON.stringify({ error: errorMsg }));
86
- process.exit(1);
87
- }
88
-
89
- console.error(`\n❌ Failed to dispute: ${errorMsg}`);
90
- process.exit(1);
91
- }
92
- }
@@ -1,86 +0,0 @@
1
- // mltl earnings - View your earnings from being hired
2
-
3
- import { formatEther } from "viem";
4
- import { loadOrCreateWallet, getWalletBalance } from "../lib/wallet.js";
5
- import { getAgentByOwner, getReputationSummary } from "../lib/mandate.js";
6
- import { CHAIN } from "../lib/constants.js";
7
-
8
- interface EarningsOptions {
9
- json?: boolean;
10
- }
11
-
12
- export async function earnings(options: EarningsOptions): Promise<void> {
13
- const { wallet } = await loadOrCreateWallet();
14
-
15
- if (!options.json) {
16
- console.log("\nMANDATE Earnings");
17
- console.log("══════════════════════════════════════════════════════════════════\n");
18
- }
19
-
20
- try {
21
- const balance = await getWalletBalance(wallet.address);
22
- const agentId = await getAgentByOwner(wallet.address);
23
-
24
- if (options.json) {
25
- const result: Record<string, unknown> = {
26
- wallet: wallet.address,
27
- balance,
28
- agent: null as Record<string, unknown> | null,
29
- };
30
-
31
- if (agentId && agentId > 0n) {
32
- const rep = await getReputationSummary(agentId);
33
- result.agent = {
34
- agentId: agentId.toString(),
35
- reputation: {
36
- count: Number(rep.count),
37
- summaryValue: Number(rep.summaryValue),
38
- },
39
- };
40
- }
41
-
42
- console.log(JSON.stringify(result));
43
- return;
44
- }
45
-
46
- console.log(`Wallet: ${wallet.address}`);
47
- console.log(`Balance: ${balance} ETH`);
48
- console.log("");
49
-
50
- if (!agentId || agentId <= 0n) {
51
- console.log("No registered agent found for this wallet.");
52
- console.log("Register one with: mltl register --name <name> --description <desc> --skills <skills> --image <path>");
53
- return;
54
- }
55
-
56
- console.log(`Agent ID: ${agentId.toString()}`);
57
- console.log(`Explorer: ${CHAIN.explorer}/token/${agentId.toString()}`);
58
- console.log("");
59
- console.log("──────────────────────────────────────────────");
60
- console.log("Reputation (ERC-8004):");
61
- console.log("──────────────────────────────────────────────");
62
-
63
- const rep = await getReputationSummary(agentId);
64
- const feedbackCount = Number(rep.count);
65
- const avgScore = feedbackCount > 0 ? Number(rep.summaryValue) / feedbackCount : 0;
66
-
67
- console.log(` Feedback received: ${feedbackCount}`);
68
- console.log(` Average score: ${avgScore > 0 ? avgScore.toFixed(1) + "/100" : "N/A"}`);
69
- console.log("");
70
- console.log("Earnings are distributed via buyback-and-burn on your Flaunch token.");
71
- console.log("Each completed task burns tokens, increasing token value for holders.");
72
-
73
- } catch (err) {
74
- if (options.json) {
75
- console.log(
76
- JSON.stringify({
77
- error: err instanceof Error ? err.message : String(err),
78
- })
79
- );
80
- process.exit(1);
81
- }
82
-
83
- console.error(`\n❌ Failed to fetch earnings: ${err instanceof Error ? err.message : err}`);
84
- process.exit(1);
85
- }
86
- }
@@ -1,147 +0,0 @@
1
- // mltl feedback - Submit verified feedback for an agent after completing a task
2
- // Uses ERC-8004 Reputation Registry with full field utilization:
3
- // - feedbackHash: keccak256(taskId) — links to escrow record
4
- // - feedbackURI: "moltlaunch:task:<taskId>" — human-readable reference
5
- // - tag1: "mandate" — platform identifier
6
- // - tag2: agent contract address (CA)
7
-
8
- import { loadOrCreateWallet } from "../lib/wallet.js";
9
- import { giveFeedback, getAgent } from "../lib/mandate.js";
10
- import { getTask, rateTask } from "../lib/tasks.js";
11
-
12
- interface FeedbackOptions {
13
- agent?: string;
14
- task?: string;
15
- score: string;
16
- comment?: string;
17
- json?: boolean;
18
- }
19
-
20
- export async function feedback(options: FeedbackOptions): Promise<void> {
21
- const { wallet } = await loadOrCreateWallet();
22
-
23
- const score = parseInt(options.score, 10);
24
-
25
- if (score < 0 || score > 100) {
26
- if (options.json) {
27
- console.log(JSON.stringify({ error: "Score must be between 0 and 100" }));
28
- process.exit(1);
29
- }
30
- console.error("Score must be between 0 and 100");
31
- process.exit(1);
32
- }
33
-
34
- if (!options.agent && !options.task) {
35
- if (options.json) {
36
- console.log(JSON.stringify({ error: "Provide --agent or --task" }));
37
- process.exit(1);
38
- }
39
- console.error("Provide --agent <id> or --task <taskId>");
40
- process.exit(1);
41
- }
42
-
43
- let agentIdStr = options.agent || "";
44
- let taskId = options.task;
45
-
46
- // If --task provided, resolve agent from task and verify caller is the client
47
- if (taskId) {
48
- try {
49
- const task = await getTask(taskId);
50
-
51
- if (task.status !== "completed") {
52
- const msg = `Task ${taskId} is not completed (status: ${task.status})`;
53
- if (options.json) {
54
- console.log(JSON.stringify({ error: msg }));
55
- process.exit(1);
56
- }
57
- console.error(msg);
58
- process.exit(1);
59
- }
60
-
61
- if (task.clientAddress.toLowerCase() !== wallet.address.toLowerCase()) {
62
- const msg = "Only the task client can leave feedback";
63
- if (options.json) {
64
- console.log(JSON.stringify({ error: msg }));
65
- process.exit(1);
66
- }
67
- console.error(msg);
68
- process.exit(1);
69
- }
70
-
71
- agentIdStr = task.agentId;
72
- } catch (err) {
73
- const msg = err instanceof Error ? err.message : String(err);
74
- if (options.json) {
75
- console.log(JSON.stringify({ error: msg }));
76
- process.exit(1);
77
- }
78
- console.error(`Failed to fetch task: ${msg}`);
79
- process.exit(1);
80
- }
81
- }
82
-
83
- const agentId = BigInt(agentIdStr.startsWith("0x") ? agentIdStr : agentIdStr);
84
-
85
- if (!options.json) {
86
- console.log("\nSubmitting verified feedback...");
87
- console.log("──────────────────────────────────────────────");
88
- console.log(`Agent: #${agentIdStr}`);
89
- console.log(`Score: ${score}/100`);
90
- if (taskId) console.log(`Task: ${taskId}`);
91
- console.log(`Tag1: mandate`);
92
- console.log("──────────────────────────────────────────────\n");
93
- }
94
-
95
- try {
96
- // Resolve agent's contract address for tag2
97
- const agent = await getAgent(agentId);
98
- const agentCA = agent?.owner || "";
99
-
100
- const txHash = await giveFeedback(wallet, agentId, score, {
101
- taskId,
102
- agentContractAddress: agentCA,
103
- });
104
-
105
- // Sync rating to worker KV for verified reputation tracking
106
- if (taskId) {
107
- try {
108
- await rateTask(wallet, taskId, txHash, score, options.comment);
109
- } catch {
110
- // Non-fatal: onchain feedback succeeded, KV sync is best-effort
111
- }
112
- }
113
-
114
- if (options.json) {
115
- console.log(
116
- JSON.stringify({
117
- success: true,
118
- agentId: agentIdStr,
119
- score,
120
- taskId: taskId || null,
121
- feedbackHash: taskId ? `keccak256(${taskId})` : null,
122
- txHash,
123
- })
124
- );
125
- return;
126
- }
127
-
128
- console.log("Feedback submitted!\n");
129
- console.log(`Transaction: ${txHash}`);
130
- console.log(`View on Basescan: https://basescan.org/tx/${txHash}`);
131
- if (taskId) {
132
- console.log(`Linked to task: ${taskId}`);
133
- }
134
- } catch (err) {
135
- if (options.json) {
136
- console.log(
137
- JSON.stringify({
138
- error: err instanceof Error ? err.message : String(err),
139
- })
140
- );
141
- process.exit(1);
142
- }
143
-
144
- console.error(`\nFeedback failed: ${err instanceof Error ? err.message : err}`);
145
- process.exit(1);
146
- }
147
- }