moltlaunch 2.3.0 → 2.5.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/README.md +1 -0
- package/dist/index.js +431 -107
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1032,14 +1032,18 @@ Provide an image with: --image <path>`);
|
|
|
1032
1032
|
|
|
1033
1033
|
// src/lib/tasks.ts
|
|
1034
1034
|
var API_BASE = APIS.MOLTLAUNCH;
|
|
1035
|
-
async function createTask(agentId, clientAddress, taskDescription) {
|
|
1035
|
+
async function createTask(wallet2, agentId, clientAddress, taskDescription) {
|
|
1036
|
+
const { signature, timestamp, nonce } = await signAction(wallet2, "create", agentId);
|
|
1036
1037
|
const response = await fetch(`${API_BASE}/api/tasks`, {
|
|
1037
1038
|
method: "POST",
|
|
1038
1039
|
headers: { "Content-Type": "application/json" },
|
|
1039
1040
|
body: JSON.stringify({
|
|
1040
1041
|
agentId,
|
|
1041
1042
|
clientAddress,
|
|
1042
|
-
task: taskDescription
|
|
1043
|
+
task: taskDescription,
|
|
1044
|
+
signature,
|
|
1045
|
+
timestamp,
|
|
1046
|
+
nonce
|
|
1043
1047
|
})
|
|
1044
1048
|
});
|
|
1045
1049
|
if (!response.ok) {
|
|
@@ -1321,7 +1325,7 @@ Task: ${options.task}
|
|
|
1321
1325
|
`);
|
|
1322
1326
|
console.log("Creating task request...");
|
|
1323
1327
|
}
|
|
1324
|
-
const task = await createTask(agentId, wallet2.address, options.task);
|
|
1328
|
+
const task = await createTask(wallet2, agentId, wallet2.address, options.task);
|
|
1325
1329
|
if (options.json) {
|
|
1326
1330
|
console.log(
|
|
1327
1331
|
JSON.stringify({
|
|
@@ -1329,7 +1333,14 @@ Task: ${options.task}
|
|
|
1329
1333
|
taskId: task.id,
|
|
1330
1334
|
agentId,
|
|
1331
1335
|
status: task.status,
|
|
1332
|
-
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."
|
|
1333
1344
|
})
|
|
1334
1345
|
);
|
|
1335
1346
|
return;
|
|
@@ -1341,9 +1352,12 @@ Task ID: ${task.id}`);
|
|
|
1341
1352
|
console.log(`Agent: ${name} (#${agentId})`);
|
|
1342
1353
|
console.log(`Status: ${task.status}`);
|
|
1343
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");
|
|
1344
|
-
console.log("\
|
|
1345
|
-
console.log("
|
|
1346
|
-
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 "..."
|
|
1347
1361
|
`);
|
|
1348
1362
|
} catch (err) {
|
|
1349
1363
|
if (options.json) {
|
|
@@ -1741,8 +1755,120 @@ async function earnings(options) {
|
|
|
1741
1755
|
}
|
|
1742
1756
|
}
|
|
1743
1757
|
|
|
1744
|
-
// src/commands/
|
|
1758
|
+
// src/commands/fees.ts
|
|
1745
1759
|
import { formatEther as formatEther3 } from "viem";
|
|
1760
|
+
import { createPublicClient as createPublicClient3, createWalletClient as createWalletClient3, http as http3 } from "viem";
|
|
1761
|
+
import { base as base3 } from "viem/chains";
|
|
1762
|
+
import { privateKeyToAccount as privateKeyToAccount4 } from "viem/accounts";
|
|
1763
|
+
var REVENUE_MANAGER_ABI = [
|
|
1764
|
+
{
|
|
1765
|
+
name: "balances",
|
|
1766
|
+
type: "function",
|
|
1767
|
+
stateMutability: "view",
|
|
1768
|
+
inputs: [{ name: "_recipient", type: "address" }],
|
|
1769
|
+
outputs: [{ name: "balance_", type: "uint256" }]
|
|
1770
|
+
},
|
|
1771
|
+
{
|
|
1772
|
+
name: "claim",
|
|
1773
|
+
type: "function",
|
|
1774
|
+
stateMutability: "nonpayable",
|
|
1775
|
+
inputs: [],
|
|
1776
|
+
outputs: [{ name: "amount_", type: "uint256" }]
|
|
1777
|
+
}
|
|
1778
|
+
];
|
|
1779
|
+
async function fees(options) {
|
|
1780
|
+
const { wallet: wallet2 } = await loadOrCreateWallet();
|
|
1781
|
+
const publicClient = createPublicClient3({ chain: base3, transport: http3(BASE_RPC_URL) });
|
|
1782
|
+
if (!options.json) {
|
|
1783
|
+
console.log("\nFlaunch Trading Fees");
|
|
1784
|
+
console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n");
|
|
1785
|
+
}
|
|
1786
|
+
try {
|
|
1787
|
+
const agentId = await getAgentByOwner(wallet2.address);
|
|
1788
|
+
if (!agentId || agentId <= 0n) {
|
|
1789
|
+
throw new Error("No registered agent found for this wallet");
|
|
1790
|
+
}
|
|
1791
|
+
const balance = await publicClient.readContract({
|
|
1792
|
+
address: REVENUE_MANAGER_ADDRESS,
|
|
1793
|
+
abi: REVENUE_MANAGER_ABI,
|
|
1794
|
+
functionName: "balances",
|
|
1795
|
+
args: [wallet2.address]
|
|
1796
|
+
});
|
|
1797
|
+
const balanceEth = formatEther3(balance);
|
|
1798
|
+
if (!options.claim) {
|
|
1799
|
+
if (options.json) {
|
|
1800
|
+
console.log(JSON.stringify({
|
|
1801
|
+
wallet: wallet2.address,
|
|
1802
|
+
agentId: agentId.toString(),
|
|
1803
|
+
revenueManager: REVENUE_MANAGER_ADDRESS,
|
|
1804
|
+
pendingFees: { wei: balance.toString(), eth: balanceEth }
|
|
1805
|
+
}));
|
|
1806
|
+
return;
|
|
1807
|
+
}
|
|
1808
|
+
console.log(`Wallet: ${wallet2.address}`);
|
|
1809
|
+
console.log(`Agent ID: ${agentId.toString()}`);
|
|
1810
|
+
console.log(`Revenue Manager: ${REVENUE_MANAGER_ADDRESS}`);
|
|
1811
|
+
console.log("");
|
|
1812
|
+
console.log(`Pending fees: ${balanceEth} ETH`);
|
|
1813
|
+
console.log("");
|
|
1814
|
+
if (balance === 0n) {
|
|
1815
|
+
console.log("No fees to claim yet. Fees accumulate from token trading activity.");
|
|
1816
|
+
} else {
|
|
1817
|
+
console.log("Run with --claim to withdraw fees to your wallet.");
|
|
1818
|
+
}
|
|
1819
|
+
return;
|
|
1820
|
+
}
|
|
1821
|
+
if (balance === 0n) {
|
|
1822
|
+
if (options.json) {
|
|
1823
|
+
console.log(JSON.stringify({ error: "No fees to claim" }));
|
|
1824
|
+
process.exit(1);
|
|
1825
|
+
}
|
|
1826
|
+
console.log("No fees to claim yet.");
|
|
1827
|
+
return;
|
|
1828
|
+
}
|
|
1829
|
+
if (!options.json) {
|
|
1830
|
+
console.log(`Claiming ${balanceEth} ETH in trading fees...`);
|
|
1831
|
+
}
|
|
1832
|
+
const account = privateKeyToAccount4(wallet2.privateKey);
|
|
1833
|
+
const walletClient = createWalletClient3({
|
|
1834
|
+
account,
|
|
1835
|
+
chain: base3,
|
|
1836
|
+
transport: http3(BASE_RPC_URL)
|
|
1837
|
+
});
|
|
1838
|
+
const txHash = await walletClient.writeContract({
|
|
1839
|
+
address: REVENUE_MANAGER_ADDRESS,
|
|
1840
|
+
abi: REVENUE_MANAGER_ABI,
|
|
1841
|
+
functionName: "claim",
|
|
1842
|
+
args: []
|
|
1843
|
+
});
|
|
1844
|
+
await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
1845
|
+
if (options.json) {
|
|
1846
|
+
console.log(JSON.stringify({
|
|
1847
|
+
success: true,
|
|
1848
|
+
claimed: { wei: balance.toString(), eth: balanceEth },
|
|
1849
|
+
txHash
|
|
1850
|
+
}));
|
|
1851
|
+
return;
|
|
1852
|
+
}
|
|
1853
|
+
console.log("\n\u2705 Fees claimed!");
|
|
1854
|
+
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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
1855
|
+
console.log(`Amount: ${balanceEth} ETH`);
|
|
1856
|
+
console.log(`TX: ${txHash}`);
|
|
1857
|
+
console.log("");
|
|
1858
|
+
} catch (err) {
|
|
1859
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
1860
|
+
if (options.json) {
|
|
1861
|
+
console.log(JSON.stringify({ error: errorMsg }));
|
|
1862
|
+
process.exit(1);
|
|
1863
|
+
}
|
|
1864
|
+
console.error(`
|
|
1865
|
+
\u274C Failed: ${errorMsg}`);
|
|
1866
|
+
process.exit(1);
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
// src/commands/inbox.ts
|
|
1871
|
+
import { formatEther as formatEther4 } from "viem";
|
|
1746
1872
|
function formatTimestamp(ts) {
|
|
1747
1873
|
const date = new Date(ts);
|
|
1748
1874
|
return date.toLocaleString();
|
|
@@ -1783,7 +1909,7 @@ var STATUS_GROUPS = [
|
|
|
1783
1909
|
{ key: "disputed", label: "DISPUTED", emoji: "\u26A0\uFE0F", hint: "Task is disputed. Await admin resolution." }
|
|
1784
1910
|
];
|
|
1785
1911
|
function renderTask(task) {
|
|
1786
|
-
const priceEth = task.quotedPriceWei ?
|
|
1912
|
+
const priceEth = task.quotedPriceWei ? formatEther4(BigInt(task.quotedPriceWei)) : null;
|
|
1787
1913
|
console.log(`Task ID: ${task.id}${taskCounts(task)}`);
|
|
1788
1914
|
console.log(`Client: ${task.clientAddress}`);
|
|
1789
1915
|
if (priceEth) console.log(`Price: ${priceEth} ETH`);
|
|
@@ -1805,7 +1931,11 @@ async function inbox(options) {
|
|
|
1805
1931
|
const tasks2 = await getInbox(agentId);
|
|
1806
1932
|
if (tasks2.length === 0) {
|
|
1807
1933
|
if (options.json) {
|
|
1808
|
-
console.log(JSON.stringify({
|
|
1934
|
+
console.log(JSON.stringify({
|
|
1935
|
+
tasks: [],
|
|
1936
|
+
total: 0,
|
|
1937
|
+
polling: { recommended: "5m", note: "No active tasks. Check less frequently." }
|
|
1938
|
+
}));
|
|
1809
1939
|
return;
|
|
1810
1940
|
}
|
|
1811
1941
|
console.log("No pending tasks.\n");
|
|
@@ -1813,8 +1943,28 @@ async function inbox(options) {
|
|
|
1813
1943
|
console.log("Run this command periodically to check for new work.\n");
|
|
1814
1944
|
return;
|
|
1815
1945
|
}
|
|
1946
|
+
const hasRevision = tasks2.some((t) => t.status === "revision");
|
|
1947
|
+
const hasRequested = tasks2.some((t) => t.status === "requested");
|
|
1948
|
+
const hasSubmitted = tasks2.some((t) => t.status === "submitted");
|
|
1949
|
+
let pollingInterval = "5m";
|
|
1950
|
+
let pollingNote = "Normal activity.";
|
|
1951
|
+
if (hasRevision) {
|
|
1952
|
+
pollingInterval = "1m";
|
|
1953
|
+
pollingNote = "Revision requested \u2014 client is waiting for your rework.";
|
|
1954
|
+
} else if (hasRequested) {
|
|
1955
|
+
pollingInterval = "2m";
|
|
1956
|
+
pollingNote = "New requests \u2014 quote promptly to win the work.";
|
|
1957
|
+
} else if (hasSubmitted) {
|
|
1958
|
+
pollingInterval = "5m";
|
|
1959
|
+
pollingNote = "Waiting on client review. Check back periodically.";
|
|
1960
|
+
}
|
|
1816
1961
|
if (options.json) {
|
|
1817
|
-
console.log(JSON.stringify({
|
|
1962
|
+
console.log(JSON.stringify({
|
|
1963
|
+
tasks: tasks2,
|
|
1964
|
+
total: tasks2.length,
|
|
1965
|
+
polling: { recommended: pollingInterval, note: pollingNote },
|
|
1966
|
+
flow: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 completed"
|
|
1967
|
+
}));
|
|
1818
1968
|
return;
|
|
1819
1969
|
}
|
|
1820
1970
|
for (const group of STATUS_GROUPS) {
|
|
@@ -1842,19 +1992,19 @@ Failed to fetch inbox: ${errorMsg}`);
|
|
|
1842
1992
|
}
|
|
1843
1993
|
|
|
1844
1994
|
// src/commands/accept.ts
|
|
1845
|
-
import { formatEther as
|
|
1995
|
+
import { formatEther as formatEther5, parseEther as parseEther2 } from "viem";
|
|
1846
1996
|
|
|
1847
1997
|
// src/lib/escrow.ts
|
|
1848
1998
|
import {
|
|
1849
|
-
createPublicClient as
|
|
1850
|
-
createWalletClient as
|
|
1851
|
-
http as
|
|
1999
|
+
createPublicClient as createPublicClient4,
|
|
2000
|
+
createWalletClient as createWalletClient4,
|
|
2001
|
+
http as http4,
|
|
1852
2002
|
keccak256 as keccak2562,
|
|
1853
2003
|
toBytes as toBytes2,
|
|
1854
2004
|
parseAbi
|
|
1855
2005
|
} from "viem";
|
|
1856
|
-
import { privateKeyToAccount as
|
|
1857
|
-
import { base as
|
|
2006
|
+
import { privateKeyToAccount as privateKeyToAccount5 } from "viem/accounts";
|
|
2007
|
+
import { base as base4 } from "viem/chains";
|
|
1858
2008
|
var ESCROW_ADDRESS = process.env.ESCROW_ADDRESS || "0x5Df1ffa02c8515a0Fed7d0e5d6375FcD2c1950Ee";
|
|
1859
2009
|
var ESCROW_ABI = parseAbi([
|
|
1860
2010
|
// Write functions
|
|
@@ -1896,17 +2046,17 @@ function taskIdToBytes32(taskId) {
|
|
|
1896
2046
|
return keccak2562(toBytes2(taskId));
|
|
1897
2047
|
}
|
|
1898
2048
|
function getPublicClient2() {
|
|
1899
|
-
return
|
|
1900
|
-
chain:
|
|
1901
|
-
transport:
|
|
2049
|
+
return createPublicClient4({
|
|
2050
|
+
chain: base4,
|
|
2051
|
+
transport: http4(BASE_RPC_URL)
|
|
1902
2052
|
});
|
|
1903
2053
|
}
|
|
1904
2054
|
function getWalletClient2(wallet2) {
|
|
1905
|
-
const account =
|
|
1906
|
-
return
|
|
2055
|
+
const account = privateKeyToAccount5(wallet2.privateKey);
|
|
2056
|
+
return createWalletClient4({
|
|
1907
2057
|
account,
|
|
1908
|
-
chain:
|
|
1909
|
-
transport:
|
|
2058
|
+
chain: base4,
|
|
2059
|
+
transport: http4(BASE_RPC_URL)
|
|
1910
2060
|
});
|
|
1911
2061
|
}
|
|
1912
2062
|
async function depositEscrow(wallet2, taskId, agentAddress, tokenAddress, amountWei) {
|
|
@@ -2115,7 +2265,7 @@ async function accept(options) {
|
|
|
2115
2265
|
if (taskBefore.clientAddress.toLowerCase() !== wallet2.address.toLowerCase()) {
|
|
2116
2266
|
throw new Error("Only the client who created this task can accept the quote");
|
|
2117
2267
|
}
|
|
2118
|
-
const priceEth = taskBefore.quotedPriceWei ?
|
|
2268
|
+
const priceEth = taskBefore.quotedPriceWei ? formatEther5(BigInt(taskBefore.quotedPriceWei)) : "0";
|
|
2119
2269
|
const agent = await fetchAgent2(taskBefore.agentId);
|
|
2120
2270
|
if (!agent) {
|
|
2121
2271
|
throw new Error(`Agent #${taskBefore.agentId} not found`);
|
|
@@ -2140,6 +2290,7 @@ Task ID: ${taskBefore.id}`);
|
|
|
2140
2290
|
console.log(`Agent: #${taskBefore.agentId} (${agent.name || "Unknown"})`);
|
|
2141
2291
|
console.log(`Owner: ${agentOwner}`);
|
|
2142
2292
|
console.log(`Quote: ${priceEth} ETH`);
|
|
2293
|
+
console.log(`Balance: ${balance} ETH`);
|
|
2143
2294
|
if (taskBefore.quotedMessage) {
|
|
2144
2295
|
console.log(`Message: ${taskBefore.quotedMessage}`);
|
|
2145
2296
|
}
|
|
@@ -2147,6 +2298,12 @@ Task ID: ${taskBefore.id}`);
|
|
|
2147
2298
|
Task:
|
|
2148
2299
|
${taskBefore.task}
|
|
2149
2300
|
`);
|
|
2301
|
+
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");
|
|
2302
|
+
console.log(`
|
|
2303
|
+
This will deposit ${priceEth} ETH into escrow.`);
|
|
2304
|
+
console.log("Funds are locked until you approve the work or request a refund.");
|
|
2305
|
+
console.log(" - Approve submitted work: funds buy back & burn agent's token");
|
|
2306
|
+
console.log(" - Cancel before submission: 10% fee to agent, 90% refunded");
|
|
2150
2307
|
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");
|
|
2151
2308
|
console.log("\nDepositing funds into escrow...");
|
|
2152
2309
|
}
|
|
@@ -2170,7 +2327,14 @@ ${taskBefore.task}
|
|
|
2170
2327
|
txHash: escrowTxHash,
|
|
2171
2328
|
amount: priceEth,
|
|
2172
2329
|
tokenAddress: agentToken
|
|
2173
|
-
}
|
|
2330
|
+
},
|
|
2331
|
+
nextActions: [
|
|
2332
|
+
{ command: `mltl tasks`, description: "Check task status" },
|
|
2333
|
+
{ command: `mltl message --task ${task.id} --content "..."`, description: "Message the agent" },
|
|
2334
|
+
{ command: `mltl cancel --task ${task.id}`, description: "Cancel (10% fee to agent)" }
|
|
2335
|
+
],
|
|
2336
|
+
flow: "requested \u2192 quoted \u2192 [accepted] \u2192 submitted \u2192 completed",
|
|
2337
|
+
note: "Funds are locked in escrow. Agent can now begin work."
|
|
2174
2338
|
})
|
|
2175
2339
|
);
|
|
2176
2340
|
return;
|
|
@@ -2180,9 +2344,12 @@ ${taskBefore.task}
|
|
|
2180
2344
|
Escrow: ${priceEth} ETH deposited`);
|
|
2181
2345
|
console.log(`Token: ${agentToken}`);
|
|
2182
2346
|
console.log(`TX: ${escrowTxHash}`);
|
|
2183
|
-
console.log("\
|
|
2184
|
-
console.log("
|
|
2185
|
-
console.log(
|
|
2347
|
+
console.log("\nThe agent can now begin work. When they submit:");
|
|
2348
|
+
console.log(" - Review & approve: mltl approve --task " + task.id);
|
|
2349
|
+
console.log(" - Request changes: mltl revise --task " + task.id + ' --reason "..."');
|
|
2350
|
+
console.log(" - Cancel (10% fee): mltl cancel --task " + task.id);
|
|
2351
|
+
console.log(`
|
|
2352
|
+
Flow: requested \u2192 quoted \u2192 [accepted] \u2192 submitted \u2192 completed
|
|
2186
2353
|
`);
|
|
2187
2354
|
} catch (err) {
|
|
2188
2355
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -2215,14 +2382,19 @@ async function decline(options) {
|
|
|
2215
2382
|
task: {
|
|
2216
2383
|
id: task.id,
|
|
2217
2384
|
status: task.status
|
|
2218
|
-
}
|
|
2385
|
+
},
|
|
2386
|
+
nextActions: [
|
|
2387
|
+
{ command: `mltl inbox`, description: "Check for other tasks" }
|
|
2388
|
+
],
|
|
2389
|
+
note: "Declined tasks are tracked in your stats. This is normal \u2014 only accept work you can deliver."
|
|
2219
2390
|
})
|
|
2220
2391
|
);
|
|
2221
2392
|
return;
|
|
2222
2393
|
}
|
|
2223
2394
|
console.log(`
|
|
2224
2395
|
\u2705 Task ${task.id} declined.`);
|
|
2225
|
-
console.log("\nThe client will be notified
|
|
2396
|
+
console.log("\nThe client will be notified.");
|
|
2397
|
+
console.log("Tip: Declining tasks you can't deliver is better than accepting and underdelivering.\n");
|
|
2226
2398
|
} catch (err) {
|
|
2227
2399
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
2228
2400
|
if (options.json) {
|
|
@@ -2236,7 +2408,7 @@ async function decline(options) {
|
|
|
2236
2408
|
}
|
|
2237
2409
|
|
|
2238
2410
|
// src/commands/submit.ts
|
|
2239
|
-
import { formatEther as
|
|
2411
|
+
import { formatEther as formatEther6 } from "viem";
|
|
2240
2412
|
|
|
2241
2413
|
// src/lib/files.ts
|
|
2242
2414
|
import { readFileSync, statSync } from "fs";
|
|
@@ -2328,6 +2500,13 @@ Uploading ${filePaths.length} file(s)...`);
|
|
|
2328
2500
|
}
|
|
2329
2501
|
}
|
|
2330
2502
|
if (options.json) {
|
|
2503
|
+
const nextActions = [
|
|
2504
|
+
{ command: `mltl view --task ${task.id}`, description: "View full task thread" },
|
|
2505
|
+
{ command: `mltl message --task ${task.id} --content "..."`, description: "Message the client" }
|
|
2506
|
+
];
|
|
2507
|
+
if (escrowTxHash) {
|
|
2508
|
+
nextActions.push({ command: `mltl claim --task ${task.id}`, description: "Claim payment after 24h timeout" });
|
|
2509
|
+
}
|
|
2331
2510
|
console.log(
|
|
2332
2511
|
JSON.stringify({
|
|
2333
2512
|
success: true,
|
|
@@ -2338,12 +2517,15 @@ Uploading ${filePaths.length} file(s)...`);
|
|
|
2338
2517
|
quotedPriceWei: task.quotedPriceWei,
|
|
2339
2518
|
result: task.result
|
|
2340
2519
|
},
|
|
2341
|
-
escrow: escrowTxHash ? { txHash: escrowTxHash, timeoutHours: 24 } : null
|
|
2520
|
+
escrow: escrowTxHash ? { txHash: escrowTxHash, timeoutHours: 24 } : null,
|
|
2521
|
+
nextActions,
|
|
2522
|
+
flow: isRevision ? "requested \u2192 quoted \u2192 accepted \u2192 revision \u2192 [submitted] \u2192 completed" : "requested \u2192 quoted \u2192 accepted \u2192 [submitted] \u2192 completed",
|
|
2523
|
+
note: escrowTxHash ? "24h countdown started. Client must approve, revise, or dispute within 24h \u2014 otherwise you can claim payment." : "Awaiting client review."
|
|
2342
2524
|
})
|
|
2343
2525
|
);
|
|
2344
2526
|
return;
|
|
2345
2527
|
}
|
|
2346
|
-
const priceEth = task.quotedPriceWei ?
|
|
2528
|
+
const priceEth = task.quotedPriceWei ? formatEther6(BigInt(task.quotedPriceWei)) : "0";
|
|
2347
2529
|
console.log(isRevision ? "\n\u2705 Revised work submitted!" : "\n\u2705 Work submitted!");
|
|
2348
2530
|
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");
|
|
2349
2531
|
console.log(`
|
|
@@ -2355,21 +2537,23 @@ Task ID: ${task.id}`);
|
|
|
2355
2537
|
console.log(`Price: ${priceEth} ETH`);
|
|
2356
2538
|
if (escrowTxHash) {
|
|
2357
2539
|
console.log(`
|
|
2358
|
-
Timeout: 24 hours
|
|
2540
|
+
Timeout: 24 hours from now`);
|
|
2541
|
+
console.log(` Client must respond or you can auto-claim payment.`);
|
|
2359
2542
|
}
|
|
2360
2543
|
console.log(`
|
|
2361
2544
|
Your result:
|
|
2362
2545
|
${options.result}
|
|
2363
2546
|
`);
|
|
2364
2547
|
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");
|
|
2365
|
-
console.log("\
|
|
2548
|
+
console.log("\nWhat happens next:");
|
|
2549
|
+
console.log(" - Client approves \u2192 payment released (buyback & burn)");
|
|
2550
|
+
console.log(" - Client revises \u2192 you'll see it in your inbox");
|
|
2366
2551
|
if (escrowTxHash) {
|
|
2367
|
-
console.log("
|
|
2368
|
-
console.log(` mltl claim --task ${task.id}
|
|
2369
|
-
`);
|
|
2370
|
-
} else {
|
|
2371
|
-
console.log("Once approved, payment will be sent to your wallet.\n");
|
|
2552
|
+
console.log(" - No response 24h \u2192 claim with: mltl claim --task " + task.id);
|
|
2372
2553
|
}
|
|
2554
|
+
console.log(`
|
|
2555
|
+
Check status: mltl view --task ${task.id}
|
|
2556
|
+
`);
|
|
2373
2557
|
} catch (err) {
|
|
2374
2558
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
2375
2559
|
if (options.json) {
|
|
@@ -2383,7 +2567,7 @@ ${options.result}
|
|
|
2383
2567
|
}
|
|
2384
2568
|
|
|
2385
2569
|
// src/commands/approve.ts
|
|
2386
|
-
import { formatEther as
|
|
2570
|
+
import { formatEther as formatEther7 } from "viem";
|
|
2387
2571
|
async function fetchAgent3(agentId) {
|
|
2388
2572
|
const res = await fetch(`${APIS.MOLTLAUNCH}/api/agents/${agentId}`);
|
|
2389
2573
|
if (!res.ok) return null;
|
|
@@ -2408,7 +2592,7 @@ async function approve(options) {
|
|
|
2408
2592
|
throw new Error("Task has no quoted price");
|
|
2409
2593
|
}
|
|
2410
2594
|
const priceWei = BigInt(task.quotedPriceWei);
|
|
2411
|
-
const priceEth =
|
|
2595
|
+
const priceEth = formatEther7(priceWei);
|
|
2412
2596
|
const agent = await fetchAgent3(task.agentId);
|
|
2413
2597
|
if (!agent) {
|
|
2414
2598
|
throw new Error(`Agent #${task.agentId} not found`);
|
|
@@ -2429,11 +2613,14 @@ async function approve(options) {
|
|
|
2429
2613
|
Task ID: ${task.id}`);
|
|
2430
2614
|
console.log(`Agent: ${agent.name || `#${task.agentId}`}`);
|
|
2431
2615
|
console.log(`Agent Owner: ${agentOwner}`);
|
|
2432
|
-
console.log(`Escrow: ${
|
|
2616
|
+
console.log(`Escrow: ${formatEther7(escrow.amount)} ETH (locked)`);
|
|
2433
2617
|
console.log(`
|
|
2434
2618
|
Submitted result:
|
|
2435
2619
|
${task.result}
|
|
2436
2620
|
`);
|
|
2621
|
+
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");
|
|
2622
|
+
console.log("\nThis will release payment. This action is final and irreversible.");
|
|
2623
|
+
console.log("If unsatisfied, use 'mltl revise' or 'mltl dispute' instead.");
|
|
2437
2624
|
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");
|
|
2438
2625
|
console.log("\nReleasing payment from escrow...");
|
|
2439
2626
|
}
|
|
@@ -2455,7 +2642,11 @@ ${task.result}
|
|
|
2455
2642
|
amount: priceEth,
|
|
2456
2643
|
txHash,
|
|
2457
2644
|
type: "escrow_release"
|
|
2458
|
-
}
|
|
2645
|
+
},
|
|
2646
|
+
nextActions: [
|
|
2647
|
+
{ command: `mltl feedback --task ${completedTask.id} --score <0-100>`, description: "Leave a verified review (on-chain)" }
|
|
2648
|
+
],
|
|
2649
|
+
flow: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 [completed]"
|
|
2459
2650
|
})
|
|
2460
2651
|
);
|
|
2461
2652
|
return;
|
|
@@ -2465,8 +2656,9 @@ ${task.result}
|
|
|
2465
2656
|
console.log(`
|
|
2466
2657
|
Payment: ${priceEth} ETH \u2192 ${agentOwner}`);
|
|
2467
2658
|
console.log(`TX: ${txHash}`);
|
|
2468
|
-
console.log("\
|
|
2469
|
-
console.log(` mltl feedback --
|
|
2659
|
+
console.log("\nLeave a verified review (score 0-100):");
|
|
2660
|
+
console.log(` mltl feedback --task ${completedTask.id} --score 90`);
|
|
2661
|
+
console.log(` mltl feedback --task ${completedTask.id} --score 85 --comment "Great work"
|
|
2470
2662
|
`);
|
|
2471
2663
|
} catch (err) {
|
|
2472
2664
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -2481,7 +2673,7 @@ Payment: ${priceEth} ETH \u2192 ${agentOwner}`);
|
|
|
2481
2673
|
}
|
|
2482
2674
|
|
|
2483
2675
|
// src/commands/tasks.ts
|
|
2484
|
-
import { formatEther as
|
|
2676
|
+
import { formatEther as formatEther8 } from "viem";
|
|
2485
2677
|
function formatTimestamp2(ts) {
|
|
2486
2678
|
const date = new Date(ts);
|
|
2487
2679
|
return date.toLocaleString();
|
|
@@ -2497,7 +2689,14 @@ async function tasks(options) {
|
|
|
2497
2689
|
const allTasks = await getClientTasks(wallet2.address);
|
|
2498
2690
|
if (allTasks.length === 0) {
|
|
2499
2691
|
if (options.json) {
|
|
2500
|
-
console.log(JSON.stringify({
|
|
2692
|
+
console.log(JSON.stringify({
|
|
2693
|
+
tasks: [],
|
|
2694
|
+
total: 0,
|
|
2695
|
+
nextActions: [
|
|
2696
|
+
{ command: `mltl agents`, description: "Browse available agents" },
|
|
2697
|
+
{ command: `mltl hire --agent <id> --task "..."`, description: "Request work from an agent" }
|
|
2698
|
+
]
|
|
2699
|
+
}));
|
|
2501
2700
|
return;
|
|
2502
2701
|
}
|
|
2503
2702
|
console.log("No tasks yet.\n");
|
|
@@ -2505,8 +2704,24 @@ async function tasks(options) {
|
|
|
2505
2704
|
console.log(' mltl hire --agent <id> --task "Your task description"\n');
|
|
2506
2705
|
return;
|
|
2507
2706
|
}
|
|
2707
|
+
const hasSubmittedReview = allTasks.some((t) => t.status === "submitted");
|
|
2708
|
+
const hasQuoted = allTasks.some((t) => t.status === "quoted");
|
|
2709
|
+
let pollingInterval = "5m";
|
|
2710
|
+
let pollingNote = "Normal activity.";
|
|
2711
|
+
if (hasSubmittedReview) {
|
|
2712
|
+
pollingInterval = "1m";
|
|
2713
|
+
pollingNote = "Work submitted \u2014 review and approve/revise promptly so agent can get paid.";
|
|
2714
|
+
} else if (hasQuoted) {
|
|
2715
|
+
pollingInterval = "2m";
|
|
2716
|
+
pollingNote = "Quote received \u2014 accept to lock escrow and start work.";
|
|
2717
|
+
}
|
|
2508
2718
|
if (options.json) {
|
|
2509
|
-
console.log(JSON.stringify({
|
|
2719
|
+
console.log(JSON.stringify({
|
|
2720
|
+
tasks: allTasks,
|
|
2721
|
+
total: allTasks.length,
|
|
2722
|
+
polling: { recommended: pollingInterval, note: pollingNote },
|
|
2723
|
+
flow: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 completed"
|
|
2724
|
+
}));
|
|
2510
2725
|
return;
|
|
2511
2726
|
}
|
|
2512
2727
|
const needsReview = allTasks.filter((t) => t.status === "submitted");
|
|
@@ -2522,7 +2737,7 @@ async function tasks(options) {
|
|
|
2522
2737
|
console.log(`\u{1F4E5} NEEDS REVIEW (${needsReview.length})`);
|
|
2523
2738
|
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");
|
|
2524
2739
|
for (const task of needsReview) {
|
|
2525
|
-
const priceEth = task.quotedPriceWei ?
|
|
2740
|
+
const priceEth = task.quotedPriceWei ? formatEther8(BigInt(task.quotedPriceWei)) : "0";
|
|
2526
2741
|
console.log(`Task ID: ${task.id}`);
|
|
2527
2742
|
console.log(`Agent: #${task.agentId}`);
|
|
2528
2743
|
console.log(`Price: ${priceEth} ETH`);
|
|
@@ -2544,7 +2759,7 @@ ${task.result}
|
|
|
2544
2759
|
\u{1F4AC} QUOTES RECEIVED (${quoted.length})`);
|
|
2545
2760
|
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");
|
|
2546
2761
|
for (const task of quoted) {
|
|
2547
|
-
const priceEth = task.quotedPriceWei ?
|
|
2762
|
+
const priceEth = task.quotedPriceWei ? formatEther8(BigInt(task.quotedPriceWei)) : "0";
|
|
2548
2763
|
console.log(`Task ID: ${task.id}`);
|
|
2549
2764
|
console.log(`Agent: #${task.agentId}`);
|
|
2550
2765
|
console.log(`Quote: ${priceEth} ETH`);
|
|
@@ -2575,7 +2790,7 @@ ${task.result}
|
|
|
2575
2790
|
\u{1F528} IN PROGRESS (${inProgress.length})`);
|
|
2576
2791
|
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");
|
|
2577
2792
|
for (const task of inProgress) {
|
|
2578
|
-
const priceEth = task.quotedPriceWei ?
|
|
2793
|
+
const priceEth = task.quotedPriceWei ? formatEther8(BigInt(task.quotedPriceWei)) : "0";
|
|
2579
2794
|
console.log(`Task ID: ${task.id}`);
|
|
2580
2795
|
console.log(`Agent: #${task.agentId}`);
|
|
2581
2796
|
console.log(`Price: ${priceEth} ETH`);
|
|
@@ -2589,7 +2804,7 @@ ${task.result}
|
|
|
2589
2804
|
\u2705 COMPLETED (${completed.length})`);
|
|
2590
2805
|
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");
|
|
2591
2806
|
for (const task of completed.slice(0, 5)) {
|
|
2592
|
-
const priceEth = task.quotedPriceWei ?
|
|
2807
|
+
const priceEth = task.quotedPriceWei ? formatEther8(BigInt(task.quotedPriceWei)) : "0";
|
|
2593
2808
|
console.log(`Task ID: ${task.id}`);
|
|
2594
2809
|
console.log(`Agent: #${task.agentId}`);
|
|
2595
2810
|
console.log(`Paid: ${priceEth} ETH`);
|
|
@@ -2607,7 +2822,7 @@ ${task.result}
|
|
|
2607
2822
|
\u{1F504} REVISION REQUESTED (${revision.length})`);
|
|
2608
2823
|
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");
|
|
2609
2824
|
for (const task of revision) {
|
|
2610
|
-
const priceEth = task.quotedPriceWei ?
|
|
2825
|
+
const priceEth = task.quotedPriceWei ? formatEther8(BigInt(task.quotedPriceWei)) : "0";
|
|
2611
2826
|
console.log(`Task ID: ${task.id}`);
|
|
2612
2827
|
console.log(`Agent: #${task.agentId}`);
|
|
2613
2828
|
console.log(`Price: ${priceEth} ETH`);
|
|
@@ -2621,7 +2836,7 @@ ${task.result}
|
|
|
2621
2836
|
\u26A0\uFE0F DISPUTED (${disputed.length})`);
|
|
2622
2837
|
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");
|
|
2623
2838
|
for (const task of disputed) {
|
|
2624
|
-
const priceEth = task.quotedPriceWei ?
|
|
2839
|
+
const priceEth = task.quotedPriceWei ? formatEther8(BigInt(task.quotedPriceWei)) : "0";
|
|
2625
2840
|
console.log(`Task ID: ${task.id}`);
|
|
2626
2841
|
console.log(`Agent: #${task.agentId}`);
|
|
2627
2842
|
console.log(`Price: ${priceEth} ETH`);
|
|
@@ -2636,7 +2851,7 @@ ${task.result}
|
|
|
2636
2851
|
\u2705 RESOLVED (${resolved.length})`);
|
|
2637
2852
|
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");
|
|
2638
2853
|
for (const task of resolved) {
|
|
2639
|
-
const priceEth = task.quotedPriceWei ?
|
|
2854
|
+
const priceEth = task.quotedPriceWei ? formatEther8(BigInt(task.quotedPriceWei)) : "0";
|
|
2640
2855
|
const winner = task.disputeResolution === "client" ? "Client (refunded)" : "Agent (buyback)";
|
|
2641
2856
|
console.log(`Task ID: ${task.id}`);
|
|
2642
2857
|
console.log(`Agent: #${task.agentId}`);
|
|
@@ -2667,7 +2882,7 @@ ${task.result}
|
|
|
2667
2882
|
}
|
|
2668
2883
|
|
|
2669
2884
|
// src/commands/quote.ts
|
|
2670
|
-
import { parseEther as parseEther3, formatEther as
|
|
2885
|
+
import { parseEther as parseEther3, formatEther as formatEther9 } from "viem";
|
|
2671
2886
|
async function quote(options) {
|
|
2672
2887
|
const { wallet: wallet2 } = await loadOrCreateWallet();
|
|
2673
2888
|
if (!options.json) {
|
|
@@ -2680,7 +2895,7 @@ async function quote(options) {
|
|
|
2680
2895
|
throw new Error(`Task is ${taskBefore.status}, cannot quote`);
|
|
2681
2896
|
}
|
|
2682
2897
|
const priceWei = parseEther3(options.price);
|
|
2683
|
-
const priceEth =
|
|
2898
|
+
const priceEth = formatEther9(priceWei);
|
|
2684
2899
|
if (!options.json) {
|
|
2685
2900
|
console.log(`
|
|
2686
2901
|
Task ID: ${taskBefore.id}`);
|
|
@@ -2694,6 +2909,11 @@ ${taskBefore.task}
|
|
|
2694
2909
|
console.log(`Message: ${options.message}`);
|
|
2695
2910
|
}
|
|
2696
2911
|
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");
|
|
2912
|
+
if (taskBefore.status === "quoted") {
|
|
2913
|
+
console.log("\nNote: Updating your previous quote. Client has not yet accepted.");
|
|
2914
|
+
}
|
|
2915
|
+
console.log("\nBy quoting, you commit to delivering this work at this price.");
|
|
2916
|
+
console.log("The client can accept at any time, locking funds in escrow.");
|
|
2697
2917
|
}
|
|
2698
2918
|
const task = await quoteTask(wallet2, options.task, priceWei.toString(), options.message);
|
|
2699
2919
|
if (options.json) {
|
|
@@ -2706,17 +2926,24 @@ ${taskBefore.task}
|
|
|
2706
2926
|
status: task.status,
|
|
2707
2927
|
quotedPriceWei: task.quotedPriceWei,
|
|
2708
2928
|
quotedMessage: task.quotedMessage
|
|
2709
|
-
}
|
|
2929
|
+
},
|
|
2930
|
+
nextActions: [
|
|
2931
|
+
{ command: `mltl inbox`, description: "Check inbox for status updates" },
|
|
2932
|
+
{ command: `mltl message --task ${task.id} --content "..."`, description: "Message the client" }
|
|
2933
|
+
],
|
|
2934
|
+
flow: "requested \u2192 [quoted] \u2192 accepted \u2192 submitted \u2192 completed"
|
|
2710
2935
|
})
|
|
2711
2936
|
);
|
|
2712
2937
|
return;
|
|
2713
2938
|
}
|
|
2714
2939
|
console.log("\n\u2705 Quote submitted!");
|
|
2715
2940
|
console.log("\nThe client will review your quote.");
|
|
2716
|
-
console.log("If they accept,
|
|
2717
|
-
console.log("
|
|
2718
|
-
console.log(
|
|
2719
|
-
console.log(` mltl
|
|
2941
|
+
console.log("If they accept, funds lock in escrow and you can begin work.\n");
|
|
2942
|
+
console.log("Next steps:");
|
|
2943
|
+
console.log(` Check inbox: mltl inbox`);
|
|
2944
|
+
console.log(` Send a message: mltl message --task ${task.id} --content "..."`);
|
|
2945
|
+
console.log(`
|
|
2946
|
+
Flow: requested \u2192 [quoted] \u2192 accepted \u2192 submitted \u2192 completed
|
|
2720
2947
|
`);
|
|
2721
2948
|
} catch (err) {
|
|
2722
2949
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -2731,7 +2958,7 @@ ${taskBefore.task}
|
|
|
2731
2958
|
}
|
|
2732
2959
|
|
|
2733
2960
|
// src/commands/claim.ts
|
|
2734
|
-
import { formatEther as
|
|
2961
|
+
import { formatEther as formatEther10 } from "viem";
|
|
2735
2962
|
async function claim(options) {
|
|
2736
2963
|
const { wallet: wallet2 } = await loadOrCreateWallet();
|
|
2737
2964
|
if (!options.json) {
|
|
@@ -2753,7 +2980,7 @@ async function claim(options) {
|
|
|
2753
2980
|
if (escrow.status === 3 /* Disputed */) {
|
|
2754
2981
|
throw new Error("Task is disputed. Cannot claim until dispute is resolved.");
|
|
2755
2982
|
}
|
|
2756
|
-
const priceEth =
|
|
2983
|
+
const priceEth = formatEther10(escrow.amount);
|
|
2757
2984
|
const timedOut = await isEscrowTimedOut(options.task);
|
|
2758
2985
|
if (!timedOut) {
|
|
2759
2986
|
const secondsLeft = await getTimeUntilTimeout(options.task);
|
|
@@ -2830,7 +3057,7 @@ The client did not respond within 24 hours.`);
|
|
|
2830
3057
|
}
|
|
2831
3058
|
|
|
2832
3059
|
// src/commands/refund.ts
|
|
2833
|
-
import { formatEther as
|
|
3060
|
+
import { formatEther as formatEther11 } from "viem";
|
|
2834
3061
|
async function refund(options) {
|
|
2835
3062
|
const { wallet: wallet2 } = await loadOrCreateWallet();
|
|
2836
3063
|
if (!options.json) {
|
|
@@ -2858,7 +3085,7 @@ async function refund(options) {
|
|
|
2858
3085
|
if (!options.json) {
|
|
2859
3086
|
console.log(`
|
|
2860
3087
|
Task ID: ${task.id}`);
|
|
2861
|
-
console.log(`Escrowed: ${
|
|
3088
|
+
console.log(`Escrowed: ${formatEther11(escrow.amount)} ETH`);
|
|
2862
3089
|
console.log("\nRefunding to your wallet...");
|
|
2863
3090
|
}
|
|
2864
3091
|
const txHash = await refundEscrow(wallet2, task.id);
|
|
@@ -2871,16 +3098,21 @@ Task ID: ${task.id}`);
|
|
|
2871
3098
|
JSON.stringify({
|
|
2872
3099
|
success: true,
|
|
2873
3100
|
taskId: task.id,
|
|
2874
|
-
refundedAmount:
|
|
2875
|
-
txHash
|
|
3101
|
+
refundedAmount: formatEther11(escrow.amount),
|
|
3102
|
+
txHash,
|
|
3103
|
+
nextActions: [
|
|
3104
|
+
{ command: `mltl hire --agent ${task.agentId} --task "..."`, description: "Hire the same agent again" },
|
|
3105
|
+
{ command: `mltl agents`, description: "Browse other agents" }
|
|
3106
|
+
],
|
|
3107
|
+
note: "Full refund \u2014 no fees deducted. Task is closed."
|
|
2876
3108
|
})
|
|
2877
3109
|
);
|
|
2878
3110
|
return;
|
|
2879
3111
|
}
|
|
2880
|
-
console.log("\n\u2705 Refund successful!");
|
|
3112
|
+
console.log("\n\u2705 Refund successful! No fees deducted.");
|
|
2881
3113
|
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");
|
|
2882
3114
|
console.log(`
|
|
2883
|
-
Refunded: ${
|
|
3115
|
+
Refunded: ${formatEther11(escrow.amount)} ETH \u2192 ${wallet2.address}`);
|
|
2884
3116
|
console.log(`TX: ${txHash}
|
|
2885
3117
|
`);
|
|
2886
3118
|
} catch (err) {
|
|
@@ -2896,7 +3128,7 @@ Refunded: ${formatEther10(escrow.amount)} ETH \u2192 ${wallet2.address}`);
|
|
|
2896
3128
|
}
|
|
2897
3129
|
|
|
2898
3130
|
// src/commands/cancel.ts
|
|
2899
|
-
import { formatEther as
|
|
3131
|
+
import { formatEther as formatEther12 } from "viem";
|
|
2900
3132
|
async function cancel(options) {
|
|
2901
3133
|
const { wallet: wallet2 } = await loadOrCreateWallet();
|
|
2902
3134
|
if (!options.json) {
|
|
@@ -2922,10 +3154,12 @@ async function cancel(options) {
|
|
|
2922
3154
|
if (!options.json) {
|
|
2923
3155
|
console.log(`
|
|
2924
3156
|
Task ID: ${task.id}`);
|
|
2925
|
-
console.log(`Escrowed: ${
|
|
2926
|
-
console.log(`Cancel fee: ${
|
|
2927
|
-
console.log(`You receive: ${
|
|
2928
|
-
console.log("\
|
|
3157
|
+
console.log(`Escrowed: ${formatEther12(escrow.amount)} ETH`);
|
|
3158
|
+
console.log(`Cancel fee: ${formatEther12(fee)} ETH (10% to agent for lost opportunity)`);
|
|
3159
|
+
console.log(`You receive: ${formatEther12(escrow.amount - fee)} ETH`);
|
|
3160
|
+
console.log("\nNote: If the agent hasn't started yet, consider 'mltl refund' instead (no fee).");
|
|
3161
|
+
console.log("Cancel is for tasks already accepted by the agent.\n");
|
|
3162
|
+
console.log("Cancelling...");
|
|
2929
3163
|
}
|
|
2930
3164
|
const txHash = await cancelEscrow(wallet2, task.id);
|
|
2931
3165
|
try {
|
|
@@ -2937,9 +3171,13 @@ Task ID: ${task.id}`);
|
|
|
2937
3171
|
JSON.stringify({
|
|
2938
3172
|
success: true,
|
|
2939
3173
|
taskId: task.id,
|
|
2940
|
-
cancelFee:
|
|
2941
|
-
refundedAmount:
|
|
2942
|
-
txHash
|
|
3174
|
+
cancelFee: formatEther12(fee),
|
|
3175
|
+
refundedAmount: formatEther12(escrow.amount - fee),
|
|
3176
|
+
txHash,
|
|
3177
|
+
nextActions: [
|
|
3178
|
+
{ command: `mltl hire --agent ${task.agentId} --task "..."`, description: "Hire the same agent again" },
|
|
3179
|
+
{ command: `mltl agents`, description: "Browse other agents" }
|
|
3180
|
+
]
|
|
2943
3181
|
})
|
|
2944
3182
|
);
|
|
2945
3183
|
return;
|
|
@@ -2947,8 +3185,8 @@ Task ID: ${task.id}`);
|
|
|
2947
3185
|
console.log("\nTask cancelled.");
|
|
2948
3186
|
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");
|
|
2949
3187
|
console.log(`
|
|
2950
|
-
Cancel fee: ${
|
|
2951
|
-
console.log(`Refunded: ${
|
|
3188
|
+
Cancel fee: ${formatEther12(fee)} ETH \u2192 agent`);
|
|
3189
|
+
console.log(`Refunded: ${formatEther12(escrow.amount - fee)} ETH \u2192 ${wallet2.address}`);
|
|
2952
3190
|
console.log(`TX: ${txHash}
|
|
2953
3191
|
`);
|
|
2954
3192
|
} catch (err) {
|
|
@@ -2964,7 +3202,7 @@ Cancel fee: ${formatEther11(fee)} ETH \u2192 agent`);
|
|
|
2964
3202
|
}
|
|
2965
3203
|
|
|
2966
3204
|
// src/commands/dispute.ts
|
|
2967
|
-
import { formatEther as
|
|
3205
|
+
import { formatEther as formatEther13 } from "viem";
|
|
2968
3206
|
async function dispute(options) {
|
|
2969
3207
|
const { wallet: wallet2 } = await loadOrCreateWallet();
|
|
2970
3208
|
if (!options.json) {
|
|
@@ -2987,12 +3225,17 @@ async function dispute(options) {
|
|
|
2987
3225
|
throw new Error("Escrow is not in submitted state");
|
|
2988
3226
|
}
|
|
2989
3227
|
const feeWei = await getDisputeFee(task.id);
|
|
2990
|
-
const feeEth =
|
|
3228
|
+
const feeEth = formatEther13(feeWei);
|
|
2991
3229
|
if (!options.json) {
|
|
2992
3230
|
console.log(`
|
|
2993
3231
|
Task ID: ${task.id}`);
|
|
2994
|
-
console.log(`Escrow: ${
|
|
2995
|
-
console.log(`Dispute fee: ${feeEth} ETH (10% of escrow)`);
|
|
3232
|
+
console.log(`Escrow: ${formatEther13(escrow.amount)} ETH`);
|
|
3233
|
+
console.log(`Dispute fee: ${feeEth} ETH (10% of escrow, non-refundable if you lose)`);
|
|
3234
|
+
console.log("\n\u26A0 Disputes are a last resort. Consider these alternatives first:");
|
|
3235
|
+
console.log(` Request revision: mltl revise --task ${task.id} --reason "..."`);
|
|
3236
|
+
console.log(` Message the agent: mltl message --task ${task.id} --content "..."`);
|
|
3237
|
+
console.log("\n If you win: escrow refunded + dispute fee returned.");
|
|
3238
|
+
console.log(" If you lose: agent gets paid, you lose the dispute fee.");
|
|
2996
3239
|
console.log("\nOpening dispute...");
|
|
2997
3240
|
}
|
|
2998
3241
|
const txHash = await disputeEscrow(wallet2, task.id, feeWei);
|
|
@@ -3008,18 +3251,25 @@ Task ID: ${task.id}`);
|
|
|
3008
3251
|
success: true,
|
|
3009
3252
|
taskId: task.id,
|
|
3010
3253
|
disputeFee: feeEth,
|
|
3011
|
-
txHash
|
|
3254
|
+
txHash,
|
|
3255
|
+
note: "Timeout frozen. Admin will review. If you win: escrow + fee returned. If you lose: agent gets paid, fee lost.",
|
|
3256
|
+
nextActions: [
|
|
3257
|
+
{ command: `mltl message --task ${task.id} --content "..."`, description: "Add context for the admin" },
|
|
3258
|
+
{ command: `mltl view --task ${task.id}`, description: "View task details" }
|
|
3259
|
+
]
|
|
3012
3260
|
})
|
|
3013
3261
|
);
|
|
3014
3262
|
return;
|
|
3015
3263
|
}
|
|
3016
|
-
console.log("\nDispute opened!
|
|
3264
|
+
console.log("\nDispute opened! 24h timeout is now frozen.");
|
|
3017
3265
|
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");
|
|
3018
3266
|
console.log(`
|
|
3019
3267
|
Fee paid: ${feeEth} ETH`);
|
|
3020
3268
|
console.log(`TX: ${txHash}`);
|
|
3021
3269
|
console.log("\nAn admin will review and resolve the dispute.");
|
|
3022
|
-
console.log("
|
|
3270
|
+
console.log("Add context via messages to help resolution:");
|
|
3271
|
+
console.log(` mltl message --task ${task.id} --content "..."
|
|
3272
|
+
`);
|
|
3023
3273
|
} catch (err) {
|
|
3024
3274
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
3025
3275
|
if (options.json) {
|
|
@@ -3033,7 +3283,7 @@ Fee paid: ${feeEth} ETH`);
|
|
|
3033
3283
|
}
|
|
3034
3284
|
|
|
3035
3285
|
// src/commands/resolve.ts
|
|
3036
|
-
import { formatEther as
|
|
3286
|
+
import { formatEther as formatEther14 } from "viem";
|
|
3037
3287
|
async function resolve(options) {
|
|
3038
3288
|
const { wallet: wallet2 } = await loadOrCreateWallet();
|
|
3039
3289
|
if (!["client", "agent"].includes(options.winner)) {
|
|
@@ -3060,8 +3310,8 @@ async function resolve(options) {
|
|
|
3060
3310
|
if (!options.json) {
|
|
3061
3311
|
console.log(`
|
|
3062
3312
|
Task ID: ${task.id}`);
|
|
3063
|
-
console.log(`Escrow: ${
|
|
3064
|
-
console.log(`Dispute fee: ${
|
|
3313
|
+
console.log(`Escrow: ${formatEther14(escrow.amount)} ETH`);
|
|
3314
|
+
console.log(`Dispute fee: ${formatEther14(escrow.disputeFee)} ETH`);
|
|
3065
3315
|
console.log(`Resolution: ${clientWins ? "CLIENT WINS (refund)" : "AGENT WINS (buyback)"}`);
|
|
3066
3316
|
console.log("\nCalling resolveDispute on-chain...");
|
|
3067
3317
|
}
|
|
@@ -3134,7 +3384,13 @@ async function revise(options) {
|
|
|
3134
3384
|
agentId: task.agentId,
|
|
3135
3385
|
status: task.status,
|
|
3136
3386
|
revisionCount: task.revisionCount
|
|
3137
|
-
}
|
|
3387
|
+
},
|
|
3388
|
+
nextActions: [
|
|
3389
|
+
{ command: `mltl message --task ${task.id} --content "..."`, description: "Add more context for the agent" },
|
|
3390
|
+
{ command: `mltl view --task ${task.id}`, description: "View task thread" }
|
|
3391
|
+
],
|
|
3392
|
+
flow: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 [revision] \u2192 submitted \u2192 completed",
|
|
3393
|
+
note: "Agent will rework and resubmit. No additional cost \u2014 same escrow applies."
|
|
3138
3394
|
})
|
|
3139
3395
|
);
|
|
3140
3396
|
return;
|
|
@@ -3150,8 +3406,8 @@ Your feedback:
|
|
|
3150
3406
|
${options.reason}
|
|
3151
3407
|
`);
|
|
3152
3408
|
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");
|
|
3153
|
-
console.log("\nThe agent will revise and resubmit
|
|
3154
|
-
console.log("
|
|
3409
|
+
console.log("\nThe agent will revise and resubmit. No additional cost.");
|
|
3410
|
+
console.log("Add more context:");
|
|
3155
3411
|
console.log(` mltl message --task ${task.id} --content "additional details"
|
|
3156
3412
|
`);
|
|
3157
3413
|
} catch (err) {
|
|
@@ -3248,34 +3504,93 @@ Failed to send message: ${errorMsg}`);
|
|
|
3248
3504
|
}
|
|
3249
3505
|
|
|
3250
3506
|
// src/commands/view.ts
|
|
3251
|
-
import { formatEther as
|
|
3507
|
+
import { formatEther as formatEther15 } from "viem";
|
|
3252
3508
|
function formatTimestamp4(ts) {
|
|
3253
3509
|
return new Date(ts).toLocaleString();
|
|
3254
3510
|
}
|
|
3255
|
-
function
|
|
3511
|
+
function suggestedActions(task, role) {
|
|
3512
|
+
const id = task.id;
|
|
3256
3513
|
switch (task.status) {
|
|
3257
3514
|
case "requested":
|
|
3258
|
-
return `Quote: mltl quote --task ${
|
|
3259
|
-
Decline: mltl decline --task ${
|
|
3515
|
+
if (role === "agent") return `Quote: mltl quote --task ${id} --price <eth>
|
|
3516
|
+
Decline: mltl decline --task ${id}`;
|
|
3517
|
+
if (role === "client") return `Waiting for agent to quote. You can add context:
|
|
3518
|
+
mltl message --task ${id} --content "..."`;
|
|
3519
|
+
return `Agent: mltl quote --task ${id} --price <eth>
|
|
3520
|
+
Agent: mltl decline --task ${id}`;
|
|
3260
3521
|
case "quoted":
|
|
3261
|
-
return `
|
|
3522
|
+
if (role === "client") return `Accept: mltl accept --task ${id} (deposits ETH into escrow)
|
|
3523
|
+
Message: mltl message --task ${id} --content "..."`;
|
|
3524
|
+
if (role === "agent") return `Waiting for client to accept your quote.
|
|
3525
|
+
Message: mltl message --task ${id} --content "..."`;
|
|
3526
|
+
return `Client: mltl accept --task ${id}
|
|
3527
|
+
Either: mltl message --task ${id} --content "..."`;
|
|
3262
3528
|
case "accepted":
|
|
3529
|
+
if (role === "agent") return `Submit work when ready:
|
|
3530
|
+
mltl submit --task ${id} --result "..." --files file1.txt,file2.pdf`;
|
|
3531
|
+
if (role === "client") return `Agent is working. You can:
|
|
3532
|
+
Message: mltl message --task ${id} --content "..."
|
|
3533
|
+
Cancel: mltl cancel --task ${id} (10% fee to agent)`;
|
|
3534
|
+
return `Agent: mltl submit --task ${id} --result "..."`;
|
|
3263
3535
|
case "revision":
|
|
3264
|
-
return `
|
|
3536
|
+
if (role === "agent") return `Revision requested. Fix and resubmit:
|
|
3537
|
+
mltl submit --task ${id} --result "..." --files file1.txt`;
|
|
3538
|
+
if (role === "client") return `Waiting for agent to resubmit.
|
|
3539
|
+
Message: mltl message --task ${id} --content "..."`;
|
|
3540
|
+
return `Agent: mltl submit --task ${id} --result "..."`;
|
|
3265
3541
|
case "submitted":
|
|
3266
|
-
return `
|
|
3542
|
+
if (role === "client") return `Review the result above, then:
|
|
3543
|
+
Approve: mltl approve --task ${id} (releases payment, final)
|
|
3544
|
+
Revise: mltl revise --task ${id} --reason "..."
|
|
3545
|
+
Dispute: mltl dispute --task ${id} (10% fee, last resort)`;
|
|
3546
|
+
if (role === "agent") return `Waiting for client review. 24h timeout protects you.
|
|
3547
|
+
Claim: mltl claim --task ${id} (after 24h with no response)`;
|
|
3548
|
+
return `Client: mltl approve --task ${id}
|
|
3549
|
+
Client: mltl revise --task ${id} --reason "..."`;
|
|
3550
|
+
case "completed":
|
|
3551
|
+
if (role === "client") return `Leave a review:
|
|
3552
|
+
mltl feedback --task ${id} --score <0-100> --comment "..."`;
|
|
3553
|
+
return null;
|
|
3554
|
+
case "disputed":
|
|
3555
|
+
return `Awaiting admin resolution.
|
|
3556
|
+
Add context: mltl message --task ${id} --content "..."`;
|
|
3267
3557
|
default:
|
|
3268
3558
|
return null;
|
|
3269
3559
|
}
|
|
3270
3560
|
}
|
|
3561
|
+
var STATUS_FLOW = {
|
|
3562
|
+
requested: "[requested] \u2192 quoted \u2192 accepted \u2192 submitted \u2192 completed",
|
|
3563
|
+
quoted: "requested \u2192 [quoted] \u2192 accepted \u2192 submitted \u2192 completed",
|
|
3564
|
+
accepted: "requested \u2192 quoted \u2192 [accepted] \u2192 submitted \u2192 completed",
|
|
3565
|
+
revision: "requested \u2192 quoted \u2192 accepted \u2192 [revision] \u2192 submitted \u2192 completed",
|
|
3566
|
+
submitted: "requested \u2192 quoted \u2192 accepted \u2192 [submitted] \u2192 completed",
|
|
3567
|
+
completed: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 [completed]",
|
|
3568
|
+
declined: "requested \u2192 [declined]",
|
|
3569
|
+
disputed: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 [disputed] \u2192 resolved",
|
|
3570
|
+
resolved: "requested \u2192 quoted \u2192 accepted \u2192 submitted \u2192 disputed \u2192 [resolved]"
|
|
3571
|
+
};
|
|
3271
3572
|
async function view(options) {
|
|
3272
3573
|
try {
|
|
3273
3574
|
const task = await getTask(options.task);
|
|
3575
|
+
let role = "unknown";
|
|
3576
|
+
try {
|
|
3577
|
+
const wallet2 = await loadWallet();
|
|
3578
|
+
if (wallet2) {
|
|
3579
|
+
const addr = wallet2.address.toLowerCase();
|
|
3580
|
+
if (task.clientAddress.toLowerCase() === addr) {
|
|
3581
|
+
role = "client";
|
|
3582
|
+
} else {
|
|
3583
|
+
role = "agent";
|
|
3584
|
+
}
|
|
3585
|
+
}
|
|
3586
|
+
} catch {
|
|
3587
|
+
}
|
|
3274
3588
|
if (options.json) {
|
|
3275
|
-
|
|
3589
|
+
const flow2 = STATUS_FLOW[task.status] || null;
|
|
3590
|
+
console.log(JSON.stringify({ task, role, flow: flow2 }));
|
|
3276
3591
|
return;
|
|
3277
3592
|
}
|
|
3278
|
-
const priceEth = task.quotedPriceWei ?
|
|
3593
|
+
const priceEth = task.quotedPriceWei ? formatEther15(BigInt(task.quotedPriceWei)) : null;
|
|
3279
3594
|
console.log("\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
3280
3595
|
console.log(` Task ${task.id}`);
|
|
3281
3596
|
console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n");
|
|
@@ -3324,10 +3639,18 @@ async function view(options) {
|
|
|
3324
3639
|
`);
|
|
3325
3640
|
}
|
|
3326
3641
|
}
|
|
3327
|
-
const
|
|
3328
|
-
if (
|
|
3642
|
+
const flow = STATUS_FLOW[task.status];
|
|
3643
|
+
if (flow) {
|
|
3329
3644
|
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");
|
|
3330
|
-
console.log("
|
|
3645
|
+
console.log(" Flow");
|
|
3646
|
+
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");
|
|
3647
|
+
console.log(flow);
|
|
3648
|
+
}
|
|
3649
|
+
const action = suggestedActions(task, role);
|
|
3650
|
+
if (action) {
|
|
3651
|
+
const roleLabel = role === "client" ? " (you are the client)" : role === "agent" ? " (you are the agent)" : "";
|
|
3652
|
+
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");
|
|
3653
|
+
console.log(` Next Action${roleLabel}`);
|
|
3331
3654
|
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");
|
|
3332
3655
|
console.log(action);
|
|
3333
3656
|
}
|
|
@@ -3540,6 +3863,7 @@ program.command("agents").description("Browse registered agents").option("--skil
|
|
|
3540
3863
|
program.command("reviews").description("View verified reviews for an agent").requiredOption("--agent <id>", "Agent ID").option("--json", "Output as JSON").action(reviews);
|
|
3541
3864
|
program.command("wallet").description("Show wallet info and balance").option("--json", "Output as JSON").action(wallet);
|
|
3542
3865
|
program.command("earnings").description("View your earnings from being hired").option("--json", "Output as JSON").action(earnings);
|
|
3866
|
+
program.command("fees").description("Check and claim trading fees from your Flaunch token").option("--claim", "Claim pending fees to your wallet").option("--json", "Output as JSON").action(fees);
|
|
3543
3867
|
program.command("inbox").description("View pending work requests for your agent").option("--agent <id>", "Agent ID (auto-detected from wallet if omitted)").option("--json", "Output as JSON").action(inbox);
|
|
3544
3868
|
program.command("quote").description("Quote a price for a task request (agent)").requiredOption("--task <id>", "Task ID to quote").requiredOption("--price <eth>", "Price in ETH").option("--message <text>", "Optional message to client").option("--json", "Output as JSON").action(quote);
|
|
3545
3869
|
program.command("decline").description("Decline a task request (agent)").requiredOption("--task <id>", "Task ID to decline").option("--json", "Output as JSON").action(decline);
|