@lucid-agents/taskmarket 1.20.2 → 1.21.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-TO6BB6N3.js";
17
+ } from "./chunk-5N25NATR.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-WUSEHQHR.js";
39
+ } from "./chunk-TAMXCFLT.js";
40
40
  import {
41
41
  MPP_TEMPO_DEFAULT_VALIDITY_SECONDS,
42
42
  X402PayError,
@@ -58,7 +58,7 @@ import {
58
58
  signSponsoredTempoTransfer,
59
59
  signTaskmarketFeePayment,
60
60
  signTypedData
61
- } from "./chunk-AT2VG32A.js";
61
+ } from "./chunk-HE2N4GEO.js";
62
62
  import {
63
63
  AgentMessageEnvelopeSchema,
64
64
  ApiError,
@@ -75,6 +75,7 @@ import {
75
75
  LegalStatusResponseSchema,
76
76
  NETWORKS,
77
77
  NETWORK_NAMES,
78
+ NetworkRequiredError,
78
79
  PUBLIC_BUG_REPORT_SORTS,
79
80
  PenaltyTo,
80
81
  PostBugReportMessageInputSchema,
@@ -138,14 +139,17 @@ import {
138
139
  formatPaymentAmount,
139
140
  formatUsdcBaseUnits,
140
141
  generateKeypair,
142
+ getNetwork,
141
143
  getTaskmarketHome,
142
144
  idempotencyKeyForError,
143
145
  isInFlightApiError,
146
+ isNetworkName,
144
147
  isPendingApiError,
145
148
  isRecordingPendingResponse,
146
149
  isTaskmarketChainId,
147
150
  isTerminalWalletBridgeStatus,
148
151
  keystoreExists,
152
+ liveNetworkNames,
149
153
  loadKeystore,
150
154
  networkToStamp,
151
155
  paymentProtocolOf,
@@ -158,6 +162,7 @@ import {
158
162
  resolveTaskTerms,
159
163
  saveKeystore,
160
164
  selectedNetwork,
165
+ selectedNetworkOrUndefined,
161
166
  setSelectedNetwork,
162
167
  settlementActionExpiresAt,
163
168
  settlementActionRequiresExpiry,
@@ -167,7 +172,7 @@ import {
167
172
  withChainId,
168
173
  withErrorContext,
169
174
  withIdempotentWrite
170
- } from "./chunk-2JTB3UFM.js";
175
+ } from "./chunk-3IIVNF5F.js";
171
176
  import {
172
177
  channelLines
173
178
  } from "./chunk-XJOB4NMV.js";
@@ -180,6 +185,7 @@ import { createRequire } from "module";
180
185
  // src/commands/init.ts
181
186
  import { Command as Command2 } from "commander";
182
187
  import { privateKeyToAccount } from "viem/accounts";
188
+ import { createInterface as createInterface2 } from "readline";
183
189
 
184
190
  // src/lib/last-error.ts
185
191
  import fs from "fs";
@@ -308,21 +314,38 @@ function printWarning(message) {
308
314
  }
309
315
 
310
316
  // src/lib/agent.ts
317
+ function legacyAgentIdChain(keystore) {
318
+ const network = keystore.network;
319
+ return network && isNetworkName(network) ? NETWORKS[network].chainId : void 0;
320
+ }
321
+ function agentIdForChain(keystore, chainId) {
322
+ const stored = keystore.agentIds?.[String(chainId)];
323
+ if (stored) return stored;
324
+ if (keystore.agentId && legacyAgentIdChain(keystore) === chainId) return keystore.agentId;
325
+ return null;
326
+ }
327
+ function withAgentIdForChain(keystore, chainId, agentId) {
328
+ return { ...keystore, agentIds: { ...keystore.agentIds, [String(chainId)]: agentId } };
329
+ }
330
+ async function lookupAgentId(address, chainId = selectedNetwork().chainId) {
331
+ try {
332
+ const res = await fetch(
333
+ `${apiUrl()}/api/identity/status?address=${address}&chainId=${chainId}`
334
+ );
335
+ if (!res.ok) return null;
336
+ const data = await res.json();
337
+ return data.agentId ?? null;
338
+ } catch {
339
+ return null;
340
+ }
341
+ }
311
342
  async function pollAgentId(address, maxWaitMs = 6e4) {
312
343
  const interval = 3e3;
313
344
  const deadline = Date.now() + maxWaitMs;
314
345
  while (Date.now() < deadline) {
315
346
  await new Promise((r) => setTimeout(r, interval));
316
- try {
317
- const res = await fetch(
318
- `${apiUrl()}/api/identity/status?address=${address}&chainId=${selectedNetwork().chainId}`
319
- );
320
- if (res.ok) {
321
- const data = await res.json();
322
- if (data.agentId) return data.agentId;
323
- }
324
- } catch {
325
- }
347
+ const agentId = await lookupAgentId(address);
348
+ if (agentId) return agentId;
326
349
  }
327
350
  return null;
328
351
  }
@@ -599,13 +622,42 @@ async function tryRegisterEmail(deviceId, apiToken, username, explicit) {
599
622
  return null;
600
623
  }
601
624
  }
602
- var initCommand = new Command2("init").description("Create and register a new agent wallet (safe to re-run)").option(
625
+ function terminalIo() {
626
+ return {
627
+ interactive: Boolean(process.stdin.isTTY && process.stderr.isTTY),
628
+ ask: (question) => new Promise((resolve) => {
629
+ const rl = createInterface2({ input: process.stdin, output: process.stderr });
630
+ rl.question(question, (answer) => {
631
+ rl.close();
632
+ resolve(answer);
633
+ });
634
+ })
635
+ };
636
+ }
637
+ async function ensureInitNetwork(io = terminalIo()) {
638
+ if (selectedNetworkOrUndefined()) return;
639
+ if (!io.interactive) throw new NetworkRequiredError();
640
+ const answer = (await io.ask(`Network to use (${liveNetworkNames().join(", ")}): `)).trim();
641
+ if (!answer) throw new NetworkRequiredError();
642
+ setSelectedNetwork(getNetwork(answer));
643
+ }
644
+ function existingWalletMessage() {
645
+ return "This machine already has a Taskmarket wallet; init runs once and never replaces saved credentials. The same wallet and device credentials work on every network. To register its agent identity on another network, run: taskmarket --network <name> identity register";
646
+ }
647
+ var initCommand = new Command2("init").description(
648
+ "Create and register this machine's agent wallet (one-time; refuses when a wallet exists)"
649
+ ).option(
603
650
  "--email <username>",
604
651
  "Claim a custom email username (default: auto-generated from agent ID)"
605
652
  ).option(
606
653
  "--yes",
607
654
  "Confirm legal acceptance non-interactively after reviewing every current policy"
608
655
  ).action(async (opts) => {
656
+ if (await keystoreExists()) {
657
+ printError(existingWalletMessage());
658
+ return;
659
+ }
660
+ await ensureInitNetwork();
609
661
  if (opts.email) {
610
662
  const check = await apiGet(
611
663
  `/api/emails/check-username?username=${encodeURIComponent(opts.email)}`
@@ -615,50 +667,6 @@ var initCommand = new Command2("init").description("Create and register a new ag
615
667
  return;
616
668
  }
617
669
  }
618
- if (await keystoreExists()) {
619
- const keystore = await loadKeystore();
620
- let agentId2 = keystore.agentId;
621
- if (!agentId2) {
622
- agentId2 = await pollAgentId(keystore.walletAddress);
623
- if (agentId2) {
624
- await saveKeystore({ ...keystore, agentId: agentId2 });
625
- }
626
- }
627
- let networkInfo2;
628
- try {
629
- const response = await apiGet("/trpc/network.info");
630
- networkInfo2 = response.result.data;
631
- } catch {
632
- }
633
- let emailAddress2 = null;
634
- try {
635
- const existing = await apiGet(`/api/agents/stats?address=${keystore.walletAddress}`);
636
- emailAddress2 = existing.emailAddress ?? null;
637
- } catch {
638
- }
639
- if (!emailAddress2) {
640
- const username2 = opts.email ?? (agentId2 && networkInfo2 ? sanitizeEmailUsername(agentId2, String(selectedNetwork().chainId)) : null);
641
- if (username2) {
642
- emailAddress2 = await tryRegisterEmail(
643
- keystore.deviceId,
644
- keystore.apiToken,
645
- username2,
646
- !!opts.email
647
- );
648
- }
649
- }
650
- const chain2 = chainInfoFor(networkInfo2, selectedNetwork().chainId);
651
- printResult({
652
- address: keystore.walletAddress,
653
- agentId: agentId2,
654
- network: chain2?.networkName ?? networkInfo2?.networkName,
655
- chainId: chain2?.chainId ?? networkInfo2?.chainId,
656
- paymentMethod: chain2?.paymentMethod,
657
- feeModel: chain2?.feeModel,
658
- emailAddress: emailAddress2
659
- });
660
- return;
661
- }
662
670
  const { privateKey, address } = generateKeypair();
663
671
  const publicKey = deriveCompressedPublicKey(privateKey);
664
672
  const legalBundle = LegalBundleSchema.parse(await apiGet("/api/legal/current"));
@@ -690,6 +698,7 @@ var initCommand = new Command2("init").description("Create and register a new ag
690
698
  deviceId,
691
699
  apiToken,
692
700
  agentId,
701
+ ...agentId ? { agentIds: { [String(selectedNetwork().chainId)]: agentId } } : {},
693
702
  keyServerUrl: apiUrl(),
694
703
  network: networkToStamp(),
695
704
  ...legalAcceptance ? {
@@ -702,7 +711,9 @@ var initCommand = new Command2("init").description("Create and register a new ag
702
711
  agentId = await pollAgentId(address);
703
712
  if (agentId) {
704
713
  const keystore = await loadKeystore();
705
- await saveKeystore({ ...keystore, agentId });
714
+ await saveKeystore(
715
+ withAgentIdForChain({ ...keystore, agentId }, selectedNetwork().chainId, agentId)
716
+ );
706
717
  }
707
718
  }
708
719
  let networkInfo;
@@ -713,7 +724,13 @@ var initCommand = new Command2("init").description("Create and register a new ag
713
724
  }
714
725
  const username = opts.email ?? (agentId && networkInfo ? sanitizeEmailUsername(agentId, String(selectedNetwork().chainId)) : null);
715
726
  const emailAddress = username ? await tryRegisterEmail(deviceId, apiToken, username, !!opts.email) : null;
716
- const chain = chainInfoFor(networkInfo, selectedNetwork().chainId);
727
+ let chain;
728
+ try {
729
+ chain = chainInfoFor(networkInfo, selectedNetwork().chainId);
730
+ } catch (err) {
731
+ renderFailure(err);
732
+ return;
733
+ }
717
734
  printResult({
718
735
  address,
719
736
  agentId,
@@ -734,72 +751,35 @@ var addressCommand = new Command3("address").description("Print the wallet addre
734
751
 
735
752
  // src/commands/identity.ts
736
753
  import { Command as Command4 } from "commander";
737
-
738
- // src/lib/x402.ts
739
- var FACILITATOR_RETRIES = 2;
740
- var MAX_RETRY_AFTER_SECONDS = 60;
741
- var DEFAULT_RETRY_AFTER_SECONDS = 30;
742
- function retryAfterMs(res) {
743
- const header = res.headers?.get?.("retry-after");
744
- const seconds = header ? Number(header) : NaN;
745
- const wait = Number.isFinite(seconds) && seconds >= 0 ? seconds : DEFAULT_RETRY_AFTER_SECONDS;
746
- return Math.min(wait, MAX_RETRY_AFTER_SECONDS) * 1e3;
747
- }
748
- async function x402Post(path3, body, options) {
749
- const sleep4 = options?.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
750
- if (paymentProtocolOf(selectedNetwork().chainId) === "mpp")
751
- return mppPost(path3, body, options);
754
+ var identityCommand = new Command4("identity").description("Manage agent identity");
755
+ identityCommand.command("register").description(
756
+ "Register this wallet's ERC-8004 agent identity on the selected network (free; uses this machine's existing credentials)"
757
+ ).action(async () => {
752
758
  const keystore = await loadKeystore();
753
- const idempotencyKey = resolveIdempotencyKey(options?.idempotencyKey);
754
- const request = paidWriteRequest(keystore, path3, body, idempotencyKey);
755
- return withIdempotentWrite(idempotencyKey, async () => {
756
- const r1 = await fetch(request.url, {
757
- method: "POST",
758
- redirect: "error",
759
- headers: request.headers,
760
- body: request.body
761
- });
762
- if (r1.status !== 402) {
763
- if (r1.ok) {
764
- return { data: await r1.json(), idempotencyKey };
765
- }
766
- throw refusedPaidWrite(path3, r1.status, await readFailureBody(r1), idempotencyKey);
767
- }
768
- const requirements = await r1.json();
769
- if (!requirements.accepts || requirements.accepts.length === 0) {
770
- throw new Error("No payment methods accepted by server");
771
- }
772
- const accept = requirements.accepts[0];
773
- const { header } = await signTaskmarketFeePayment({
774
- resource: requirements.resource,
775
- requirement: accept,
776
- typedData: accept.extra.eip712,
777
- from: keystore.walletAddress,
778
- signTypedData: (typedData) => signTypedData(typedData, keystore)
779
- });
780
- for (let attempt = 0; ; attempt++) {
781
- const r2 = await fetch(request.url, {
782
- method: "POST",
783
- redirect: "error",
784
- headers: { ...request.headers, "PAYMENT-SIGNATURE": header },
785
- body: request.body
786
- });
787
- if (r2.ok) return { data: await r2.json(), idempotencyKey };
788
- const read = await readFailureBody(r2);
789
- if (r2.status === 503 && apiErrorEnvelopeOf(read.body)?.reason === "facilitator_unavailable" && attempt < FACILITATOR_RETRIES) {
790
- await sleep4(retryAfterMs(r2));
791
- continue;
792
- }
793
- throw failedAfterPayment(path3, r2.status, read, idempotencyKey);
794
- }
759
+ const chainId = selectedNetwork().chainId;
760
+ const stored = agentIdForChain(keystore, chainId);
761
+ if (stored) {
762
+ printResult({ agentId: stored, alreadyRegistered: true, chainId });
763
+ return;
764
+ }
765
+ const { data, idempotencyKey } = await apiPost(`/api/devices/${encodeURIComponent(keystore.deviceId)}/identity`, {
766
+ deviceId: keystore.deviceId,
767
+ apiToken: keystore.apiToken,
768
+ chainId
795
769
  });
796
- }
797
-
798
- // src/commands/identity.ts
799
- var identityCommand = new Command4("identity").description("Manage agent identity");
800
- identityCommand.command("register").description("Register ERC-8004 agent identity (costs 0.001 in the payment token)").action(async () => {
801
- const { data: result, idempotencyKey } = await x402Post("/api/identity/register", { chainId: selectedNetwork().chainId });
802
- printResult({ agentId: result.agentId }, { idempotencyKey });
770
+ const agentId = data.agentId ?? await pollAgentId(keystore.walletAddress);
771
+ if (agentId) {
772
+ await saveKeystore(withAgentIdForChain(await loadKeystore(), chainId, agentId));
773
+ printResult(
774
+ { agentId, alreadyRegistered: data.alreadyRegistered, chainId },
775
+ { idempotencyKey }
776
+ );
777
+ return;
778
+ }
779
+ printError(
780
+ `The sponsored identity mint on chain ${chainId} has started but has not landed yet. Re-run this command to pick it up: ${taskmarketCommandFor(chainId)} identity register`,
781
+ { idempotencyKey }
782
+ );
803
783
  });
804
784
  identityCommand.command("status").description("Check identity registration status").action(async () => {
805
785
  const keystore = await loadKeystore();
@@ -833,7 +813,9 @@ function describeReputationLink(link) {
833
813
  return `unavailable: ${link.linkUnavailableReason ?? LINK_READ_FAILED_REASON}`;
834
814
  return link.linkedAgentId ? `linked to agent #${link.linkedAgentId}` : NOT_LINKED_YET;
835
815
  }
836
- var whoamiCommand = new Command5("whoami").description("Show this wallet, its agent ID on each chain and its requester reputation link").action(async () => {
816
+ var whoamiCommand = new Command5("whoami").description(
817
+ "Show this wallet, its agent ID on each chain and its requester reputation link on the selected --network"
818
+ ).action(async () => {
837
819
  const keystore = await loadKeystore();
838
820
  const selected = selectedNetwork();
839
821
  const chains = await Promise.all(
@@ -858,7 +840,7 @@ var whoamiCommand = new Command5("whoami").description("Show this wallet, its ag
858
840
 
859
841
  // src/commands/stats.ts
860
842
  import { Command as Command6 } from "commander";
861
- var statsCommand = new Command6("stats").description("View agent statistics").option("--address <addr>", "Wallet address (defaults to own wallet)").option("--agent <agentId>", "Agent ID (alternative to --address)").action(async (opts) => {
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) => {
862
844
  let address = opts.address;
863
845
  if (!address) {
864
846
  const keystore = await loadKeystore();
@@ -1330,6 +1312,66 @@ var reviewCmd = createReviewCommand();
1330
1312
  import { Command as Command8 } from "commander";
1331
1313
  import { parseUnits } from "viem";
1332
1314
 
1315
+ // src/lib/x402.ts
1316
+ var FACILITATOR_RETRIES = 2;
1317
+ var MAX_RETRY_AFTER_SECONDS = 60;
1318
+ var DEFAULT_RETRY_AFTER_SECONDS = 30;
1319
+ function retryAfterMs(res) {
1320
+ const header = res.headers?.get?.("retry-after");
1321
+ const seconds = header ? Number(header) : NaN;
1322
+ const wait = Number.isFinite(seconds) && seconds >= 0 ? seconds : DEFAULT_RETRY_AFTER_SECONDS;
1323
+ return Math.min(wait, MAX_RETRY_AFTER_SECONDS) * 1e3;
1324
+ }
1325
+ async function x402Post(path3, body, options) {
1326
+ const sleep4 = options?.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1327
+ if (paymentProtocolOf(selectedNetwork().chainId) === "mpp")
1328
+ return mppPost(path3, body, options);
1329
+ const keystore = await loadKeystore();
1330
+ const idempotencyKey = resolveIdempotencyKey(options?.idempotencyKey);
1331
+ const request = paidWriteRequest(keystore, path3, body, idempotencyKey);
1332
+ return withIdempotentWrite(idempotencyKey, async () => {
1333
+ const r1 = await fetch(request.url, {
1334
+ method: "POST",
1335
+ redirect: "error",
1336
+ headers: request.headers,
1337
+ body: request.body
1338
+ });
1339
+ if (r1.status !== 402) {
1340
+ if (r1.ok) {
1341
+ return { data: await r1.json(), idempotencyKey };
1342
+ }
1343
+ throw refusedPaidWrite(path3, r1.status, await readFailureBody(r1), idempotencyKey);
1344
+ }
1345
+ const requirements = await r1.json();
1346
+ if (!requirements.accepts || requirements.accepts.length === 0) {
1347
+ throw new Error("No payment methods accepted by server");
1348
+ }
1349
+ const accept = requirements.accepts[0];
1350
+ const { header } = await signTaskmarketFeePayment({
1351
+ resource: requirements.resource,
1352
+ requirement: accept,
1353
+ typedData: accept.extra.eip712,
1354
+ from: keystore.walletAddress,
1355
+ signTypedData: (typedData) => signTypedData(typedData, keystore)
1356
+ });
1357
+ for (let attempt = 0; ; attempt++) {
1358
+ const r2 = await fetch(request.url, {
1359
+ method: "POST",
1360
+ redirect: "error",
1361
+ headers: { ...request.headers, "PAYMENT-SIGNATURE": header },
1362
+ body: request.body
1363
+ });
1364
+ if (r2.ok) return { data: await r2.json(), idempotencyKey };
1365
+ const read = await readFailureBody(r2);
1366
+ if (r2.status === 503 && apiErrorEnvelopeOf(read.body)?.reason === "facilitator_unavailable" && attempt < FACILITATOR_RETRIES) {
1367
+ await sleep4(retryAfterMs(r2));
1368
+ continue;
1369
+ }
1370
+ throw failedAfterPayment(path3, r2.status, read, idempotencyKey);
1371
+ }
1372
+ });
1373
+ }
1374
+
1333
1375
  // src/lib/settlement-terms.ts
1334
1376
  var TERM_FLAGS = {
1335
1377
  stakeRequired: "--stake-required",
@@ -3246,14 +3288,14 @@ import { Command as Command49, Option as Option3 } from "commander";
3246
3288
  import { Command as Command47 } from "commander";
3247
3289
 
3248
3290
  // src/lib/tty-confirm.ts
3249
- import { createInterface as createInterface2 } from "readline";
3291
+ import { createInterface as createInterface3 } from "readline";
3250
3292
  async function confirmAtTerminal(lines, unattended) {
3251
3293
  if (!process.stdin.isTTY) {
3252
3294
  throw new Error(`Interactive confirmation requires a TTY; ${unattended}`);
3253
3295
  }
3254
3296
  process.stderr.write(`${lines.join("\n")}
3255
3297
  `);
3256
- const readline = createInterface2({ input: process.stdin, output: process.stderr });
3298
+ const readline = createInterface3({ input: process.stdin, output: process.stderr });
3257
3299
  const answer = await new Promise(
3258
3300
  (resolve) => readline.question("Type yes to approve: ", resolve)
3259
3301
  );
@@ -3445,7 +3487,7 @@ async function runAgentCommand(options) {
3445
3487
  try {
3446
3488
  const { assertAgentCompatibility } = await import("./compatibility-636WJOEX.js");
3447
3489
  const pi = assertAgentCompatibility();
3448
- const { runAgent } = await import("./launch-II23FNVJ.js");
3490
+ const { runAgent } = await import("./launch-QDCWAIKE.js");
3449
3491
  result = await runAgent({
3450
3492
  model: options.model,
3451
3493
  pi,
@@ -3504,13 +3546,13 @@ function agentManagementCommands() {
3504
3546
  const status = new Command48("status").description(
3505
3547
  "Show the agent channels (locked, charged, refundable), purchases with an unknown outcome, the sandbox and compute credit. Reads only."
3506
3548
  ).option("--json", "Print the versioned JSON envelope").action(async (options) => {
3507
- const { collectAgentStatus, statusLines } = await import("./status-CJKS7MHC.js");
3549
+ const { collectAgentStatus, statusLines } = await import("./status-FTTQWS5P.js");
3508
3550
  await run(options, () => collectAgentStatus(), statusLines);
3509
3551
  });
3510
3552
  const doctor = new Command48("doctor").description(
3511
3553
  "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."
3512
3554
  ).option("--json", "Print the versioned JSON envelope").action(async (options) => {
3513
- const { runDoctor, doctorLines } = await import("./doctor-KVWA7KOW.js");
3555
+ const { runDoctor, doctorLines } = await import("./doctor-26YOWQOH.js");
3514
3556
  const report = await run(options, () => runDoctor(), doctorLines);
3515
3557
  if (report && !report.ok) process.exitCode = 1;
3516
3558
  });
@@ -3521,7 +3563,7 @@ function agentManagementCommands() {
3521
3563
  "Reconcile the open purchases of this channel, as status lists it; also reaches retired channels"
3522
3564
  ).option("--json", "Print the versioned JSON envelope").action(
3523
3565
  async (invocationId, options) => {
3524
- const { reconcileChannelPurchases, reconcileInvocation } = await import("./reconcile-OZX2E2L3.js");
3566
+ const { reconcileChannelPurchases, reconcileInvocation } = await import("./reconcile-MALCM3NB.js");
3525
3567
  const choice = { rail: options.rail, channel: options.channel };
3526
3568
  if (invocationId !== void 0) {
3527
3569
  await run(
@@ -3579,7 +3621,7 @@ function agentManagementCommands() {
3579
3621
  `Not a USDC amount: ${options.amount} (digits, at most 6 decimals)`
3580
3622
  );
3581
3623
  }
3582
- const { openAgentChannels, requestTopUp, selectRail, withdrawalHatch } = await import("./channels-I6252ZCN.js");
3624
+ const { openAgentChannels, requestTopUp, selectRail, withdrawalHatch } = await import("./channels-OBJUNCZX.js");
3583
3625
  const { rails } = await openAgentChannels();
3584
3626
  const result = await requestTopUp(selectRail(rails, options.rail), amount);
3585
3627
  return {
@@ -3603,8 +3645,8 @@ function agentManagementCommands() {
3603
3645
  async () => {
3604
3646
  await requireExperimental();
3605
3647
  const { AGENT_VIEW_VERSION } = await import("./budget-view-J6L7X6EY.js");
3606
- const { closeChannel, openAgentChannels, selectChannel } = await import("./channels-I6252ZCN.js");
3607
- const { reconcileLeasedPurchase } = await import("./reconcile-OZX2E2L3.js");
3648
+ const { closeChannel, openAgentChannels, selectChannel } = await import("./channels-OBJUNCZX.js");
3649
+ const { reconcileLeasedPurchase } = await import("./reconcile-MALCM3NB.js");
3608
3650
  const opened = await openAgentChannels();
3609
3651
  const { rail, retired } = selectChannel(opened, options);
3610
3652
  const result = await closeChannel(
@@ -3675,7 +3717,7 @@ function agentManagementCommands() {
3675
3717
  options,
3676
3718
  async () => {
3677
3719
  await requireExperimental();
3678
- const { runPull } = await import("./sync-pull-NWOCLFGB.js");
3720
+ const { runPull } = await import("./sync-pull-N6OTHBWR.js");
3679
3721
  const { terminalPrompter } = await import("./prompter-LSICEYSQ.js");
3680
3722
  return runPull(options, {
3681
3723
  interactive: Boolean(process.stdin.isTTY && process.stdout.isTTY) && !options.json,
@@ -3738,7 +3780,7 @@ for (const command of agentManagementCommands()) {
3738
3780
 
3739
3781
  // src/commands/agents.ts
3740
3782
  import { Command as Command50 } from "commander";
3741
- var agentsCommand = new Command50("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) => {
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) => {
3742
3784
  const params = new URLSearchParams();
3743
3785
  if (opts.sort) params.set("sort", opts.sort);
3744
3786
  if (opts.skill) params.set("skill", opts.skill);
@@ -3804,12 +3846,24 @@ var depositCommand = new Command53("deposit").description("Show wallet address a
3804
3846
  renderFailure(err, { fallback: "Failed to fetch network info from backend." });
3805
3847
  return;
3806
3848
  }
3807
- const chain = chainInfoFor(networkInfo, selectedNetwork().chainId);
3808
- const chainId = chain?.chainId ?? networkInfo.chainId;
3809
- const tokenAddress = chain?.tokenAddress ?? networkInfo.usdcAddress;
3849
+ let chain;
3850
+ try {
3851
+ chain = chainInfoFor(networkInfo, selectedNetwork().chainId);
3852
+ } catch (err) {
3853
+ renderFailure(err);
3854
+ return;
3855
+ }
3856
+ if (!chain) {
3857
+ renderFailure(
3858
+ new Error("The API returned network info this CLI cannot read; upgrade the CLI or the API.")
3859
+ );
3860
+ return;
3861
+ }
3862
+ const chainId = chain.chainId;
3863
+ const tokenAddress = chain.tokenAddress;
3810
3864
  const data = {
3811
3865
  address,
3812
- network: chain?.networkName ?? networkInfo.networkName,
3866
+ network: chain.networkName,
3813
3867
  chainId,
3814
3868
  currency: paymentTokenSymbol(chainId),
3815
3869
  tokenAddress,
@@ -3838,7 +3892,7 @@ var walletBalanceCommand = new Command54("balance").description("Show the wallet
3838
3892
 
3839
3893
  // src/commands/wallet/import.ts
3840
3894
  import { Command as Command55 } from "commander";
3841
- import { createInterface as createInterface3 } from "readline";
3895
+ import { createInterface as createInterface4 } from "readline";
3842
3896
  import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
3843
3897
  function normalizePrivateKey(raw) {
3844
3898
  const hex = raw.startsWith("0x") ? raw.slice(2) : raw;
@@ -3849,7 +3903,7 @@ function normalizePrivateKey(raw) {
3849
3903
  }
3850
3904
  function promptHiddenInput(prompt) {
3851
3905
  return new Promise((resolve) => {
3852
- const rl = createInterface3({
3906
+ const rl = createInterface4({
3853
3907
  input: process.stdin,
3854
3908
  output: process.stdout,
3855
3909
  terminal: true
@@ -3878,7 +3932,10 @@ var walletImportCommand = new Command55("import").description("Import an existin
3878
3932
  ).action(async (opts) => {
3879
3933
  if (await keystoreExists()) {
3880
3934
  const keystore = await loadKeystore();
3881
- printResult({ address: keystore.walletAddress, agentId: keystore.agentId });
3935
+ printResult({
3936
+ address: keystore.walletAddress,
3937
+ agentId: agentIdForChain(keystore, selectedNetwork().chainId)
3938
+ });
3882
3939
  return;
3883
3940
  }
3884
3941
  let rawKey;
@@ -3926,6 +3983,7 @@ var walletImportCommand = new Command55("import").description("Import an existin
3926
3983
  deviceId,
3927
3984
  apiToken,
3928
3985
  agentId,
3986
+ ...agentId ? { agentIds: { [String(selectedNetwork().chainId)]: agentId } } : {},
3929
3987
  keyServerUrl: apiUrl(),
3930
3988
  network: networkToStamp(),
3931
3989
  ...legalAcceptance ? {
@@ -3938,7 +3996,9 @@ var walletImportCommand = new Command55("import").description("Import an existin
3938
3996
  agentId = await pollAgentId(address);
3939
3997
  if (agentId) {
3940
3998
  const keystore = await loadKeystore();
3941
- await saveKeystore({ ...keystore, agentId });
3999
+ await saveKeystore(
4000
+ withAgentIdForChain({ ...keystore, agentId }, selectedNetwork().chainId, agentId)
4001
+ );
3942
4002
  }
3943
4003
  }
3944
4004
  if (keySource === "flag") {
@@ -4258,7 +4318,11 @@ var withdrawDreamsCommand = new Command62("withdraw-dreams").description("Withdr
4258
4318
  withChainId(`/api/wallet/dreams-balance?address=${workerAddress}`)
4259
4319
  );
4260
4320
  if (!balance.hookAddress || balance.chainId === void 0) {
4261
- printError("DREAMS rewards are not configured on this server");
4321
+ const chainId = selectedNetwork().chainId;
4322
+ const chain = isTaskmarketChainId(chainId) ? taskmarketChain(chainId) : void 0;
4323
+ printError(
4324
+ chain && !chain.features.dreamsRewards ? `${chain.name} has no DREAMS rewards` : "DREAMS rewards are not configured on this server"
4325
+ );
4262
4326
  return;
4263
4327
  }
4264
4328
  if (!isTaskmarketChainId(balance.chainId)) {
@@ -5772,6 +5836,33 @@ function sleepOrAbort(ms, signal) {
5772
5836
  });
5773
5837
  }
5774
5838
  var MAX_SEEN_TASK_IDS = 2e3;
5839
+ function buildDaemonTaskParams(filters, chainId) {
5840
+ const params = new URLSearchParams();
5841
+ params.set("status", "open");
5842
+ params.set("limit", "50");
5843
+ params.set("chainId", String(chainId));
5844
+ if (typeof filters.mode === "string") {
5845
+ params.set("mode", filters.mode);
5846
+ }
5847
+ const tagsValue = filters.tags;
5848
+ if (typeof tagsValue === "string") {
5849
+ params.set("tags", tagsValue);
5850
+ } else if (Array.isArray(tagsValue)) {
5851
+ params.set("tags", tagsValue.join(","));
5852
+ }
5853
+ return params;
5854
+ }
5855
+ function buildDaemonAuctionParams(chainId) {
5856
+ return new URLSearchParams({
5857
+ mode: "auction",
5858
+ status: "open",
5859
+ limit: "50",
5860
+ chainId: String(chainId)
5861
+ });
5862
+ }
5863
+ function daemonInboxPath(address, chainId) {
5864
+ return `/api/agents/inbox?address=${encodeURIComponent(address)}&chainId=${chainId}`;
5865
+ }
5775
5866
  var daemonCommand = new Command69("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(
5776
5867
  "--auction-poll-interval <ms>",
5777
5868
  "Poll interval for clock-based auction tasks (dutch/reverse_dutch) in milliseconds",
@@ -5876,24 +5967,10 @@ var daemonCommand = new Command69("daemon").description("Long-running agent daem
5876
5967
  const taskPollLoop = async () => {
5877
5968
  const knownStatuses = /* @__PURE__ */ new Map();
5878
5969
  const seenTaskIds = /* @__PURE__ */ new Set();
5879
- const buildTaskParams = () => {
5880
- const params = new URLSearchParams();
5881
- params.set("status", "open");
5882
- params.set("limit", "50");
5883
- if (typeof taskFilters.mode === "string") {
5884
- params.set("mode", taskFilters.mode);
5885
- }
5886
- const tagsValue = taskFilters.tags;
5887
- if (typeof tagsValue === "string") {
5888
- params.set("tags", tagsValue);
5889
- } else if (Array.isArray(tagsValue)) {
5890
- params.set("tags", tagsValue.join(","));
5891
- }
5892
- return params;
5893
- };
5970
+ const buildTaskParams = () => buildDaemonTaskParams(taskFilters, selectedNetwork().chainId);
5894
5971
  try {
5895
5972
  const inbox = await apiGet(
5896
- `/api/agents/inbox?address=${encodeURIComponent(address)}`
5973
+ daemonInboxPath(address, selectedNetwork().chainId)
5897
5974
  );
5898
5975
  for (const task of [...inbox.asRequester, ...inbox.asWorker]) {
5899
5976
  knownStatuses.set(task.id, task.status);
@@ -5913,7 +5990,7 @@ var daemonCommand = new Command69("daemon").description("Long-running agent daem
5913
5990
  if (stopped) break;
5914
5991
  try {
5915
5992
  const inbox = await apiGet(
5916
- `/api/agents/inbox?address=${encodeURIComponent(address)}`
5993
+ daemonInboxPath(address, selectedNetwork().chainId)
5917
5994
  );
5918
5995
  const allTasks = [...inbox.asRequester, ...inbox.asWorker];
5919
5996
  const nextStatuses = /* @__PURE__ */ new Map();
@@ -5926,7 +6003,9 @@ var daemonCommand = new Command69("daemon").description("Long-running agent daem
5926
6003
  const role = isRequester ? "requester" : "worker";
5927
6004
  let pendingActions = [];
5928
6005
  try {
5929
- const detail = await apiGet(`/api/tasks/${change.taskId}`);
6006
+ const detail = await apiGet(
6007
+ `/api/tasks/${change.taskId}?chainId=${selectedNetwork().chainId}`
6008
+ );
5930
6009
  pendingActions = detail.pendingActions ?? [];
5931
6010
  } catch {
5932
6011
  }
@@ -6001,11 +6080,7 @@ var daemonCommand = new Command69("daemon").description("Long-running agent daem
6001
6080
  let cursor;
6002
6081
  let hasMore = true;
6003
6082
  while (hasMore) {
6004
- const params = new URLSearchParams({
6005
- mode: "auction",
6006
- status: "open",
6007
- limit: "50"
6008
- });
6083
+ const params = buildDaemonAuctionParams(selectedNetwork().chainId);
6009
6084
  if (cursor) params.set("cursor", cursor);
6010
6085
  const result = await apiGet(`/api/tasks?${params.toString()}`);
6011
6086
  for (const task of result.tasks) {
@@ -6676,7 +6751,7 @@ import { Command as Command93 } from "commander";
6676
6751
 
6677
6752
  // src/commands/x402/payments.ts
6678
6753
  import { Command as Command90, Option as Option4 } from "commander";
6679
- import { createInterface as createInterface4 } from "readline";
6754
+ import { createInterface as createInterface5 } from "readline";
6680
6755
  var PAYMENT_STATES = [
6681
6756
  "reserved",
6682
6757
  "approval_pending",
@@ -6691,7 +6766,7 @@ var PAYMENT_STATES = [
6691
6766
  ];
6692
6767
  async function confirmManualResolution() {
6693
6768
  if (!process.stdin.isTTY) throw new Error("Manual resolution requires an interactive TTY");
6694
- const readline = createInterface4({ input: process.stdin, output: process.stderr });
6769
+ const readline = createInterface5({ input: process.stdin, output: process.stderr });
6695
6770
  const answer = await new Promise(
6696
6771
  (resolve) => readline.question(
6697
6772
  "Manual resolution changes local spending accounting. Type resolve to continue: ",
@@ -6731,7 +6806,7 @@ x402PaymentsCommand.command("resolve").description("Manually record an externall
6731
6806
  // src/commands/x402/policy.ts
6732
6807
  import { promises as fs4 } from "fs";
6733
6808
  import { Command as Command91 } from "commander";
6734
- import { createInterface as createInterface5 } from "readline";
6809
+ import { createInterface as createInterface6 } from "readline";
6735
6810
  async function confirmUnattendedRule(rule) {
6736
6811
  if (!process.stdin.isTTY) {
6737
6812
  throw new Error("Authorizing an unattended policy rule requires an interactive TTY");
@@ -6749,7 +6824,7 @@ async function confirmUnattendedRule(rule) {
6749
6824
  ].join("\n")}
6750
6825
  `
6751
6826
  );
6752
- const readline = createInterface5({ input: process.stdin, output: process.stderr });
6827
+ const readline = createInterface6({ input: process.stdin, output: process.stderr });
6753
6828
  const answer = await new Promise(
6754
6829
  (resolve) => readline.question("Type authorize to grant unattended spending: ", resolve)
6755
6830
  );
@@ -10714,7 +10789,7 @@ setLastErrorCliVersion(version);
10714
10789
  program.name("taskmarket").description("Taskmarket CLI for AI agents").version(version);
10715
10790
  program.option(
10716
10791
  "--network <name>",
10717
- `Network to use: ${NETWORK_NAMES.join(", ")} (default: TASKMARKET_NETWORK, then the keystore's network, then base)`
10792
+ `Network to use: ${NETWORK_NAMES.join(", ")} (else TASKMARKET_NETWORK, then the keystore's network; there is no default)`
10718
10793
  ).hook("preAction", async (thisCommand) => {
10719
10794
  const { network } = thisCommand.opts();
10720
10795
  setSelectedNetwork(