@agentcash/router 1.10.3 → 1.10.4

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.cjs CHANGED
@@ -541,7 +541,8 @@ var HEADERS = {
541
541
  X402_PAYMENT_LEGACY: "X-PAYMENT",
542
542
  X402_PAYMENT_REQUIRED: "PAYMENT-REQUIRED",
543
543
  X402_PAYMENT_RESPONSE: "PAYMENT-RESPONSE",
544
- MPP_PAYMENT_RECEIPT: "Payment-Receipt"
544
+ MPP_PAYMENT_RECEIPT: "Payment-Receipt",
545
+ REQUEST_ID: "X-Request-ID"
545
546
  };
546
547
  var AUTH_SCHEME = {
547
548
  BEARER: "Bearer ",
@@ -571,19 +572,19 @@ function firePluginHook(plugin, method, ...args) {
571
572
  const result = fn.apply(plugin, args);
572
573
  if (result && typeof result.catch === "function") {
573
574
  result.catch((error) => {
574
- console.error(
575
- `[router] ERROR ${method}: ${error instanceof Error ? error.message : String(error)}`
576
- );
575
+ console.error(`[router] ERROR ${method}: ${formatUnknownError(error)}`);
577
576
  });
578
577
  }
579
578
  return result;
580
579
  } catch (error) {
581
- console.error(
582
- `[router] ERROR ${method}: ${error instanceof Error ? error.message : String(error)}`
583
- );
580
+ console.error(`[router] ERROR ${method}: ${formatUnknownError(error)}`);
584
581
  return void 0;
585
582
  }
586
583
  }
584
+ function formatUnknownError(error) {
585
+ if (error instanceof Error) return error.stack ?? error.message;
586
+ return String(error);
587
+ }
587
588
 
588
589
  // src/plugin/reporter.ts
