@blockrun/clawrouter 0.9.2 → 0.9.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.d.ts CHANGED
@@ -509,8 +509,8 @@ type ProxyOptions = {
509
509
  */
510
510
  sessionConfig?: Partial<SessionConfig>;
511
511
  /**
512
- * Auto-compress large requests to fit within API limits.
513
- * When enabled, requests approaching 200KB are automatically compressed using
512
+ * Auto-compress large requests to reduce network usage.
513
+ * When enabled, requests are automatically compressed using
514
514
  * LLM-safe context compression (15-40% reduction).
515
515
  * Default: true
516
516
  */
@@ -521,11 +521,6 @@ type ProxyOptions = {
521
521
  * Set to 0 to compress all requests.
522
522
  */
523
523
  compressionThresholdKB?: number;
524
- /**
525
- * Maximum request size in KB after compression (default: 200).
526
- * Hard limit enforced by BlockRun API.
527
- */
528
- maxRequestSizeKB?: number;
529
524
  onReady?: (port: number) => void;
530
525
  onError?: (error: Error) => void;
531
526
  onPayment?: (info: {
@@ -678,7 +673,8 @@ declare class RequestDeduplicator {
678
673
  markInflight(key: string): void;
679
674
  /** Complete an in-flight request — cache result and notify waiters. */
680
675
  complete(key: string, result: CachedResponse): void;
681
- /** Remove an in-flight entry on error (don't cache failures). */
676
+ /** Remove an in-flight entry on error (don't cache failures).
677
+ * Also rejects any waiters so they can retry independently. */
682
678
  removeInflight(key: string): void;
683
679
  /** Prune expired completed entries. */
684
680
  private prune;
package/dist/index.js CHANGED
@@ -2082,26 +2082,14 @@ var RequestDeduplicator = class {
2082
2082
  getInflight(key) {
2083
2083
  const entry = this.inflight.get(key);
2084
2084
  if (!entry) return void 0;
2085
- const promise = new Promise((resolve) => {
2086
- entry.waiters.push(
2087
- new Promise((r) => {
2088
- const orig = entry.resolve;
2089
- entry.resolve = (result) => {
2090
- orig(result);
2091
- resolve(result);
2092
- r(result);
2093
- };
2094
- })
2095
- );
2085
+ return new Promise((resolve) => {
2086
+ entry.resolvers.push(resolve);
2096
2087
  });
2097
- return promise;
2098
2088
  }
2099
2089
  /** Mark a request as in-flight. */
2100
2090
  markInflight(key) {
2101
2091
  this.inflight.set(key, {
2102
- resolve: () => {
2103
- },
2104
- waiters: []
2092
+ resolvers: []
2105
2093
  });
2106
2094
  }
2107
2095
  /** Complete an in-flight request — cache result and notify waiters. */
@@ -2111,14 +2099,31 @@ var RequestDeduplicator = class {
2111
2099
  }
2112
2100
  const entry = this.inflight.get(key);
2113
2101
  if (entry) {
2114
- entry.resolve(result);
2102
+ for (const resolve of entry.resolvers) {
2103
+ resolve(result);
2104
+ }
2115
2105
  this.inflight.delete(key);
2116
2106
  }
2117
2107
  this.prune();
2118
2108
  }
2119
- /** Remove an in-flight entry on error (don't cache failures). */
2109
+ /** Remove an in-flight entry on error (don't cache failures).
2110
+ * Also rejects any waiters so they can retry independently. */
2120
2111
  removeInflight(key) {
2121
- this.inflight.delete(key);
2112
+ const entry = this.inflight.get(key);
2113
+ if (entry) {
2114
+ const errorBody = Buffer.from(JSON.stringify({
2115
+ error: { message: "Original request failed, please retry", type: "dedup_origin_failed" }
2116
+ }));
2117
+ for (const resolve of entry.resolvers) {
2118
+ resolve({
2119
+ status: 503,
2120
+ headers: { "content-type": "application/json" },
2121
+ body: errorBody,
2122
+ completedAt: Date.now()
2123
+ });
2124
+ }
2125
+ this.inflight.delete(key);
2126
+ }
2122
2127
  }
2123
2128
  /** Prune expired completed entries. */
2124
2129
  prune() {
@@ -3391,6 +3396,8 @@ var FALLBACK_STATUS_CODES = [
3391
3396
  // Payment required - but from upstream, not x402
3392
3397
  403,
3393
3398
  // Forbidden - provider restrictions
3399
+ 413,
3400
+ // Payload too large - request exceeds model's context limit
3394
3401
  429,
3395
3402
  // Rate limited
3396
3403
  500,
@@ -4024,7 +4031,6 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
4024
4031
  }
4025
4032
  const autoCompress = options.autoCompressRequests ?? true;
4026
4033
  const compressionThreshold = options.compressionThresholdKB ?? 180;
4027
- const sizeLimit = options.maxRequestSizeKB ?? 200;
4028
4034
  const requestSizeKB = Math.ceil(body.length / 1024);
4029
4035
  if (autoCompress && requestSizeKB > compressionThreshold) {
4030
4036
  try {
@@ -4066,21 +4072,6 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
4066
4072
  );
4067
4073
  parsed.messages = compressionResult.messages;
4068
4074
  body = Buffer.from(JSON.stringify(parsed));
4069
- if (compressedSizeKB > sizeLimit) {
4070
- const errorMsg = {
4071
- error: {
4072
- message: `Request size ${compressedSizeKB}KB still exceeds limit after compression (original: ${requestSizeKB}KB). Please reduce context size.`,
4073
- type: "request_too_large",
4074
- original_size_kb: requestSizeKB,
4075
- compressed_size_kb: compressedSizeKB,
4076
- limit_kb: sizeLimit,
4077
- help: "Try: 1) Remove old messages from history, 2) Summarize large tool results, 3) Use direct API for very large contexts"
4078
- }
4079
- };
4080
- res.writeHead(413, { "Content-Type": "application/json" });
4081
- res.end(JSON.stringify(errorMsg));
4082
- return;
4083
- }
4084
4075
  }
4085
4076
  } catch (err) {
4086
4077
  console.warn(
@@ -4088,21 +4079,6 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
4088
4079
  );
4089
4080
  }
4090
4081
  }
4091
- const finalSizeKB = Math.ceil(body.length / 1024);
4092
- if (finalSizeKB > sizeLimit) {
4093
- const errorMsg = {
4094
- error: {
4095
- message: `Request size ${finalSizeKB}KB exceeds limit ${sizeLimit}KB. Please reduce context size.`,
4096
- type: "request_too_large",
4097
- size_kb: finalSizeKB,
4098
- limit_kb: sizeLimit,
4099
- help: "Try: 1) Remove old messages from history, 2) Summarize large tool results, 3) Enable compression (autoCompressRequests: true)"
4100
- }
4101
- };
4102
- res.writeHead(413, { "Content-Type": "application/json" });
4103
- res.end(JSON.stringify(errorMsg));
4104
- return;
4105
- }
4106
4082
  const dedupKey = RequestDeduplicator.hash(body);
4107
4083
  const cached = deduplicator.getCached(dedupKey);
4108
4084
  if (cached) {