x402-proxy 0.8.1 → 0.8.3

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/CHANGELOG.md CHANGED
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.8.3] - 2026-03-24
11
+
12
+ ### Added
13
+ - JSON response pretty-printing: non-streaming `application/json` responses auto-formatted with 2-space indent on TTY
14
+ - `--json` flag now works: forces JSON pretty-printing even when piped (non-TTY)
15
+ - Color-coded HTTP status lines: green for 2xx, yellow for 3xx, red for 4xx/5xx
16
+
17
+ ### Fixed
18
+ - MPP streaming payment label unified from `MPP session:` to `Payment: ... MPP` to match non-streaming format
19
+ - MPP streaming status line now starts on a new line instead of appending to last JSON chunk
20
+
21
+ ## [0.8.2] - 2026-03-24
22
+
23
+ ### Fixed
24
+ - JSON request bodies sent without explicit `Content-Type` header now auto-detect as `application/json` instead of defaulting to `text/plain` - fixes servers rejecting JSON bodies on payment retry
25
+
10
26
  ## [0.8.1] - 2026-03-24
11
27
 
12
28
  ### Added
@@ -214,7 +230,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
214
230
  - `appendHistory` / `readHistory` / `calcSpend` - JSONL transaction history
215
231
  - Re-exports from `@x402/fetch`, `@x402/svm`, `@x402/evm`
216
232
 
217
- [Unreleased]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.1...HEAD
233
+ [Unreleased]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.3...HEAD
234
+ [0.8.3]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.2...v0.8.3
235
+ [0.8.2]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.1...v0.8.2
218
236
  [0.8.1]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.0...v0.8.1
219
237
  [0.8.0]: https://github.com/cascade-protocol/x402-proxy/compare/v0.7.1...v0.8.0
220
238
  [0.7.1]: https://github.com/cascade-protocol/x402-proxy/compare/v0.7.0...v0.7.1