589
590
  function createReporter(plugin, pluginCtx, route) {
@@ -674,7 +675,8 @@ function firePaymentVerified(ctx, event) {
674
675
  function firePaymentSettled(ctx, event) {
675
676
  firePluginHook(ctx.deps.plugin, "onPaymentSettled", ctx.pluginCtx, event);
676
677
  }
677
- function firePluginResponse(ctx, response, requestBody, responseBody) {
678
+ function firePluginResponse(ctx, response, requestBody, responseBody, failure) {
679
+ attachRequestId(response, ctx.meta.requestId);
678
680
  firePluginHook(ctx.deps.plugin, "onResponse", ctx.pluginCtx, {
679
681
  statusCode: response.status,
680
682
  statusText: response.statusText,
@@ -685,11 +687,9 @@ function firePluginResponse(ctx, response, requestBody, responseBody) {
685
687
  responseBody
686
688
  });
687
689
  if (response.status >= 400 && response.status !== 402) {
688
- firePluginHook(ctx.deps.plugin, "onError", ctx.pluginCtx, {
689
- status: response.status,
690
- message: response.statusText || `HTTP ${response.status}`,
691
- settled: false
692
- });
690
+ const error = buildErrorEvent(ctx, response, failure);
691
+ if (response.status >= 500) logRouterFailure(error);
692
+ firePluginHook(ctx.deps.plugin, "onError", ctx.pluginCtx, error);
693
693
  }
694
694
  }
695
695
  function fireProviderQuota(ctx, response, handlerResult) {
@@ -721,6 +721,67 @@ function computeQuotaLevel(remaining, warn, critical) {
721
721
  if (warn !== void 0 && remaining <= warn) return "warn";
722
722
  return "healthy";
723
723
  }
724
+ function attachRequestId(response, requestId) {
725
+ try {
726
+ if (!response.headers.has(HEADERS.REQUEST_ID)) {
727
+ response.headers.set(HEADERS.REQUEST_ID, requestId);
728
+ }
729
+ } catch {
730
+ }
731
+ }
732
+ function buildErrorEvent(ctx, response, failure) {
733
+ const error = errorDetails(failure?.cause);
734
+ const responseMessage = response.statusText || `HTTP ${response.status}`;
735
+ const message = failure?.message ?? error.message ?? responseMessage;
736
+ return {
737
+ status: response.status,
738
+ message,
739
+ settled: failure?.settled ?? false,
740
+ requestId: ctx.meta.requestId,
741
+ route: ctx.meta.route,
742
+ method: ctx.meta.method,
743
+ duration: Date.now() - ctx.meta.startTime,
744
+ walletAddress: ctx.meta.walletAddress,
745
+ verifiedWallet: ctx.pluginCtx.verifiedWallet,
746
+ clientId: ctx.meta.clientId,
747
+ sessionId: ctx.meta.sessionId,
748
+ errorName: error.name,
749
+ stack: error.stack,
750
+ cause: failure?.cause
751
+ };
752
+ }
753
+ function errorDetails(error) {
754
+ if (error instanceof Error) {
755
+ return {
756
+ message: error.message,
757
+ name: error.name,
758
+ stack: error.stack
759
+ };
760
+ }
761
+ if (typeof error === "object" && error !== null) {
762
+ const record = error;
763
+ return {
764
+ message: typeof record.message === "string" ? record.message : void 0,
765
+ name: typeof record.name === "string" ? record.name : void 0,
766
+ stack: typeof record.stack === "string" ? record.stack : void 0
767
+ };
768
+ }
769
+ if (typeof error === "string") return { message: error };
770
+ return {};
771
+ }
772
+ function logRouterFailure(error) {
773
+ console.error(`[router] ERROR ${error.route ?? "unknown"} ${error.status}: ${error.message}`, {
774
+ requestId: error.requestId,
775
+ method: error.method,
776
+ duration: error.duration,
777
+ walletAddress: error.walletAddress,
778
+ verifiedWallet: error.verifiedWallet,
779
+ clientId: error.clientId,
780
+ sessionId: error.sessionId,
781
+ errorName: error.errorName,
782
+ stack: error.stack
783
+ });
784
+ }
724
785
 
725
786
  // src/pipeline/steps/parse-body.ts
726
787
  async function parseBody(ctx, request = ctx.request) {
@@ -730,20 +791,19 @@ async function parseBody(ctx, request = ctx.request) {
730
791
  raw = await bufferBody(request);
731
792
  } catch (err) {
732
793
  if (!(err instanceof MalformedJsonError)) throw err;
733
- const response2 = import_server.NextResponse.json(
734
- { success: false, error: "Invalid JSON", issues: [] },
735
- { status: 400 }
736
- );
737
- firePluginResponse(ctx, response2);
794
+ const responseBody2 = { success: false, error: "Invalid JSON", issues: [] };
795
+ const response2 = import_server.NextResponse.json(responseBody2, { status: 400 });
796
+ firePluginResponse(ctx, response2, void 0, responseBody2, {
797
+ message: responseBody2.error,
798
+ cause: err
799
+ });
738
800
  return { ok: false, response: response2 };
739
801
  }
740
802
  const result = validateBody(raw, ctx.routeEntry.bodySchema);
741
803
  if (result.success) return { ok: true, data: result.data };
742
- const response = import_server.NextResponse.json(
743
- { success: false, error: result.error, issues: result.issues },
744
- { status: 400 }
745
- );
746
- firePluginResponse(ctx, response);
804
+ const responseBody = { success: false, error: result.error, issues: result.issues };
805
+ const response = import_server.NextResponse.json(responseBody, { status: 400 });
806
+ firePluginResponse(ctx, response, raw, responseBody, { message: result.error });
747
807
  return { ok: false, response };
748
808
  }
749
809
 
@@ -755,11 +815,9 @@ function validateQuery(ctx) {
755
815
  const params = Object.fromEntries(ctx.request.nextUrl.searchParams.entries());
756
816
  const result = validateBody(params, querySchema);
757
817
  if (result.success) return { ok: true, data: result.data };
758
- const response = import_server2.NextResponse.json(
759
- { success: false, error: result.error, issues: result.issues },
760
- { status: 400 }
761
- );
762
- firePluginResponse(ctx, response);
818
+ const responseBody = { success: false, error: result.error, issues: result.issues };
819
+ const response = import_server2.NextResponse.json(responseBody, { status: 400 });
820
+ firePluginResponse(ctx, response, params, responseBody, { message: result.error });
763
821
  return { ok: false, response };
764
822
  }
765
823
 
@@ -778,9 +836,13 @@ function handlerFailureError(response) {
778
836
 
779
837
  // src/pipeline/steps/fail.ts
780
838
  var import_server3 = require("next/server");
781
- function fail(ctx, status, message, requestBody) {
782
- const response = import_server3.NextResponse.json({ success: false, error: message }, { status });
783
- firePluginResponse(ctx, response, requestBody);
839
+ function fail(ctx, status, message, requestBody, failure) {
840
+ const responseBody = { success: false, error: message };
841
+ const response = import_server3.NextResponse.json(responseBody, { status });
842
+ firePluginResponse(ctx, response, requestBody, responseBody, {
843
+ ...failure,
844
+ message: failure?.message ?? message
845
+ });
784
846
  return response;
785
847
  }
786
848
 
@@ -856,9 +918,10 @@ async function runHandler(ctx, handlerCtx) {
856
918
  function errorResult(error) {
857
919
  const status = error instanceof HttpError ? error.status : typeof error?.status === "number" ? error.status : 500;
858
920
  const message = error instanceof Error ? error.message : "Internal error";
921
+ const responseBody = { success: false, error: message };
859
922
  return {
860
- response: import_server4.NextResponse.json({ success: false, error: message }, { status }),
861
- rawResult: void 0,
923
+ response: import_server4.NextResponse.json(responseBody, { status }),
924
+ rawResult: responseBody,
862
925
  handlerError: error
863
926
  };
864
927
  }
@@ -870,9 +933,9 @@ function isThenable(value) {
870
933
  }
871
934
 
872
935
  // src/pipeline/steps/finalize/response.ts
873
- function finalize(ctx, response, rawResult, requestBody) {
936
+ function finalize(ctx, response, rawResult, requestBody, failure) {
874
937
  fireProviderQuota(ctx, response, rawResult);
875
- firePluginResponse(ctx, response, requestBody, rawResult);
938
+ firePluginResponse(ctx, response, requestBody, rawResult, failure);
876
939
  return response;
877
940
  }
878
941
 
@@ -958,7 +1021,9 @@ async function settleAndFinalizeRequest(args) {
958
1021
  });
959
1022
  if (!settle.ok) {
960
1023
  if (onSettleError) await onSettleError(settle.error, settle.failMessage);
961
- return fail(ctx, settle.failStatus ?? 500, settle.failMessage, body);
1024
+ return fail(ctx, settle.failStatus ?? 500, settle.failMessage, body, {
1025
+ cause: settle.error
1026
+ });
962
1027
  }
963
1028
  return runPostSettleEpilogue({
964
1029
  ctx,
@@ -993,7 +1058,9 @@ async function settleAndFinalizeStream(args) {
993
1058
  report
994
1059
  });
995
1060
  if (!settle.ok) {
996
- return fail(ctx, settle.failStatus ?? 500, settle.failMessage, body);
1061
+ return fail(ctx, settle.failStatus ?? 500, settle.failMessage, body, {
1062
+ cause: settle.error
1063
+ });
997
1064
  }
998
1065
  return runPostSettleEpilogue({
999
1066
  ctx,
@@ -1020,7 +1087,13 @@ async function runHandlerOnly(ctx, wallet, account) {
1020
1087
  const validateErr = await runValidate(ctx, body.data);
1021
1088
  if (validateErr) return validateErr;
1022
1089
  const result = await invokeUnauthed(ctx, wallet, account, body.data);
1023
- return finalize(ctx, result.response, result.rawResult, body.data);
1090
+ return finalize(
1091
+ ctx,
1092
+ result.response,
1093
+ result.rawResult,
1094
+ body.data,
1095
+ result.handlerError === void 0 ? void 0 : { cause: result.handlerError }
1096
+ );
1024
1097
  }
1025
1098
 
1026
1099
  // src/pipeline/steps/run-before-settle.ts
@@ -2459,11 +2532,9 @@ async function buildChallengeResponse(ctx, pricing, body, failure) {
2459
2532
  challengePrice = pricing ? await pricing.challengeQuote(body) : "0";
2460
2533
  } catch (err) {
2461
2534
  const message = errorMessage(err, "Price calculation failed");
2462
- const errorResponse = import_server5.NextResponse.json(
2463
- { success: false, error: message },
2464
- { status: errorStatus(err, 500) }
2465
- );
2466
- firePluginResponse(ctx, errorResponse);
2535
+ const responseBody2 = { success: false, error: message };
2536
+ const errorResponse = import_server5.NextResponse.json(responseBody2, { status: errorStatus(err, 500) });
2537
+ firePluginResponse(ctx, errorResponse, body, responseBody2, { message, cause: err });
2467
2538
  return errorResponse;
2468
2539
  }
2469
2540
  const extensions = await buildChallengeExtensions(ctx);
@@ -2495,11 +2566,9 @@ async function buildChallengeResponse(ctx, pricing, body, failure) {
2495
2566
  const message = `${strategy.protocol} challenge build failed: ${errorMessage(err, String(err))}`;
2496
2567
  ctx.report("critical", message);
2497
2568
  if (strategy.protocol === "x402") {
2498
- const errorResponse = import_server5.NextResponse.json(
2499
- { success: false, error: message },
2500
- { status: 500 }
2501
- );
2502
- firePluginResponse(ctx, errorResponse);
2569
+ const responseBody2 = { success: false, error: message };
2570
+ const errorResponse = import_server5.NextResponse.json(responseBody2, { status: 500 });
2571
+ firePluginResponse(ctx, errorResponse, body, responseBody2, { message, cause: err });
2503
2572
  return errorResponse;
2504
2573
  }
2505
2574
  }
@@ -2658,10 +2727,11 @@ function toResponse(rawResult) {
2658
2727
  function errorResult2(error) {
2659
2728
  const status = error instanceof HttpError ? error.status : typeof error?.status === "number" ? error.status : 500;
2660
2729
  const message = error instanceof Error ? error.message : "Internal error";
2730
+ const responseBody = { success: false, error: message };
2661
2731
  return {
2662
2732
  kind: "request",
2663
- response: import_server7.NextResponse.json({ success: false, error: message }, { status }),
2664
- rawResult: void 0,
2733
+ response: import_server7.NextResponse.json(responseBody, { status }),
2734
+ rawResult: responseBody,
2665
2735
  handlerError: error
2666
2736
  };
2667
2737
  }
@@ -2792,7 +2862,13 @@ async function runDynamicRequestFlow(args) {
2792
2862
  handlerError: result.handlerError
2793
2863
  };
2794
2864
  if (result.response.status >= 400) {
2795
- return finalize(ctx, result.response, result.rawResult, body);
2865
+ return finalize(
2866
+ ctx,
2867
+ result.response,
2868
+ result.rawResult,
2869
+ body,
2870
+ failureFromCause(result.handlerError)
2871
+ );
2796
2872
  }
2797
2873
  const beforeErr = await runBeforeSettle(ctx, settleScope);
2798
2874
  if (beforeErr) return beforeErr;
@@ -2814,6 +2890,9 @@ async function runDynamicRequestFlow(args) {
2814
2890
  }
2815
2891
  });
2816
2892
  }
2893
+ function failureFromCause(cause) {
2894
+ return cause === void 0 ? void 0 : { cause };
2895
+ }
2817
2896
  function computeBilledAmount(routeEntry, result) {
2818
2897
  if (routeEntry.billing === "upto") {
2819
2898
  const total = result.uptoContext?.atomicTotal() ?? 0n;
@@ -2978,7 +3057,13 @@ async function runStaticRequestFlow(args) {
2978
3057
  if (result.response.status >= 400) {
2979
3058
  const settledScope = settleScope;
2980
3059
  await runSettledHandlerError(ctx, settledScope);
2981
- return finalize(ctx, result.response, result.rawResult, body);
3060
+ return finalize(
3061
+ ctx,
3062
+ result.response,
3063
+ result.rawResult,
3064
+ body,
3065
+ failureFromCause2(result.handlerError)
3066
+ );
2982
3067
  }
2983
3068
  return settleAndFinalizeRequest({
2984
3069
  ctx,
@@ -2991,7 +3076,13 @@ async function runStaticRequestFlow(args) {
2991
3076
  });
2992
3077
  }
2993
3078
  if (result.response.status >= 400) {
2994
- return finalize(ctx, result.response, result.rawResult, body);
3079
+ return finalize(
3080
+ ctx,
3081
+ result.response,
3082
+ result.rawResult,
3083
+ body,
3084
+ failureFromCause2(result.handlerError)
3085
+ );
2995
3086
  }
2996
3087
  const beforeErr = await runBeforeSettle(ctx, settleScope);
2997
3088
  if (beforeErr) return beforeErr;
@@ -3012,6 +3103,9 @@ async function runStaticRequestFlow(args) {
3012
3103
  }
3013
3104
  });
3014
3105
  }
3106
+ function failureFromCause2(cause) {
3107
+ return cause === void 0 ? void 0 : { cause };
3108
+ }
3015
3109
 
3016
3110
  // src/pipeline/flows/static/static-paid.ts
3017
3111
  async function runStaticPaidFlow(ctx) {
package/dist/index.d.cts CHANGED
@@ -77,13 +77,24 @@ interface ResponseMeta {
77
77
  headers: Record<string, string>;
78
78
  /** Parsed request body (when .body() was used). undefined when no body was parsed. */
79
79
  requestBody?: unknown;
80
- /** Handler return value. undefined for raw Response returns (streams) or error paths. */
80
+ /** Handler return value or structured router-generated error body. */
81
81
  responseBody?: unknown;
82
82
  }
83
83
  interface ErrorEvent {
84
84
  status: number;
85
85
  message: string;
86
86
  settled: boolean;
87
+ requestId?: string;
88
+ route?: string;
89
+ method?: string;
90
+ duration?: number;
91
+ walletAddress?: string | null;
92
+ verifiedWallet?: string | null;
93
+ clientId?: string | null;
94
+ sessionId?: string | null;
95
+ errorName?: string;
96
+ stack?: string;
97
+ cause?: unknown;
87
98
  }
88
99
  interface AuthEvent {
89
100
  /** Authentication mode that was verified */
package/dist/index.d.ts CHANGED
@@ -77,13 +77,24 @@ interface ResponseMeta {
77
77
  headers: Record<string, string>;
78
78
  /** Parsed request body (when .body() was used). undefined when no body was parsed. */
79
79
  requestBody?: unknown;
80
- /** Handler return value. undefined for raw Response returns (streams) or error paths. */
80
+ /** Handler return value or structured router-generated error body. */
81
81
  responseBody?: unknown;
82
82
  }
83
83
  interface ErrorEvent {
84
84
  status: number;
85
85
  message: string;
86
86
  settled: boolean;
87
+ requestId?: string;
88
+ route?: string;
89
+ method?: string;
90
+ duration?: number;
91
+ walletAddress?: string | null;
92
+ verifiedWallet?: string | null;
93
+ clientId?: string | null;
94
+ sessionId?: string | null;
95
+ errorName?: string;
96
+ stack?: string;
97
+ cause?: unknown;
87
98
  }
88
99
  interface AuthEvent {
89
100
  /** Authentication mode that was verified */
package/dist/index.js CHANGED
@@ -499,7 +499,8 @@ var HEADERS = {
499
499
  X402_PAYMENT_LEGACY: "X-PAYMENT",
500
500
  X402_PAYMENT_REQUIRED: "PAYMENT-REQUIRED",
501
501
  X402_PAYMENT_RESPONSE: "PAYMENT-RESPONSE",
502
- MPP_PAYMENT_RECEIPT: "Payment-Receipt"
502
+ MPP_PAYMENT_RECEIPT: "Payment-Receipt",
503
+ REQUEST_ID: "X-Request-ID"
503
504
  };
504
505
  var AUTH_SCHEME = {
505
506
  BEARER: "Bearer ",
@@ -529,19 +530,19 @@ function firePluginHook(plugin, method, ...args) {
529
530
  const result = fn.apply(plugin, args);
530
531
  if (result && typeof result.catch === "function") {
531
532
  result.catch((error) => {
532
- console.error(
533
- `[router] ERROR ${method}: ${error instanceof Error ? error.message : String(error)}`
534
- );
533
+ console.error(`[router] ERROR ${method}: ${formatUnknownError(error)}`);
535
534
  });
536
535
  }
537
536
  return result;
538
537
  } catch (error) {
539
- console.error(
540
- `[router] ERROR ${method}: ${error instanceof Error ? error.message : String(error)}`
541
- );
538
+ console.error(`[router] ERROR ${method}: ${formatUnknownError(error)}`);
542
539
  return void 0;
543
540
  }
544
541
  }
542
+ function formatUnknownError(error) {
543
+ if (error instanceof Error) return error.stack ?? error.message;
544
+ return String(error);
545
+ }
545
546
 
546
547
  // src/plugin/reporter.ts
547
548
  function createReporter(plugin, pluginCtx, route) {
@@ -632,7 +633,8 @@ function firePaymentVerified(ctx, event) {
632
633
  function firePaymentSettled(ctx, event) {
633
634
  firePluginHook(ctx.deps.plugin, "onPaymentSettled", ctx.pluginCtx, event);
634
635
  }
635
- function firePluginResponse(ctx, response, requestBody, responseBody) {
636
+ function firePluginResponse(ctx, response, requestBody, responseBody, failure) {
637
+ attachRequestId(response, ctx.meta.requestId);
636
638
  firePluginHook(ctx.deps.plugin, "onResponse", ctx.pluginCtx, {
637
639
  statusCode: response.status,
638
640
  statusText: response.statusText,
@@ -643,11 +645,9 @@ function firePluginResponse(ctx, response, requestBody, responseBody) {
643
645
  responseBody
644
646
  });
645
647
  if (response.status >= 400 && response.status !== 402) {
646
- firePluginHook(ctx.deps.plugin, "onError", ctx.pluginCtx, {
647
- status: response.status,
648
- message: response.statusText || `HTTP ${response.status}`,
649
- settled: false
650
- });
648
+ const error = buildErrorEvent(ctx, response, failure);
649
+ if (response.status >= 500) logRouterFailure(error);
650
+ firePluginHook(ctx.deps.plugin, "onError", ctx.pluginCtx, error);
651
651
  }
652
652
  }
653
653
  function fireProviderQuota(ctx, response, handlerResult) {
@@ -679,6 +679,67 @@ function computeQuotaLevel(remaining, warn, critical) {
679
679
  if (warn !== void 0 && remaining <= warn) return "warn";
680
680
  return "healthy";
681
681
  }
682
+ function attachRequestId(response, requestId) {
683
+ try {
684
+ if (!response.headers.has(HEADERS.REQUEST_ID)) {
685
+ response.headers.set(HEADERS.REQUEST_ID, requestId);
686
+ }
687
+ } catch {
688
+ }
689
+ }
690
+ function buildErrorEvent(ctx, response, failure) {
691
+ const error = errorDetails(failure?.cause);
692
+ const responseMessage = response.statusText || `HTTP ${response.status}`;
693
+ const message = failure?.message ?? error.message ?? responseMessage;
694
+ return {
695
+ status: response.status,
696
+ message,
697
+ settled: failure?.settled ?? false,
698
+ requestId: ctx.meta.requestId,
699
+ route: ctx.meta.route,
700
+ method: ctx.meta.method,
701
+ duration: Date.now() - ctx.meta.startTime,
702
+ walletAddress: ctx.meta.walletAddress,
703
+ verifiedWallet: ctx.pluginCtx.verifiedWallet,
704
+ clientId: ctx.meta.clientId,
705
+ sessionId: ctx.meta.sessionId,
706
+ errorName: error.name,
707
+ stack: error.stack,
708
+ cause: failure?.cause
709
+ };
710
+ }
711
+ function errorDetails(error) {
712
+ if (error instanceof Error) {
713
+ return {
714
+ message: error.message,
715
+ name: error.name,
716
+ stack: error.stack
717
+ };
718
+ }
719
+ if (typeof error === "object" && error !== null) {
720
+ const record = error;
721
+ return {
722
+ message: typeof record.message === "string" ? record.message : void 0,
723
+ name: typeof record.name === "string" ? record.name : void 0,
724
+ stack: typeof record.stack === "string" ? record.stack : void 0
725
+ };
726
+ }
727
+ if (typeof error === "string") return { message: error };
728
+ return {};
729
+ }
730
+ function logRouterFailure(error) {
731
+ console.error(`[router] ERROR ${error.route ?? "unknown"} ${error.status}: ${error.message}`, {
732
+ requestId: error.requestId,
733
+ method: error.method,
734
+ duration: error.duration,
735
+ walletAddress: error.walletAddress,
736
+ verifiedWallet: error.verifiedWallet,
737
+ clientId: error.clientId,
738
+ sessionId: error.sessionId,
739
+ errorName: error.errorName,
740
+ stack: error.stack
741
+ });
742
+ }
682
743
 
683
744
  // src/pipeline/steps/parse-body.ts
684
745
  async function parseBody(ctx, request = ctx.request) {
@@ -688,20 +749,19 @@ async function parseBody(ctx, request = ctx.request) {
688
749
  raw = await bufferBody(request);
689
750
  } catch (err) {
690
751
  if (!(err instanceof MalformedJsonError)) throw err;
691
- const response2 = NextResponse.json(
692
- { success: false, error: "Invalid JSON", issues: [] },
693
- { status: 400 }
694
- );
695
- firePluginResponse(ctx, response2);
752
+ const responseBody2 = { success: false, error: "Invalid JSON", issues: [] };
753
+ const response2 = NextResponse.json(responseBody2, { status: 400 });
754
+ firePluginResponse(ctx, response2, void 0, responseBody2, {
755
+ message: responseBody2.error,
756
+ cause: err
757
+ });
696
758
  return { ok: false, response: response2 };
697
759
  }
698
760
  const result = validateBody(raw, ctx.routeEntry.bodySchema);
699
761
  if (result.success) return { ok: true, data: result.data };
700
- const response = NextResponse.json(
701
- { success: false, error: result.error, issues: result.issues },
702
- { status: 400 }
703
- );
704
- firePluginResponse(ctx, response);
762
+ const responseBody = { success: false, error: result.error, issues: result.issues };
763
+ const response = NextResponse.json(responseBody, { status: 400 });
764
+ firePluginResponse(ctx, response, raw, responseBody, { message: result.error });
705
765
  return { ok: false, response };
706
766
  }
707
767
 
@@ -713,11 +773,9 @@ function validateQuery(ctx) {
713
773
  const params = Object.fromEntries(ctx.request.nextUrl.searchParams.entries());
714
774
  const result = validateBody(params, querySchema);
715
775
  if (result.success) return { ok: true, data: result.data };
716
- const response = NextResponse2.json(
717
- { success: false, error: result.error, issues: result.issues },
718
- { status: 400 }
719
- );
720
- firePluginResponse(ctx, response);
776
+ const responseBody = { success: false, error: result.error, issues: result.issues };
777
+ const response = NextResponse2.json(responseBody, { status: 400 });
778
+ firePluginResponse(ctx, response, params, responseBody, { message: result.error });
721
779
  return { ok: false, response };
722
780
  }
723
781
 
@@ -736,9 +794,13 @@ function handlerFailureError(response) {
736
794
 
737
795
  // src/pipeline/steps/fail.ts
738
796
  import { NextResponse as NextResponse3 } from "next/server";
739
- function fail(ctx, status, message, requestBody) {
740
- const response = NextResponse3.json({ success: false, error: message }, { status });
741
- firePluginResponse(ctx, response, requestBody);
797
+ function fail(ctx, status, message, requestBody, failure) {
798
+ const responseBody = { success: false, error: message };
799
+ const response = NextResponse3.json(responseBody, { status });
800
+ firePluginResponse(ctx, response, requestBody, responseBody, {
801
+ ...failure,
802
+ message: failure?.message ?? message
803
+ });
742
804
  return response;
743
805
  }
744
806
 
@@ -814,9 +876,10 @@ async function runHandler(ctx, handlerCtx) {
814
876
  function errorResult(error) {
815
877
  const status = error instanceof HttpError ? error.status : typeof error?.status === "number" ? error.status : 500;
816
878
  const message = error instanceof Error ? error.message : "Internal error";
879
+ const responseBody = { success: false, error: message };
817
880
  return {
818
- response: NextResponse4.json({ success: false, error: message }, { status }),
819
- rawResult: void 0,
881
+ response: NextResponse4.json(responseBody, { status }),
882
+ rawResult: responseBody,
820
883
  handlerError: error
821
884
  };
822
885
  }
@@ -828,9 +891,9 @@ function isThenable(value) {
828
891
  }
829
892
 
830
893
  // src/pipeline/steps/finalize/response.ts
831
- function finalize(ctx, response, rawResult, requestBody) {
894
+ function finalize(ctx, response, rawResult, requestBody, failure) {
832
895
  fireProviderQuota(ctx, response, rawResult);
833
- firePluginResponse(ctx, response, requestBody, rawResult);
896
+ firePluginResponse(ctx, response, requestBody, rawResult, failure);
834
897
  return response;
835
898
  }
836
899
 
@@ -916,7 +979,9 @@ async function settleAndFinalizeRequest(args) {
916
979
  });
917
980
  if (!settle.ok) {
918
981
  if (onSettleError) await onSettleError(settle.error, settle.failMessage);
919
- return fail(ctx, settle.failStatus ?? 500, settle.failMessage, body);
982
+ return fail(ctx, settle.failStatus ?? 500, settle.failMessage, body, {
983
+ cause: settle.error
984
+ });
920
985
  }
921
986
  return runPostSettleEpilogue({
922
987
  ctx,
@@ -951,7 +1016,9 @@ async function settleAndFinalizeStream(args) {
951
1016
  report
952
1017
  });
953
1018
  if (!settle.ok) {
954
- return fail(ctx, settle.failStatus ?? 500, settle.failMessage, body);
1019
+ return fail(ctx, settle.failStatus ?? 500, settle.failMessage, body, {
1020
+ cause: settle.error
1021
+ });
955
1022
  }
956
1023
  return runPostSettleEpilogue({
957
1024
  ctx,
@@ -978,7 +1045,13 @@ async function runHandlerOnly(ctx, wallet, account) {
978
1045
  const validateErr = await runValidate(ctx, body.data);
979
1046
  if (validateErr) return validateErr;
980
1047
  const result = await invokeUnauthed(ctx, wallet, account, body.data);
981
- return finalize(ctx, result.response, result.rawResult, body.data);
1048
+ return finalize(
1049
+ ctx,
1050
+ result.response,
1051
+ result.rawResult,
1052
+ body.data,
1053
+ result.handlerError === void 0 ? void 0 : { cause: result.handlerError }
1054
+ );
982
1055
  }
983
1056
 
984
1057
  // src/pipeline/steps/run-before-settle.ts
@@ -2417,11 +2490,9 @@ async function buildChallengeResponse(ctx, pricing, body, failure) {
2417
2490
  challengePrice = pricing ? await pricing.challengeQuote(body) : "0";
2418
2491
  } catch (err) {
2419
2492
  const message = errorMessage(err, "Price calculation failed");
2420
- const errorResponse = NextResponse5.json(
2421
- { success: false, error: message },
2422
- { status: errorStatus(err, 500) }
2423
- );
2424
- firePluginResponse(ctx, errorResponse);
2493
+ const responseBody2 = { success: false, error: message };
2494
+ const errorResponse = NextResponse5.json(responseBody2, { status: errorStatus(err, 500) });
2495
+ firePluginResponse(ctx, errorResponse, body, responseBody2, { message, cause: err });
2425
2496
  return errorResponse;
2426
2497
  }
2427
2498
  const extensions = await buildChallengeExtensions(ctx);
@@ -2453,11 +2524,9 @@ async function buildChallengeResponse(ctx, pricing, body, failure) {
2453
2524
  const message = `${strategy.protocol} challenge build failed: ${errorMessage(err, String(err))}`;
2454
2525
  ctx.report("critical", message);
2455
2526
  if (strategy.protocol === "x402") {
2456
- const errorResponse = NextResponse5.json(
2457
- { success: false, error: message },
2458
- { status: 500 }
2459
- );
2460
- firePluginResponse(ctx, errorResponse);
2527
+ const responseBody2 = { success: false, error: message };
2528
+ const errorResponse = NextResponse5.json(responseBody2, { status: 500 });
2529
+ firePluginResponse(ctx, errorResponse, body, responseBody2, { message, cause: err });
2461
2530
  return errorResponse;
2462
2531
  }
2463
2532
  }
@@ -2616,10 +2685,11 @@ function toResponse(rawResult) {
2616
2685
  function errorResult2(error) {
2617
2686
  const status = error instanceof HttpError ? error.status : typeof error?.status === "number" ? error.status : 500;
2618
2687
  const message = error instanceof Error ? error.message : "Internal error";
2688
+ const responseBody = { success: false, error: message };
2619
2689
  return {
2620
2690
  kind: "request",
2621
- response: NextResponse7.json({ success: false, error: message }, { status }),
2622
- rawResult: void 0,
2691
+ response: NextResponse7.json(responseBody, { status }),
2692
+ rawResult: responseBody,
2623
2693
  handlerError: error
2624
2694
  };
2625
2695
  }
@@ -2750,7 +2820,13 @@ async function runDynamicRequestFlow(args) {
2750
2820
  handlerError: result.handlerError
2751
2821
  };
2752
2822
  if (result.response.status >= 400) {
2753
- return finalize(ctx, result.response, result.rawResult, body);
2823
+ return finalize(
2824
+ ctx,
2825
+ result.response,
2826
+ result.rawResult,
2827
+ body,
2828
+ failureFromCause(result.handlerError)
2829
+ );
2754
2830
  }
2755
2831
  const beforeErr = await runBeforeSettle(ctx, settleScope);
2756
2832
  if (beforeErr) return beforeErr;
@@ -2772,6 +2848,9 @@ async function runDynamicRequestFlow(args) {
2772
2848
  }
2773
2849
  });
2774
2850
  }
2851
+ function failureFromCause(cause) {
2852
+ return cause === void 0 ? void 0 : { cause };
2853
+ }
2775
2854
  function computeBilledAmount(routeEntry, result) {
2776
2855
  if (routeEntry.billing === "upto") {
2777
2856
  const total = result.uptoContext?.atomicTotal() ?? 0n;
@@ -2936,7 +3015,13 @@ async function runStaticRequestFlow(args) {
2936
3015
  if (result.response.status >= 400) {
2937
3016
  const settledScope = settleScope;
2938
3017
  await runSettledHandlerError(ctx, settledScope);
2939
- return finalize(ctx, result.response, result.rawResult, body);
3018
+ return finalize(
3019
+ ctx,
3020
+ result.response,
3021
+ result.rawResult,
3022
+ body,
3023
+ failureFromCause2(result.handlerError)
3024
+ );
2940
3025
  }
2941
3026
  return settleAndFinalizeRequest({
2942
3027
  ctx,
@@ -2949,7 +3034,13 @@ async function runStaticRequestFlow(args) {
2949
3034
  });
2950
3035
  }
2951
3036
  if (result.response.status >= 400) {
2952
- return finalize(ctx, result.response, result.rawResult, body);
3037
+ return finalize(
3038
+ ctx,
3039
+ result.response,
3040
+ result.rawResult,
3041
+ body,
3042
+ failureFromCause2(result.handlerError)
3043
+ );
2953
3044
  }
2954
3045
  const beforeErr = await runBeforeSettle(ctx, settleScope);
2955
3046
  if (beforeErr) return beforeErr;
@@ -2970,6 +3061,9 @@ async function runStaticRequestFlow(args) {
2970
3061
  }
2971
3062
  });
2972
3063
  }
3064
+ function failureFromCause2(cause) {
3065
+ return cause === void 0 ? void 0 : { cause };
3066
+ }
2973
3067
 
2974
3068
  // src/pipeline/flows/static/static-paid.ts
2975
3069
  async function runStaticPaidFlow(ctx) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentcash/router",
3
- "version": "1.10.3",
3
+ "version": "1.10.4",
4
4
  "description": "Unified route builder for Next.js App Router APIs with x402, MPP, SIWX, and API key auth",
5
5
  "type": "module",
6
6
  "exports": {