agentcash 0.7.7 → 0.8.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.
Files changed (54) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/run-server.cjs +59 -28
  3. package/dist/esm/{chunk-5EMDWOPZ.js → chunk-4R52CY5Q.js} +23 -23
  4. package/dist/esm/chunk-4R52CY5Q.js.map +1 -0
  5. package/dist/esm/{chunk-2XMLNLWS.js → chunk-5ELAEV2M.js} +9 -7
  6. package/dist/esm/{chunk-2XMLNLWS.js.map → chunk-5ELAEV2M.js.map} +1 -1
  7. package/dist/esm/{chunk-SRV57WB2.js → chunk-62B3GENJ.js} +8 -6
  8. package/dist/esm/{chunk-SRV57WB2.js.map → chunk-62B3GENJ.js.map} +1 -1
  9. package/dist/esm/{chunk-TRPO7BKD.js → chunk-6PU3XK6I.js} +8 -228
  10. package/dist/esm/chunk-6PU3XK6I.js.map +1 -0
  11. package/dist/esm/{chunk-FLIDR6EU.js → chunk-7ZEXMJYJ.js} +5 -3
  12. package/dist/esm/{chunk-FLIDR6EU.js.map → chunk-7ZEXMJYJ.js.map} +1 -1
  13. package/dist/esm/{chunk-QPL3AVUK.js → chunk-C36IAW7R.js} +5 -3
  14. package/dist/esm/{chunk-QPL3AVUK.js.map → chunk-C36IAW7R.js.map} +1 -1
  15. package/dist/esm/chunk-FBPC4LGY.js +7 -0
  16. package/dist/esm/{chunk-PWYZN62H.js → chunk-OHA3LLUQ.js} +3 -3
  17. package/dist/esm/{chunk-24E2V3PA.js → chunk-UN3PRLTL.js} +15 -43
  18. package/dist/esm/chunk-UN3PRLTL.js.map +1 -0
  19. package/dist/esm/{chunk-JKCEMNAF.js → chunk-VR5I67WE.js} +2 -2
  20. package/dist/esm/{chunk-XNU6FVCF.js → chunk-W7DAJMFQ.js} +87 -19
  21. package/dist/esm/chunk-W7DAJMFQ.js.map +1 -0
  22. package/dist/esm/chunk-YQFK4U62.js +230 -0
  23. package/dist/esm/chunk-YQFK4U62.js.map +1 -0
  24. package/dist/esm/{chunk-X6KM3YLG.js → chunk-Z2R7VYNM.js} +11 -9
  25. package/dist/esm/{chunk-X6KM3YLG.js.map → chunk-Z2R7VYNM.js.map} +1 -1
  26. package/dist/esm/chunk-ZDDDU5O2.js +41 -0
  27. package/dist/esm/chunk-ZDDDU5O2.js.map +1 -0
  28. package/dist/esm/{chunk-KPEJO3KV.js → chunk-ZOVLXKVL.js} +8 -8
  29. package/dist/esm/chunk-ZOVLXKVL.js.map +1 -0
  30. package/dist/esm/{commands-IFU565JX.js → commands-YSOBBE4N.js} +625 -504
  31. package/dist/esm/commands-YSOBBE4N.js.map +1 -0
  32. package/dist/esm/{fund-N47ZRBRZ.js → fund-PRV53MDA.js} +7 -5
  33. package/dist/esm/{fund-N47ZRBRZ.js.map → fund-PRV53MDA.js.map} +1 -1
  34. package/dist/esm/index.js +65 -23
  35. package/dist/esm/index.js.map +1 -1
  36. package/dist/esm/{install-WJ645IFJ.js → install-QT37XD4R.js} +10 -8
  37. package/dist/esm/{install-WJ645IFJ.js.map → install-QT37XD4R.js.map} +1 -1
  38. package/dist/esm/lib.js +4 -3
  39. package/dist/esm/{server-VU3UAM7K.js → server-QARME5NA.js} +26 -19
  40. package/dist/esm/server-QARME5NA.js.map +1 -0
  41. package/dist/esm/shared/operations/index.js +7 -6
  42. package/dist/esm/shared/operations/index.js.map +1 -1
  43. package/package.json +1 -1
  44. package/dist/esm/chunk-24E2V3PA.js.map +0 -1
  45. package/dist/esm/chunk-5EMDWOPZ.js.map +0 -1
  46. package/dist/esm/chunk-KPEJO3KV.js.map +0 -1
  47. package/dist/esm/chunk-L7FC4RVF.js +0 -7
  48. package/dist/esm/chunk-TRPO7BKD.js.map +0 -1
  49. package/dist/esm/chunk-XNU6FVCF.js.map +0 -1
  50. package/dist/esm/commands-IFU565JX.js.map +0 -1
  51. package/dist/esm/server-VU3UAM7K.js.map +0 -1
  52. /package/dist/esm/{chunk-L7FC4RVF.js.map → chunk-FBPC4LGY.js.map} +0 -0
  53. /package/dist/esm/{chunk-PWYZN62H.js.map → chunk-OHA3LLUQ.js.map} +0 -0
  54. /package/dist/esm/{chunk-JKCEMNAF.js.map → chunk-VR5I67WE.js.map} +0 -0
@@ -1,51 +1,61 @@
1
1
  import {
2
2
  registerOrigin
3
- } from "./chunk-QPL3AVUK.js";
3
+ } from "./chunk-C36IAW7R.js";
4
4
  import {
5
5
  buildRequest,
6
6
  createFetchWithAuth,
7
7
  createFetchWithPayment,
8
8
  requestSchema
9
- } from "./chunk-X6KM3YLG.js";
10
- import "./chunk-XNU6FVCF.js";
9
+ } from "./chunk-Z2R7VYNM.js";
10
+ import {
11
+ ORIGIN_METADATA,
12
+ PRIMARY_ORIGINS,
13
+ addUserOrigin,
14
+ loadUserOrigins,
15
+ removeUserOrigin
16
+ } from "./chunk-W7DAJMFQ.js";
11
17
  import {
12
18
  TEMPO_RPC_URL,
13
19
  getOnboardingCta,
14
20
  getWalletInfo,
15
21
  submitErrorReport
16
- } from "./chunk-SRV57WB2.js";
17
- import "./chunk-L7FC4RVF.js";
22
+ } from "./chunk-62B3GENJ.js";
23
+ import "./chunk-FBPC4LGY.js";
18
24
  import {
19
25
  checkEndpoint,
20
26
  discoverResources
21
- } from "./chunk-5EMDWOPZ.js";
27
+ } from "./chunk-4R52CY5Q.js";
22
28
  import {
23
29
  getPlatformPath,
24
30
  tryAddServer
25
- } from "./chunk-2XMLNLWS.js";
26
- import "./chunk-KPEJO3KV.js";
31
+ } from "./chunk-5ELAEV2M.js";
32
+ import "./chunk-ZOVLXKVL.js";
27
33
  import {
28
34
  MCP_VERSION
29
- } from "./chunk-JKCEMNAF.js";
35
+ } from "./chunk-VR5I67WE.js";
30
36
  import "./chunk-DZNSJ2BA.js";
