@lucid-agents/taskmarket 1.0.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 +132 -30
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -638,9 +638,14 @@ var getCmd = new Command7("get").description("Get task details").argument("<task
|
|
|
638
638
|
});
|
|
639
639
|
|
|
640
640
|
// src/commands/task/submit.ts
|
|
641
|
-
import { Command as Command8 } from "commander";
|
|
642
|
-
import { promises as
|
|
641
|
+
import { Command as Command8, Option } from "commander";
|
|
642
|
+
import { promises as fsPromises } from "fs";
|
|
643
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";
|
|
644
649
|
function collectFile(value, previous) {
|
|
645
650
|
return [...previous, value];
|
|
646
651
|
}
|
|
@@ -679,30 +684,98 @@ function mimeTypeForPath(filePath) {
|
|
|
679
684
|
return "application/octet-stream";
|
|
680
685
|
}
|
|
681
686
|
}
|
|
682
|
-
|
|
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);
|
|
728
|
+
});
|
|
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) => {
|
|
683
733
|
try {
|
|
684
734
|
if (!opts.file || opts.file.length === 0) {
|
|
685
735
|
printError("--file is required");
|
|
686
736
|
}
|
|
687
737
|
const keystore = await loadKeystore();
|
|
688
738
|
const signature = await signMessage(`taskmarket:submit:${taskId}`, keystore);
|
|
689
|
-
const
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
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,
|
|
696
752
|
fileName: basename(filePath),
|
|
697
|
-
mimeType
|
|
698
|
-
role:
|
|
699
|
-
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
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
|
|
706
779
|
});
|
|
707
780
|
printResult({ submissionId: result.submissionId });
|
|
708
781
|
} finally {
|
|
@@ -831,10 +904,10 @@ var pitchCmd = new Command13("pitch").description("Submit a pitch for a task (co
|
|
|
831
904
|
|
|
832
905
|
// src/commands/task/select-worker.ts
|
|
833
906
|
import { Command as Command14 } from "commander";
|
|
834
|
-
import { keccak256, toBytes } from "viem";
|
|
907
|
+
import { keccak256 as keccak2562, toBytes } from "viem";
|
|
835
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) => {
|
|
836
909
|
const keystore = await loadKeystore();
|
|
837
|
-
const hash =
|
|
910
|
+
const hash = keccak2562(toBytes(taskId + opts.pitch + opts.worker));
|
|
838
911
|
const signature = await signMessage(hash, keystore);
|
|
839
912
|
await apiPost(`/api/tasks/${taskId}/pitches/select`, {
|
|
840
913
|
taskId,
|
|
@@ -1510,11 +1583,11 @@ var withdrawCommand = new Command38("withdraw").description("Withdraw USDC to th
|
|
|
1510
1583
|
|
|
1511
1584
|
// src/commands/encrypt.ts
|
|
1512
1585
|
import { Command as Command39 } from "commander";
|
|
1513
|
-
import { promises as
|
|
1586
|
+
import { promises as fs2 } from "fs";
|
|
1514
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) => {
|
|
1515
1588
|
let plaintext;
|
|
1516
1589
|
try {
|
|
1517
|
-
plaintext = await
|
|
1590
|
+
plaintext = await fs2.readFile(file);
|
|
1518
1591
|
} catch {
|
|
1519
1592
|
printError(`Cannot read file: ${file}`);
|
|
1520
1593
|
}
|
|
@@ -1551,7 +1624,7 @@ var encryptCommand = new Command39("encrypt").description("Encrypt a file with E
|
|
|
1551
1624
|
}
|
|
1552
1625
|
const encrypted = encryptForRecipient(plaintext, recipientPubKey);
|
|
1553
1626
|
const outputPath = opts.output ?? `${file}.enc`;
|
|
1554
|
-
await
|
|
1627
|
+
await fs2.writeFile(outputPath, encrypted);
|
|
1555
1628
|
printResult({
|
|
1556
1629
|
output: outputPath,
|
|
1557
1630
|
bytes: encrypted.length,
|
|
@@ -1561,11 +1634,11 @@ var encryptCommand = new Command39("encrypt").description("Encrypt a file with E
|
|
|
1561
1634
|
|
|
1562
1635
|
// src/commands/decrypt.ts
|
|
1563
1636
|
import { Command as Command40 } from "commander";
|
|
1564
|
-
import { promises as
|
|
1637
|
+
import { promises as fs3 } from "fs";
|
|
1565
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) => {
|
|
1566
1639
|
let ciphertext;
|
|
1567
1640
|
try {
|
|
1568
|
-
ciphertext = await
|
|
1641
|
+
ciphertext = await fs3.readFile(file);
|
|
1569
1642
|
} catch {
|
|
1570
1643
|
printError(`Cannot read file: ${file}`);
|
|
1571
1644
|
}
|
|
@@ -1592,7 +1665,7 @@ var decryptCommand = new Command40("decrypt").description("Decrypt a file using
|
|
|
1592
1665
|
} else {
|
|
1593
1666
|
outputPath = `${file}.dec`;
|
|
1594
1667
|
}
|
|
1595
|
-
await
|
|
1668
|
+
await fs3.writeFile(outputPath, plaintext);
|
|
1596
1669
|
printResult({
|
|
1597
1670
|
output: outputPath,
|
|
1598
1671
|
bytes: plaintext.length
|
|
@@ -5806,9 +5879,9 @@ var UpdateTaskInputSchema = external_exports.object({
|
|
|
5806
5879
|
pitchDeadline: external_exports.number().optional(),
|
|
5807
5880
|
auctionFloorPrice: external_exports.string().optional(),
|
|
5808
5881
|
auctionStartPrice: external_exports.string().optional(),
|
|
5809
|
-
description: external_exports.string().optional(),
|
|
5810
|
-
tags: external_exports.array(external_exports.string()).optional(),
|
|
5811
|
-
metricDescription: 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()
|
|
5812
5885
|
});
|
|
5813
5886
|
|
|
5814
5887
|
// ../../packages/shared/dist/schemas/submission.schemas.js
|
|
@@ -5878,6 +5951,35 @@ var DownloadResponseSchema = external_exports.object({
|
|
|
5878
5951
|
keyBundle: external_exports.string().nullable().optional(),
|
|
5879
5952
|
expiresAt: external_exports.string()
|
|
5880
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
|
+
});
|
|
5881
5983
|
|
|
5882
5984
|
// ../../packages/shared/dist/schemas/agent.schemas.js
|
|
5883
5985
|
var ActorType = external_exports.enum(["agent", "human"]);
|