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.
- package/README.md +2 -2
- package/dist/index.js +18 -18
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
- package/.claude/commands/deploy.md +0 -33
- package/.claude/hooks/regenerate-docs.sh +0 -12
- package/.claude/settings.json +0 -15
- package/.env.example +0 -2
- package/.github/workflows/deploy.yml +0 -37
- package/ROADMAP.md +0 -29
- package/contracts/MandateEscrowV4.sol +0 -281
- package/contracts/mocks/MockFlaunchBuyback.sol +0 -24
- package/hardhat.config.cjs +0 -29
- package/scripts/check-deploy-cost.ts +0 -15
- package/scripts/deploy-escrow-v4.ts +0 -81
- package/scripts/deploy-escrow.cjs +0 -22
- package/scripts/generate-docs.ts +0 -309
- package/shared/manifest.json +0 -87
- package/site/.vscode/extensions.json +0 -4
- package/site/.vscode/launch.json +0 -11
- package/site/README.md +0 -43
- package/site/astro.config.mjs +0 -21
- package/site/functions/agent/[[path]].ts +0 -9
- package/site/functions/task/[[path]].ts +0 -9
- package/site/index.html.bak +0 -1755
- package/site/package-lock.json +0 -6165
- package/site/package.json +0 -17
- package/site/public/_redirects +0 -1
- package/site/public/art/hero.webp +0 -0
- package/site/public/favicon.ico +0 -0
- package/site/public/favicon.svg +0 -4
- package/site/public/logo.png +0 -0
- package/site/public/skill.md +0 -276
- package/site/src/components/AgentGridCard.astro +0 -97
- package/site/src/components/AgentRow.astro +0 -75
- package/site/src/components/Footer.astro +0 -71
- package/site/src/components/GigCard.astro +0 -36
- package/site/src/components/Navbar.astro +0 -93
- package/site/src/components/ReviewCard.astro +0 -29
- package/site/src/components/SkillPill.astro +0 -19
- package/site/src/components/StatusBadge.astro +0 -27
- package/site/src/components/TaskEntry.astro +0 -98
- package/site/src/layouts/Layout.astro +0 -268
- package/site/src/lib/api.ts +0 -342
- package/site/src/pages/404.astro +0 -33
- package/site/src/pages/admin.astro +0 -445
- package/site/src/pages/agent/[...id].astro +0 -678
- package/site/src/pages/agents/index.astro +0 -235
- package/site/src/pages/dashboard.astro +0 -244
- package/site/src/pages/docs.astro +0 -191
- package/site/src/pages/how.astro +0 -156
- package/site/src/pages/index.astro +0 -226
- package/site/src/pages/leaderboard.astro +0 -155
- package/site/src/pages/task/[...id].astro +0 -1467
- package/site/src/styles/global.css +0 -159
- package/site/tailwind.config.mjs +0 -94
- package/site/tsconfig.json +0 -5
- package/site/wrangler.toml +0 -5
- package/src/commands/accept.ts +0 -135
- package/src/commands/agents.ts +0 -190
- package/src/commands/approve.ts +0 -127
- package/src/commands/claim.ts +0 -130
- package/src/commands/decline.ts +0 -55
- package/src/commands/dispute.ts +0 -92
- package/src/commands/earnings.ts +0 -86
- package/src/commands/feedback.ts +0 -147
- package/src/commands/gig.ts +0 -141
- package/src/commands/hire.ts +0 -96
- package/src/commands/inbox.ts +0 -135
- package/src/commands/message.ts +0 -97
- package/src/commands/profile.ts +0 -62
- package/src/commands/quote.ts +0 -80
- package/src/commands/refund.ts +0 -82
- package/src/commands/register.ts +0 -250
- package/src/commands/resolve.ts +0 -104
- package/src/commands/reviews.ts +0 -78
- package/src/commands/revise.ts +0 -65
- package/src/commands/submit.ts +0 -123
- package/src/commands/tasks.ts +0 -224
- package/src/commands/view.ts +0 -122
- package/src/commands/wallet.ts +0 -42
- package/src/index.ts +0 -285
- package/src/lib/agent0.ts +0 -158
- package/src/lib/auth.ts +0 -25
- package/src/lib/constants.ts +0 -55
- package/src/lib/escrow.ts +0 -374
- package/src/lib/files.ts +0 -87
- package/src/lib/flaunch.ts +0 -277
- package/src/lib/mandate.ts +0 -623
- package/src/lib/tasks.ts +0 -466
- package/src/lib/types.ts +0 -112
- package/src/lib/wallet.ts +0 -119
- package/src/lib/x402.ts +0 -86
- package/test/MandateEscrowV4.test.cjs +0 -568
- package/tsconfig.json +0 -19
- package/tsup.config.ts +0 -15
- package/worker/package-lock.json +0 -1812
- package/worker/package.json +0 -18
- package/worker/src/agents.ts +0 -755
- package/worker/src/auth.ts +0 -126
- package/worker/src/files.ts +0 -40
- package/worker/src/index.ts +0 -963
- package/worker/src/profiles.ts +0 -85
- package/worker/src/ratelimit.ts +0 -45
- package/worker/src/tasks.ts +0 -498
- package/worker/src/types.ts +0 -95
- package/worker/tsconfig.json +0 -15
- package/worker/wrangler.toml +0 -19
package/src/commands/register.ts
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
// mltl register - Register an agent in MANDATE
|
|
2
|
-
// Launches a Flaunch token (or uses existing) + registers via ERC-8004
|
|
3
|
-
|
|
4
|
-
import { parseEther } from "viem";
|
|
5
|
-
import { loadOrCreateWallet, getWalletBalance } from "../lib/wallet.js";
|
|
6
|
-
import { registerAgent } from "../lib/mandate.js";
|
|
7
|
-
import { launchFlaunchToken } from "../lib/flaunch.js";
|
|
8
|
-
import { signAction } from "../lib/auth.js";
|
|
9
|
-
import { CONTRACTS, CHAIN, APIS } from "../lib/constants.js";
|
|
10
|
-
|
|
11
|
-
interface RegisterOptions {
|
|
12
|
-
name: string;
|
|
13
|
-
description: string;
|
|
14
|
-
skills: string;
|
|
15
|
-
endpoint?: string; // Optional - agents can use task queue instead
|
|
16
|
-
price: string;
|
|
17
|
-
symbol?: string; // Required if launching new token
|
|
18
|
-
token?: string; // Existing Flaunch token address (skips launch)
|
|
19
|
-
image?: string;
|
|
20
|
-
website?: string;
|
|
21
|
-
json?: boolean;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export async function register(options: RegisterOptions): Promise<void> {
|
|
25
|
-
const { wallet, isNew } = await loadOrCreateWallet();
|
|
26
|
-
|
|
27
|
-
if (isNew && !options.json) {
|
|
28
|
-
console.log(`\n✨ Created wallet: ${wallet.address}`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Check balance - need ETH for gas (Flaunch launch is gasless but registration isn't)
|
|
32
|
-
const balance = await getWalletBalance(wallet.address);
|
|
33
|
-
const balanceWei = parseEther(balance);
|
|
34
|
-
|
|
35
|
-
if (balanceWei === 0n) {
|
|
36
|
-
if (options.json) {
|
|
37
|
-
console.log(JSON.stringify({
|
|
38
|
-
error: "Wallet has no ETH. Fund it first.",
|
|
39
|
-
wallet: wallet.address,
|
|
40
|
-
}));
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
console.error(`\n❌ Wallet has no ETH. Send ETH on Base to: ${wallet.address}`);
|
|
44
|
-
process.exit(1);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Validate: need either --token (existing) or --symbol (new launch)
|
|
48
|
-
const hasExistingToken = options.token && /^0x[a-fA-F0-9]{40}$/.test(options.token);
|
|
49
|
-
|
|
50
|
-
if (!hasExistingToken && (!options.symbol || options.symbol.length < 2 || options.symbol.length > 10)) {
|
|
51
|
-
if (options.json) {
|
|
52
|
-
console.log(JSON.stringify({ error: "Provide --token <address> for existing token, or --symbol for new launch" }));
|
|
53
|
-
process.exit(1);
|
|
54
|
-
}
|
|
55
|
-
console.error("❌ Provide --token <address> for existing Flaunch token, or --symbol (2-10 chars) to launch new");
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const skills = options.skills.split(",").map((s) => s.trim().toLowerCase());
|
|
60
|
-
const symbol = options.symbol?.toUpperCase() || "";
|
|
61
|
-
|
|
62
|
-
if (!options.json) {
|
|
63
|
-
console.log("\n═══════════════════════════════════════════════");
|
|
64
|
-
console.log(" MANDATE Agent Registration");
|
|
65
|
-
console.log("═══════════════════════════════════════════════\n");
|
|
66
|
-
console.log(`Name: ${options.name}`);
|
|
67
|
-
if (hasExistingToken) {
|
|
68
|
-
console.log(`Token: ${options.token} (existing)`);
|
|
69
|
-
} else {
|
|
70
|
-
console.log(`Token: $${symbol} (new launch)`);
|
|
71
|
-
}
|
|
72
|
-
console.log(`Description: ${options.description}`);
|
|
73
|
-
console.log(`Skills: ${skills.join(", ")}`);
|
|
74
|
-
if (options.endpoint) {
|
|
75
|
-
console.log(`Endpoint: ${options.endpoint}`);
|
|
76
|
-
} else {
|
|
77
|
-
console.log(`Endpoint: (task queue - use 'mltl inbox' to receive work)`);
|
|
78
|
-
}
|
|
79
|
-
console.log(`Price: ${options.price} ETH per hire`);
|
|
80
|
-
console.log(`Wallet: ${wallet.address}`);
|
|
81
|
-
console.log(`Balance: ${balance} ETH`);
|
|
82
|
-
console.log("\n───────────────────────────────────────────────\n");
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
let tokenAddress: string | undefined;
|
|
86
|
-
let flaunchUrl: string | undefined;
|
|
87
|
-
let tokenTxHash: string | undefined;
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
// Step 1: Launch Flaunch token OR use existing
|
|
91
|
-
if (hasExistingToken) {
|
|
92
|
-
// Use existing token
|
|
93
|
-
tokenAddress = options.token;
|
|
94
|
-
flaunchUrl = `https://flaunch.gg/base/coin/${options.token}`;
|
|
95
|
-
|
|
96
|
-
if (!options.json) {
|
|
97
|
-
console.log("Step 1: Using existing Flaunch token\n");
|
|
98
|
-
console.log(` ✓ Token: ${tokenAddress}`);
|
|
99
|
-
console.log(` ✓ URL: ${flaunchUrl}\n`);
|
|
100
|
-
}
|
|
101
|
-
} else {
|
|
102
|
-
// Launch new token
|
|
103
|
-
if (!options.json) {
|
|
104
|
-
console.log("Step 1: Launching token on Flaunch...\n");
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const tokenResult = await launchFlaunchToken({
|
|
108
|
-
name: options.name,
|
|
109
|
-
symbol,
|
|
110
|
-
description: options.description,
|
|
111
|
-
imagePath: options.image,
|
|
112
|
-
creatorAddress: wallet.address,
|
|
113
|
-
websiteUrl: options.website,
|
|
114
|
-
onProgress: options.json ? undefined : (msg) => console.log(` ${msg}`),
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
tokenAddress = tokenResult.tokenAddress;
|
|
118
|
-
flaunchUrl = tokenResult.flaunchUrl;
|
|
119
|
-
tokenTxHash = tokenResult.transactionHash;
|
|
120
|
-
|
|
121
|
-
if (!options.json) {
|
|
122
|
-
console.log(`\n ✓ Token launched: ${tokenAddress}`);
|
|
123
|
-
console.log(` ✓ TX: ${tokenTxHash}\n`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Step 2: Register agent with ERC-8004
|
|
128
|
-
if (!options.json) {
|
|
129
|
-
console.log("Step 2: Registering agent identity...\n");
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Build agent URI as data URI with JSON metadata
|
|
133
|
-
const agentMetadata = {
|
|
134
|
-
name: options.name,
|
|
135
|
-
description: options.description,
|
|
136
|
-
image: options.image || "",
|
|
137
|
-
};
|
|
138
|
-
const agentURI = `data:application/json;base64,${Buffer.from(JSON.stringify(agentMetadata)).toString("base64")}`;
|
|
139
|
-
|
|
140
|
-
const agentResult = await registerAgent(wallet, agentURI, {
|
|
141
|
-
skills,
|
|
142
|
-
endpoint: options.endpoint || "",
|
|
143
|
-
priceWei: parseEther(options.price),
|
|
144
|
-
flaunchToken: tokenAddress as `0x${string}`,
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// Register in Moltlaunch worker index (authenticated with owner signature)
|
|
148
|
-
try {
|
|
149
|
-
const agentIdStr = agentResult.agentId.toString();
|
|
150
|
-
const { signature, timestamp, nonce } = await signAction(wallet, "register", agentIdStr);
|
|
151
|
-
await fetch(`${APIS.MANDATE}/api/agents/register`, {
|
|
152
|
-
method: "POST",
|
|
153
|
-
headers: { "Content-Type": "application/json" },
|
|
154
|
-
body: JSON.stringify({ agentId: agentIdStr, signature, timestamp, nonce }),
|
|
155
|
-
});
|
|
156
|
-
} catch {
|
|
157
|
-
// Non-fatal - agent is still registered on-chain
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Success output
|
|
161
|
-
if (options.json) {
|
|
162
|
-
console.log(
|
|
163
|
-
JSON.stringify({
|
|
164
|
-
success: true,
|
|
165
|
-
agentId: agentResult.agentId,
|
|
166
|
-
agentURI: agentResult.agentURI,
|
|
167
|
-
tokenAddress,
|
|
168
|
-
tokenSymbol: symbol,
|
|
169
|
-
flaunchUrl,
|
|
170
|
-
tokenTxHash,
|
|
171
|
-
registryTxHash: agentResult.txHash,
|
|
172
|
-
wallet: wallet.address,
|
|
173
|
-
name: options.name,
|
|
174
|
-
skills,
|
|
175
|
-
endpoint: options.endpoint,
|
|
176
|
-
priceEth: options.price,
|
|
177
|
-
registry: CONTRACTS.IDENTITY_REGISTRY,
|
|
178
|
-
})
|
|
179
|
-
);
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
console.log("\n═══════════════════════════════════════════════");
|
|
184
|
-
console.log(" ✅ Registration Complete!");
|
|
185
|
-
console.log("═══════════════════════════════════════════════\n");
|
|
186
|
-
console.log(`Agent ID: ${agentResult.agentId}`);
|
|
187
|
-
console.log(`Name: ${options.name}`);
|
|
188
|
-
console.log(`Token: ${symbol ? `$${symbol}` : tokenAddress}`);
|
|
189
|
-
console.log(`Address: ${tokenAddress}`);
|
|
190
|
-
console.log(`Skills: ${skills.join(", ")}`);
|
|
191
|
-
if (options.endpoint) {
|
|
192
|
-
console.log(`Endpoint: ${options.endpoint}`);
|
|
193
|
-
} else {
|
|
194
|
-
console.log(`Endpoint: (task queue)`);
|
|
195
|
-
}
|
|
196
|
-
console.log(`Price: ${options.price} ETH`);
|
|
197
|
-
console.log(`Wallet: ${wallet.address}`);
|
|
198
|
-
console.log("\n───────────────────────────────────────────────");
|
|
199
|
-
console.log("\nLinks:");
|
|
200
|
-
console.log(` Flaunch: ${flaunchUrl}`);
|
|
201
|
-
if (tokenTxHash) {
|
|
202
|
-
console.log(` Token TX: ${CHAIN.explorer}/tx/${tokenTxHash}`);
|
|
203
|
-
}
|
|
204
|
-
console.log(` Agent TX: ${CHAIN.explorer}/tx/${agentResult.txHash}`);
|
|
205
|
-
console.log("\n───────────────────────────────────────────────");
|
|
206
|
-
if (symbol) {
|
|
207
|
-
console.log("\nYou earn 10% of all $" + symbol + " trading fees forever.");
|
|
208
|
-
}
|
|
209
|
-
console.log("\nOthers can hire your agent with:");
|
|
210
|
-
console.log(` mltl hire --agent ${agentResult.agentId} --task "..."`);
|
|
211
|
-
if (!options.endpoint) {
|
|
212
|
-
console.log("\nTo receive work requests, run:");
|
|
213
|
-
console.log(` mltl inbox --agent ${agentResult.agentId}`);
|
|
214
|
-
}
|
|
215
|
-
console.log("\nOthers can invest in your agent at:");
|
|
216
|
-
console.log(` ${flaunchUrl}`);
|
|
217
|
-
|
|
218
|
-
} catch (err) {
|
|
219
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
220
|
-
|
|
221
|
-
if (options.json) {
|
|
222
|
-
console.log(JSON.stringify({
|
|
223
|
-
error: errorMsg,
|
|
224
|
-
tokenAddress, // Include if token launched but registration failed
|
|
225
|
-
tokenTxHash,
|
|
226
|
-
}));
|
|
227
|
-
process.exit(1);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
console.error(`\n❌ Registration failed: ${errorMsg}`);
|
|
231
|
-
|
|
232
|
-
// If token launched but registration failed, tell user
|
|
233
|
-
if (tokenAddress) {
|
|
234
|
-
console.error(`\n⚠️ Your token was launched but agent registration failed.`);
|
|
235
|
-
console.error(`Token address: ${tokenAddress}`);
|
|
236
|
-
console.error(`You can try registering again without --symbol.`);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (errorMsg.includes("insufficient funds")) {
|
|
240
|
-
console.error(`\nYour wallet balance: ${balance} ETH`);
|
|
241
|
-
console.error(`Send more ETH to: ${wallet.address}`);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (errorMsg.includes("Image is required")) {
|
|
245
|
-
console.error(`\nProvide an image with: --image <path>`);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
process.exit(1);
|
|
249
|
-
}
|
|
250
|
-
}
|
package/src/commands/resolve.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
// mltl resolve - Admin resolves a disputed task
|
|
2
|
-
|
|
3
|
-
import { formatEther } from "viem";
|
|
4
|
-
import { loadOrCreateWallet } from "../lib/wallet.js";
|
|
5
|
-
import { getTask } from "../lib/tasks.js";
|
|
6
|
-
import { getEscrowDetails, resolveEscrowDispute, EscrowStatus } from "../lib/escrow.js";
|
|
7
|
-
import { signAction } from "../lib/auth.js";
|
|
8
|
-
import { APIS } from "../lib/constants.js";
|
|
9
|
-
|
|
10
|
-
interface ResolveOptions {
|
|
11
|
-
task: string;
|
|
12
|
-
winner: string;
|
|
13
|
-
json?: boolean;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export async function resolve(options: ResolveOptions): Promise<void> {
|
|
17
|
-
const { wallet } = await loadOrCreateWallet();
|
|
18
|
-
|
|
19
|
-
if (!["client", "agent"].includes(options.winner)) {
|
|
20
|
-
console.error('❌ --winner must be "client" or "agent"');
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const clientWins = options.winner === "client";
|
|
25
|
-
|
|
26
|
-
if (!options.json) {
|
|
27
|
-
console.log("\nResolving dispute...");
|
|
28
|
-
console.log("──────────────────────────────────────────────");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
const task = await getTask(options.task);
|
|
33
|
-
|
|
34
|
-
if (task.status !== "disputed") {
|
|
35
|
-
throw new Error(`Task is ${task.status}, cannot resolve (must be disputed)`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const escrow = await getEscrowDetails(task.id);
|
|
39
|
-
if (!escrow) {
|
|
40
|
-
throw new Error("No escrow found for this task");
|
|
41
|
-
}
|
|
42
|
-
if (escrow.status !== EscrowStatus.Disputed) {
|
|
43
|
-
throw new Error("Escrow is not in disputed state");
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (!options.json) {
|
|
47
|
-
console.log(`\nTask ID: ${task.id}`);
|
|
48
|
-
console.log(`Escrow: ${formatEther(escrow.amount)} ETH`);
|
|
49
|
-
console.log(`Dispute fee: ${formatEther(escrow.disputeFee)} ETH`);
|
|
50
|
-
console.log(`Resolution: ${clientWins ? "CLIENT WINS (refund)" : "AGENT WINS (buyback)"}`);
|
|
51
|
-
console.log("\nCalling resolveDispute on-chain...");
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const txHash = await resolveEscrowDispute(wallet, task.id, clientWins);
|
|
55
|
-
|
|
56
|
-
// Sign and notify worker
|
|
57
|
-
const { signature, timestamp, nonce } = await signAction(wallet, "resolve", task.id);
|
|
58
|
-
|
|
59
|
-
await fetch(`${APIS.MANDATE}/api/tasks/${task.id}/resolve`, {
|
|
60
|
-
method: "POST",
|
|
61
|
-
headers: { "Content-Type": "application/json" },
|
|
62
|
-
body: JSON.stringify({
|
|
63
|
-
resolution: options.winner,
|
|
64
|
-
txHash,
|
|
65
|
-
signature,
|
|
66
|
-
timestamp,
|
|
67
|
-
nonce,
|
|
68
|
-
}),
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
if (options.json) {
|
|
72
|
-
console.log(
|
|
73
|
-
JSON.stringify({
|
|
74
|
-
success: true,
|
|
75
|
-
taskId: task.id,
|
|
76
|
-
resolution: options.winner,
|
|
77
|
-
txHash,
|
|
78
|
-
})
|
|
79
|
-
);
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
console.log("\nDispute resolved!");
|
|
84
|
-
console.log("──────────────────────────────────────────────");
|
|
85
|
-
console.log(`\nWinner: ${options.winner}`);
|
|
86
|
-
console.log(`TX: ${txHash}`);
|
|
87
|
-
if (clientWins) {
|
|
88
|
-
console.log("\nClient gets escrow + dispute fee refunded.");
|
|
89
|
-
} else {
|
|
90
|
-
console.log("\nAgent gets dispute fee. Escrow released via buyback-and-burn.");
|
|
91
|
-
}
|
|
92
|
-
console.log();
|
|
93
|
-
} catch (err) {
|
|
94
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
95
|
-
|
|
96
|
-
if (options.json) {
|
|
97
|
-
console.log(JSON.stringify({ error: errorMsg }));
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
console.error(`\n❌ Failed to resolve: ${errorMsg}`);
|
|
102
|
-
process.exit(1);
|
|
103
|
-
}
|
|
104
|
-
}
|
package/src/commands/reviews.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// mltl reviews - View verified reviews for an agent
|
|
2
|
-
|
|
3
|
-
import { APIS } from "../lib/constants.js";
|
|
4
|
-
|
|
5
|
-
interface ReviewsOptions {
|
|
6
|
-
agent: string;
|
|
7
|
-
json?: boolean;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
interface Review {
|
|
11
|
-
taskId: string;
|
|
12
|
-
score: number | null;
|
|
13
|
-
comment: string | null;
|
|
14
|
-
reviewer: string;
|
|
15
|
-
ratedAt: number;
|
|
16
|
-
ratedTxHash: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface ReviewsResponse {
|
|
20
|
-
reviews: Review[];
|
|
21
|
-
total: number;
|
|
22
|
-
avgScore: number | null;
|
|
23
|
-
reviewCount: number;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function formatTimestamp(ts: number): string {
|
|
27
|
-
return new Date(ts).toLocaleString();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export async function reviews(options: ReviewsOptions): Promise<void> {
|
|
31
|
-
try {
|
|
32
|
-
const res = await fetch(`${APIS.MANDATE}/api/agents/${encodeURIComponent(options.agent)}/reviews`);
|
|
33
|
-
if (!res.ok) {
|
|
34
|
-
const err = (await res.json()) as { error: string };
|
|
35
|
-
throw new Error(err.error || `HTTP ${res.status}`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const data = (await res.json()) as ReviewsResponse;
|
|
39
|
-
|
|
40
|
-
if (options.json) {
|
|
41
|
-
console.log(JSON.stringify(data));
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
console.log("\n═══════════════════════════════════════════════");
|
|
46
|
-
console.log(` Reviews for Agent #${options.agent}`);
|
|
47
|
-
console.log("═══════════════════════════════════════════════\n");
|
|
48
|
-
|
|
49
|
-
if (data.avgScore !== null) {
|
|
50
|
-
console.log(`Score: ${data.avgScore}/100 (${data.reviewCount} verified review${data.reviewCount !== 1 ? "s" : ""})\n`);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (data.reviews.length === 0) {
|
|
54
|
-
console.log("No reviews yet.\n");
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
console.log("───────────────────────────────────────────────\n");
|
|
59
|
-
for (const review of data.reviews) {
|
|
60
|
-
const scoreStr = review.score !== null ? `${review.score}/100` : "No score";
|
|
61
|
-
console.log(`${scoreStr} ${formatTimestamp(review.ratedAt)}`);
|
|
62
|
-
console.log(`Task: ${review.taskId}`);
|
|
63
|
-
console.log(`Reviewer: ${review.reviewer}`);
|
|
64
|
-
if (review.comment) console.log(`Comment: ${review.comment}`);
|
|
65
|
-
console.log(`TX: ${review.ratedTxHash}\n`);
|
|
66
|
-
}
|
|
67
|
-
} catch (err) {
|
|
68
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
69
|
-
|
|
70
|
-
if (options.json) {
|
|
71
|
-
console.log(JSON.stringify({ error: errorMsg }));
|
|
72
|
-
process.exit(1);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
console.error(`\nFailed to fetch reviews: ${errorMsg}`);
|
|
76
|
-
process.exit(1);
|
|
77
|
-
}
|
|
78
|
-
}
|
package/src/commands/revise.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
// mltl revise - Request revision on submitted work (client action)
|
|
2
|
-
|
|
3
|
-
import { loadOrCreateWallet } from "../lib/wallet.js";
|
|
4
|
-
import { requestRevision, getTask } from "../lib/tasks.js";
|
|
5
|
-
|
|
6
|
-
interface ReviseOptions {
|
|
7
|
-
task: string;
|
|
8
|
-
reason: string;
|
|
9
|
-
json?: boolean;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export async function revise(options: ReviseOptions): Promise<void> {
|
|
13
|
-
const { wallet } = await loadOrCreateWallet();
|
|
14
|
-
|
|
15
|
-
if (!options.json) {
|
|
16
|
-
console.log("\nRequesting revision...");
|
|
17
|
-
console.log("──────────────────────────────────────────────");
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
const taskBefore = await getTask(options.task);
|
|
22
|
-
|
|
23
|
-
if (taskBefore.status !== "submitted") {
|
|
24
|
-
throw new Error(`Task is ${taskBefore.status}, can only request revision on submitted work`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const task = await requestRevision(wallet, options.task, options.reason);
|
|
28
|
-
|
|
29
|
-
if (options.json) {
|
|
30
|
-
console.log(
|
|
31
|
-
JSON.stringify({
|
|
32
|
-
success: true,
|
|
33
|
-
task: {
|
|
34
|
-
id: task.id,
|
|
35
|
-
agentId: task.agentId,
|
|
36
|
-
status: task.status,
|
|
37
|
-
revisionCount: task.revisionCount,
|
|
38
|
-
},
|
|
39
|
-
}),
|
|
40
|
-
);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
console.log("\nRevision requested!");
|
|
45
|
-
console.log("──────────────────────────────────────────────");
|
|
46
|
-
console.log(`\nTask ID: ${task.id}`);
|
|
47
|
-
console.log(`Status: ${task.status}`);
|
|
48
|
-
console.log(`Revisions: ${task.revisionCount || 1}`);
|
|
49
|
-
console.log(`\nYour feedback:\n${options.reason}\n`);
|
|
50
|
-
console.log("──────────────────────────────────────────────");
|
|
51
|
-
console.log("\nThe agent will revise and resubmit their work.");
|
|
52
|
-
console.log("You can also send messages with:");
|
|
53
|
-
console.log(` mltl message --task ${task.id} --content "additional details"\n`);
|
|
54
|
-
} catch (err) {
|
|
55
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
56
|
-
|
|
57
|
-
if (options.json) {
|
|
58
|
-
console.log(JSON.stringify({ error: errorMsg }));
|
|
59
|
-
process.exit(1);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
console.error(`\nFailed to request revision: ${errorMsg}`);
|
|
63
|
-
process.exit(1);
|
|
64
|
-
}
|
|
65
|
-
}
|
package/src/commands/submit.ts
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
// mltl submit - Submit completed work for a task (agent action)
|
|
2
|
-
// Also marks submission onchain to start 24h timeout countdown
|
|
3
|
-
|
|
4
|
-
import { formatEther } from "viem";
|
|
5
|
-
import { loadOrCreateWallet } from "../lib/wallet.js";
|
|
6
|
-
import { submitTask, getTask } from "../lib/tasks.js";
|
|
7
|
-
import { markSubmitted, isEscrowPending } from "../lib/escrow.js";
|
|
8
|
-
import { uploadFiles } from "../lib/files.js";
|
|
9
|
-
import type { TaskFile } from "../lib/types.js";
|
|
10
|
-
|
|
11
|
-
interface SubmitOptions {
|
|
12
|
-
task: string;
|
|
13
|
-
result: string;
|
|
14
|
-
files?: string;
|
|
15
|
-
json?: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export async function submit(options: SubmitOptions): Promise<void> {
|
|
19
|
-
const { wallet } = await loadOrCreateWallet();
|
|
20
|
-
|
|
21
|
-
if (!options.json) {
|
|
22
|
-
console.log("\nSubmitting work...");
|
|
23
|
-
console.log("──────────────────────────────────────────────");
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
let isRevision = false;
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
// First verify task exists and is in accepted state
|
|
30
|
-
const taskBefore = await getTask(options.task);
|
|
31
|
-
|
|
32
|
-
if (taskBefore.status !== "accepted" && taskBefore.status !== "revision") {
|
|
33
|
-
throw new Error(`Task is ${taskBefore.status}, cannot submit (must be accepted or in revision)`);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
isRevision = taskBefore.status === "revision";
|
|
37
|
-
|
|
38
|
-
// Upload files if provided
|
|
39
|
-
let uploadedFiles: TaskFile[] | undefined;
|
|
40
|
-
if (options.files) {
|
|
41
|
-
const filePaths = options.files.split(",").map((f) => f.trim());
|
|
42
|
-
if (!options.json) {
|
|
43
|
-
console.log(`\nUploading ${filePaths.length} file(s)...`);
|
|
44
|
-
}
|
|
45
|
-
uploadedFiles = await uploadFiles(wallet, options.task, filePaths);
|
|
46
|
-
if (!options.json) {
|
|
47
|
-
for (const f of uploadedFiles) {
|
|
48
|
-
console.log(` Uploaded: ${f.name} (${f.size} bytes)`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Submit the work to task queue (signed with wallet)
|
|
54
|
-
const task = await submitTask(wallet, options.task, options.result, uploadedFiles);
|
|
55
|
-
|
|
56
|
-
// Check if escrow exists for this task (skip on revision — already marked on first submit)
|
|
57
|
-
const hasEscrow = !isRevision && await isEscrowPending(options.task);
|
|
58
|
-
let escrowTxHash: string | null = null;
|
|
59
|
-
|
|
60
|
-
if (hasEscrow) {
|
|
61
|
-
if (!options.json) {
|
|
62
|
-
console.log("\nMarking submission onchain (starts 24h timeout)...");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Mark submitted on escrow contract (starts timeout countdown)
|
|
66
|
-
escrowTxHash = await markSubmitted(wallet, options.task);
|
|
67
|
-
|
|
68
|
-
if (!options.json) {
|
|
69
|
-
console.log(`Escrow TX: ${escrowTxHash}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (options.json) {
|
|
74
|
-
console.log(
|
|
75
|
-
JSON.stringify({
|
|
76
|
-
success: true,
|
|
77
|
-
task: {
|
|
78
|
-
id: task.id,
|
|
79
|
-
agentId: task.agentId,
|
|
80
|
-
status: task.status,
|
|
81
|
-
quotedPriceWei: task.quotedPriceWei,
|
|
82
|
-
result: task.result,
|
|
83
|
-
},
|
|
84
|
-
escrow: escrowTxHash ? { txHash: escrowTxHash, timeoutHours: 24 } : null,
|
|
85
|
-
}),
|
|
86
|
-
);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const priceEth = task.quotedPriceWei ? formatEther(BigInt(task.quotedPriceWei)) : "0";
|
|
91
|
-
|
|
92
|
-
console.log(isRevision ? "\n✅ Revised work submitted!" : "\n✅ Work submitted!");
|
|
93
|
-
console.log("──────────────────────────────────────────────");
|
|
94
|
-
console.log(`\nTask ID: ${task.id}`);
|
|
95
|
-
console.log(`Status: ${task.status}`);
|
|
96
|
-
if (isRevision) {
|
|
97
|
-
console.log(`Revision: #${taskBefore.revisionCount || 1}`);
|
|
98
|
-
}
|
|
99
|
-
console.log(`Price: ${priceEth} ETH`);
|
|
100
|
-
if (escrowTxHash) {
|
|
101
|
-
console.log(`\nTimeout: 24 hours (auto-release if client doesn't respond)`);
|
|
102
|
-
}
|
|
103
|
-
console.log(`\nYour result:\n${options.result}\n`);
|
|
104
|
-
console.log("──────────────────────────────────────────────");
|
|
105
|
-
console.log("\nThe client will review your work.");
|
|
106
|
-
if (escrowTxHash) {
|
|
107
|
-
console.log("If they don't respond within 24h, you can claim payment with:");
|
|
108
|
-
console.log(` mltl claim --task ${task.id}\n`);
|
|
109
|
-
} else {
|
|
110
|
-
console.log("Once approved, payment will be sent to your wallet.\n");
|
|
111
|
-
}
|
|
112
|
-
} catch (err) {
|
|
113
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
114
|
-
|
|
115
|
-
if (options.json) {
|
|
116
|
-
console.log(JSON.stringify({ error: errorMsg }));
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
console.error(`\n❌ Failed to submit work: ${errorMsg}`);
|
|
121
|
-
process.exit(1);
|
|
122
|
-
}
|
|
123
|
-
}
|