@lucid-agents/taskmarket 1.21.0 → 1.22.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 CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  signReadAuth,
15
15
  submitTaskFiles,
16
16
  taskAccessGrantHeaders
17
- } from "./chunk-5N25NATR.js";
17
+ } from "./chunk-7MXTPGES.js";
18
18
  import {
19
19
  ComputeCreditError,
20
20
  applyComputeCreditSetup,
@@ -36,7 +36,7 @@ import {
36
36
  refusedPaidWrite,
37
37
  releasePendingComputePurchase,
38
38
  resolvePendingComputePurchases
39
- } from "./chunk-TAMXCFLT.js";
39
+ } from "./chunk-RSSJD6JU.js";
40
40
  import {
41
41
  MPP_TEMPO_DEFAULT_VALIDITY_SECONDS,
42
42
  X402PayError,
@@ -58,17 +58,25 @@ import {
58
58
  signSponsoredTempoTransfer,
59
59
  signTaskmarketFeePayment,
60
60
  signTypedData
61
- } from "./chunk-HE2N4GEO.js";
61
+ } from "./chunk-BO3XPXQ6.js";
62
62
  import {
63
+ ActivityFeedInputSchema,
64
+ ActivityHeatmapInputSchema,
65
+ ActorType,
63
66
  AgentMessageEnvelopeSchema,
67
+ AgentTimeSeriesInputSchema,
64
68
  ApiError,
65
69
  BUG_REPORT_SEVERITIES,
66
70
  BUG_REPORT_STATUSES,
67
71
  BUG_REPORT_VISIBILITIES,
68
72
  BugReportMessageBodySchema,
73
+ CrossChainFundingConfigOutputSchema,
69
74
  DEFAULT_EVALUATION_WINDOW_HOURS,
70
75
  DEFAULT_TERMS_BOUNDS,
76
+ HookGetInputSchema,
77
+ HookIndexInputSchema,
71
78
  IntentStatusResponseSchema,
79
+ KeystoreExistsError,
72
80
  LegalAcceptanceResponseSchema,
73
81
  LegalBundleSchema,
74
82
  LegalChallengeResponseSchema,
@@ -78,11 +86,15 @@ import {
78
86
  NetworkRequiredError,
79
87
  PUBLIC_BUG_REPORT_SORTS,
80
88
  PenaltyTo,
89
+ PlatformTimeSeriesInputSchema,
81
90
  PostBugReportMessageInputSchema,
82
91
  READ_AUTH_ADDRESS_HEADER,
83
92
  READ_AUTH_SIGNATURE_HEADER,
84
93
  REDACTED,
94
+ RELAY_BRIDGE_ROUTES,
85
95
  RejectOutcome,
96
+ RelayBridgeFundingConfigOutputSchema,
97
+ RelayBridgeRouteIdSchema,
86
98
  SponsoredTaskRewardStateSchema,
87
99
  SponsoredTaskWorkerRewardClaimStatusSchema,
88
100
  SubmissionReviewAssessmentInputSchema,
@@ -103,6 +115,12 @@ import {
103
115
  SubmissionReviewStartPayloadSchema,
104
116
  SubmissionReviewTaskInputSchema,
105
117
  SubmitBugReportInputSchema,
118
+ TaskDropDirectoryInputSchema,
119
+ TaskDropGetInputSchema,
120
+ TaskDropOfficialStatusInputSchema,
121
+ TaskDropOfficialSubscribeInputSchema,
122
+ TaskDropStatusInputSchema,
123
+ TaskDropSubscribeInputSchema,
106
124
  TaskTermsError,
107
125
  TermsPresetName,
108
126
  WALLET_BRIDGE_ORIGIN_CHAIN_ID,
@@ -131,6 +149,7 @@ import {
131
149
  chainInfoFor,
132
150
  claimStakeToPost,
133
151
  clientValidityWindowSeconds,
152
+ createKeystore,
134
153
  decryptPrivateKey,
135
154
  dreamsToUsd,
136
155
  encryptPrivateKey,
@@ -157,6 +176,7 @@ import {
157
176
  readFailureBody,
158
177
  readKeystoreNetwork,
159
178
  redactSecrets,
179
+ relayBridgeRoute,
160
180
  resolveIdempotencyKey,
161
181
  resolveNetwork,
162
182
  resolveTaskTerms,
@@ -172,14 +192,14 @@ import {
172
192
  withChainId,
173
193
  withErrorContext,
174
194
  withIdempotentWrite
175
- } from "./chunk-3IIVNF5F.js";
195
+ } from "./chunk-H2HOWIJ6.js";
176
196
  import {
177
197
  channelLines
178
198
  } from "./chunk-XJOB4NMV.js";
179
199
  import "./chunk-S7SJMJ2I.js";
180
200
 
181
201
  // src/index.ts
182
- import { Command as Command109 } from "commander";
202
+ import { Command as Command113 } from "commander";
183
203
  import { createRequire } from "module";
184
204
 
185
205
  // src/commands/init.ts
@@ -369,10 +389,32 @@ async function registerDevice(input) {
369
389
  });
370
390
  if (!response.ok) {
371
391
  const text = await response.text().catch(() => "");
392
+ const limited = sponsoredMintRateLimitMessage(
393
+ response.status,
394
+ text,
395
+ response.headers.get("retry-after")
396
+ );
397
+ if (limited) throw new Error(limited);
372
398
  throw new Error(`Device registration failed (${response.status}): ${text}`);
373
399
  }
374
400
  return await response.json();
375
401
  }
402
+ function sponsoredMintRateLimitMessage(status, body, retryAfter) {
403
+ let parsed = body;
404
+ if (typeof body === "string") {
405
+ try {
406
+ parsed = JSON.parse(body);
407
+ } catch {
408
+ parsed = void 0;
409
+ }
410
+ }
411
+ const envelope = parsed;
412
+ if (status !== 429 && envelope?.taskmarket?.reason !== "rate_limited") return void 0;
413
+ const seconds = Number(retryAfter);
414
+ const wait = Number.isFinite(seconds) && seconds > 0 ? `Retry after ${seconds} seconds.` : "Retry later.";
415
+ const detail = envelope?.message ?? envelope?.error?.message;
416
+ return `Sponsored identity registration is rate limited (rate_limited). ${detail ? `${detail} ` : ""}${wait}`.trim();
417
+ }
376
418
 
377
419
  // src/lib/encryption.ts
378
420
  import { createECDH, hkdfSync, createCipheriv, createDecipheriv, randomBytes } from "crypto";
@@ -692,7 +734,7 @@ var initCommand = new Command2("init").description(
692
734
  });
693
735
  const encryptedKey = encryptPrivateKey(deviceEncryptionKey, privateKey);
694
736
  let agentId = initialAgentId;
695
- await saveKeystore({
737
+ const newKeystore = {
696
738
  encryptedKey,
697
739
  walletAddress: address,
698
740
  deviceId,
@@ -706,7 +748,18 @@ var initCommand = new Command2("init").description(
706
748
  legalAcceptanceBundleVersion: legalAcceptance.bundleVersion,
707
749
  legalAcceptanceReceipt: legalAcceptance.receipt
708
750
  } : {}
709
- });
751
+ };
752
+ const created = await createKeystore(newKeystore).then(
753
+ () => true,
754
+ (error) => {
755
+ if (error instanceof KeystoreExistsError) return false;
756
+ throw error;
757
+ }
758
+ );
759
+ if (!created) {
760
+ printError(existingWalletMessage());
761
+ return;
762
+ }
710
763
  if (!agentId) {
711
764
  agentId = await pollAgentId(address);
712
765
  if (agentId) {
@@ -762,11 +815,26 @@ identityCommand.command("register").description(
762
815
  printResult({ agentId: stored, alreadyRegistered: true, chainId });
763
816
  return;
764
817
  }
765
- const { data, idempotencyKey } = await apiPost(`/api/devices/${encodeURIComponent(keystore.deviceId)}/identity`, {
766
- deviceId: keystore.deviceId,
767
- apiToken: keystore.apiToken,
768
- chainId
769
- });
818
+ let posted;
819
+ try {
820
+ posted = await apiPost(
821
+ `/api/devices/${encodeURIComponent(keystore.deviceId)}/identity`,
822
+ { deviceId: keystore.deviceId, apiToken: keystore.apiToken, chainId }
823
+ );
824
+ } catch (error) {
825
+ if (error instanceof ApiError) {
826
+ const limited = sponsoredMintRateLimitMessage(
827
+ error.status,
828
+ error.envelope ?? error.message
829
+ );
830
+ if (limited) {
831
+ renderFailure(new ApiError(error.status, limited, error.idempotencyKey, error.envelope));
832
+ return;
833
+ }
834
+ }
835
+ throw error;
836
+ }
837
+ const { data, idempotencyKey } = posted;
770
838
  const agentId = data.agentId ?? await pollAgentId(keystore.walletAddress);
771
839
  if (agentId) {
772
840
  await saveKeystore(withAgentIdForChain(await loadKeystore(), chainId, agentId));
@@ -840,7 +908,91 @@ var whoamiCommand = new Command5("whoami").description(
840
908
 
841
909
  // src/commands/stats.ts
842
910
  import { Command as Command6 } from "commander";
843
- var statsCommand = new Command6("stats").description("View agent statistics on the selected --network").option("--address <addr>", "Wallet address (defaults to own wallet)").option("--agent <agentId>", "Agent ID (alternative to --address)").action(async (opts) => {
911
+
912
+ // src/lib/parse-input.ts
913
+ function parseInput(schema, input) {
914
+ const result = schema.safeParse(input);
915
+ if (!result.success) {
916
+ const detail = result.error.issues.map((issue) => (issue.path.length > 0 ? `${issue.path.join(".")}: ` : "") + issue.message).join("; ");
917
+ throw new Error(`Invalid input: ${detail}`);
918
+ }
919
+ return result.data;
920
+ }
921
+ function optionalInt(value) {
922
+ if (value === void 0) return void 0;
923
+ const parsed = Number(value);
924
+ return Number.isInteger(parsed) ? parsed : Number.NaN;
925
+ }
926
+
927
+ // src/commands/stats.ts
928
+ function query(values) {
929
+ const params = new URLSearchParams();
930
+ for (const [key, value] of Object.entries(values)) {
931
+ if (value !== void 0) params.set(key, String(value));
932
+ }
933
+ return params.toString();
934
+ }
935
+ async function platformView(opts) {
936
+ const views = [opts.platform, opts.activity, opts.heatmap, opts.series].filter(Boolean).length;
937
+ if (views === 0) return false;
938
+ if (views > 1) {
939
+ throw new Error("Pass only one of --platform, --activity, --heatmap or --series");
940
+ }
941
+ if (opts.platform) {
942
+ const input2 = parseInput(PlatformTimeSeriesInputSchema, {
943
+ range: opts.range,
944
+ bucket: opts.bucket
945
+ });
946
+ const [market, breakdowns, timeSeries] = await Promise.all([
947
+ apiGet(withChainId("/api/market/stats")),
948
+ apiGet(withChainId("/api/stats/breakdowns")),
949
+ apiGet(withChainId(`/api/stats/platform-time-series?${query(input2)}`))
950
+ ]);
951
+ printResult({ chainId: selectedNetwork().chainId, market, breakdowns, timeSeries });
952
+ return true;
953
+ }
954
+ if (opts.activity) {
955
+ const input2 = parseInput(ActivityFeedInputSchema, {
956
+ limit: optionalInt(opts.limit),
957
+ cursor: opts.cursor
958
+ });
959
+ printResult(
960
+ await apiGet(
961
+ withChainId(
962
+ `/api/stats/activity-feed?${query({ limit: input2.limit, cursor: input2.cursor })}`
963
+ )
964
+ )
965
+ );
966
+ return true;
967
+ }
968
+ if (opts.heatmap) {
969
+ const input2 = parseInput(ActivityHeatmapInputSchema, {
970
+ range: opts.range,
971
+ dimension: opts.dimension
972
+ });
973
+ printResult(await apiGet(withChainId(`/api/stats/activity-heatmap?${query(input2)}`)));
974
+ return true;
975
+ }
976
+ let address = opts.address;
977
+ if (!address && !opts.agent) {
978
+ address = (await loadKeystore()).walletAddress;
979
+ }
980
+ const input = parseInput(AgentTimeSeriesInputSchema, {
981
+ address: opts.agent ? void 0 : address,
982
+ agentId: opts.agent,
983
+ range: opts.range,
984
+ bucket: opts.bucket
985
+ });
986
+ printResult(await apiGet(withChainId(`/api/stats/agent-time-series?${query(input)}`)));
987
+ return true;
988
+ }
989
+ var statsCommand = new Command6("stats").description("View agent or platform-wide statistics on the selected --network").option("--address <addr>", "Wallet address (defaults to own wallet)").option("--agent <agentId>", "Agent ID (alternative to --address)").option("--platform", "Platform-wide market stats, breakdowns and time series").option("--activity", "Recent platform activity feed").option("--heatmap", "Market activity heat map").option("--series", "An agent's earnings, ratings and activity time series").option("--range <range>", "Time range for --platform, --heatmap, --series: 7d, 30d, 90d or all").option("--bucket <bucket>", "Bucket for --platform and --series: day or week").option("--dimension <dimension>", "Heat map dimension for --heatmap: mode or hourOfWeek").option("--limit <n>", "Items for --activity (1-50)").option("--cursor <cursor>", "nextCursor from a previous --activity page").action(async (opts) => {
990
+ try {
991
+ if (await platformView(opts)) return;
992
+ } catch (err) {
993
+ renderFailure(err);
994
+ return;
995
+ }
844
996
  let address = opts.address;
845
997
  if (!address) {
846
998
  const keystore = await loadKeystore();
@@ -883,7 +1035,12 @@ var statsCommand = new Command6("stats").description("View agent statistics on t
883
1035
  ratedTasks: result.ratedTasks,
884
1036
  averageRating: result.averageRating,
885
1037
  credibility: result.credibility,
1038
+ // Paid on the selected chain, in its token; earningsByChain lists every chain where the
1039
+ // wallet earned, each in its own token, never summed.
886
1040
  totalEarnings: result.totalEarnings,
1041
+ earningsChainId: selectedNetwork().chainId,
1042
+ earningsToken: paymentTokenSymbol(selectedNetwork().chainId),
1043
+ earningsByChain: result.earningsByChain ?? [],
887
1044
  skills: result.skills,
888
1045
  emailAddress: result.emailAddress,
889
1046
  recentRatings: result.recentRatings
@@ -908,7 +1065,7 @@ var correctionOutput = z.object({
908
1065
  correctionId: z.string().uuid(),
909
1066
  createdAt: z.string().datetime()
910
1067
  });
911
- var query = (values) => {
1068
+ var query2 = (values) => {
912
1069
  const params = new URLSearchParams();
913
1070
  for (const [key, value] of Object.entries(values))
914
1071
  if (value !== void 0) params.set(key, String(value));
@@ -968,7 +1125,7 @@ function createSubmissionReviewClient(options) {
968
1125
  async profile(input) {
969
1126
  const { taskId, ...params } = SubmissionReviewTaskInputSchema.parse(input);
970
1127
  return get(
971
- `${taskPath(taskId)}/submission-review-profile${query(params)}`,
1128
+ `${taskPath(taskId)}/submission-review-profile${query2(params)}`,
972
1129
  SubmissionReviewProfileOutputSchema
973
1130
  );
974
1131
  },
@@ -1011,12 +1168,12 @@ function createSubmissionReviewClient(options) {
1011
1168
  },
1012
1169
  async status(input) {
1013
1170
  const { runId, ...params } = SubmissionReviewRunInputSchema.parse(input);
1014
- return get(`${runPath(runId)}${query(params)}`, SubmissionReviewRunSummarySchema);
1171
+ return get(`${runPath(runId)}${query2(params)}`, SubmissionReviewRunSummarySchema);
1015
1172
  },
1016
1173
  async lookup(input) {
1017
1174
  const { idempotencyKey, ...params } = SubmissionReviewLookupInputSchema.parse(input);
1018
1175
  return get(
1019
- `/api/submission-review-requests/${idempotencyKey}${query(params)}`,
1176
+ `/api/submission-review-requests/${idempotencyKey}${query2(params)}`,
1020
1177
  SubmissionReviewRunSummarySchema
1021
1178
  );
1022
1179
  },
@@ -1035,7 +1192,7 @@ function createSubmissionReviewClient(options) {
1035
1192
  async results(input) {
1036
1193
  const { taskId, ...params } = SubmissionReviewResultsInputSchema.parse(input);
1037
1194
  return get(
1038
- `${taskPath(taskId)}/submission-review-results${query(params)}`,
1195
+ `${taskPath(taskId)}/submission-review-results${query2(params)}`,
1039
1196
  SubmissionReviewResultsOutputSchema
1040
1197
  );
1041
1198
  },
@@ -1067,14 +1224,14 @@ function createSubmissionReviewClient(options) {
1067
1224
  async history(input) {
1068
1225
  const { taskId, ...params } = SubmissionReviewHistoryInputSchema.parse(input);
1069
1226
  return get(
1070
- `${taskPath(taskId)}/submission-reviews${query(params)}`,
1227
+ `${taskPath(taskId)}/submission-reviews${query2(params)}`,
1071
1228
  SubmissionReviewHistoryOutputSchema
1072
1229
  );
1073
1230
  },
1074
1231
  async assessment(input) {
1075
1232
  const { runId, submissionId, ...params } = SubmissionReviewAssessmentInputSchema.parse(input);
1076
1233
  return get(
1077
- `${runPath(runId)}/assessments/${encodeURIComponent(submissionId)}${query(params)}`,
1234
+ `${runPath(runId)}/assessments/${encodeURIComponent(submissionId)}${query2(params)}`,
1078
1235
  SubmissionReviewAssessmentOutputSchema
1079
1236
  );
1080
1237
  },
@@ -3487,7 +3644,7 @@ async function runAgentCommand(options) {
3487
3644
  try {
3488
3645
  const { assertAgentCompatibility } = await import("./compatibility-636WJOEX.js");
3489
3646
  const pi = assertAgentCompatibility();
3490
- const { runAgent } = await import("./launch-QDCWAIKE.js");
3647
+ const { runAgent } = await import("./launch-UUW34PHS.js");
3491
3648
  result = await runAgent({
3492
3649
  model: options.model,
3493
3650
  pi,
@@ -3546,13 +3703,13 @@ function agentManagementCommands() {
3546
3703
  const status = new Command48("status").description(
3547
3704
  "Show the agent channels (locked, charged, refundable), purchases with an unknown outcome, the sandbox and compute credit. Reads only."
3548
3705
  ).option("--json", "Print the versioned JSON envelope").action(async (options) => {
3549
- const { collectAgentStatus, statusLines } = await import("./status-FTTQWS5P.js");
3706
+ const { collectAgentStatus, statusLines } = await import("./status-5AVXIFQJ.js");
3550
3707
  await run(options, () => collectAgentStatus(), statusLines);
3551
3708
  });
3552
3709
  const doctor = new Command48("doctor").description(
3553
3710
  "Check that the agent can start: Node and the bundled runtime, wallet and policy, channels, API, sandbox broker, host keys, xgate and RPC. Reads only."
3554
3711
  ).option("--json", "Print the versioned JSON envelope").action(async (options) => {
3555
- const { runDoctor, doctorLines } = await import("./doctor-26YOWQOH.js");
3712
+ const { runDoctor, doctorLines } = await import("./doctor-MZUDBF4B.js");
3556
3713
  const report = await run(options, () => runDoctor(), doctorLines);
3557
3714
  if (report && !report.ok) process.exitCode = 1;
3558
3715
  });
@@ -3563,7 +3720,7 @@ function agentManagementCommands() {
3563
3720
  "Reconcile the open purchases of this channel, as status lists it; also reaches retired channels"
3564
3721
  ).option("--json", "Print the versioned JSON envelope").action(
3565
3722
  async (invocationId, options) => {
3566
- const { reconcileChannelPurchases, reconcileInvocation } = await import("./reconcile-MALCM3NB.js");
3723
+ const { reconcileChannelPurchases, reconcileInvocation } = await import("./reconcile-NDPFPJEB.js");
3567
3724
  const choice = { rail: options.rail, channel: options.channel };
3568
3725
  if (invocationId !== void 0) {
3569
3726
  await run(
@@ -3621,7 +3778,7 @@ function agentManagementCommands() {
3621
3778
  `Not a USDC amount: ${options.amount} (digits, at most 6 decimals)`
3622
3779
  );
3623
3780
  }
3624
- const { openAgentChannels, requestTopUp, selectRail, withdrawalHatch } = await import("./channels-OBJUNCZX.js");
3781
+ const { openAgentChannels, requestTopUp, selectRail, withdrawalHatch } = await import("./channels-NUZWFG26.js");
3625
3782
  const { rails } = await openAgentChannels();
3626
3783
  const result = await requestTopUp(selectRail(rails, options.rail), amount);
3627
3784
  return {
@@ -3645,8 +3802,8 @@ function agentManagementCommands() {
3645
3802
  async () => {
3646
3803
  await requireExperimental();
3647
3804
  const { AGENT_VIEW_VERSION } = await import("./budget-view-J6L7X6EY.js");
3648
- const { closeChannel, openAgentChannels, selectChannel } = await import("./channels-OBJUNCZX.js");
3649
- const { reconcileLeasedPurchase } = await import("./reconcile-MALCM3NB.js");
3805
+ const { closeChannel, openAgentChannels, selectChannel } = await import("./channels-NUZWFG26.js");
3806
+ const { reconcileLeasedPurchase } = await import("./reconcile-NDPFPJEB.js");
3650
3807
  const opened = await openAgentChannels();
3651
3808
  const { rail, retired } = selectChannel(opened, options);
3652
3809
  const result = await closeChannel(
@@ -3717,7 +3874,7 @@ function agentManagementCommands() {
3717
3874
  options,
3718
3875
  async () => {
3719
3876
  await requireExperimental();
3720
- const { runPull } = await import("./sync-pull-N6OTHBWR.js");
3877
+ const { runPull } = await import("./sync-pull-FHKF7A44.js");
3721
3878
  const { terminalPrompter } = await import("./prompter-LSICEYSQ.js");
3722
3879
  return runPull(options, {
3723
3880
  interactive: Boolean(process.stdin.isTTY && process.stdout.isTTY) && !options.json,
@@ -3780,16 +3937,36 @@ for (const command of agentManagementCommands()) {
3780
3937
 
3781
3938
  // src/commands/agents.ts
3782
3939
  import { Command as Command50 } from "commander";
3783
- var agentsCommand = new Command50("agents").description("Browse the agent directory on the selected --network").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) => {
3784
- const params = new URLSearchParams();
3785
- if (opts.sort) params.set("sort", opts.sort);
3786
- if (opts.skill) params.set("skill", opts.skill);
3787
- if (opts.search) params.set("search", opts.search);
3788
- if (opts.limit) params.set("limit", opts.limit);
3789
- params.set("chainId", String(selectedNetwork().chainId));
3790
- const result = await apiGet(`/api/agents/leaderboard?${params.toString()}`);
3791
- printResult(result);
3792
- });
3940
+ var agentsCommand = new Command50("agents").description("Browse the agent directory on the selected --network").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").option(
3941
+ "--kind <kind>",
3942
+ "Filter by actor kind: agent, human (the web humans directory) or hosted"
3943
+ ).action(
3944
+ async (opts) => {
3945
+ let kind;
3946
+ try {
3947
+ kind = opts.kind === void 0 ? void 0 : parseInput(ActorType, opts.kind);
3948
+ } catch (err) {
3949
+ renderFailure(err);
3950
+ return;
3951
+ }
3952
+ const params = new URLSearchParams();
3953
+ if (opts.sort) params.set("sort", opts.sort);
3954
+ if (opts.skill) params.set("skill", opts.skill);
3955
+ if (opts.search) params.set("search", opts.search);
3956
+ if (opts.limit) params.set("limit", opts.limit);
3957
+ if (kind) params.set("actorType", kind);
3958
+ const { chainId } = selectedNetwork();
3959
+ params.set("chainId", String(chainId));
3960
+ const result = await apiGet(`/api/agents/leaderboard?${params.toString()}`);
3961
+ printResult(
3962
+ Array.isArray(result) ? result.map((entry) => ({
3963
+ ...entry,
3964
+ earningsChainId: chainId,
3965
+ earningsToken: paymentTokenSymbol(chainId)
3966
+ })) : result
3967
+ );
3968
+ }
3969
+ );
3793
3970
 
3794
3971
  // src/commands/inbox.ts
3795
3972
  import { Command as Command51 } from "commander";
@@ -3830,7 +4007,94 @@ var actionsCommand = new Command52("actions").description("Show lifecycle action
3830
4007
 
3831
4008
  // src/commands/deposit.ts
3832
4009
  import { Command as Command53 } from "commander";
3833
- var depositCommand = new Command53("deposit").description("Show wallet address and network info for funding").action(async () => {
4010
+
4011
+ // src/lib/relay-bridge.ts
4012
+ import { z as z3 } from "zod";
4013
+ var RELAY_API_BASE_URL = "https://api.relay.link";
4014
+ var RelayQuoteResponseSchema = z3.object({
4015
+ requestId: z3.string().min(1),
4016
+ steps: z3.array(
4017
+ z3.object({
4018
+ depositAddress: z3.string().regex(/^0x[a-fA-F0-9]{40}$/).optional()
4019
+ })
4020
+ ).optional(),
4021
+ details: z3.object({
4022
+ currencyOut: z3.object({
4023
+ amount: z3.string().regex(/^[0-9]+$/).optional()
4024
+ }).optional()
4025
+ }).optional()
4026
+ });
4027
+ async function requestRelayBridgeDepositAddress(request, fetchImpl = fetch) {
4028
+ const route = relayBridgeRoute(request.routeId);
4029
+ const res = await fetchImpl(`${RELAY_API_BASE_URL}/quote`, {
4030
+ method: "POST",
4031
+ headers: { "Content-Type": "application/json" },
4032
+ body: JSON.stringify({
4033
+ user: request.recipient,
4034
+ recipient: request.recipient,
4035
+ originChainId: route.origin.chainId,
4036
+ originCurrency: route.origin.currency,
4037
+ destinationChainId: route.destination.chainId,
4038
+ destinationCurrency: route.destination.currency,
4039
+ amount: request.amountBaseUnits,
4040
+ tradeType: "EXACT_INPUT",
4041
+ useDepositAddress: true
4042
+ })
4043
+ });
4044
+ if (!res.ok) {
4045
+ throw new Error(`Relay quote request failed: ${res.status}`);
4046
+ }
4047
+ const parsed = RelayQuoteResponseSchema.safeParse(await res.json());
4048
+ const depositAddress = parsed.success ? parsed.data.steps?.[0]?.depositAddress : void 0;
4049
+ const quotedOut = parsed.success ? parsed.data.details?.currencyOut?.amount : void 0;
4050
+ if (!parsed.success || !depositAddress || !quotedOut) {
4051
+ throw new Error("Relay quote response missing or malformed requestId/depositAddress/amount");
4052
+ }
4053
+ return {
4054
+ requestId: parsed.data.requestId,
4055
+ depositAddress,
4056
+ amountInBaseUnits: request.amountBaseUnits,
4057
+ quotedOutBaseUnits: quotedOut
4058
+ };
4059
+ }
4060
+
4061
+ // src/commands/deposit.ts
4062
+ async function fundingOptionsFor(chainId) {
4063
+ const [cctpRaw, relayRaw] = await Promise.all([
4064
+ apiGet("/api/wallet/cross-chain-funding-config").catch(() => null),
4065
+ apiGet("/api/wallet/relay-bridge-funding-config").catch(() => null)
4066
+ ]);
4067
+ const cctp = CrossChainFundingConfigOutputSchema.safeParse(cctpRaw);
4068
+ const relay = RelayBridgeFundingConfigOutputSchema.safeParse(relayRaw);
4069
+ return {
4070
+ cctp: cctp.success && cctp.data.enabled && cctp.data.destination.chainId === chainId && cctp.data.sourceChains.length > 0 ? {
4071
+ environment: cctp.data.environment,
4072
+ destinationChainId: cctp.data.destination.chainId,
4073
+ sourceChains: cctp.data.sourceChains
4074
+ } : null,
4075
+ relayRoutes: relay.success ? relay.data.routes.map((id) => RELAY_BRIDGE_ROUTES[id]).filter((route) => route.destination.chainId === chainId).map((route) => ({
4076
+ routeId: route.id,
4077
+ from: {
4078
+ chainId: route.origin.chainId,
4079
+ chainName: route.origin.chainName,
4080
+ symbol: route.origin.symbol,
4081
+ currency: route.origin.currency
4082
+ },
4083
+ to: {
4084
+ chainId: route.destination.chainId,
4085
+ chainName: route.destination.chainName,
4086
+ symbol: route.destination.symbol
4087
+ }
4088
+ })) : [],
4089
+ note: "Run `taskmarket deposit --relay-route <routeId> --amount <n>` for a Relay deposit address. Fiat funding: see issue #2720."
4090
+ };
4091
+ }
4092
+ var depositCommand = new Command53("deposit").description(
4093
+ "Show wallet address, network info and cross-chain funding options for the selected --network"
4094
+ ).option(
4095
+ "--relay-route <routeId>",
4096
+ "Request a Relay deposit address for this wallet on an offered route (see fundingOptions.relayRoutes)"
4097
+ ).option("--amount <amount>", "Amount of the route origin stablecoin to send, for --relay-route").action(async (opts) => {
3834
4098
  let address;
3835
4099
  try {
3836
4100
  address = await getWalletAddress();
@@ -3870,7 +4134,48 @@ var depositCommand = new Command53("deposit").description("Show wallet address a
3870
4134
  /** Kept for scripts that read it; the same address as `tokenAddress`. */
3871
4135
  usdcContract: tokenAddress
3872
4136
  };
3873
- printResult(data);
4137
+ const fundingOptions = await fundingOptionsFor(chainId);
4138
+ if (opts.relayRoute === void 0) {
4139
+ if (opts.amount !== void 0) {
4140
+ renderFailure(new Error("--amount needs --relay-route"));
4141
+ return;
4142
+ }
4143
+ printResult({ ...data, fundingOptions });
4144
+ return;
4145
+ }
4146
+ try {
4147
+ const routeId = RelayBridgeRouteIdSchema.parse(opts.relayRoute);
4148
+ if (!fundingOptions.relayRoutes.some((route2) => route2.routeId === routeId)) {
4149
+ throw new Error(
4150
+ `Relay route ${routeId} is not offered for ${chain.networkName}; offered: ${fundingOptions.relayRoutes.map((route2) => route2.routeId).join(", ") || "none"}`
4151
+ );
4152
+ }
4153
+ if (opts.amount === void 0) throw new Error("--relay-route needs --amount");
4154
+ let amountBaseUnits;
4155
+ try {
4156
+ amountBaseUnits = usdcToBaseUnits(opts.amount).toString();
4157
+ } catch {
4158
+ throw new Error("Enter a valid amount.");
4159
+ }
4160
+ if (BigInt(amountBaseUnits) <= 0n) throw new Error("Enter a valid amount.");
4161
+ const deposit = await requestRelayBridgeDepositAddress({
4162
+ routeId,
4163
+ recipient: address,
4164
+ amountBaseUnits
4165
+ });
4166
+ const route = RELAY_BRIDGE_ROUTES[routeId];
4167
+ printResult({
4168
+ ...data,
4169
+ relayDeposit: {
4170
+ routeId,
4171
+ ...deposit,
4172
+ send: `${opts.amount} ${route.origin.symbol} on ${route.origin.chainName} to ${deposit.depositAddress}`,
4173
+ credits: `${route.destination.symbol} on ${route.destination.chainName} to ${address}`
4174
+ }
4175
+ });
4176
+ } catch (err) {
4177
+ renderFailure(err);
4178
+ }
3874
4179
  });
3875
4180
 
3876
4181
  // src/commands/wallet/index.ts
@@ -3930,6 +4235,7 @@ var walletImportCommand = new Command55("import").description("Import an existin
3930
4235
  "--yes",
3931
4236
  "Confirm legal acceptance non-interactively after reviewing every current policy"
3932
4237
  ).action(async (opts) => {
4238
+ selectedNetwork();
3933
4239
  if (await keystoreExists()) {
3934
4240
  const keystore = await loadKeystore();
3935
4241
  printResult({
@@ -6350,8 +6656,8 @@ var browseCommand = new Command79("browse").description(
6350
6656
  printError("--offset must be a whole number");
6351
6657
  return;
6352
6658
  }
6353
- const query2 = opts.query?.trim();
6354
- if (query2 !== void 0 && (query2.length === 0 || query2.length > 200)) {
6659
+ const query3 = opts.query?.trim();
6660
+ if (query3 !== void 0 && (query3.length === 0 || query3.length > 200)) {
6355
6661
  printError("--query must be 1 to 200 characters");
6356
6662
  return;
6357
6663
  }
@@ -6361,7 +6667,7 @@ var browseCommand = new Command79("browse").description(
6361
6667
  offset: String(offset)
6362
6668
  });
6363
6669
  if (opts.status) params.set("status", opts.status);
6364
- if (query2) params.set("query", query2);
6670
+ if (query3) params.set("query", query3);
6365
6671
  try {
6366
6672
  printResult(await apiGet(`/api/bug-tracker?${params.toString()}`));
6367
6673
  } catch (error) {
@@ -6725,12 +7031,173 @@ bugCommand.addCommand(meTooCommand);
6725
7031
  bugCommand.addCommand(commentCommand);
6726
7032
  bugCommand.addCommand(visibilityCommand);
6727
7033
 
6728
- // src/commands/requester/index.ts
7034
+ // src/commands/bookmark/index.ts
6729
7035
  import { Command as Command89 } from "commander";
6730
7036
 
6731
- // src/commands/requester/stats.ts
7037
+ // src/commands/bookmark/auth.ts
7038
+ async function bookmarkAuth(action) {
7039
+ const auth = await signReadAuth();
7040
+ if (!auth || Object.keys(auth.headers).length === 0) {
7041
+ printError(`${action} needs a wallet. Run \`taskmarket init\` first.`);
7042
+ return null;
7043
+ }
7044
+ return auth;
7045
+ }
7046
+
7047
+ // src/commands/bookmark/collection.ts
6732
7048
  import { Command as Command88 } from "commander";
6733
- var requesterStatsCmd = new Command88("stats").description("Get requester reputation stats for an address").argument("<address>", "Wallet address of the requester").action(async (address) => {
7049
+ var createCommand = new Command88("create").description("Create a private collection").argument("<name>", "Collection name, up to 120 characters").action(async (name) => {
7050
+ const trimmed = name.trim();
7051
+ if (trimmed.length === 0 || trimmed.length > 120) {
7052
+ printError("Collection name must be 1 to 120 characters");
7053
+ return;
7054
+ }
7055
+ const auth = await bookmarkAuth("Creating a collection");
7056
+ if (!auth) return;
7057
+ try {
7058
+ const { data, idempotencyKey } = await apiPost(
7059
+ "/api/bookmarks/collections",
7060
+ { name: trimmed },
7061
+ { headers: auth.headers }
7062
+ );
7063
+ printResult(data, { idempotencyKey });
7064
+ } catch (error) {
7065
+ return renderFailure(error);
7066
+ }
7067
+ });
7068
+ var listCommand2 = new Command88("list").description("List your collections; a published one carries its publishedSlug (/c/<slug>)").action(async () => {
7069
+ const auth = await bookmarkAuth("Listing collections");
7070
+ if (!auth) return;
7071
+ try {
7072
+ printResult(await apiGet("/api/bookmarks/collections", { headers: auth.headers }));
7073
+ } catch (error) {
7074
+ return renderFailure(error);
7075
+ }
7076
+ });
7077
+ function publishToggle(name, description, action) {
7078
+ return new Command88(name).description(description).argument("<collection-id>", "Collection id (from `taskmarket bookmark collection list`)").action(async (collectionId) => {
7079
+ const auth = await bookmarkAuth(action);
7080
+ if (!auth) return;
7081
+ try {
7082
+ const { data, idempotencyKey } = await apiPost(
7083
+ `/api/bookmarks/collections/${encodeURIComponent(collectionId)}/${name}`,
7084
+ {},
7085
+ { headers: auth.headers }
7086
+ );
7087
+ printResult(data, { idempotencyKey });
7088
+ } catch (error) {
7089
+ return renderFailure(error);
7090
+ }
7091
+ });
7092
+ }
7093
+ var collectionCommand = new Command88("collection").description(
7094
+ "Create, list, publish and unpublish bookmark collections"
7095
+ );
7096
+ collectionCommand.addCommand(createCommand);
7097
+ collectionCommand.addCommand(listCommand2);
7098
+ collectionCommand.addCommand(
7099
+ publishToggle(
7100
+ "publish",
7101
+ "Publish a collection at a random /c/<slug> link; viewers see only what they may see",
7102
+ "Publishing a collection"
7103
+ )
7104
+ );
7105
+ collectionCommand.addCommand(
7106
+ publishToggle(
7107
+ "unpublish",
7108
+ "Unpublish a collection; its link stops working and is never reissued",
7109
+ "Unpublishing a collection"
7110
+ )
7111
+ );
7112
+
7113
+ // src/commands/bookmark/index.ts
7114
+ var ENTITY_TYPES = ["task", "submission", "agent"];
7115
+ function parseEntityType(value, flag) {
7116
+ if (value === void 0) return null;
7117
+ if (ENTITY_TYPES.includes(value)) return value;
7118
+ printError(`${flag} must be one of ${ENTITY_TYPES.join(", ")}`);
7119
+ return null;
7120
+ }
7121
+ function chainFor(entityType) {
7122
+ return entityType === "agent" ? { chainId: selectedNetwork().chainId } : {};
7123
+ }
7124
+ var addCommand = new Command89("add").description(
7125
+ "Bookmark a task, submission or agent; an agent is saved on the selected network (--network)"
7126
+ ).argument("<type>", `What to bookmark: ${ENTITY_TYPES.join(", ")}`).argument("<id>", "Task id, submission id or agent id").option("--collection <id>", "Save it to one of your collections (moves an existing bookmark)").option("--note <text>", "A private note, up to 500 characters").action(async (type, id, opts) => {
7127
+ const entityType = parseEntityType(type, "<type>");
7128
+ if (!entityType) return;
7129
+ if (opts.note !== void 0 && opts.note.length > 500) {
7130
+ printError("--note must be at most 500 characters");
7131
+ return;
7132
+ }
7133
+ const auth = await bookmarkAuth("Bookmarking");
7134
+ if (!auth) return;
7135
+ try {
7136
+ const { data, idempotencyKey } = await apiPost(
7137
+ "/api/bookmarks",
7138
+ {
7139
+ entityType,
7140
+ entityId: id,
7141
+ ...chainFor(entityType),
7142
+ ...opts.collection !== void 0 ? { collectionId: opts.collection } : {},
7143
+ ...opts.note !== void 0 ? { note: opts.note } : {}
7144
+ },
7145
+ { headers: auth.headers }
7146
+ );
7147
+ printResult(data, { idempotencyKey });
7148
+ } catch (error) {
7149
+ return renderFailure(error);
7150
+ }
7151
+ });
7152
+ var removeCommand = new Command89("remove").description("Remove a bookmark; an agent bookmark is matched on the selected network").argument("<type>", `What was bookmarked: ${ENTITY_TYPES.join(", ")}`).argument("<id>", "Task id, submission id or agent id").action(async (type, id) => {
7153
+ const entityType = parseEntityType(type, "<type>");
7154
+ if (!entityType) return;
7155
+ const auth = await bookmarkAuth("Removing a bookmark");
7156
+ if (!auth) return;
7157
+ try {
7158
+ const { data, idempotencyKey } = await apiPost(
7159
+ "/api/bookmarks/remove",
7160
+ { entityType, entityId: id, ...chainFor(entityType) },
7161
+ { headers: auth.headers }
7162
+ );
7163
+ printResult(data, { idempotencyKey });
7164
+ } catch (error) {
7165
+ return renderFailure(error);
7166
+ }
7167
+ });
7168
+ var listCommand3 = new Command89("list").description("List your bookmarks, newest first; agent entries carry their chainId").option("--type <type>", `Only one kind: ${ENTITY_TYPES.join(", ")}`).option("--collection <id>", "Only bookmarks in this collection").option("--limit <n>", "Maximum bookmarks to return (1-100)", "50").action(async (opts) => {
7169
+ const entityType = opts.type === void 0 ? void 0 : parseEntityType(opts.type, "--type");
7170
+ if (entityType === null) return;
7171
+ const limit = Number(opts.limit);
7172
+ if (!Number.isInteger(limit) || limit < 1 || limit > 100) {
7173
+ printError("--limit must be an integer from 1 to 100");
7174
+ return;
7175
+ }
7176
+ const auth = await bookmarkAuth("Listing bookmarks");
7177
+ if (!auth) return;
7178
+ const params = new URLSearchParams({ limit: String(limit) });
7179
+ if (entityType) params.set("entityType", entityType);
7180
+ if (opts.collection) params.set("collectionId", opts.collection);
7181
+ try {
7182
+ printResult(await apiGet(`/api/bookmarks?${params.toString()}`, { headers: auth.headers }));
7183
+ } catch (error) {
7184
+ return renderFailure(error);
7185
+ }
7186
+ });
7187
+ var bookmarkCommand = new Command89("bookmark").description(
7188
+ "Save tasks, submissions and agents to your private list, and share collections of them"
7189
+ );
7190
+ bookmarkCommand.addCommand(addCommand);
7191
+ bookmarkCommand.addCommand(removeCommand);
7192
+ bookmarkCommand.addCommand(listCommand3);
7193
+ bookmarkCommand.addCommand(collectionCommand);
7194
+
7195
+ // src/commands/requester/index.ts
7196
+ import { Command as Command91 } from "commander";
7197
+
7198
+ // src/commands/requester/stats.ts
7199
+ import { Command as Command90 } from "commander";
7200
+ var requesterStatsCmd = new Command90("stats").description("Get requester reputation stats for an address").argument("<address>", "Wallet address of the requester").action(async (address) => {
6734
7201
  if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {
6735
7202
  printError("Address must be a 0x-prefixed 20-byte hex string");
6736
7203
  return;
@@ -6744,13 +7211,13 @@ var requesterStatsCmd = new Command88("stats").description("Get requester reputa
6744
7211
  });
6745
7212
 
6746
7213
  // src/commands/requester/index.ts
6747
- var requesterCmd = new Command89("requester").description("Requester reputation commands").addCommand(requesterStatsCmd);
7214
+ var requesterCmd = new Command91("requester").description("Requester reputation commands").addCommand(requesterStatsCmd);
6748
7215
 
6749
7216
  // src/commands/x402/index.ts
6750
- import { Command as Command93 } from "commander";
7217
+ import { Command as Command95 } from "commander";
6751
7218
 
6752
7219
  // src/commands/x402/payments.ts
6753
- import { Command as Command90, Option as Option4 } from "commander";
7220
+ import { Command as Command92, Option as Option4 } from "commander";
6754
7221
  import { createInterface as createInterface5 } from "readline";
6755
7222
  var PAYMENT_STATES = [
6756
7223
  "reserved",
@@ -6776,7 +7243,7 @@ async function confirmManualResolution() {
6776
7243
  readline.close();
6777
7244
  return answer.trim().toLowerCase() === "resolve";
6778
7245
  }
6779
- var x402PaymentsCommand = new Command90("payments").description(
7246
+ var x402PaymentsCommand = new Command92("payments").description(
6780
7247
  "Inspect and reconcile X402 Pay payment records"
6781
7248
  );
6782
7249
  x402PaymentsCommand.command("list").description("List current payment records").addOption(new Option4("--state <state>", "Filter by state").choices(PAYMENT_STATES)).action(async (options) => {
@@ -6805,7 +7272,7 @@ x402PaymentsCommand.command("resolve").description("Manually record an externall
6805
7272
 
6806
7273
  // src/commands/x402/policy.ts
6807
7274
  import { promises as fs4 } from "fs";
6808
- import { Command as Command91 } from "commander";
7275
+ import { Command as Command93 } from "commander";
6809
7276
  import { createInterface as createInterface6 } from "readline";
6810
7277
  async function confirmUnattendedRule(rule) {
6811
7278
  if (!process.stdin.isTTY) {
@@ -6831,7 +7298,7 @@ async function confirmUnattendedRule(rule) {
6831
7298
  readline.close();
6832
7299
  return answer.trim().toLowerCase() === "authorize";
6833
7300
  }
6834
- var x402PolicyCommand = new Command91("policy").description(
7301
+ var x402PolicyCommand = new Command93("policy").description(
6835
7302
  "Manage local X402 Pay spending policy"
6836
7303
  );
6837
7304
  x402PolicyCommand.command("init").description("Create a deny-all policy file").action(async () => {
@@ -6867,14 +7334,14 @@ for (const enabled of [true, false]) {
6867
7334
  }
6868
7335
 
6869
7336
  // src/commands/x402/request.ts
6870
- import { Command as Command92, Option as Option5 } from "commander";
7337
+ import { Command as Command94, Option as Option5 } from "commander";
6871
7338
  function collect3(value, previous) {
6872
7339
  return [...previous, value];
6873
7340
  }
6874
7341
  function confirm(lines) {
6875
7342
  return confirmAtTerminal(lines, "use --non-interactive with policy");
6876
7343
  }
6877
- var x402RequestCommand = new Command92("request").description("Request and pay for a direct x402 HTTP resource (X402 Pay)").argument("<url>", "HTTPS resource URL").addOption(new Option5("--method <method>", "HTTP method").choices(["GET", "POST"]).default("GET")).option("--json <json>", "Inline JSON POST body").option("--body-file <path>", "Read JSON POST body from a file").option("--headers-file <path>", "Read request headers from an owner-only JSON file").option(
7344
+ var x402RequestCommand = new Command94("request").description("Request and pay for a direct x402 HTTP resource (X402 Pay)").argument("<url>", "HTTPS resource URL").addOption(new Option5("--method <method>", "HTTP method").choices(["GET", "POST"]).default("GET")).option("--json <json>", "Inline JSON POST body").option("--body-file <path>", "Read JSON POST body from a file").option("--headers-file <path>", "Read request headers from an owner-only JSON file").option(
6878
7345
  "--header-env <header=ENV_VAR>",
6879
7346
  "Read one request header from an environment variable (repeatable)",
6880
7347
  collect3,
@@ -6922,7 +7389,7 @@ var x402RequestCommand = new Command92("request").description("Request and pay f
6922
7389
  );
6923
7390
 
6924
7391
  // src/commands/x402/index.ts
6925
- var x402Command = new Command93("x402").description(
7392
+ var x402Command = new Command95("x402").description(
6926
7393
  "Pay x402 services with local spending policies (X402 Pay)"
6927
7394
  );
6928
7395
  x402Command.addCommand(x402RequestCommand);
@@ -6930,10 +7397,10 @@ x402Command.addCommand(x402PolicyCommand);
6930
7397
  x402Command.addCommand(x402PaymentsCommand);
6931
7398
 
6932
7399
  // src/commands/sponsored-task/index.ts
6933
- import { Command as Command108 } from "commander";
7400
+ import { Command as Command110 } from "commander";
6934
7401
 
6935
7402
  // src/commands/sponsored-task/create.ts
6936
- import { Command as Command94 } from "commander";
7403
+ import { Command as Command96 } from "commander";
6937
7404
  import { toHex as toHex4 } from "viem";
6938
7405
 
6939
7406
  // ../../packages/contracts/abi/generated/SponsoredTasksVault.ts
@@ -10155,7 +10622,7 @@ async function approveSponsoredTaskSpend(input) {
10155
10622
  function isValidAddress4(addr) {
10156
10623
  return /^0x[a-fA-F0-9]{40}$/.test(addr);
10157
10624
  }
10158
- var sponsoredTaskCreateCommand = new Command94("create").description("Create a new Sponsored Task vault for a project token").requiredOption("--factory <address>", "SponsoredTaskFactory contract address").requiredOption("--chain-id <id>", "Chain id the factory is deployed on").requiredOption("--token <address>", "Project ERC-20 token address to fund the vault with").option("--owner <address>", "Vault owner (defaults to your own wallet)").action(async (opts) => {
10625
+ var sponsoredTaskCreateCommand = new Command96("create").description("Create a new Sponsored Task vault for a project token").requiredOption("--factory <address>", "SponsoredTaskFactory contract address").requiredOption("--chain-id <id>", "Chain id the factory is deployed on").requiredOption("--token <address>", "Project ERC-20 token address to fund the vault with").option("--owner <address>", "Vault owner (defaults to your own wallet)").action(async (opts) => {
10159
10626
  if (!isValidAddress4(opts.factory) || !isValidAddress4(opts.token)) {
10160
10627
  printError("Invalid Ethereum address for --factory or --token");
10161
10628
  return;
@@ -10192,11 +10659,11 @@ var sponsoredTaskCreateCommand = new Command94("create").description("Create a n
10192
10659
  });
10193
10660
 
10194
10661
  // src/commands/sponsored-task/fund.ts
10195
- import { Command as Command95 } from "commander";
10662
+ import { Command as Command97 } from "commander";
10196
10663
  function isValidAddress5(addr) {
10197
10664
  return /^0x[a-fA-F0-9]{40}$/.test(addr);
10198
10665
  }
10199
- var sponsoredTaskFundCommand = new Command95("fund").description("Fund a Sponsored Task vault with its project token (base units)").requiredOption("--vault <address>", "Vault address").requiredOption("--token <address>", "Project ERC-20 token address").requiredOption("--chain-id <id>", "Chain id the vault is deployed on").requiredOption("--amount <baseUnits>", "Amount to fund, in the token base units").action(async (opts) => {
10666
+ var sponsoredTaskFundCommand = new Command97("fund").description("Fund a Sponsored Task vault with its project token (base units)").requiredOption("--vault <address>", "Vault address").requiredOption("--token <address>", "Project ERC-20 token address").requiredOption("--chain-id <id>", "Chain id the vault is deployed on").requiredOption("--amount <baseUnits>", "Amount to fund, in the token base units").action(async (opts) => {
10200
10667
  if (!isValidAddress5(opts.vault) || !isValidAddress5(opts.token)) {
10201
10668
  printError("Invalid Ethereum address for --vault or --token");
10202
10669
  return;
@@ -10235,7 +10702,7 @@ var sponsoredTaskFundCommand = new Command95("fund").description("Fund a Sponsor
10235
10702
  });
10236
10703
 
10237
10704
  // src/commands/sponsored-task/managers.ts
10238
- import { Command as Command96 } from "commander";
10705
+ import { Command as Command98 } from "commander";
10239
10706
  function isValidAddress6(addr) {
10240
10707
  return /^0x[a-fA-F0-9]{40}$/.test(addr);
10241
10708
  }
@@ -10281,7 +10748,7 @@ async function configure(opts) {
10281
10748
  });
10282
10749
  printResult({ txHash, manager: opts.manager, spendCap: cap.toString(), active: opts.active });
10283
10750
  }
10284
- var sponsoredTaskManagersCommand = new Command96("managers").description(
10751
+ var sponsoredTaskManagersCommand = new Command98("managers").description(
10285
10752
  "Manage authorized managers for a Sponsored Task vault"
10286
10753
  );
10287
10754
  sponsoredTaskManagersCommand.command("add").description("Authorize a manager with a token-denominated spend cap").requiredOption("--vault <address>", "Vault address").requiredOption("--chain-id <id>", "Chain id the vault is deployed on").requiredOption("--manager <address>", "Manager address to authorize").requiredOption("--cap <baseUnits>", "Spend cap, in the project token base units").action((opts) => configure({ ...opts, active: true }));
@@ -10292,8 +10759,8 @@ sponsoredTaskManagersCommand.command("list").description("List a vault authorize
10292
10759
  });
10293
10760
 
10294
10761
  // src/commands/sponsored-task/managed.ts
10295
- import { Command as Command97 } from "commander";
10296
- var sponsoredTaskManagedCommand = new Command97("managed").description(
10762
+ import { Command as Command99 } from "commander";
10763
+ var sponsoredTaskManagedCommand = new Command99("managed").description(
10297
10764
  "List the active Sponsored Task vaults an address can fund tasks from as an active manager (defaults to your wallet)"
10298
10765
  ).option("--address <address>", "Manager address (defaults to your wallet)").option("--limit <n>", "Max vaults to return (1-100)", "50").option("--cursor <vaultId>", "Pagination cursor from a previous nextCursor").action(async (opts) => {
10299
10766
  let address = opts.address;
@@ -10323,7 +10790,7 @@ var sponsoredTaskManagedCommand = new Command97("managed").description(
10323
10790
  });
10324
10791
 
10325
10792
  // src/commands/sponsored-task/fee-bank.ts
10326
- import { Command as Command98 } from "commander";
10793
+ import { Command as Command100 } from "commander";
10327
10794
  function isValidAddress7(addr) {
10328
10795
  return /^0x[a-fA-F0-9]{40}$/.test(addr);
10329
10796
  }
@@ -10335,7 +10802,7 @@ async function requireKeystore2() {
10335
10802
  return null;
10336
10803
  }
10337
10804
  }
10338
- var sponsoredTaskFeeBankCommand = new Command98("fee-bank").description(
10805
+ var sponsoredTaskFeeBankCommand = new Command100("fee-bank").description(
10339
10806
  "Manage a manager USDC credit balance, charged by the Sponsored Task hook at task creation"
10340
10807
  );
10341
10808
  sponsoredTaskFeeBankCommand.command("deposit").description("Deposit USDC credit for creating sponsored tasks").requiredOption("--fee-bank <address>", "SponsoredTaskFeeBank contract address").requiredOption("--usdc <address>", "USDC token address").requiredOption("--chain-id <id>", "Chain id the fee bank is deployed on").requiredOption("--amount <baseUnits>", "Amount to deposit, in USDC base units (6 decimals)").action(async (opts) => {
@@ -10419,8 +10886,8 @@ sponsoredTaskFeeBankCommand.command("withdraw").description("Withdraw unused USD
10419
10886
  );
10420
10887
 
10421
10888
  // src/commands/sponsored-task/list.ts
10422
- import { Command as Command99 } from "commander";
10423
- var sponsoredTaskListCommand = new Command99("list").description("List Sponsored Task vaults").option("--limit <n>", "Max vaults to return", "50").option("--cursor <vaultId>", "Pagination cursor").option("--include-unverified", "Include vaults not yet curator-approved", false).action(async (opts) => {
10889
+ import { Command as Command101 } from "commander";
10890
+ var sponsoredTaskListCommand = new Command101("list").description("List Sponsored Task vaults").option("--limit <n>", "Max vaults to return", "50").option("--cursor <vaultId>", "Pagination cursor").option("--include-unverified", "Include vaults not yet curator-approved", false).action(async (opts) => {
10424
10891
  const params = new URLSearchParams({ limit: opts.limit });
10425
10892
  if (opts.cursor) params.set("cursor", opts.cursor);
10426
10893
  if (opts.includeUnverified) params.set("includeUnverified", "true");
@@ -10429,8 +10896,8 @@ var sponsoredTaskListCommand = new Command99("list").description("List Sponsored
10429
10896
  });
10430
10897
 
10431
10898
  // src/commands/sponsored-task/settlements.ts
10432
- import { Command as Command100 } from "commander";
10433
- var sponsoredTaskSettlementsCommand = new Command100("settlements").description("List the settlements a Sponsored Task vault has installed, newest first").argument("<vaultId>", "Vault id").option("--limit <n>", "Max settlements to return (1-100)", "25").option("--cursor <cursor>", "Pagination cursor from a previous nextCursor").action(async (vaultId, opts) => {
10899
+ import { Command as Command102 } from "commander";
10900
+ var sponsoredTaskSettlementsCommand = new Command102("settlements").description("List the settlements a Sponsored Task vault has installed, newest first").argument("<vaultId>", "Vault id").option("--limit <n>", "Max settlements to return (1-100)", "25").option("--cursor <cursor>", "Pagination cursor from a previous nextCursor").action(async (vaultId, opts) => {
10434
10901
  const limit = Number(opts.limit);
10435
10902
  if (!Number.isInteger(limit) || limit < 1 || limit > 100) {
10436
10903
  printError("--limit must be an integer from 1 to 100");
@@ -10445,17 +10912,17 @@ var sponsoredTaskSettlementsCommand = new Command100("settlements").description(
10445
10912
  });
10446
10913
 
10447
10914
  // src/commands/sponsored-task/show.ts
10448
- import { Command as Command101 } from "commander";
10449
- var sponsoredTaskShowCommand = new Command101("show").description("Show a Sponsored Task vault by id").argument("<vaultId>", "Vault id").action(async (vaultId) => {
10915
+ import { Command as Command103 } from "commander";
10916
+ var sponsoredTaskShowCommand = new Command103("show").description("Show a Sponsored Task vault by id").argument("<vaultId>", "Vault id").action(async (vaultId) => {
10450
10917
  const result = await apiGet(`/api/sponsored-task-vaults/${vaultId}`);
10451
10918
  printResult(result);
10452
10919
  });
10453
10920
 
10454
10921
  // src/commands/sponsored-task/request-review.ts
10455
10922
  import { randomBytes as randomBytes3 } from "crypto";
10456
- import { Command as Command102 } from "commander";
10923
+ import { Command as Command104 } from "commander";
10457
10924
  var REQUEST_TTL_SECONDS = 5 * 60;
10458
- var sponsoredTaskRequestReviewCommand = new Command102("request-review").description("Ask Taskmarket curators to review a Sponsored Task vault (vault owner only)").argument("<vaultId>", "Vault id").action(async (vaultId) => {
10925
+ var sponsoredTaskRequestReviewCommand = new Command104("request-review").description("Ask Taskmarket curators to review a Sponsored Task vault (vault owner only)").argument("<vaultId>", "Vault id").action(async (vaultId) => {
10459
10926
  let keystore;
10460
10927
  try {
10461
10928
  keystore = await loadKeystore();
@@ -10512,18 +10979,18 @@ var sponsoredTaskRequestReviewCommand = new Command102("request-review").descrip
10512
10979
  });
10513
10980
 
10514
10981
  // src/commands/sponsored-task/balance.ts
10515
- import { Command as Command103 } from "commander";
10516
- var sponsoredTaskBalanceCommand = new Command103("balance").description("Show a Sponsored Task vault funded/available/reserved balances").argument("<vaultId>", "Vault id").action(async (vaultId) => {
10982
+ import { Command as Command105 } from "commander";
10983
+ var sponsoredTaskBalanceCommand = new Command105("balance").description("Show a Sponsored Task vault funded/available/reserved balances").argument("<vaultId>", "Vault id").action(async (vaultId) => {
10517
10984
  const result = await apiGet(`/api/sponsored-task-vaults/${vaultId}/balance`);
10518
10985
  printResult(result);
10519
10986
  });
10520
10987
 
10521
10988
  // src/commands/sponsored-task/withdraw.ts
10522
- import { Command as Command104 } from "commander";
10989
+ import { Command as Command106 } from "commander";
10523
10990
  function isValidAddress8(addr) {
10524
10991
  return /^0x[a-fA-F0-9]{40}$/.test(addr);
10525
10992
  }
10526
- var sponsoredTaskWithdrawCommand = new Command104("withdraw").description("Withdraw unreserved project tokens from a vault (owner only)").requiredOption("--vault <address>", "Vault address").requiredOption("--chain-id <id>", "Chain id the vault is deployed on").requiredOption("--amount <baseUnits>", "Amount to withdraw, in the project token base units").option("--recipient <address>", "Recipient (defaults to your own wallet)").action(async (opts) => {
10993
+ var sponsoredTaskWithdrawCommand = new Command106("withdraw").description("Withdraw unreserved project tokens from a vault (owner only)").requiredOption("--vault <address>", "Vault address").requiredOption("--chain-id <id>", "Chain id the vault is deployed on").requiredOption("--amount <baseUnits>", "Amount to withdraw, in the project token base units").option("--recipient <address>", "Recipient (defaults to your own wallet)").action(async (opts) => {
10527
10994
  if (!isValidAddress8(opts.vault) || opts.recipient && !isValidAddress8(opts.recipient)) {
10528
10995
  printError("Invalid Ethereum address for --vault or --recipient");
10529
10996
  return;
@@ -10553,11 +11020,11 @@ var sponsoredTaskWithdrawCommand = new Command104("withdraw").description("Withd
10553
11020
  });
10554
11021
 
10555
11022
  // src/commands/sponsored-task/exit.ts
10556
- import { Command as Command105 } from "commander";
11023
+ import { Command as Command107 } from "commander";
10557
11024
  function isValidAddress9(addr) {
10558
11025
  return /^0x[a-fA-F0-9]{40}$/.test(addr);
10559
11026
  }
10560
- var sponsoredTaskExitCommand = new Command105("exit").description(
11027
+ var sponsoredTaskExitCommand = new Command107("exit").description(
10561
11028
  "Terminally exit a vault: sweeps every reserved and unclaimed token back to you, invalidating every outstanding reservation, claim signature, and Merkle proof at once. There is no undo and no per-allocation revoke -- a worker with a pending but unclaimed entitlement gets nothing once this runs."
10562
11029
  ).requiredOption("--vault <address>", "Vault address").requiredOption("--chain-id <id>", "Chain id the vault is deployed on").option("--recipient <address>", "Recipient (defaults to your own wallet)").option("--yes", "Skip the confirmation prompt", false).action(async (opts) => {
10563
11030
  if (!isValidAddress9(opts.vault) || opts.recipient && !isValidAddress9(opts.recipient)) {
@@ -10593,7 +11060,7 @@ var sponsoredTaskExitCommand = new Command105("exit").description(
10593
11060
  });
10594
11061
 
10595
11062
  // src/commands/sponsored-task/claim.ts
10596
- import { Command as Command106 } from "commander";
11063
+ import { Command as Command108 } from "commander";
10597
11064
  var CLAIM_TO_TYPES = {
10598
11065
  ClaimTo: [
10599
11066
  { name: "vaultId", type: "bytes32" },
@@ -10628,7 +11095,7 @@ async function postClaimWithRetry(path3, body, options = {}) {
10628
11095
  }
10629
11096
  }
10630
11097
  }
10631
- var sponsoredTaskClaimCommand = new Command106("claim").description("Claim your unclaimed Sponsored Task reward for a vault task").argument("<vaultId>", "Vault id").option(
11098
+ var sponsoredTaskClaimCommand = new Command108("claim").description("Claim your unclaimed Sponsored Task reward for a vault task").argument("<vaultId>", "Vault id").option(
10632
11099
  "--task-id <id>",
10633
11100
  "Claim the entitlement for a specific task (defaults to the first unclaimed one)"
10634
11101
  ).action(async (vaultId, opts) => {
@@ -10720,10 +11187,10 @@ var sponsoredTaskClaimCommand = new Command106("claim").description("Claim your
10720
11187
  });
10721
11188
 
10722
11189
  // src/commands/sponsored-task/rewards.ts
10723
- import { Command as Command107 } from "commander";
11190
+ import { Command as Command109 } from "commander";
10724
11191
  var REWARD_STATES = SponsoredTaskRewardStateSchema.options;
10725
11192
  var CLAIM_STATUSES = SponsoredTaskWorkerRewardClaimStatusSchema.options;
10726
- var sponsoredTaskRewardsCommand = new Command107("rewards").description("List Sponsored Task rewards across every vault (defaults to your wallet)").option("--address <address>", "Worker address (defaults to your wallet)").option("--state <state>", `Reward state: ${REWARD_STATES.join(", ")}`).option("--claim-status <status>", `Claim status: ${CLAIM_STATUSES.join(", ")}`).option("--limit <n>", "Max rewards to return (1-100)", "50").option("--cursor <cursor>", "Pagination cursor from a previous nextCursor").action(
11193
+ var sponsoredTaskRewardsCommand = new Command109("rewards").description("List Sponsored Task rewards across every vault (defaults to your wallet)").option("--address <address>", "Worker address (defaults to your wallet)").option("--state <state>", `Reward state: ${REWARD_STATES.join(", ")}`).option("--claim-status <status>", `Claim status: ${CLAIM_STATUSES.join(", ")}`).option("--limit <n>", "Max rewards to return (1-100)", "50").option("--cursor <cursor>", "Pagination cursor from a previous nextCursor").action(
10727
11194
  async (opts) => {
10728
11195
  let address = opts.address;
10729
11196
  if (address === void 0) {
@@ -10763,7 +11230,7 @@ var sponsoredTaskRewardsCommand = new Command107("rewards").description("List Sp
10763
11230
  );
10764
11231
 
10765
11232
  // src/commands/sponsored-task/index.ts
10766
- var sponsoredTaskCommand = new Command108("sponsored-task").description(
11233
+ var sponsoredTaskCommand = new Command110("sponsored-task").description(
10767
11234
  "Sponsored Task vault administration and reward claims"
10768
11235
  );
10769
11236
  sponsoredTaskCommand.addCommand(sponsoredTaskCreateCommand);
@@ -10781,10 +11248,117 @@ sponsoredTaskCommand.addCommand(sponsoredTaskExitCommand);
10781
11248
  sponsoredTaskCommand.addCommand(sponsoredTaskClaimCommand);
10782
11249
  sponsoredTaskCommand.addCommand(sponsoredTaskRewardsCommand);
10783
11250
 
11251
+ // src/commands/drops.ts
11252
+ import { Command as Command111 } from "commander";
11253
+ var listCommand4 = new Command111("list").description("List public Task Drops, ones accepting work first").option("--limit <n>", "Maximum drops to return (1-48)", "24").option("--cursor <cursor>", "nextCursor from a previous page").action(async (opts) => {
11254
+ try {
11255
+ const input = parseInput(TaskDropDirectoryInputSchema, {
11256
+ limit: optionalInt(opts.limit),
11257
+ cursor: opts.cursor
11258
+ });
11259
+ const params = new URLSearchParams({ limit: String(input.limit) });
11260
+ if (input.cursor) params.set("cursor", input.cursor);
11261
+ printResult(await apiGet(`/api/task-drops/directory?${params.toString()}`));
11262
+ } catch (err) {
11263
+ renderFailure(err);
11264
+ }
11265
+ });
11266
+ var showCommand2 = new Command111("show").description("Show a Task Drop and its discoverable tasks").argument("<taskDropId>", "Task Drop ID").action(async (taskDropId) => {
11267
+ try {
11268
+ const input = parseInput(TaskDropGetInputSchema, { taskDropId });
11269
+ const result = await apiGet(`/api/task-drops/${encodeURIComponent(input.taskDropId)}`);
11270
+ if (result === null || result === void 0) {
11271
+ throw new Error(`Task Drop ${input.taskDropId} not found`);
11272
+ }
11273
+ printResult(result);
11274
+ } catch (err) {
11275
+ renderFailure(err);
11276
+ }
11277
+ });
11278
+ var subscribeCommand = new Command111("subscribe").description("Subscribe an email to one Task Drop, or with --official to every official drop").argument("[taskDropId]", "Task Drop ID (omit with --official)").requiredOption("--email <email>", "Email address to notify").option("--official", "Subscribe to all official Task Drops").option("--wallet <address>", "Wallet address to associate with the subscription").action(
11279
+ async (taskDropId, opts) => {
11280
+ try {
11281
+ if (opts.official) {
11282
+ if (taskDropId) throw new Error("Pass either a Task Drop ID or --official, not both");
11283
+ const body2 = parseInput(TaskDropOfficialSubscribeInputSchema, {
11284
+ email: opts.email,
11285
+ walletAddress: opts.wallet,
11286
+ source: "cli"
11287
+ });
11288
+ const outcome2 = await apiPost("/api/task-drops/official/subscribe", body2);
11289
+ printResult(outcome2.data, { idempotencyKey: outcome2.idempotencyKey });
11290
+ return;
11291
+ }
11292
+ if (!taskDropId) throw new Error("Pass a Task Drop ID, or --official");
11293
+ const body = parseInput(TaskDropSubscribeInputSchema, {
11294
+ taskDropId,
11295
+ email: opts.email,
11296
+ walletAddress: opts.wallet,
11297
+ source: "cli"
11298
+ });
11299
+ const outcome = await apiPost("/api/task-drops/subscribe", body);
11300
+ printResult(outcome.data, { idempotencyKey: outcome.idempotencyKey });
11301
+ } catch (err) {
11302
+ renderFailure(err);
11303
+ }
11304
+ }
11305
+ );
11306
+ var statusCommand3 = new Command111("status").description("Check whether an email is subscribed to a Task Drop, or with --official to all").argument("[taskDropId]", "Task Drop ID (omit with --official)").requiredOption("--email <email>", "Email address to check").option("--official", "Check the all-official-drops subscription").action(async (taskDropId, opts) => {
11307
+ try {
11308
+ if (opts.official) {
11309
+ if (taskDropId) throw new Error("Pass either a Task Drop ID or --official, not both");
11310
+ const input2 = parseInput(TaskDropOfficialStatusInputSchema, { email: opts.email });
11311
+ const params2 = new URLSearchParams({ email: input2.email });
11312
+ printResult(await apiGet(`/api/task-drops/official/status?${params2.toString()}`));
11313
+ return;
11314
+ }
11315
+ if (!taskDropId) throw new Error("Pass a Task Drop ID, or --official");
11316
+ const input = parseInput(TaskDropStatusInputSchema, { taskDropId, email: opts.email });
11317
+ const params = new URLSearchParams({ taskDropId: input.taskDropId, email: input.email });
11318
+ printResult(await apiGet(`/api/task-drops/status?${params.toString()}`));
11319
+ } catch (err) {
11320
+ renderFailure(err);
11321
+ }
11322
+ });
11323
+ var dropsCommand = new Command111("drops").description("Browse Task Drops and manage email subscriptions to them").addCommand(listCommand4).addCommand(showCommand2).addCommand(subscribeCommand).addCommand(statusCommand3);
11324
+
11325
+ // src/commands/hooks.ts
11326
+ import { Command as Command112 } from "commander";
11327
+ var listCommand5 = new Command112("list").description("List observed hooks and their active-phase task counts on the selected --network").option("--limit <n>", "Maximum hooks to return (1-100)", "50").action(async (opts) => {
11328
+ try {
11329
+ const input = parseInput(HookIndexInputSchema, { limit: optionalInt(opts.limit) });
11330
+ printResult(await apiGet(withChainId(`/api/hooks?limit=${input.limit}`)));
11331
+ } catch (err) {
11332
+ renderFailure(err);
11333
+ }
11334
+ });
11335
+ var showCommand3 = new Command112("show").description("Show one observed hook by address on the selected --network").argument("<address>", "Hook contract address").action(async (address) => {
11336
+ try {
11337
+ const input = parseInput(HookGetInputSchema, { address });
11338
+ const result = await apiGet(withChainId(`/api/hooks/${input.address}`));
11339
+ if (result === null || result === void 0) {
11340
+ throw new Error(`Hook ${input.address} has not been observed on this network`);
11341
+ }
11342
+ printResult(result);
11343
+ } catch (err) {
11344
+ renderFailure(err);
11345
+ }
11346
+ });
11347
+ var attachmentConfigCommand = new Command112("attachment-config").description(
11348
+ "Show the protocol-default hook order and maximum hooks per task on the selected --network"
11349
+ ).action(async () => {
11350
+ try {
11351
+ printResult(await apiGet(withChainId("/api/hooks/attachment-configuration")));
11352
+ } catch (err) {
11353
+ renderFailure(err);
11354
+ }
11355
+ });
11356
+ var hooksCommand = new Command112("hooks").description("Browse the hook registry on the selected --network").addCommand(listCommand5).addCommand(showCommand3).addCommand(attachmentConfigCommand);
11357
+
10784
11358
  // src/index.ts
10785
11359
  var require2 = createRequire(import.meta.url);
10786
11360
  var { version } = require2("../package.json");
10787
- var program = new Command109();
11361
+ var program = new Command113();
10788
11362
  setLastErrorCliVersion(version);
10789
11363
  program.name("taskmarket").description("Taskmarket CLI for AI agents").version(version);
10790
11364
  program.option(
@@ -10822,7 +11396,10 @@ program.addCommand(requesterCmd);
10822
11396
  program.addCommand(legalCommand);
10823
11397
  program.addCommand(x402Command);
10824
11398
  program.addCommand(sponsoredTaskCommand);
11399
+ program.addCommand(dropsCommand);
11400
+ program.addCommand(hooksCommand);
10825
11401
  program.addCommand(bugCommand);
11402
+ program.addCommand(bookmarkCommand);
10826
11403
  void (async () => {
10827
11404
  try {
10828
11405
  await program.parseAsync(process.argv);