@blockrun/clawrouter 0.9.3 → 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/README.md +28 -17
- package/dist/cli.js +23 -49
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -8
- package/dist/index.js +23 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
513
|
-
* When enabled, requests
|
|
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
|
-
|
|
2086
|
-
entry.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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() {
|
|
@@ -4026,7 +4031,6 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
4026
4031
|
}
|
|
4027
4032
|
const autoCompress = options.autoCompressRequests ?? true;
|
|
4028
4033
|
const compressionThreshold = options.compressionThresholdKB ?? 180;
|
|
4029
|
-
const sizeLimit = options.maxRequestSizeKB ?? 200;
|
|
4030
4034
|
const requestSizeKB = Math.ceil(body.length / 1024);
|
|
4031
4035
|
if (autoCompress && requestSizeKB > compressionThreshold) {
|
|
4032
4036
|
try {
|
|
@@ -4068,21 +4072,6 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
4068
4072
|
);
|
|
4069
4073
|
parsed.messages = compressionResult.messages;
|
|
4070
4074
|
body = Buffer.from(JSON.stringify(parsed));
|
|
4071
|
-
if (compressedSizeKB > sizeLimit) {
|
|
4072
|
-
const errorMsg = {
|
|
4073
|
-
error: {
|
|
4074
|
-
message: `Request size ${compressedSizeKB}KB still exceeds limit after compression (original: ${requestSizeKB}KB). Please reduce context size.`,
|
|
4075
|
-
type: "request_too_large",
|
|
4076
|
-
original_size_kb: requestSizeKB,
|
|
4077
|
-
compressed_size_kb: compressedSizeKB,
|
|
4078
|
-
limit_kb: sizeLimit,
|
|
4079
|
-
help: "Try: 1) Remove old messages from history, 2) Summarize large tool results, 3) Use direct API for very large contexts"
|
|
4080
|
-
}
|
|
4081
|
-
};
|
|
4082
|
-
res.writeHead(413, { "Content-Type": "application/json" });
|
|
4083
|
-
res.end(JSON.stringify(errorMsg));
|
|
4084
|
-
return;
|
|
4085
|
-
}
|
|
4086
4075
|
}
|
|
4087
4076
|
} catch (err) {
|
|
4088
4077
|
console.warn(
|
|
@@ -4090,21 +4079,6 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
4090
4079
|
);
|
|
4091
4080
|
}
|
|
4092
4081
|
}
|
|
4093
|
-
const finalSizeKB = Math.ceil(body.length / 1024);
|
|
4094
|
-
if (finalSizeKB > sizeLimit) {
|
|
4095
|
-
const errorMsg = {
|
|
4096
|
-
error: {
|
|
4097
|
-
message: `Request size ${finalSizeKB}KB exceeds limit ${sizeLimit}KB. Please reduce context size.`,
|
|
4098
|
-
type: "request_too_large",
|
|
4099
|
-
size_kb: finalSizeKB,
|
|
4100
|
-
limit_kb: sizeLimit,
|
|
4101
|
-
help: "Try: 1) Remove old messages from history, 2) Summarize large tool results, 3) Enable compression (autoCompressRequests: true)"
|
|
4102
|
-
}
|
|
4103
|
-
};
|
|
4104
|
-
res.writeHead(413, { "Content-Type": "application/json" });
|
|
4105
|
-
res.end(JSON.stringify(errorMsg));
|
|
4106
|
-
return;
|
|
4107
|
-
}
|
|
4108
4082
|
const dedupKey = RequestDeduplicator.hash(body);
|
|
4109
4083
|
const cached = deduplicator.getCached(dedupKey);
|
|
4110
4084
|
if (cached) {
|