@wrongstack/core 0.291.2 → 0.292.1
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/coordination/director-tools.d.ts.map +1 -1
- package/dist/coordination/index.d.ts +1 -1
- package/dist/coordination/index.d.ts.map +1 -1
- package/dist/coordination/index.js +276 -152
- package/dist/coordination/index.js.map +4 -4
- package/dist/coordination/mailbox-http-router.d.ts +38 -0
- package/dist/coordination/mailbox-http-router.d.ts.map +1 -1
- package/dist/coordination/provider-status-tracker.d.ts.map +1 -1
- package/dist/core/agent-loop.d.ts.map +1 -1
- package/dist/core/agent-response.d.ts.map +1 -1
- package/dist/core/context.d.ts +10 -0
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/fallback-model.d.ts.map +1 -1
- package/dist/core/system-prompt-builder.d.ts +20 -1
- package/dist/core/system-prompt-builder.d.ts.map +1 -1
- package/dist/defaults/index.d.ts +1 -0
- package/dist/defaults/index.d.ts.map +1 -1
- package/dist/defaults/index.js +3137 -2441
- package/dist/defaults/index.js.map +4 -4
- package/dist/execution/auto-compaction-middleware.d.ts +34 -2
- package/dist/execution/auto-compaction-middleware.d.ts.map +1 -1
- package/dist/execution/compaction-core.d.ts +59 -0
- package/dist/execution/compaction-core.d.ts.map +1 -1
- package/dist/execution/compactor.d.ts.map +1 -1
- package/dist/execution/error-handler.d.ts +7 -0
- package/dist/execution/error-handler.d.ts.map +1 -1
- package/dist/execution/index.d.ts +1 -0
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/index.js +4684 -3924
- package/dist/execution/index.js.map +4 -4
- package/dist/execution/intelligent-compactor.d.ts.map +1 -1
- package/dist/execution/model-runtime.d.ts.map +1 -1
- package/dist/execution/one-shot-llm.d.ts.map +1 -1
- package/dist/execution/selective-compactor.d.ts +10 -0
- package/dist/execution/selective-compactor.d.ts.map +1 -1
- package/dist/execution/subagent-compaction.d.ts +24 -0
- package/dist/execution/subagent-compaction.d.ts.map +1 -0
- package/dist/hq/alerts.d.ts +5 -0
- package/dist/hq/alerts.d.ts.map +1 -1
- package/dist/hq/auth-audit.d.ts +115 -0
- package/dist/hq/auth-audit.d.ts.map +1 -0
- package/dist/hq/auth-store.d.ts +98 -2
- package/dist/hq/auth-store.d.ts.map +1 -1
- package/dist/hq/brain-bridge.d.ts +2 -8
- package/dist/hq/brain-bridge.d.ts.map +1 -1
- package/dist/hq/bridge-context.d.ts +74 -0
- package/dist/hq/bridge-context.d.ts.map +1 -0
- package/dist/hq/cost-bridge.d.ts +4 -10
- package/dist/hq/cost-bridge.d.ts.map +1 -1
- package/dist/hq/fleet-bridge.d.ts +2 -8
- package/dist/hq/fleet-bridge.d.ts.map +1 -1
- package/dist/hq/index.d.ts +2 -0
- package/dist/hq/index.d.ts.map +1 -1
- package/dist/hq/index.js +358 -222
- package/dist/hq/index.js.map +4 -4
- package/dist/hq/protocol/session.d.ts +13 -0
- package/dist/hq/protocol/session.d.ts.map +1 -1
- package/dist/hq/tool-bridge.d.ts +2 -8
- package/dist/hq/tool-bridge.d.ts.map +1 -1
- package/dist/hq/worktree-bridge.d.ts +2 -8
- package/dist/hq/worktree-bridge.d.ts.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6332 -4853
- package/dist/index.js.map +4 -4
- package/dist/infrastructure/index.js +32 -15
- package/dist/infrastructure/index.js.map +2 -2
- package/dist/infrastructure/provider-cache-ledger.d.ts +48 -0
- package/dist/infrastructure/provider-cache-ledger.d.ts.map +1 -0
- package/dist/infrastructure/token-counter.d.ts +4 -2
- package/dist/infrastructure/token-counter.d.ts.map +1 -1
- package/dist/kernel/events/brain-events.d.ts +2 -0
- package/dist/kernel/events/brain-events.d.ts.map +1 -1
- package/dist/kernel/events/memory-events.d.ts +102 -0
- package/dist/kernel/events/memory-events.d.ts.map +1 -1
- package/dist/kernel/events/session-events.d.ts +35 -0
- package/dist/kernel/events/session-events.d.ts.map +1 -1
- package/dist/models/index.js +161 -78
- package/dist/models/index.js.map +3 -3
- package/dist/models/llm-selector.d.ts.map +1 -1
- package/dist/notifications/index.d.ts +40 -0
- package/dist/notifications/index.d.ts.map +1 -0
- package/dist/notifications/notifier-impl.d.ts +34 -0
- package/dist/notifications/notifier-impl.d.ts.map +1 -0
- package/dist/notifications/notifier.d.ts +95 -0
- package/dist/notifications/notifier.d.ts.map +1 -0
- package/dist/notifications/types.d.ts +111 -0
- package/dist/notifications/types.d.ts.map +1 -0
- package/dist/plugin/api.d.ts +10 -1
- package/dist/plugin/api.d.ts.map +1 -1
- package/dist/registry/provider-registry.d.ts +1 -1
- package/dist/registry/provider-registry.d.ts.map +1 -1
- package/dist/security/index.js +15 -15
- package/dist/security/index.js.map +3 -3
- package/dist/skills/index.js +80 -80
- package/dist/skills/index.js.map +3 -3
- package/dist/storage/config-loader.d.ts +3 -5
- package/dist/storage/config-loader.d.ts.map +1 -1
- package/dist/storage/index.js +325 -259
- package/dist/storage/index.js.map +4 -4
- package/dist/storage/memory-consolidator.d.ts +14 -2
- package/dist/storage/memory-consolidator.d.ts.map +1 -1
- package/dist/storage/queue-store.d.ts +2 -0
- package/dist/storage/queue-store.d.ts.map +1 -1
- package/dist/tools/index.js +14 -7
- package/dist/tools/index.js.map +3 -3
- package/dist/tools/mcp-control.d.ts +1 -1
- package/dist/types/config.d.ts +64 -20
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/index.js +65 -35
- package/dist/types/index.js.map +3 -3
- package/dist/types/plugin.d.ts +11 -0
- package/dist/types/plugin.d.ts.map +1 -1
- package/dist/types/provider.d.ts +31 -0
- package/dist/types/provider.d.ts.map +1 -1
- package/dist/types/token-counter.d.ts +8 -1
- package/dist/types/token-counter.d.ts.map +1 -1
- package/dist/utils/cache-key.d.ts +19 -0
- package/dist/utils/cache-key.d.ts.map +1 -0
- package/dist/utils/compaction-preview.d.ts +8 -0
- package/dist/utils/compaction-preview.d.ts.map +1 -0
- package/dist/utils/connectivity.d.ts +36 -0
- package/dist/utils/connectivity.d.ts.map +1 -0
- package/dist/utils/context-breakdown.d.ts +59 -0
- package/dist/utils/context-breakdown.d.ts.map +1 -0
- package/dist/utils/context-evidence.d.ts +22 -0
- package/dist/utils/context-evidence.d.ts.map +1 -1
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1761 -1541
- package/dist/utils/index.js.map +4 -4
- package/dist/utils/token-estimate.d.ts +27 -0
- package/dist/utils/token-estimate.d.ts.map +1 -1
- package/instructions/llm/memory-consolidator.md +19 -3
- package/instructions/system.md +10 -2
- package/package.json +2 -2
|
@@ -328,6 +328,112 @@ function expectDefined(value, label) {
|
|
|
328
328
|
return value;
|
|
329
329
|
}
|
|
330
330
|
|
|
331
|
+
// src/utils/message-invariants.ts
|
|
332
|
+
function repairToolUseAdjacency(messages) {
|
|
333
|
+
const removedToolUses = [];
|
|
334
|
+
const removedToolResults = [];
|
|
335
|
+
let removedMessages = 0;
|
|
336
|
+
let changed = false;
|
|
337
|
+
const out = [];
|
|
338
|
+
for (let i = 0; i < messages.length; i++) {
|
|
339
|
+
const original = expectDefined(messages[i]);
|
|
340
|
+
let msg = original;
|
|
341
|
+
if (hasToolUse(msg)) {
|
|
342
|
+
const nextIds = toolResultIds(messages[i + 1]);
|
|
343
|
+
const filtered = mapContent(msg, (blocks) => {
|
|
344
|
+
const next = [];
|
|
345
|
+
for (const block of blocks) {
|
|
346
|
+
if (block.type === "tool_use" && !nextIds.has(block.id)) {
|
|
347
|
+
removedToolUses.push(block.id);
|
|
348
|
+
changed = true;
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
next.push(block);
|
|
352
|
+
}
|
|
353
|
+
return next;
|
|
354
|
+
});
|
|
355
|
+
msg = filtered ?? msg;
|
|
356
|
+
}
|
|
357
|
+
if (hasToolResult(msg)) {
|
|
358
|
+
const allowed = toolUseIds(out[out.length - 1]);
|
|
359
|
+
const filtered = mapContent(msg, (blocks) => {
|
|
360
|
+
const next = [];
|
|
361
|
+
for (const block of blocks) {
|
|
362
|
+
if (block.type === "tool_result" && !allowed.has(block.tool_use_id)) {
|
|
363
|
+
removedToolResults.push(block.tool_use_id);
|
|
364
|
+
changed = true;
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
next.push(block);
|
|
368
|
+
}
|
|
369
|
+
return next;
|
|
370
|
+
});
|
|
371
|
+
msg = filtered ?? msg;
|
|
372
|
+
}
|
|
373
|
+
if (isEmptyMessage(msg)) {
|
|
374
|
+
removedMessages++;
|
|
375
|
+
changed = true;
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
out.push(msg);
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
messages: changed ? out : messages,
|
|
382
|
+
report: { changed, removedToolUses, removedToolResults, removedMessages }
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
function hasToolUse(msg) {
|
|
386
|
+
return contentBlocks(msg).some((b) => b.type === "tool_use");
|
|
387
|
+
}
|
|
388
|
+
function hasToolResult(msg) {
|
|
389
|
+
return contentBlocks(msg).some((b) => b.type === "tool_result");
|
|
390
|
+
}
|
|
391
|
+
function toolUseIds(msg) {
|
|
392
|
+
const ids = /* @__PURE__ */ new Set();
|
|
393
|
+
if (msg?.role !== "assistant") return ids;
|
|
394
|
+
for (const block of contentBlocks(msg)) {
|
|
395
|
+
if (block.type === "tool_use") ids.add(block.id);
|
|
396
|
+
}
|
|
397
|
+
return ids;
|
|
398
|
+
}
|
|
399
|
+
function toolResultIds(msg) {
|
|
400
|
+
const ids = /* @__PURE__ */ new Set();
|
|
401
|
+
if (msg?.role !== "user") return ids;
|
|
402
|
+
for (const block of contentBlocks(msg)) {
|
|
403
|
+
if (block.type === "tool_result") ids.add(block.tool_use_id);
|
|
404
|
+
}
|
|
405
|
+
return ids;
|
|
406
|
+
}
|
|
407
|
+
function contentBlocks(msg) {
|
|
408
|
+
return msg && Array.isArray(msg.content) ? msg.content : [];
|
|
409
|
+
}
|
|
410
|
+
function mapContent(msg, fn) {
|
|
411
|
+
if (!Array.isArray(msg.content)) return msg;
|
|
412
|
+
const next = fn(msg.content);
|
|
413
|
+
if (next.length === msg.content.length && next.every((b, idx) => b === msg.content[idx])) {
|
|
414
|
+
return msg;
|
|
415
|
+
}
|
|
416
|
+
return { ...msg, content: next };
|
|
417
|
+
}
|
|
418
|
+
function hasMeaningfulContent(content) {
|
|
419
|
+
if (typeof content === "string") return content.trim().length > 0;
|
|
420
|
+
for (const block of content) {
|
|
421
|
+
if (block.type === "text") {
|
|
422
|
+
if (block.text.trim().length > 0) return true;
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
if (block.type === "thinking") {
|
|
426
|
+
if (block.thinking.trim().length > 0 || block.signature) return true;
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
return true;
|
|
430
|
+
}
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
function isEmptyMessage(msg) {
|
|
434
|
+
return !hasMeaningfulContent(msg.content);
|
|
435
|
+
}
|
|
436
|
+
|
|
331
437
|
// src/utils/glob-expand.ts
|
|
332
438
|
import * as fsp from "node:fs/promises";
|
|
333
439
|
import { isAbsolute, resolve } from "node:path";
|
|
@@ -455,112 +561,6 @@ async function expandGlob(pattern) {
|
|
|
455
561
|
return [...results];
|
|
456
562
|
}
|
|
457
563
|
|
|
458
|
-
// src/utils/message-invariants.ts
|
|
459
|
-
function repairToolUseAdjacency(messages) {
|
|
460
|
-
const removedToolUses = [];
|
|
461
|
-
const removedToolResults = [];
|
|
462
|
-
let removedMessages = 0;
|
|
463
|
-
let changed = false;
|
|
464
|
-
const out = [];
|
|
465
|
-
for (let i = 0; i < messages.length; i++) {
|
|
466
|
-
const original = expectDefined(messages[i]);
|
|
467
|
-
let msg = original;
|
|
468
|
-
if (hasToolUse(msg)) {
|
|
469
|
-
const nextIds = toolResultIds(messages[i + 1]);
|
|
470
|
-
const filtered = mapContent(msg, (blocks) => {
|
|
471
|
-
const next = [];
|
|
472
|
-
for (const block of blocks) {
|
|
473
|
-
if (block.type === "tool_use" && !nextIds.has(block.id)) {
|
|
474
|
-
removedToolUses.push(block.id);
|
|
475
|
-
changed = true;
|
|
476
|
-
continue;
|
|
477
|
-
}
|
|
478
|
-
next.push(block);
|
|
479
|
-
}
|
|
480
|
-
return next;
|
|
481
|
-
});
|
|
482
|
-
msg = filtered ?? msg;
|
|
483
|
-
}
|
|
484
|
-
if (hasToolResult(msg)) {
|
|
485
|
-
const allowed = toolUseIds(out[out.length - 1]);
|
|
486
|
-
const filtered = mapContent(msg, (blocks) => {
|
|
487
|
-
const next = [];
|
|
488
|
-
for (const block of blocks) {
|
|
489
|
-
if (block.type === "tool_result" && !allowed.has(block.tool_use_id)) {
|
|
490
|
-
removedToolResults.push(block.tool_use_id);
|
|
491
|
-
changed = true;
|
|
492
|
-
continue;
|
|
493
|
-
}
|
|
494
|
-
next.push(block);
|
|
495
|
-
}
|
|
496
|
-
return next;
|
|
497
|
-
});
|
|
498
|
-
msg = filtered ?? msg;
|
|
499
|
-
}
|
|
500
|
-
if (isEmptyMessage(msg)) {
|
|
501
|
-
removedMessages++;
|
|
502
|
-
changed = true;
|
|
503
|
-
continue;
|
|
504
|
-
}
|
|
505
|
-
out.push(msg);
|
|
506
|
-
}
|
|
507
|
-
return {
|
|
508
|
-
messages: changed ? out : messages,
|
|
509
|
-
report: { changed, removedToolUses, removedToolResults, removedMessages }
|
|
510
|
-
};
|
|
511
|
-
}
|
|
512
|
-
function hasToolUse(msg) {
|
|
513
|
-
return contentBlocks(msg).some((b) => b.type === "tool_use");
|
|
514
|
-
}
|
|
515
|
-
function hasToolResult(msg) {
|
|
516
|
-
return contentBlocks(msg).some((b) => b.type === "tool_result");
|
|
517
|
-
}
|
|
518
|
-
function toolUseIds(msg) {
|
|
519
|
-
const ids = /* @__PURE__ */ new Set();
|
|
520
|
-
if (msg?.role !== "assistant") return ids;
|
|
521
|
-
for (const block of contentBlocks(msg)) {
|
|
522
|
-
if (block.type === "tool_use") ids.add(block.id);
|
|
523
|
-
}
|
|
524
|
-
return ids;
|
|
525
|
-
}
|
|
526
|
-
function toolResultIds(msg) {
|
|
527
|
-
const ids = /* @__PURE__ */ new Set();
|
|
528
|
-
if (msg?.role !== "user") return ids;
|
|
529
|
-
for (const block of contentBlocks(msg)) {
|
|
530
|
-
if (block.type === "tool_result") ids.add(block.tool_use_id);
|
|
531
|
-
}
|
|
532
|
-
return ids;
|
|
533
|
-
}
|
|
534
|
-
function contentBlocks(msg) {
|
|
535
|
-
return msg && Array.isArray(msg.content) ? msg.content : [];
|
|
536
|
-
}
|
|
537
|
-
function mapContent(msg, fn) {
|
|
538
|
-
if (!Array.isArray(msg.content)) return msg;
|
|
539
|
-
const next = fn(msg.content);
|
|
540
|
-
if (next.length === msg.content.length && next.every((b, idx) => b === msg.content[idx])) {
|
|
541
|
-
return msg;
|
|
542
|
-
}
|
|
543
|
-
return { ...msg, content: next };
|
|
544
|
-
}
|
|
545
|
-
function hasMeaningfulContent(content) {
|
|
546
|
-
if (typeof content === "string") return content.trim().length > 0;
|
|
547
|
-
for (const block of content) {
|
|
548
|
-
if (block.type === "text") {
|
|
549
|
-
if (block.text.trim().length > 0) return true;
|
|
550
|
-
continue;
|
|
551
|
-
}
|
|
552
|
-
if (block.type === "thinking") {
|
|
553
|
-
if (block.thinking.trim().length > 0 || block.signature) return true;
|
|
554
|
-
continue;
|
|
555
|
-
}
|
|
556
|
-
return true;
|
|
557
|
-
}
|
|
558
|
-
return false;
|
|
559
|
-
}
|
|
560
|
-
function isEmptyMessage(msg) {
|
|
561
|
-
return !hasMeaningfulContent(msg.content);
|
|
562
|
-
}
|
|
563
|
-
|
|
564
564
|
// src/utils/safe-json.ts
|
|
565
565
|
function safeParse(input, maxBytes = 5e6) {
|
|
566
566
|
if (Buffer.byteLength(input, "utf8") > maxBytes) {
|
|
@@ -5235,8 +5235,8 @@ function createDelegateTool(opts) {
|
|
|
5235
5235
|
};
|
|
5236
5236
|
return {
|
|
5237
5237
|
name: "delegate",
|
|
5238
|
-
description: "Hand a piece of work to a subagent and
|
|
5239
|
-
usageHint: "Set `task` to a complete instruction. Pick `role` from roster or pass `name` for free-form.
|
|
5238
|
+
description: "Hand a piece of work to a subagent and block until it returns. This call is synchronous: the leader's iteration pauses for the full duration of the subagent's run. (Multiple `delegate` calls fired in the same assistant turn still parallelize through the provider's parallel-tool-call surface, but each one eats wall-clock time \u2014 so for fan-out you actually control, reach for the async path below.) Use `delegate` when your next step genuinely needs the subagent's verdict \u2014 a review, a fact-check, a sign-off. Has own context, own LLM call, auto-extending budget, and a partial-completion handoff path (maxHandoffs, default 1). Workers cannot recursively spawn.\n\n**Do NOT use `delegate` for fan-out you control.** Multiple sequential `delegate` calls each block the leader, wasting wall-clock time. For independent investigations you want to run in parallel \u2014 security scan + bug hunt + perf review on the same PR \u2014 use the async tool family: `spawn_subagent` to create each worker (returns a `subagentId` immediately), `assign_task` to queue work on it (returns a `taskId` immediately), then the `await_tasks` tool with `{mode: 'any'}` to fold the first useful result into the next decision while the rest keep churning. Reach for `delegate` only when the result gates your next move.",
|
|
5239
|
+
usageHint: "Set `task` to a complete instruction. Pick `role` from roster or pass `name` for free-form. Raise `maxHandoffs` (default 1, cap 8) for multi-day or multi-refactor tasks; pass larger `timeoutMs`/`maxIterations`/`maxToolCalls` only when needed. For parallel work, use `spawn_subagent` + `assign_task` + `await_tasks` instead.",
|
|
5240
5240
|
permission: "auto",
|
|
5241
5241
|
mutating: false,
|
|
5242
5242
|
managesOwnTimeout: true,
|
|
@@ -6511,8 +6511,8 @@ function makeSpawnTool(director, roster) {
|
|
|
6511
6511
|
};
|
|
6512
6512
|
return {
|
|
6513
6513
|
name: "spawn_subagent",
|
|
6514
|
-
description: "Create a new subagent under this director.
|
|
6515
|
-
usageHint: "Pass `role` (matches the roster), `description` (smart dispatch to best agent), or `name` + `provider`/`model`. Returns `{ subagentId }`.",
|
|
6514
|
+
description: "Create a new subagent under this director (own LLM context, own budget). NON-BLOCKING: returns a `subagentId` immediately without triggering any model call. Pair with `assign_task` to send work and `await_tasks` to retrieve the result later \u2014 this is the async-delegation pattern that lets the leader keep working while the subagent runs in its own context.",
|
|
6515
|
+
usageHint: "Pass `role` (matches the roster), `description` (smart dispatch to best agent), or `name` + `provider`/`model`. Returns `{ subagentId }`. Use this instead of `delegate` when you want to fan out to multiple subagents or keep the leader unblocked while work runs in parallel.",
|
|
6516
6516
|
permission: "auto",
|
|
6517
6517
|
mutating: false,
|
|
6518
6518
|
capabilities: [ToolCapabilities.SUBAGENT_SPAWN],
|
|
@@ -6994,7 +6994,7 @@ function makeAssignTool(director) {
|
|
|
6994
6994
|
};
|
|
6995
6995
|
return {
|
|
6996
6996
|
name: "assign_task",
|
|
6997
|
-
description: "
|
|
6997
|
+
description: "Queue a task on a previously spawned subagent. NON-BLOCKING: returns a `taskId` IMMEDIATELY \u2014 the subagent processes the task on its next iteration with its own LLM budget. The `taskId` is the durable handle for retrieving the result later via `await_tasks`, `roll_up`, or `ask_result`. Many `assign_task` calls can be in flight in parallel against the same or different subagents. This is the primary tool for fan-out work; do NOT use `delegate` to spawn multiple investigations sequentially.",
|
|
6998
6998
|
permission: "auto",
|
|
6999
6999
|
mutating: false,
|
|
7000
7000
|
capabilities: [ToolCapabilities.SUBAGENT_SPAWN],
|
|
@@ -7521,7 +7521,7 @@ function resultErrorText(result) {
|
|
|
7521
7521
|
function makeAwaitTasksTool(director) {
|
|
7522
7522
|
return {
|
|
7523
7523
|
name: "await_tasks",
|
|
7524
|
-
description: '
|
|
7524
|
+
description: 'Block until one or more `taskId`s complete, then return their results. The subagents keep running in the background \u2014 only the leader\'s iteration pauses, which is the point: this is the correct tool to retrieve a result you started earlier with `assign_task`. mode:"all" (default) blocks until EVERY named task completes. mode:"any" returns as soon as AT LEAST ONE completes \u2014 use it for independent tasks so you can handle each finisher immediately (reassign work, spawn helpers) instead of idling on the slowest; call again with the returned `pending` ids to pick up the next finisher. The pattern "fan out via assign_task, then await_tasks({mode:\'any\'})" is the async replacement for serial `delegate` calls.',
|
|
7525
7525
|
permission: "auto",
|
|
7526
7526
|
mutating: false,
|
|
7527
7527
|
capabilities: [ToolCapabilities.COORDINATION_FLEET_READ],
|
|
@@ -8192,9 +8192,10 @@ function hashStr(s) {
|
|
|
8192
8192
|
}
|
|
8193
8193
|
|
|
8194
8194
|
// src/types/provider.ts
|
|
8195
|
-
var CONTEXT_OVERFLOW_RE = /context.length|context.window|max.*tokens?.*exceeded|prompt is too long|too long|exceeds the context|\btokens\b.*exceed|context_length_exceeded/i;
|
|
8195
|
+
var CONTEXT_OVERFLOW_RE = /context.length|context.window|maximum context|max.*tokens?.*exceeded|prompt is too long|too long|exceeds the context|\btokens\b.*exceed|too many tokens|reduce the length|resulted in \d+ tokens|input.{0,12}too (?:large|long)|context_length_exceeded/i;
|
|
8196
8196
|
var CONTENT_FILTER_RE = /content.(filter|policy|moderation)|safety (system|filter)/i;
|
|
8197
|
-
var QUOTA_EXHAUSTED_RE = /(?:insufficient|exhausted|depleted|exceeded|no|not enough)[-_\s]*(?:quota|credit|balance)|(?:quota|credit|balance)[-_\s]*(?:exhausted|depleted|exceeded|insufficient)|billing[_\s-]*(?:hard[_\s-]*)?limit|payment required|spending limit|plan limit/i;
|
|
8197
|
+
var QUOTA_EXHAUSTED_RE = /(?:insufficient|exhausted|depleted|exceeded|no|not enough)[-_\s]*(?:quota|credit|balance)|(?:quota|credit|balance)[-_\s]*(?:exhausted|depleted|exceeded|insufficient)|billing[_\s-]*(?:hard[_\s-]*)?limit|payment required|spending limit|plan limit|usage[-_\s]*limit[-_\s]*(?:reached|exceeded)/i;
|
|
8198
|
+
var RATE_LIMIT_EXCEEDED_RE = /rate[-_\s]*limit[-_\s]*exceeded/i;
|
|
8198
8199
|
function classifyProviderError(status, body, message) {
|
|
8199
8200
|
const type = body?.type;
|
|
8200
8201
|
const text = [message, body?.message, type, body?.raw].filter(Boolean).join("\n");
|
|
@@ -8202,6 +8203,9 @@ function classifyProviderError(status, body, message) {
|
|
|
8202
8203
|
if (status === 408) return "timeout";
|
|
8203
8204
|
if (status === 599) return "stream_hang";
|
|
8204
8205
|
if (status === 402 || QUOTA_EXHAUSTED_RE.test(text)) return "quota_exhausted";
|
|
8206
|
+
if (status === 429 && body?.message && RATE_LIMIT_EXCEEDED_RE.test(body.message)) {
|
|
8207
|
+
return "quota_exhausted";
|
|
8208
|
+
}
|
|
8205
8209
|
if (type === "rate_limit_error" || status === 429) return "rate_limit";
|
|
8206
8210
|
if (type === "overloaded_error" || status === 529) return "overloaded";
|
|
8207
8211
|
if (status >= 500) return "server";
|
|
@@ -17354,6 +17358,8 @@ import { timingSafeEqual } from "node:crypto";
|
|
|
17354
17358
|
var MAILBOX_HTTP_MAX_BODY_BYTES = 256 * 1024;
|
|
17355
17359
|
var MAILBOX_HTTP_RATE_LIMIT_PER_MINUTE = 120;
|
|
17356
17360
|
var MAILBOX_HTTP_RATE_LIMIT_WINDOW_MS = 6e4;
|
|
17361
|
+
var MAILBOX_HTTP_DEFAULT_MAX_AGE_MS = 60 * 60 * 1e3;
|
|
17362
|
+
var MAILBOX_HTTP_MAX_AGE_CEILING_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
17357
17363
|
function authorizeMailboxBearerToken(request, expectedToken) {
|
|
17358
17364
|
const header = request.headers.authorization;
|
|
17359
17365
|
if (typeof header !== "string") return { allowed: false };
|
|
@@ -17397,6 +17403,7 @@ var MailboxHttpRateLimiter = class {
|
|
|
17397
17403
|
};
|
|
17398
17404
|
function createMailboxHttpRouter(options) {
|
|
17399
17405
|
const maxBodyBytes = options.maxBodyBytes ?? MAILBOX_HTTP_MAX_BODY_BYTES;
|
|
17406
|
+
const defaultMaxAgeMs = options.defaultMaxAgeMs ?? void 0;
|
|
17400
17407
|
const closeSseStreams = /* @__PURE__ */ new Set();
|
|
17401
17408
|
return {
|
|
17402
17409
|
async handle(request, response, routePath) {
|
|
@@ -17411,15 +17418,17 @@ function createMailboxHttpRouter(options) {
|
|
|
17411
17418
|
if (!access2.allowed) {
|
|
17412
17419
|
const forwardedFor = request.headers["x-forwarded-for"];
|
|
17413
17420
|
const clientIp = (Array.isArray(forwardedFor) ? forwardedFor[0] : forwardedFor)?.split(",")[0]?.trim() ?? request.socket?.remoteAddress ?? "unknown";
|
|
17414
|
-
console.warn(
|
|
17415
|
-
|
|
17416
|
-
|
|
17417
|
-
|
|
17418
|
-
|
|
17419
|
-
|
|
17420
|
-
|
|
17421
|
-
|
|
17422
|
-
|
|
17421
|
+
console.warn(
|
|
17422
|
+
JSON.stringify({
|
|
17423
|
+
level: "warn",
|
|
17424
|
+
event: "mailbox.http_auth_failure",
|
|
17425
|
+
message: `Mailbox HTTP auth rejected for ${request.method ?? "?"} ${request.url ?? "?"} from ${clientIp}`,
|
|
17426
|
+
method: request.method,
|
|
17427
|
+
url: request.url,
|
|
17428
|
+
clientIp,
|
|
17429
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
17430
|
+
})
|
|
17431
|
+
);
|
|
17423
17432
|
writeJson(
|
|
17424
17433
|
response,
|
|
17425
17434
|
access2.status ?? 401,
|
|
@@ -17446,7 +17455,9 @@ function createMailboxHttpRouter(options) {
|
|
|
17446
17455
|
method,
|
|
17447
17456
|
url,
|
|
17448
17457
|
maxBodyBytes,
|
|
17449
|
-
|
|
17458
|
+
defaultMaxAgeMs,
|
|
17459
|
+
closeSseStreams,
|
|
17460
|
+
routePath
|
|
17450
17461
|
);
|
|
17451
17462
|
} catch (error) {
|
|
17452
17463
|
const code = error instanceof MailboxHttpValidationError ? "VALIDATION_ERROR" : "INTERNAL_ERROR";
|
|
@@ -17465,85 +17476,134 @@ function createMailboxHttpRouter(options) {
|
|
|
17465
17476
|
}
|
|
17466
17477
|
};
|
|
17467
17478
|
}
|
|
17468
|
-
async function dispatchMailboxRoute(mailbox, eventEmitter, request, response, method, url, maxBodyBytes, closeSseStreams) {
|
|
17469
|
-
if (
|
|
17479
|
+
async function dispatchMailboxRoute(mailbox, eventEmitter, request, response, method, url, maxBodyBytes, defaultMaxAgeMs, closeSseStreams, routePath) {
|
|
17480
|
+
if (routePath !== void 0 && routePath.indexOf("?") === 0) {
|
|
17481
|
+
throw validationError(`routePath must not start with '?' (got ${JSON.stringify(routePath)})`);
|
|
17482
|
+
}
|
|
17483
|
+
const queryIndex = url.indexOf("?");
|
|
17484
|
+
const path20 = queryIndex === -1 ? url : url.slice(0, queryIndex);
|
|
17485
|
+
if (method === "POST" && path20 === "/mailbox/send") {
|
|
17470
17486
|
const input = validateSend(await readJsonBody(request, maxBodyBytes));
|
|
17471
17487
|
writeJson(response, 201, await mailbox.send(input));
|
|
17472
17488
|
return;
|
|
17473
17489
|
}
|
|
17474
|
-
if (method === "POST" &&
|
|
17490
|
+
if (method === "POST" && path20 === "/mailbox/query") {
|
|
17491
|
+
const queryContext = parseSinceMs(url, defaultMaxAgeMs);
|
|
17492
|
+
if ("error" in queryContext) {
|
|
17493
|
+
writeJson(response, 400, { error: queryContext.error });
|
|
17494
|
+
return;
|
|
17495
|
+
}
|
|
17475
17496
|
const messages = await mailbox.query(validateQuery(await readJsonBody(request, maxBodyBytes)));
|
|
17476
|
-
|
|
17497
|
+
const filtered = filterMailboxMessagesByTimestamp(messages, queryContext.minTimestampIso);
|
|
17498
|
+
writeJson(response, 200, { data: filtered, count: filtered.length });
|
|
17477
17499
|
return;
|
|
17478
17500
|
}
|
|
17479
|
-
if (method === "POST" &&
|
|
17501
|
+
if (method === "POST" && path20 === "/mailbox/check") {
|
|
17502
|
+
const queryContext = parseSinceMs(url, defaultMaxAgeMs);
|
|
17503
|
+
if ("error" in queryContext) {
|
|
17504
|
+
writeJson(response, 400, { error: queryContext.error });
|
|
17505
|
+
return;
|
|
17506
|
+
}
|
|
17480
17507
|
const result = await checkMailbox(
|
|
17481
17508
|
mailbox,
|
|
17482
|
-
validateCheck(await readJsonBody(request, maxBodyBytes))
|
|
17509
|
+
validateCheck(await readJsonBody(request, maxBodyBytes)),
|
|
17510
|
+
queryContext.minTimestampIso
|
|
17483
17511
|
);
|
|
17484
17512
|
writeJson(response, 200, result);
|
|
17485
17513
|
return;
|
|
17486
17514
|
}
|
|
17487
|
-
if (method === "POST" &&
|
|
17515
|
+
if (method === "POST" && path20 === "/mailbox/ack") {
|
|
17488
17516
|
const updated = await mailbox.ack(validateAck(await readJsonBody(request, maxBodyBytes)));
|
|
17489
17517
|
writeJson(response, 200, { updated });
|
|
17490
17518
|
return;
|
|
17491
17519
|
}
|
|
17492
|
-
if (method === "POST" &&
|
|
17520
|
+
if (method === "POST" && path20 === "/mailbox/ack-many") {
|
|
17493
17521
|
const updated = await mailbox.ackMany(
|
|
17494
17522
|
validateAckMany(await readJsonBody(request, maxBodyBytes))
|
|
17495
17523
|
);
|
|
17496
17524
|
writeJson(response, 200, { updated, count: updated.length });
|
|
17497
17525
|
return;
|
|
17498
17526
|
}
|
|
17499
|
-
if (method === "POST" &&
|
|
17527
|
+
if (method === "POST" && path20 === "/mailbox/unread-count") {
|
|
17500
17528
|
const body = await readJsonBody(request, maxBodyBytes);
|
|
17501
|
-
writeJson(response, 200, {
|
|
17529
|
+
writeJson(response, 200, {
|
|
17530
|
+
count: await mailbox.unreadCount(requireString(body, "forAgentId"))
|
|
17531
|
+
});
|
|
17502
17532
|
return;
|
|
17503
17533
|
}
|
|
17504
|
-
if (method === "POST" &&
|
|
17505
|
-
await mailbox.registerAgent(
|
|
17534
|
+
if (method === "POST" && path20 === "/mailbox/agents/register") {
|
|
17535
|
+
await mailbox.registerAgent(
|
|
17536
|
+
validateAgentRegistration(await readJsonBody(request, maxBodyBytes))
|
|
17537
|
+
);
|
|
17506
17538
|
writeJson(response, 200, { ok: true });
|
|
17507
17539
|
return;
|
|
17508
17540
|
}
|
|
17509
|
-
if (method === "POST" &&
|
|
17541
|
+
if (method === "POST" && path20 === "/mailbox/agents/heartbeat") {
|
|
17510
17542
|
await mailbox.heartbeat(validateAgentHeartbeat(await readJsonBody(request, maxBodyBytes)));
|
|
17511
17543
|
writeJson(response, 200, { ok: true });
|
|
17512
17544
|
return;
|
|
17513
17545
|
}
|
|
17514
|
-
if (method === "POST" &&
|
|
17515
|
-
await mailbox.registerClient(
|
|
17546
|
+
if (method === "POST" && path20 === "/mailbox/register-client") {
|
|
17547
|
+
await mailbox.registerClient(
|
|
17548
|
+
validateClientRegistration(await readJsonBody(request, maxBodyBytes))
|
|
17549
|
+
);
|
|
17516
17550
|
writeJson(response, 200, { ok: true });
|
|
17517
17551
|
return;
|
|
17518
17552
|
}
|
|
17519
|
-
if (method === "POST" &&
|
|
17520
|
-
await mailbox.clientHeartbeat(
|
|
17553
|
+
if (method === "POST" && path20 === "/mailbox/heartbeat") {
|
|
17554
|
+
await mailbox.clientHeartbeat(
|
|
17555
|
+
validateClientHeartbeat(await readJsonBody(request, maxBodyBytes))
|
|
17556
|
+
);
|
|
17521
17557
|
writeJson(response, 200, { ok: true });
|
|
17522
17558
|
return;
|
|
17523
17559
|
}
|
|
17524
|
-
if (method === "POST" &&
|
|
17560
|
+
if (method === "POST" && path20 === "/mailbox/purge-clients") {
|
|
17525
17561
|
writeJson(response, 200, { ok: true, purged: await mailbox.purgeClients() });
|
|
17526
17562
|
return;
|
|
17527
17563
|
}
|
|
17528
|
-
if (method === "GET" &&
|
|
17564
|
+
if (method === "GET" && path20 === "/mailbox/agents") {
|
|
17529
17565
|
const agents = await mailbox.getAgentStatuses();
|
|
17530
17566
|
writeJson(response, 200, { data: agents, count: agents.length });
|
|
17531
17567
|
return;
|
|
17532
17568
|
}
|
|
17533
|
-
if (method === "GET" &&
|
|
17569
|
+
if (method === "GET" && path20 === "/mailbox/agents/online") {
|
|
17534
17570
|
const agents = await mailbox.getOnlineAgents();
|
|
17535
17571
|
writeJson(response, 200, { data: agents, count: agents.length });
|
|
17536
17572
|
return;
|
|
17537
17573
|
}
|
|
17538
|
-
if (method === "GET" &&
|
|
17539
|
-
|
|
17574
|
+
if (method === "GET" && path20 === "/mailbox/events" && eventEmitter) {
|
|
17575
|
+
const queryContext = parseSinceMs(url, defaultMaxAgeMs);
|
|
17576
|
+
if ("error" in queryContext) {
|
|
17577
|
+
writeJson(response, 400, { error: queryContext.error });
|
|
17578
|
+
return;
|
|
17579
|
+
}
|
|
17580
|
+
handleSse(request, response, eventEmitter, queryContext.minTimestampIso, closeSseStreams);
|
|
17540
17581
|
return;
|
|
17541
17582
|
}
|
|
17542
17583
|
writeJson(response, 404, {
|
|
17543
17584
|
error: { code: "NOT_FOUND", message: `no route for ${method} ${url}` }
|
|
17544
17585
|
});
|
|
17545
17586
|
}
|
|
17546
|
-
function
|
|
17587
|
+
function extractEventTimestamp(event) {
|
|
17588
|
+
if (event === null || typeof event !== "object") return void 0;
|
|
17589
|
+
const top = event.timestamp;
|
|
17590
|
+
if (typeof top === "string") return top;
|
|
17591
|
+
const nestedKeys = ["messageSent", "ackUpdated"];
|
|
17592
|
+
for (const key of nestedKeys) {
|
|
17593
|
+
const nested = event[key];
|
|
17594
|
+
if (nested !== null && typeof nested === "object") {
|
|
17595
|
+
const inner = nested.timestamp;
|
|
17596
|
+
if (typeof inner === "string") return inner;
|
|
17597
|
+
}
|
|
17598
|
+
}
|
|
17599
|
+
return void 0;
|
|
17600
|
+
}
|
|
17601
|
+
function isEventOlderThan(event, minTimestampIso) {
|
|
17602
|
+
const eventTimestamp = extractEventTimestamp(event);
|
|
17603
|
+
if (eventTimestamp === void 0) return false;
|
|
17604
|
+
return eventTimestamp < minTimestampIso;
|
|
17605
|
+
}
|
|
17606
|
+
function handleSse(request, response, eventEmitter, minTimestampIso, closeSseStreams) {
|
|
17547
17607
|
response.writeHead(200, {
|
|
17548
17608
|
"Content-Type": "text/event-stream",
|
|
17549
17609
|
"Cache-Control": "no-store",
|
|
@@ -17553,6 +17613,9 @@ function handleSse(request, response, eventEmitter, closeSseStreams) {
|
|
|
17553
17613
|
response.write(": connected\n\n");
|
|
17554
17614
|
const unsubscribe = eventEmitter.subscribe((event) => {
|
|
17555
17615
|
try {
|
|
17616
|
+
if (minTimestampIso !== void 0 && isEventOlderThan(event, minTimestampIso)) {
|
|
17617
|
+
return;
|
|
17618
|
+
}
|
|
17556
17619
|
response.write(`data: ${JSON.stringify(event)}
|
|
17557
17620
|
|
|
17558
17621
|
`);
|
|
@@ -17662,6 +17725,52 @@ function optionalNumber(object, key) {
|
|
|
17662
17725
|
}
|
|
17663
17726
|
return value;
|
|
17664
17727
|
}
|
|
17728
|
+
function parseSinceMs(url, defaultMaxAgeMs) {
|
|
17729
|
+
const queryStart = url.indexOf("?");
|
|
17730
|
+
if (queryStart === -1) return resolveDefault(defaultMaxAgeMs, Date.now());
|
|
17731
|
+
const params = new URLSearchParams(url.slice(queryStart + 1));
|
|
17732
|
+
if (!params.has("sinceMs")) return resolveDefault(defaultMaxAgeMs, Date.now());
|
|
17733
|
+
const raw = params.get("sinceMs");
|
|
17734
|
+
if (raw === null || raw === void 0 || raw === "") {
|
|
17735
|
+
return {
|
|
17736
|
+
error: {
|
|
17737
|
+
code: "VALIDATION_ERROR",
|
|
17738
|
+
message: 'query parameter "sinceMs" is required (integer in milliseconds) when present'
|
|
17739
|
+
}
|
|
17740
|
+
};
|
|
17741
|
+
}
|
|
17742
|
+
if (!/^\d+$/.test(raw)) {
|
|
17743
|
+
return {
|
|
17744
|
+
error: {
|
|
17745
|
+
code: "VALIDATION_ERROR",
|
|
17746
|
+
message: 'query parameter "sinceMs" must be a non-negative integer (milliseconds)'
|
|
17747
|
+
}
|
|
17748
|
+
};
|
|
17749
|
+
}
|
|
17750
|
+
const requestedMs = Number(raw);
|
|
17751
|
+
if (!Number.isFinite(requestedMs) || requestedMs > Number.MAX_SAFE_INTEGER) {
|
|
17752
|
+
return {
|
|
17753
|
+
error: {
|
|
17754
|
+
code: "VALIDATION_ERROR",
|
|
17755
|
+
message: `query parameter "sinceMs" is out of range (max ${Number.MAX_SAFE_INTEGER})`
|
|
17756
|
+
}
|
|
17757
|
+
};
|
|
17758
|
+
}
|
|
17759
|
+
const now = Date.now();
|
|
17760
|
+
if (requestedMs === 0) return { minTimestampIso: void 0 };
|
|
17761
|
+
const effectiveMs = Math.min(requestedMs, MAILBOX_HTTP_MAX_AGE_CEILING_MS);
|
|
17762
|
+
return { minTimestampIso: new Date(now - effectiveMs).toISOString() };
|
|
17763
|
+
}
|
|
17764
|
+
function resolveDefault(defaultMaxAgeMs, now) {
|
|
17765
|
+
if (defaultMaxAgeMs === void 0 || !Number.isFinite(defaultMaxAgeMs) || defaultMaxAgeMs < 0 || defaultMaxAgeMs === 0) {
|
|
17766
|
+
return { minTimestampIso: void 0 };
|
|
17767
|
+
}
|
|
17768
|
+
return { minTimestampIso: new Date(now - defaultMaxAgeMs).toISOString() };
|
|
17769
|
+
}
|
|
17770
|
+
function filterMailboxMessagesByTimestamp(messages, minTimestampIso) {
|
|
17771
|
+
if (minTimestampIso === void 0) return messages.slice();
|
|
17772
|
+
return messages.filter((message) => message.timestamp >= minTimestampIso);
|
|
17773
|
+
}
|
|
17665
17774
|
function optionalBoolean(object, key) {
|
|
17666
17775
|
if (typeof object !== "object" || object === null) return void 0;
|
|
17667
17776
|
const value = object[key];
|
|
@@ -17782,7 +17891,7 @@ function validateQuery(body) {
|
|
|
17782
17891
|
if (incompleteOnly !== void 0) result.incompleteOnly = incompleteOnly;
|
|
17783
17892
|
return result;
|
|
17784
17893
|
}
|
|
17785
|
-
async function checkMailbox(mailbox, input) {
|
|
17894
|
+
async function checkMailbox(mailbox, input, minTimestampIso) {
|
|
17786
17895
|
const limit = input.limit ?? 20;
|
|
17787
17896
|
const markRead = input.markRead ?? true;
|
|
17788
17897
|
const completed = input.completed ?? false;
|
|
@@ -17790,8 +17899,9 @@ async function checkMailbox(mailbox, input) {
|
|
|
17790
17899
|
const batches = await Promise.all(
|
|
17791
17900
|
targets.map((to) => mailbox.query({ to, unreadBy: input.agentId, limit }))
|
|
17792
17901
|
);
|
|
17902
|
+
const withinWindow = filterMailboxMessagesByTimestamp(batches.flat(), minTimestampIso);
|
|
17793
17903
|
const seen = /* @__PURE__ */ new Set();
|
|
17794
|
-
const messages =
|
|
17904
|
+
const messages = withinWindow.filter((message) => {
|
|
17795
17905
|
if (seen.has(message.id) || message.from === input.agentId) return false;
|
|
17796
17906
|
seen.add(message.id);
|
|
17797
17907
|
return true;
|
|
@@ -19354,19 +19464,24 @@ var ProviderModelStatusTracker = class {
|
|
|
19354
19464
|
let newState = s.state;
|
|
19355
19465
|
let reason = "";
|
|
19356
19466
|
const quotaExhausted = kind === "quota_exhausted" || isQuotaExhausted(kind, status, message);
|
|
19467
|
+
const endpointUnreachable = isEndpointUnreachable(kind, status, message);
|
|
19357
19468
|
if (quotaExhausted) {
|
|
19358
19469
|
newState = "blocked";
|
|
19359
19470
|
reason = "quota_exhausted";
|
|
19360
19471
|
s.stateExpiresAt = now + this.cfg.quotaBlockDurationMs;
|
|
19472
|
+
} else if (endpointUnreachable) {
|
|
19473
|
+
newState = "blocked";
|
|
19474
|
+
reason = "endpoint_unreachable";
|
|
19475
|
+
s.stateExpiresAt = now + this.cfg.quotaBlockDurationMs;
|
|
19361
19476
|
}
|
|
19362
|
-
if (!quotaExhausted && s.state === "healthy") {
|
|
19477
|
+
if (!quotaExhausted && !endpointUnreachable && s.state === "healthy") {
|
|
19363
19478
|
if (s.consecutiveFailures >= this.cfg.degradedAfterFailures) {
|
|
19364
19479
|
newState = "degraded";
|
|
19365
19480
|
reason = `consecutive_failures_${s.consecutiveFailures}`;
|
|
19366
19481
|
s.stateExpiresAt = now + this.cfg.degradedDurationMs;
|
|
19367
19482
|
}
|
|
19368
19483
|
}
|
|
19369
|
-
if (!quotaExhausted && (s.state === "degraded" || s.state === "healthy")) {
|
|
19484
|
+
if (!quotaExhausted && !endpointUnreachable && (s.state === "degraded" || s.state === "healthy")) {
|
|
19370
19485
|
if (s.rateLimitHits >= this.cfg.blockAfterRateLimitHits) {
|
|
19371
19486
|
newState = "blocked";
|
|
19372
19487
|
reason = `rate_limit_threshold_${this.cfg.blockAfterRateLimitHits}`;
|
|
@@ -19696,13 +19811,20 @@ function unpairKey(key) {
|
|
|
19696
19811
|
if (idx === -1) return [key, ""];
|
|
19697
19812
|
return [key.slice(0, idx), key.slice(idx + 1)];
|
|
19698
19813
|
}
|
|
19699
|
-
var QUOTA_EXHAUSTED_RE2 = /(?:insufficient|exhausted|depleted|exceeded|no|not enough)[-_\s]*(?:quota|credit|balance)|(?:quota|credit|balance)[-_\s]*(?:exhausted|depleted|exceeded|insufficient)|billing[_\s-]*(?:hard[_\s-]*)?limit|payment required|spending limit|plan limit/i;
|
|
19814
|
+
var QUOTA_EXHAUSTED_RE2 = /(?:insufficient|exhausted|depleted|exceeded|no|not enough)[-_\s]*(?:quota|credit|balance)|(?:quota|credit|balance)[-_\s]*(?:exhausted|depleted|exceeded|insufficient)|billing[_\s-]*(?:hard[_\s-]*)?limit|payment required|spending limit|plan limit|usage[-_\s]*limit[-_\s]*(?:reached|exceeded)|rate[-_\s]*limit[-_\s]*exceeded/i;
|
|
19700
19815
|
function isQuotaExhausted(kind, status, message) {
|
|
19701
19816
|
if (status === 402) return true;
|
|
19702
19817
|
if (kind !== "rate_limit" && kind !== "quota_exhausted" && kind !== "invalid_request" && kind !== "auth")
|
|
19703
19818
|
return false;
|
|
19704
19819
|
return QUOTA_EXHAUSTED_RE2.test(message);
|
|
19705
19820
|
}
|
|
19821
|
+
var ENDPOINT_UNREACHABLE_RE = /(?:upstream|origin|backend|endpoint)[-_\s]*(?:unreachable|refused|connect(?:ion)?[-_\s]*(?:refused|error|fail)|unavailable|down|timeout)|no[-_\s]*(?:healthy|valid)[-_\s]*upstream|cannot[-_\s]*connect|connection[-_\s]*(?:refused|reset|closed|timed?[-_\s]out)/i;
|
|
19822
|
+
function isEndpointUnreachable(kind, status, message) {
|
|
19823
|
+
if (status !== 502 && status !== 503 && status !== 0) return false;
|
|
19824
|
+
if (kind !== "server" && kind !== "network" && kind !== "overloaded" && kind !== "timeout")
|
|
19825
|
+
return false;
|
|
19826
|
+
return ENDPOINT_UNREACHABLE_RE.test(message);
|
|
19827
|
+
}
|
|
19706
19828
|
function safeCount(value) {
|
|
19707
19829
|
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : 0;
|
|
19708
19830
|
}
|
|
@@ -22911,6 +23033,8 @@ export {
|
|
|
22911
23033
|
MAILBOX_HEALTH_DEFAULT_FROM,
|
|
22912
23034
|
MAILBOX_HEALTH_DEFAULT_INTERVAL_MS,
|
|
22913
23035
|
MAILBOX_HEALTH_DEFAULT_TIMEOUT_MS,
|
|
23036
|
+
MAILBOX_HTTP_DEFAULT_MAX_AGE_MS,
|
|
23037
|
+
MAILBOX_HTTP_MAX_AGE_CEILING_MS,
|
|
22914
23038
|
MAILBOX_HTTP_MAX_BODY_BYTES,
|
|
22915
23039
|
MAILBOX_HTTP_RATE_LIMIT_PER_MINUTE,
|
|
22916
23040
|
MAILBOX_HTTP_RATE_LIMIT_WINDOW_MS,
|