@lucid-agents/taskmarket 0.9.0 → 1.1.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 +1007 -158
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ var __export = (target, all) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// src/index.ts
|
|
9
|
-
import { Command as
|
|
9
|
+
import { Command as Command52 } from "commander";
|
|
10
10
|
import { createRequire } from "module";
|
|
11
11
|
|
|
12
12
|
// src/commands/init.ts
|
|
@@ -73,7 +73,7 @@ async function keystoreExists(keystorePath) {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
// src/lib/api.ts
|
|
76
|
-
var API_URL = process.env.TASKMARKET_API_URL ?? "https://api
|
|
76
|
+
var API_URL = process.env.TASKMARKET_API_URL ?? "https://api.taskmarket.dev";
|
|
77
77
|
async function apiGet(path3, options) {
|
|
78
78
|
const res = await fetch(`${API_URL}${path3}`, {
|
|
79
79
|
method: "GET",
|
|
@@ -198,6 +198,14 @@ function decryptWithPrivateKey(fileBuffer, privateKeyHex) {
|
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
// src/commands/init.ts
|
|
201
|
+
function sanitizeEmailUsername(agentId, suffix) {
|
|
202
|
+
const maxBase = 30 - 1 - suffix.length;
|
|
203
|
+
if (maxBase < 2) return null;
|
|
204
|
+
const base = agentId.toLowerCase().replace(/[^a-z0-9]/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "").slice(0, maxBase).replace(/-+$/, "");
|
|
205
|
+
if (base.length < 2) return null;
|
|
206
|
+
const candidate = `${base}-${suffix}`;
|
|
207
|
+
return /^[a-z0-9][a-z0-9-]{1,28}[a-z0-9]$/.test(candidate) ? candidate : null;
|
|
208
|
+
}
|
|
201
209
|
async function tryRegisterEmail(deviceId, apiToken, username, explicit) {
|
|
202
210
|
try {
|
|
203
211
|
const reg = await apiPost("/api/emails/register", {
|
|
@@ -253,7 +261,7 @@ var initCommand = new Command("init").description("Create and register a new age
|
|
|
253
261
|
} catch {
|
|
254
262
|
}
|
|
255
263
|
if (!emailAddress2) {
|
|
256
|
-
const username2 = opts.email ?? (agentId2 && networkInfo2 ?
|
|
264
|
+
const username2 = opts.email ?? (agentId2 && networkInfo2 ? sanitizeEmailUsername(agentId2, String(networkInfo2.chainId)) : null);
|
|
257
265
|
if (username2) {
|
|
258
266
|
emailAddress2 = await tryRegisterEmail(
|
|
259
267
|
keystore.deviceId,
|
|
@@ -291,7 +299,14 @@ var initCommand = new Command("init").description("Create and register a new age
|
|
|
291
299
|
} = await res.json();
|
|
292
300
|
const encryptedKey = encryptPrivateKey(deviceEncryptionKey, privateKey);
|
|
293
301
|
let agentId = initialAgentId;
|
|
294
|
-
await saveKeystore({
|
|
302
|
+
await saveKeystore({
|
|
303
|
+
encryptedKey,
|
|
304
|
+
walletAddress: address,
|
|
305
|
+
deviceId,
|
|
306
|
+
apiToken,
|
|
307
|
+
agentId,
|
|
308
|
+
keyServerUrl: API_URL
|
|
309
|
+
});
|
|
295
310
|
if (!agentId) {
|
|
296
311
|
agentId = await pollAgentId(address);
|
|
297
312
|
if (agentId) {
|
|
@@ -305,7 +320,7 @@ var initCommand = new Command("init").description("Create and register a new age
|
|
|
305
320
|
networkInfo = response.result.data;
|
|
306
321
|
} catch {
|
|
307
322
|
}
|
|
308
|
-
const username = opts.email ?? (agentId && networkInfo ?
|
|
323
|
+
const username = opts.email ?? (agentId && networkInfo ? sanitizeEmailUsername(agentId, String(networkInfo.chainId)) : null);
|
|
309
324
|
const emailAddress = username ? await tryRegisterEmail(deviceId, apiToken, username, !!opts.email) : null;
|
|
310
325
|
printResult({
|
|
311
326
|
address,
|
|
@@ -329,8 +344,9 @@ import { Command as Command3 } from "commander";
|
|
|
329
344
|
// src/lib/signer.ts
|
|
330
345
|
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
331
346
|
import { toHex } from "viem";
|
|
332
|
-
async function fetchDeviceKey(deviceId, apiToken) {
|
|
333
|
-
const
|
|
347
|
+
async function fetchDeviceKey(deviceId, apiToken, keyServerUrl) {
|
|
348
|
+
const base = keyServerUrl ?? API_URL;
|
|
349
|
+
const res = await fetch(`${base}/api/devices/${deviceId}/key`, {
|
|
334
350
|
method: "POST",
|
|
335
351
|
headers: { "Content-Type": "application/json" },
|
|
336
352
|
body: JSON.stringify({ deviceId, apiToken })
|
|
@@ -353,7 +369,7 @@ async function signMessage(message, keystore) {
|
|
|
353
369
|
return sig;
|
|
354
370
|
}
|
|
355
371
|
async function createWalletAccountFromKeystore(keystore) {
|
|
356
|
-
const dek = await fetchDeviceKey(keystore.deviceId, keystore.apiToken);
|
|
372
|
+
const dek = await fetchDeviceKey(keystore.deviceId, keystore.apiToken, keystore.keyServerUrl);
|
|
357
373
|
const privateKey = decryptPrivateKey(dek, keystore.encryptedKey);
|
|
358
374
|
return privateKeyToAccount2(privateKey);
|
|
359
375
|
}
|
|
@@ -467,6 +483,7 @@ var statsCommand = new Command4("stats").description("View agent statistics").op
|
|
|
467
483
|
completedTasks: result.completedTasks,
|
|
468
484
|
ratedTasks: result.ratedTasks,
|
|
469
485
|
averageRating: result.averageRating,
|
|
486
|
+
credibility: result.credibility,
|
|
470
487
|
totalEarnings: result.totalEarnings,
|
|
471
488
|
skills: result.skills,
|
|
472
489
|
emailAddress: result.emailAddress,
|
|
@@ -475,14 +492,44 @@ var statsCommand = new Command4("stats").description("View agent statistics").op
|
|
|
475
492
|
});
|
|
476
493
|
|
|
477
494
|
// src/commands/task/index.ts
|
|
478
|
-
import { Command as
|
|
495
|
+
import { Command as Command29 } from "commander";
|
|
479
496
|
|
|
480
497
|
// src/commands/task/create.ts
|
|
481
498
|
import { Command as Command5 } from "commander";
|
|
482
|
-
var createCmd = new Command5("create").description("Create a new task (costs reward amount in USDC)").requiredOption("--description <text>", "Task description").requiredOption("--reward <usdc>", "Reward in USDC (e.g. 5 for 5 USDC)").requiredOption("--duration <hours>", "Task duration in hours").option("--mode <mode>", "Task mode: bounty, claim, pitch, benchmark, auction", "bounty").option("--tags <tags>", "Comma-separated tags").option("--pitch-deadline <hours>", "Pitch deadline in hours from now (pitch mode only)").option("--bid-deadline <hours>", "Bid deadline in hours from now (auction mode only)").option("--max-price <usdc>", "Maximum bid price in USDC (required for auction mode)").
|
|
499
|
+
var createCmd = new Command5("create").description("Create a new task (costs reward amount in USDC)").requiredOption("--description <text>", "Task description").requiredOption("--reward <usdc>", "Reward in USDC (e.g. 5 for 5 USDC)").requiredOption("--duration <hours>", "Task duration in hours").option("--mode <mode>", "Task mode: bounty, claim, pitch, benchmark, auction", "bounty").option("--tags <tags>", "Comma-separated tags").option("--pitch-deadline <hours>", "Pitch deadline in hours from now (pitch mode only)").option("--bid-deadline <hours>", "Bid deadline in hours from now (auction mode only)").option("--max-price <usdc>", "Maximum bid price in USDC (required for auction mode)").option(
|
|
500
|
+
"--auction-type <type>",
|
|
501
|
+
"Auction subtype: dutch, english, reverse_dutch, reverse_english (required for auction mode)"
|
|
502
|
+
).option(
|
|
503
|
+
"--auction-start-price <usdc>",
|
|
504
|
+
"Starting clock price in USDC for reverse_dutch (required for reverse_dutch)"
|
|
505
|
+
).option(
|
|
506
|
+
"--auction-floor-price <usdc>",
|
|
507
|
+
"Floor price in USDC for dutch clock (optional, defaults to 0)"
|
|
508
|
+
).option("--hook <address>", "ITaskHook contract address (optional)").option(
|
|
509
|
+
"--hook-data <hex>",
|
|
510
|
+
"Hook config bytes forwarded to checkFund; encode uint32 as 4 big-endian bytes (e.g. 0x000006b4 for a 1800s TWAP window)"
|
|
511
|
+
).option("--evaluator <address>", "Evaluator address (optional)").option("--evaluator-fee-bps <bps>", "Evaluator fee in basis points (optional)").option("--evaluation-window <hours>", "Evaluation window in hours (default: 24)").option("--appeal-window <hours>", "Appeal window in hours (default: 24)").option("--dispute-resolver <address>", "Dispute resolver address (optional)").action(
|
|
483
512
|
async (opts) => {
|
|
484
|
-
if (opts.mode === "auction"
|
|
485
|
-
|
|
513
|
+
if (opts.mode === "auction") {
|
|
514
|
+
if (!opts.maxPrice) {
|
|
515
|
+
return void printError("--max-price is required for auction mode");
|
|
516
|
+
}
|
|
517
|
+
if (!opts.auctionType) {
|
|
518
|
+
return void printError(
|
|
519
|
+
"--auction-type is required for auction mode (dutch, english, reverse_dutch, reverse_english)"
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
const validTypes = ["dutch", "english", "reverse_dutch", "reverse_english"];
|
|
523
|
+
if (!validTypes.includes(opts.auctionType)) {
|
|
524
|
+
return void printError(
|
|
525
|
+
`--auction-type must be one of: ${validTypes.join(", ")}. Got: ${opts.auctionType}`
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
if (opts.auctionType === "reverse_dutch" && !opts.auctionStartPrice) {
|
|
529
|
+
return void printError(
|
|
530
|
+
"--auction-start-price is required for reverse_dutch auction type"
|
|
531
|
+
);
|
|
532
|
+
}
|
|
486
533
|
}
|
|
487
534
|
const rewardBaseUnits = String(Math.round(parseFloat(opts.reward) * 1e6));
|
|
488
535
|
const tags = opts.tags ? opts.tags.split(",").map((t) => t.trim()) : [];
|
|
@@ -504,6 +551,52 @@ var createCmd = new Command5("create").description("Create a new task (costs rew
|
|
|
504
551
|
if (opts.maxPrice) {
|
|
505
552
|
body.maxPrice = String(Math.round(parseFloat(opts.maxPrice) * 1e6));
|
|
506
553
|
}
|
|
554
|
+
if (opts.auctionType) {
|
|
555
|
+
body.auctionType = opts.auctionType;
|
|
556
|
+
}
|
|
557
|
+
if (opts.auctionStartPrice) {
|
|
558
|
+
body.auctionStartPrice = String(Math.round(parseFloat(opts.auctionStartPrice) * 1e6));
|
|
559
|
+
}
|
|
560
|
+
if (opts.auctionFloorPrice) {
|
|
561
|
+
body.auctionFloorPrice = String(Math.round(parseFloat(opts.auctionFloorPrice) * 1e6));
|
|
562
|
+
}
|
|
563
|
+
const ethAddrRe = /^0x[0-9a-fA-F]{40}$/;
|
|
564
|
+
if (opts.hook && !ethAddrRe.test(opts.hook)) {
|
|
565
|
+
return void printError("--hook must be a valid Ethereum address (0x + 40 hex chars)");
|
|
566
|
+
}
|
|
567
|
+
if (opts.hookData && !/^0x(?:[0-9a-fA-F]{2})*$/.test(opts.hookData)) {
|
|
568
|
+
return void printError(
|
|
569
|
+
"--hook-data must be a 0x-prefixed hex string with an even number of hex digits"
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
let feeBps;
|
|
573
|
+
if (opts.evaluator) {
|
|
574
|
+
if (!ethAddrRe.test(opts.evaluator)) {
|
|
575
|
+
return void printError(
|
|
576
|
+
"--evaluator must be a valid Ethereum address (0x + 40 hex chars)"
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
if (opts.evaluatorFeeBps) {
|
|
580
|
+
feeBps = Number(opts.evaluatorFeeBps);
|
|
581
|
+
if (!Number.isInteger(feeBps) || feeBps < 0 || feeBps > 1e4) {
|
|
582
|
+
return void printError("--evaluator-fee-bps must be an integer between 0 and 10000");
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
if (opts.disputeResolver && !ethAddrRe.test(opts.disputeResolver)) {
|
|
586
|
+
return void printError(
|
|
587
|
+
"--dispute-resolver must be a valid Ethereum address (0x + 40 hex chars)"
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
if (opts.hook) body.hookContract = opts.hook;
|
|
592
|
+
if (opts.hookData) body.hookData = opts.hookData;
|
|
593
|
+
if (opts.evaluator) {
|
|
594
|
+
body.evaluator = opts.evaluator;
|
|
595
|
+
if (feeBps !== void 0) body.evaluatorFeeBps = feeBps;
|
|
596
|
+
if (opts.evaluationWindow) body.evaluationWindowHours = parseFloat(opts.evaluationWindow);
|
|
597
|
+
if (opts.appealWindow) body.appealWindowHours = parseFloat(opts.appealWindow);
|
|
598
|
+
if (opts.disputeResolver) body.disputeResolver = opts.disputeResolver;
|
|
599
|
+
}
|
|
507
600
|
const result = await x402Post("/api/tasks", body);
|
|
508
601
|
printResult({ taskId: result.taskId });
|
|
509
602
|
}
|
|
@@ -511,11 +604,15 @@ var createCmd = new Command5("create").description("Create a new task (costs rew
|
|
|
511
604
|
|
|
512
605
|
// src/commands/task/search.ts
|
|
513
606
|
import { Command as Command6 } from "commander";
|
|
514
|
-
var listCmd = new Command6("list").alias("search").description("List available tasks").option("--status <status>", "Filter by status (e.g. open)", "open").option("--mode <mode>", "Filter by mode (bounty, claim, pitch, benchmark, auction)").option(
|
|
607
|
+
var listCmd = new Command6("list").alias("search").description("List available tasks").option("--status <status>", "Filter by status (e.g. open)", "open").option("--mode <mode>", "Filter by mode (bounty, claim, pitch, benchmark, auction)").option(
|
|
608
|
+
"--auction-type <type>",
|
|
609
|
+
"Filter auction tasks by subtype (dutch, english, reverse_dutch, reverse_english)"
|
|
610
|
+
).option("--tags <tags>", "Comma-separated tags to filter by").option("--skill <skill>", "Filter by skill tag (comma-separated, alias for --tags)").option("--reward-min <n>", "Minimum reward in USDC").option("--reward-max <n>", "Maximum reward in USDC").option("--deadline-hours <n>", "Only tasks expiring within this many hours").option("--limit <n>", "Maximum results to return", "20").option("--cursor <cursor>", "Cursor from previous page (nextCursor in JSON output)").action(
|
|
515
611
|
async (opts) => {
|
|
516
612
|
const params = new URLSearchParams();
|
|
517
613
|
if (opts.status) params.set("status", opts.status);
|
|
518
614
|
if (opts.mode) params.set("mode", opts.mode);
|
|
615
|
+
if (opts.auctionType) params.set("auctionType", opts.auctionType);
|
|
519
616
|
const tagsValue = opts.tags ?? opts.skill;
|
|
520
617
|
if (tagsValue) params.set("tags", tagsValue);
|
|
521
618
|
if (opts.rewardMin)
|
|
@@ -541,50 +638,245 @@ var getCmd = new Command7("get").description("Get task details").argument("<task
|
|
|
541
638
|
});
|
|
542
639
|
|
|
543
640
|
// src/commands/task/submit.ts
|
|
544
|
-
import { Command as Command8 } from "commander";
|
|
545
|
-
import { promises as
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
641
|
+
import { Command as Command8, Option } from "commander";
|
|
642
|
+
import { promises as fsPromises } from "fs";
|
|
643
|
+
import { basename, extname } from "path";
|
|
644
|
+
import { createHash } from "crypto";
|
|
645
|
+
import { Readable } from "stream";
|
|
646
|
+
import https from "https";
|
|
647
|
+
import http from "http";
|
|
648
|
+
import { keccak256 } from "viem";
|
|
649
|
+
function collectFile(value, previous) {
|
|
650
|
+
return [...previous, value];
|
|
651
|
+
}
|
|
652
|
+
function mimeTypeForPath(filePath) {
|
|
653
|
+
switch (extname(filePath).toLowerCase()) {
|
|
654
|
+
case ".png":
|
|
655
|
+
return "image/png";
|
|
656
|
+
case ".jpg":
|
|
657
|
+
case ".jpeg":
|
|
658
|
+
return "image/jpeg";
|
|
659
|
+
case ".webp":
|
|
660
|
+
return "image/webp";
|
|
661
|
+
case ".gif":
|
|
662
|
+
return "image/gif";
|
|
663
|
+
case ".svg":
|
|
664
|
+
return "image/svg+xml";
|
|
665
|
+
case ".pdf":
|
|
666
|
+
return "application/pdf";
|
|
667
|
+
case ".mp4":
|
|
668
|
+
return "video/mp4";
|
|
669
|
+
case ".webm":
|
|
670
|
+
return "video/webm";
|
|
671
|
+
case ".mp3":
|
|
672
|
+
return "audio/mpeg";
|
|
673
|
+
case ".wav":
|
|
674
|
+
return "audio/wav";
|
|
675
|
+
case ".md":
|
|
676
|
+
return "text/markdown";
|
|
677
|
+
case ".txt":
|
|
678
|
+
return "text/plain";
|
|
679
|
+
case ".json":
|
|
680
|
+
return "application/json";
|
|
681
|
+
case ".zip":
|
|
682
|
+
return "application/zip";
|
|
683
|
+
default:
|
|
684
|
+
return "application/octet-stream";
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
function streamingPut(uploadUrl, data, mimeType, label) {
|
|
688
|
+
return new Promise((resolve, reject) => {
|
|
689
|
+
const url = new URL(uploadUrl);
|
|
690
|
+
const transport = url.protocol === "https:" ? https : http;
|
|
691
|
+
const req = transport.request(
|
|
692
|
+
url,
|
|
693
|
+
{
|
|
694
|
+
method: "PUT",
|
|
695
|
+
headers: {
|
|
696
|
+
"Content-Type": mimeType,
|
|
697
|
+
"Content-Length": String(data.length)
|
|
698
|
+
}
|
|
699
|
+
},
|
|
700
|
+
(res) => {
|
|
701
|
+
const chunks = [];
|
|
702
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
703
|
+
res.on("end", () => {
|
|
704
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
705
|
+
process.stderr.write("\n");
|
|
706
|
+
resolve();
|
|
707
|
+
} else {
|
|
708
|
+
const body = Buffer.concat(chunks).toString("utf8").slice(0, 500);
|
|
709
|
+
reject(
|
|
710
|
+
new Error(
|
|
711
|
+
`Upload failed (${res.statusCode ?? "unknown"}): ${body || "no response body"}`
|
|
712
|
+
)
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
);
|
|
718
|
+
req.on("error", reject);
|
|
719
|
+
let uploaded = 0;
|
|
720
|
+
const stream = Readable.from([data]);
|
|
721
|
+
stream.on("data", (chunk) => {
|
|
722
|
+
uploaded += chunk.length;
|
|
723
|
+
const pct = Math.round(uploaded / data.length * 100);
|
|
724
|
+
process.stderr.write(`\r ${label}: ${pct}%`);
|
|
725
|
+
});
|
|
726
|
+
stream.on("error", reject);
|
|
727
|
+
stream.pipe(req);
|
|
555
728
|
});
|
|
556
|
-
|
|
729
|
+
}
|
|
730
|
+
var submitCmd = new Command8("submit").description("Submit work for a task").argument("<taskId>", "Task ID (0x-prefixed hex)").option("--file <path>", "Path to a submission file (repeatable)", collectFile, []).addOption(
|
|
731
|
+
new Option("--role <role>", "Artifact role applied to all files").choices(["preview", "source", "final", "attachment"]).default("attachment")
|
|
732
|
+
).action(async (taskId, opts) => {
|
|
733
|
+
try {
|
|
734
|
+
if (!opts.file || opts.file.length === 0) {
|
|
735
|
+
printError("--file is required");
|
|
736
|
+
}
|
|
737
|
+
const keystore = await loadKeystore();
|
|
738
|
+
const signature = await signMessage(`taskmarket:submit:${taskId}`, keystore);
|
|
739
|
+
const artifactInputs = await Promise.all(
|
|
740
|
+
opts.file.map(async (filePath) => {
|
|
741
|
+
const mimeType = mimeTypeForPath(filePath);
|
|
742
|
+
const data = await fsPromises.readFile(filePath);
|
|
743
|
+
if (data.length === 0) {
|
|
744
|
+
printError(`File is empty: ${basename(filePath)}`);
|
|
745
|
+
}
|
|
746
|
+
const { uploadUrl, artifactKey } = await apiPost(
|
|
747
|
+
`/api/tasks/${taskId}/submissions/request-upload-url`,
|
|
748
|
+
{
|
|
749
|
+
taskId,
|
|
750
|
+
workerAddress: keystore.walletAddress,
|
|
751
|
+
signature,
|
|
752
|
+
fileName: basename(filePath),
|
|
753
|
+
mimeType,
|
|
754
|
+
role: opts.role,
|
|
755
|
+
sizeBytes: data.length
|
|
756
|
+
}
|
|
757
|
+
);
|
|
758
|
+
const sha256Hash = createHash("sha256").update(data).digest("hex");
|
|
759
|
+
const keccak256Hash = keccak256(new Uint8Array(data));
|
|
760
|
+
process.stderr.write(` Uploading ${basename(filePath)}...
|
|
761
|
+
`);
|
|
762
|
+
await streamingPut(uploadUrl, data, mimeType, basename(filePath));
|
|
763
|
+
return {
|
|
764
|
+
artifactKey,
|
|
765
|
+
fileName: basename(filePath),
|
|
766
|
+
mimeType,
|
|
767
|
+
role: opts.role,
|
|
768
|
+
sizeBytes: data.length,
|
|
769
|
+
sha256Hash,
|
|
770
|
+
keccak256Hash
|
|
771
|
+
};
|
|
772
|
+
})
|
|
773
|
+
);
|
|
774
|
+
const result = await apiPost(`/api/tasks/${taskId}/submissions/from-keys`, {
|
|
775
|
+
taskId,
|
|
776
|
+
workerAddress: keystore.walletAddress,
|
|
777
|
+
artifacts: artifactInputs,
|
|
778
|
+
signature
|
|
779
|
+
});
|
|
780
|
+
printResult({ submissionId: result.submissionId });
|
|
781
|
+
} finally {
|
|
782
|
+
submitCmd.setOptionValue("file", []);
|
|
783
|
+
}
|
|
557
784
|
});
|
|
558
785
|
|
|
559
786
|
// src/commands/task/accept.ts
|
|
560
787
|
import { Command as Command9 } from "commander";
|
|
561
|
-
var acceptCmd = new Command9("accept").description("Accept a submission (costs 0.001 USDC)").argument("<taskId>", "Task ID (0x-prefixed hex)").requiredOption("--worker <addr>", "Worker wallet address").
|
|
788
|
+
var acceptCmd = new Command9("accept").description("Accept a submission (costs 0.001 USDC)").argument("<taskId>", "Task ID (0x-prefixed hex)").requiredOption("--worker <addr>", "Worker wallet address").option(
|
|
789
|
+
"--deliverable <hash>",
|
|
790
|
+
"Deliverable hash to commit on-chain (32-byte hex). Backend will look it up from the submission if omitted."
|
|
791
|
+
).action(async (taskId, opts) => {
|
|
792
|
+
if (opts.deliverable && !/^0x[0-9a-fA-F]{64}$/.test(opts.deliverable)) {
|
|
793
|
+
throw new Error("--deliverable must be a 0x-prefixed 32-byte hex string (0x + 64 hex chars)");
|
|
794
|
+
}
|
|
562
795
|
await x402Post(`/api/tasks/${taskId}/accept`, {
|
|
563
796
|
taskId,
|
|
564
|
-
worker: opts.worker
|
|
797
|
+
worker: opts.worker,
|
|
798
|
+
...opts.deliverable ? { deliverable: opts.deliverable } : {}
|
|
565
799
|
});
|
|
566
800
|
printResult({ accepted: true });
|
|
567
801
|
});
|
|
568
802
|
|
|
569
|
-
// src/commands/task/
|
|
803
|
+
// src/commands/task/accept-submissions.ts
|
|
570
804
|
import { Command as Command10 } from "commander";
|
|
571
|
-
|
|
572
|
-
const
|
|
573
|
-
if (
|
|
574
|
-
|
|
805
|
+
function parseWinner(spec) {
|
|
806
|
+
const parts = spec.split(":");
|
|
807
|
+
if (parts.length < 2 || parts.length > 4) {
|
|
808
|
+
throw new Error(
|
|
809
|
+
`Invalid --winner value "${spec}". Expected <addr>:<share>[:<submissionId>][:<deliverable>]`
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
const [worker, shareStr, submissionId, deliverable] = parts;
|
|
813
|
+
if (!/^0x[0-9a-fA-F]{40}$/.test(worker)) {
|
|
814
|
+
throw new Error(`Invalid worker address in "${spec}"`);
|
|
815
|
+
}
|
|
816
|
+
const share = parseInt(shareStr, 10);
|
|
817
|
+
if (Number.isNaN(share) || share < 1 || share > 1e4) {
|
|
818
|
+
throw new Error(`Invalid share in "${spec}" \u2014 must be integer 1..10000 (basis points)`);
|
|
819
|
+
}
|
|
820
|
+
if (deliverable && !/^0x[0-9a-fA-F]{64}$/.test(deliverable)) {
|
|
821
|
+
throw new Error(`Invalid deliverable hash in "${spec}" \u2014 must be 0x + 64 hex chars`);
|
|
822
|
+
}
|
|
823
|
+
return {
|
|
824
|
+
worker,
|
|
825
|
+
share,
|
|
826
|
+
...submissionId ? { submissionId } : {},
|
|
827
|
+
...deliverable ? { deliverable } : {}
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
var acceptSubmissionsCmd = new Command10("accept-submissions").description(
|
|
831
|
+
"Accept N submissions for a Bounty/Benchmark task with explicit share basis points (costs 0.001 USDC).\nShares must sum to 10000. The backend resolves each winner's deliverable from the submission row\nif --winner omits the explicit hash.\n\nFor ranked payouts, pass winners in rank order \u2014 workers[0] is the primary winner.\n\nExamples:\n task accept-submissions 0x\u2026 --winner 0xAlice:5000 --winner 0xBob:3000 --winner 0xCarol:2000\n task accept-submissions 0x\u2026 --winner 0xAlice:5000:sub-uuid --winner 0xBob:5000:sub-uuid2"
|
|
832
|
+
).argument("<taskId>", "Task ID (0x-prefixed hex)").requiredOption(
|
|
833
|
+
"--winner <spec...>",
|
|
834
|
+
"Winner spec <addr>:<share>[:<submissionId>][:<deliverable>]. Pass multiple times."
|
|
835
|
+
).action(async (taskId, opts) => {
|
|
836
|
+
let winners;
|
|
837
|
+
try {
|
|
838
|
+
winners = opts.winner.map(parseWinner);
|
|
839
|
+
} catch (err) {
|
|
840
|
+
printError(err instanceof Error ? err.message : String(err));
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
const sum = winners.reduce((a, w) => a + w.share, 0);
|
|
844
|
+
if (sum !== 1e4) {
|
|
845
|
+
printError(`Winner shares must sum to 10000 basis points (got ${sum})`);
|
|
846
|
+
return;
|
|
575
847
|
}
|
|
576
|
-
const result = await x402Post(`/api/tasks/${taskId}/
|
|
848
|
+
const result = await x402Post(`/api/tasks/${taskId}/accept-submissions`, {
|
|
577
849
|
taskId,
|
|
578
|
-
|
|
579
|
-
rating,
|
|
580
|
-
...opts.feedback ? { feedbackText: opts.feedback } : {}
|
|
850
|
+
winners
|
|
581
851
|
});
|
|
582
|
-
printResult({
|
|
852
|
+
printResult({ accepted: result.success, winners: winners.length });
|
|
583
853
|
});
|
|
584
854
|
|
|
585
|
-
// src/commands/task/
|
|
855
|
+
// src/commands/task/rate.ts
|
|
586
856
|
import { Command as Command11 } from "commander";
|
|
587
|
-
var
|
|
857
|
+
var rateCmd = new Command11("rate").description("Rate a worker (costs 0.001 USDC)").argument("<taskId>", "Task ID (0x-prefixed hex)").requiredOption("--worker <addr>", "Worker wallet address").requiredOption("--rating <n>", "Rating 0-100").option("--feedback <text>", "Optional feedback text").option(
|
|
858
|
+
"--rater-agent-id <id>",
|
|
859
|
+
"ERC-8004 agent ID of the requester (overrides server-side lookup)"
|
|
860
|
+
).action(
|
|
861
|
+
async (taskId, opts) => {
|
|
862
|
+
const rating = parseInt(opts.rating, 10);
|
|
863
|
+
if (rating < 0 || rating > 100) {
|
|
864
|
+
printError("Rating must be between 0 and 100");
|
|
865
|
+
}
|
|
866
|
+
const result = await x402Post(`/api/tasks/${taskId}/rate`, {
|
|
867
|
+
taskId,
|
|
868
|
+
worker: opts.worker,
|
|
869
|
+
rating,
|
|
870
|
+
...opts.feedback ? { feedbackText: opts.feedback } : {},
|
|
871
|
+
...opts.raterAgentId ? { raterAgentId: parseInt(opts.raterAgentId, 10) } : {}
|
|
872
|
+
});
|
|
873
|
+
printResult({ feedbackId: result.feedbackId });
|
|
874
|
+
}
|
|
875
|
+
);
|
|
876
|
+
|
|
877
|
+
// src/commands/task/claim.ts
|
|
878
|
+
import { Command as Command12 } from "commander";
|
|
879
|
+
var claimCmd = new Command12("claim").description("Claim a task as a worker").argument("<taskId>", "Task ID (0x-prefixed hex)").action(async (taskId) => {
|
|
588
880
|
const keystore = await loadKeystore();
|
|
589
881
|
const message = `taskmarket:claim:${taskId}`;
|
|
590
882
|
const signature = await signMessage(message, keystore);
|
|
@@ -596,11 +888,12 @@ var claimCmd = new Command11("claim").description("Claim a task as a worker").ar
|
|
|
596
888
|
});
|
|
597
889
|
|
|
598
890
|
// src/commands/task/pitch.ts
|
|
599
|
-
import { Command as
|
|
600
|
-
var pitchCmd = new
|
|
891
|
+
import { Command as Command13 } from "commander";
|
|
892
|
+
var pitchCmd = new Command13("pitch").description("Submit a pitch for a task (costs 0.001 USDC, anchors hash on-chain)").argument("<taskId>", "Task ID (0x-prefixed hex)").requiredOption("--text <text>", "Pitch text").option("--duration <hours>", "Estimated duration in hours").action(async (taskId, opts) => {
|
|
601
893
|
const keystore = await loadKeystore();
|
|
602
894
|
const signature = await signMessage(`taskmarket:pitch:${taskId}`, keystore);
|
|
603
|
-
const result = await
|
|
895
|
+
const result = await x402Post(`/api/tasks/${taskId}/pitches`, {
|
|
896
|
+
taskId,
|
|
604
897
|
workerAddress: keystore.walletAddress,
|
|
605
898
|
pitchText: opts.text,
|
|
606
899
|
...opts.duration ? { estimatedDuration: parseInt(opts.duration, 10) } : {},
|
|
@@ -610,11 +903,11 @@ var pitchCmd = new Command12("pitch").description("Submit a pitch for a task").a
|
|
|
610
903
|
});
|
|
611
904
|
|
|
612
905
|
// src/commands/task/select-worker.ts
|
|
613
|
-
import { Command as
|
|
614
|
-
import { keccak256, toBytes } from "viem";
|
|
615
|
-
var selectWorkerCmd = new
|
|
906
|
+
import { Command as Command14 } from "commander";
|
|
907
|
+
import { keccak256 as keccak2562, toBytes } from "viem";
|
|
908
|
+
var selectWorkerCmd = new Command14("select-worker").description("Select a worker from pitches (requester only)").argument("<taskId>", "Task ID (0x-prefixed hex)").requiredOption("--pitch <pitchId>", "Pitch ID to select").requiredOption("--worker <address>", "Worker wallet address to assign").action(async (taskId, opts) => {
|
|
616
909
|
const keystore = await loadKeystore();
|
|
617
|
-
const hash =
|
|
910
|
+
const hash = keccak2562(toBytes(taskId + opts.pitch + opts.worker));
|
|
618
911
|
const signature = await signMessage(hash, keystore);
|
|
619
912
|
await apiPost(`/api/tasks/${taskId}/pitches/select`, {
|
|
620
913
|
taskId,
|
|
@@ -626,11 +919,12 @@ var selectWorkerCmd = new Command13("select-worker").description("Select a worke
|
|
|
626
919
|
});
|
|
627
920
|
|
|
628
921
|
// src/commands/task/proof.ts
|
|
629
|
-
import { Command as
|
|
630
|
-
var proofCmd = new
|
|
922
|
+
import { Command as Command15 } from "commander";
|
|
923
|
+
var proofCmd = new Command15("proof").description("Submit a benchmark proof (costs 0.001 USDC, anchors hash on-chain)").argument("<taskId>", "Task ID (0x-prefixed hex)").requiredOption("--data <data>", "Proof data").requiredOption("--type <type>", "Proof type").option("--metric <val>", "Metric value").action(async (taskId, opts) => {
|
|
631
924
|
const keystore = await loadKeystore();
|
|
632
925
|
const signature = await signMessage(`taskmarket:proof:${taskId}`, keystore);
|
|
633
|
-
const result = await
|
|
926
|
+
const result = await x402Post(`/api/tasks/${taskId}/proofs`, {
|
|
927
|
+
taskId,
|
|
634
928
|
workerAddress: keystore.walletAddress,
|
|
635
929
|
proofData: opts.data,
|
|
636
930
|
proofType: opts.type,
|
|
@@ -641,8 +935,8 @@ var proofCmd = new Command14("proof").description("Submit a proof for a task").a
|
|
|
641
935
|
});
|
|
642
936
|
|
|
643
937
|
// src/commands/task/bid.ts
|
|
644
|
-
import { Command as
|
|
645
|
-
var bidCmd = new
|
|
938
|
+
import { Command as Command16 } from "commander";
|
|
939
|
+
var bidCmd = new Command16("bid").description("Submit a bid on an auction task").argument("<taskId>", "Task ID (0x-prefixed hex)").requiredOption("--price <usdc>", "Bid price in USDC (e.g. 3 or 1.5)").action(async (taskId, opts) => {
|
|
646
940
|
const priceBaseUnits = String(Math.round(parseFloat(opts.price) * 1e6));
|
|
647
941
|
const result = await x402Post(`/api/tasks/${taskId}/bids`, {
|
|
648
942
|
taskId,
|
|
@@ -651,9 +945,32 @@ var bidCmd = new Command15("bid").description("Submit a bid on an auction task")
|
|
|
651
945
|
printResult({ bidId: result.bidId });
|
|
652
946
|
});
|
|
653
947
|
|
|
948
|
+
// src/commands/task/auction-accept.ts
|
|
949
|
+
import { Command as Command17 } from "commander";
|
|
950
|
+
var auctionAcceptCmd = new Command17("auction-accept").description("Accept current clock price on a dutch or reverse_dutch auction task").argument("<taskId>", "Task ID (0x-prefixed hex)").option(
|
|
951
|
+
"--min-price <usdc>",
|
|
952
|
+
"Reject if current clock price is below this value (price floor guard)"
|
|
953
|
+
).action(async (taskId, opts) => {
|
|
954
|
+
const body = { taskId };
|
|
955
|
+
if (opts.minPrice) {
|
|
956
|
+
const [intPart = "0", fracPart = ""] = opts.minPrice.trim().split(".");
|
|
957
|
+
if (!/^\d+$/.test(intPart) || fracPart && !/^\d+$/.test(fracPart)) {
|
|
958
|
+
throw new Error(`--min-price: invalid number "${opts.minPrice}"`);
|
|
959
|
+
}
|
|
960
|
+
const padded = fracPart.slice(0, 6).padEnd(6, "0");
|
|
961
|
+
body.minPrice = (BigInt(intPart) * 1000000n + BigInt(padded)).toString();
|
|
962
|
+
}
|
|
963
|
+
const result = await x402Post(`/api/tasks/${taskId}/bids/accept`, body);
|
|
964
|
+
printResult({
|
|
965
|
+
acceptedPrice: result.acceptedPrice,
|
|
966
|
+
acceptedPriceUsdc: (Number(result.acceptedPrice) / 1e6).toFixed(6),
|
|
967
|
+
workerAddress: result.workerAddress
|
|
968
|
+
});
|
|
969
|
+
});
|
|
970
|
+
|
|
654
971
|
// src/commands/task/submissions.ts
|
|
655
|
-
import { Command as
|
|
656
|
-
var submissionsCmd = new
|
|
972
|
+
import { Command as Command18 } from "commander";
|
|
973
|
+
var submissionsCmd = new Command18("submissions").description("List submissions for a task").argument("<taskId>", "Task ID (0x-prefixed hex)").action(async (taskId) => {
|
|
657
974
|
let subs;
|
|
658
975
|
try {
|
|
659
976
|
subs = await apiGet(`/api/tasks/${taskId}/submissions`);
|
|
@@ -665,8 +982,8 @@ var submissionsCmd = new Command16("submissions").description("List submissions
|
|
|
665
982
|
});
|
|
666
983
|
|
|
667
984
|
// src/commands/task/select-winner.ts
|
|
668
|
-
import { Command as
|
|
669
|
-
var selectWinnerCmd = new
|
|
985
|
+
import { Command as Command19 } from "commander";
|
|
986
|
+
var selectWinnerCmd = new Command19("select-winner").description("Select lowest bidder after auction deadline (requester only)").argument("<taskId>", "Task ID (0x-prefixed hex)").action(async (taskId) => {
|
|
670
987
|
let result;
|
|
671
988
|
try {
|
|
672
989
|
result = await apiPost(`/api/tasks/${taskId}/bids/select-winner`, {
|
|
@@ -680,56 +997,296 @@ var selectWinnerCmd = new Command17("select-winner").description("Select lowest
|
|
|
680
997
|
});
|
|
681
998
|
|
|
682
999
|
// src/commands/task/download.ts
|
|
683
|
-
import { Command as
|
|
1000
|
+
import { Command as Command20 } from "commander";
|
|
684
1001
|
import { writeFileSync } from "fs";
|
|
685
|
-
var downloadCmd = new
|
|
686
|
-
|
|
687
|
-
|
|
1002
|
+
var downloadCmd = new Command20("download").description("Download a submission file (requester or worker)").argument("<taskId>", "Task ID (0x-prefixed hex)").requiredOption("--submission <id>", "Submission ID (from `task submissions`)").option("--artifact <id>", "Artifact ID for multi-artifact submissions").option("--output <path>", "Save to file instead of printing to stdout").action(
|
|
1003
|
+
async (taskId, opts) => {
|
|
1004
|
+
const keystore = await loadKeystore();
|
|
1005
|
+
let presignedUrl;
|
|
1006
|
+
try {
|
|
1007
|
+
const body = {
|
|
1008
|
+
taskId,
|
|
1009
|
+
submissionId: opts.submission,
|
|
1010
|
+
deviceId: keystore.deviceId,
|
|
1011
|
+
apiToken: keystore.apiToken
|
|
1012
|
+
};
|
|
1013
|
+
if (opts.artifact) {
|
|
1014
|
+
body.artifactId = opts.artifact;
|
|
1015
|
+
}
|
|
1016
|
+
const result = await apiPost(
|
|
1017
|
+
`/api/tasks/${taskId}/submissions/${opts.submission}/preview`,
|
|
1018
|
+
body
|
|
1019
|
+
);
|
|
1020
|
+
presignedUrl = result.presignedUrl;
|
|
1021
|
+
} catch (err) {
|
|
1022
|
+
const msg = err instanceof Error ? err.message : "Failed to get download URL.";
|
|
1023
|
+
printError(msg);
|
|
1024
|
+
}
|
|
1025
|
+
const res = await fetch(presignedUrl);
|
|
1026
|
+
if (!res.ok) {
|
|
1027
|
+
printError(`Failed to download file: ${res.status}`);
|
|
1028
|
+
}
|
|
1029
|
+
const content = Buffer.from(await res.arrayBuffer());
|
|
1030
|
+
if (opts.output) {
|
|
1031
|
+
writeFileSync(opts.output, content);
|
|
1032
|
+
process.stdout.write(JSON.stringify({ ok: true, data: { savedTo: opts.output } }) + "\n");
|
|
1033
|
+
} else {
|
|
1034
|
+
process.stdout.write(content);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
);
|
|
1038
|
+
|
|
1039
|
+
// src/commands/task/cancel.ts
|
|
1040
|
+
import { Command as Command21 } from "commander";
|
|
1041
|
+
var cancelCmd = new Command21("cancel").description("Cancel an open task and refund the escrowed reward (costs 0.001 USDC)").argument("<taskId>", "Task ID (0x-prefixed hex)").action(async (taskId) => {
|
|
1042
|
+
const result = await x402Post(`/api/tasks/${taskId}/cancel`, { taskId });
|
|
1043
|
+
printResult(result);
|
|
1044
|
+
});
|
|
1045
|
+
|
|
1046
|
+
// src/commands/task/update.ts
|
|
1047
|
+
import { Command as Command22 } from "commander";
|
|
1048
|
+
function toBaseUnits(humanUsdc) {
|
|
1049
|
+
const [intPart = "0", fracPart = ""] = humanUsdc.trim().split(".");
|
|
1050
|
+
const padded = fracPart.slice(0, 6).padEnd(6, "0");
|
|
1051
|
+
return (BigInt(intPart) * 1000000n + BigInt(padded)).toString();
|
|
1052
|
+
}
|
|
1053
|
+
var updateCmd = new Command22("update").description("Update an open task (costs 0.001 USDC)").argument("<taskId>", "Task ID (0x-prefixed hex)").option("--reward <usdc>", 'New reward in USDC (human units, e.g. "50")').option("--extend-expiry <seconds>", "Extend expiry by this many seconds").option("--bid-deadline <iso>", "New bid deadline (ISO 8601)").option("--pitch-deadline <iso>", "New pitch deadline (ISO 8601)").option("--auction-floor-price <usdc>", "New auction floor price in USDC").option("--auction-start-price <usdc>", "New auction start price in USDC").option("--description <text>", "New description").option("--tags <csv>", "New tags (comma-separated)").option("--metric-description <text>", "New metric description").action(
|
|
1054
|
+
async (taskId, opts) => {
|
|
1055
|
+
const body = { taskId };
|
|
1056
|
+
if (opts.reward !== void 0) {
|
|
1057
|
+
body.reward = toBaseUnits(opts.reward);
|
|
1058
|
+
}
|
|
1059
|
+
if (opts.extendExpiry !== void 0) {
|
|
1060
|
+
const delta = parseInt(opts.extendExpiry, 10);
|
|
1061
|
+
if (!Number.isFinite(delta) || delta < 0) {
|
|
1062
|
+
printError(`--extend-expiry must be a non-negative integer, got: ${opts.extendExpiry}`);
|
|
1063
|
+
}
|
|
1064
|
+
const task = await apiGet(`/api/tasks/${taskId}`);
|
|
1065
|
+
if (!task) {
|
|
1066
|
+
printError(`Task not found: ${taskId}`);
|
|
1067
|
+
}
|
|
1068
|
+
const currentExpiry = Math.floor(new Date(task.expiryTime).getTime() / 1e3);
|
|
1069
|
+
body.expiryTime = currentExpiry + delta;
|
|
1070
|
+
}
|
|
1071
|
+
if (opts.bidDeadline !== void 0) {
|
|
1072
|
+
const ts = Math.floor(new Date(opts.bidDeadline).getTime() / 1e3);
|
|
1073
|
+
if (ts <= Math.floor(Date.now() / 1e3)) {
|
|
1074
|
+
printError("--bid-deadline must be in the future");
|
|
1075
|
+
} else {
|
|
1076
|
+
body.bidDeadline = ts;
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
if (opts.pitchDeadline !== void 0) {
|
|
1080
|
+
const ts = Math.floor(new Date(opts.pitchDeadline).getTime() / 1e3);
|
|
1081
|
+
if (ts <= Math.floor(Date.now() / 1e3)) {
|
|
1082
|
+
printError("--pitch-deadline must be in the future");
|
|
1083
|
+
} else {
|
|
1084
|
+
body.pitchDeadline = ts;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
if (opts.auctionFloorPrice !== void 0) {
|
|
1088
|
+
body.auctionFloorPrice = toBaseUnits(opts.auctionFloorPrice);
|
|
1089
|
+
}
|
|
1090
|
+
if (opts.auctionStartPrice !== void 0) {
|
|
1091
|
+
body.auctionStartPrice = toBaseUnits(opts.auctionStartPrice);
|
|
1092
|
+
}
|
|
1093
|
+
if (opts.description !== void 0) {
|
|
1094
|
+
body.description = opts.description;
|
|
1095
|
+
}
|
|
1096
|
+
if (opts.tags !== void 0) {
|
|
1097
|
+
body.tags = opts.tags.split(",").map((t) => t.trim()).filter(Boolean);
|
|
1098
|
+
}
|
|
1099
|
+
if (opts.metricDescription !== void 0) {
|
|
1100
|
+
body.metricDescription = opts.metricDescription;
|
|
1101
|
+
}
|
|
1102
|
+
const result = await x402Post(`/api/tasks/${taskId}/update`, body);
|
|
1103
|
+
printResult(result);
|
|
1104
|
+
}
|
|
1105
|
+
);
|
|
1106
|
+
|
|
1107
|
+
// src/commands/task/forfeit.ts
|
|
1108
|
+
import { Command as Command23 } from "commander";
|
|
1109
|
+
var forfeitCmd = new Command23("forfeit").description("Reclaim a claim-mode task whose worker's claim has expired (requester only)").argument("<taskId>", "Task ID (0x-prefixed hex)").action(async (taskId) => {
|
|
688
1110
|
try {
|
|
689
|
-
const
|
|
1111
|
+
const keystore = await loadKeystore();
|
|
1112
|
+
const message = `taskmarket:forfeit:${taskId}`;
|
|
1113
|
+
const signature = await signMessage(message, keystore);
|
|
1114
|
+
const result = await apiPost(`/api/tasks/${taskId}/forfeit`, {
|
|
690
1115
|
taskId,
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
apiToken: keystore.apiToken
|
|
1116
|
+
requesterAddress: keystore.walletAddress,
|
|
1117
|
+
signature
|
|
694
1118
|
});
|
|
695
|
-
|
|
1119
|
+
printResult(result);
|
|
696
1120
|
} catch (err) {
|
|
697
|
-
|
|
698
|
-
printError(msg);
|
|
1121
|
+
printError(err instanceof Error ? err.message : String(err));
|
|
699
1122
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
1123
|
+
});
|
|
1124
|
+
|
|
1125
|
+
// src/commands/task/evaluate.ts
|
|
1126
|
+
import { Command as Command24 } from "commander";
|
|
1127
|
+
var evaluateCmd = new Command24("evaluate").description("Submit an evaluation verdict for a task in Review state").argument("<taskId>", "Task ID (0x-prefixed hex)").requiredOption("--verdict <type>", "Verdict: approve, reject, or partial").option("--score <n>", "Score 0-1000 (default: 1000)", "1000").option("--confidence <n>", "Confidence 0-1000 (default: 1000)", "1000").option("--evidence-hash <hash>", "Evidence hash (32-byte hex)").option(
|
|
1128
|
+
"--award <worker:amount:rank>",
|
|
1129
|
+
"Award entry (repeatable): worker:amountUSDC:rank",
|
|
1130
|
+
collect,
|
|
1131
|
+
[]
|
|
1132
|
+
).action(
|
|
1133
|
+
async (taskId, opts) => {
|
|
1134
|
+
const validVerdicts = ["approve", "reject", "partial"];
|
|
1135
|
+
if (!validVerdicts.includes(opts.verdict)) {
|
|
1136
|
+
return void printError(`--verdict must be one of: ${validVerdicts.join(", ")}`);
|
|
1137
|
+
}
|
|
1138
|
+
const awards = [];
|
|
1139
|
+
for (const entry of opts.award) {
|
|
1140
|
+
const parts = entry.split(":");
|
|
1141
|
+
if (parts.length < 3 || !parts[0] || !parts[1] || !parts[2]) {
|
|
1142
|
+
return void printError(
|
|
1143
|
+
`Invalid award format '${entry}'. Expected worker:amountUSDC:rank`
|
|
1144
|
+
);
|
|
1145
|
+
}
|
|
1146
|
+
const [worker, amountUSDC, rankStr] = parts;
|
|
1147
|
+
if (!/^0x[0-9a-fA-F]{40}$/.test(worker)) {
|
|
1148
|
+
return void printError(
|
|
1149
|
+
`Invalid worker address in '${entry}': must be 0x-prefixed 40-char hex`
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
1152
|
+
const parsedAmount = Number(amountUSDC);
|
|
1153
|
+
if (!Number.isFinite(parsedAmount) || parsedAmount <= 0) {
|
|
1154
|
+
return void printError(`Invalid amount in '${entry}': must be a positive number`);
|
|
1155
|
+
}
|
|
1156
|
+
const microUnits = Math.round(parsedAmount * 1e6);
|
|
1157
|
+
if (!Number.isFinite(microUnits) || microUnits > Number.MAX_SAFE_INTEGER) {
|
|
1158
|
+
return void printError(`Amount in '${entry}' is too large to convert to micro-units`);
|
|
1159
|
+
}
|
|
1160
|
+
const parsedRank = Number(rankStr);
|
|
1161
|
+
if (!Number.isInteger(parsedRank) || parsedRank < 1) {
|
|
1162
|
+
return void printError(`Invalid rank in '${entry}': must be a positive integer`);
|
|
1163
|
+
}
|
|
1164
|
+
awards.push({ worker, amount: String(microUnits), rank: parsedRank });
|
|
1165
|
+
}
|
|
1166
|
+
const body = {
|
|
1167
|
+
taskId,
|
|
1168
|
+
verdict: opts.verdict,
|
|
1169
|
+
score: parseInt(opts.score, 10),
|
|
1170
|
+
confidence: parseInt(opts.confidence, 10),
|
|
1171
|
+
awards
|
|
1172
|
+
};
|
|
1173
|
+
if (opts.evidenceHash) {
|
|
1174
|
+
if (!/^0x[0-9a-fA-F]{64}$/.test(opts.evidenceHash)) {
|
|
1175
|
+
return void printError(
|
|
1176
|
+
"--evidence-hash must be a 0x-prefixed 32-byte hex string (0x + 64 hex chars)"
|
|
1177
|
+
);
|
|
1178
|
+
}
|
|
1179
|
+
body.evidenceHash = opts.evidenceHash;
|
|
1180
|
+
}
|
|
1181
|
+
const result = await x402Post(`/api/tasks/${taskId}/evaluate`, body);
|
|
1182
|
+
printResult({ txHash: result.txHash });
|
|
703
1183
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
1184
|
+
);
|
|
1185
|
+
function collect(val, prev) {
|
|
1186
|
+
return prev.concat([val]);
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
// src/commands/task/appeal.ts
|
|
1190
|
+
import { Command as Command25 } from "commander";
|
|
1191
|
+
var appealCmd = new Command25("appeal").description("Appeal an evaluator verdict while in Appealing state").argument("<taskId>", "Task ID (0x-prefixed hex)").action(async (taskId) => {
|
|
1192
|
+
const result = await x402Post(`/api/tasks/${taskId}/appeal`, { taskId });
|
|
1193
|
+
printResult({ txHash: result.txHash });
|
|
1194
|
+
});
|
|
1195
|
+
|
|
1196
|
+
// src/commands/task/evaluator-timeout.ts
|
|
1197
|
+
import { Command as Command26 } from "commander";
|
|
1198
|
+
var evaluatorTimeoutCmd = new Command26("evaluator-timeout").description("Trigger evaluator timeout after the evaluation window expires (requester only)").argument("<taskId>", "Task ID (0x-prefixed hex)").action(async (taskId) => {
|
|
1199
|
+
const result = await x402Post(`/api/tasks/${taskId}/evaluator-timeout`, { taskId });
|
|
1200
|
+
printResult({ txHash: result.txHash });
|
|
1201
|
+
});
|
|
1202
|
+
|
|
1203
|
+
// src/commands/task/finalize-verdict.ts
|
|
1204
|
+
import { Command as Command27 } from "commander";
|
|
1205
|
+
var finalizeVerdictCmd = new Command27("finalize-verdict").description("Finalize an evaluator verdict after the appeal window expires (permissionless)").argument("<taskId>", "Task ID (0x-prefixed hex)").action(async (taskId) => {
|
|
1206
|
+
const result = await x402Post(`/api/tasks/${taskId}/finalize-verdict`, { taskId });
|
|
1207
|
+
printResult({ txHash: result.txHash });
|
|
1208
|
+
});
|
|
1209
|
+
|
|
1210
|
+
// src/commands/task/resolve-dispute.ts
|
|
1211
|
+
import { Command as Command28 } from "commander";
|
|
1212
|
+
function parseAward(spec) {
|
|
1213
|
+
const parts = spec.split(":");
|
|
1214
|
+
if (parts.length !== 3) {
|
|
1215
|
+
throw new Error(`Invalid --award value "${spec}". Expected <addr>:<amount_usdc>:<rank>`);
|
|
1216
|
+
}
|
|
1217
|
+
const [worker, amountStr, rankStr] = parts;
|
|
1218
|
+
if (!/^0x[0-9a-fA-F]{40}$/.test(worker)) {
|
|
1219
|
+
throw new Error(`Invalid worker address in "${spec}"`);
|
|
1220
|
+
}
|
|
1221
|
+
const amount = parseFloat(amountStr);
|
|
1222
|
+
if (Number.isNaN(amount) || amount <= 0) {
|
|
1223
|
+
throw new Error(`Invalid amount in "${spec}" \u2014 must be a positive number`);
|
|
1224
|
+
}
|
|
1225
|
+
const rank = parseInt(rankStr, 10);
|
|
1226
|
+
if (!Number.isInteger(rank) || rank < 1) {
|
|
1227
|
+
throw new Error(`Invalid rank in "${spec}" \u2014 must be an integer >= 1`);
|
|
1228
|
+
}
|
|
1229
|
+
return {
|
|
1230
|
+
worker,
|
|
1231
|
+
amount: String(Math.round(amount * 1e6)),
|
|
1232
|
+
rank
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1235
|
+
var resolveDisputeCmd = new Command28("resolve-dispute").description(
|
|
1236
|
+
"Resolve a disputed task as the designated dispute resolver (X402 required).\n\nExamples:\n task resolve-dispute 0x\u2026 --verdict approve --award 0xAlice:5:1\n task resolve-dispute 0x\u2026 --verdict partial --award 0xAlice:3:1 --award 0xBob:2:2"
|
|
1237
|
+
).argument("<taskId>", "Task ID (0x-prefixed hex)").requiredOption("--verdict <type>", "Verdict type: approve or partial").requiredOption(
|
|
1238
|
+
"--award <spec...>",
|
|
1239
|
+
"Award spec <addr>:<amount_usdc>:<rank>. Pass multiple times."
|
|
1240
|
+
).action(async (taskId, opts) => {
|
|
1241
|
+
if (opts.verdict !== "approve" && opts.verdict !== "partial") {
|
|
1242
|
+
printError('--verdict must be "approve" or "partial"');
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
let awards;
|
|
1246
|
+
try {
|
|
1247
|
+
awards = opts.award.map(parseAward);
|
|
1248
|
+
} catch (err) {
|
|
1249
|
+
printError(err instanceof Error ? err.message : String(err));
|
|
1250
|
+
return;
|
|
710
1251
|
}
|
|
1252
|
+
const result = await x402Post(`/api/tasks/${taskId}/resolve-dispute`, {
|
|
1253
|
+
taskId,
|
|
1254
|
+
verdict: opts.verdict,
|
|
1255
|
+
awards
|
|
1256
|
+
});
|
|
1257
|
+
printResult({ txHash: result.txHash });
|
|
711
1258
|
});
|
|
712
1259
|
|
|
713
1260
|
// src/commands/task/index.ts
|
|
714
|
-
var taskCommand = new
|
|
1261
|
+
var taskCommand = new Command29("task").description("Manage tasks");
|
|
715
1262
|
taskCommand.addCommand(createCmd);
|
|
716
1263
|
taskCommand.addCommand(listCmd);
|
|
717
1264
|
taskCommand.addCommand(getCmd);
|
|
718
1265
|
taskCommand.addCommand(submitCmd);
|
|
719
1266
|
taskCommand.addCommand(acceptCmd);
|
|
1267
|
+
taskCommand.addCommand(acceptSubmissionsCmd);
|
|
720
1268
|
taskCommand.addCommand(rateCmd);
|
|
721
1269
|
taskCommand.addCommand(claimCmd);
|
|
722
1270
|
taskCommand.addCommand(pitchCmd);
|
|
723
1271
|
taskCommand.addCommand(selectWorkerCmd);
|
|
724
1272
|
taskCommand.addCommand(proofCmd);
|
|
725
1273
|
taskCommand.addCommand(bidCmd);
|
|
1274
|
+
taskCommand.addCommand(auctionAcceptCmd);
|
|
726
1275
|
taskCommand.addCommand(submissionsCmd);
|
|
727
1276
|
taskCommand.addCommand(selectWinnerCmd);
|
|
728
1277
|
taskCommand.addCommand(downloadCmd);
|
|
1278
|
+
taskCommand.addCommand(cancelCmd);
|
|
1279
|
+
taskCommand.addCommand(updateCmd);
|
|
1280
|
+
taskCommand.addCommand(forfeitCmd);
|
|
1281
|
+
taskCommand.addCommand(evaluateCmd);
|
|
1282
|
+
taskCommand.addCommand(appealCmd);
|
|
1283
|
+
taskCommand.addCommand(evaluatorTimeoutCmd);
|
|
1284
|
+
taskCommand.addCommand(finalizeVerdictCmd);
|
|
1285
|
+
taskCommand.addCommand(resolveDisputeCmd);
|
|
729
1286
|
|
|
730
1287
|
// src/commands/agents.ts
|
|
731
|
-
import { Command as
|
|
732
|
-
var agentsCommand = new
|
|
1288
|
+
import { Command as Command30 } from "commander";
|
|
1289
|
+
var agentsCommand = new Command30("agents").description("Browse the agent directory").option("--sort <order>", "Sort order: reputation or tasks", "reputation").option("--skill <tag>", "Filter by skill tag").option("--search <query>", "Search by agentId or wallet address").option("--limit <n>", "Maximum results to return", "20").action(async (opts) => {
|
|
733
1290
|
const params = new URLSearchParams();
|
|
734
1291
|
if (opts.sort) params.set("sort", opts.sort);
|
|
735
1292
|
if (opts.skill) params.set("skill", opts.skill);
|
|
@@ -740,8 +1297,8 @@ var agentsCommand = new Command20("agents").description("Browse the agent direct
|
|
|
740
1297
|
});
|
|
741
1298
|
|
|
742
1299
|
// src/commands/inbox.ts
|
|
743
|
-
import { Command as
|
|
744
|
-
var inboxCommand = new
|
|
1300
|
+
import { Command as Command31 } from "commander";
|
|
1301
|
+
var inboxCommand = new Command31("inbox").description("Show tasks you created and tasks you are working on").action(async () => {
|
|
745
1302
|
let address;
|
|
746
1303
|
try {
|
|
747
1304
|
address = await getWalletAddress();
|
|
@@ -749,15 +1306,26 @@ var inboxCommand = new Command21("inbox").description("Show tasks you created an
|
|
|
749
1306
|
const msg = err instanceof Error ? err.message : "No keystore found. Run `taskmarket init` first.";
|
|
750
1307
|
printError(msg);
|
|
751
1308
|
}
|
|
752
|
-
const
|
|
1309
|
+
const taskResult = await apiGet(
|
|
753
1310
|
`/api/agents/inbox?address=${encodeURIComponent(address)}`
|
|
754
1311
|
);
|
|
755
|
-
|
|
1312
|
+
let pendingBids = [];
|
|
1313
|
+
try {
|
|
1314
|
+
const keystore = await loadKeystore();
|
|
1315
|
+
if (keystore.deviceId && keystore.apiToken) {
|
|
1316
|
+
const params = new URLSearchParams({ deviceId: keystore.deviceId });
|
|
1317
|
+
pendingBids = await apiGet(`/api/bids/my?${params.toString()}`, {
|
|
1318
|
+
headers: { "x-taskmarket-api-token": keystore.apiToken }
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
} catch {
|
|
1322
|
+
}
|
|
1323
|
+
printResult({ ...taskResult, pendingBids });
|
|
756
1324
|
});
|
|
757
1325
|
|
|
758
1326
|
// src/commands/deposit.ts
|
|
759
|
-
import { Command as
|
|
760
|
-
var depositCommand = new
|
|
1327
|
+
import { Command as Command32 } from "commander";
|
|
1328
|
+
var depositCommand = new Command32("deposit").description("Show wallet address and network info for funding").action(async () => {
|
|
761
1329
|
let address;
|
|
762
1330
|
try {
|
|
763
1331
|
address = await getWalletAddress();
|
|
@@ -784,11 +1352,11 @@ var depositCommand = new Command22("deposit").description("Show wallet address a
|
|
|
784
1352
|
});
|
|
785
1353
|
|
|
786
1354
|
// src/commands/wallet/index.ts
|
|
787
|
-
import { Command as
|
|
1355
|
+
import { Command as Command37 } from "commander";
|
|
788
1356
|
|
|
789
1357
|
// src/commands/wallet/balance.ts
|
|
790
|
-
import { Command as
|
|
791
|
-
var walletBalanceCommand = new
|
|
1358
|
+
import { Command as Command33 } from "commander";
|
|
1359
|
+
var walletBalanceCommand = new Command33("balance").description("Show USDC balance").option("--address <addr>", "Address to check (defaults to own wallet)").action(async (opts) => {
|
|
792
1360
|
let address = opts.address;
|
|
793
1361
|
if (!address) {
|
|
794
1362
|
const keystore = await loadKeystore();
|
|
@@ -799,7 +1367,7 @@ var walletBalanceCommand = new Command23("balance").description("Show USDC balan
|
|
|
799
1367
|
});
|
|
800
1368
|
|
|
801
1369
|
// src/commands/wallet/import.ts
|
|
802
|
-
import { Command as
|
|
1370
|
+
import { Command as Command34 } from "commander";
|
|
803
1371
|
import { createInterface } from "readline";
|
|
804
1372
|
import { privateKeyToAccount as privateKeyToAccount3 } from "viem/accounts";
|
|
805
1373
|
function normalizePrivateKey(raw) {
|
|
@@ -834,7 +1402,7 @@ function promptHiddenInput(prompt) {
|
|
|
834
1402
|
});
|
|
835
1403
|
});
|
|
836
1404
|
}
|
|
837
|
-
var walletImportCommand = new
|
|
1405
|
+
var walletImportCommand = new Command34("import").description("Import an existing private key as the agent wallet").option("--key <privateKey>", "Private key to import (64 hex chars, with or without 0x prefix)").action(async (opts) => {
|
|
838
1406
|
if (await keystoreExists()) {
|
|
839
1407
|
const keystore = await loadKeystore();
|
|
840
1408
|
printResult({ address: keystore.walletAddress, agentId: keystore.agentId });
|
|
@@ -873,7 +1441,14 @@ var walletImportCommand = new Command24("import").description("Import an existin
|
|
|
873
1441
|
} = await res.json();
|
|
874
1442
|
const encryptedKey = encryptPrivateKey(deviceEncryptionKey, privateKey);
|
|
875
1443
|
let agentId = initialAgentId;
|
|
876
|
-
await saveKeystore({
|
|
1444
|
+
await saveKeystore({
|
|
1445
|
+
encryptedKey,
|
|
1446
|
+
walletAddress: address,
|
|
1447
|
+
deviceId,
|
|
1448
|
+
apiToken,
|
|
1449
|
+
agentId,
|
|
1450
|
+
keyServerUrl: API_URL
|
|
1451
|
+
});
|
|
877
1452
|
if (!agentId) {
|
|
878
1453
|
agentId = await pollAgentId(address);
|
|
879
1454
|
if (agentId) {
|
|
@@ -892,11 +1467,11 @@ var walletImportCommand = new Command24("import").description("Import an existin
|
|
|
892
1467
|
});
|
|
893
1468
|
|
|
894
1469
|
// src/commands/wallet/set-withdrawal-address.ts
|
|
895
|
-
import { Command as
|
|
1470
|
+
import { Command as Command35 } from "commander";
|
|
896
1471
|
function isValidAddress(addr) {
|
|
897
1472
|
return /^0x[a-fA-F0-9]{40}$/.test(addr);
|
|
898
1473
|
}
|
|
899
|
-
var setWithdrawalAddressCommand = new
|
|
1474
|
+
var setWithdrawalAddressCommand = new Command35("set-withdrawal-address").description("Set a withdrawal address for USDC withdrawals (one-time, free)").argument("<address>", "Ethereum address to receive withdrawals").action(async (address) => {
|
|
900
1475
|
if (!isValidAddress(address)) {
|
|
901
1476
|
printError("Invalid Ethereum address: must be 0x followed by 40 hex characters");
|
|
902
1477
|
}
|
|
@@ -918,8 +1493,8 @@ var setWithdrawalAddressCommand = new Command25("set-withdrawal-address").descri
|
|
|
918
1493
|
});
|
|
919
1494
|
|
|
920
1495
|
// src/commands/wallet/publish-key.ts
|
|
921
|
-
import { Command as
|
|
922
|
-
var publishKeyCommand = new
|
|
1496
|
+
import { Command as Command36 } from "commander";
|
|
1497
|
+
var publishKeyCommand = new Command36("publish-key").description("Publish your secp256k1 public key so others can encrypt files for you").action(async () => {
|
|
923
1498
|
let keystore;
|
|
924
1499
|
try {
|
|
925
1500
|
keystore = await loadKeystore();
|
|
@@ -938,14 +1513,14 @@ var publishKeyCommand = new Command26("publish-key").description("Publish your s
|
|
|
938
1513
|
});
|
|
939
1514
|
|
|
940
1515
|
// src/commands/wallet/index.ts
|
|
941
|
-
var walletCommand = new
|
|
1516
|
+
var walletCommand = new Command37("wallet").description("Wallet management commands");
|
|
942
1517
|
walletCommand.addCommand(walletBalanceCommand);
|
|
943
1518
|
walletCommand.addCommand(walletImportCommand);
|
|
944
1519
|
walletCommand.addCommand(setWithdrawalAddressCommand);
|
|
945
1520
|
walletCommand.addCommand(publishKeyCommand);
|
|
946
1521
|
|
|
947
1522
|
// src/commands/withdraw.ts
|
|
948
|
-
import { Command as
|
|
1523
|
+
import { Command as Command38 } from "commander";
|
|
949
1524
|
import { toHex as toHex2 } from "viem";
|
|
950
1525
|
var USDC_TYPES = {
|
|
951
1526
|
TransferWithAuthorization: [
|
|
@@ -957,7 +1532,7 @@ var USDC_TYPES = {
|
|
|
957
1532
|
{ name: "nonce", type: "bytes32" }
|
|
958
1533
|
]
|
|
959
1534
|
};
|
|
960
|
-
var withdrawCommand = new
|
|
1535
|
+
var withdrawCommand = new Command38("withdraw").description("Withdraw USDC to the registered withdrawal address").argument("<amount>", "Amount in USDC (e.g. 5 for 5 USDC)").action(async (amount) => {
|
|
961
1536
|
const parsed = parseFloat(amount);
|
|
962
1537
|
if (isNaN(parsed) || parsed <= 0) {
|
|
963
1538
|
printError("Invalid amount: must be a positive number (e.g. 5 for 5 USDC)");
|
|
@@ -1007,12 +1582,12 @@ var withdrawCommand = new Command28("withdraw").description("Withdraw USDC to th
|
|
|
1007
1582
|
});
|
|
1008
1583
|
|
|
1009
1584
|
// src/commands/encrypt.ts
|
|
1010
|
-
import { Command as
|
|
1011
|
-
import { promises as
|
|
1012
|
-
var encryptCommand = new
|
|
1585
|
+
import { Command as Command39 } from "commander";
|
|
1586
|
+
import { promises as fs2 } from "fs";
|
|
1587
|
+
var encryptCommand = new Command39("encrypt").description("Encrypt a file with ECIES using wallet keys").argument("<file>", "Path to the file to encrypt").option("--recipient <address>", "Recipient wallet address (default: self)").option("--output <path>", "Output path (default: <file>.enc)").action(async (file, opts) => {
|
|
1013
1588
|
let plaintext;
|
|
1014
1589
|
try {
|
|
1015
|
-
plaintext = await
|
|
1590
|
+
plaintext = await fs2.readFile(file);
|
|
1016
1591
|
} catch {
|
|
1017
1592
|
printError(`Cannot read file: ${file}`);
|
|
1018
1593
|
}
|
|
@@ -1049,7 +1624,7 @@ var encryptCommand = new Command29("encrypt").description("Encrypt a file with E
|
|
|
1049
1624
|
}
|
|
1050
1625
|
const encrypted = encryptForRecipient(plaintext, recipientPubKey);
|
|
1051
1626
|
const outputPath = opts.output ?? `${file}.enc`;
|
|
1052
|
-
await
|
|
1627
|
+
await fs2.writeFile(outputPath, encrypted);
|
|
1053
1628
|
printResult({
|
|
1054
1629
|
output: outputPath,
|
|
1055
1630
|
bytes: encrypted.length,
|
|
@@ -1058,12 +1633,12 @@ var encryptCommand = new Command29("encrypt").description("Encrypt a file with E
|
|
|
1058
1633
|
});
|
|
1059
1634
|
|
|
1060
1635
|
// src/commands/decrypt.ts
|
|
1061
|
-
import { Command as
|
|
1062
|
-
import { promises as
|
|
1063
|
-
var decryptCommand = new
|
|
1636
|
+
import { Command as Command40 } from "commander";
|
|
1637
|
+
import { promises as fs3 } from "fs";
|
|
1638
|
+
var decryptCommand = new Command40("decrypt").description("Decrypt a file using your wallet key").argument("<file>", "Path to the encrypted file").option("--output <path>", "Output path (default: strips .enc, otherwise appends .dec)").action(async (file, opts) => {
|
|
1064
1639
|
let ciphertext;
|
|
1065
1640
|
try {
|
|
1066
|
-
ciphertext = await
|
|
1641
|
+
ciphertext = await fs3.readFile(file);
|
|
1067
1642
|
} catch {
|
|
1068
1643
|
printError(`Cannot read file: ${file}`);
|
|
1069
1644
|
}
|
|
@@ -1090,7 +1665,7 @@ var decryptCommand = new Command30("decrypt").description("Decrypt a file using
|
|
|
1090
1665
|
} else {
|
|
1091
1666
|
outputPath = `${file}.dec`;
|
|
1092
1667
|
}
|
|
1093
|
-
await
|
|
1668
|
+
await fs3.writeFile(outputPath, plaintext);
|
|
1094
1669
|
printResult({
|
|
1095
1670
|
output: outputPath,
|
|
1096
1671
|
bytes: plaintext.length
|
|
@@ -1098,7 +1673,7 @@ var decryptCommand = new Command30("decrypt").description("Decrypt a file using
|
|
|
1098
1673
|
});
|
|
1099
1674
|
|
|
1100
1675
|
// src/commands/xmtp.ts
|
|
1101
|
-
import { Command as
|
|
1676
|
+
import { Command as Command41 } from "commander";
|
|
1102
1677
|
|
|
1103
1678
|
// src/lib/xmtp-client.ts
|
|
1104
1679
|
import os2 from "os";
|
|
@@ -5157,11 +5732,14 @@ var TaskStatus = external_exports.enum([
|
|
|
5157
5732
|
"claimed",
|
|
5158
5733
|
"worker_selected",
|
|
5159
5734
|
"pending_approval",
|
|
5160
|
-
"
|
|
5735
|
+
"review",
|
|
5736
|
+
"appealing",
|
|
5737
|
+
"disputed",
|
|
5161
5738
|
"completed",
|
|
5162
5739
|
"expired",
|
|
5163
|
-
"
|
|
5740
|
+
"cancelled"
|
|
5164
5741
|
]);
|
|
5742
|
+
var AuctionType = external_exports.enum(["dutch", "english", "reverse_dutch", "reverse_english"]);
|
|
5165
5743
|
var TaskCreateSchema = external_exports.object({
|
|
5166
5744
|
description: external_exports.string().min(1, "Description is required").max(2e3, "Description is too long"),
|
|
5167
5745
|
reward: external_exports.string().min(1, "Reward is required"),
|
|
@@ -5174,7 +5752,17 @@ var TaskCreateSchema = external_exports.object({
|
|
|
5174
5752
|
bidDeadline: external_exports.number().positive().optional(),
|
|
5175
5753
|
maxPrice: external_exports.string().optional(),
|
|
5176
5754
|
metricDescription: external_exports.string().max(500).optional(),
|
|
5177
|
-
metricTarget: external_exports.string().max(200).optional()
|
|
5755
|
+
metricTarget: external_exports.string().max(200).optional(),
|
|
5756
|
+
auctionType: AuctionType.optional(),
|
|
5757
|
+
auctionStartPrice: external_exports.string().optional(),
|
|
5758
|
+
auctionFloorPrice: external_exports.string().optional(),
|
|
5759
|
+
hookContract: external_exports.string().optional(),
|
|
5760
|
+
hookData: external_exports.string().regex(/^0x(?:[0-9a-fA-F]{2})*$/, "hookData must be hex-encoded bytes (0x followed by pairs of hex digits)").optional(),
|
|
5761
|
+
evaluator: external_exports.string().optional(),
|
|
5762
|
+
evaluatorFeeBps: external_exports.number().min(0).max(1e4).optional(),
|
|
5763
|
+
evaluationWindowHours: external_exports.number().positive().optional(),
|
|
5764
|
+
appealWindowHours: external_exports.number().positive().optional(),
|
|
5765
|
+
disputeResolver: external_exports.string().optional()
|
|
5178
5766
|
});
|
|
5179
5767
|
var TaskResponseSchema = external_exports.object({
|
|
5180
5768
|
id: external_exports.string(),
|
|
@@ -5203,23 +5791,38 @@ var TaskResponseSchema = external_exports.object({
|
|
|
5203
5791
|
submissionCount: external_exports.number().optional().default(0),
|
|
5204
5792
|
pitchCount: external_exports.number().optional().default(0),
|
|
5205
5793
|
requesterAgentId: external_exports.string().nullable().optional(),
|
|
5206
|
-
|
|
5794
|
+
requesterActorType: external_exports.enum(["agent", "human"]).optional(),
|
|
5795
|
+
workerAgentId: external_exports.string().nullable().optional(),
|
|
5796
|
+
workerActorType: external_exports.enum(["agent", "human"]).optional(),
|
|
5797
|
+
auctionType: AuctionType.nullable().optional(),
|
|
5798
|
+
auctionStartPrice: external_exports.string().nullable().optional(),
|
|
5799
|
+
auctionFloorPrice: external_exports.string().nullable().optional(),
|
|
5800
|
+
currentAuctionPrice: external_exports.string().nullable().optional(),
|
|
5801
|
+
auctionBidCount: external_exports.number().nullable().optional(),
|
|
5802
|
+
auctionPriceReachesFloorAt: external_exports.string().nullable().optional(),
|
|
5803
|
+
auctionPriceReachesMaxAt: external_exports.string().nullable().optional(),
|
|
5804
|
+
currentLowestBid: external_exports.string().nullable().optional(),
|
|
5805
|
+
hookContract: external_exports.string().nullable().optional(),
|
|
5806
|
+
evaluator: external_exports.string().nullable().optional(),
|
|
5807
|
+
evaluatorStake: external_exports.string().nullable().optional(),
|
|
5808
|
+
evaluatorFeeBps: external_exports.number().nullable().optional(),
|
|
5809
|
+
evaluationWindow: external_exports.number().nullable().optional(),
|
|
5810
|
+
appealWindow: external_exports.number().nullable().optional(),
|
|
5811
|
+
disputeResolver: external_exports.string().nullable().optional(),
|
|
5812
|
+
appealDeadline: external_exports.string().nullable().optional(),
|
|
5813
|
+
evaluatorDeadline: external_exports.string().nullable().optional(),
|
|
5814
|
+
verdictType: external_exports.enum(["APPROVE", "REJECT", "PARTIAL"]).nullable().optional(),
|
|
5815
|
+
verdictScore: external_exports.number().nullable().optional(),
|
|
5816
|
+
verdictConfidence: external_exports.number().nullable().optional(),
|
|
5817
|
+
verdictEvidenceHash: external_exports.string().nullable().optional()
|
|
5207
5818
|
});
|
|
5208
5819
|
var TaskListInputSchema = external_exports.object({
|
|
5209
5820
|
limit: external_exports.number().min(1).max(100).optional().default(20),
|
|
5210
5821
|
cursor: external_exports.string().optional(),
|
|
5211
|
-
status: external_exports.
|
|
5212
|
-
"ALL",
|
|
5213
|
-
"open",
|
|
5214
|
-
"claimed",
|
|
5215
|
-
"worker_selected",
|
|
5216
|
-
"pending_approval",
|
|
5217
|
-
"accepted",
|
|
5218
|
-
"completed",
|
|
5219
|
-
"expired",
|
|
5220
|
-
"disputed"
|
|
5221
|
-
]).optional().default("ALL"),
|
|
5822
|
+
status: external_exports.union([TaskStatus, external_exports.literal("ALL")]).optional().default("ALL"),
|
|
5222
5823
|
mode: external_exports.enum(["ALL", "bounty", "claim", "pitch", "benchmark", "auction"]).optional().default("ALL"),
|
|
5824
|
+
auctionType: AuctionType.optional(),
|
|
5825
|
+
requesterActorType: external_exports.enum(["agent", "human"]).optional(),
|
|
5223
5826
|
tags: external_exports.array(external_exports.string()).optional(),
|
|
5224
5827
|
minReward: external_exports.string().optional(),
|
|
5225
5828
|
maxReward: external_exports.string().optional(),
|
|
@@ -5237,20 +5840,88 @@ var TaskInboxResponseSchema = external_exports.object({
|
|
|
5237
5840
|
asRequester: external_exports.array(TaskResponseSchema),
|
|
5238
5841
|
asWorker: external_exports.array(TaskResponseSchema)
|
|
5239
5842
|
});
|
|
5843
|
+
var PendingActionName = external_exports.enum([
|
|
5844
|
+
"accept",
|
|
5845
|
+
"appeal",
|
|
5846
|
+
"auction_accept",
|
|
5847
|
+
"bid",
|
|
5848
|
+
"cancel",
|
|
5849
|
+
"claim",
|
|
5850
|
+
"evaluate",
|
|
5851
|
+
"evaluator_timeout",
|
|
5852
|
+
"finalize_verdict",
|
|
5853
|
+
"forfeit",
|
|
5854
|
+
"pitch",
|
|
5855
|
+
"rate",
|
|
5856
|
+
"resolve_dispute",
|
|
5857
|
+
"select_winner",
|
|
5858
|
+
"select_worker",
|
|
5859
|
+
"submit",
|
|
5860
|
+
"submit_proof",
|
|
5861
|
+
"update"
|
|
5862
|
+
]);
|
|
5240
5863
|
var PendingActionSchema = external_exports.object({
|
|
5241
|
-
role: external_exports.enum(["requester", "worker"]),
|
|
5242
|
-
action:
|
|
5864
|
+
role: external_exports.enum(["requester", "worker", "evaluator", "dispute_resolver", "anyone"]),
|
|
5865
|
+
action: PendingActionName,
|
|
5243
5866
|
command: external_exports.string()
|
|
5244
5867
|
});
|
|
5245
5868
|
var TaskDetailResponseSchema = TaskResponseSchema.extend({
|
|
5246
5869
|
pendingActions: PendingActionSchema.array()
|
|
5247
5870
|
});
|
|
5871
|
+
var CancelTaskInputSchema = external_exports.object({
|
|
5872
|
+
taskId: external_exports.string()
|
|
5873
|
+
});
|
|
5874
|
+
var UpdateTaskInputSchema = external_exports.object({
|
|
5875
|
+
taskId: external_exports.string(),
|
|
5876
|
+
reward: external_exports.string().optional(),
|
|
5877
|
+
expiryTime: external_exports.number().optional(),
|
|
5878
|
+
bidDeadline: external_exports.number().optional(),
|
|
5879
|
+
pitchDeadline: external_exports.number().optional(),
|
|
5880
|
+
auctionFloorPrice: external_exports.string().optional(),
|
|
5881
|
+
auctionStartPrice: external_exports.string().optional(),
|
|
5882
|
+
description: external_exports.string().max(2e3, "Description is too long").optional(),
|
|
5883
|
+
tags: external_exports.array(external_exports.string()).max(10, "Maximum 10 tags allowed").optional(),
|
|
5884
|
+
metricDescription: external_exports.string().max(500).optional()
|
|
5885
|
+
});
|
|
5248
5886
|
|
|
5249
5887
|
// ../../packages/shared/dist/schemas/submission.schemas.js
|
|
5888
|
+
var ArtifactRole = external_exports.enum(["preview", "source", "final", "attachment"]);
|
|
5889
|
+
var ArtifactMediaKind = external_exports.enum([
|
|
5890
|
+
"image",
|
|
5891
|
+
"video",
|
|
5892
|
+
"audio",
|
|
5893
|
+
"pdf",
|
|
5894
|
+
"text",
|
|
5895
|
+
"archive",
|
|
5896
|
+
"unknown"
|
|
5897
|
+
]);
|
|
5898
|
+
var ArtifactCreateSchema = external_exports.object({
|
|
5899
|
+
fileName: external_exports.string().min(1, "File name is required").max(255, "File name is too long"),
|
|
5900
|
+
mimeType: external_exports.string().min(1, "MIME type is required").max(120, "MIME type is too long"),
|
|
5901
|
+
role: ArtifactRole.optional().default("attachment"),
|
|
5902
|
+
file: external_exports.string().min(1, "File is required")
|
|
5903
|
+
});
|
|
5904
|
+
var ArtifactResponseSchema = external_exports.object({
|
|
5905
|
+
id: external_exports.string(),
|
|
5906
|
+
taskId: external_exports.string(),
|
|
5907
|
+
submissionId: external_exports.string(),
|
|
5908
|
+
workerAddress: external_exports.string(),
|
|
5909
|
+
workerAgentId: external_exports.string().nullable(),
|
|
5910
|
+
role: ArtifactRole,
|
|
5911
|
+
fileName: external_exports.string(),
|
|
5912
|
+
mimeType: external_exports.string(),
|
|
5913
|
+
mediaKind: ArtifactMediaKind,
|
|
5914
|
+
storageUri: external_exports.string(),
|
|
5915
|
+
sizeBytes: external_exports.number(),
|
|
5916
|
+
sha256Hash: external_exports.string(),
|
|
5917
|
+
keccak256Hash: external_exports.string(),
|
|
5918
|
+
displayOrder: external_exports.number(),
|
|
5919
|
+
textPreview: external_exports.string().optional()
|
|
5920
|
+
});
|
|
5250
5921
|
var SubmissionCreateSchema = external_exports.object({
|
|
5251
5922
|
taskId: external_exports.string(),
|
|
5252
5923
|
workerAddress: external_exports.string(),
|
|
5253
|
-
|
|
5924
|
+
artifacts: external_exports.array(ArtifactCreateSchema).min(1).max(20),
|
|
5254
5925
|
signature: external_exports.string()
|
|
5255
5926
|
});
|
|
5256
5927
|
var SubmissionResponseSchema = external_exports.object({
|
|
@@ -5261,6 +5932,9 @@ var SubmissionResponseSchema = external_exports.object({
|
|
|
5261
5932
|
signature: external_exports.string(),
|
|
5262
5933
|
submittedAt: external_exports.string(),
|
|
5263
5934
|
workerAgentId: external_exports.string().nullable().optional(),
|
|
5935
|
+
deliverableHash: external_exports.string().nullable().optional(),
|
|
5936
|
+
submitTxHash: external_exports.string().nullable().optional(),
|
|
5937
|
+
artifacts: external_exports.array(ArtifactResponseSchema).optional().default([]),
|
|
5264
5938
|
workerStats: external_exports.object({
|
|
5265
5939
|
completedTasks: external_exports.number(),
|
|
5266
5940
|
ratedTasks: external_exports.number(),
|
|
@@ -5269,18 +5943,51 @@ var SubmissionResponseSchema = external_exports.object({
|
|
|
5269
5943
|
}).nullable().optional()
|
|
5270
5944
|
});
|
|
5271
5945
|
var DownloadRequestSchema = external_exports.object({
|
|
5272
|
-
acceptanceTxHash: external_exports.string()
|
|
5946
|
+
acceptanceTxHash: external_exports.string(),
|
|
5947
|
+
artifactId: external_exports.string().optional()
|
|
5273
5948
|
});
|
|
5274
5949
|
var DownloadResponseSchema = external_exports.object({
|
|
5275
5950
|
fileUrl: external_exports.string(),
|
|
5276
5951
|
keyBundle: external_exports.string().nullable().optional(),
|
|
5277
5952
|
expiresAt: external_exports.string()
|
|
5278
5953
|
});
|
|
5954
|
+
var MAX_ARTIFACT_BYTES = 500 * 1024 * 1024;
|
|
5955
|
+
var RequestUploadUrlInputSchema = external_exports.object({
|
|
5956
|
+
taskId: external_exports.string(),
|
|
5957
|
+
workerAddress: external_exports.string(),
|
|
5958
|
+
signature: external_exports.string(),
|
|
5959
|
+
fileName: external_exports.string().min(1, "File name is required").max(255, "File name is too long"),
|
|
5960
|
+
mimeType: external_exports.string().min(1, "MIME type is required").max(120, "MIME type is too long"),
|
|
5961
|
+
role: ArtifactRole.optional().default("attachment"),
|
|
5962
|
+
sizeBytes: external_exports.number().int().positive("Size must be positive").max(MAX_ARTIFACT_BYTES, "File must not exceed 500 MB")
|
|
5963
|
+
});
|
|
5964
|
+
var RequestUploadUrlOutputSchema = external_exports.object({
|
|
5965
|
+
uploadUrl: external_exports.string(),
|
|
5966
|
+
artifactKey: external_exports.string()
|
|
5967
|
+
});
|
|
5968
|
+
var ArtifactKeyInputSchema = external_exports.object({
|
|
5969
|
+
artifactKey: external_exports.string().min(1, "Artifact key is required"),
|
|
5970
|
+
fileName: external_exports.string().min(1, "File name is required").max(255, "File name is too long"),
|
|
5971
|
+
mimeType: external_exports.string().min(1, "MIME type is required").max(120, "MIME type is too long"),
|
|
5972
|
+
role: ArtifactRole.optional().default("attachment"),
|
|
5973
|
+
sizeBytes: external_exports.number().int().positive("Size must be positive").max(MAX_ARTIFACT_BYTES, "File must not exceed 500 MB"),
|
|
5974
|
+
sha256Hash: external_exports.string().regex(/^[0-9a-f]{64}$/, "sha256Hash must be 64 lowercase hex chars"),
|
|
5975
|
+
keccak256Hash: external_exports.string().regex(/^0x[0-9a-fA-F]{64}$/, "keccak256Hash must be 0x followed by 64 hex chars")
|
|
5976
|
+
});
|
|
5977
|
+
var SubmissionCreateFromKeysSchema = external_exports.object({
|
|
5978
|
+
taskId: external_exports.string(),
|
|
5979
|
+
workerAddress: external_exports.string(),
|
|
5980
|
+
artifacts: external_exports.array(ArtifactKeyInputSchema).min(1).max(20),
|
|
5981
|
+
signature: external_exports.string()
|
|
5982
|
+
});
|
|
5279
5983
|
|
|
5280
5984
|
// ../../packages/shared/dist/schemas/agent.schemas.js
|
|
5985
|
+
var ActorType = external_exports.enum(["agent", "human"]);
|
|
5986
|
+
var RegistrationSource = external_exports.enum(["cli", "web"]);
|
|
5281
5987
|
var AgentStatsSchema = external_exports.object({
|
|
5282
5988
|
address: external_exports.string(),
|
|
5283
5989
|
agentId: external_exports.string().nullable().optional(),
|
|
5990
|
+
actorType: ActorType.optional(),
|
|
5284
5991
|
completedTasks: external_exports.number(),
|
|
5285
5992
|
ratedTasks: external_exports.number(),
|
|
5286
5993
|
totalStars: external_exports.number(),
|
|
@@ -5288,12 +5995,18 @@ var AgentStatsSchema = external_exports.object({
|
|
|
5288
5995
|
totalEarnings: external_exports.string(),
|
|
5289
5996
|
skills: external_exports.array(external_exports.string()).optional(),
|
|
5290
5997
|
emailAddress: external_exports.string().nullable().optional(),
|
|
5998
|
+
credibility: external_exports.number().int().min(0).max(1e3).optional(),
|
|
5291
5999
|
recentRatings: external_exports.array(external_exports.object({
|
|
5292
6000
|
taskId: external_exports.string(),
|
|
5293
6001
|
rating: external_exports.number(),
|
|
5294
|
-
createdAt: external_exports.string()
|
|
6002
|
+
createdAt: external_exports.string(),
|
|
6003
|
+
taskTitle: external_exports.string().nullable().optional(),
|
|
6004
|
+
feedbackText: external_exports.string().nullable().optional()
|
|
5295
6005
|
})).optional()
|
|
5296
6006
|
});
|
|
6007
|
+
var AgentRegistrationInputSchema = external_exports.object({
|
|
6008
|
+
source: RegistrationSource.optional().default("cli")
|
|
6009
|
+
});
|
|
5297
6010
|
var LeaderboardInputSchema = external_exports.object({
|
|
5298
6011
|
limit: external_exports.number().optional().default(20),
|
|
5299
6012
|
offset: external_exports.number().optional().default(0),
|
|
@@ -5301,17 +6014,20 @@ var LeaderboardInputSchema = external_exports.object({
|
|
|
5301
6014
|
skill: external_exports.string().optional(),
|
|
5302
6015
|
search: external_exports.string().optional(),
|
|
5303
6016
|
minRating: external_exports.number().min(0).max(5).optional(),
|
|
5304
|
-
minTasks: external_exports.number().int().min(0).optional()
|
|
6017
|
+
minTasks: external_exports.number().int().min(0).optional(),
|
|
6018
|
+
actorType: ActorType.optional()
|
|
5305
6019
|
});
|
|
5306
6020
|
var LeaderboardEntrySchema = external_exports.object({
|
|
5307
6021
|
rank: external_exports.number(),
|
|
5308
6022
|
address: external_exports.string(),
|
|
5309
6023
|
agentId: external_exports.string().nullable(),
|
|
6024
|
+
actorType: ActorType.optional(),
|
|
5310
6025
|
completedTasks: external_exports.number(),
|
|
5311
6026
|
averageRating: external_exports.number(),
|
|
5312
6027
|
totalEarnings: external_exports.string(),
|
|
5313
6028
|
skills: external_exports.array(external_exports.string()),
|
|
5314
|
-
emailAddress: external_exports.string().nullable().optional()
|
|
6029
|
+
emailAddress: external_exports.string().nullable().optional(),
|
|
6030
|
+
credibility: external_exports.number().int().min(0).max(1e3).optional()
|
|
5315
6031
|
});
|
|
5316
6032
|
var LeaderboardResponseSchema = external_exports.array(LeaderboardEntrySchema);
|
|
5317
6033
|
|
|
@@ -5320,7 +6036,8 @@ var RatingInputSchema = external_exports.object({
|
|
|
5320
6036
|
taskId: external_exports.string(),
|
|
5321
6037
|
worker: external_exports.string(),
|
|
5322
6038
|
rating: external_exports.number().int().min(0).max(100),
|
|
5323
|
-
feedbackText: external_exports.string().max(500).optional()
|
|
6039
|
+
feedbackText: external_exports.string().max(500).optional(),
|
|
6040
|
+
raterAgentId: external_exports.number().int().nonnegative().optional()
|
|
5324
6041
|
});
|
|
5325
6042
|
var FeedbackSchema = external_exports.object({
|
|
5326
6043
|
id: external_exports.string(),
|
|
@@ -5390,7 +6107,16 @@ var ClaimResponseSchema = external_exports.object({
|
|
|
5390
6107
|
});
|
|
5391
6108
|
|
|
5392
6109
|
// ../../packages/shared/dist/schemas/proof.schemas.js
|
|
5393
|
-
var ProofType = external_exports.enum([
|
|
6110
|
+
var ProofType = external_exports.enum([
|
|
6111
|
+
"url",
|
|
6112
|
+
"screenshot",
|
|
6113
|
+
"api_data",
|
|
6114
|
+
"manual",
|
|
6115
|
+
"custom",
|
|
6116
|
+
"eval",
|
|
6117
|
+
"tlsn",
|
|
6118
|
+
"zk"
|
|
6119
|
+
]);
|
|
5394
6120
|
var ProofStatus = external_exports.enum(["pending", "verified", "rejected"]);
|
|
5395
6121
|
var ProofSubmitSchema = external_exports.object({
|
|
5396
6122
|
taskId: external_exports.string().min(1, "Task ID is required"),
|
|
@@ -5417,13 +6143,18 @@ var BidCreateSchema = external_exports.object({
|
|
|
5417
6143
|
taskId: external_exports.string().min(1, "Task ID is required"),
|
|
5418
6144
|
price: external_exports.string().min(1, "Price is required")
|
|
5419
6145
|
});
|
|
6146
|
+
var AuctionAcceptSchema = external_exports.object({
|
|
6147
|
+
taskId: external_exports.string().min(1, "Task ID is required"),
|
|
6148
|
+
minPrice: external_exports.string().optional()
|
|
6149
|
+
});
|
|
5420
6150
|
var BidResponseSchema = external_exports.object({
|
|
5421
6151
|
id: external_exports.string(),
|
|
5422
6152
|
taskId: external_exports.string(),
|
|
5423
|
-
workerAddress: external_exports.string(),
|
|
5424
|
-
price: external_exports.string(),
|
|
6153
|
+
workerAddress: external_exports.string().nullable(),
|
|
6154
|
+
price: external_exports.string().nullable(),
|
|
5425
6155
|
createdAt: external_exports.string(),
|
|
5426
|
-
workerAgentId: external_exports.string().nullable().optional()
|
|
6156
|
+
workerAgentId: external_exports.string().nullable().optional(),
|
|
6157
|
+
isMyBid: external_exports.boolean().optional()
|
|
5427
6158
|
});
|
|
5428
6159
|
|
|
5429
6160
|
// ../../packages/shared/dist/schemas/wallet.schemas.js
|
|
@@ -5571,6 +6302,20 @@ var EmailInboundHeadersSchema = external_exports.object({
|
|
|
5571
6302
|
"x-email-from": external_exports.string(),
|
|
5572
6303
|
"x-email-to": external_exports.string().email()
|
|
5573
6304
|
});
|
|
6305
|
+
var BroadcastInputSchema = external_exports.object({
|
|
6306
|
+
subject: external_exports.string().min(1).max(200),
|
|
6307
|
+
body: external_exports.string().min(1).max(5e4),
|
|
6308
|
+
filters: external_exports.object({
|
|
6309
|
+
skills: external_exports.array(external_exports.string()).max(20).optional(),
|
|
6310
|
+
minTasks: external_exports.number().int().min(0).optional(),
|
|
6311
|
+
actorType: external_exports.enum(["agent", "human", "all"]).optional()
|
|
6312
|
+
}).optional()
|
|
6313
|
+
});
|
|
6314
|
+
var BroadcastResultSchema = external_exports.object({
|
|
6315
|
+
sent: external_exports.number(),
|
|
6316
|
+
failed: external_exports.number(),
|
|
6317
|
+
total: external_exports.number()
|
|
6318
|
+
});
|
|
5574
6319
|
|
|
5575
6320
|
// ../../packages/shared/dist/lib/agentName.js
|
|
5576
6321
|
var MODIFIERS = [
|
|
@@ -6595,7 +7340,7 @@ function getDefaultQueryTimeoutMs() {
|
|
|
6595
7340
|
}
|
|
6596
7341
|
return Math.floor(parsed);
|
|
6597
7342
|
}
|
|
6598
|
-
var xmtpCommand = new
|
|
7343
|
+
var xmtpCommand = new Command41("xmtp").description("Manage XMTP messaging for this agent");
|
|
6599
7344
|
xmtpCommand.command("init").description("Initialize XMTP client and register installation metadata with backend").action(async () => {
|
|
6600
7345
|
const keystore = await loadKeystore();
|
|
6601
7346
|
const client = await createXmtpClient({
|
|
@@ -6823,7 +7568,7 @@ xmtpCommand.command("purge").description("Revoke stale XMTP installations that h
|
|
|
6823
7568
|
});
|
|
6824
7569
|
|
|
6825
7570
|
// src/commands/daemon.ts
|
|
6826
|
-
import { Command as
|
|
7571
|
+
import { Command as Command42 } from "commander";
|
|
6827
7572
|
function diffTaskStatuses(prev, next) {
|
|
6828
7573
|
const changes = [];
|
|
6829
7574
|
for (const [taskId, newStatus] of next) {
|
|
@@ -6851,11 +7596,17 @@ function sleepOrAbort(ms, signal) {
|
|
|
6851
7596
|
});
|
|
6852
7597
|
}
|
|
6853
7598
|
var MAX_SEEN_TASK_IDS = 2e3;
|
|
6854
|
-
var daemonCommand = new
|
|
7599
|
+
var daemonCommand = new Command42("daemon").description("Long-running agent daemon: XMTP stream, heartbeats, and task polling").option("--heartbeat-interval <ms>", "Heartbeat interval in milliseconds", "1800000").option("--inbox-interval <ms>", "Inbox poll interval in milliseconds", "15000").option("--task-interval <ms>", "New task poll interval in milliseconds", "60000").option(
|
|
7600
|
+
"--auction-poll-interval <ms>",
|
|
7601
|
+
"Poll interval for clock-based auction tasks (dutch/reverse_dutch) in milliseconds",
|
|
7602
|
+
"15000"
|
|
7603
|
+
).option("--email-poll-interval <ms>", "Email inbox poll interval in milliseconds", "60000").option("--task-filters <json>", "JSON filter object for new-task discovery").option("--no-xmtp", "Disable XMTP stream and heartbeat").action(
|
|
6855
7604
|
async (opts) => {
|
|
6856
7605
|
const heartbeatIntervalMs = Number(opts.heartbeatInterval);
|
|
6857
7606
|
const inboxIntervalMs = Number(opts.inboxInterval);
|
|
6858
7607
|
const taskIntervalMs = Number(opts.taskInterval);
|
|
7608
|
+
const auctionPollIntervalMs = Number(opts.auctionPollInterval);
|
|
7609
|
+
const emailPollIntervalMs = Number(opts.emailPollInterval);
|
|
6859
7610
|
if (!Number.isFinite(heartbeatIntervalMs) || heartbeatIntervalMs <= 0) {
|
|
6860
7611
|
throw new Error("--heartbeat-interval must be a positive number");
|
|
6861
7612
|
}
|
|
@@ -6865,6 +7616,12 @@ var daemonCommand = new Command32("daemon").description("Long-running agent daem
|
|
|
6865
7616
|
if (!Number.isFinite(taskIntervalMs) || taskIntervalMs <= 0) {
|
|
6866
7617
|
throw new Error("--task-interval must be a positive number");
|
|
6867
7618
|
}
|
|
7619
|
+
if (!Number.isFinite(auctionPollIntervalMs) || auctionPollIntervalMs <= 0) {
|
|
7620
|
+
throw new Error("--auction-poll-interval must be a positive number");
|
|
7621
|
+
}
|
|
7622
|
+
if (!Number.isFinite(emailPollIntervalMs) || emailPollIntervalMs <= 0) {
|
|
7623
|
+
throw new Error("--email-poll-interval must be a positive number");
|
|
7624
|
+
}
|
|
6868
7625
|
let taskFilters = {};
|
|
6869
7626
|
if (opts.taskFilters) {
|
|
6870
7627
|
try {
|
|
@@ -7057,7 +7814,99 @@ var daemonCommand = new Command32("daemon").description("Long-running agent daem
|
|
|
7057
7814
|
}
|
|
7058
7815
|
}
|
|
7059
7816
|
};
|
|
7060
|
-
|
|
7817
|
+
const auctionPollLoop = async () => {
|
|
7818
|
+
while (!stopped) {
|
|
7819
|
+
await sleepOrAbort(auctionPollIntervalMs, abortController.signal);
|
|
7820
|
+
if (stopped) break;
|
|
7821
|
+
try {
|
|
7822
|
+
let cursor;
|
|
7823
|
+
let hasMore = true;
|
|
7824
|
+
while (hasMore) {
|
|
7825
|
+
const params = new URLSearchParams({
|
|
7826
|
+
mode: "auction",
|
|
7827
|
+
status: "open",
|
|
7828
|
+
limit: "50"
|
|
7829
|
+
});
|
|
7830
|
+
if (cursor) params.set("cursor", cursor);
|
|
7831
|
+
const result = await apiGet(`/api/tasks?${params.toString()}`);
|
|
7832
|
+
for (const task of result.tasks) {
|
|
7833
|
+
if (task.auctionType === "dutch" || task.auctionType === "reverse_dutch") {
|
|
7834
|
+
printResult({
|
|
7835
|
+
event: "task.auction_clock",
|
|
7836
|
+
taskId: task.id,
|
|
7837
|
+
auctionType: task.auctionType,
|
|
7838
|
+
currentAuctionPrice: task.currentAuctionPrice ?? null,
|
|
7839
|
+
bidDeadline: task.bidDeadline ?? null
|
|
7840
|
+
});
|
|
7841
|
+
}
|
|
7842
|
+
}
|
|
7843
|
+
cursor = result.nextCursor ?? void 0;
|
|
7844
|
+
hasMore = result.hasMore && cursor !== void 0;
|
|
7845
|
+
}
|
|
7846
|
+
} catch (err) {
|
|
7847
|
+
process.stderr.write(
|
|
7848
|
+
`Auction poll failed: ${err instanceof Error ? err.message : String(err)}
|
|
7849
|
+
`
|
|
7850
|
+
);
|
|
7851
|
+
}
|
|
7852
|
+
}
|
|
7853
|
+
};
|
|
7854
|
+
const emailPollLoop = async () => {
|
|
7855
|
+
const PAGE_SIZE = 50;
|
|
7856
|
+
while (!stopped) {
|
|
7857
|
+
await sleepOrAbort(emailPollIntervalMs, abortController.signal);
|
|
7858
|
+
if (stopped) break;
|
|
7859
|
+
try {
|
|
7860
|
+
let hasMore = true;
|
|
7861
|
+
while (hasMore) {
|
|
7862
|
+
const params = new URLSearchParams({
|
|
7863
|
+
deviceId: keystore.deviceId,
|
|
7864
|
+
apiToken: keystore.apiToken,
|
|
7865
|
+
limit: String(PAGE_SIZE),
|
|
7866
|
+
unread: "true"
|
|
7867
|
+
});
|
|
7868
|
+
const result = await apiGet(
|
|
7869
|
+
`/api/emails/list?${params.toString()}`
|
|
7870
|
+
);
|
|
7871
|
+
for (const email of result.emails) {
|
|
7872
|
+
printResult({
|
|
7873
|
+
event: "email.new",
|
|
7874
|
+
id: email.id,
|
|
7875
|
+
fromAddress: email.fromAddress,
|
|
7876
|
+
subject: email.subject,
|
|
7877
|
+
bodyText: email.bodyText,
|
|
7878
|
+
receivedAt: email.receivedAt
|
|
7879
|
+
});
|
|
7880
|
+
try {
|
|
7881
|
+
await apiPost("/api/emails/mark-read", {
|
|
7882
|
+
deviceId: keystore.deviceId,
|
|
7883
|
+
apiToken: keystore.apiToken,
|
|
7884
|
+
id: email.id,
|
|
7885
|
+
read: true
|
|
7886
|
+
});
|
|
7887
|
+
} catch (markErr) {
|
|
7888
|
+
process.stderr.write(
|
|
7889
|
+
`Email mark-read failed for ${email.id}: ${markErr instanceof Error ? markErr.message : String(markErr)}
|
|
7890
|
+
`
|
|
7891
|
+
);
|
|
7892
|
+
}
|
|
7893
|
+
}
|
|
7894
|
+
hasMore = result.emails.length === PAGE_SIZE;
|
|
7895
|
+
}
|
|
7896
|
+
} catch (err) {
|
|
7897
|
+
process.stderr.write(
|
|
7898
|
+
`Email poll failed: ${err instanceof Error ? err.message : String(err)}
|
|
7899
|
+
`
|
|
7900
|
+
);
|
|
7901
|
+
}
|
|
7902
|
+
}
|
|
7903
|
+
};
|
|
7904
|
+
await Promise.allSettled([
|
|
7905
|
+
inboxPollLoop(),
|
|
7906
|
+
newTaskPollLoop(),
|
|
7907
|
+
auctionPollLoop(),
|
|
7908
|
+
emailPollLoop()
|
|
7909
|
+
]);
|
|
7061
7910
|
};
|
|
7062
7911
|
await Promise.allSettled([xmtpLoop(), heartbeatLoop(), taskPollLoop()]);
|
|
7063
7912
|
} finally {
|
|
@@ -7068,11 +7917,11 @@ var daemonCommand = new Command32("daemon").description("Long-running agent daem
|
|
|
7068
7917
|
);
|
|
7069
7918
|
|
|
7070
7919
|
// src/commands/email/index.ts
|
|
7071
|
-
import { Command as
|
|
7920
|
+
import { Command as Command51 } from "commander";
|
|
7072
7921
|
|
|
7073
7922
|
// src/commands/email/register.ts
|
|
7074
|
-
import { Command as
|
|
7075
|
-
var registerCommand = new
|
|
7923
|
+
import { Command as Command43 } from "commander";
|
|
7924
|
+
var registerCommand = new Command43("register").description("Register an email address for this agent").requiredOption("--username <name>", "Desired username (e.g. myagent)").action(async (opts) => {
|
|
7076
7925
|
const check = await apiGet(
|
|
7077
7926
|
`/api/emails/check-username?username=${encodeURIComponent(opts.username)}`
|
|
7078
7927
|
);
|
|
@@ -7089,8 +7938,8 @@ var registerCommand = new Command33("register").description("Register an email a
|
|
|
7089
7938
|
});
|
|
7090
7939
|
|
|
7091
7940
|
// src/commands/email/inbox.ts
|
|
7092
|
-
import { Command as
|
|
7093
|
-
var inboxCommand2 = new
|
|
7941
|
+
import { Command as Command44 } from "commander";
|
|
7942
|
+
var inboxCommand2 = new Command44("inbox").description("List emails in your inbox").option("--limit <n>", "Number of emails to return", "20").option("--unread", "Show only unread emails").action(async (opts) => {
|
|
7094
7943
|
const keystore = await loadKeystore();
|
|
7095
7944
|
const params = new URLSearchParams({
|
|
7096
7945
|
deviceId: keystore.deviceId,
|
|
@@ -7105,8 +7954,8 @@ var inboxCommand2 = new Command34("inbox").description("List emails in your inbo
|
|
|
7105
7954
|
});
|
|
7106
7955
|
|
|
7107
7956
|
// src/commands/email/read.ts
|
|
7108
|
-
import { Command as
|
|
7109
|
-
var readCommand = new
|
|
7957
|
+
import { Command as Command45 } from "commander";
|
|
7958
|
+
var readCommand = new Command45("read").description("Read an email by ID (marks it as read)").argument("<id>", "Email ID").action(async (id) => {
|
|
7110
7959
|
const keystore = await loadKeystore();
|
|
7111
7960
|
const params = new URLSearchParams({
|
|
7112
7961
|
deviceId: keystore.deviceId,
|
|
@@ -7118,8 +7967,8 @@ var readCommand = new Command35("read").description("Read an email by ID (marks
|
|
|
7118
7967
|
});
|
|
7119
7968
|
|
|
7120
7969
|
// src/commands/email/send.ts
|
|
7121
|
-
import { Command as
|
|
7122
|
-
var sendCommand = new
|
|
7970
|
+
import { Command as Command46 } from "commander";
|
|
7971
|
+
var sendCommand = new Command46("send").description("Send an email").requiredOption("--to <address>", "Recipient email address").requiredOption("--subject <subject>", "Email subject").requiredOption("--body <text>", "Email body text").action(async (opts) => {
|
|
7123
7972
|
const keystore = await loadKeystore();
|
|
7124
7973
|
const result = await apiPost("/api/emails/send", {
|
|
7125
7974
|
deviceId: keystore.deviceId,
|
|
@@ -7132,8 +7981,8 @@ var sendCommand = new Command36("send").description("Send an email").requiredOpt
|
|
|
7132
7981
|
});
|
|
7133
7982
|
|
|
7134
7983
|
// src/commands/email/reply.ts
|
|
7135
|
-
import { Command as
|
|
7136
|
-
var replyCommand = new
|
|
7984
|
+
import { Command as Command47 } from "commander";
|
|
7985
|
+
var replyCommand = new Command47("reply").description("Reply to an email").argument("<id>", "Email ID to reply to").requiredOption("--body <text>", "Reply body text").action(async (id, opts) => {
|
|
7137
7986
|
const keystore = await loadKeystore();
|
|
7138
7987
|
const params = new URLSearchParams({
|
|
7139
7988
|
deviceId: keystore.deviceId,
|
|
@@ -7155,8 +8004,8 @@ var replyCommand = new Command37("reply").description("Reply to an email").argum
|
|
|
7155
8004
|
});
|
|
7156
8005
|
|
|
7157
8006
|
// src/commands/email/delete.ts
|
|
7158
|
-
import { Command as
|
|
7159
|
-
var deleteCommand = new
|
|
8007
|
+
import { Command as Command48 } from "commander";
|
|
8008
|
+
var deleteCommand = new Command48("delete").description("Delete an email by ID").argument("<id>", "Email ID").action(async (id) => {
|
|
7160
8009
|
const keystore = await loadKeystore();
|
|
7161
8010
|
const result = await apiPost("/api/emails/delete", {
|
|
7162
8011
|
deviceId: keystore.deviceId,
|
|
@@ -7167,15 +8016,15 @@ var deleteCommand = new Command38("delete").description("Delete an email by ID")
|
|
|
7167
8016
|
});
|
|
7168
8017
|
|
|
7169
8018
|
// src/commands/email/address.ts
|
|
7170
|
-
import { Command as
|
|
7171
|
-
var addressCommand2 = new
|
|
8019
|
+
import { Command as Command49 } from "commander";
|
|
8020
|
+
var addressCommand2 = new Command49("address").description("Show your registered email address").action(async () => {
|
|
7172
8021
|
const keystore = await loadKeystore();
|
|
7173
8022
|
const result = await apiGet(`/api/agents/stats?address=${keystore.walletAddress}`);
|
|
7174
8023
|
printResult({ emailAddress: result.emailAddress ?? null });
|
|
7175
8024
|
});
|
|
7176
8025
|
|
|
7177
8026
|
// src/commands/email/mark-read.ts
|
|
7178
|
-
import { Command as
|
|
8027
|
+
import { Command as Command50 } from "commander";
|
|
7179
8028
|
async function setReadStatus(id, read) {
|
|
7180
8029
|
const keystore = await loadKeystore();
|
|
7181
8030
|
const result = await apiPost("/api/emails/mark-read", {
|
|
@@ -7186,12 +8035,12 @@ async function setReadStatus(id, read) {
|
|
|
7186
8035
|
});
|
|
7187
8036
|
printResult({ id: result.id, isRead: result.isRead });
|
|
7188
8037
|
}
|
|
7189
|
-
var markReadCommand = new
|
|
8038
|
+
var markReadCommand = new Command50("mark-read").description("Mark an email as read or unread").argument("<id>", "Email ID").option("--unread", "Mark as unread instead of read").action(async (id, opts) => {
|
|
7190
8039
|
await setReadStatus(id, !opts.unread);
|
|
7191
8040
|
});
|
|
7192
8041
|
|
|
7193
8042
|
// src/commands/email/index.ts
|
|
7194
|
-
var emailCommand = new
|
|
8043
|
+
var emailCommand = new Command51("email").description("Email management commands");
|
|
7195
8044
|
emailCommand.addCommand(registerCommand);
|
|
7196
8045
|
emailCommand.addCommand(inboxCommand2);
|
|
7197
8046
|
emailCommand.addCommand(readCommand);
|
|
@@ -7204,7 +8053,7 @@ emailCommand.addCommand(markReadCommand);
|
|
|
7204
8053
|
// src/index.ts
|
|
7205
8054
|
var require2 = createRequire(import.meta.url);
|
|
7206
8055
|
var { version } = require2("../package.json");
|
|
7207
|
-
var program = new
|
|
8056
|
+
var program = new Command52();
|
|
7208
8057
|
program.name("taskmarket").description("Taskmarket CLI for AI agents").version(version);
|
|
7209
8058
|
program.addCommand(initCommand);
|
|
7210
8059
|
program.addCommand(walletCommand);
|