moltlaunch 2.2.0 → 2.4.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/dist/index.js +277 -55
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -919,8 +919,19 @@ async function register(options) {
|
|
|
919
919
|
if (regRes.ok) {
|
|
920
920
|
const regData = await regRes.json();
|
|
921
921
|
registrationStatus = regData.status === "approved" ? "approved" : "pending";
|
|
922
|
+
} else {
|
|
923
|
+
const errData = await regRes.json().catch(() => ({ error: "Unknown error" }));
|
|
924
|
+
if (!options.json) {
|
|
925
|
+
console.log(`
|
|
926
|
+
\u26A0\uFE0F Marketplace registration failed: ${errData.error || regRes.status}`);
|
|
927
|
+
console.log(" Your agent is registered on-chain but may not appear in the marketplace yet.");
|
|
928
|
+
console.log(" Contact admin or try: mltl register --token <address> to re-register.");
|
|
929
|
+
}
|
|
922
930
|
}
|
|
923
931
|
} catch {
|
|
932
|
+
if (!options.json) {
|
|
933
|
+
console.log("\n\u26A0\uFE0F Could not reach marketplace API. Agent is registered on-chain.");
|
|
934
|
+
}
|
|
924
935
|
}
|
|
925
936
|
if (options.json) {
|
|
926
937
|
console.log(
|
|
@@ -1021,14 +1032,18 @@ Provide an image with: --image <path>`);
|
|
|
1021
1032
|
|
|
1022
1033
|
// src/lib/tasks.ts
|
|
1023
1034
|
var API_BASE = APIS.MOLTLAUNCH;
|
|
1024
|
-
async function createTask(agentId, clientAddress, taskDescription) {
|
|
1035
|
+
async function createTask(wallet2, agentId, clientAddress, taskDescription) {
|
|
1036
|
+
const { signature, timestamp, nonce } = await signAction(wallet2, "create", agentId);
|
|
1025
1037
|
const response = await fetch(`${API_BASE}/api/tasks`, {
|
|
1026
1038
|
method: "POST",
|
|
1027
1039
|
headers: { "Content-Type": "application/json" },
|
|
1028
1040
|
body: JSON.stringify({
|
|
1029
1041
|
agentId,
|
|
1030
1042
|
clientAddress,
|
|
1031
|
-
task: taskDescription
|
|
1043
|
+
task: taskDescription,
|
|
1044
|
+
signature,
|
|
1045
|
+
timestamp,
|
|
1046
|
+
nonce
|
|
1032
1047
|
})
|
|
1033
1048
|
});
|
|
1034
1049
|
if (!response.ok) {
|
|
@@ -1310,7 +1325,7 @@ Task: ${options.task}
|
|
|
1310
1325
|
`);
|
|
1311
1326
|
console.log("Creating task request...");
|
|
1312
1327
|
}
|
|
1313
|
-
const task = await createTask(agentId, wallet2.address, options.task);
|
|
1328
|
+
const task = await createTask(wallet2, agentId, wallet2.address, options.task);
|
|
1314
1329
|
if (options.json) {
|
|
1315
1330
|
console.log(
|
|
1316
1331
|
JSON.stringify({
|
|
@@ -1318,7 +1333,14 @@ Task: ${options.task}
|
|
|
1318
1333
|
taskId: task.id,
|
|
1319
1334
|
agentId,
|
|
1320
1335
|
status: task.status,
|
|
1321
|
-
task: task.task
|
|
1336
|
+
task: task.task,
|
|
1337
|
+
nextActions: [
|
|
1338
|
+
{ command: `mltl tasks`, description: "Check task status and quotes" },
|
|
1339
|
+
{ command: `mltl view --task ${task.id}`, description: "View task details" },
|
|
1340
|
+
{ command: `mltl message --task ${task.id} --content "..."`, description: "Add details for the agent" }
|
|
1341
|
+
],
|
|
1342
|
+
flow: "[requested] \u2192 quoted \u2192 accepted \u2192 submitted \u2192 completed",
|
|
1343
|
+
note: "No funds committed. The agent will quote a price. You decide whether to accept."
|
|
1322
1344
|
})
|
|
1323
1345
|
);
|
|
1324
1346
|
return;
|
|
@@ -1330,9 +1352,12 @@ Task ID: ${task.id}`);
|
|
|
1330
1352
|
console.log(`Agent: ${name} (#${agentId})`);
|
|
1331
1353
|
console.log(`Status: ${task.status}`);
|
|
1332
1354
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
1333
|
-
console.log("\
|
|
1334
|
-
console.log("
|
|
1335
|
-
console.log(
|
|
1355
|
+
console.log("\nNo funds committed yet. The agent will review and quote a price.");
|
|
1356
|
+
console.log("You can accept, negotiate, or walk away at no cost.\n");
|
|
1357
|
+
console.log("Next steps:");
|
|
1358
|
+
console.log(` Check for quotes: mltl tasks`);
|
|
1359
|
+
console.log(` View details: mltl view --task ${task.id}`);
|
|
1360
|
+
console.log(` Add context: mltl message --task ${task.id} --content "..."
|
|
1336
1361
|
`);
|
|
1337
1362
|
} catch (err) {
|
|
1338
1363
|
if (options.json) {
|
|
@@ -1794,7 +1819,11 @@ async function inbox(options) {
|
|
|
1794
1819
|
const tasks2 = await getInbox(agentId);
|
|
1795
1820
|
if (tasks2.length === 0) {
|
|
1796
1821
|
if (options.json) {
|
|
1797
|
-
console.log(JSON.stringify({
|
|
1822
|
+
console.log(JSON.stringify({
|
|
1823
|
+
tasks: [],
|
|
1824
|
+
total: 0,
|
|
1825
|
+
polling: { recommended: "5m", note: "No active tasks. Check less frequently." }
|
|
1826
|
+
}));
|
|
1798
1827
|
return;
|
|
1799
1828
|
}
|
|
1800
1829
|
console.log("No pending tasks.\n");
|
|
@@ -1802,8 +1831,28 @@ async function inbox(options) {
|
|
|
1802
1831
|
console.log("Run this command periodically to check for new work.\n");
|
|
1803
1832
|
return;
|
|
1804
1833
|
}
|
|
1834
|
+
const hasRevision = tasks2.some((t) => t.status === "revision");
|
|
1835
|
+
const hasRequested = tasks2.some((t) => t.status === "requested");
|
|
1836
|
+
const hasSubmitted = tasks2.some((t) => t.status === "submitted");
|
|
1837
|
+
let pollingInterval = "5m";
|
|
1838
|
+
let pollingNote = "Normal activity.";
|
|
1839
|
+
if (hasRevision) {
|
|
1840
|
+
pollingInterval = "1m";
|
|
1841
|
+
pollingNote = "Revision requested \u2014 client is waiting for your rework.";
|
|
1842
|
+
} else if (hasRequested) {
|
|
1843
|
+
pollingInterval = "2m";
|
|
1844
|
+
pollingNote = "New requests \u2014 quote promptly to win the work.";
|
|
1845
|
+
} else if (hasSubmitted) {
|
|
1846
|
+
pollingInterval = "5m";
|
|
1847
|
+
pollingNote = "Waiting on client review. Check back periodically.";
|
|
1848
|
+
}
|
|
1805
1849
|
if (options.json) {
|
|
1806
|
-
console.log(JSON.stringify({
|
|
1850
|
+
console.log(JSON.stringify({
|
|
1851
|
+
tasks: tasks2,
|
|
1852
|
+
total: tasks2.length,
|
|
1853
|
+
polling: { recommended: pollingInterval, note: pollingNote },
|
|
1854
|
+
flow: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 completed"
|
|
1855
|
+
}));
|
|
1807
1856
|
return;
|
|
1808
1857
|
}
|
|
1809
1858
|
for (const group of STATUS_GROUPS) {
|
|
@@ -2129,6 +2178,7 @@ Task ID: ${taskBefore.id}`);
|
|
|
2129
2178
|
console.log(`Agent: #${taskBefore.agentId} (${agent.name || "Unknown"})`);
|
|
2130
2179
|
console.log(`Owner: ${agentOwner}`);
|
|
2131
2180
|
console.log(`Quote: ${priceEth} ETH`);
|
|
2181
|
+
console.log(`Balance: ${balance} ETH`);
|
|
2132
2182
|
if (taskBefore.quotedMessage) {
|
|
2133
2183
|
console.log(`Message: ${taskBefore.quotedMessage}`);
|
|
2134
2184
|
}
|
|
@@ -2136,6 +2186,12 @@ Task ID: ${taskBefore.id}`);
|
|
|
2136
2186
|
Task:
|
|
2137
2187
|
${taskBefore.task}
|
|
2138
2188
|
`);
|
|
2189
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2190
|
+
console.log(`
|
|
2191
|
+
This will deposit ${priceEth} ETH into escrow.`);
|
|
2192
|
+
console.log("Funds are locked until you approve the work or request a refund.");
|
|
2193
|
+
console.log(" - Approve submitted work: funds buy back & burn agent's token");
|
|
2194
|
+
console.log(" - Cancel before submission: 10% fee to agent, 90% refunded");
|
|
2139
2195
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2140
2196
|
console.log("\nDepositing funds into escrow...");
|
|
2141
2197
|
}
|
|
@@ -2159,7 +2215,14 @@ ${taskBefore.task}
|
|
|
2159
2215
|
txHash: escrowTxHash,
|
|
2160
2216
|
amount: priceEth,
|
|
2161
2217
|
tokenAddress: agentToken
|
|
2162
|
-
}
|
|
2218
|
+
},
|
|
2219
|
+
nextActions: [
|
|
2220
|
+
{ command: `mltl tasks`, description: "Check task status" },
|
|
2221
|
+
{ command: `mltl message --task ${task.id} --content "..."`, description: "Message the agent" },
|
|
2222
|
+
{ command: `mltl cancel --task ${task.id}`, description: "Cancel (10% fee to agent)" }
|
|
2223
|
+
],
|
|
2224
|
+
flow: "requested \u2192 quoted \u2192 [accepted] \u2192 submitted \u2192 completed",
|
|
2225
|
+
note: "Funds are locked in escrow. Agent can now begin work."
|
|
2163
2226
|
})
|
|
2164
2227
|
);
|
|
2165
2228
|
return;
|
|
@@ -2169,9 +2232,12 @@ ${taskBefore.task}
|
|
|
2169
2232
|
Escrow: ${priceEth} ETH deposited`);
|
|
2170
2233
|
console.log(`Token: ${agentToken}`);
|
|
2171
2234
|
console.log(`TX: ${escrowTxHash}`);
|
|
2172
|
-
console.log("\
|
|
2173
|
-
console.log("
|
|
2174
|
-
console.log(
|
|
2235
|
+
console.log("\nThe agent can now begin work. When they submit:");
|
|
2236
|
+
console.log(" - Review & approve: mltl approve --task " + task.id);
|
|
2237
|
+
console.log(" - Request changes: mltl revise --task " + task.id + ' --reason "..."');
|
|
2238
|
+
console.log(" - Cancel (10% fee): mltl cancel --task " + task.id);
|
|
2239
|
+
console.log(`
|
|
2240
|
+
Flow: requested \u2192 quoted \u2192 [accepted] \u2192 submitted \u2192 completed
|
|
2175
2241
|
`);
|
|
2176
2242
|
} catch (err) {
|
|
2177
2243
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -2204,14 +2270,19 @@ async function decline(options) {
|
|
|
2204
2270
|
task: {
|
|
2205
2271
|
id: task.id,
|
|
2206
2272
|
status: task.status
|
|
2207
|
-
}
|
|
2273
|
+
},
|
|
2274
|
+
nextActions: [
|
|
2275
|
+
{ command: `mltl inbox`, description: "Check for other tasks" }
|
|
2276
|
+
],
|
|
2277
|
+
note: "Declined tasks are tracked in your stats. This is normal \u2014 only accept work you can deliver."
|
|
2208
2278
|
})
|
|
2209
2279
|
);
|
|
2210
2280
|
return;
|
|
2211
2281
|
}
|
|
2212
2282
|
console.log(`
|
|
2213
2283
|
\u2705 Task ${task.id} declined.`);
|
|
2214
|
-
console.log("\nThe client will be notified
|
|
2284
|
+
console.log("\nThe client will be notified.");
|
|
2285
|
+
console.log("Tip: Declining tasks you can't deliver is better than accepting and underdelivering.\n");
|
|
2215
2286
|
} catch (err) {
|
|
2216
2287
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
2217
2288
|
if (options.json) {
|
|
@@ -2317,6 +2388,13 @@ Uploading ${filePaths.length} file(s)...`);
|
|
|
2317
2388
|
}
|
|
2318
2389
|
}
|
|
2319
2390
|
if (options.json) {
|
|
2391
|
+
const nextActions = [
|
|
2392
|
+
{ command: `mltl view --task ${task.id}`, description: "View full task thread" },
|
|
2393
|
+
{ command: `mltl message --task ${task.id} --content "..."`, description: "Message the client" }
|
|
2394
|
+
];
|
|
2395
|
+
if (escrowTxHash) {
|
|
2396
|
+
nextActions.push({ command: `mltl claim --task ${task.id}`, description: "Claim payment after 24h timeout" });
|
|
2397
|
+
}
|
|
2320
2398
|
console.log(
|
|
2321
2399
|
JSON.stringify({
|
|
2322
2400
|
success: true,
|
|
@@ -2327,7 +2405,10 @@ Uploading ${filePaths.length} file(s)...`);
|
|
|
2327
2405
|
quotedPriceWei: task.quotedPriceWei,
|
|
2328
2406
|
result: task.result
|
|
2329
2407
|
},
|
|
2330
|
-
escrow: escrowTxHash ? { txHash: escrowTxHash, timeoutHours: 24 } : null
|
|
2408
|
+
escrow: escrowTxHash ? { txHash: escrowTxHash, timeoutHours: 24 } : null,
|
|
2409
|
+
nextActions,
|
|
2410
|
+
flow: isRevision ? "requested \u2192 quoted \u2192 accepted \u2192 revision \u2192 [submitted] \u2192 completed" : "requested \u2192 quoted \u2192 accepted \u2192 [submitted] \u2192 completed",
|
|
2411
|
+
note: escrowTxHash ? "24h countdown started. Client must approve, revise, or dispute within 24h \u2014 otherwise you can claim payment." : "Awaiting client review."
|
|
2331
2412
|
})
|
|
2332
2413
|
);
|
|
2333
2414
|
return;
|
|
@@ -2344,21 +2425,23 @@ Task ID: ${task.id}`);
|
|
|
2344
2425
|
console.log(`Price: ${priceEth} ETH`);
|
|
2345
2426
|
if (escrowTxHash) {
|
|
2346
2427
|
console.log(`
|
|
2347
|
-
Timeout: 24 hours
|
|
2428
|
+
Timeout: 24 hours from now`);
|
|
2429
|
+
console.log(` Client must respond or you can auto-claim payment.`);
|
|
2348
2430
|
}
|
|
2349
2431
|
console.log(`
|
|
2350
2432
|
Your result:
|
|
2351
2433
|
${options.result}
|
|
2352
2434
|
`);
|
|
2353
2435
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2354
|
-
console.log("\
|
|
2436
|
+
console.log("\nWhat happens next:");
|
|
2437
|
+
console.log(" - Client approves \u2192 payment released (buyback & burn)");
|
|
2438
|
+
console.log(" - Client revises \u2192 you'll see it in your inbox");
|
|
2355
2439
|
if (escrowTxHash) {
|
|
2356
|
-
console.log("
|
|
2357
|
-
console.log(` mltl claim --task ${task.id}
|
|
2358
|
-
`);
|
|
2359
|
-
} else {
|
|
2360
|
-
console.log("Once approved, payment will be sent to your wallet.\n");
|
|
2440
|
+
console.log(" - No response 24h \u2192 claim with: mltl claim --task " + task.id);
|
|
2361
2441
|
}
|
|
2442
|
+
console.log(`
|
|
2443
|
+
Check status: mltl view --task ${task.id}
|
|
2444
|
+
`);
|
|
2362
2445
|
} catch (err) {
|
|
2363
2446
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
2364
2447
|
if (options.json) {
|
|
@@ -2423,6 +2506,9 @@ Task ID: ${task.id}`);
|
|
|
2423
2506
|
Submitted result:
|
|
2424
2507
|
${task.result}
|
|
2425
2508
|
`);
|
|
2509
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2510
|
+
console.log("\nThis will release payment. This action is final and irreversible.");
|
|
2511
|
+
console.log("If unsatisfied, use 'mltl revise' or 'mltl dispute' instead.");
|
|
2426
2512
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2427
2513
|
console.log("\nReleasing payment from escrow...");
|
|
2428
2514
|
}
|
|
@@ -2444,7 +2530,11 @@ ${task.result}
|
|
|
2444
2530
|
amount: priceEth,
|
|
2445
2531
|
txHash,
|
|
2446
2532
|
type: "escrow_release"
|
|
2447
|
-
}
|
|
2533
|
+
},
|
|
2534
|
+
nextActions: [
|
|
2535
|
+
{ command: `mltl feedback --task ${completedTask.id} --score <0-100>`, description: "Leave a verified review (on-chain)" }
|
|
2536
|
+
],
|
|
2537
|
+
flow: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 [completed]"
|
|
2448
2538
|
})
|
|
2449
2539
|
);
|
|
2450
2540
|
return;
|
|
@@ -2454,8 +2544,9 @@ ${task.result}
|
|
|
2454
2544
|
console.log(`
|
|
2455
2545
|
Payment: ${priceEth} ETH \u2192 ${agentOwner}`);
|
|
2456
2546
|
console.log(`TX: ${txHash}`);
|
|
2457
|
-
console.log("\
|
|
2458
|
-
console.log(` mltl feedback --
|
|
2547
|
+
console.log("\nLeave a verified review (score 0-100):");
|
|
2548
|
+
console.log(` mltl feedback --task ${completedTask.id} --score 90`);
|
|
2549
|
+
console.log(` mltl feedback --task ${completedTask.id} --score 85 --comment "Great work"
|
|
2459
2550
|
`);
|
|
2460
2551
|
} catch (err) {
|
|
2461
2552
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -2486,7 +2577,14 @@ async function tasks(options) {
|
|
|
2486
2577
|
const allTasks = await getClientTasks(wallet2.address);
|
|
2487
2578
|
if (allTasks.length === 0) {
|
|
2488
2579
|
if (options.json) {
|
|
2489
|
-
console.log(JSON.stringify({
|
|
2580
|
+
console.log(JSON.stringify({
|
|
2581
|
+
tasks: [],
|
|
2582
|
+
total: 0,
|
|
2583
|
+
nextActions: [
|
|
2584
|
+
{ command: `mltl agents`, description: "Browse available agents" },
|
|
2585
|
+
{ command: `mltl hire --agent <id> --task "..."`, description: "Request work from an agent" }
|
|
2586
|
+
]
|
|
2587
|
+
}));
|
|
2490
2588
|
return;
|
|
2491
2589
|
}
|
|
2492
2590
|
console.log("No tasks yet.\n");
|
|
@@ -2494,8 +2592,24 @@ async function tasks(options) {
|
|
|
2494
2592
|
console.log(' mltl hire --agent <id> --task "Your task description"\n');
|
|
2495
2593
|
return;
|
|
2496
2594
|
}
|
|
2595
|
+
const hasSubmittedReview = allTasks.some((t) => t.status === "submitted");
|
|
2596
|
+
const hasQuoted = allTasks.some((t) => t.status === "quoted");
|
|
2597
|
+
let pollingInterval = "5m";
|
|
2598
|
+
let pollingNote = "Normal activity.";
|
|
2599
|
+
if (hasSubmittedReview) {
|
|
2600
|
+
pollingInterval = "1m";
|
|
2601
|
+
pollingNote = "Work submitted \u2014 review and approve/revise promptly so agent can get paid.";
|
|
2602
|
+
} else if (hasQuoted) {
|
|
2603
|
+
pollingInterval = "2m";
|
|
2604
|
+
pollingNote = "Quote received \u2014 accept to lock escrow and start work.";
|
|
2605
|
+
}
|
|
2497
2606
|
if (options.json) {
|
|
2498
|
-
console.log(JSON.stringify({
|
|
2607
|
+
console.log(JSON.stringify({
|
|
2608
|
+
tasks: allTasks,
|
|
2609
|
+
total: allTasks.length,
|
|
2610
|
+
polling: { recommended: pollingInterval, note: pollingNote },
|
|
2611
|
+
flow: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 completed"
|
|
2612
|
+
}));
|
|
2499
2613
|
return;
|
|
2500
2614
|
}
|
|
2501
2615
|
const needsReview = allTasks.filter((t) => t.status === "submitted");
|
|
@@ -2683,6 +2797,11 @@ ${taskBefore.task}
|
|
|
2683
2797
|
console.log(`Message: ${options.message}`);
|
|
2684
2798
|
}
|
|
2685
2799
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2800
|
+
if (taskBefore.status === "quoted") {
|
|
2801
|
+
console.log("\nNote: Updating your previous quote. Client has not yet accepted.");
|
|
2802
|
+
}
|
|
2803
|
+
console.log("\nBy quoting, you commit to delivering this work at this price.");
|
|
2804
|
+
console.log("The client can accept at any time, locking funds in escrow.");
|
|
2686
2805
|
}
|
|
2687
2806
|
const task = await quoteTask(wallet2, options.task, priceWei.toString(), options.message);
|
|
2688
2807
|
if (options.json) {
|
|
@@ -2695,17 +2814,24 @@ ${taskBefore.task}
|
|
|
2695
2814
|
status: task.status,
|
|
2696
2815
|
quotedPriceWei: task.quotedPriceWei,
|
|
2697
2816
|
quotedMessage: task.quotedMessage
|
|
2698
|
-
}
|
|
2817
|
+
},
|
|
2818
|
+
nextActions: [
|
|
2819
|
+
{ command: `mltl inbox`, description: "Check inbox for status updates" },
|
|
2820
|
+
{ command: `mltl message --task ${task.id} --content "..."`, description: "Message the client" }
|
|
2821
|
+
],
|
|
2822
|
+
flow: "requested \u2192 [quoted] \u2192 accepted \u2192 submitted \u2192 completed"
|
|
2699
2823
|
})
|
|
2700
2824
|
);
|
|
2701
2825
|
return;
|
|
2702
2826
|
}
|
|
2703
2827
|
console.log("\n\u2705 Quote submitted!");
|
|
2704
2828
|
console.log("\nThe client will review your quote.");
|
|
2705
|
-
console.log("If they accept,
|
|
2706
|
-
console.log("
|
|
2707
|
-
console.log(
|
|
2708
|
-
console.log(` mltl
|
|
2829
|
+
console.log("If they accept, funds lock in escrow and you can begin work.\n");
|
|
2830
|
+
console.log("Next steps:");
|
|
2831
|
+
console.log(` Check inbox: mltl inbox`);
|
|
2832
|
+
console.log(` Send a message: mltl message --task ${task.id} --content "..."`);
|
|
2833
|
+
console.log(`
|
|
2834
|
+
Flow: requested \u2192 [quoted] \u2192 accepted \u2192 submitted \u2192 completed
|
|
2709
2835
|
`);
|
|
2710
2836
|
} catch (err) {
|
|
2711
2837
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -2861,12 +2987,17 @@ Task ID: ${task.id}`);
|
|
|
2861
2987
|
success: true,
|
|
2862
2988
|
taskId: task.id,
|
|
2863
2989
|
refundedAmount: formatEther10(escrow.amount),
|
|
2864
|
-
txHash
|
|
2990
|
+
txHash,
|
|
2991
|
+
nextActions: [
|
|
2992
|
+
{ command: `mltl hire --agent ${task.agentId} --task "..."`, description: "Hire the same agent again" },
|
|
2993
|
+
{ command: `mltl agents`, description: "Browse other agents" }
|
|
2994
|
+
],
|
|
2995
|
+
note: "Full refund \u2014 no fees deducted. Task is closed."
|
|
2865
2996
|
})
|
|
2866
2997
|
);
|
|
2867
2998
|
return;
|
|
2868
2999
|
}
|
|
2869
|
-
console.log("\n\u2705 Refund successful!");
|
|
3000
|
+
console.log("\n\u2705 Refund successful! No fees deducted.");
|
|
2870
3001
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2871
3002
|
console.log(`
|
|
2872
3003
|
Refunded: ${formatEther10(escrow.amount)} ETH \u2192 ${wallet2.address}`);
|
|
@@ -2912,9 +3043,11 @@ async function cancel(options) {
|
|
|
2912
3043
|
console.log(`
|
|
2913
3044
|
Task ID: ${task.id}`);
|
|
2914
3045
|
console.log(`Escrowed: ${formatEther11(escrow.amount)} ETH`);
|
|
2915
|
-
console.log(`Cancel fee: ${formatEther11(fee)} ETH (10% to agent)`);
|
|
3046
|
+
console.log(`Cancel fee: ${formatEther11(fee)} ETH (10% to agent for lost opportunity)`);
|
|
2916
3047
|
console.log(`You receive: ${formatEther11(escrow.amount - fee)} ETH`);
|
|
2917
|
-
console.log("\
|
|
3048
|
+
console.log("\nNote: If the agent hasn't started yet, consider 'mltl refund' instead (no fee).");
|
|
3049
|
+
console.log("Cancel is for tasks already accepted by the agent.\n");
|
|
3050
|
+
console.log("Cancelling...");
|
|
2918
3051
|
}
|
|
2919
3052
|
const txHash = await cancelEscrow(wallet2, task.id);
|
|
2920
3053
|
try {
|
|
@@ -2928,7 +3061,11 @@ Task ID: ${task.id}`);
|
|
|
2928
3061
|
taskId: task.id,
|
|
2929
3062
|
cancelFee: formatEther11(fee),
|
|
2930
3063
|
refundedAmount: formatEther11(escrow.amount - fee),
|
|
2931
|
-
txHash
|
|
3064
|
+
txHash,
|
|
3065
|
+
nextActions: [
|
|
3066
|
+
{ command: `mltl hire --agent ${task.agentId} --task "..."`, description: "Hire the same agent again" },
|
|
3067
|
+
{ command: `mltl agents`, description: "Browse other agents" }
|
|
3068
|
+
]
|
|
2932
3069
|
})
|
|
2933
3070
|
);
|
|
2934
3071
|
return;
|
|
@@ -2981,7 +3118,12 @@ async function dispute(options) {
|
|
|
2981
3118
|
console.log(`
|
|
2982
3119
|
Task ID: ${task.id}`);
|
|
2983
3120
|
console.log(`Escrow: ${formatEther12(escrow.amount)} ETH`);
|
|
2984
|
-
console.log(`Dispute fee: ${feeEth} ETH (10% of escrow)`);
|
|
3121
|
+
console.log(`Dispute fee: ${feeEth} ETH (10% of escrow, non-refundable if you lose)`);
|
|
3122
|
+
console.log("\n\u26A0 Disputes are a last resort. Consider these alternatives first:");
|
|
3123
|
+
console.log(` Request revision: mltl revise --task ${task.id} --reason "..."`);
|
|
3124
|
+
console.log(` Message the agent: mltl message --task ${task.id} --content "..."`);
|
|
3125
|
+
console.log("\n If you win: escrow refunded + dispute fee returned.");
|
|
3126
|
+
console.log(" If you lose: agent gets paid, you lose the dispute fee.");
|
|
2985
3127
|
console.log("\nOpening dispute...");
|
|
2986
3128
|
}
|
|
2987
3129
|
const txHash = await disputeEscrow(wallet2, task.id, feeWei);
|
|
@@ -2997,18 +3139,25 @@ Task ID: ${task.id}`);
|
|
|
2997
3139
|
success: true,
|
|
2998
3140
|
taskId: task.id,
|
|
2999
3141
|
disputeFee: feeEth,
|
|
3000
|
-
txHash
|
|
3142
|
+
txHash,
|
|
3143
|
+
note: "Timeout frozen. Admin will review. If you win: escrow + fee returned. If you lose: agent gets paid, fee lost.",
|
|
3144
|
+
nextActions: [
|
|
3145
|
+
{ command: `mltl message --task ${task.id} --content "..."`, description: "Add context for the admin" },
|
|
3146
|
+
{ command: `mltl view --task ${task.id}`, description: "View task details" }
|
|
3147
|
+
]
|
|
3001
3148
|
})
|
|
3002
3149
|
);
|
|
3003
3150
|
return;
|
|
3004
3151
|
}
|
|
3005
|
-
console.log("\nDispute opened!
|
|
3152
|
+
console.log("\nDispute opened! 24h timeout is now frozen.");
|
|
3006
3153
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
3007
3154
|
console.log(`
|
|
3008
3155
|
Fee paid: ${feeEth} ETH`);
|
|
3009
3156
|
console.log(`TX: ${txHash}`);
|
|
3010
3157
|
console.log("\nAn admin will review and resolve the dispute.");
|
|
3011
|
-
console.log("
|
|
3158
|
+
console.log("Add context via messages to help resolution:");
|
|
3159
|
+
console.log(` mltl message --task ${task.id} --content "..."
|
|
3160
|
+
`);
|
|
3012
3161
|
} catch (err) {
|
|
3013
3162
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
3014
3163
|
if (options.json) {
|
|
@@ -3123,7 +3272,13 @@ async function revise(options) {
|
|
|
3123
3272
|
agentId: task.agentId,
|
|
3124
3273
|
status: task.status,
|
|
3125
3274
|
revisionCount: task.revisionCount
|
|
3126
|
-
}
|
|
3275
|
+
},
|
|
3276
|
+
nextActions: [
|
|
3277
|
+
{ command: `mltl message --task ${task.id} --content "..."`, description: "Add more context for the agent" },
|
|
3278
|
+
{ command: `mltl view --task ${task.id}`, description: "View task thread" }
|
|
3279
|
+
],
|
|
3280
|
+
flow: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 [revision] \u2192 submitted \u2192 completed",
|
|
3281
|
+
note: "Agent will rework and resubmit. No additional cost \u2014 same escrow applies."
|
|
3127
3282
|
})
|
|
3128
3283
|
);
|
|
3129
3284
|
return;
|
|
@@ -3139,8 +3294,8 @@ Your feedback:
|
|
|
3139
3294
|
${options.reason}
|
|
3140
3295
|
`);
|
|
3141
3296
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
3142
|
-
console.log("\nThe agent will revise and resubmit
|
|
3143
|
-
console.log("
|
|
3297
|
+
console.log("\nThe agent will revise and resubmit. No additional cost.");
|
|
3298
|
+
console.log("Add more context:");
|
|
3144
3299
|
console.log(` mltl message --task ${task.id} --content "additional details"
|
|
3145
3300
|
`);
|
|
3146
3301
|
} catch (err) {
|
|
@@ -3241,27 +3396,86 @@ import { formatEther as formatEther14 } from "viem";
|
|
|
3241
3396
|
function formatTimestamp4(ts) {
|
|
3242
3397
|
return new Date(ts).toLocaleString();
|
|
3243
3398
|
}
|
|
3244
|
-
function
|
|
3399
|
+
function suggestedActions(task, role) {
|
|
3400
|
+
const id = task.id;
|
|
3245
3401
|
switch (task.status) {
|
|
3246
3402
|
case "requested":
|
|
3247
|
-
return `Quote: mltl quote --task ${
|
|
3248
|
-
Decline: mltl decline --task ${
|
|
3403
|
+
if (role === "agent") return `Quote: mltl quote --task ${id} --price <eth>
|
|
3404
|
+
Decline: mltl decline --task ${id}`;
|
|
3405
|
+
if (role === "client") return `Waiting for agent to quote. You can add context:
|
|
3406
|
+
mltl message --task ${id} --content "..."`;
|
|
3407
|
+
return `Agent: mltl quote --task ${id} --price <eth>
|
|
3408
|
+
Agent: mltl decline --task ${id}`;
|
|
3249
3409
|
case "quoted":
|
|
3250
|
-
return `
|
|
3410
|
+
if (role === "client") return `Accept: mltl accept --task ${id} (deposits ETH into escrow)
|
|
3411
|
+
Message: mltl message --task ${id} --content "..."`;
|
|
3412
|
+
if (role === "agent") return `Waiting for client to accept your quote.
|
|
3413
|
+
Message: mltl message --task ${id} --content "..."`;
|
|
3414
|
+
return `Client: mltl accept --task ${id}
|
|
3415
|
+
Either: mltl message --task ${id} --content "..."`;
|
|
3251
3416
|
case "accepted":
|
|
3417
|
+
if (role === "agent") return `Submit work when ready:
|
|
3418
|
+
mltl submit --task ${id} --result "..." --files file1.txt,file2.pdf`;
|
|
3419
|
+
if (role === "client") return `Agent is working. You can:
|
|
3420
|
+
Message: mltl message --task ${id} --content "..."
|
|
3421
|
+
Cancel: mltl cancel --task ${id} (10% fee to agent)`;
|
|
3422
|
+
return `Agent: mltl submit --task ${id} --result "..."`;
|
|
3252
3423
|
case "revision":
|
|
3253
|
-
return `
|
|
3424
|
+
if (role === "agent") return `Revision requested. Fix and resubmit:
|
|
3425
|
+
mltl submit --task ${id} --result "..." --files file1.txt`;
|
|
3426
|
+
if (role === "client") return `Waiting for agent to resubmit.
|
|
3427
|
+
Message: mltl message --task ${id} --content "..."`;
|
|
3428
|
+
return `Agent: mltl submit --task ${id} --result "..."`;
|
|
3254
3429
|
case "submitted":
|
|
3255
|
-
return `
|
|
3430
|
+
if (role === "client") return `Review the result above, then:
|
|
3431
|
+
Approve: mltl approve --task ${id} (releases payment, final)
|
|
3432
|
+
Revise: mltl revise --task ${id} --reason "..."
|
|
3433
|
+
Dispute: mltl dispute --task ${id} (10% fee, last resort)`;
|
|
3434
|
+
if (role === "agent") return `Waiting for client review. 24h timeout protects you.
|
|
3435
|
+
Claim: mltl claim --task ${id} (after 24h with no response)`;
|
|
3436
|
+
return `Client: mltl approve --task ${id}
|
|
3437
|
+
Client: mltl revise --task ${id} --reason "..."`;
|
|
3438
|
+
case "completed":
|
|
3439
|
+
if (role === "client") return `Leave a review:
|
|
3440
|
+
mltl feedback --task ${id} --score <0-100> --comment "..."`;
|
|
3441
|
+
return null;
|
|
3442
|
+
case "disputed":
|
|
3443
|
+
return `Awaiting admin resolution.
|
|
3444
|
+
Add context: mltl message --task ${id} --content "..."`;
|
|
3256
3445
|
default:
|
|
3257
3446
|
return null;
|
|
3258
3447
|
}
|
|
3259
3448
|
}
|
|
3449
|
+
var STATUS_FLOW = {
|
|
3450
|
+
requested: "[requested] \u2192 quoted \u2192 accepted \u2192 submitted \u2192 completed",
|
|
3451
|
+
quoted: "requested \u2192 [quoted] \u2192 accepted \u2192 submitted \u2192 completed",
|
|
3452
|
+
accepted: "requested \u2192 quoted \u2192 [accepted] \u2192 submitted \u2192 completed",
|
|
3453
|
+
revision: "requested \u2192 quoted \u2192 accepted \u2192 [revision] \u2192 submitted \u2192 completed",
|
|
3454
|
+
submitted: "requested \u2192 quoted \u2192 accepted \u2192 [submitted] \u2192 completed",
|
|
3455
|
+
completed: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 [completed]",
|
|
3456
|
+
declined: "requested \u2192 [declined]",
|
|
3457
|
+
disputed: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 [disputed] \u2192 resolved",
|
|
3458
|
+
resolved: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 disputed \u2192 [resolved]"
|
|
3459
|
+
};
|
|
3260
3460
|
async function view(options) {
|
|
3261
3461
|
try {
|
|
3262
3462
|
const task = await getTask(options.task);
|
|
3463
|
+
let role = "unknown";
|
|
3464
|
+
try {
|
|
3465
|
+
const wallet2 = await loadWallet();
|
|
3466
|
+
if (wallet2) {
|
|
3467
|
+
const addr = wallet2.address.toLowerCase();
|
|
3468
|
+
if (task.clientAddress.toLowerCase() === addr) {
|
|
3469
|
+
role = "client";
|
|
3470
|
+
} else {
|
|
3471
|
+
role = "agent";
|
|
3472
|
+
}
|
|
3473
|
+
}
|
|
3474
|
+
} catch {
|
|
3475
|
+
}
|
|
3263
3476
|
if (options.json) {
|
|
3264
|
-
|
|
3477
|
+
const flow2 = STATUS_FLOW[task.status] || null;
|
|
3478
|
+
console.log(JSON.stringify({ task, role, flow: flow2 }));
|
|
3265
3479
|
return;
|
|
3266
3480
|
}
|
|
3267
3481
|
const priceEth = task.quotedPriceWei ? formatEther14(BigInt(task.quotedPriceWei)) : null;
|
|
@@ -3313,10 +3527,18 @@ async function view(options) {
|
|
|
3313
3527
|
`);
|
|
3314
3528
|
}
|
|
3315
3529
|
}
|
|
3316
|
-
const
|
|
3317
|
-
if (
|
|
3530
|
+
const flow = STATUS_FLOW[task.status];
|
|
3531
|
+
if (flow) {
|
|
3318
3532
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
3319
|
-
console.log("
|
|
3533
|
+
console.log(" Flow");
|
|
3534
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n");
|
|
3535
|
+
console.log(flow);
|
|
3536
|
+
}
|
|
3537
|
+
const action = suggestedActions(task, role);
|
|
3538
|
+
if (action) {
|
|
3539
|
+
const roleLabel = role === "client" ? " (you are the client)" : role === "agent" ? " (you are the agent)" : "";
|
|
3540
|
+
console.log("\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
3541
|
+
console.log(` Next Action${roleLabel}`);
|
|
3320
3542
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n");
|
|
3321
3543
|
console.log(action);
|
|
3322
3544
|
}
|