@lucid-agents/taskmarket 1.6.0 → 1.7.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 +416 -147
- 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 Command66 } from "commander";
|
|
10
10
|
import { createRequire } from "module";
|
|
11
11
|
|
|
12
12
|
// src/commands/init.ts
|
|
@@ -490,8 +490,8 @@ function getErrorMap() {
|
|
|
490
490
|
|
|
491
491
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
492
492
|
var makeIssue = (params) => {
|
|
493
|
-
const { data, path:
|
|
494
|
-
const fullPath = [...
|
|
493
|
+
const { data, path: path4, errorMaps, issueData } = params;
|
|
494
|
+
const fullPath = [...path4, ...issueData.path || []];
|
|
495
495
|
const fullIssue = {
|
|
496
496
|
...issueData,
|
|
497
497
|
path: fullPath
|
|
@@ -607,11 +607,11 @@ var errorUtil;
|
|
|
607
607
|
|
|
608
608
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
609
609
|
var ParseInputLazyPath = class {
|
|
610
|
-
constructor(parent, value,
|
|
610
|
+
constructor(parent, value, path4, key) {
|
|
611
611
|
this._cachedPath = [];
|
|
612
612
|
this.parent = parent;
|
|
613
613
|
this.data = value;
|
|
614
|
-
this._path =
|
|
614
|
+
this._path = path4;
|
|
615
615
|
this._key = key;
|
|
616
616
|
}
|
|
617
617
|
get path() {
|
|
@@ -4151,6 +4151,10 @@ var TaskDropListByOwnerInputSchema = external_exports.object({
|
|
|
4151
4151
|
var TaskDropGetInputSchema = external_exports.object({
|
|
4152
4152
|
taskDropId: external_exports.string().min(1)
|
|
4153
4153
|
});
|
|
4154
|
+
var TaskDropDirectoryInputSchema = external_exports.object({
|
|
4155
|
+
cursor: external_exports.string().min(1).max(2048).optional(),
|
|
4156
|
+
limit: external_exports.number().int().min(1).max(48).optional().default(24)
|
|
4157
|
+
});
|
|
4154
4158
|
var TaskDropSummarySchema = external_exports.object({
|
|
4155
4159
|
id: external_exports.string().min(1),
|
|
4156
4160
|
ownerAddress: EthAddress,
|
|
@@ -4178,10 +4182,23 @@ var TaskDropPageDataSchema = external_exports.object({
|
|
|
4178
4182
|
drop: TaskDropSummarySchema,
|
|
4179
4183
|
tasks: external_exports.array(TaskDropTaskSchema)
|
|
4180
4184
|
});
|
|
4185
|
+
var TaskDropDirectoryItemSchema = external_exports.object({
|
|
4186
|
+
drop: TaskDropSummarySchema,
|
|
4187
|
+
availableTaskCount: external_exports.number().int().nonnegative(),
|
|
4188
|
+
taskCount: external_exports.number().int().positive(),
|
|
4189
|
+
resolvedTaskCount: external_exports.number().int().nonnegative(),
|
|
4190
|
+
totalReward: external_exports.string().regex(/^\d+$/),
|
|
4191
|
+
nextExpiryTime: external_exports.string().datetime().nullable(),
|
|
4192
|
+
latestTaskAt: external_exports.string().datetime()
|
|
4193
|
+
});
|
|
4194
|
+
var TaskDropDirectoryResponseSchema = external_exports.object({
|
|
4195
|
+
items: external_exports.array(TaskDropDirectoryItemSchema),
|
|
4196
|
+
nextCursor: external_exports.string().nullable()
|
|
4197
|
+
});
|
|
4181
4198
|
|
|
4182
4199
|
// ../../packages/shared/dist/schemas/task.schemas.js
|
|
4183
4200
|
var TaskMode = external_exports.enum(["bounty", "claim", "pitch", "benchmark", "auction"]);
|
|
4184
|
-
var TaskVisibility = external_exports.enum(["unlisted", "public"]);
|
|
4201
|
+
var TaskVisibility = external_exports.enum(["unlisted", "public", "private"]);
|
|
4185
4202
|
var SubmissionVisibility = external_exports.enum(["public", "reveal_all", "winner_only", "never"]);
|
|
4186
4203
|
var TaskStatus = external_exports.enum([
|
|
4187
4204
|
"open",
|
|
@@ -4270,7 +4287,12 @@ var TaskCreateSchema = external_exports.object({
|
|
|
4270
4287
|
appealWindowHours: external_exports.number().positive().optional(),
|
|
4271
4288
|
disputeResolver: external_exports.string().optional(),
|
|
4272
4289
|
taskDropId: external_exports.string().min(1).optional(),
|
|
4273
|
-
taskDropCreate: TaskDropCreateInlineSchema.optional()
|
|
4290
|
+
taskDropCreate: TaskDropCreateInlineSchema.optional(),
|
|
4291
|
+
// Phase 3 (ADR-0030): only meaningful when taskVisibility === 'private'. At least
|
|
4292
|
+
// one of the two invite mechanisms is required for a private task; either or both
|
|
4293
|
+
// may be provided (requester's choice).
|
|
4294
|
+
allowedViewers: external_exports.array(external_exports.string()).max(50, "Maximum 50 invited wallets at creation").optional(),
|
|
4295
|
+
accessPassword: external_exports.string().min(8, "Password must be at least 8 characters").max(200).optional()
|
|
4274
4296
|
}).superRefine((input, ctx) => {
|
|
4275
4297
|
if (input.taskDropId && input.taskDropCreate) {
|
|
4276
4298
|
ctx.addIssue({
|
|
@@ -4279,6 +4301,32 @@ var TaskCreateSchema = external_exports.object({
|
|
|
4279
4301
|
message: "Provide taskDropId or taskDropCreate, not both"
|
|
4280
4302
|
});
|
|
4281
4303
|
}
|
|
4304
|
+
if (input.taskVisibility === "private") {
|
|
4305
|
+
const hasViewers = !!input.allowedViewers && input.allowedViewers.length > 0;
|
|
4306
|
+
const hasPassword = !!input.accessPassword;
|
|
4307
|
+
if (!hasViewers && !hasPassword) {
|
|
4308
|
+
ctx.addIssue({
|
|
4309
|
+
code: external_exports.ZodIssueCode.custom,
|
|
4310
|
+
path: ["taskVisibility"],
|
|
4311
|
+
message: "A private task needs at least one of allowedViewers or accessPassword"
|
|
4312
|
+
});
|
|
4313
|
+
}
|
|
4314
|
+
} else {
|
|
4315
|
+
if (input.allowedViewers && input.allowedViewers.length > 0) {
|
|
4316
|
+
ctx.addIssue({
|
|
4317
|
+
code: external_exports.ZodIssueCode.custom,
|
|
4318
|
+
path: ["allowedViewers"],
|
|
4319
|
+
message: "allowedViewers is only valid when taskVisibility is private"
|
|
4320
|
+
});
|
|
4321
|
+
}
|
|
4322
|
+
if (input.accessPassword) {
|
|
4323
|
+
ctx.addIssue({
|
|
4324
|
+
code: external_exports.ZodIssueCode.custom,
|
|
4325
|
+
path: ["accessPassword"],
|
|
4326
|
+
message: "accessPassword is only valid when taskVisibility is private"
|
|
4327
|
+
});
|
|
4328
|
+
}
|
|
4329
|
+
}
|
|
4282
4330
|
if (input.mode !== "auction")
|
|
4283
4331
|
return;
|
|
4284
4332
|
const toBaseUnits = (value) => value !== void 0 && /^[0-9]+$/.test(value) ? BigInt(value) : null;
|
|
@@ -4346,6 +4394,9 @@ var TaskResponseSchema = external_exports.object({
|
|
|
4346
4394
|
mode: TaskMode,
|
|
4347
4395
|
taskVisibility: TaskVisibility.optional().default("public"),
|
|
4348
4396
|
submissionVisibility: SubmissionVisibility.optional().default("public"),
|
|
4397
|
+
// Phase 3 (ADR-0030): whether a private task has a password mechanism configured --
|
|
4398
|
+
// never the hash itself, and never returned for a non-private task.
|
|
4399
|
+
hasAccessPassword: external_exports.boolean().optional(),
|
|
4349
4400
|
stakeRequired: external_exports.boolean(),
|
|
4350
4401
|
stakeBps: external_exports.number(),
|
|
4351
4402
|
pitchDeadline: external_exports.string().nullable(),
|
|
@@ -4430,7 +4481,11 @@ var TaskInboxInputSchema = external_exports.object({
|
|
|
4430
4481
|
});
|
|
4431
4482
|
var TaskInboxResponseSchema = external_exports.object({
|
|
4432
4483
|
asRequester: external_exports.array(TaskResponseSchema),
|
|
4433
|
-
asWorker: external_exports.array(TaskResponseSchema)
|
|
4484
|
+
asWorker: external_exports.array(TaskResponseSchema),
|
|
4485
|
+
// Phase 3 (ADR-0030): private tasks this address has been wallet-allowlisted onto,
|
|
4486
|
+
// surfaced here (self-authed only) as the in-app invite-discovery mechanism rather
|
|
4487
|
+
// than a separate notification-center feature.
|
|
4488
|
+
invitedPrivateTasks: external_exports.array(TaskResponseSchema).optional().default([])
|
|
4434
4489
|
});
|
|
4435
4490
|
var TaskDetailResponseSchema = TaskResponseSchema.extend({
|
|
4436
4491
|
pendingActions: PendingActionSchema.array(),
|
|
@@ -5121,6 +5176,33 @@ var LegalAcceptanceResponseSchema = external_exports.object({
|
|
|
5121
5176
|
receipt: external_exports.string()
|
|
5122
5177
|
});
|
|
5123
5178
|
|
|
5179
|
+
// ../../packages/shared/dist/schemas/task-access.schemas.js
|
|
5180
|
+
var VerifyTaskAccessPasswordInputSchema = external_exports.object({
|
|
5181
|
+
taskId: external_exports.string(),
|
|
5182
|
+
password: external_exports.string().min(1)
|
|
5183
|
+
});
|
|
5184
|
+
var VerifyTaskAccessPasswordResponseSchema = external_exports.object({
|
|
5185
|
+
grant: external_exports.string(),
|
|
5186
|
+
expiresAt: external_exports.string()
|
|
5187
|
+
});
|
|
5188
|
+
var AddAllowedViewerInputSchema = external_exports.object({
|
|
5189
|
+
taskId: external_exports.string(),
|
|
5190
|
+
viewerAddress: external_exports.string()
|
|
5191
|
+
});
|
|
5192
|
+
var RemoveAllowedViewerInputSchema = external_exports.object({
|
|
5193
|
+
taskId: external_exports.string(),
|
|
5194
|
+
viewerAddress: external_exports.string()
|
|
5195
|
+
});
|
|
5196
|
+
var ListAllowedViewersInputSchema = external_exports.object({
|
|
5197
|
+
taskId: external_exports.string()
|
|
5198
|
+
});
|
|
5199
|
+
var AllowedViewerResponseSchema = external_exports.object({
|
|
5200
|
+
viewerAddress: external_exports.string(),
|
|
5201
|
+
addedBy: external_exports.string(),
|
|
5202
|
+
createdAt: external_exports.string()
|
|
5203
|
+
});
|
|
5204
|
+
var ListAllowedViewersResponseSchema = external_exports.array(AllowedViewerResponseSchema);
|
|
5205
|
+
|
|
5124
5206
|
// ../../packages/shared/dist/platform.constants.js
|
|
5125
5207
|
var USDC_DECIMALS = 6;
|
|
5126
5208
|
|
|
@@ -5424,6 +5506,7 @@ function buildReadAuthMessage(address) {
|
|
|
5424
5506
|
}
|
|
5425
5507
|
var READ_AUTH_ADDRESS_HEADER = "X-Taskmarket-Caller-Address";
|
|
5426
5508
|
var READ_AUTH_SIGNATURE_HEADER = "X-Taskmarket-Caller-Signature";
|
|
5509
|
+
var TASK_ACCESS_GRANT_HEADER = "X-Taskmarket-Task-Access-Grant";
|
|
5427
5510
|
function buildSubmitMessage(taskId) {
|
|
5428
5511
|
return `taskmarket:submit:${taskId}`;
|
|
5429
5512
|
}
|
|
@@ -5443,6 +5526,38 @@ function buildDeviceRegisterMessage(walletAddress) {
|
|
|
5443
5526
|
return `taskmarket:device-register:${walletAddress.toLowerCase()}`;
|
|
5444
5527
|
}
|
|
5445
5528
|
|
|
5529
|
+
// ../../packages/shared/dist/lib/usdc.js
|
|
5530
|
+
var USDC_BASE_UNITS = 10n ** BigInt(USDC_DECIMALS);
|
|
5531
|
+
var USDC_PATTERN = new RegExp(`^(0|[1-9][0-9]*)(?:\\.([0-9]{1,${USDC_DECIMALS}}))?$`);
|
|
5532
|
+
function usdcToBaseUnits(value, options = {}) {
|
|
5533
|
+
const normalized = value.trim();
|
|
5534
|
+
const match = USDC_PATTERN.exec(normalized);
|
|
5535
|
+
if (!match) {
|
|
5536
|
+
throw new Error(`USDC amount must be a positive decimal with at most ${USDC_DECIMALS} fractional digits`);
|
|
5537
|
+
}
|
|
5538
|
+
const whole = BigInt(match[1]);
|
|
5539
|
+
const fraction = BigInt((match[2] ?? "").padEnd(USDC_DECIMALS, "0") || "0");
|
|
5540
|
+
const baseUnits = whole * USDC_BASE_UNITS + fraction;
|
|
5541
|
+
if (baseUnits < 0n || baseUnits === 0n && !options.allowZero) {
|
|
5542
|
+
throw new Error("USDC amount must be greater than zero");
|
|
5543
|
+
}
|
|
5544
|
+
return baseUnits.toString();
|
|
5545
|
+
}
|
|
5546
|
+
function formatUsdcBaseUnits(value, options = {}) {
|
|
5547
|
+
const baseUnits = BigInt(value);
|
|
5548
|
+
const negative = baseUnits < 0n;
|
|
5549
|
+
const absolute = negative ? -baseUnits : baseUnits;
|
|
5550
|
+
const wholeUnits = absolute / USDC_BASE_UNITS;
|
|
5551
|
+
const fractionalUnits = absolute % USDC_BASE_UNITS;
|
|
5552
|
+
const whole = options.groupThousands ? new Intl.NumberFormat("en-US", { maximumFractionDigits: 0 }).format(wholeUnits) : wholeUnits.toString();
|
|
5553
|
+
let fraction = fractionalUnits.toString().padStart(USDC_DECIMALS, "0");
|
|
5554
|
+
if (options.trimTrailingZeros) {
|
|
5555
|
+
fraction = fraction.replace(/0+$/, "");
|
|
5556
|
+
}
|
|
5557
|
+
const sign = negative ? "-" : "";
|
|
5558
|
+
return fraction ? `${sign}${whole}.${fraction}` : `${sign}${whole}`;
|
|
5559
|
+
}
|
|
5560
|
+
|
|
5446
5561
|
// ../../packages/shared/dist/legal.js
|
|
5447
5562
|
var LEGAL_RECEIPT_HEADER = "X-Taskmarket-Legal-Receipt";
|
|
5448
5563
|
function buildLegalReceiptHeaders(receipt) {
|
|
@@ -5921,21 +6036,21 @@ async function keystoreExists(keystorePath) {
|
|
|
5921
6036
|
// src/lib/api.ts
|
|
5922
6037
|
var API_URL = process.env.TASKMARKET_API_URL ?? "https://api.taskmarket.dev";
|
|
5923
6038
|
var API_ORIGIN = new URL(API_URL).origin;
|
|
5924
|
-
function legalReceiptHeadersForKeystore(keystore,
|
|
5925
|
-
const canSend = keystore.legalAcceptanceApiOrigin === API_ORIGIN && (method === "POST" ||
|
|
6039
|
+
function legalReceiptHeadersForKeystore(keystore, path4, method) {
|
|
6040
|
+
const canSend = keystore.legalAcceptanceApiOrigin === API_ORIGIN && (method === "POST" || path4 === "/api/legal/status");
|
|
5926
6041
|
return canSend ? buildLegalReceiptHeaders(keystore.legalAcceptanceReceipt) : {};
|
|
5927
6042
|
}
|
|
5928
|
-
async function legalReceiptHeaders(
|
|
6043
|
+
async function legalReceiptHeaders(path4, method) {
|
|
5929
6044
|
try {
|
|
5930
6045
|
const keystore = await loadKeystore();
|
|
5931
|
-
return legalReceiptHeadersForKeystore(keystore,
|
|
6046
|
+
return legalReceiptHeadersForKeystore(keystore, path4, method);
|
|
5932
6047
|
} catch {
|
|
5933
6048
|
return {};
|
|
5934
6049
|
}
|
|
5935
6050
|
}
|
|
5936
|
-
async function apiGet(
|
|
5937
|
-
const legalHeaders = await legalReceiptHeaders(
|
|
5938
|
-
const res = await fetch(`${API_URL}${
|
|
6051
|
+
async function apiGet(path4, options) {
|
|
6052
|
+
const legalHeaders = await legalReceiptHeaders(path4, "GET");
|
|
6053
|
+
const res = await fetch(`${API_URL}${path4}`, {
|
|
5939
6054
|
method: "GET",
|
|
5940
6055
|
redirect: "error",
|
|
5941
6056
|
headers: {
|
|
@@ -5946,21 +6061,42 @@ async function apiGet(path3, options) {
|
|
|
5946
6061
|
});
|
|
5947
6062
|
const body = await res.json();
|
|
5948
6063
|
if (!res.ok) {
|
|
5949
|
-
throw new Error(`GET ${
|
|
6064
|
+
throw new Error(`GET ${path4} failed (${res.status}): ${JSON.stringify(body)}`);
|
|
5950
6065
|
}
|
|
5951
6066
|
return body;
|
|
5952
6067
|
}
|
|
5953
|
-
async function apiPost(
|
|
5954
|
-
const legalHeaders = await legalReceiptHeaders(
|
|
5955
|
-
const res = await fetch(`${API_URL}${
|
|
6068
|
+
async function apiPost(path4, body, options) {
|
|
6069
|
+
const legalHeaders = await legalReceiptHeaders(path4, "POST");
|
|
6070
|
+
const res = await fetch(`${API_URL}${path4}`, {
|
|
5956
6071
|
method: "POST",
|
|
5957
6072
|
redirect: "error",
|
|
5958
|
-
headers: {
|
|
6073
|
+
headers: {
|
|
6074
|
+
"Content-Type": "application/json",
|
|
6075
|
+
...legalHeaders,
|
|
6076
|
+
...options?.headers ?? {}
|
|
6077
|
+
},
|
|
5959
6078
|
body: JSON.stringify(body)
|
|
5960
6079
|
});
|
|
5961
6080
|
const result = await res.json();
|
|
5962
6081
|
if (!res.ok) {
|
|
5963
|
-
throw new Error(`POST ${
|
|
6082
|
+
throw new Error(`POST ${path4} failed (${res.status}): ${JSON.stringify(result)}`);
|
|
6083
|
+
}
|
|
6084
|
+
return result;
|
|
6085
|
+
}
|
|
6086
|
+
async function apiDelete(path4, options) {
|
|
6087
|
+
const legalHeaders = await legalReceiptHeaders(path4, "POST");
|
|
6088
|
+
const res = await fetch(`${API_URL}${path4}`, {
|
|
6089
|
+
method: "DELETE",
|
|
6090
|
+
redirect: "error",
|
|
6091
|
+
headers: {
|
|
6092
|
+
"Content-Type": "application/json",
|
|
6093
|
+
...legalHeaders,
|
|
6094
|
+
...options?.headers ?? {}
|
|
6095
|
+
}
|
|
6096
|
+
});
|
|
6097
|
+
const result = await res.json();
|
|
6098
|
+
if (!res.ok) {
|
|
6099
|
+
throw new Error(`DELETE ${path4} failed (${res.status}): ${JSON.stringify(result)}`);
|
|
5964
6100
|
}
|
|
5965
6101
|
return result;
|
|
5966
6102
|
}
|
|
@@ -6454,10 +6590,10 @@ var addressCommand = new Command3("address").description("Print the wallet addre
|
|
|
6454
6590
|
import { Command as Command4 } from "commander";
|
|
6455
6591
|
|
|
6456
6592
|
// src/lib/x402.ts
|
|
6457
|
-
async function x402Post(
|
|
6458
|
-
const url = `${API_URL}${
|
|
6593
|
+
async function x402Post(path4, body) {
|
|
6594
|
+
const url = `${API_URL}${path4}`;
|
|
6459
6595
|
const keystore = await loadKeystore();
|
|
6460
|
-
const legalHeaders = legalReceiptHeadersForKeystore(keystore,
|
|
6596
|
+
const legalHeaders = legalReceiptHeadersForKeystore(keystore, path4, "POST");
|
|
6461
6597
|
const r1 = await fetch(url, {
|
|
6462
6598
|
method: "POST",
|
|
6463
6599
|
redirect: "error",
|
|
@@ -6469,7 +6605,7 @@ async function x402Post(path3, body) {
|
|
|
6469
6605
|
return r1.json();
|
|
6470
6606
|
}
|
|
6471
6607
|
const text = await r1.text().catch(() => "");
|
|
6472
|
-
throw new Error(`POST ${
|
|
6608
|
+
throw new Error(`POST ${path4} failed (${r1.status}): ${text}`);
|
|
6473
6609
|
}
|
|
6474
6610
|
const requirements = await r1.json();
|
|
6475
6611
|
if (!requirements.accepts || requirements.accepts.length === 0) {
|
|
@@ -6503,7 +6639,7 @@ async function x402Post(path3, body) {
|
|
|
6503
6639
|
});
|
|
6504
6640
|
const result = await r2.json();
|
|
6505
6641
|
if (!r2.ok) {
|
|
6506
|
-
throw new Error(`POST ${
|
|
6642
|
+
throw new Error(`POST ${path4} failed after payment (${r2.status}): ${JSON.stringify(result)}`);
|
|
6507
6643
|
}
|
|
6508
6644
|
return result;
|
|
6509
6645
|
}
|
|
@@ -6544,7 +6680,7 @@ var statsCommand = new Command5("stats").description("View agent statistics").op
|
|
|
6544
6680
|
dreamsResult.claimableBaseUnits,
|
|
6545
6681
|
exchangeRateResult.dreamsPerUsdc
|
|
6546
6682
|
);
|
|
6547
|
-
pendingDreamsUsd = (
|
|
6683
|
+
pendingDreamsUsd = formatUsdcBaseUnits(usdBaseUnits);
|
|
6548
6684
|
}
|
|
6549
6685
|
}
|
|
6550
6686
|
const dreamsPerUsdc = exchangeRateResult !== null && exchangeRateResult.dreamsPerUsdc !== "0" ? exchangeRateResult.dreamsPerUsdc : null;
|
|
@@ -6568,36 +6704,20 @@ var statsCommand = new Command5("stats").description("View agent statistics").op
|
|
|
6568
6704
|
});
|
|
6569
6705
|
|
|
6570
6706
|
// src/commands/task/index.ts
|
|
6571
|
-
import { Command as
|
|
6707
|
+
import { Command as Command40 } from "commander";
|
|
6572
6708
|
|
|
6573
6709
|
// src/commands/task/create.ts
|
|
6574
6710
|
import { Command as Command6 } from "commander";
|
|
6575
|
-
|
|
6576
|
-
// src/lib/usdc.ts
|
|
6577
|
-
var USDC_BASE_UNITS = 10n ** BigInt(USDC_DECIMALS);
|
|
6578
|
-
var USDC_PATTERN = new RegExp(`^(0|[1-9][0-9]*)(?:\\.([0-9]{1,${USDC_DECIMALS}}))?$`);
|
|
6579
|
-
function usdcToBaseUnits(value, options = {}) {
|
|
6580
|
-
const normalized = value.trim();
|
|
6581
|
-
const match = USDC_PATTERN.exec(normalized);
|
|
6582
|
-
if (!match) {
|
|
6583
|
-
throw new Error(
|
|
6584
|
-
`USDC amount must be a positive decimal with at most ${USDC_DECIMALS} fractional digits`
|
|
6585
|
-
);
|
|
6586
|
-
}
|
|
6587
|
-
const whole = BigInt(match[1]);
|
|
6588
|
-
const fraction = BigInt((match[2] ?? "").padEnd(USDC_DECIMALS, "0") || "0");
|
|
6589
|
-
const baseUnits = whole * USDC_BASE_UNITS + fraction;
|
|
6590
|
-
if (baseUnits < 0n || baseUnits === 0n && !options.allowZero) {
|
|
6591
|
-
throw new Error("USDC amount must be greater than zero");
|
|
6592
|
-
}
|
|
6593
|
-
return baseUnits.toString();
|
|
6594
|
-
}
|
|
6595
|
-
|
|
6596
|
-
// src/commands/task/create.ts
|
|
6597
6711
|
var createCmd = new Command6("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(
|
|
6598
6712
|
"--task-visibility <mode>",
|
|
6599
|
-
"Task visibility: public (default) or
|
|
6713
|
+
"Task visibility: public (default), unlisted, or private. Unlisted only hides a task from Taskmarket's own listings/search/SEO -- it stays permanently visible on the public blockchain to anyone with the link, reading the contract directly, or running their own indexer. private is genuinely access-controlled: only the requester and invited/assigned workers can view it via listings, get, or the gated reads -- see --allowed-viewers and --access-password. Even private, the on-chain existence, reward, and participation stay publicly observable regardless.",
|
|
6600
6714
|
"public"
|
|
6715
|
+
).option(
|
|
6716
|
+
"--allowed-viewers <addresses>",
|
|
6717
|
+
"Comma-separated wallet addresses to invite to a private task. At least one of --allowed-viewers or --access-password is required when --task-visibility is private; both may be given together. More wallets can be invited later with `task invite`."
|
|
6718
|
+
).option(
|
|
6719
|
+
"--access-password <password>",
|
|
6720
|
+
"Password (min 8 characters) granting anonymous access to a private task via `task unlock`. Set once at creation -- there is no command to change it later."
|
|
6601
6721
|
).option(
|
|
6602
6722
|
"--submission-visibility <mode>",
|
|
6603
6723
|
"Submission visibility: public (default), reveal_all, winner_only, or never. Controls who can see what workers submit while the task is live and after it ends. public matches today's behavior exactly. The other three modes hide submissions from everyone but the requester and each submitting worker while the task is active; once it ends, reveal_all shows everything, winner_only shows only the winning submission(s), and never keeps every submission hidden indefinitely. Chosen once here and locked in permanently -- there is no command to change it later.",
|
|
@@ -6628,8 +6748,11 @@ var createCmd = new Command6("create").description("Create a new task (costs rew
|
|
|
6628
6748
|
if (!Number.isFinite(duration) || duration <= 0) {
|
|
6629
6749
|
return void printError("--duration must be a positive number of hours");
|
|
6630
6750
|
}
|
|
6631
|
-
|
|
6632
|
-
|
|
6751
|
+
const validTaskVisibilities = ["public", "unlisted", "private"];
|
|
6752
|
+
if (!validTaskVisibilities.includes(opts.taskVisibility)) {
|
|
6753
|
+
return void printError(
|
|
6754
|
+
`--task-visibility must be one of: ${validTaskVisibilities.join(", ")}`
|
|
6755
|
+
);
|
|
6633
6756
|
}
|
|
6634
6757
|
const validSubmissionVisibilities = ["public", "reveal_all", "winner_only", "never"];
|
|
6635
6758
|
if (!validSubmissionVisibilities.includes(opts.submissionVisibility)) {
|
|
@@ -6637,6 +6760,21 @@ var createCmd = new Command6("create").description("Create a new task (costs rew
|
|
|
6637
6760
|
`--submission-visibility must be one of: ${validSubmissionVisibilities.join(", ")}`
|
|
6638
6761
|
);
|
|
6639
6762
|
}
|
|
6763
|
+
const allowedViewers = opts.allowedViewers ? opts.allowedViewers.split(",").map((a) => a.trim()) : void 0;
|
|
6764
|
+
if (opts.taskVisibility === "private") {
|
|
6765
|
+
if ((!allowedViewers || allowedViewers.length === 0) && !opts.accessPassword) {
|
|
6766
|
+
return void printError(
|
|
6767
|
+
"--task-visibility private requires at least one of --allowed-viewers or --access-password"
|
|
6768
|
+
);
|
|
6769
|
+
}
|
|
6770
|
+
if (opts.accessPassword && opts.accessPassword.length < 8) {
|
|
6771
|
+
return void printError("--access-password must be at least 8 characters");
|
|
6772
|
+
}
|
|
6773
|
+
} else if (allowedViewers || opts.accessPassword) {
|
|
6774
|
+
return void printError(
|
|
6775
|
+
"--allowed-viewers/--access-password are only valid with --task-visibility private"
|
|
6776
|
+
);
|
|
6777
|
+
}
|
|
6640
6778
|
if (opts.mode === "auction") {
|
|
6641
6779
|
if (!opts.maxPrice) {
|
|
6642
6780
|
return void printError("--max-price is required for auction mode");
|
|
@@ -6686,6 +6824,12 @@ var createCmd = new Command6("create").description("Create a new task (costs rew
|
|
|
6686
6824
|
stakeRequired: false,
|
|
6687
6825
|
stakeBps: 0
|
|
6688
6826
|
};
|
|
6827
|
+
if (allowedViewers && allowedViewers.length > 0) {
|
|
6828
|
+
body.allowedViewers = allowedViewers;
|
|
6829
|
+
}
|
|
6830
|
+
if (opts.accessPassword) {
|
|
6831
|
+
body.accessPassword = opts.accessPassword;
|
|
6832
|
+
}
|
|
6689
6833
|
if (opts.pitchDeadline) {
|
|
6690
6834
|
body.pitchDeadline = parseInt(opts.pitchDeadline, 10) * 3600;
|
|
6691
6835
|
}
|
|
@@ -6768,6 +6912,33 @@ var createCmd = new Command6("create").description("Create a new task (costs rew
|
|
|
6768
6912
|
|
|
6769
6913
|
// src/commands/task/search.ts
|
|
6770
6914
|
import { Command as Command7 } from "commander";
|
|
6915
|
+
|
|
6916
|
+
// src/lib/read-auth.ts
|
|
6917
|
+
async function signReadAuth() {
|
|
6918
|
+
let keystore;
|
|
6919
|
+
try {
|
|
6920
|
+
keystore = await loadKeystore();
|
|
6921
|
+
} catch {
|
|
6922
|
+
return null;
|
|
6923
|
+
}
|
|
6924
|
+
try {
|
|
6925
|
+
const account = await createWalletAccountFromKeystore(keystore);
|
|
6926
|
+
const signature = await account.signMessage({
|
|
6927
|
+
message: buildReadAuthMessage(keystore.walletAddress)
|
|
6928
|
+
});
|
|
6929
|
+
return {
|
|
6930
|
+
walletAddress: keystore.walletAddress,
|
|
6931
|
+
headers: {
|
|
6932
|
+
[READ_AUTH_ADDRESS_HEADER]: keystore.walletAddress,
|
|
6933
|
+
[READ_AUTH_SIGNATURE_HEADER]: signature
|
|
6934
|
+
}
|
|
6935
|
+
};
|
|
6936
|
+
} catch {
|
|
6937
|
+
return { walletAddress: keystore.walletAddress, headers: {} };
|
|
6938
|
+
}
|
|
6939
|
+
}
|
|
6940
|
+
|
|
6941
|
+
// src/commands/task/search.ts
|
|
6771
6942
|
var listCmd = new Command7("list").alias("search").description("List available tasks").option("--status <status>", "Filter by status (e.g. open)", "open").option(
|
|
6772
6943
|
"--phase <phase>",
|
|
6773
6944
|
"Filter by derived lifecycle phase (active, in_review, awaiting_settlement, resolved) -- independent of --status, e.g. --phase awaiting_settlement finds tasks whose deadline has passed but are still open/claimed/worker_selected"
|
|
@@ -6790,15 +6961,58 @@ var listCmd = new Command7("list").alias("search").description("List available t
|
|
|
6790
6961
|
if (opts.deadlineHours) params.set("deadlineHours", opts.deadlineHours);
|
|
6791
6962
|
if (opts.limit) params.set("limit", opts.limit);
|
|
6792
6963
|
if (opts.cursor) params.set("cursor", opts.cursor);
|
|
6793
|
-
const
|
|
6964
|
+
const auth = await signReadAuth();
|
|
6965
|
+
const result = await apiGet(`/api/tasks?${params.toString()}`, {
|
|
6966
|
+
headers: auth?.headers ?? {}
|
|
6967
|
+
});
|
|
6794
6968
|
printResult({ tasks: result.tasks, hasMore: result.hasMore, nextCursor: result.nextCursor });
|
|
6795
6969
|
}
|
|
6796
6970
|
);
|
|
6797
6971
|
|
|
6798
6972
|
// src/commands/task/get.ts
|
|
6799
6973
|
import { Command as Command8 } from "commander";
|
|
6974
|
+
|
|
6975
|
+
// src/lib/task-access-grants.ts
|
|
6976
|
+
import { promises as fs2 } from "fs";
|
|
6977
|
+
import os2 from "os";
|
|
6978
|
+
import path2 from "path";
|
|
6979
|
+
function getGrantsPath() {
|
|
6980
|
+
return path2.join(os2.homedir(), ".taskmarket", "task-access-grants.json");
|
|
6981
|
+
}
|
|
6982
|
+
async function readGrantsFile() {
|
|
6983
|
+
try {
|
|
6984
|
+
const raw = await fs2.readFile(getGrantsPath(), "utf-8");
|
|
6985
|
+
return JSON.parse(raw);
|
|
6986
|
+
} catch {
|
|
6987
|
+
return {};
|
|
6988
|
+
}
|
|
6989
|
+
}
|
|
6990
|
+
async function loadTaskAccessGrant(taskId) {
|
|
6991
|
+
const grants = await readGrantsFile();
|
|
6992
|
+
const record = grants[taskId];
|
|
6993
|
+
if (!record) return null;
|
|
6994
|
+
if (new Date(record.expiresAt).getTime() <= Date.now()) return null;
|
|
6995
|
+
return record.grant;
|
|
6996
|
+
}
|
|
6997
|
+
async function taskAccessGrantHeaders(taskId) {
|
|
6998
|
+
const grant = await loadTaskAccessGrant(taskId);
|
|
6999
|
+
return grant ? { [TASK_ACCESS_GRANT_HEADER]: grant } : {};
|
|
7000
|
+
}
|
|
7001
|
+
async function saveTaskAccessGrant(taskId, grant, expiresAt) {
|
|
7002
|
+
const grants = await readGrantsFile();
|
|
7003
|
+
grants[taskId] = { grant, expiresAt };
|
|
7004
|
+
const dir = path2.dirname(getGrantsPath());
|
|
7005
|
+
await fs2.mkdir(dir, { recursive: true });
|
|
7006
|
+
await fs2.writeFile(getGrantsPath(), JSON.stringify(grants, null, 2), {
|
|
7007
|
+
mode: 384
|
|
7008
|
+
});
|
|
7009
|
+
}
|
|
7010
|
+
|
|
7011
|
+
// src/commands/task/get.ts
|
|
6800
7012
|
var getCmd = new Command8("get").description("Get task details").argument("<taskId>", "Task ID (0x-prefixed hex)").action(async (taskId) => {
|
|
6801
|
-
const
|
|
7013
|
+
const auth = await signReadAuth();
|
|
7014
|
+
const headers = { ...auth?.headers ?? {}, ...await taskAccessGrantHeaders(taskId) };
|
|
7015
|
+
const task = await apiGet(`/api/tasks/${taskId}`, { headers });
|
|
6802
7016
|
if (!task) {
|
|
6803
7017
|
printError(`Task not found: ${taskId}`);
|
|
6804
7018
|
}
|
|
@@ -7073,7 +7287,9 @@ var pitchCmd = new Command14("pitch").description("Submit a pitch for a task (co
|
|
|
7073
7287
|
import { Command as Command15 } from "commander";
|
|
7074
7288
|
var pitchesCmd = new Command15("pitches").description("List pitches for a task").argument("<taskId>", "Task ID (0x-prefixed hex)").action(async (taskId) => {
|
|
7075
7289
|
try {
|
|
7076
|
-
|
|
7290
|
+
const auth = await signReadAuth();
|
|
7291
|
+
const headers = { ...auth?.headers ?? {}, ...await taskAccessGrantHeaders(taskId) };
|
|
7292
|
+
printResult(await apiGet(`/api/tasks/${taskId}/pitches`, { headers }));
|
|
7077
7293
|
} catch (err) {
|
|
7078
7294
|
printError(err instanceof Error ? err.message : String(err));
|
|
7079
7295
|
}
|
|
@@ -7114,7 +7330,9 @@ var proofCmd = new Command17("proof").description("Submit a benchmark proof (cos
|
|
|
7114
7330
|
import { Command as Command18 } from "commander";
|
|
7115
7331
|
var proofsCmd = new Command18("proofs").description("List proofs for a benchmark task").argument("<taskId>", "Task ID (0x-prefixed hex)").action(async (taskId) => {
|
|
7116
7332
|
try {
|
|
7117
|
-
|
|
7333
|
+
const auth = await signReadAuth();
|
|
7334
|
+
const headers = { ...auth?.headers ?? {}, ...await taskAccessGrantHeaders(taskId) };
|
|
7335
|
+
printResult(await apiGet(`/api/tasks/${taskId}/proofs`, { headers }));
|
|
7118
7336
|
} catch (err) {
|
|
7119
7337
|
printError(err instanceof Error ? err.message : String(err));
|
|
7120
7338
|
}
|
|
@@ -7157,40 +7375,13 @@ var auctionAcceptCmd = new Command20("auction-accept").description("Accept curre
|
|
|
7157
7375
|
const result = await x402Post(`/api/tasks/${taskId}/bids/accept`, body);
|
|
7158
7376
|
printResult({
|
|
7159
7377
|
acceptedPrice: result.acceptedPrice,
|
|
7160
|
-
acceptedPriceUsdc: (
|
|
7378
|
+
acceptedPriceUsdc: formatUsdcBaseUnits(result.acceptedPrice),
|
|
7161
7379
|
workerAddress: result.workerAddress
|
|
7162
7380
|
});
|
|
7163
7381
|
});
|
|
7164
7382
|
|
|
7165
7383
|
// src/commands/task/submissions.ts
|
|
7166
7384
|
import { Command as Command21 } from "commander";
|
|
7167
|
-
|
|
7168
|
-
// src/lib/read-auth.ts
|
|
7169
|
-
async function signReadAuth() {
|
|
7170
|
-
let keystore;
|
|
7171
|
-
try {
|
|
7172
|
-
keystore = await loadKeystore();
|
|
7173
|
-
} catch {
|
|
7174
|
-
return null;
|
|
7175
|
-
}
|
|
7176
|
-
try {
|
|
7177
|
-
const account = await createWalletAccountFromKeystore(keystore);
|
|
7178
|
-
const signature = await account.signMessage({
|
|
7179
|
-
message: buildReadAuthMessage(keystore.walletAddress)
|
|
7180
|
-
});
|
|
7181
|
-
return {
|
|
7182
|
-
walletAddress: keystore.walletAddress,
|
|
7183
|
-
headers: {
|
|
7184
|
-
[READ_AUTH_ADDRESS_HEADER]: keystore.walletAddress,
|
|
7185
|
-
[READ_AUTH_SIGNATURE_HEADER]: signature
|
|
7186
|
-
}
|
|
7187
|
-
};
|
|
7188
|
-
} catch {
|
|
7189
|
-
return { walletAddress: keystore.walletAddress, headers: {} };
|
|
7190
|
-
}
|
|
7191
|
-
}
|
|
7192
|
-
|
|
7193
|
-
// src/commands/task/submissions.ts
|
|
7194
7385
|
var submissionsCmd = new Command21("submissions").description("List submissions for a task").argument("<taskId>", "Task ID (0x-prefixed hex)").action(async (taskId) => {
|
|
7195
7386
|
const auth = await signReadAuth();
|
|
7196
7387
|
let subs;
|
|
@@ -7608,8 +7799,82 @@ var resolveDisputeCmd = new Command35("resolve-dispute").description(
|
|
|
7608
7799
|
printResult({ txHash: result.txHash });
|
|
7609
7800
|
});
|
|
7610
7801
|
|
|
7802
|
+
// src/commands/task/unlock.ts
|
|
7803
|
+
import { Command as Command36 } from "commander";
|
|
7804
|
+
var unlockCmd = new Command36("unlock").description("Unlock a private task with its password, caching a task-scoped access grant").argument("<taskId>", "Task ID (0x-prefixed hex)").requiredOption("--password <password>", "The private task's password").action(async (taskId, opts) => {
|
|
7805
|
+
let result;
|
|
7806
|
+
try {
|
|
7807
|
+
result = await apiPost(`/api/tasks/${taskId}/private-access/verify`, {
|
|
7808
|
+
taskId,
|
|
7809
|
+
password: opts.password
|
|
7810
|
+
});
|
|
7811
|
+
} catch (err) {
|
|
7812
|
+
printError(err instanceof Error ? err.message : "Failed to unlock task.");
|
|
7813
|
+
return;
|
|
7814
|
+
}
|
|
7815
|
+
await saveTaskAccessGrant(taskId, result.grant, result.expiresAt);
|
|
7816
|
+
printResult({ taskId, expiresAt: result.expiresAt });
|
|
7817
|
+
});
|
|
7818
|
+
|
|
7819
|
+
// src/commands/task/invite.ts
|
|
7820
|
+
import { Command as Command37 } from "commander";
|
|
7821
|
+
var inviteCmd = new Command37("invite").description("Invite a wallet to view a private task (requester only)").argument("<taskId>", "Task ID (0x-prefixed hex)").argument("<address>", "Wallet address to invite").action(async (taskId, address) => {
|
|
7822
|
+
const auth = await signReadAuth();
|
|
7823
|
+
if (!auth || Object.keys(auth.headers).length === 0) {
|
|
7824
|
+
printError("No keystore found. Run `taskmarket init` first.");
|
|
7825
|
+
return;
|
|
7826
|
+
}
|
|
7827
|
+
try {
|
|
7828
|
+
const result = await apiPost(
|
|
7829
|
+
`/api/tasks/${taskId}/private-access/viewers`,
|
|
7830
|
+
{ taskId, viewerAddress: address },
|
|
7831
|
+
{ headers: auth.headers }
|
|
7832
|
+
);
|
|
7833
|
+
printResult(result);
|
|
7834
|
+
} catch (err) {
|
|
7835
|
+
printError(err instanceof Error ? err.message : "Failed to invite viewer.");
|
|
7836
|
+
}
|
|
7837
|
+
});
|
|
7838
|
+
|
|
7839
|
+
// src/commands/task/uninvite.ts
|
|
7840
|
+
import { Command as Command38 } from "commander";
|
|
7841
|
+
var uninviteCmd = new Command38("uninvite").description("Remove a wallet from a private task's allowlist (requester only)").argument("<taskId>", "Task ID (0x-prefixed hex)").argument("<address>", "Wallet address to remove").action(async (taskId, address) => {
|
|
7842
|
+
const auth = await signReadAuth();
|
|
7843
|
+
if (!auth || Object.keys(auth.headers).length === 0) {
|
|
7844
|
+
printError("No keystore found. Run `taskmarket init` first.");
|
|
7845
|
+
return;
|
|
7846
|
+
}
|
|
7847
|
+
try {
|
|
7848
|
+
const result = await apiDelete(
|
|
7849
|
+
`/api/tasks/${taskId}/private-access/viewers/${encodeURIComponent(address)}`,
|
|
7850
|
+
{ headers: auth.headers }
|
|
7851
|
+
);
|
|
7852
|
+
printResult(result);
|
|
7853
|
+
} catch (err) {
|
|
7854
|
+
printError(err instanceof Error ? err.message : "Failed to remove viewer.");
|
|
7855
|
+
}
|
|
7856
|
+
});
|
|
7857
|
+
|
|
7858
|
+
// src/commands/task/viewers.ts
|
|
7859
|
+
import { Command as Command39 } from "commander";
|
|
7860
|
+
var viewersCmd = new Command39("viewers").description("List a private task's wallet allowlist (requester only)").argument("<taskId>", "Task ID (0x-prefixed hex)").action(async (taskId) => {
|
|
7861
|
+
const auth = await signReadAuth();
|
|
7862
|
+
if (!auth || Object.keys(auth.headers).length === 0) {
|
|
7863
|
+
printError("No keystore found. Run `taskmarket init` first.");
|
|
7864
|
+
return;
|
|
7865
|
+
}
|
|
7866
|
+
try {
|
|
7867
|
+
const result = await apiGet(`/api/tasks/${taskId}/private-access/viewers`, {
|
|
7868
|
+
headers: auth.headers
|
|
7869
|
+
});
|
|
7870
|
+
printResult(result);
|
|
7871
|
+
} catch (err) {
|
|
7872
|
+
printError(err instanceof Error ? err.message : "Failed to list viewers.");
|
|
7873
|
+
}
|
|
7874
|
+
});
|
|
7875
|
+
|
|
7611
7876
|
// src/commands/task/index.ts
|
|
7612
|
-
var taskCommand = new
|
|
7877
|
+
var taskCommand = new Command40("task").description("Manage tasks");
|
|
7613
7878
|
taskCommand.addCommand(createCmd);
|
|
7614
7879
|
taskCommand.addCommand(listCmd);
|
|
7615
7880
|
taskCommand.addCommand(getCmd);
|
|
@@ -7640,10 +7905,14 @@ taskCommand.addCommand(appealCmd);
|
|
|
7640
7905
|
taskCommand.addCommand(evaluatorTimeoutCmd);
|
|
7641
7906
|
taskCommand.addCommand(finalizeVerdictCmd);
|
|
7642
7907
|
taskCommand.addCommand(resolveDisputeCmd);
|
|
7908
|
+
taskCommand.addCommand(unlockCmd);
|
|
7909
|
+
taskCommand.addCommand(inviteCmd);
|
|
7910
|
+
taskCommand.addCommand(uninviteCmd);
|
|
7911
|
+
taskCommand.addCommand(viewersCmd);
|
|
7643
7912
|
|
|
7644
7913
|
// src/commands/agents.ts
|
|
7645
|
-
import { Command as
|
|
7646
|
-
var agentsCommand = new
|
|
7914
|
+
import { Command as Command41 } from "commander";
|
|
7915
|
+
var agentsCommand = new Command41("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) => {
|
|
7647
7916
|
const params = new URLSearchParams();
|
|
7648
7917
|
if (opts.sort) params.set("sort", opts.sort);
|
|
7649
7918
|
if (opts.skill) params.set("skill", opts.skill);
|
|
@@ -7654,8 +7923,8 @@ var agentsCommand = new Command37("agents").description("Browse the agent direct
|
|
|
7654
7923
|
});
|
|
7655
7924
|
|
|
7656
7925
|
// src/commands/inbox.ts
|
|
7657
|
-
import { Command as
|
|
7658
|
-
var inboxCommand = new
|
|
7926
|
+
import { Command as Command42 } from "commander";
|
|
7927
|
+
var inboxCommand = new Command42("inbox").description("Show tasks you created and tasks you are working on").action(async () => {
|
|
7659
7928
|
const auth = await signReadAuth();
|
|
7660
7929
|
if (!auth) {
|
|
7661
7930
|
printError("No keystore found. Run `taskmarket init` first.");
|
|
@@ -7675,8 +7944,8 @@ var inboxCommand = new Command38("inbox").description("Show tasks you created an
|
|
|
7675
7944
|
});
|
|
7676
7945
|
|
|
7677
7946
|
// src/commands/deposit.ts
|
|
7678
|
-
import { Command as
|
|
7679
|
-
var depositCommand = new
|
|
7947
|
+
import { Command as Command43 } from "commander";
|
|
7948
|
+
var depositCommand = new Command43("deposit").description("Show wallet address and network info for funding").action(async () => {
|
|
7680
7949
|
let address;
|
|
7681
7950
|
try {
|
|
7682
7951
|
address = await getWalletAddress();
|
|
@@ -7703,11 +7972,11 @@ var depositCommand = new Command39("deposit").description("Show wallet address a
|
|
|
7703
7972
|
});
|
|
7704
7973
|
|
|
7705
7974
|
// src/commands/wallet/index.ts
|
|
7706
|
-
import { Command as
|
|
7975
|
+
import { Command as Command49 } from "commander";
|
|
7707
7976
|
|
|
7708
7977
|
// src/commands/wallet/balance.ts
|
|
7709
|
-
import { Command as
|
|
7710
|
-
var walletBalanceCommand = new
|
|
7978
|
+
import { Command as Command44 } from "commander";
|
|
7979
|
+
var walletBalanceCommand = new Command44("balance").description("Show USDC balance").option("--address <addr>", "Address to check (defaults to own wallet)").action(async (opts) => {
|
|
7711
7980
|
let address = opts.address;
|
|
7712
7981
|
if (!address) {
|
|
7713
7982
|
const keystore = await loadKeystore();
|
|
@@ -7718,7 +7987,7 @@ var walletBalanceCommand = new Command40("balance").description("Show USDC balan
|
|
|
7718
7987
|
});
|
|
7719
7988
|
|
|
7720
7989
|
// src/commands/wallet/import.ts
|
|
7721
|
-
import { Command as
|
|
7990
|
+
import { Command as Command45 } from "commander";
|
|
7722
7991
|
import { createInterface as createInterface2 } from "readline";
|
|
7723
7992
|
import { privateKeyToAccount as privateKeyToAccount4 } from "viem/accounts";
|
|
7724
7993
|
function normalizePrivateKey(raw) {
|
|
@@ -7753,7 +8022,7 @@ function promptHiddenInput(prompt) {
|
|
|
7753
8022
|
});
|
|
7754
8023
|
});
|
|
7755
8024
|
}
|
|
7756
|
-
var walletImportCommand = new
|
|
8025
|
+
var walletImportCommand = new Command45("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)").option(
|
|
7757
8026
|
"--yes",
|
|
7758
8027
|
"Confirm legal acceptance non-interactively after reviewing every current policy"
|
|
7759
8028
|
).action(async (opts) => {
|
|
@@ -7832,11 +8101,11 @@ var walletImportCommand = new Command41("import").description("Import an existin
|
|
|
7832
8101
|
});
|
|
7833
8102
|
|
|
7834
8103
|
// src/commands/wallet/set-withdrawal-address.ts
|
|
7835
|
-
import { Command as
|
|
8104
|
+
import { Command as Command46 } from "commander";
|
|
7836
8105
|
function isValidAddress(addr) {
|
|
7837
8106
|
return /^0x[a-fA-F0-9]{40}$/.test(addr);
|
|
7838
8107
|
}
|
|
7839
|
-
var setWithdrawalAddressCommand = new
|
|
8108
|
+
var setWithdrawalAddressCommand = new Command46("set-withdrawal-address").description("Set a withdrawal address for USDC withdrawals (one-time, free)").argument("<address>", "Ethereum address to receive withdrawals").action(async (address) => {
|
|
7840
8109
|
if (!isValidAddress(address)) {
|
|
7841
8110
|
printError("Invalid Ethereum address: must be 0x followed by 40 hex characters");
|
|
7842
8111
|
}
|
|
@@ -7858,8 +8127,8 @@ var setWithdrawalAddressCommand = new Command42("set-withdrawal-address").descri
|
|
|
7858
8127
|
});
|
|
7859
8128
|
|
|
7860
8129
|
// src/commands/wallet/publish-key.ts
|
|
7861
|
-
import { Command as
|
|
7862
|
-
var publishKeyCommand = new
|
|
8130
|
+
import { Command as Command47 } from "commander";
|
|
8131
|
+
var publishKeyCommand = new Command47("publish-key").description("Publish your secp256k1 public key so others can encrypt files for you").action(async () => {
|
|
7863
8132
|
let keystore;
|
|
7864
8133
|
try {
|
|
7865
8134
|
keystore = await loadKeystore();
|
|
@@ -7878,13 +8147,13 @@ var publishKeyCommand = new Command43("publish-key").description("Publish your s
|
|
|
7878
8147
|
});
|
|
7879
8148
|
|
|
7880
8149
|
// src/commands/wallet/withdraw-dreams.ts
|
|
7881
|
-
import { Command as
|
|
8150
|
+
import { Command as Command48 } from "commander";
|
|
7882
8151
|
import { toHex as toHex2 } from "viem";
|
|
7883
8152
|
var AUTHORIZATION_VALIDITY_SECONDS = 300;
|
|
7884
8153
|
function isValidAddress2(addr) {
|
|
7885
8154
|
return /^0x[a-fA-F0-9]{40}$/.test(addr);
|
|
7886
8155
|
}
|
|
7887
|
-
var withdrawDreamsCommand = new
|
|
8156
|
+
var withdrawDreamsCommand = new Command48("withdraw-dreams").description("Withdraw accumulated DREAMS rewards to the withdrawal address").option("--destination <addr>", "Destination address (defaults to registered withdrawal address)").action(async (opts) => {
|
|
7888
8157
|
let keystore;
|
|
7889
8158
|
try {
|
|
7890
8159
|
keystore = await loadKeystore();
|
|
@@ -7929,7 +8198,7 @@ var withdrawDreamsCommand = new Command44("withdraw-dreams").description("Withdr
|
|
|
7929
8198
|
});
|
|
7930
8199
|
|
|
7931
8200
|
// src/commands/wallet/index.ts
|
|
7932
|
-
var walletCommand = new
|
|
8201
|
+
var walletCommand = new Command49("wallet").description("Wallet management commands");
|
|
7933
8202
|
walletCommand.addCommand(walletBalanceCommand);
|
|
7934
8203
|
walletCommand.addCommand(walletImportCommand);
|
|
7935
8204
|
walletCommand.addCommand(setWithdrawalAddressCommand);
|
|
@@ -7937,7 +8206,7 @@ walletCommand.addCommand(publishKeyCommand);
|
|
|
7937
8206
|
walletCommand.addCommand(withdrawDreamsCommand);
|
|
7938
8207
|
|
|
7939
8208
|
// src/commands/withdraw.ts
|
|
7940
|
-
import { Command as
|
|
8209
|
+
import { Command as Command50 } from "commander";
|
|
7941
8210
|
import { toHex as toHex3 } from "viem";
|
|
7942
8211
|
var USDC_TYPES = {
|
|
7943
8212
|
TransferWithAuthorization: [
|
|
@@ -7949,7 +8218,7 @@ var USDC_TYPES = {
|
|
|
7949
8218
|
{ name: "nonce", type: "bytes32" }
|
|
7950
8219
|
]
|
|
7951
8220
|
};
|
|
7952
|
-
var withdrawCommand = new
|
|
8221
|
+
var withdrawCommand = new Command50("withdraw").description("Withdraw USDC to the registered withdrawal address").argument("<amount>", "Amount in USDC (e.g. 5 for 5 USDC)").action(async (amount) => {
|
|
7953
8222
|
const parsed = parseFloat(amount);
|
|
7954
8223
|
if (isNaN(parsed) || parsed <= 0) {
|
|
7955
8224
|
printError("Invalid amount: must be a positive number (e.g. 5 for 5 USDC)");
|
|
@@ -7999,12 +8268,12 @@ var withdrawCommand = new Command46("withdraw").description("Withdraw USDC to th
|
|
|
7999
8268
|
});
|
|
8000
8269
|
|
|
8001
8270
|
// src/commands/encrypt.ts
|
|
8002
|
-
import { Command as
|
|
8003
|
-
import { promises as
|
|
8004
|
-
var encryptCommand = new
|
|
8271
|
+
import { Command as Command51 } from "commander";
|
|
8272
|
+
import { promises as fs3 } from "fs";
|
|
8273
|
+
var encryptCommand = new Command51("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) => {
|
|
8005
8274
|
let plaintext;
|
|
8006
8275
|
try {
|
|
8007
|
-
plaintext = await
|
|
8276
|
+
plaintext = await fs3.readFile(file);
|
|
8008
8277
|
} catch {
|
|
8009
8278
|
printError(`Cannot read file: ${file}`);
|
|
8010
8279
|
}
|
|
@@ -8041,7 +8310,7 @@ var encryptCommand = new Command47("encrypt").description("Encrypt a file with E
|
|
|
8041
8310
|
}
|
|
8042
8311
|
const encrypted = encryptForRecipient(plaintext, recipientPubKey);
|
|
8043
8312
|
const outputPath = opts.output ?? `${file}.enc`;
|
|
8044
|
-
await
|
|
8313
|
+
await fs3.writeFile(outputPath, encrypted);
|
|
8045
8314
|
printResult({
|
|
8046
8315
|
output: outputPath,
|
|
8047
8316
|
bytes: encrypted.length,
|
|
@@ -8050,12 +8319,12 @@ var encryptCommand = new Command47("encrypt").description("Encrypt a file with E
|
|
|
8050
8319
|
});
|
|
8051
8320
|
|
|
8052
8321
|
// src/commands/decrypt.ts
|
|
8053
|
-
import { Command as
|
|
8054
|
-
import { promises as
|
|
8055
|
-
var decryptCommand = new
|
|
8322
|
+
import { Command as Command52 } from "commander";
|
|
8323
|
+
import { promises as fs4 } from "fs";
|
|
8324
|
+
var decryptCommand = new Command52("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) => {
|
|
8056
8325
|
let ciphertext;
|
|
8057
8326
|
try {
|
|
8058
|
-
ciphertext = await
|
|
8327
|
+
ciphertext = await fs4.readFile(file);
|
|
8059
8328
|
} catch {
|
|
8060
8329
|
printError(`Cannot read file: ${file}`);
|
|
8061
8330
|
}
|
|
@@ -8082,7 +8351,7 @@ var decryptCommand = new Command48("decrypt").description("Decrypt a file using
|
|
|
8082
8351
|
} else {
|
|
8083
8352
|
outputPath = `${file}.dec`;
|
|
8084
8353
|
}
|
|
8085
|
-
await
|
|
8354
|
+
await fs4.writeFile(outputPath, plaintext);
|
|
8086
8355
|
printResult({
|
|
8087
8356
|
output: outputPath,
|
|
8088
8357
|
bytes: plaintext.length
|
|
@@ -8090,11 +8359,11 @@ var decryptCommand = new Command48("decrypt").description("Decrypt a file using
|
|
|
8090
8359
|
});
|
|
8091
8360
|
|
|
8092
8361
|
// src/commands/xmtp.ts
|
|
8093
|
-
import { Command as
|
|
8362
|
+
import { Command as Command53 } from "commander";
|
|
8094
8363
|
|
|
8095
8364
|
// src/lib/xmtp-client.ts
|
|
8096
|
-
import
|
|
8097
|
-
import
|
|
8365
|
+
import os3 from "os";
|
|
8366
|
+
import path3 from "path";
|
|
8098
8367
|
import { randomUUID as randomUUID2, hkdfSync as hkdfSync2 } from "crypto";
|
|
8099
8368
|
import { privateKeyToAccount as privateKeyToAccount5 } from "viem/accounts";
|
|
8100
8369
|
|
|
@@ -8249,11 +8518,11 @@ var XmtpTransportError = class extends Error {
|
|
|
8249
8518
|
}
|
|
8250
8519
|
};
|
|
8251
8520
|
function defaultXmtpDbDir() {
|
|
8252
|
-
return process.env.TASKMARKET_XMTP_DB_DIR ??
|
|
8521
|
+
return process.env.TASKMARKET_XMTP_DB_DIR ?? path3.join(os3.homedir(), ".taskmarket", "xmtp");
|
|
8253
8522
|
}
|
|
8254
8523
|
function defaultDbPath(walletAddress) {
|
|
8255
8524
|
const normalized = walletAddress.toLowerCase();
|
|
8256
|
-
return
|
|
8525
|
+
return path3.join(defaultXmtpDbDir(), `${normalized}.sqlite`);
|
|
8257
8526
|
}
|
|
8258
8527
|
async function createDevClient(input) {
|
|
8259
8528
|
const inboxId = input.existingInboxId ?? `dev-inbox-${input.walletAddress.slice(2, 10).toLowerCase()}`;
|
|
@@ -8854,7 +9123,7 @@ function getDefaultQueryTimeoutMs() {
|
|
|
8854
9123
|
}
|
|
8855
9124
|
return Math.floor(parsed);
|
|
8856
9125
|
}
|
|
8857
|
-
var xmtpCommand = new
|
|
9126
|
+
var xmtpCommand = new Command53("xmtp").description("Manage XMTP messaging for this agent");
|
|
8858
9127
|
xmtpCommand.command("init").description("Initialize XMTP client and register installation metadata with backend").action(async () => {
|
|
8859
9128
|
const keystore = await loadKeystore();
|
|
8860
9129
|
const client = await createXmtpClient({
|
|
@@ -9082,7 +9351,7 @@ xmtpCommand.command("purge").description("Revoke stale XMTP installations that h
|
|
|
9082
9351
|
});
|
|
9083
9352
|
|
|
9084
9353
|
// src/commands/daemon.ts
|
|
9085
|
-
import { Command as
|
|
9354
|
+
import { Command as Command54 } from "commander";
|
|
9086
9355
|
function diffTaskStatuses(prev, next) {
|
|
9087
9356
|
const changes = [];
|
|
9088
9357
|
for (const [taskId, newStatus] of next) {
|
|
@@ -9110,7 +9379,7 @@ function sleepOrAbort(ms, signal) {
|
|
|
9110
9379
|
});
|
|
9111
9380
|
}
|
|
9112
9381
|
var MAX_SEEN_TASK_IDS = 2e3;
|
|
9113
|
-
var daemonCommand = new
|
|
9382
|
+
var daemonCommand = new Command54("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", "15000").option(
|
|
9114
9383
|
"--auction-poll-interval <ms>",
|
|
9115
9384
|
"Poll interval for clock-based auction tasks (dutch/reverse_dutch) in milliseconds",
|
|
9116
9385
|
"15000"
|
|
@@ -9431,11 +9700,11 @@ var daemonCommand = new Command50("daemon").description("Long-running agent daem
|
|
|
9431
9700
|
);
|
|
9432
9701
|
|
|
9433
9702
|
// src/commands/email/index.ts
|
|
9434
|
-
import { Command as
|
|
9703
|
+
import { Command as Command63 } from "commander";
|
|
9435
9704
|
|
|
9436
9705
|
// src/commands/email/register.ts
|
|
9437
|
-
import { Command as
|
|
9438
|
-
var registerCommand = new
|
|
9706
|
+
import { Command as Command55 } from "commander";
|
|
9707
|
+
var registerCommand = new Command55("register").description("Register an email address for this agent").requiredOption("--username <name>", "Desired username (e.g. myagent)").action(async (opts) => {
|
|
9439
9708
|
const check = await apiGet(
|
|
9440
9709
|
`/api/emails/check-username?username=${encodeURIComponent(opts.username)}`
|
|
9441
9710
|
);
|
|
@@ -9452,8 +9721,8 @@ var registerCommand = new Command51("register").description("Register an email a
|
|
|
9452
9721
|
});
|
|
9453
9722
|
|
|
9454
9723
|
// src/commands/email/inbox.ts
|
|
9455
|
-
import { Command as
|
|
9456
|
-
var inboxCommand2 = new
|
|
9724
|
+
import { Command as Command56 } from "commander";
|
|
9725
|
+
var inboxCommand2 = new Command56("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) => {
|
|
9457
9726
|
const keystore = await loadKeystore();
|
|
9458
9727
|
const params = new URLSearchParams({
|
|
9459
9728
|
deviceId: keystore.deviceId,
|
|
@@ -9468,8 +9737,8 @@ var inboxCommand2 = new Command52("inbox").description("List emails in your inbo
|
|
|
9468
9737
|
});
|
|
9469
9738
|
|
|
9470
9739
|
// src/commands/email/read.ts
|
|
9471
|
-
import { Command as
|
|
9472
|
-
var readCommand = new
|
|
9740
|
+
import { Command as Command57 } from "commander";
|
|
9741
|
+
var readCommand = new Command57("read").description("Read an email by ID (marks it as read)").argument("<id>", "Email ID").action(async (id) => {
|
|
9473
9742
|
const keystore = await loadKeystore();
|
|
9474
9743
|
const params = new URLSearchParams({
|
|
9475
9744
|
deviceId: keystore.deviceId,
|
|
@@ -9481,8 +9750,8 @@ var readCommand = new Command53("read").description("Read an email by ID (marks
|
|
|
9481
9750
|
});
|
|
9482
9751
|
|
|
9483
9752
|
// src/commands/email/send.ts
|
|
9484
|
-
import { Command as
|
|
9485
|
-
var sendCommand = new
|
|
9753
|
+
import { Command as Command58 } from "commander";
|
|
9754
|
+
var sendCommand = new Command58("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) => {
|
|
9486
9755
|
const keystore = await loadKeystore();
|
|
9487
9756
|
const result = await apiPost("/api/emails/send", {
|
|
9488
9757
|
deviceId: keystore.deviceId,
|
|
@@ -9495,8 +9764,8 @@ var sendCommand = new Command54("send").description("Send an email").requiredOpt
|
|
|
9495
9764
|
});
|
|
9496
9765
|
|
|
9497
9766
|
// src/commands/email/reply.ts
|
|
9498
|
-
import { Command as
|
|
9499
|
-
var replyCommand = new
|
|
9767
|
+
import { Command as Command59 } from "commander";
|
|
9768
|
+
var replyCommand = new Command59("reply").description("Reply to an email").argument("<id>", "Email ID to reply to").requiredOption("--body <text>", "Reply body text").action(async (id, opts) => {
|
|
9500
9769
|
const keystore = await loadKeystore();
|
|
9501
9770
|
const params = new URLSearchParams({
|
|
9502
9771
|
deviceId: keystore.deviceId,
|
|
@@ -9518,8 +9787,8 @@ var replyCommand = new Command55("reply").description("Reply to an email").argum
|
|
|
9518
9787
|
});
|
|
9519
9788
|
|
|
9520
9789
|
// src/commands/email/delete.ts
|
|
9521
|
-
import { Command as
|
|
9522
|
-
var deleteCommand = new
|
|
9790
|
+
import { Command as Command60 } from "commander";
|
|
9791
|
+
var deleteCommand = new Command60("delete").description("Delete an email by ID").argument("<id>", "Email ID").action(async (id) => {
|
|
9523
9792
|
const keystore = await loadKeystore();
|
|
9524
9793
|
const result = await apiPost("/api/emails/delete", {
|
|
9525
9794
|
deviceId: keystore.deviceId,
|
|
@@ -9530,15 +9799,15 @@ var deleteCommand = new Command56("delete").description("Delete an email by ID")
|
|
|
9530
9799
|
});
|
|
9531
9800
|
|
|
9532
9801
|
// src/commands/email/address.ts
|
|
9533
|
-
import { Command as
|
|
9534
|
-
var addressCommand2 = new
|
|
9802
|
+
import { Command as Command61 } from "commander";
|
|
9803
|
+
var addressCommand2 = new Command61("address").description("Show your registered email address").action(async () => {
|
|
9535
9804
|
const keystore = await loadKeystore();
|
|
9536
9805
|
const result = await apiGet(`/api/agents/stats?address=${keystore.walletAddress}`);
|
|
9537
9806
|
printResult({ emailAddress: result.emailAddress ?? null });
|
|
9538
9807
|
});
|
|
9539
9808
|
|
|
9540
9809
|
// src/commands/email/mark-read.ts
|
|
9541
|
-
import { Command as
|
|
9810
|
+
import { Command as Command62 } from "commander";
|
|
9542
9811
|
async function setReadStatus(id, read) {
|
|
9543
9812
|
const keystore = await loadKeystore();
|
|
9544
9813
|
const result = await apiPost("/api/emails/mark-read", {
|
|
@@ -9549,12 +9818,12 @@ async function setReadStatus(id, read) {
|
|
|
9549
9818
|
});
|
|
9550
9819
|
printResult({ id: result.id, isRead: result.isRead });
|
|
9551
9820
|
}
|
|
9552
|
-
var markReadCommand = new
|
|
9821
|
+
var markReadCommand = new Command62("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) => {
|
|
9553
9822
|
await setReadStatus(id, !opts.unread);
|
|
9554
9823
|
});
|
|
9555
9824
|
|
|
9556
9825
|
// src/commands/email/index.ts
|
|
9557
|
-
var emailCommand = new
|
|
9826
|
+
var emailCommand = new Command63("email").description("Email management commands");
|
|
9558
9827
|
emailCommand.addCommand(registerCommand);
|
|
9559
9828
|
emailCommand.addCommand(inboxCommand2);
|
|
9560
9829
|
emailCommand.addCommand(readCommand);
|
|
@@ -9565,11 +9834,11 @@ emailCommand.addCommand(addressCommand2);
|
|
|
9565
9834
|
emailCommand.addCommand(markReadCommand);
|
|
9566
9835
|
|
|
9567
9836
|
// src/commands/requester/index.ts
|
|
9568
|
-
import { Command as
|
|
9837
|
+
import { Command as Command65 } from "commander";
|
|
9569
9838
|
|
|
9570
9839
|
// src/commands/requester/stats.ts
|
|
9571
|
-
import { Command as
|
|
9572
|
-
var requesterStatsCmd = new
|
|
9840
|
+
import { Command as Command64 } from "commander";
|
|
9841
|
+
var requesterStatsCmd = new Command64("stats").description("Get requester reputation stats for an address").argument("<address>", "Wallet address of the requester").action(async (address) => {
|
|
9573
9842
|
if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {
|
|
9574
9843
|
printError("Address must be a 0x-prefixed 20-byte hex string");
|
|
9575
9844
|
process.exit(1);
|
|
@@ -9585,12 +9854,12 @@ var requesterStatsCmd = new Command60("stats").description("Get requester reputa
|
|
|
9585
9854
|
});
|
|
9586
9855
|
|
|
9587
9856
|
// src/commands/requester/index.ts
|
|
9588
|
-
var requesterCmd = new
|
|
9857
|
+
var requesterCmd = new Command65("requester").description("Requester reputation commands").addCommand(requesterStatsCmd);
|
|
9589
9858
|
|
|
9590
9859
|
// src/index.ts
|
|
9591
9860
|
var require2 = createRequire(import.meta.url);
|
|
9592
9861
|
var { version } = require2("../package.json");
|
|
9593
|
-
var program = new
|
|
9862
|
+
var program = new Command66();
|
|
9594
9863
|
program.name("taskmarket").description("Taskmarket CLI for AI agents").version(version);
|
|
9595
9864
|
program.addCommand(initCommand);
|
|
9596
9865
|
program.addCommand(walletCommand);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lucid-agents/taskmarket",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"taskmarket": "./dist/index.js"
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"tsx": "^4.7.0",
|
|
18
18
|
"typescript": "^5.3.3",
|
|
19
19
|
"vitest": "^2.0.0",
|
|
20
|
-
"@taskmarket/prettier-config": "0.0.0",
|
|
21
20
|
"@taskmarket/eslint-config": "0.0.0",
|
|
21
|
+
"@taskmarket/prettier-config": "0.0.0",
|
|
22
22
|
"@taskmarket/shared": "2.0.0"
|
|
23
23
|
},
|
|
24
24
|
"files": [
|