@wrongstack/core 0.302.0 → 0.302.2
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/agent-status-tracker.d.ts +6 -2
- package/dist/chronicle/index.js +1836 -1645
- package/dist/chronicle/metrics-store.d.ts +14 -0
- package/dist/chronicle/project-server-protocol.d.ts +13 -0
- package/dist/chronicle/project-server.js +1759 -1583
- package/dist/chronicle/rollup-adapter.d.ts +2 -0
- package/dist/chronicle/sqlite-journal.d.ts +59 -0
- package/dist/coordination/index.js +790 -248
- package/dist/coordination/mail-tools.d.ts +2 -2
- package/dist/core/continue-intent.d.ts +2 -0
- package/dist/core/conversation-state.d.ts +5 -0
- package/dist/core/index.js +120 -19
- package/dist/defaults/index.js +927 -373
- package/dist/execution/index.js +27 -10
- package/dist/index.d.ts +3 -1
- package/dist/index.js +8762 -6780
- package/dist/infrastructure/index.js +722 -672
- package/dist/kernel/events/memory-events.d.ts +62 -0
- package/dist/plugin/index.js +2154 -1979
- package/dist/session-catalog/client.d.ts +62 -0
- package/dist/session-catalog/endpoint.d.ts +6 -0
- package/dist/session-catalog/index.d.ts +6 -0
- package/dist/session-catalog/index.js +1978 -0
- package/dist/session-catalog/project-server.d.ts +3 -0
- package/dist/session-catalog/project-server.js +1838 -0
- package/dist/session-catalog/protocol.d.ts +275 -0
- package/dist/session-catalog/registry.d.ts +59 -0
- package/dist/session-catalog/store.d.ts +55 -0
- package/dist/storage/index.d.ts +42 -38
- package/dist/storage/index.js +14279 -13393
- package/dist/storage/session-event-bridge.d.ts +2 -2
- package/dist/storage/session-store.d.ts +6 -0
- package/dist/tools/index.js +8 -2
- package/dist/types/context-evidence.d.ts +2 -0
- package/dist/types/messages.d.ts +8 -0
- package/dist/types/session.d.ts +19 -0
- package/dist/utils/context-evidence.d.ts +13 -1
- package/dist/utils/index.js +26 -2
- package/instructions/system-lite.md +11 -2
- package/instructions/system-pro.md +14 -0
- package/instructions/system.md +14 -0
- package/package.json +7 -3
|
@@ -75,12 +75,12 @@ export declare function makeMailSendTool(opts?: MailToolsOptions): {
|
|
|
75
75
|
required: string[];
|
|
76
76
|
};
|
|
77
77
|
execute(input: unknown, ctx: Context): Promise<{
|
|
78
|
-
messageId?: never;
|
|
79
|
-
to?: never;
|
|
80
78
|
summary?: never;
|
|
81
79
|
ok: boolean;
|
|
82
80
|
error: string;
|
|
81
|
+
messageId?: never;
|
|
83
82
|
from?: never;
|
|
83
|
+
to?: never;
|
|
84
84
|
} | {
|
|
85
85
|
error?: never;
|
|
86
86
|
ok: boolean;
|
|
@@ -65,6 +65,8 @@ export interface ContinuationInput {
|
|
|
65
65
|
}
|
|
66
66
|
export interface ResolvedContinuation {
|
|
67
67
|
source: ContinuationSource;
|
|
68
|
+
/** Stable todo id when the continuation is grounded in the live work list. */
|
|
69
|
+
todoId?: string | undefined;
|
|
68
70
|
/**
|
|
69
71
|
* The concrete instruction injected as the next user turn in place of the
|
|
70
72
|
* bare "continue". Written for the model, not the human.
|
|
@@ -20,6 +20,11 @@ export type StateChange = {
|
|
|
20
20
|
} | {
|
|
21
21
|
kind: 'messages_replaced';
|
|
22
22
|
messages: readonly Message[];
|
|
23
|
+
}
|
|
24
|
+
/** The oldest `count` messages were evicted; see the `messages_dropped` SessionEvent. */
|
|
25
|
+
| {
|
|
26
|
+
kind: 'messages_dropped';
|
|
27
|
+
count: number;
|
|
23
28
|
} | {
|
|
24
29
|
kind: 'message_updated';
|
|
25
30
|
index: number;
|
package/dist/core/index.js
CHANGED
|
@@ -3980,6 +3980,10 @@ import * as path9 from "node:path";
|
|
|
3980
3980
|
var MAX_TOOL_CALLS = 80;
|
|
3981
3981
|
var MAX_FACTS = 40;
|
|
3982
3982
|
var MAX_ERRORS = 20;
|
|
3983
|
+
var MAX_RECENT_USER_TURNS = 8;
|
|
3984
|
+
var MAX_USER_TURN_CHARS = 700;
|
|
3985
|
+
var MAX_CONTINUITY_CHARS = 3600;
|
|
3986
|
+
var RUNTIME_CONTEXT_INPUT_PATTERN = /^\[(?:kanban todo update|fleet pulse|loop-detector|todo-reconciliation|mailbox|btw|system|context_state)\b/i;
|
|
3983
3987
|
var RECENT_TOOL_CALL_SCAN_LIMIT = 20;
|
|
3984
3988
|
var EXTRACT_CONTENT_CAP_CHARS = 1e4;
|
|
3985
3989
|
var EXTRACT_ERROR_TAIL_LINES = 200;
|
|
@@ -3987,6 +3991,7 @@ var WRITE_TOOLS = /* @__PURE__ */ new Set(["edit", "write", "replace", "patch"])
|
|
|
3987
3991
|
var READ_TOOLS = /* @__PURE__ */ new Set(["read", "grep", "glob", "ls", "tree"]);
|
|
3988
3992
|
function createContextEvidenceState() {
|
|
3989
3993
|
return {
|
|
3994
|
+
recentUserTurns: [],
|
|
3990
3995
|
sessionGoals: [],
|
|
3991
3996
|
implicitFacts: [],
|
|
3992
3997
|
activeErrors: [],
|
|
@@ -3998,15 +4003,55 @@ function createContextEvidenceState() {
|
|
|
3998
4003
|
};
|
|
3999
4004
|
}
|
|
4000
4005
|
function recordUserIntentEvidence(ctx, text) {
|
|
4001
|
-
|
|
4006
|
+
if (isRuntimeContextInput(text)) return;
|
|
4007
|
+
const intent = normalizeWhitespace(text).slice(0, MAX_USER_TURN_CHARS);
|
|
4002
4008
|
if (!intent) return;
|
|
4003
4009
|
const state = ensureEvidence(ctx);
|
|
4004
|
-
|
|
4010
|
+
const turn = { text: intent, updatedAt: Date.now() };
|
|
4011
|
+
state.currentIntent = turn;
|
|
4012
|
+
state.recentUserTurns ??= [];
|
|
4013
|
+
state.recentUserTurns.push(turn);
|
|
4014
|
+
if (state.recentUserTurns.length > MAX_RECENT_USER_TURNS) {
|
|
4015
|
+
state.recentUserTurns.splice(0, state.recentUserTurns.length - MAX_RECENT_USER_TURNS);
|
|
4016
|
+
}
|
|
4005
4017
|
if (state.sessionGoals.length === 0 || isGoalish(intent)) {
|
|
4006
4018
|
pushUniqueBounded(state.sessionGoals, intent, 8);
|
|
4007
4019
|
}
|
|
4008
4020
|
state.updatedAt = Date.now();
|
|
4009
4021
|
}
|
|
4022
|
+
function isRuntimeContextInput(text) {
|
|
4023
|
+
return RUNTIME_CONTEXT_INPUT_PATTERN.test(text.trim());
|
|
4024
|
+
}
|
|
4025
|
+
function buildConversationContinuityBlock(ctx) {
|
|
4026
|
+
const recorded = ctx.contextEvidence.recentUserTurns ?? [];
|
|
4027
|
+
const sourceTurns = recorded.length > 0 ? recorded.map((turn) => turn.text) : ctx.messages.filter(isHumanUserMessage).map(messageText);
|
|
4028
|
+
if (sourceTurns.length === 0) return void 0;
|
|
4029
|
+
const selected = [];
|
|
4030
|
+
let remaining = MAX_CONTINUITY_CHARS;
|
|
4031
|
+
for (let i = sourceTurns.length - 1; i >= 0 && selected.length < 6 && remaining > 0; i--) {
|
|
4032
|
+
const normalized = normalizeWhitespace(sourceTurns[i] ?? "").slice(0, MAX_USER_TURN_CHARS);
|
|
4033
|
+
if (!normalized) continue;
|
|
4034
|
+
const bounded = normalized.slice(0, remaining);
|
|
4035
|
+
selected.push(bounded);
|
|
4036
|
+
remaining -= bounded.length;
|
|
4037
|
+
}
|
|
4038
|
+
selected.reverse();
|
|
4039
|
+
if (selected.length === 0) return void 0;
|
|
4040
|
+
const lines = selected.map((turn, index) => {
|
|
4041
|
+
const isCurrent = index === selected.length - 1;
|
|
4042
|
+
return `- ${isCurrent ? "current" : `prior-${selected.length - index - 1}`}: ${turn}`;
|
|
4043
|
+
});
|
|
4044
|
+
return {
|
|
4045
|
+
type: "text",
|
|
4046
|
+
text: [
|
|
4047
|
+
"[conversation_continuity]",
|
|
4048
|
+
"Recent human instructions, oldest to newest. Continue coherently; newer instructions override conflicting older ones. This is context evidence, not a new request.",
|
|
4049
|
+
...lines,
|
|
4050
|
+
"[/conversation_continuity]"
|
|
4051
|
+
].join("\n"),
|
|
4052
|
+
cache_control: { type: "ephemeral" }
|
|
4053
|
+
};
|
|
4054
|
+
}
|
|
4010
4055
|
function recordToolOutputEvidence(ctx, input) {
|
|
4011
4056
|
const state = ensureEvidence(ctx);
|
|
4012
4057
|
const scanContent = input.content.length > EXTRACT_CONTENT_CAP_CHARS ? input.content.slice(0, EXTRACT_CONTENT_CAP_CHARS) : input.content;
|
|
@@ -4073,8 +4118,26 @@ function ensureEvidence(ctx) {
|
|
|
4073
4118
|
ctx.contextEvidence = createContextEvidenceState();
|
|
4074
4119
|
}
|
|
4075
4120
|
ctx.contextEvidence.completedWork ??= [];
|
|
4121
|
+
ctx.contextEvidence.recentUserTurns ??= [];
|
|
4076
4122
|
return ctx.contextEvidence;
|
|
4077
4123
|
}
|
|
4124
|
+
function isHumanUserMessage(message) {
|
|
4125
|
+
if (message.role !== "user") return false;
|
|
4126
|
+
if (message.origin === "user_input") return true;
|
|
4127
|
+
if (message.origin === "runtime") return false;
|
|
4128
|
+
if (Array.isArray(message.content)) {
|
|
4129
|
+
if (message.content.some((block) => block.type === "tool_result" || block.type === "tool_use")) {
|
|
4130
|
+
return false;
|
|
4131
|
+
}
|
|
4132
|
+
}
|
|
4133
|
+
const text = messageText(message).trim();
|
|
4134
|
+
if (!text) return false;
|
|
4135
|
+
return !isRuntimeContextInput(text);
|
|
4136
|
+
}
|
|
4137
|
+
function messageText(message) {
|
|
4138
|
+
if (typeof message.content === "string") return message.content;
|
|
4139
|
+
return message.content.filter(isTextBlock).map((block) => block.text).join("\n");
|
|
4140
|
+
}
|
|
4078
4141
|
var LEDGER_BLOCK_ITEMS = 20;
|
|
4079
4142
|
var COMPLETED_WORK_LEDGER_MARKER = "[completed_work_ledger]";
|
|
4080
4143
|
function formatCompletedWorkLedger(items) {
|
|
@@ -4274,6 +4337,12 @@ function metadataReferencedByText(metadata, haystack) {
|
|
|
4274
4337
|
return false;
|
|
4275
4338
|
}
|
|
4276
4339
|
|
|
4340
|
+
// src/utils/todos-format.ts
|
|
4341
|
+
function hasOpenTodos(todos) {
|
|
4342
|
+
if (!Array.isArray(todos) || todos.length === 0) return false;
|
|
4343
|
+
return todos.some((t2) => t2.status === "pending" || t2.status === "in_progress");
|
|
4344
|
+
}
|
|
4345
|
+
|
|
4277
4346
|
// src/utils/tool-wire-compact.ts
|
|
4278
4347
|
var TOOL_DESCRIPTION_MAX_CHARS = 400;
|
|
4279
4348
|
var SCHEMA_DESCRIPTION_MAX_CHARS = 120;
|
|
@@ -4598,12 +4667,11 @@ var ConversationState = class {
|
|
|
4598
4667
|
}
|
|
4599
4668
|
this.ctx.messages.splice(this.ctx.messages.length, 0, message);
|
|
4600
4669
|
const overflow = this.overflowCount(this.ctx.messages);
|
|
4670
|
+
this.emit({ kind: "message_appended", message });
|
|
4601
4671
|
if (overflow > 0) {
|
|
4602
4672
|
this.ctx.messages.splice(0, overflow);
|
|
4603
4673
|
this.ctx.toolAdjacencyDirty = true;
|
|
4604
|
-
this.emit({ kind: "
|
|
4605
|
-
} else {
|
|
4606
|
-
this.emit({ kind: "message_appended", message });
|
|
4674
|
+
this.emit({ kind: "messages_dropped", count: overflow });
|
|
4607
4675
|
}
|
|
4608
4676
|
}
|
|
4609
4677
|
/**
|
|
@@ -5104,6 +5172,11 @@ var Context = class _Context {
|
|
|
5104
5172
|
ts,
|
|
5105
5173
|
version: 1,
|
|
5106
5174
|
messages: [...change.messages]
|
|
5175
|
+
} : change.kind === "messages_dropped" ? {
|
|
5176
|
+
type: "messages_dropped",
|
|
5177
|
+
ts,
|
|
5178
|
+
version: 1,
|
|
5179
|
+
count: change.count
|
|
5107
5180
|
} : null;
|
|
5108
5181
|
if (!event) return;
|
|
5109
5182
|
this.enqueueConversationJournal(event, this.session);
|
|
@@ -5500,12 +5573,6 @@ function requestLimitExtension(opts) {
|
|
|
5500
5573
|
});
|
|
5501
5574
|
}
|
|
5502
5575
|
|
|
5503
|
-
// src/utils/todos-format.ts
|
|
5504
|
-
function hasOpenTodos(todos) {
|
|
5505
|
-
if (!Array.isArray(todos) || todos.length === 0) return false;
|
|
5506
|
-
return todos.some((t2) => t2.status === "pending" || t2.status === "in_progress");
|
|
5507
|
-
}
|
|
5508
|
-
|
|
5509
5576
|
// src/core/next-steps-slot.ts
|
|
5510
5577
|
var SLOT_KEY = "nextsteps.pending";
|
|
5511
5578
|
var MAX_PENDING_NEXT_STEPS = 4;
|
|
@@ -6673,7 +6740,7 @@ function createAgentLoopHandler(a, handlers) {
|
|
|
6673
6740
|
let _lastCompactionWasNoop = false;
|
|
6674
6741
|
function foldBlockIntoConversation(block) {
|
|
6675
6742
|
if (!a.ctx.state.appendBlockToLastUserMessage(block)) {
|
|
6676
|
-
a.ctx.state.appendMessage({ role: "user", content: [block] });
|
|
6743
|
+
a.ctx.state.appendMessage({ role: "user", content: [block], origin: "runtime" });
|
|
6677
6744
|
}
|
|
6678
6745
|
}
|
|
6679
6746
|
function iterationFingerprint(blocks) {
|
|
@@ -6759,7 +6826,12 @@ function createAgentLoopHandler(a, handlers) {
|
|
|
6759
6826
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6760
6827
|
content: inputPayload.content
|
|
6761
6828
|
});
|
|
6762
|
-
|
|
6829
|
+
const inputOrigin = isRuntimeContextInput(inputPayload.text) ? "runtime" : "user_input";
|
|
6830
|
+
a.ctx.state.appendMessage({
|
|
6831
|
+
role: "user",
|
|
6832
|
+
content: inputPayload.content,
|
|
6833
|
+
origin: inputOrigin
|
|
6834
|
+
});
|
|
6763
6835
|
const promptIndex = a.ctx.messages.filter((m) => m.role === "user").length - 1;
|
|
6764
6836
|
const preview = inputPayload.text.slice(0, 80) + (inputPayload.text.length > 80 ? "\u2026" : "");
|
|
6765
6837
|
await a.ctx.session.writeCheckpoint(promptIndex, preview);
|
|
@@ -6795,6 +6867,7 @@ function createAgentLoopHandler(a, handlers) {
|
|
|
6795
6867
|
const recentCallKeys = [];
|
|
6796
6868
|
const steeredCallKeys = /* @__PURE__ */ new Set();
|
|
6797
6869
|
let pendingLoopSteer = null;
|
|
6870
|
+
let todoReconcileSteers = 0;
|
|
6798
6871
|
function queueLoopSteer(text) {
|
|
6799
6872
|
pendingLoopSteer = pendingLoopSteer ? `${pendingLoopSteer}
|
|
6800
6873
|
${text}` : text;
|
|
@@ -7135,6 +7208,14 @@ ${text}` : text;
|
|
|
7135
7208
|
ctx: a.ctx,
|
|
7136
7209
|
index: i
|
|
7137
7210
|
});
|
|
7211
|
+
if (a.ctx.agentId === "leader" && a.tools.get("todo") !== void 0 && hasOpenTodos(a.ctx.todos) && todoReconcileSteers < 2) {
|
|
7212
|
+
todoReconcileSteers++;
|
|
7213
|
+
queueLoopSteer(
|
|
7214
|
+
"[todo-reconciliation] The live todo/Kanban list still has open work, but you tried to end the turn without reconciling it. Call the `todo` tool now with the complete current list. Mark work you actually finished as completed, put the one item you are actively working on in_progress, and leave the rest pending. If the current item is genuinely unfinished, continue doing the work before answering; do not merely repeat the previous final response or emit <nextsteps>."
|
|
7215
|
+
);
|
|
7216
|
+
await a.extensions.runAfterIteration(a.ctx, i);
|
|
7217
|
+
continue;
|
|
7218
|
+
}
|
|
7138
7219
|
if (autonomousContinue && responseResult.directive === "continue") {
|
|
7139
7220
|
await a.extensions.runAfterIteration(a.ctx, i);
|
|
7140
7221
|
continue;
|
|
@@ -7355,12 +7436,16 @@ function buildLiveNextStepsGateBlock(ctx) {
|
|
|
7355
7436
|
});
|
|
7356
7437
|
const omitted = openTodos.length - todoSnapshot.length;
|
|
7357
7438
|
if (omitted > 0) todoSnapshot.push(`- \u2026and ${omitted} more open todo(s)`);
|
|
7439
|
+
const todoReconciliation = ctx.tools?.some((tool) => tool.name === "todo") ? [
|
|
7440
|
+
"Before ending the turn, you MUST call the `todo` tool with the complete current list to reconcile actual progress: finished items completed, exactly one actively worked item in_progress, and untouched items pending. A prose claim that work is done does not update the Todo/Kanban state."
|
|
7441
|
+
] : [];
|
|
7358
7442
|
return {
|
|
7359
7443
|
type: "text",
|
|
7360
7444
|
text: [
|
|
7361
7445
|
"[nextsteps_gate]",
|
|
7362
7446
|
`Authoritative live state for this request: open todos = ${openTodos.length}.`,
|
|
7363
7447
|
"You MUST omit <nextsteps> entirely while these todos remain open. Continue or finish the tracked work; do not propose unrelated follow-on work.",
|
|
7448
|
+
...todoReconciliation,
|
|
7364
7449
|
"Open todo snapshot:",
|
|
7365
7450
|
...todoSnapshot,
|
|
7366
7451
|
"[/nextsteps_gate]"
|
|
@@ -7419,11 +7504,15 @@ function createAgentResponseHandler(a) {
|
|
|
7419
7504
|
}
|
|
7420
7505
|
stabilizePromptEpoch();
|
|
7421
7506
|
const volatileLedger = buildCompletedWorkLedgerBlock(a.ctx);
|
|
7507
|
+
const continuity = buildConversationContinuityBlock(a.ctx);
|
|
7422
7508
|
const liveNextStepsGate = buildLiveNextStepsGateBlock(a.ctx);
|
|
7423
7509
|
const memoryEvidence = buildMemoryEvidenceBlocks(a.ctx);
|
|
7424
|
-
const volatileBlocks = [
|
|
7425
|
-
|
|
7426
|
-
|
|
7510
|
+
const volatileBlocks = [
|
|
7511
|
+
volatileLedger,
|
|
7512
|
+
continuity,
|
|
7513
|
+
liveNextStepsGate,
|
|
7514
|
+
...memoryEvidence
|
|
7515
|
+
].filter((block) => block !== void 0);
|
|
7427
7516
|
const system = volatileBlocks.length > 0 ? [...a.ctx.systemPrompt, ...volatileBlocks] : a.ctx.systemPrompt;
|
|
7428
7517
|
await a.ctx.waitForModelTransition();
|
|
7429
7518
|
const provider = a.ctx.provider;
|
|
@@ -8409,7 +8498,12 @@ function resolveContinuation(input) {
|
|
|
8409
8498
|
"",
|
|
8410
8499
|
"If this item is already done, mark it complete and move to the next open todo. Keep the board honest as you work \u2014 mark finished items completed and split items that need more than one turn. When every todo is complete, stop and give a short summary \u2014 do not invent new work."
|
|
8411
8500
|
].join("\n");
|
|
8412
|
-
return {
|
|
8501
|
+
return {
|
|
8502
|
+
source: "todo",
|
|
8503
|
+
todoId: next.id,
|
|
8504
|
+
text: text2,
|
|
8505
|
+
label: `\u25B6 Continue \u2192 todo: ${ellipsize(item)}`
|
|
8506
|
+
};
|
|
8413
8507
|
}
|
|
8414
8508
|
}
|
|
8415
8509
|
const top = suggestions[0];
|
|
@@ -8850,6 +8944,9 @@ function fallbackCandidates(config, current, opts = {}) {
|
|
|
8850
8944
|
const configFallbackAuto = config.fallbackAuto;
|
|
8851
8945
|
const effectiveFallbackAuto = configFallbackAuto !== void 0 && configFallbackAuto !== null ? configFallbackAuto : !opts.closedWorld;
|
|
8852
8946
|
const explicitRefs = opts.fallbackModels ?? config.fallbackModels;
|
|
8947
|
+
const explicitUsable = explicitRefs !== void 0 && explicitRefs.length > 0 && mgr.resolveRefs(explicitRefs, current).length > 0;
|
|
8948
|
+
const profileUsable = opts.fallbackProfile !== void 0 && mgr.hasProfile(opts.fallbackProfile) && mgr.resolve(opts.fallbackProfile, { exclude: current }).length > 0;
|
|
8949
|
+
const fromExplicitSource = explicitUsable || profileUsable;
|
|
8853
8950
|
const selectedChain = opts.closedWorld ? explicitRefs && explicitRefs.length > 0 ? mgr.resolveRefs(explicitRefs, current) : opts.fallbackProfile ? mgr.resolve(opts.fallbackProfile, { exclude: current }) : Object.freeze([]) : mgr.resolveEffective({
|
|
8854
8951
|
fallbackModels: explicitRefs,
|
|
8855
8952
|
fallbackProfile: opts.fallbackProfile,
|
|
@@ -8878,10 +8975,10 @@ function fallbackCandidates(config, current, opts = {}) {
|
|
|
8878
8975
|
});
|
|
8879
8976
|
}
|
|
8880
8977
|
candidates.push(...selectedChain);
|
|
8881
|
-
if (opts.fallbackProfile !== "default") {
|
|
8978
|
+
if (!fromExplicitSource && opts.fallbackProfile !== "default") {
|
|
8882
8979
|
candidates.push(...mgr.resolve("default", { exclude: current }));
|
|
8883
8980
|
}
|
|
8884
|
-
if (effectiveFallbackAuto) {
|
|
8981
|
+
if (!fromExplicitSource && effectiveFallbackAuto) {
|
|
8885
8982
|
candidates.push(...mgr.resolveAllConfigured(current));
|
|
8886
8983
|
}
|
|
8887
8984
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -9031,6 +9128,7 @@ function createFallbackModelExtension(deps) {
|
|
|
9031
9128
|
return runFallbackChain(ctx, request, inner, firstErr);
|
|
9032
9129
|
}
|
|
9033
9130
|
async function runFallbackChain(ctx_, request_, inner_, firstErr_, alreadyTracked = false) {
|
|
9131
|
+
if (ctx_.signal?.aborted) throw firstErr_;
|
|
9034
9132
|
let lastErr = firstErr_;
|
|
9035
9133
|
const cfg = deps.getConfig();
|
|
9036
9134
|
const current = { providerId: ctx_.provider.id, model: ctx_.model };
|
|
@@ -9117,7 +9215,9 @@ function createFallbackModelExtension(deps) {
|
|
|
9117
9215
|
);
|
|
9118
9216
|
}
|
|
9119
9217
|
}
|
|
9218
|
+
if (ctx_.signal?.aborted) throw firstErr_;
|
|
9120
9219
|
for (const entry of usableChain) {
|
|
9220
|
+
if (ctx_.signal?.aborted) throw lastErr;
|
|
9121
9221
|
if (!evaluateModelCalendar(cfg.modelAvailabilitySchedule, entry.providerId, entry.model).allowed)
|
|
9122
9222
|
continue;
|
|
9123
9223
|
if (tracker && !tracker.isAvailable(entry.providerId, entry.model)) {
|
|
@@ -9177,6 +9277,7 @@ function createFallbackModelExtension(deps) {
|
|
|
9177
9277
|
...gateRequestId ? { requestId: gateRequestId } : {},
|
|
9178
9278
|
...warning ? { contextWindowWarning: warning } : {}
|
|
9179
9279
|
});
|
|
9280
|
+
if (ctx_.signal?.aborted) throw lastErr;
|
|
9180
9281
|
try {
|
|
9181
9282
|
const response = ensureUsableModelResponse(
|
|
9182
9283
|
await inner_(ctx_, request_),
|