@blockrun/clawrouter 0.12.254 → 0.12.256
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/cli.js +39 -12
- package/dist/index.js +39 -12
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -39252,6 +39252,26 @@ var init_stats = __esm({
|
|
|
39252
39252
|
}
|
|
39253
39253
|
});
|
|
39254
39254
|
|
|
39255
|
+
// src/timestamp-strip.ts
|
|
39256
|
+
function stripLeadingTextBlockTimestamp(blocks) {
|
|
39257
|
+
let stripped = false;
|
|
39258
|
+
return blocks.map((block) => {
|
|
39259
|
+
if (!stripped && block !== null && typeof block === "object" && block.type === "text" && typeof block.text === "string") {
|
|
39260
|
+
stripped = true;
|
|
39261
|
+
const b = block;
|
|
39262
|
+
return { ...b, text: b.text.replace(TIMESTAMP_PATTERN, "") };
|
|
39263
|
+
}
|
|
39264
|
+
return block;
|
|
39265
|
+
});
|
|
39266
|
+
}
|
|
39267
|
+
var TIMESTAMP_PATTERN;
|
|
39268
|
+
var init_timestamp_strip = __esm({
|
|
39269
|
+
"src/timestamp-strip.ts"() {
|
|
39270
|
+
"use strict";
|
|
39271
|
+
TIMESTAMP_PATTERN = /^\[\w{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+\w+\]\s*/;
|
|
39272
|
+
}
|
|
39273
|
+
});
|
|
39274
|
+
|
|
39255
39275
|
// src/dedup.ts
|
|
39256
39276
|
import { createHash } from "crypto";
|
|
39257
39277
|
function canonicalize(obj) {
|
|
@@ -39278,19 +39298,21 @@ function stripTimestamps(obj) {
|
|
|
39278
39298
|
for (const [key2, value] of Object.entries(obj)) {
|
|
39279
39299
|
if (key2 === "content" && typeof value === "string") {
|
|
39280
39300
|
result[key2] = value.replace(TIMESTAMP_PATTERN, "");
|
|
39301
|
+
} else if (key2 === "content" && Array.isArray(value)) {
|
|
39302
|
+
result[key2] = stripLeadingTextBlockTimestamp(value.map(stripTimestamps));
|
|
39281
39303
|
} else {
|
|
39282
39304
|
result[key2] = stripTimestamps(value);
|
|
39283
39305
|
}
|
|
39284
39306
|
}
|
|
39285
39307
|
return result;
|
|
39286
39308
|
}
|
|
39287
|
-
var DEFAULT_TTL_MS2, MAX_BODY_SIZE,
|
|
39309
|
+
var DEFAULT_TTL_MS2, MAX_BODY_SIZE, RequestDeduplicator;
|
|
39288
39310
|
var init_dedup = __esm({
|
|
39289
39311
|
"src/dedup.ts"() {
|
|
39290
39312
|
"use strict";
|
|
39313
|
+
init_timestamp_strip();
|
|
39291
39314
|
DEFAULT_TTL_MS2 = 3e4;
|
|
39292
39315
|
MAX_BODY_SIZE = 1048576;
|
|
39293
|
-
TIMESTAMP_PATTERN = /^\[\w{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+\w+\]\s*/;
|
|
39294
39316
|
RequestDeduplicator = class {
|
|
39295
39317
|
inflight = /* @__PURE__ */ new Map();
|
|
39296
39318
|
completed = /* @__PURE__ */ new Map();
|
|
@@ -39408,7 +39430,10 @@ function normalizeForCache(obj) {
|
|
|
39408
39430
|
if (typeof msg === "object" && msg !== null) {
|
|
39409
39431
|
const m = msg;
|
|
39410
39432
|
if (typeof m.content === "string") {
|
|
39411
|
-
return { ...m, content: m.content.replace(
|
|
39433
|
+
return { ...m, content: m.content.replace(TIMESTAMP_PATTERN, "") };
|
|
39434
|
+
}
|
|
39435
|
+
if (Array.isArray(m.content)) {
|
|
39436
|
+
return { ...m, content: stripLeadingTextBlockTimestamp(m.content) };
|
|
39412
39437
|
}
|
|
39413
39438
|
}
|
|
39414
39439
|
return msg;
|
|
@@ -39419,10 +39444,11 @@ function normalizeForCache(obj) {
|
|
|
39419
39444
|
}
|
|
39420
39445
|
return result;
|
|
39421
39446
|
}
|
|
39422
|
-
var DEFAULT_CONFIG,
|
|
39447
|
+
var DEFAULT_CONFIG, ResponseCache;
|
|
39423
39448
|
var init_response_cache = __esm({
|
|
39424
39449
|
"src/response-cache.ts"() {
|
|
39425
39450
|
"use strict";
|
|
39451
|
+
init_timestamp_strip();
|
|
39426
39452
|
DEFAULT_CONFIG = {
|
|
39427
39453
|
maxSize: 200,
|
|
39428
39454
|
defaultTTL: 600,
|
|
@@ -39430,7 +39456,6 @@ var init_response_cache = __esm({
|
|
|
39430
39456
|
// 1MB
|
|
39431
39457
|
enabled: true
|
|
39432
39458
|
};
|
|
39433
|
-
TIMESTAMP_PATTERN2 = /^\[\w{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+\w+\]\s*/;
|
|
39434
39459
|
ResponseCache = class {
|
|
39435
39460
|
cache = /* @__PURE__ */ new Map();
|
|
39436
39461
|
expirationHeap = [];
|
|
@@ -90441,7 +90466,7 @@ async function startProxy(options) {
|
|
|
90441
90466
|
console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
|
|
90442
90467
|
} else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
|
|
90443
90468
|
try {
|
|
90444
|
-
const imgResp = await fetch(img.url);
|
|
90469
|
+
const imgResp = await fetch(img.url, { signal: clientAbort.signal });
|
|
90445
90470
|
if (imgResp.ok) {
|
|
90446
90471
|
const contentType = imgResp.headers.get("content-type") ?? "image/png";
|
|
90447
90472
|
const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
|
|
@@ -90523,6 +90548,7 @@ async function startProxy(options) {
|
|
|
90523
90548
|
img2imgCost = estimateImageCost(img2imgModel, parsed.size, parsed.n || 1);
|
|
90524
90549
|
reqBody = JSON.stringify(parsed);
|
|
90525
90550
|
} catch (parseErr) {
|
|
90551
|
+
if (clientAbort.signal.aborted) return;
|
|
90526
90552
|
const msg = parseErr instanceof Error ? parseErr.message : String(parseErr);
|
|
90527
90553
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
90528
90554
|
res.end(JSON.stringify({ error: "Invalid request", details: msg }));
|
|
@@ -90563,7 +90589,7 @@ async function startProxy(options) {
|
|
|
90563
90589
|
console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
|
|
90564
90590
|
} else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
|
|
90565
90591
|
try {
|
|
90566
|
-
const imgResp = await fetch(img.url);
|
|
90592
|
+
const imgResp = await fetch(img.url, { signal: clientAbort.signal });
|
|
90567
90593
|
if (imgResp.ok) {
|
|
90568
90594
|
const contentType = imgResp.headers.get("content-type") ?? "image/png";
|
|
90569
90595
|
const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
|
|
@@ -90809,7 +90835,7 @@ async function startProxy(options) {
|
|
|
90809
90835
|
for (const clip of finalResult.data) {
|
|
90810
90836
|
if (clip.url?.startsWith("https://") || clip.url?.startsWith("http://")) {
|
|
90811
90837
|
try {
|
|
90812
|
-
const videoResp = await fetch(clip.url);
|
|
90838
|
+
const videoResp = await fetch(clip.url, { signal: clientAbort.signal });
|
|
90813
90839
|
if (videoResp.ok) {
|
|
90814
90840
|
const contentType = videoResp.headers.get("content-type") ?? "video/mp4";
|
|
90815
90841
|
const ext = contentType.includes("webm") ? "webm" : contentType.includes("quicktime") ? "mov" : "mp4";
|
|
@@ -91428,6 +91454,10 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
91428
91454
|
console.log(
|
|
91429
91455
|
`[ClawRouter] /imagegen command \u2192 ${imageModel} (${imageSize}): ${imagePrompt.slice(0, 80)}...`
|
|
91430
91456
|
);
|
|
91457
|
+
const imagegenAbort = new AbortController();
|
|
91458
|
+
res.on("close", () => {
|
|
91459
|
+
if (!res.writableEnded) imagegenAbort.abort();
|
|
91460
|
+
});
|
|
91431
91461
|
try {
|
|
91432
91462
|
const imageUpstreamUrl = `${apiBase}/v1/images/generations`;
|
|
91433
91463
|
const imageBody = JSON.stringify({
|
|
@@ -91436,10 +91466,6 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
91436
91466
|
size: imageSize,
|
|
91437
91467
|
n: 1
|
|
91438
91468
|
});
|
|
91439
|
-
const imagegenAbort = new AbortController();
|
|
91440
|
-
res.on("close", () => {
|
|
91441
|
-
if (!res.writableEnded) imagegenAbort.abort();
|
|
91442
|
-
});
|
|
91443
91469
|
const imageResponse = await payFetch(imageUpstreamUrl, {
|
|
91444
91470
|
method: "POST",
|
|
91445
91471
|
headers: { "content-type": "application/json", "user-agent": USER_AGENT },
|
|
@@ -91581,6 +91607,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
91581
91607
|
);
|
|
91582
91608
|
}
|
|
91583
91609
|
} catch (err) {
|
|
91610
|
+
if (imagegenAbort.signal.aborted) return;
|
|
91584
91611
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
91585
91612
|
console.error(`[ClawRouter] /imagegen error: ${errMsg}`);
|
|
91586
91613
|
if (!res.headersSent) {
|
package/dist/index.js
CHANGED
|
@@ -39121,6 +39121,26 @@ var init_stats = __esm({
|
|
|
39121
39121
|
}
|
|
39122
39122
|
});
|
|
39123
39123
|
|
|
39124
|
+
// src/timestamp-strip.ts
|
|
39125
|
+
function stripLeadingTextBlockTimestamp(blocks) {
|
|
39126
|
+
let stripped = false;
|
|
39127
|
+
return blocks.map((block) => {
|
|
39128
|
+
if (!stripped && block !== null && typeof block === "object" && block.type === "text" && typeof block.text === "string") {
|
|
39129
|
+
stripped = true;
|
|
39130
|
+
const b = block;
|
|
39131
|
+
return { ...b, text: b.text.replace(TIMESTAMP_PATTERN, "") };
|
|
39132
|
+
}
|
|
39133
|
+
return block;
|
|
39134
|
+
});
|
|
39135
|
+
}
|
|
39136
|
+
var TIMESTAMP_PATTERN;
|
|
39137
|
+
var init_timestamp_strip = __esm({
|
|
39138
|
+
"src/timestamp-strip.ts"() {
|
|
39139
|
+
"use strict";
|
|
39140
|
+
TIMESTAMP_PATTERN = /^\[\w{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+\w+\]\s*/;
|
|
39141
|
+
}
|
|
39142
|
+
});
|
|
39143
|
+
|
|
39124
39144
|
// src/dedup.ts
|
|
39125
39145
|
import { createHash } from "crypto";
|
|
39126
39146
|
function canonicalize(obj) {
|
|
@@ -39147,19 +39167,21 @@ function stripTimestamps(obj) {
|
|
|
39147
39167
|
for (const [key2, value] of Object.entries(obj)) {
|
|
39148
39168
|
if (key2 === "content" && typeof value === "string") {
|
|
39149
39169
|
result[key2] = value.replace(TIMESTAMP_PATTERN, "");
|
|
39170
|
+
} else if (key2 === "content" && Array.isArray(value)) {
|
|
39171
|
+
result[key2] = stripLeadingTextBlockTimestamp(value.map(stripTimestamps));
|
|
39150
39172
|
} else {
|
|
39151
39173
|
result[key2] = stripTimestamps(value);
|
|
39152
39174
|
}
|
|
39153
39175
|
}
|
|
39154
39176
|
return result;
|
|
39155
39177
|
}
|
|
39156
|
-
var DEFAULT_TTL_MS2, MAX_BODY_SIZE,
|
|
39178
|
+
var DEFAULT_TTL_MS2, MAX_BODY_SIZE, RequestDeduplicator;
|
|
39157
39179
|
var init_dedup = __esm({
|
|
39158
39180
|
"src/dedup.ts"() {
|
|
39159
39181
|
"use strict";
|
|
39182
|
+
init_timestamp_strip();
|
|
39160
39183
|
DEFAULT_TTL_MS2 = 3e4;
|
|
39161
39184
|
MAX_BODY_SIZE = 1048576;
|
|
39162
|
-
TIMESTAMP_PATTERN = /^\[\w{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+\w+\]\s*/;
|
|
39163
39185
|
RequestDeduplicator = class {
|
|
39164
39186
|
inflight = /* @__PURE__ */ new Map();
|
|
39165
39187
|
completed = /* @__PURE__ */ new Map();
|
|
@@ -39277,7 +39299,10 @@ function normalizeForCache(obj) {
|
|
|
39277
39299
|
if (typeof msg === "object" && msg !== null) {
|
|
39278
39300
|
const m = msg;
|
|
39279
39301
|
if (typeof m.content === "string") {
|
|
39280
|
-
return { ...m, content: m.content.replace(
|
|
39302
|
+
return { ...m, content: m.content.replace(TIMESTAMP_PATTERN, "") };
|
|
39303
|
+
}
|
|
39304
|
+
if (Array.isArray(m.content)) {
|
|
39305
|
+
return { ...m, content: stripLeadingTextBlockTimestamp(m.content) };
|
|
39281
39306
|
}
|
|
39282
39307
|
}
|
|
39283
39308
|
return msg;
|
|
@@ -39288,10 +39313,11 @@ function normalizeForCache(obj) {
|
|
|
39288
39313
|
}
|
|
39289
39314
|
return result;
|
|
39290
39315
|
}
|
|
39291
|
-
var DEFAULT_CONFIG,
|
|
39316
|
+
var DEFAULT_CONFIG, ResponseCache;
|
|
39292
39317
|
var init_response_cache = __esm({
|
|
39293
39318
|
"src/response-cache.ts"() {
|
|
39294
39319
|
"use strict";
|
|
39320
|
+
init_timestamp_strip();
|
|
39295
39321
|
DEFAULT_CONFIG = {
|
|
39296
39322
|
maxSize: 200,
|
|
39297
39323
|
defaultTTL: 600,
|
|
@@ -39299,7 +39325,6 @@ var init_response_cache = __esm({
|
|
|
39299
39325
|
// 1MB
|
|
39300
39326
|
enabled: true
|
|
39301
39327
|
};
|
|
39302
|
-
TIMESTAMP_PATTERN2 = /^\[\w{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+\w+\]\s*/;
|
|
39303
39328
|
ResponseCache = class {
|
|
39304
39329
|
cache = /* @__PURE__ */ new Map();
|
|
39305
39330
|
expirationHeap = [];
|
|
@@ -90261,7 +90286,7 @@ async function startProxy(options) {
|
|
|
90261
90286
|
console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
|
|
90262
90287
|
} else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
|
|
90263
90288
|
try {
|
|
90264
|
-
const imgResp = await fetch(img.url);
|
|
90289
|
+
const imgResp = await fetch(img.url, { signal: clientAbort.signal });
|
|
90265
90290
|
if (imgResp.ok) {
|
|
90266
90291
|
const contentType = imgResp.headers.get("content-type") ?? "image/png";
|
|
90267
90292
|
const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
|
|
@@ -90343,6 +90368,7 @@ async function startProxy(options) {
|
|
|
90343
90368
|
img2imgCost = estimateImageCost(img2imgModel, parsed.size, parsed.n || 1);
|
|
90344
90369
|
reqBody = JSON.stringify(parsed);
|
|
90345
90370
|
} catch (parseErr) {
|
|
90371
|
+
if (clientAbort.signal.aborted) return;
|
|
90346
90372
|
const msg = parseErr instanceof Error ? parseErr.message : String(parseErr);
|
|
90347
90373
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
90348
90374
|
res.end(JSON.stringify({ error: "Invalid request", details: msg }));
|
|
@@ -90383,7 +90409,7 @@ async function startProxy(options) {
|
|
|
90383
90409
|
console.log(`[ClawRouter] Image saved \u2192 ${img.url}`);
|
|
90384
90410
|
} else if (img.url?.startsWith("https://") || img.url?.startsWith("http://")) {
|
|
90385
90411
|
try {
|
|
90386
|
-
const imgResp = await fetch(img.url);
|
|
90412
|
+
const imgResp = await fetch(img.url, { signal: clientAbort.signal });
|
|
90387
90413
|
if (imgResp.ok) {
|
|
90388
90414
|
const contentType = imgResp.headers.get("content-type") ?? "image/png";
|
|
90389
90415
|
const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg" : contentType.includes("webp") ? "webp" : "png";
|
|
@@ -90629,7 +90655,7 @@ async function startProxy(options) {
|
|
|
90629
90655
|
for (const clip of finalResult.data) {
|
|
90630
90656
|
if (clip.url?.startsWith("https://") || clip.url?.startsWith("http://")) {
|
|
90631
90657
|
try {
|
|
90632
|
-
const videoResp = await fetch(clip.url);
|
|
90658
|
+
const videoResp = await fetch(clip.url, { signal: clientAbort.signal });
|
|
90633
90659
|
if (videoResp.ok) {
|
|
90634
90660
|
const contentType = videoResp.headers.get("content-type") ?? "video/mp4";
|
|
90635
90661
|
const ext = contentType.includes("webm") ? "webm" : contentType.includes("quicktime") ? "mov" : "mp4";
|
|
@@ -91248,6 +91274,10 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
91248
91274
|
console.log(
|
|
91249
91275
|
`[ClawRouter] /imagegen command \u2192 ${imageModel} (${imageSize}): ${imagePrompt.slice(0, 80)}...`
|
|
91250
91276
|
);
|
|
91277
|
+
const imagegenAbort = new AbortController();
|
|
91278
|
+
res.on("close", () => {
|
|
91279
|
+
if (!res.writableEnded) imagegenAbort.abort();
|
|
91280
|
+
});
|
|
91251
91281
|
try {
|
|
91252
91282
|
const imageUpstreamUrl = `${apiBase}/v1/images/generations`;
|
|
91253
91283
|
const imageBody = JSON.stringify({
|
|
@@ -91256,10 +91286,6 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
91256
91286
|
size: imageSize,
|
|
91257
91287
|
n: 1
|
|
91258
91288
|
});
|
|
91259
|
-
const imagegenAbort = new AbortController();
|
|
91260
|
-
res.on("close", () => {
|
|
91261
|
-
if (!res.writableEnded) imagegenAbort.abort();
|
|
91262
|
-
});
|
|
91263
91289
|
const imageResponse = await payFetch(imageUpstreamUrl, {
|
|
91264
91290
|
method: "POST",
|
|
91265
91291
|
headers: { "content-type": "application/json", "user-agent": USER_AGENT },
|
|
@@ -91401,6 +91427,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
91401
91427
|
);
|
|
91402
91428
|
}
|
|
91403
91429
|
} catch (err) {
|
|
91430
|
+
if (imagegenAbort.signal.aborted) return;
|
|
91404
91431
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
91405
91432
|
console.error(`[ClawRouter] /imagegen error: ${errMsg}`);
|
|
91406
91433
|
if (!res.headersSent) {
|
package/package.json
CHANGED