31
37
  import {
32
38
  DEFAULT_NETWORK,
33
39
  getWallet,
34
- redeemInviteCode,
40
+ redeemInviteCode
41
+ } from "./chunk-UN3PRLTL.js";
42
+ import {
35
43
  safeParseJson,
36
44
  toJsonObject
37
- } from "./chunk-24E2V3PA.js";
45
+ } from "./chunk-ZDDDU5O2.js";
38
46
  import {
39
47
  getBaseUrl,
40
48
  getDepositLink
41
- } from "./chunk-FLIDR6EU.js";
49
+ } from "./chunk-7ZEXMJYJ.js";
42
50
  import {
43
51
  DEFAULT_USER_FETCH_TIMEOUT,
44
- resultFromPromise,
45
52
  safeFetch,
46
53
  safeFetchJson,
47
54
  safeParseResponse
48
- } from "./chunk-TRPO7BKD.js";
55
+ } from "./chunk-YQFK4U62.js";
56
+ import {
57
+ resultFromPromise
58
+ } from "./chunk-6PU3XK6I.js";
49
59
  import "./chunk-ISR6DJ53.js";
50
60
 
51
61
  // src/cli/commands/fetch.ts
@@ -317,348 +327,66 @@ function parseRequestInput(surface, args, flags) {
317
327
  return inputResult.data;
318
328
  }
319
329
 
