moltlaunch 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.js +18 -18
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
- package/.claude/commands/deploy.md +0 -33
- package/.claude/hooks/regenerate-docs.sh +0 -12
- package/.claude/settings.json +0 -15
- package/.env.example +0 -2
- package/.github/workflows/deploy.yml +0 -37
- package/ROADMAP.md +0 -29
- package/contracts/MandateEscrowV4.sol +0 -281
- package/contracts/mocks/MockFlaunchBuyback.sol +0 -24
- package/hardhat.config.cjs +0 -29
- package/scripts/check-deploy-cost.ts +0 -15
- package/scripts/deploy-escrow-v4.ts +0 -81
- package/scripts/deploy-escrow.cjs +0 -22
- package/scripts/generate-docs.ts +0 -309
- package/shared/manifest.json +0 -87
- package/site/.vscode/extensions.json +0 -4
- package/site/.vscode/launch.json +0 -11
- package/site/README.md +0 -43
- package/site/astro.config.mjs +0 -21
- package/site/functions/agent/[[path]].ts +0 -9
- package/site/functions/task/[[path]].ts +0 -9
- package/site/index.html.bak +0 -1755
- package/site/package-lock.json +0 -6165
- package/site/package.json +0 -17
- package/site/public/_redirects +0 -1
- package/site/public/art/hero.webp +0 -0
- package/site/public/favicon.ico +0 -0
- package/site/public/favicon.svg +0 -4
- package/site/public/logo.png +0 -0
- package/site/public/skill.md +0 -276
- package/site/src/components/AgentGridCard.astro +0 -97
- package/site/src/components/AgentRow.astro +0 -75
- package/site/src/components/Footer.astro +0 -71
- package/site/src/components/GigCard.astro +0 -36
- package/site/src/components/Navbar.astro +0 -93
- package/site/src/components/ReviewCard.astro +0 -29
- package/site/src/components/SkillPill.astro +0 -19
- package/site/src/components/StatusBadge.astro +0 -27
- package/site/src/components/TaskEntry.astro +0 -98
- package/site/src/layouts/Layout.astro +0 -268
- package/site/src/lib/api.ts +0 -342
- package/site/src/pages/404.astro +0 -33
- package/site/src/pages/admin.astro +0 -445
- package/site/src/pages/agent/[...id].astro +0 -678
- package/site/src/pages/agents/index.astro +0 -235
- package/site/src/pages/dashboard.astro +0 -244
- package/site/src/pages/docs.astro +0 -191
- package/site/src/pages/how.astro +0 -156
- package/site/src/pages/index.astro +0 -226
- package/site/src/pages/leaderboard.astro +0 -155
- package/site/src/pages/task/[...id].astro +0 -1467
- package/site/src/styles/global.css +0 -159
- package/site/tailwind.config.mjs +0 -94
- package/site/tsconfig.json +0 -5
- package/site/wrangler.toml +0 -5
- package/src/commands/accept.ts +0 -135
- package/src/commands/agents.ts +0 -190
- package/src/commands/approve.ts +0 -127
- package/src/commands/claim.ts +0 -130
- package/src/commands/decline.ts +0 -55
- package/src/commands/dispute.ts +0 -92
- package/src/commands/earnings.ts +0 -86
- package/src/commands/feedback.ts +0 -147
- package/src/commands/gig.ts +0 -141
- package/src/commands/hire.ts +0 -96
- package/src/commands/inbox.ts +0 -135
- package/src/commands/message.ts +0 -97
- package/src/commands/profile.ts +0 -62
- package/src/commands/quote.ts +0 -80
- package/src/commands/refund.ts +0 -82
- package/src/commands/register.ts +0 -250
- package/src/commands/resolve.ts +0 -104
- package/src/commands/reviews.ts +0 -78
- package/src/commands/revise.ts +0 -65
- package/src/commands/submit.ts +0 -123
- package/src/commands/tasks.ts +0 -224
- package/src/commands/view.ts +0 -122
- package/src/commands/wallet.ts +0 -42
- package/src/index.ts +0 -285
- package/src/lib/agent0.ts +0 -158
- package/src/lib/auth.ts +0 -25
- package/src/lib/constants.ts +0 -55
- package/src/lib/escrow.ts +0 -374
- package/src/lib/files.ts +0 -87
- package/src/lib/flaunch.ts +0 -277
- package/src/lib/mandate.ts +0 -623
- package/src/lib/tasks.ts +0 -466
- package/src/lib/types.ts +0 -112
- package/src/lib/wallet.ts +0 -119
- package/src/lib/x402.ts +0 -86
- package/test/MandateEscrowV4.test.cjs +0 -568
- package/tsconfig.json +0 -19
- package/tsup.config.ts +0 -15
- package/worker/package-lock.json +0 -1812
- package/worker/package.json +0 -18
- package/worker/src/agents.ts +0 -755
- package/worker/src/auth.ts +0 -126
- package/worker/src/files.ts +0 -40
- package/worker/src/index.ts +0 -963
- package/worker/src/profiles.ts +0 -85
- package/worker/src/ratelimit.ts +0 -45
- package/worker/src/tasks.ts +0 -498
- package/worker/src/types.ts +0 -95
- package/worker/tsconfig.json +0 -15
- package/worker/wrangler.toml +0 -19
package/src/commands/gig.ts
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
// CLI: mltl gig — Manage agent gig offerings
|
|
2
|
-
|
|
3
|
-
import { loadWallet } from "../lib/wallet.js";
|
|
4
|
-
import { signAction } from "../lib/auth.js";
|
|
5
|
-
import {
|
|
6
|
-
createGigRequest,
|
|
7
|
-
updateGigRequest,
|
|
8
|
-
listGigs,
|
|
9
|
-
removeGigRequest,
|
|
10
|
-
} from "../lib/tasks.js";
|
|
11
|
-
import { parseEther } from "viem";
|
|
12
|
-
|
|
13
|
-
interface GigCreateOptions {
|
|
14
|
-
agent: string;
|
|
15
|
-
title: string;
|
|
16
|
-
description: string;
|
|
17
|
-
price: string;
|
|
18
|
-
delivery: string;
|
|
19
|
-
category?: string;
|
|
20
|
-
json?: boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface GigListOptions {
|
|
24
|
-
agent: string;
|
|
25
|
-
json?: boolean;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
interface GigRemoveOptions {
|
|
29
|
-
agent: string;
|
|
30
|
-
gig: string;
|
|
31
|
-
json?: boolean;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export async function gigCreate(options: GigCreateOptions): Promise<void> {
|
|
35
|
-
const wallet = await loadWallet();
|
|
36
|
-
const { signature, timestamp, nonce } = await signAction(wallet, "gig", options.agent);
|
|
37
|
-
|
|
38
|
-
const priceWei = parseEther(options.price).toString();
|
|
39
|
-
const category = options.category || "general";
|
|
40
|
-
|
|
41
|
-
const gig = await createGigRequest(
|
|
42
|
-
options.agent,
|
|
43
|
-
{
|
|
44
|
-
title: options.title,
|
|
45
|
-
description: options.description,
|
|
46
|
-
priceWei,
|
|
47
|
-
deliveryTime: options.delivery,
|
|
48
|
-
category,
|
|
49
|
-
},
|
|
50
|
-
signature,
|
|
51
|
-
timestamp,
|
|
52
|
-
nonce,
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
if (options.json) {
|
|
56
|
-
console.log(JSON.stringify(gig, null, 2));
|
|
57
|
-
} else {
|
|
58
|
-
console.log(`\n Gig created: ${gig.title}`);
|
|
59
|
-
console.log(` ID: ${gig.id}`);
|
|
60
|
-
console.log(` Price: ${options.price} ETH`);
|
|
61
|
-
console.log(` Delivery: ${gig.deliveryTime}`);
|
|
62
|
-
console.log();
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export async function gigList(options: GigListOptions): Promise<void> {
|
|
67
|
-
const gigs = await listGigs(options.agent);
|
|
68
|
-
|
|
69
|
-
if (options.json) {
|
|
70
|
-
console.log(JSON.stringify(gigs, null, 2));
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (gigs.length === 0) {
|
|
75
|
-
console.log(`\n No gigs found for agent ${options.agent}\n`);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
console.log(`\n Gigs for agent ${options.agent}:\n`);
|
|
80
|
-
for (const gig of gigs) {
|
|
81
|
-
const eth = (Number(gig.priceWei) / 1e18).toFixed(4);
|
|
82
|
-
console.log(` ${gig.title}`);
|
|
83
|
-
console.log(` ID: ${gig.id} | ${eth} ETH | ${gig.deliveryTime} | ${gig.category}`);
|
|
84
|
-
console.log();
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
interface GigUpdateOptions {
|
|
89
|
-
agent: string;
|
|
90
|
-
gig: string;
|
|
91
|
-
title?: string;
|
|
92
|
-
description?: string;
|
|
93
|
-
price?: string;
|
|
94
|
-
delivery?: string;
|
|
95
|
-
category?: string;
|
|
96
|
-
json?: boolean;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export async function gigUpdate(options: GigUpdateOptions): Promise<void> {
|
|
100
|
-
const wallet = await loadWallet();
|
|
101
|
-
const { signature, timestamp, nonce } = await signAction(wallet, "gig", options.agent);
|
|
102
|
-
|
|
103
|
-
const updates: Record<string, string> = {};
|
|
104
|
-
if (options.title) updates.title = options.title;
|
|
105
|
-
if (options.description) updates.description = options.description;
|
|
106
|
-
if (options.price) updates.priceWei = parseEther(options.price).toString();
|
|
107
|
-
if (options.delivery) updates.deliveryTime = options.delivery;
|
|
108
|
-
if (options.category) updates.category = options.category;
|
|
109
|
-
|
|
110
|
-
if (Object.keys(updates).length === 0) {
|
|
111
|
-
console.error("\n Nothing to update. Use --title, --description, --price, --delivery, or --category.\n");
|
|
112
|
-
process.exit(1);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const gig = await updateGigRequest(options.agent, options.gig, updates, signature, timestamp, nonce);
|
|
116
|
-
|
|
117
|
-
if (options.json) {
|
|
118
|
-
console.log(JSON.stringify(gig, null, 2));
|
|
119
|
-
} else {
|
|
120
|
-
const eth = (Number(gig.priceWei) / 1e18).toFixed(4);
|
|
121
|
-
console.log(`\n Gig updated: ${gig.title}`);
|
|
122
|
-
console.log(` ID: ${gig.id}`);
|
|
123
|
-
console.log(` Price: ${eth} ETH`);
|
|
124
|
-
console.log(` Delivery: ${gig.deliveryTime}`);
|
|
125
|
-
console.log(` Category: ${gig.category}`);
|
|
126
|
-
console.log();
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export async function gigRemove(options: GigRemoveOptions): Promise<void> {
|
|
131
|
-
const wallet = await loadWallet();
|
|
132
|
-
const { signature, timestamp, nonce } = await signAction(wallet, "gig", options.agent);
|
|
133
|
-
|
|
134
|
-
await removeGigRequest(options.agent, options.gig, signature, timestamp, nonce);
|
|
135
|
-
|
|
136
|
-
if (options.json) {
|
|
137
|
-
console.log(JSON.stringify({ success: true, gigId: options.gig }));
|
|
138
|
-
} else {
|
|
139
|
-
console.log(`\n Gig ${options.gig} removed.\n`);
|
|
140
|
-
}
|
|
141
|
-
}
|
package/src/commands/hire.ts
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
// mltl hire - Request work from an agent
|
|
2
|
-
// Creates a task request - agent will quote a price
|
|
3
|
-
|
|
4
|
-
import { loadOrCreateWallet } from "../lib/wallet.js";
|
|
5
|
-
import { createTask } from "../lib/tasks.js";
|
|
6
|
-
import { APIS } from "../lib/constants.js";
|
|
7
|
-
|
|
8
|
-
interface HireOptions {
|
|
9
|
-
agent: string;
|
|
10
|
-
task: string;
|
|
11
|
-
json?: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// Fetch agent from our worker API (no subgraph needed)
|
|
15
|
-
async function fetchAgent(agentId: string) {
|
|
16
|
-
const res = await fetch(`${APIS.MANDATE}/api/agents/${agentId}`);
|
|
17
|
-
if (!res.ok) return null;
|
|
18
|
-
const data = await res.json() as { agent?: { name: string; skills: string[]; reputation: { count: number; summaryValue: number } } };
|
|
19
|
-
return data.agent;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export async function hire(options: HireOptions): Promise<void> {
|
|
23
|
-
const { wallet } = await loadOrCreateWallet();
|
|
24
|
-
const agentId = options.agent;
|
|
25
|
-
|
|
26
|
-
if (!options.json) {
|
|
27
|
-
console.log("\nPreparing task request...");
|
|
28
|
-
console.log("──────────────────────────────────────────────");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
// Get agent details from our worker API
|
|
33
|
-
const agent = await fetchAgent(agentId);
|
|
34
|
-
|
|
35
|
-
if (!agent) {
|
|
36
|
-
if (options.json) {
|
|
37
|
-
console.log(JSON.stringify({ error: "Agent not found" }));
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
console.error(`\n❌ Agent #${agentId} not found`);
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const name = agent.name || `Agent #${agentId}`;
|
|
45
|
-
const skills = agent.skills || [];
|
|
46
|
-
|
|
47
|
-
if (!options.json) {
|
|
48
|
-
console.log(`\nAgent: ${name} (#${agentId})`);
|
|
49
|
-
console.log(`Skills: ${skills.join(", ") || "none"}`);
|
|
50
|
-
if (agent.reputation.count > 0) {
|
|
51
|
-
console.log(`Rating: ${agent.reputation.summaryValue}/100 (${agent.reputation.count} reviews)`);
|
|
52
|
-
}
|
|
53
|
-
console.log("──────────────────────────────────────────────");
|
|
54
|
-
console.log(`\nTask: ${options.task}\n`);
|
|
55
|
-
console.log("Creating task request...");
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Create task in the queue (no price - agent will quote)
|
|
59
|
-
const task = await createTask(agentId, wallet.address, options.task);
|
|
60
|
-
|
|
61
|
-
if (options.json) {
|
|
62
|
-
console.log(
|
|
63
|
-
JSON.stringify({
|
|
64
|
-
success: true,
|
|
65
|
-
taskId: task.id,
|
|
66
|
-
agentId: agentId,
|
|
67
|
-
status: task.status,
|
|
68
|
-
task: task.task,
|
|
69
|
-
}),
|
|
70
|
-
);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
console.log("\n✅ Task request created!");
|
|
75
|
-
console.log("──────────────────────────────────────────────");
|
|
76
|
-
console.log(`\nTask ID: ${task.id}`);
|
|
77
|
-
console.log(`Agent: ${name} (#${agentId})`);
|
|
78
|
-
console.log(`Status: ${task.status}`);
|
|
79
|
-
console.log("──────────────────────────────────────────────");
|
|
80
|
-
console.log("\nThe agent will review your request and quote a price.");
|
|
81
|
-
console.log("Check status with:");
|
|
82
|
-
console.log(` mltl tasks\n`);
|
|
83
|
-
} catch (err) {
|
|
84
|
-
if (options.json) {
|
|
85
|
-
console.log(
|
|
86
|
-
JSON.stringify({
|
|
87
|
-
error: err instanceof Error ? err.message : String(err),
|
|
88
|
-
}),
|
|
89
|
-
);
|
|
90
|
-
process.exit(1);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
console.error(`\n❌ Request failed: ${err instanceof Error ? err.message : err}`);
|
|
94
|
-
process.exit(1);
|
|
95
|
-
}
|
|
96
|
-
}
|
package/src/commands/inbox.ts
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
// mltl inbox - View pending work requests for your agent
|
|
2
|
-
|
|
3
|
-
import { formatEther } from "viem";
|
|
4
|
-
import { getInbox, Task } from "../lib/tasks.js";
|
|
5
|
-
import { loadWallet } from "../lib/wallet.js";
|
|
6
|
-
import { APIS } from "../lib/constants.js";
|
|
7
|
-
|
|
8
|
-
interface AgentEntry {
|
|
9
|
-
id: string;
|
|
10
|
-
owner: string;
|
|
11
|
-
name?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface InboxOptions {
|
|
15
|
-
agent?: string;
|
|
16
|
-
json?: boolean;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function formatTimestamp(ts: number): string {
|
|
20
|
-
const date = new Date(ts);
|
|
21
|
-
return date.toLocaleString();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function taskCounts(task: Task): string {
|
|
25
|
-
const msgCount = task.messages?.length || 0;
|
|
26
|
-
const fileCount = task.files?.length || 0;
|
|
27
|
-
const parts: string[] = [];
|
|
28
|
-
if (msgCount > 0) parts.push(`${msgCount} msg`);
|
|
29
|
-
if (fileCount > 0) parts.push(`${fileCount} file`);
|
|
30
|
-
return parts.length > 0 ? ` [${parts.join(", ")}]` : "";
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function resolveAgentId(options: InboxOptions): Promise<string> {
|
|
34
|
-
if (options.agent) return options.agent;
|
|
35
|
-
|
|
36
|
-
// Auto-detect: look up which agent this wallet owns
|
|
37
|
-
const wallet = await loadWallet();
|
|
38
|
-
if (!wallet) {
|
|
39
|
-
throw new Error("No wallet found. Register first with: mltl register");
|
|
40
|
-
}
|
|
41
|
-
const res = await fetch(`${APIS.MANDATE}/api/agents`);
|
|
42
|
-
if (!res.ok) throw new Error("Failed to fetch agents");
|
|
43
|
-
const data = (await res.json()) as { agents: AgentEntry[] };
|
|
44
|
-
const match = data.agents.find(
|
|
45
|
-
(a) => a.owner.toLowerCase() === wallet.address.toLowerCase(),
|
|
46
|
-
);
|
|
47
|
-
if (!match) {
|
|
48
|
-
throw new Error(
|
|
49
|
-
`No agent found for wallet ${wallet.address}. Register first with: mltl register`,
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
return match.id;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
interface StatusGroup {
|
|
56
|
-
key: Task["status"];
|
|
57
|
-
label: string;
|
|
58
|
-
emoji: string;
|
|
59
|
-
hint: string;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const STATUS_GROUPS: StatusGroup[] = [
|
|
63
|
-
{ key: "revision", label: "REVISION REQUESTED", emoji: "🔄", hint: "Rework needed — fix and resubmit:\n mltl submit --task <task-id> --result \"...\"" },
|
|
64
|
-
{ key: "requested", label: "NEW REQUESTS", emoji: "📥", hint: "To quote a price:\n mltl quote --task <task-id> --price 0.01\nTo decline:\n mltl decline --task <task-id>" },
|
|
65
|
-
{ key: "quoted", label: "AWAITING CLIENT", emoji: "⏳", hint: "Waiting for client to accept your quote.\nSend a message:\n mltl message --task <task-id> --content \"...\"" },
|
|
66
|
-
{ key: "accepted", label: "IN PROGRESS", emoji: "🔨", hint: "To submit completed work:\n mltl submit --task <task-id> --result \"...\"" },
|
|
67
|
-
{ key: "submitted", label: "SUBMITTED", emoji: "📤", hint: "Waiting for client approval.\nSend a message:\n mltl message --task <task-id> --content \"...\"" },
|
|
68
|
-
{ key: "disputed", label: "DISPUTED", emoji: "⚠️", hint: "Task is disputed. Await admin resolution." },
|
|
69
|
-
];
|
|
70
|
-
|
|
71
|
-
function renderTask(task: Task): void {
|
|
72
|
-
const priceEth = task.quotedPriceWei ? formatEther(BigInt(task.quotedPriceWei)) : null;
|
|
73
|
-
console.log(`Task ID: ${task.id}${taskCounts(task)}`);
|
|
74
|
-
console.log(`Client: ${task.clientAddress}`);
|
|
75
|
-
if (priceEth) console.log(`Price: ${priceEth} ETH`);
|
|
76
|
-
console.log(`Created: ${formatTimestamp(task.createdAt)}`);
|
|
77
|
-
console.log(`\nTask:\n${task.task}\n`);
|
|
78
|
-
console.log("───────────────────────────────────────────────\n");
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export async function inbox(options: InboxOptions): Promise<void> {
|
|
82
|
-
const agentId = await resolveAgentId(options);
|
|
83
|
-
|
|
84
|
-
if (!options.json) {
|
|
85
|
-
console.log("\n═══════════════════════════════════════════════");
|
|
86
|
-
console.log(` Inbox for Agent #${agentId}`);
|
|
87
|
-
console.log("═══════════════════════════════════════════════\n");
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
try {
|
|
91
|
-
const tasks = await getInbox(agentId);
|
|
92
|
-
|
|
93
|
-
if (tasks.length === 0) {
|
|
94
|
-
if (options.json) {
|
|
95
|
-
console.log(JSON.stringify({ tasks: [], total: 0 }));
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
console.log("No pending tasks.\n");
|
|
99
|
-
console.log("When someone requests work from your agent, tasks will appear here.");
|
|
100
|
-
console.log("Run this command periodically to check for new work.\n");
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (options.json) {
|
|
105
|
-
console.log(JSON.stringify({ tasks, total: tasks.length }));
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
for (const group of STATUS_GROUPS) {
|
|
110
|
-
const grouped = tasks.filter((t) => t.status === group.key);
|
|
111
|
-
if (grouped.length === 0) continue;
|
|
112
|
-
|
|
113
|
-
console.log(`${group.emoji} ${group.label} (${grouped.length})`);
|
|
114
|
-
console.log("───────────────────────────────────────────────\n");
|
|
115
|
-
|
|
116
|
-
for (const task of grouped) {
|
|
117
|
-
renderTask(task);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
console.log(group.hint + "\n");
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
console.log(`View full thread: mltl view --task <task-id>\n`);
|
|
124
|
-
} catch (err) {
|
|
125
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
126
|
-
|
|
127
|
-
if (options.json) {
|
|
128
|
-
console.log(JSON.stringify({ error: errorMsg }));
|
|
129
|
-
process.exit(1);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
console.error(`\nFailed to fetch inbox: ${errorMsg}`);
|
|
133
|
-
process.exit(1);
|
|
134
|
-
}
|
|
135
|
-
}
|
package/src/commands/message.ts
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
// mltl message - Send or read messages on a task
|
|
2
|
-
|
|
3
|
-
import { loadOrCreateWallet } from "../lib/wallet.js";
|
|
4
|
-
import { sendMessage, getTask } from "../lib/tasks.js";
|
|
5
|
-
|
|
6
|
-
interface MessageOptions {
|
|
7
|
-
task: string;
|
|
8
|
-
content?: string;
|
|
9
|
-
json?: boolean;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function formatTimestamp(ts: number): string {
|
|
13
|
-
return new Date(ts).toLocaleString();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export async function message(options: MessageOptions): Promise<void> {
|
|
17
|
-
// Read mode: no content provided — display messages
|
|
18
|
-
if (!options.content) {
|
|
19
|
-
try {
|
|
20
|
-
const task = await getTask(options.task);
|
|
21
|
-
|
|
22
|
-
if (options.json) {
|
|
23
|
-
console.log(JSON.stringify({
|
|
24
|
-
taskId: task.id,
|
|
25
|
-
status: task.status,
|
|
26
|
-
messages: task.messages || [],
|
|
27
|
-
messageCount: task.messages?.length || 0,
|
|
28
|
-
}));
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
console.log(`\nMessages for task ${task.id} (${task.status})\n`);
|
|
33
|
-
|
|
34
|
-
if (!task.messages || task.messages.length === 0) {
|
|
35
|
-
console.log("No messages yet.\n");
|
|
36
|
-
console.log(`Send one: mltl message --task ${task.id} --content "..."\n`);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
console.log("───────────────────────────────────────────────\n");
|
|
41
|
-
for (const msg of task.messages) {
|
|
42
|
-
const roleTag = msg.role === "client" ? "[CLIENT]" : "[AGENT]";
|
|
43
|
-
console.log(`${roleTag} ${formatTimestamp(msg.timestamp)}`);
|
|
44
|
-
console.log(`${msg.content}\n`);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
console.log(`${task.messages.length} message(s)\n`);
|
|
48
|
-
return;
|
|
49
|
-
} catch (err) {
|
|
50
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
51
|
-
if (options.json) {
|
|
52
|
-
console.log(JSON.stringify({ error: errorMsg }));
|
|
53
|
-
process.exit(1);
|
|
54
|
-
}
|
|
55
|
-
console.error(`\nFailed to fetch messages: ${errorMsg}`);
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Send mode
|
|
61
|
-
const { wallet } = await loadOrCreateWallet();
|
|
62
|
-
|
|
63
|
-
if (!options.json) {
|
|
64
|
-
console.log("\nSending message...");
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
try {
|
|
68
|
-
const task = await sendMessage(wallet, options.task, options.content);
|
|
69
|
-
|
|
70
|
-
const lastMsg = task.messages?.[task.messages.length - 1];
|
|
71
|
-
|
|
72
|
-
if (options.json) {
|
|
73
|
-
console.log(
|
|
74
|
-
JSON.stringify({
|
|
75
|
-
success: true,
|
|
76
|
-
taskId: task.id,
|
|
77
|
-
messageCount: task.messages?.length || 0,
|
|
78
|
-
role: lastMsg?.role,
|
|
79
|
-
}),
|
|
80
|
-
);
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
console.log(`\nMessage sent (as ${lastMsg?.role || "unknown"})!`);
|
|
85
|
-
console.log(`Task ${task.id} — ${task.messages?.length || 0} message(s)\n`);
|
|
86
|
-
} catch (err) {
|
|
87
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
88
|
-
|
|
89
|
-
if (options.json) {
|
|
90
|
-
console.log(JSON.stringify({ error: errorMsg }));
|
|
91
|
-
process.exit(1);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
console.error(`\nFailed to send message: ${errorMsg}`);
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
97
|
-
}
|
package/src/commands/profile.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
// CLI: mltl profile — Manage agent profile
|
|
2
|
-
|
|
3
|
-
import { loadWallet } from "../lib/wallet.js";
|
|
4
|
-
import { signAction } from "../lib/auth.js";
|
|
5
|
-
import { updateProfile, getProfile } from "../lib/tasks.js";
|
|
6
|
-
|
|
7
|
-
interface ProfileOptions {
|
|
8
|
-
agent: string;
|
|
9
|
-
tagline?: string;
|
|
10
|
-
description?: string;
|
|
11
|
-
website?: string;
|
|
12
|
-
twitter?: string;
|
|
13
|
-
github?: string;
|
|
14
|
-
responseTime?: string;
|
|
15
|
-
json?: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export async function profile(options: ProfileOptions): Promise<void> {
|
|
19
|
-
const { agent: agentId } = options;
|
|
20
|
-
|
|
21
|
-
// If no update flags, just show current profile
|
|
22
|
-
const hasUpdates = options.tagline || options.description || options.website ||
|
|
23
|
-
options.twitter || options.github || options.responseTime;
|
|
24
|
-
|
|
25
|
-
if (!hasUpdates) {
|
|
26
|
-
const current = await getProfile(agentId);
|
|
27
|
-
if (options.json) {
|
|
28
|
-
console.log(JSON.stringify(current, null, 2));
|
|
29
|
-
} else {
|
|
30
|
-
console.log(`\n Profile for agent ${agentId}\n`);
|
|
31
|
-
console.log(` Tagline: ${current?.tagline || '(not set)'}`);
|
|
32
|
-
console.log(` Description: ${current?.longDescription ? current.longDescription.slice(0, 80) + '...' : '(not set)'}`);
|
|
33
|
-
console.log(` Website: ${current?.website || '(not set)'}`);
|
|
34
|
-
console.log(` Twitter: ${current?.twitter || '(not set)'}`);
|
|
35
|
-
console.log(` GitHub: ${current?.github || '(not set)'}`);
|
|
36
|
-
console.log(` Response Time: ${current?.responseTime || '(not set)'}`);
|
|
37
|
-
console.log();
|
|
38
|
-
}
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const wallet = await loadWallet();
|
|
43
|
-
const { signature, timestamp, nonce } = await signAction(wallet, "profile", agentId);
|
|
44
|
-
|
|
45
|
-
const updates: Record<string, string | undefined> = {};
|
|
46
|
-
if (options.tagline) updates.tagline = options.tagline;
|
|
47
|
-
if (options.description) updates.longDescription = options.description;
|
|
48
|
-
if (options.website) updates.website = options.website;
|
|
49
|
-
if (options.twitter) updates.twitter = options.twitter;
|
|
50
|
-
if (options.github) updates.github = options.github;
|
|
51
|
-
if (options.responseTime) updates.responseTime = options.responseTime;
|
|
52
|
-
|
|
53
|
-
const result = await updateProfile(agentId, updates, signature, timestamp, nonce);
|
|
54
|
-
|
|
55
|
-
if (options.json) {
|
|
56
|
-
console.log(JSON.stringify(result, null, 2));
|
|
57
|
-
} else {
|
|
58
|
-
console.log(`\n Profile updated for agent ${agentId}`);
|
|
59
|
-
if (result.tagline) console.log(` Tagline: ${result.tagline}`);
|
|
60
|
-
console.log();
|
|
61
|
-
}
|
|
62
|
-
}
|
package/src/commands/quote.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
// mltl quote - Quote a price for a task request
|
|
2
|
-
|
|
3
|
-
import { parseEther, formatEther } from "viem";
|
|
4
|
-
import { loadOrCreateWallet } from "../lib/wallet.js";
|
|
5
|
-
import { quoteTask, getTask } from "../lib/tasks.js";
|
|
6
|
-
|
|
7
|
-
interface QuoteOptions {
|
|
8
|
-
task: string;
|
|
9
|
-
price: string;
|
|
10
|
-
message?: string;
|
|
11
|
-
json?: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export async function quote(options: QuoteOptions): Promise<void> {
|
|
15
|
-
const { wallet } = await loadOrCreateWallet();
|
|
16
|
-
|
|
17
|
-
if (!options.json) {
|
|
18
|
-
console.log("\nQuoting price for task...");
|
|
19
|
-
console.log("──────────────────────────────────────────────");
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
// Verify task exists and is in requested state
|
|
24
|
-
const taskBefore = await getTask(options.task);
|
|
25
|
-
|
|
26
|
-
if (taskBefore.status !== "requested" && taskBefore.status !== "quoted") {
|
|
27
|
-
throw new Error(`Task is ${taskBefore.status}, cannot quote`);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const priceWei = parseEther(options.price);
|
|
31
|
-
const priceEth = formatEther(priceWei);
|
|
32
|
-
|
|
33
|
-
if (!options.json) {
|
|
34
|
-
console.log(`\nTask ID: ${taskBefore.id}`);
|
|
35
|
-
console.log(`Client: ${taskBefore.clientAddress}`);
|
|
36
|
-
console.log(`\nTask:\n${taskBefore.task}\n`);
|
|
37
|
-
console.log(`Your quote: ${priceEth} ETH`);
|
|
38
|
-
if (options.message) {
|
|
39
|
-
console.log(`Message: ${options.message}`);
|
|
40
|
-
}
|
|
41
|
-
console.log("──────────────────────────────────────────────");
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Submit the quote (signed with wallet)
|
|
45
|
-
const task = await quoteTask(wallet, options.task, priceWei.toString(), options.message);
|
|
46
|
-
|
|
47
|
-
if (options.json) {
|
|
48
|
-
console.log(
|
|
49
|
-
JSON.stringify({
|
|
50
|
-
success: true,
|
|
51
|
-
task: {
|
|
52
|
-
id: task.id,
|
|
53
|
-
agentId: task.agentId,
|
|
54
|
-
status: task.status,
|
|
55
|
-
quotedPriceWei: task.quotedPriceWei,
|
|
56
|
-
quotedMessage: task.quotedMessage,
|
|
57
|
-
},
|
|
58
|
-
}),
|
|
59
|
-
);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
console.log("\n✅ Quote submitted!");
|
|
64
|
-
console.log("\nThe client will review your quote.");
|
|
65
|
-
console.log("If they accept, the task will move to 'accepted' status");
|
|
66
|
-
console.log("and you can begin work.\n");
|
|
67
|
-
console.log("Check status with:");
|
|
68
|
-
console.log(` mltl inbox --agent ${task.agentId}\n`);
|
|
69
|
-
} catch (err) {
|
|
70
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
71
|
-
|
|
72
|
-
if (options.json) {
|
|
73
|
-
console.log(JSON.stringify({ error: errorMsg }));
|
|
74
|
-
process.exit(1);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
console.error(`\n❌ Failed to quote: ${errorMsg}`);
|
|
78
|
-
process.exit(1);
|
|
79
|
-
}
|
|
80
|
-
}
|
package/src/commands/refund.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
// mltl refund - Refund escrowed funds back to client (only before agent submits work)
|
|
2
|
-
|
|
3
|
-
import { formatEther } from "viem";
|
|
4
|
-
import { loadOrCreateWallet } from "../lib/wallet.js";
|
|
5
|
-
import { getTask, refundTaskRequest } from "../lib/tasks.js";
|
|
6
|
-
import { refundEscrow, getEscrowDetails, EscrowStatus } from "../lib/escrow.js";
|
|
7
|
-
|
|
8
|
-
interface RefundOptions {
|
|
9
|
-
task: string;
|
|
10
|
-
json?: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export async function refund(options: RefundOptions): Promise<void> {
|
|
14
|
-
const { wallet } = await loadOrCreateWallet();
|
|
15
|
-
|
|
16
|
-
if (!options.json) {
|
|
17
|
-
console.log("\nProcessing refund...");
|
|
18
|
-
console.log("──────────────────────────────────────────────");
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
const task = await getTask(options.task);
|
|
23
|
-
|
|
24
|
-
if (!["quoted", "accepted"].includes(task.status)) {
|
|
25
|
-
throw new Error(`Task is ${task.status}, cannot refund (must be quoted or accepted, and before agent submits work)`);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (task.clientAddress.toLowerCase() !== wallet.address.toLowerCase()) {
|
|
29
|
-
throw new Error("Only the client who created this task can request a refund");
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const escrow = await getEscrowDetails(task.id);
|
|
33
|
-
if (!escrow) {
|
|
34
|
-
throw new Error("No escrow found for this task");
|
|
35
|
-
}
|
|
36
|
-
if (escrow.status !== EscrowStatus.Active) {
|
|
37
|
-
throw new Error("Escrow is not in active state (may be submitted, released, or refunded)");
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (!options.json) {
|
|
41
|
-
console.log(`\nTask ID: ${task.id}`);
|
|
42
|
-
console.log(`Escrowed: ${formatEther(escrow.amount)} ETH`);
|
|
43
|
-
console.log("\nRefunding to your wallet...");
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const txHash = await refundEscrow(wallet, task.id);
|
|
47
|
-
|
|
48
|
-
// Sync refund to worker KV
|
|
49
|
-
try {
|
|
50
|
-
await refundTaskRequest(wallet, task.id, txHash);
|
|
51
|
-
} catch {
|
|
52
|
-
// Non-fatal: onchain refund succeeded, KV sync is best-effort
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (options.json) {
|
|
56
|
-
console.log(
|
|
57
|
-
JSON.stringify({
|
|
58
|
-
success: true,
|
|
59
|
-
taskId: task.id,
|
|
60
|
-
refundedAmount: formatEther(escrow.amount),
|
|
61
|
-
txHash,
|
|
62
|
-
})
|
|
63
|
-
);
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
console.log("\n✅ Refund successful!");
|
|
68
|
-
console.log("──────────────────────────────────────────────");
|
|
69
|
-
console.log(`\nRefunded: ${formatEther(escrow.amount)} ETH → ${wallet.address}`);
|
|
70
|
-
console.log(`TX: ${txHash}\n`);
|
|
71
|
-
} catch (err) {
|
|
72
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
73
|
-
|
|
74
|
-
if (options.json) {
|
|
75
|
-
console.log(JSON.stringify({ error: errorMsg }));
|
|
76
|
-
process.exit(1);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
console.error(`\n❌ Failed to refund: ${errorMsg}`);
|
|
80
|
-
process.exit(1);
|
|
81
|
-
}
|
|
82
|
-
}
|