package/dist/bin/cli.js CHANGED
@@ -301,6 +301,9 @@ async function createMppProxyHandler(opts) {
301
301
 
302
302
  //#endregion
303
303
  //#region src/commands/fetch.ts
304
+ function isStreamingResponse(res) {
305
+ return (res.headers.get("content-type") ?? "").includes("text/event-stream");
306
+ }
304
307
  const fetchCommand = buildCommand({
305
308
  docs: {
306
309
  brief: "Make a paid HTTP request (default command)",
@@ -473,6 +476,10 @@ Examples:
473
476
  if (idx > 0) headers.set(h.slice(0, idx).trim(), h.slice(idx + 1).trim());
474
477
  }
475
478
  const method = flags.method || "GET";
479
+ if (flags.body && !headers.has("Content-Type")) {
480
+ const trimmed = flags.body.trimStart();
481
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) headers.set("Content-Type", "application/json");
482
+ }
476
483
  const init = {
477
484
  method,
478
485
  headers: Object.fromEntries(headers.entries())
@@ -523,7 +530,8 @@ Examples:
523
530
  usedProtocol = "mpp";
524
531
  const elapsedMs = Date.now() - startMs;
525
532
  const spentAmount = mppPayment.amount ? Number(mppPayment.amount) : void 0;
526
- if (mppPayment && isTTY()) info(` MPP session: ${spentAmount != null ? `${formatAmount(spentAmount, "USDC")} ` : ""}(${displayNetwork(mppPayment.network)})`);
533
+ if (isTTY()) process.stderr.write("\n");
534
+ if (mppPayment && isTTY()) info(` Payment:${spentAmount != null ? ` ${formatAmount(spentAmount, "USDC")}` : ""} MPP (${displayNetwork(mppPayment.network)})`);
527
535
  if (isTTY()) dim(` Streamed (${elapsedMs}ms)`);
528
536
  if (mppPayment) {
529
537
  const record = {
@@ -684,7 +692,11 @@ Examples:
684
692
  else if (x402Payment) info(` Payment: ${x402Payment.amount ? formatAmount(Number(x402Payment.amount) / 1e6, "USDC") : "? USDC"} (${displayNetwork(x402Payment.network ?? "unknown")})`);
685
693
  if (txSig) dim(` Tx: ${txSig}`);
686
694
  }
687
- if (isTTY()) dim(` ${response.status} ${response.statusText} (${elapsedMs}ms)`);
695
+ if (isTTY()) {
696
+ const statusText = ` ${response.status} ${response.statusText} (${elapsedMs}ms)`;
697
+ const colorFn = response.status < 300 ? pc.green : response.status < 400 ? pc.yellow : pc.red;
698
+ process.stderr.write(`${colorFn(statusText)}\n`);
699
+ }
688
700
  if (x402Payment) {
689
701
  const record = {
690
702
  t: Date.now(),
@@ -715,7 +727,16 @@ Examples:
715
727
  };
716
728
  appendHistory(getHistoryPath(), record);
717
729
  }
718
- if (response.body) {
730
+ const shouldPrettyPrint = (response.headers.get("content-type") ?? "").includes("application/json") && (flags.json || isTTY()) && !isStreamingResponse(response);
731
+ if (response.body) if (shouldPrettyPrint) {
732
+ const text = await response.text();
733
+ try {
734
+ process.stdout.write(`${JSON.stringify(JSON.parse(text), null, 2)}\n`);
735
+ } catch {
736
+ process.stdout.write(text);
737
+ if (isTTY()) process.stdout.write("\n");
738
+ }
739
+ } else {
719
740
  const reader = response.body.getReader();
720
741
  try {
721
742
  while (true) {
@@ -726,8 +747,8 @@ Examples:
726
747
  } finally {
727
748
  reader.releaseLock();
728
749
  }
750
+ if (isTTY()) process.stdout.write("\n");
729
751
  }
730
- if (isTTY() && response.body) process.stdout.write("\n");
731
752
  }
732
753
  });
733
754
 
@@ -839,7 +860,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
839
860
  }
840
861
  const remoteClient = new Client({
841
862
  name: "x402-proxy",
842
- version: "0.8.1"
863
+ version: "0.8.3"
843
864
  });
844
865
  const x402Mcp = new x402MCPClient(remoteClient, x402PaymentClient, {
845
866
  autoPayment: true,
@@ -877,7 +898,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
877
898
  }
878
899
  const localServer = new Server({
879
900
  name: "x402-proxy",
880
- version: "0.8.1"
901
+ version: "0.8.3"
881
902
  }, { capabilities: {
882
903
  tools: tools.length > 0 ? {} : void 0,
883
904
  resources: remoteResources.length > 0 ? {} : void 0
@@ -972,7 +993,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
972
993
  }));
973
994
  const remoteClient = new Client({
974
995
  name: "x402-proxy",
975
- version: "0.8.1"
996
+ version: "0.8.3"
976
997
  });
977
998
  await connectTransport(remoteClient);
978
999
  const mppClient = McpClient.wrap(remoteClient, { methods: wrappedMethods });
@@ -987,7 +1008,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
987
1008
  }
988
1009
  const localServer = new Server({
989
1010
  name: "x402-proxy",
990
- version: "0.8.1"
1011
+ version: "0.8.3"
991
1012
  }, { capabilities: {
992
1013
  tools: tools.length > 0 ? {} : void 0,
993
1014
  resources: remoteResources.length > 0 ? {} : void 0
@@ -1199,7 +1220,7 @@ const routes = buildRouteMap({
1199
1220
  });
1200
1221
  const app = buildApplication(routes, {
1201
1222
  name: "x402-proxy",
1202
- versionInfo: { currentVersion: "0.8.1" },
1223
+ versionInfo: { currentVersion: "0.8.3" },
1203
1224
  scanner: { caseStyle: "allow-kebab-for-camel" }
1204
1225
  });
1205
1226
 
@@ -726,7 +726,7 @@ function createWalletCommand(ctx) {
726
726
  try {
727
727
  const snap = await getWalletSnapshot(ctx.rpcUrl, walletAddress, ctx.historyPath);
728
728
  const solscanUrl = `https://solscan.io/account/${walletAddress}`;
729
- const lines = [`x402-proxy v0.8.1`];
729
+ const lines = [`x402-proxy v0.8.3`];
730
730
  const defaultModel = ctx.allModels[0];
731
731
  if (defaultModel) lines.push("", `**Model** - ${defaultModel.name} (${defaultModel.provider})`);
732
732
  lines.push("", `**[Wallet](${solscanUrl})**`, `\`${walletAddress}\``);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x402-proxy",
3
- "version": "0.8.1",
3
+ "version": "0.8.3",
4
4
  "description": "curl for x402 paid APIs. Auto-pays any endpoint on Base, Solana, and Tempo. Also works as an OpenClaw plugin.",
5
5
  "type": "module",
6
6
  "sideEffects": false,