320
- // src/cli/commands/fetch.ts
321
- var SURFACE = "cli:fetch";
322
- async function fetchCommand(args, flags) {
323
- const { account } = await getWalletOrExit(flags);
324
- const sessionId = randomBytes(16).toString("hex");
325
- const input = parseRequestInput(SURFACE, args, flags);
326
- const publicClient = createPublicClient({
327
- chain: base,
328
- transport: http()
329
- });
330
- const coreClient = x402Client.fromConfig({
331
- schemes: [
332
- {
333
- network: DEFAULT_NETWORK,
334
- client: new ExactEvmScheme(toClientEvmSigner(account, publicClient))
335
- }
336
- ]
337
- });
338
- const x402HttpClient = new x402HTTPClient(coreClient);
339
- const mppxClient = Mppx.create({
340
- polyfill: false,
341
- methods: [
342
- tempoMethod({
343
- account,
344
- getClient: () => createClient({ chain: tempo, transport: http(TEMPO_RPC_URL) })
345
- })
346
- ]
347
- });
348
- const provider = flags.provider ?? `agentcash@${MCP_VERSION}`;
349
- const paymentMethod = args.paymentMethod ?? "auto";
350
- const request = buildRequest({
351
- input,
352
- address: account.address,
353
- sessionId,
354
- provider
355
- });
356
- const fetchResult = await createFetchWithPayment({
357
- surface: SURFACE,
358
- clients: { x402: x402HttpClient, mpp: mppxClient },
359
- paymentMethod,
360
- account,
361
- flags
362
- })(request);
363
- if (fetchResult.isErr()) {
364
- return outputAndExit(fromNeverthrowError(fetchResult), flags);
365
- }
366
- const { response, paymentInfo } = fetchResult.value;
367
- if (!response.ok) {
368
- const parseResult = await safeParseResponse(SURFACE, response);
369
- const details = { statusCode: response.status };
370
- let serverMessage;
371
- if (parseResult.isOk()) {
372
- const { type } = parseResult.value;
373
- if (type === "json") {
374
- details.body = parseResult.value.data;
375
- serverMessage = extractJsonErrorMessage(parseResult.value.data);
376
- } else if (type === "text") {
377
- details.body = parseResult.value.data;
378
- serverMessage = parseResult.value.data;
379
- } else {
380
- details.bodyType = type;
381
- }
382
- }
383
- return outputAndExit(
384
- errorResponse({
385
- code: "HTTP_ERROR",
386
- message: serverMessage ?? response.statusText,
387
- surface: SURFACE,
388
- cause: "http",
389
- details
390
- }),
391
- flags
392
- );
393
- }
394
- const parseResponseResult = await safeParseResponse(SURFACE, response);
395
- if (parseResponseResult.isErr()) {
396
- return outputAndExit(fromNeverthrowError(parseResponseResult), flags);
397
- }
398
- const data = parseResponseResult.value.type === "json" ? parseResponseResult.value.data : parseResponseResult.value.type === "text" ? parseResponseResult.value.data : { type: parseResponseResult.value.type };
399
- const metadata = paymentInfo ? {
400
- protocol: paymentInfo.protocol,
401
- ...paymentInfo.price ? { price: paymentInfo.price } : {},
402
- ...paymentInfo.payment ? { payment: paymentInfo.payment } : {}
403
- } : void 0;
404
- outputAndExit(successResponse(data, metadata), flags);
330
+ // src/cli/commands/lib/resolve-origin.ts
331
+ function resolveTitle(result, url) {
332
+ if (result.info?.title) return result.info.title;
333
+ const hostname = new URL(url).hostname.replace(/^www\./, "");
334
+ const parts = hostname.split(".");
335
+ return parts.length > 1 ? parts.slice(0, -1).join(".") : hostname;
405
336
  }
406
- function extractJsonErrorMessage(body) {
407
- if (typeof body === "object" && body !== null) {
408
- const obj = body;
409
- if (typeof obj.error === "string") return obj.error;
410
- if (typeof obj.error === "object" && obj.error !== null && typeof obj.error.message === "string") {
411
- return obj.error.message;
412
- }
413
- if (typeof obj.message === "string") return obj.message;
414
- }
415
- return void 0;
337
+ function resolveDescription(result) {
338
+ if (result.info?.description) return result.info.description;
339
+ if (result.guidance) return result.guidance.slice(0, 100);
340
+ return null;
416
341
  }
417
-
418
- // src/cli/commands/fetch-auth.ts
419
- import { randomBytes as randomBytes2 } from "crypto";
420
- var SURFACE2 = "cli:fetch-auth";
421
- async function fetchAuthCommand(args, flags) {
422
- const { account } = await getWalletOrExit(flags);
423
- const sessionId = randomBytes2(16).toString("hex");
424
- const input = parseRequestInput(SURFACE2, args, flags);
425
- const result = await createFetchWithAuth({
426
- surface: SURFACE2,
427
- account,
428
- timeout: input.timeout ?? DEFAULT_USER_FETCH_TIMEOUT
429
- })(buildRequest({ input, address: account.address, sessionId }));
430
- if (result.isErr()) {
431
- return outputAndExit(fromNeverthrowError(result), flags);
432
- }
433
- const value = result.value;
434
- if (value.outcome === "no_siwx_extension") {
435
- return outputAndExit(
436
- errorResponse({
342
+ async function resolveOrigin(rawUrl, surface) {
343
+ const url = /^https?:\/\//i.test(rawUrl) ? rawUrl : `https://${rawUrl}`;
344
+ if (!URL.canParse(url)) {
345
+ return {
346
+ ok: false,
347
+ error: errorResponse({
437
348
  code: "GENERAL_ERROR",
438
- message: "Endpoint returned 402 but no sign-in-with-x extension found. Use `fetch` for paid endpoints.",
439
- surface: SURFACE2,
440
- cause: "no_siwx_extension",
441
- details: { extensions: value.extensions }
442
- }),
443
- flags
444
- );
445
- }
446
- const { response } = value;
447
- if (!response.ok) {
448
- return outputAndExit(
449
- errorResponse({
450
- code: "HTTP_ERROR",
451
- message: response.statusText,
452
- surface: SURFACE2,
453
- cause: "http",
454
- details: { statusCode: response.status }
455
- }),
456
- flags
457
- );
458
- }
459
- const parseResult = await safeParseResponse(SURFACE2, response);
460
- if (parseResult.isErr()) {
461
- return outputAndExit(fromNeverthrowError(parseResult), flags);
349
+ message: `Invalid URL: ${url}`,
350
+ surface,
351
+ cause: "invalid_url"
352
+ })
353
+ };
462
354
  }
463
- const data = parseResult.value.type === "json" ? parseResult.value.data : parseResult.value.type === "text" ? parseResult.value.data : { type: parseResult.value.type };
464
- outputAndExit(successResponse(data), flags);
465
- }
466
-
467
- // src/cli/commands/check.ts
468
- import { randomBytes as randomBytes3 } from "crypto";
469
- var SURFACE3 = "cli:check";
470
- async function checkCommand(args, flags) {
471
- const { account } = await getWalletOrExit(flags);
472
- const sessionId = randomBytes3(16).toString("hex");
473
- const parsedBody = args.body ? JSON.parse(args.body) : void 0;
474
- const parsedHeaders = args.headers ? JSON.parse(args.headers) : void 0;
475
- const result = await checkEndpoint(
476
- SURFACE3,
477
- args.url,
478
- args.method ? [args.method] : void 0,
479
- parsedBody,
480
- {
481
- ...parsedHeaders,
482
- "X-Wallet-Address": account.address,
483
- "X-Session-ID": sessionId
484
- }
485
- );
355
+ const result = await discoverResources(surface, url);
486
356
  if (!result.found) {
487
- return outputAndExit(
488
- successResponse(
489
- toJsonObject({
490
- url: args.url,
491
- error: result.cause,
492
- message: result.message
493
- })
494
- ),
495
- flags
496
- );
357
+ return {
358
+ ok: false,
359
+ error: errorResponse({
360
+ code: "GENERAL_ERROR",
361
+ message: result.message ?? `No OpenAPI spec found for ${url}`,
362
+ surface,
363
+ cause: result.cause
364
+ })
365
+ };
497
366
  }
498
- const results = result.advisories.map((a) => ({
499
- ...a,
500
- requiresPayment: a.authMode === "paid" || a.authMode === "apiKey+paid"
501
- }));
502
- return outputAndExit(
503
- successResponse(toJsonObject({ url: args.url, results })),
504
- flags
505
- );
506
- }
507
-
508
- // src/cli/commands/discover.ts
509
- async function discoverCommand(args, flags) {
510
- const result = await discoverResources("cli:discover", args.url, {
511
- includeGuidance: args.includeGuidance
512
- });
513
- if (result.found) {
514
- return outputAndExit(
515
- successResponse({
516
- found: true,
517
- origin: result.origin,
518
- source: result.source,
519
- ...result.info ? { info: result.info } : {},
520
- guidanceAvailable: result.guidanceAvailable,
521
- ...result.guidanceTokens != null ? { guidanceTokens: result.guidanceTokens } : {},
522
- ...result.guidance ? { guidance: result.guidance } : {},
523
- endpoints: result.endpoints.map((e) => ({ ...e }))
524
- }),
525
- flags
367
+ const description = resolveDescription(result) ?? "";
368
+ const warnings = [];
369
+ if (!result.info?.title)
370
+ warnings.push("No title found in OpenAPI spec; derived from URL.");
371
+ if (!result.info?.description)
372
+ warnings.push(
373
+ description ? "No description found in OpenAPI spec; derived from guidance." : "No description could be found."
526
374
  );
527
- }
528
- const origin = URL.canParse(args.url) ? new URL(args.url).origin : args.url;
529
- return outputAndExit(
530
- errorResponse({
531
- code: "GENERAL_ERROR",
532
- message: result.message ?? `No OpenAPI spec found for ${origin}. Tried: /openapi.json, /.well-known/openapi.json`,
533
- surface: "cli:discover",
534
- cause: result.cause,
535
- details: { origin }
536
- }),
537
- flags
538
- );
375
+ return {
376
+ ok: true,
377
+ origin: {
378
+ url,
379
+ title: resolveTitle(result, url),
380
+ description,
381
+ warnings
382
+ }
383
+ };
539
384
  }
540
385
 
541
- // src/cli/commands/register.ts
542
- var SURFACE4 = "cli:register";
543
- async function registerCommand(args, flags) {
544
- const result = await registerOrigin(SURFACE4, { url: args.url }, flags.dev);
545
- if (result.isErr()) {
546
- return outputAndExit(fromNeverthrowError(result), flags);
547
- }
548
- const { origin, resourceCount } = result.value;
549
- return outputAndExit(
550
- successResponse({
551
- origin: {
552
- id: origin.id,
553
- origin: origin.origin,
554
- name: origin.name
555
- },
556
- resourceCount
557
- }),
558
- flags
559
- );
560
- }
561
-
562
- // src/cli/commands/wallet.ts
563
- var SURFACE5 = "cli:wallet";
564
- async function walletInfoCommand(_args, flags) {
565
- const { account } = await getWalletOrExit(flags);
566
- const result = await getWalletInfo(SURFACE5, account.address, flags);
567
- if (result.isErr()) {
568
- return outputAndExit(fromNeverthrowError(result), flags);
569
- }
570
- return outputAndExit(
571
- successResponse({
572
- address: result.value.address,
573
- balance: result.value.balance,
574
- chains: result.value.chains.map((c) => ({
575
- chain: c.chain,
576
- balance: c.balance
577
- })),
578
- isNewWallet: result.value.isNewWallet,
579
- depositLink: result.value.depositLink,
580
- ...result.value.onboardingCta ? {
581
- onboardingCta: {
582
- onboardLink: result.value.onboardingCta.onboardLink,
583
- depositLink: result.value.onboardingCta.depositLink,
584
- message: result.value.onboardingCta.message
585
- }
586
- } : {},
587
- ...result.value.message ? { message: result.value.message } : {}
588
- }),
589
- flags
590
- );
591
- }
592
- async function walletRedeemCommand(args, flags) {
593
- const { account } = await getWalletOrExit(flags);
594
- const result = await redeemInviteCode({
595
- code: args.code,
596
- address: account.address,
597
- surface: SURFACE5,
598
- dev: flags.dev
599
- });
600
- if (result.isErr()) {
601
- return outputAndExit(fromNeverthrowError(result), flags);
602
- }
603
- return outputAndExit(
604
- successResponse({
605
- redeemed: true,
606
- amount: `${result.value.amount} USDC`,
607
- txHash: result.value.txHash
608
- }),
609
- flags
610
- );
611
- }
612
- async function walletAddressCommand(_args, flags) {
613
- const { account } = await getWalletOrExit(flags);
614
- return outputAndExit(successResponse({ address: account.address }), flags);
615
- }
616
-
617
- // src/cli/commands/report-error.ts
618
- var SURFACE6 = "cli:report-error";
619
- async function reportErrorCommand(args, flags) {
620
- const { account } = await getWalletOrExit(flags);
621
- const result = await submitErrorReport(
622
- SURFACE6,
623
- {
624
- tool: args.tool,
625
- summary: args.summary,
626
- errorMessage: args.errorMessage,
627
- resource: args.resource,
628
- stack: args.stack,
629
- fullReport: args.fullReport
630
- },
631
- account.address,
632
- flags.dev
633
- );
634
- if (result.isErr()) {
635
- return outputAndExit(fromNeverthrowError(result), flags);
636
- }
637
- return outputAndExit(
638
- successResponse({
639
- submitted: result.value.submitted,
640
- reportId: result.value.reportId,
641
- message: result.value.message
642
- }),
643
- flags
644
- );
645
- }
646
-
647
- // src/cli/commands/server.ts
648
- async function serverCommand(flags) {
649
- if (process.stdout.isTTY) {
650
- process.stdout.write(
651
- "MCP server started. If you meant to explore the CLI, run: npx agentcash --help\n"
652
- );
653
- }
654
- const { startServer } = await import("./server-VU3UAM7K.js");
655
- await startServer(flags);
656
- }
657
-
658
- // src/cli/commands/add-skill.ts
659
- import * as fs2 from "fs/promises";
660
- import * as os2 from "os";
661
- import * as path2 from "path";
386
+ // src/cli/commands/lib/add-origin-skill.ts
387
+ import * as fs2 from "fs/promises";
388
+ import * as os2 from "os";
389
+ import * as path2 from "path";
662
390
 
663
391
  // src/shared/skills/agents.ts
664
392
  import * as fs from "fs";
@@ -829,175 +557,558 @@ var all = [
829
557
  function detect() {
830
558
  return all.filter((a) => a.detect());
831
559
  }
832
- function installSkills(sourceDir, options = {}) {
833
- const isGlobal = options.global !== false;
834
- const cwd = options.cwd ?? process.cwd();
835
- const base2 = isGlobal ? home : cwd;
836
- const canonicalBase = path.join(base2, ".agents", "skills");
837
- const detected = options.agents ?? detect();
838
- const paths = [];
839
- const agents = [];
840
- for (const skill of discoverSkills(sourceDir)) {
841
- const canonicalDir = path.join(canonicalBase, skill.name);
842
- rmForce(canonicalDir);
843
- fs.mkdirSync(canonicalDir, { recursive: true });
844
- if (skill.root)
845
- fs.copyFileSync(
846
- path.join(skill.dir, "SKILL.md"),
847
- path.join(canonicalDir, "SKILL.md")
848
- );
849
- else fs.cpSync(skill.dir, canonicalDir, { recursive: true });
850
- paths.push(canonicalDir);
851
- for (const agent of detected) {
852
- if (agent.universal) continue;
853
- const agentSkillsDir = isGlobal ? agent.globalSkillsDir : path.join(cwd, agent.projectSkillsDir);
854
- const agentDir = path.join(agentSkillsDir, skill.name);
855
- if (agentDir === canonicalDir) continue;
856
- try {
857
- rmForce(agentDir);
858
- fs.mkdirSync(path.dirname(agentDir), { recursive: true });
859
- const realLinkDir = resolveParent(path.dirname(agentDir));
860
- const realTarget = resolveParent(canonicalDir);
861
- const rel = path.relative(realLinkDir, realTarget);
862
- fs.symlinkSync(rel, agentDir);
863
- agents.push({ agent: agent.name, path: agentDir, mode: "symlink" });
864
- } catch {
865
- try {
866
- fs.cpSync(canonicalDir, agentDir, { recursive: true });
867
- agents.push({ agent: agent.name, path: agentDir, mode: "copy" });
868
- } catch {
869
- }
870
- }
871
- }
560
+ function installSkills(sourceDir, options = {}) {
561
+ const isGlobal = options.global !== false;
562
+ const cwd = options.cwd ?? process.cwd();
563
+ const base2 = isGlobal ? home : cwd;
564
+ const canonicalBase = path.join(base2, ".agents", "skills");
565
+ const detected = options.agents ?? detect();
566
+ const paths = [];
567
+ const agents = [];
568
+ for (const skill of discoverSkills(sourceDir)) {
569
+ const canonicalDir = path.join(canonicalBase, skill.name);
570
+ rmForce(canonicalDir);
571
+ fs.mkdirSync(canonicalDir, { recursive: true });
572
+ if (skill.root)
573
+ fs.copyFileSync(
574
+ path.join(skill.dir, "SKILL.md"),
575
+ path.join(canonicalDir, "SKILL.md")
576
+ );
577
+ else fs.cpSync(skill.dir, canonicalDir, { recursive: true });
578
+ paths.push(canonicalDir);
579
+ for (const agent of detected) {
580
+ if (agent.universal) continue;
581
+ const agentSkillsDir = isGlobal ? agent.globalSkillsDir : path.join(cwd, agent.projectSkillsDir);
582
+ const agentDir = path.join(agentSkillsDir, skill.name);
583
+ if (agentDir === canonicalDir) continue;
584
+ try {
585
+ rmForce(agentDir);
586
+ fs.mkdirSync(path.dirname(agentDir), { recursive: true });
587
+ const realLinkDir = resolveParent(path.dirname(agentDir));
588
+ const realTarget = resolveParent(canonicalDir);
589
+ const rel = path.relative(realLinkDir, realTarget);
590
+ fs.symlinkSync(rel, agentDir);
591
+ agents.push({ agent: agent.name, path: agentDir, mode: "symlink" });
592
+ } catch {
593
+ try {
594
+ fs.cpSync(canonicalDir, agentDir, { recursive: true });
595
+ agents.push({ agent: agent.name, path: agentDir, mode: "copy" });
596
+ } catch {
597
+ }
598
+ }
599
+ }
600
+ }
601
+ return { paths, agents };
602
+ }
603
+ function discoverSkills(rootDir) {
604
+ const results = [];
605
+ function visit(dir) {
606
+ let entries;
607
+ try {
608
+ entries = fs.readdirSync(dir, { withFileTypes: true });
609
+ } catch {
610
+ return;
611
+ }
612
+ for (const entry of entries) {
613
+ if (!entry.isDirectory()) continue;
614
+ const subDir = path.join(dir, entry.name);
615
+ const skillPath = path.join(subDir, "SKILL.md");
616
+ if (fs.existsSync(skillPath)) {
617
+ const content = fs.readFileSync(skillPath, "utf8");
618
+ const nameMatch = /^name:\s*(.+)$/m.exec(content);
619
+ results.push({
620
+ name: sanitizeName(nameMatch?.[1] ?? entry.name),
621
+ dir: subDir
622
+ });
623
+ }
624
+ visit(subDir);
625
+ }
626
+ }
627
+ visit(rootDir);
628
+ const rootSkill = path.join(rootDir, "SKILL.md");
629
+ if (fs.existsSync(rootSkill)) {
630
+ const content = fs.readFileSync(rootSkill, "utf8");
631
+ const nameMatch = /^name:\s*(.+)$/m.exec(content);
632
+ const name = sanitizeName(nameMatch?.[1] ?? "skill");
633
+ if (!results.some((r) => r.name === name))
634
+ results.push({ name, dir: rootDir, root: true });
635
+ }
636
+ return results;
637
+ }
638
+ function sanitizeName(name) {
639
+ return name.trim().replace(/[/\\]/g, "-").replace(/\.\./g, "").slice(0, 255);
640
+ }
641
+ function rmForce(target) {
642
+ try {
643
+ const stat = fs.lstatSync(target);
644
+ if (stat.isSymbolicLink()) fs.unlinkSync(target);
645
+ else fs.rmSync(target, { recursive: true, force: true });
646
+ } catch {
647
+ }
648
+ }
649
+ function resolveParent(dir) {
650
+ try {
651
+ return fs.realpathSync(dir);
652
+ } catch {
653
+ const parent = path.dirname(dir);
654
+ if (parent === dir) return dir;
655
+ try {
656
+ return path.join(fs.realpathSync(parent), path.relative(parent, dir));
657
+ } catch {
658
+ return dir;
659
+ }
660
+ }
661
+ }
662
+
663
+ // src/cli/commands/lib/add-origin-skill.ts
664
+ async function addOriginSkill(origin, surface, options) {
665
+ const title = origin.title.toLowerCase().replace(/[ .]/g, "-");
666
+ const tmpDir = await fs2.mkdtemp(path2.join(os2.tmpdir(), "incur-skill-add-"));
667
+ const result = await resultFromPromise(
668
+ "add-origin-skill",
669
+ surface,
670
+ (async () => {
671
+ const skillDir = path2.join(tmpDir, title);
672
+ await fs2.mkdir(skillDir, { recursive: true });
673
+ await fs2.writeFile(
674
+ path2.join(skillDir, "SKILL.md"),
675
+ `---
676
+ name: ${title}
677
+ description: ${origin.description}
678
+ command: npx agentcash discover ${origin.url}
679
+ ---
680
+ Call \`npx agentcash discover ${origin.url}\` to discover how to use ${origin.title}.`
681
+ );
682
+ return installSkills(tmpDir, { cwd: options.cwd });
683
+ })(),
684
+ (e) => ({
685
+ cause: "install_failed",
686
+ message: e instanceof Error ? e.message : "Skill could not be written to /skills directory."
687
+ })
688
+ );
689
+ await fs2.rm(tmpDir, { recursive: true, force: true }).catch(() => void 0);
690
+ return result;
691
+ }
692
+
693
+ // src/cli/commands/fetch.ts
694
+ var SURFACE = "cli:fetch";
695
+ async function fetchCommand(args, flags) {
696
+ const { account } = await getWalletOrExit(flags);
697
+ const sessionId = randomBytes(16).toString("hex");
698
+ const input = parseRequestInput(SURFACE, args, flags);
699
+ const publicClient = createPublicClient({
700
+ chain: base,
701
+ transport: http()
702
+ });
703
+ const coreClient = x402Client.fromConfig({
704
+ schemes: [
705
+ {
706
+ network: DEFAULT_NETWORK,
707
+ client: new ExactEvmScheme(toClientEvmSigner(account, publicClient))
708
+ }
709
+ ]
710
+ });
711
+ const x402HttpClient = new x402HTTPClient(coreClient);
712
+ const mppxClient = Mppx.create({
713
+ polyfill: false,
714
+ methods: [
715
+ tempoMethod({
716
+ account,
717
+ getClient: () => createClient({ chain: tempo, transport: http(TEMPO_RPC_URL) })
718
+ })
719
+ ]
720
+ });
721
+ const provider = flags.provider ?? `agentcash@${MCP_VERSION}`;
722
+ const paymentMethod = args.paymentMethod ?? "auto";
723
+ const request = buildRequest({
724
+ input,
725
+ address: account.address,
726
+ sessionId,
727
+ provider
728
+ });
729
+ const fetchResult = await createFetchWithPayment({
730
+ surface: SURFACE,
731
+ clients: { x402: x402HttpClient, mpp: mppxClient },
732
+ paymentMethod,
733
+ account,
734
+ flags
735
+ })(request);
736
+ if (fetchResult.isErr()) {
737
+ return outputAndExit(fromNeverthrowError(fetchResult), flags);
738
+ }
739
+ const { response, paymentInfo } = fetchResult.value;
740
+ if (!response.ok) {
741
+ const parseResult = await safeParseResponse(SURFACE, response);
742
+ const details = { statusCode: response.status };
743
+ let serverMessage;
744
+ if (parseResult.isOk()) {
745
+ const { type } = parseResult.value;
746
+ if (type === "json") {
747
+ details.body = parseResult.value.data;
748
+ serverMessage = extractJsonErrorMessage(parseResult.value.data);
749
+ } else if (type === "text") {
750
+ details.body = parseResult.value.data;
751
+ serverMessage = parseResult.value.data;
752
+ } else {
753
+ details.bodyType = type;
754
+ }
755
+ }
756
+ return outputAndExit(
757
+ errorResponse({
758
+ code: "HTTP_ERROR",
759
+ message: serverMessage ?? response.statusText,
760
+ surface: SURFACE,
761
+ cause: "http",
762
+ details
763
+ }),
764
+ flags
765
+ );
766
+ }
767
+ const parseResponseResult = await safeParseResponse(SURFACE, response);
768
+ if (parseResponseResult.isErr()) {
769
+ return outputAndExit(fromNeverthrowError(parseResponseResult), flags);
770
+ }
771
+ const data = parseResponseResult.value.type === "json" ? parseResponseResult.value.data : parseResponseResult.value.type === "text" ? parseResponseResult.value.data : { type: parseResponseResult.value.type };
772
+ const metadata = paymentInfo ? {
773
+ protocol: paymentInfo.protocol,
774
+ ...paymentInfo.price ? { price: paymentInfo.price } : {},
775
+ ...paymentInfo.payment ? { payment: paymentInfo.payment } : {}
776
+ } : void 0;
777
+ outputAndExit(successResponse(data, metadata), flags);
778
+ }
779
+ function extractJsonErrorMessage(body) {
780
+ if (typeof body === "object" && body !== null) {
781
+ const obj = body;
782
+ if (typeof obj.error === "string") return obj.error;
783
+ if (typeof obj.error === "object" && obj.error !== null && typeof obj.error.message === "string") {
784
+ return obj.error.message;
785
+ }
786
+ if (typeof obj.message === "string") return obj.message;
787
+ }
788
+ return void 0;
789
+ }
790
+
791
+ // src/cli/commands/fetch-auth.ts
792
+ import { randomBytes as randomBytes2 } from "crypto";
793
+ var SURFACE2 = "cli:fetch-auth";
794
+ async function fetchAuthCommand(args, flags) {
795
+ const { account } = await getWalletOrExit(flags);
796
+ const sessionId = randomBytes2(16).toString("hex");
797
+ const input = parseRequestInput(SURFACE2, args, flags);
798
+ const result = await createFetchWithAuth({
799
+ surface: SURFACE2,
800
+ account,
801
+ timeout: input.timeout ?? DEFAULT_USER_FETCH_TIMEOUT
802
+ })(buildRequest({ input, address: account.address, sessionId }));
803
+ if (result.isErr()) {
804
+ return outputAndExit(fromNeverthrowError(result), flags);
805
+ }
806
+ const value = result.value;
807
+ if (value.outcome === "no_siwx_extension") {
808
+ return outputAndExit(
809
+ errorResponse({
810
+ code: "GENERAL_ERROR",
811
+ message: "Endpoint returned 402 but no sign-in-with-x extension found. Use `fetch` for paid endpoints.",
812
+ surface: SURFACE2,
813
+ cause: "no_siwx_extension",
814
+ details: { extensions: value.extensions }
815
+ }),
816
+ flags
817
+ );
818
+ }
819
+ const { response } = value;
820
+ if (!response.ok) {
821
+ return outputAndExit(
822
+ errorResponse({
823
+ code: "HTTP_ERROR",
824
+ message: response.statusText,
825
+ surface: SURFACE2,
826
+ cause: "http",
827
+ details: { statusCode: response.status }
828
+ }),
829
+ flags
830
+ );
831
+ }
832
+ const parseResult = await safeParseResponse(SURFACE2, response);
833
+ if (parseResult.isErr()) {
834
+ return outputAndExit(fromNeverthrowError(parseResult), flags);
835
+ }
836
+ const data = parseResult.value.type === "json" ? parseResult.value.data : parseResult.value.type === "text" ? parseResult.value.data : { type: parseResult.value.type };
837
+ outputAndExit(successResponse(data), flags);
838
+ }
839
+
840
+ // src/cli/commands/check.ts
841
+ import { randomBytes as randomBytes3 } from "crypto";
842
+ var SURFACE3 = "cli:check";
843
+ async function checkCommand(args, flags) {
844
+ const { account } = await getWalletOrExit(flags);
845
+ const sessionId = randomBytes3(16).toString("hex");
846
+ const parsedBody = args.body ? JSON.parse(args.body) : void 0;
847
+ const parsedHeaders = args.headers ? JSON.parse(args.headers) : void 0;
848
+ const result = await checkEndpoint(
849
+ SURFACE3,
850
+ args.url,
851
+ args.method ? [args.method] : void 0,
852
+ parsedBody,
853
+ {
854
+ ...parsedHeaders,
855
+ "X-Wallet-Address": account.address,
856
+ "X-Session-ID": sessionId
857
+ }
858
+ );
859
+ if (!result.found) {
860
+ return outputAndExit(
861
+ successResponse(
862
+ toJsonObject({
863
+ url: args.url,
864
+ error: result.cause,
865
+ message: result.message
866
+ })
867
+ ),
868
+ flags
869
+ );
870
+ }
871
+ const results = result.advisories.map((a) => ({
872
+ ...a,
873
+ requiresPayment: a.authMode === "paid" || a.authMode === "apiKey+paid"
874
+ }));
875
+ return outputAndExit(
876
+ successResponse(toJsonObject({ url: args.url, results })),
877
+ flags
878
+ );
879
+ }
880
+
881
+ // src/cli/commands/discover.ts
882
+ async function discoverCommand(args, flags) {
883
+ const result = await discoverResources("cli:discover", args.url, {
884
+ includeGuidance: args.includeGuidance
885
+ });
886
+ if (result.found) {
887
+ return outputAndExit(
888
+ successResponse({
889
+ found: true,
890
+ origin: result.origin,
891
+ source: result.source,
892
+ ...result.info ? { info: result.info } : {},
893
+ guidanceAvailable: result.guidanceAvailable,
894
+ ...result.guidanceTokens != null ? { guidanceTokens: result.guidanceTokens } : {},
895
+ ...result.guidance ? { guidance: result.guidance } : {},
896
+ endpoints: result.endpoints.map((e) => ({ ...e }))
897
+ }),
898
+ flags
899
+ );
900
+ }
901
+ const origin = URL.canParse(args.url) ? new URL(args.url).origin : args.url;
902
+ return outputAndExit(
903
+ errorResponse({
904
+ code: "GENERAL_ERROR",
905
+ message: result.message ?? `No OpenAPI spec found for ${origin}. Tried: /openapi.json, /.well-known/x402`,
906
+ surface: "cli:discover",
907
+ cause: result.cause,
908
+ details: { origin }
909
+ }),
910
+ flags
911
+ );
912
+ }
913
+
914
+ // src/cli/commands/register.ts
915
+ var SURFACE4 = "cli:register";
916
+ async function registerCommand(args, flags) {
917
+ const result = await registerOrigin(SURFACE4, { url: args.url }, flags.dev);
918
+ if (result.isErr()) {
919
+ return outputAndExit(fromNeverthrowError(result), flags);
872
920
  }
873
- return { paths, agents };
921
+ const { origin, resourceCount } = result.value;
922
+ return outputAndExit(
923
+ successResponse({
924
+ origin: {
925
+ id: origin.id,
926
+ origin: origin.origin,
927
+ name: origin.name
928
+ },
929
+ resourceCount
930
+ }),
931
+ flags
932
+ );
874
933
  }
875
- function discoverSkills(rootDir) {
876
- const results = [];
877
- function visit(dir) {
878
- let entries;
879
- try {
880
- entries = fs.readdirSync(dir, { withFileTypes: true });
881
- } catch {
882
- return;
883
- }
884
- for (const entry of entries) {
885
- if (!entry.isDirectory()) continue;
886
- const subDir = path.join(dir, entry.name);
887
- const skillPath = path.join(subDir, "SKILL.md");
888
- if (fs.existsSync(skillPath)) {
889
- const content = fs.readFileSync(skillPath, "utf8");
890
- const nameMatch = /^name:\s*(.+)$/m.exec(content);
891
- results.push({
892
- name: sanitizeName(nameMatch?.[1] ?? entry.name),
893
- dir: subDir
894
- });
895
- }
896
- visit(subDir);
897
- }
934
+
935
+ // src/cli/commands/wallet.ts
936
+ var SURFACE5 = "cli:wallet";
937
+ async function walletInfoCommand(_args, flags) {
938
+ const { account } = await getWalletOrExit(flags);
939
+ const result = await getWalletInfo(SURFACE5, account.address, flags);
940
+ if (result.isErr()) {
941
+ return outputAndExit(fromNeverthrowError(result), flags);
898
942
  }
899
- visit(rootDir);
900
- const rootSkill = path.join(rootDir, "SKILL.md");
901
- if (fs.existsSync(rootSkill)) {
902
- const content = fs.readFileSync(rootSkill, "utf8");
903
- const nameMatch = /^name:\s*(.+)$/m.exec(content);
904
- const name = sanitizeName(nameMatch?.[1] ?? "skill");
905
- if (!results.some((r) => r.name === name))
906
- results.push({ name, dir: rootDir, root: true });
943
+ return outputAndExit(
944
+ successResponse({
945
+ address: result.value.address,
946
+ balance: result.value.balance,
947
+ chains: result.value.chains.map((c) => ({
948
+ chain: c.chain,
949
+ balance: c.balance
950
+ })),
951
+ isNewWallet: result.value.isNewWallet,
952
+ depositLink: result.value.depositLink,
953
+ ...result.value.onboardingCta ? {
954
+ onboardingCta: {
955
+ onboardLink: result.value.onboardingCta.onboardLink,
956
+ depositLink: result.value.onboardingCta.depositLink,
957
+ message: result.value.onboardingCta.message
958
+ }
959
+ } : {},
960
+ ...result.value.message ? { message: result.value.message } : {}
961
+ }),
962
+ flags
963
+ );
964
+ }
965
+ async function walletRedeemCommand(args, flags) {
966
+ const { account } = await getWalletOrExit(flags);
967
+ const result = await redeemInviteCode({
968
+ code: args.code,
969
+ address: account.address,
970
+ surface: SURFACE5,
971
+ dev: flags.dev
972
+ });
973
+ if (result.isErr()) {
974
+ return outputAndExit(fromNeverthrowError(result), flags);
907
975
  }
908
- return results;
976
+ return outputAndExit(
977
+ successResponse({
978
+ redeemed: true,
979
+ amount: `${result.value.amount} USDC`,
980
+ txHash: result.value.txHash
981
+ }),
982
+ flags
983
+ );
909
984
  }
910
- function sanitizeName(name) {
911
- return name.trim().replace(/[/\\]/g, "-").replace(/\.\./g, "").slice(0, 255);
985
+ async function walletAddressCommand(_args, flags) {
986
+ const { account } = await getWalletOrExit(flags);
987
+ return outputAndExit(successResponse({ address: account.address }), flags);
912
988
  }
913
- function rmForce(target) {
914
- try {
915
- const stat = fs.lstatSync(target);
916
- if (stat.isSymbolicLink()) fs.unlinkSync(target);
917
- else fs.rmSync(target, { recursive: true, force: true });
918
- } catch {
989
+
990
+ // src/cli/commands/report-error.ts
991
+ var SURFACE6 = "cli:report-error";
992
+ async function reportErrorCommand(args, flags) {
993
+ const { account } = await getWalletOrExit(flags);
994
+ const result = await submitErrorReport(
995
+ SURFACE6,
996
+ {
997
+ tool: args.tool,
998
+ summary: args.summary,
999
+ errorMessage: args.errorMessage,
1000
+ resource: args.resource,
1001
+ stack: args.stack,
1002
+ fullReport: args.fullReport
1003
+ },
1004
+ account.address,
1005
+ flags.dev
1006
+ );
1007
+ if (result.isErr()) {
1008
+ return outputAndExit(fromNeverthrowError(result), flags);
919
1009
  }
1010
+ return outputAndExit(
1011
+ successResponse({
1012
+ submitted: result.value.submitted,
1013
+ reportId: result.value.reportId,
1014
+ message: result.value.message
1015
+ }),
1016
+ flags
1017
+ );
920
1018
  }
921
- function resolveParent(dir) {
922
- try {
923
- return fs.realpathSync(dir);
924
- } catch {
925
- const parent = path.dirname(dir);
926
- if (parent === dir) return dir;
927
- try {
928
- return path.join(fs.realpathSync(parent), path.relative(parent, dir));
929
- } catch {
930
- return dir;
931
- }
1019
+
1020
+ // src/cli/commands/server.ts
1021
+ async function serverCommand(flags) {
1022
+ if (process.stdout.isTTY) {
1023
+ process.stdout.write(
1024
+ "MCP server started. If you meant to explore the CLI, run: npx agentcash --help\n"
1025
+ );
932
1026
  }
1027
+ const { startServer } = await import("./server-QARME5NA.js");
1028
+ await startServer(flags);
933
1029
  }
934
1030
 
935
1031
  // src/cli/commands/add-skill.ts
936
1032
  var SURFACE7 = "cli:add-skill";
937
1033
  async function addSkillCommand(args, flags) {
938
- if (!/^https?:\/\//i.test(args.url)) {
939
- args.url = `https://${args.url}`;
940
- }
941
- if (!URL.canParse(args.url)) {
942
- return outputAndExit(
943
- errorResponse({
944
- code: "GENERAL_ERROR",
945
- message: `Invalid URL: ${args.url}`,
946
- surface: SURFACE7,
947
- cause: "invalid_url"
948
- })
949
- );
950
- }
951
- const result = await discoverResources("cli:add-skill", args.url);
952
- if (!result.found) {
953
- return outputAndExit(
954
- errorResponse({
955
- code: "GENERAL_ERROR",
956
- message: result.message ?? `No OpenAPI spec found for ${args.url}`,
957
- surface: SURFACE7,
958
- cause: result.cause
959
- }),
960
- flags
1034
+ const resolved = await resolveOrigin(args.url, SURFACE7);
1035
+ if (!resolved.ok) return outputAndExit(resolved.error, flags);
1036
+ const { origin } = resolved;
1037
+ addUserOrigin(origin);
1038
+ const skillResult = await addOriginSkill(origin, SURFACE7, {
1039
+ cwd: process.cwd()
1040
+ });
1041
+ if (!skillResult.isOk()) {
1042
+ origin.warnings.push(
1043
+ "Failed to install skill: " + skillResult.error.cause + " " + skillResult.error.message
961
1044
  );
962
1045
  }
963
- if (!result.info?.title) {
964
- return outputAndExit(
965
- errorResponse({
966
- code: "GENERAL_ERROR",
967
- message: `No description found for ${args.url}`,
968
- surface: SURFACE7,
969
- cause: "no_description"
1046
+ const installedPaths = skillResult.isOk() ? skillResult.value.paths : [];
1047
+ return outputAndExit(
1048
+ successResponse(
1049
+ toJsonObject({
1050
+ url: origin.url,
1051
+ title: origin.title,
1052
+ description: origin.description,
1053
+ installed: installedPaths,
1054
+ note: "Restart your MCP server for this origin to appear in the model context.",
1055
+ ...origin.warnings.length > 0 && { warnings: origin.warnings }
970
1056
  })
971
- );
972
- }
973
- const title = result.info.title.toLowerCase().replace(/[ .]/g, "-");
974
- const tmpDir = await fs2.mkdtemp(path2.join(os2.tmpdir(), "incur-skill-add-"));
975
- try {
976
- const skillDir = path2.join(tmpDir, title);
977
- await fs2.mkdir(skillDir, { recursive: true });
978
- await fs2.writeFile(
979
- path2.join(skillDir, "SKILL.md"),
980
- `---
981
- name: ${title}
982
- description: ${result.info.description}
983
- command: npx agentcash discover ${args.url}
984
- ---
985
- Call \`npx agentcash discover ${args.url}\` to discover how to use ${result.info.title}.`
986
- );
987
- const installResult = installSkills(tmpDir, {
988
- cwd: process.cwd()
989
- });
1057
+ ),
1058
+ flags
1059
+ );
1060
+ }
1061
+
1062
+ // src/cli/commands/origins.ts
1063
+ var SURFACE8 = "cli:origins";
1064
+ async function originsAddCommand(args, flags) {
1065
+ const resolved = await resolveOrigin(args.url, SURFACE8);
1066
+ if (!resolved.ok) return outputAndExit(resolved.error, flags);
1067
+ const origin = addUserOrigin(resolved.origin);
1068
+ return outputAndExit(
1069
+ successResponse({
1070
+ url: origin.url,
1071
+ title: origin.title,
1072
+ description: origin.description,
1073
+ note: "Restart your MCP server for this origin to appear in the model context.",
1074
+ ...resolved.origin.warnings.length > 0 && {
1075
+ warnings: resolved.origin.warnings
1076
+ }
1077
+ }),
1078
+ flags
1079
+ );
1080
+ }
1081
+ function originsListCommand(_args, flags) {
1082
+ const primary = PRIMARY_ORIGINS.flatMap((o) => {
1083
+ const meta = ORIGIN_METADATA[o];
1084
+ return meta ? [{ url: o, title: meta.title, description: meta.description }] : [];
1085
+ });
1086
+ const added = loadUserOrigins();
1087
+ return outputAndExit(successResponse({ primary, added }), flags);
1088
+ }
1089
+ function originsRemoveCommand(args, flags) {
1090
+ const url = /^https?:\/\//i.test(args.url) ? args.url : `https://${args.url}`;
1091
+ const result = removeUserOrigin(url);
1092
+ if (!result.removed) {
1093
+ const isPrimary = PRIMARY_ORIGINS.some((o) => String(o) === url);
990
1094
  return outputAndExit(
991
- successResponse(
992
- toJsonObject({
993
- installed: installResult.paths
994
- })
1095
+ errorResponse(
1096
+ isPrimary ? {
1097
+ code: "GENERAL_ERROR",
1098
+ message: `Cannot remove primary origin: ${url}. Only user-added origins can be removed.`,
1099
+ surface: SURFACE8,
1100
+ cause: "primary_origin"
1101
+ } : {
1102
+ code: "GENERAL_ERROR",
1103
+ message: `Origin not found: ${url}`,
1104
+ surface: SURFACE8,
1105
+ cause: "not_found"
1106
+ }
995
1107
  ),
996
1108
  flags
997
1109
  );
998
- } finally {
999
- await fs2.rm(tmpDir, { recursive: true, force: true });
1000
1110
  }
1111
+ return outputAndExit(successResponse({ removed: true, url }), flags);
1001
1112
  }
1002
1113
 
1003
1114
  // src/cli/commands/onboard.ts
@@ -1017,7 +1128,7 @@ var agentClientMap = {
1017
1128
  Cursor: "cursor" /* Cursor */,
1018
1129
  "Gemini CLI": "gemini-cli" /* GeminiCli */,
1019
1130
  Goose: "goose" /* Goose */,
1020
- OpenCode: "opencode" /* Opencode */,
1131
+ OpenCode: "opencode" /* OpenCode */,
1021
1132
  Roo: "roo-cline" /* RooCline */,
1022
1133
  Windsurf: "windsurf" /* Windsurf */
1023
1134
  };
@@ -1225,7 +1336,7 @@ function formatDemoPromptsJson(baseUrl) {
1225
1336
  }
1226
1337
 
1227
1338
  // src/cli/commands/onboard.ts
1228
- var SURFACE8 = "cli:onboard";
1339
+ var SURFACE9 = "cli:onboard";
1229
1340
  var AGENTCASH_SKILL = {
1230
1341
  owner: "merit-systems",
1231
1342
  repo: "agentcash-skills",
@@ -1287,14 +1398,14 @@ function installAgentcashWalletSkill() {
1287
1398
  const detectedAgents = detect();
1288
1399
  return resultFromPromise(
1289
1400
  "skill",
1290
- SURFACE8,
1401
+ SURFACE9,
1291
1402
  (async () => {
1292
1403
  const tmpDir = await fs5.mkdtemp(
1293
1404
  path5.join(os4.tmpdir(), "agentcash-onboard-")
1294
1405
  );
1295
1406
  const installPromise = (async () => {
1296
1407
  const downloaded = await downloadGitHubSkill(
1297
- SURFACE8,
1408
+ SURFACE9,
1298
1409
  AGENTCASH_SKILL,
1299
1410
  tmpDir
1300
1411
  );
@@ -1357,7 +1468,7 @@ async function onboardCommand(args, flags) {
1357
1468
  errorResponse({
1358
1469
  code: "GENERAL_ERROR",
1359
1470
  message: skillInstallResult.error.message,
1360
- surface: SURFACE8,
1471
+ surface: SURFACE9,
1361
1472
  cause: "skill_install_failed"
1362
1473
  }),
1363
1474
  flags
@@ -1374,7 +1485,7 @@ async function onboardCommand(args, flags) {
1374
1485
  address,
1375
1486
  code: args.code,
1376
1487
  dev: flags.dev,
1377
- surface: SURFACE8
1488
+ surface: SURFACE9
1378
1489
  });
1379
1490
  if (redeemResult.isErr()) {
1380
1491
  const format2 = getOutputFormat(flags.format);
@@ -1425,7 +1536,7 @@ async function onboardCommand(args, flags) {
1425
1536
  redeemValue = redeemResult.value;
1426
1537
  }
1427
1538
  progress(flags, "Fetching wallet balance...");
1428
- const walletInfoResult = await getWalletInfo(SURFACE8, address, flags);
1539
+ const walletInfoResult = await getWalletInfo(SURFACE9, address, flags);
1429
1540
  const walletInfo = walletInfoResult.isOk() ? walletInfoResult.value : void 0;
1430
1541
  if (!args.code && (!walletInfo?.balance || walletInfo.balance <= 0)) {
1431
1542
  const cta = getOnboardingCta(address, flags);
@@ -1433,7 +1544,7 @@ async function onboardCommand(args, flags) {
1433
1544
  errorResponse({
1434
1545
  code: "GENERAL_ERROR",
1435
1546
  message: cta.message,
1436
- surface: SURFACE8,
1547
+ surface: SURFACE9,
1437
1548
  cause: "no_funds"
1438
1549
  }),
1439
1550
  flags
@@ -1556,6 +1667,12 @@ async function tryCommand(args, flags) {
1556
1667
  `If you have the AgentCash MCP installed, you can also call this directly using the check_endpoint_schema and fetch tools.`
1557
1668
  ].join("\n");
1558
1669
  }
1670
+ const modelInstructions = [
1671
+ `Present the originSummary to the user, then ask them what they would like to do \u2014 e.g. "What would you like to do with ${title}?"`,
1672
+ ...onboardingCta ? [
1673
+ `IMPORTANT: The user has not yet onboarded. Show the onboard link VERBATIM as a clickable URL so the user can click it: ${onboardingCta.onboardLink}`
1674
+ ] : []
1675
+ ].join("\n");
1559
1676
  return outputAndExit(
1560
1677
  successResponse({
1561
1678
  ...onboardingCta ? {
@@ -1563,7 +1680,8 @@ async function tryCommand(args, flags) {
1563
1680
  onboardLink: onboardingCta.onboardLink
1564
1681
  } : {},
1565
1682
  originSummary,
1566
- ...callToAction ? { callToAction } : {}
1683
+ ...callToAction ? { callToAction } : {},
1684
+ modelInstructions
1567
1685
  }),
1568
1686
  flags
1569
1687
  );
@@ -1575,6 +1693,9 @@ export {
1575
1693
  fetchAuthCommand,
1576
1694
  fetchCommand,
1577
1695
  onboardCommand,
1696
+ originsAddCommand,
1697
+ originsListCommand,
1698
+ originsRemoveCommand,
1578
1699
  registerCommand,
1579
1700
  reportErrorCommand,
1580
1701
  serverCommand,
@@ -1583,4 +1704,4 @@ export {
1583
1704
  walletInfoCommand,
1584
1705
  walletRedeemCommand
1585
1706
  };
1586
- //# sourceMappingURL=commands-IFU565JX.js.map
1707
+ //# sourceMappingURL=commands-YSOBBE4N.js.map