@openrouter/agent 0.7.2 → 0.9.0
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 +728 -19
- package/esm/index.d.ts +24 -6
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +20 -5
- package/esm/index.js.map +1 -1
- package/esm/inner-loop/call-model.d.ts +8 -5
- package/esm/inner-loop/call-model.d.ts.map +1 -1
- package/esm/inner-loop/call-model.js +49 -40
- package/esm/inner-loop/call-model.js.map +1 -1
- package/esm/inner-loop/resume-tool-results.d.ts +128 -0
- package/esm/inner-loop/resume-tool-results.d.ts.map +1 -0
- package/esm/inner-loop/resume-tool-results.js +244 -0
- package/esm/inner-loop/resume-tool-results.js.map +1 -0
- package/esm/lib/agent-tool.d.ts +92 -0
- package/esm/lib/agent-tool.d.ts.map +1 -0
- package/esm/lib/agent-tool.js +211 -0
- package/esm/lib/agent-tool.js.map +1 -0
- package/esm/lib/async-params.d.ts +107 -6
- package/esm/lib/async-params.d.ts.map +1 -1
- package/esm/lib/async-params.js +8 -1
- package/esm/lib/async-params.js.map +1 -1
- package/esm/lib/async-tool-registry.d.ts +134 -0
- package/esm/lib/async-tool-registry.d.ts.map +1 -0
- package/esm/lib/async-tool-registry.js +352 -0
- package/esm/lib/async-tool-registry.js.map +1 -0
- package/esm/lib/async-tools.d.ts +23 -0
- package/esm/lib/async-tools.d.ts.map +1 -0
- package/esm/lib/async-tools.js +19 -0
- package/esm/lib/async-tools.js.map +1 -0
- package/esm/lib/conversation-state.d.ts +45 -1
- package/esm/lib/conversation-state.d.ts.map +1 -1
- package/esm/lib/conversation-state.js +119 -0
- package/esm/lib/conversation-state.js.map +1 -1
- package/esm/lib/doom-loop.d.ts +533 -0
- package/esm/lib/doom-loop.d.ts.map +1 -0
- package/esm/lib/doom-loop.js +1221 -0
- package/esm/lib/doom-loop.js.map +1 -0
- package/esm/lib/hooks-emit.d.ts +50 -0
- package/esm/lib/hooks-emit.d.ts.map +1 -0
- package/esm/lib/hooks-emit.js +307 -0
- package/esm/lib/hooks-emit.js.map +1 -0
- package/esm/lib/hooks-manager.d.ts +141 -0
- package/esm/lib/hooks-manager.d.ts.map +1 -0
- package/esm/lib/hooks-manager.js +282 -0
- package/esm/lib/hooks-manager.js.map +1 -0
- package/esm/lib/hooks-matchers.d.ts +12 -0
- package/esm/lib/hooks-matchers.d.ts.map +1 -0
- package/esm/lib/hooks-matchers.js +26 -0
- package/esm/lib/hooks-matchers.js.map +1 -0
- package/esm/lib/hooks-resolve.d.ts +17 -0
- package/esm/lib/hooks-resolve.d.ts.map +1 -0
- package/esm/lib/hooks-resolve.js +42 -0
- package/esm/lib/hooks-resolve.js.map +1 -0
- package/esm/lib/hooks-schemas.d.ts +221 -0
- package/esm/lib/hooks-schemas.d.ts.map +1 -0
- package/esm/lib/hooks-schemas.js +238 -0
- package/esm/lib/hooks-schemas.js.map +1 -0
- package/esm/lib/hooks-types.d.ts +178 -0
- package/esm/lib/hooks-types.d.ts.map +1 -0
- package/esm/lib/hooks-types.js +45 -0
- package/esm/lib/hooks-types.js.map +1 -0
- package/esm/lib/model-result.d.ts +848 -12
- package/esm/lib/model-result.d.ts.map +1 -1
- package/esm/lib/model-result.js +4055 -410
- package/esm/lib/model-result.js.map +1 -1
- package/esm/lib/reusable-stream.d.ts +15 -0
- package/esm/lib/reusable-stream.d.ts.map +1 -1
- package/esm/lib/reusable-stream.js +25 -0
- package/esm/lib/reusable-stream.js.map +1 -1
- package/esm/lib/stream-transformers.d.ts +20 -0
- package/esm/lib/stream-transformers.d.ts.map +1 -1
- package/esm/lib/stream-transformers.js +45 -0
- package/esm/lib/stream-transformers.js.map +1 -1
- package/esm/lib/tool-check.d.ts +76 -0
- package/esm/lib/tool-check.d.ts.map +1 -0
- package/esm/lib/tool-check.js +241 -0
- package/esm/lib/tool-check.js.map +1 -0
- package/esm/lib/tool-concurrency.d.ts +42 -0
- package/esm/lib/tool-concurrency.d.ts.map +1 -0
- package/esm/lib/tool-concurrency.js +80 -0
- package/esm/lib/tool-concurrency.js.map +1 -0
- package/esm/lib/tool-context.d.ts +45 -1
- package/esm/lib/tool-context.d.ts.map +1 -1
- package/esm/lib/tool-context.js +60 -1
- package/esm/lib/tool-context.js.map +1 -1
- package/esm/lib/tool-executor.d.ts +52 -9
- package/esm/lib/tool-executor.d.ts.map +1 -1
- package/esm/lib/tool-executor.js +263 -21
- package/esm/lib/tool-executor.js.map +1 -1
- package/esm/lib/tool-orchestrator.d.ts.map +1 -1
- package/esm/lib/tool-orchestrator.js +87 -47
- package/esm/lib/tool-orchestrator.js.map +1 -1
- package/esm/lib/tool-task.d.ts +157 -0
- package/esm/lib/tool-task.d.ts.map +1 -0
- package/esm/lib/tool-task.js +206 -0
- package/esm/lib/tool-task.js.map +1 -0
- package/esm/lib/tool-types.d.ts +609 -58
- package/esm/lib/tool-types.d.ts.map +1 -1
- package/esm/lib/tool-types.js +72 -10
- package/esm/lib/tool-types.js.map +1 -1
- package/esm/lib/tool.d.ts +217 -25
- package/esm/lib/tool.d.ts.map +1 -1
- package/esm/lib/tool.js +210 -1
- package/esm/lib/tool.js.map +1 -1
- package/package.json +35 -3
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doom-loop detection for the tool-execution loop.
|
|
3
|
+
*
|
|
4
|
+
* A "doom loop" is a run that stops making progress while continuing to spend:
|
|
5
|
+
* the model re-issues the same tool call with identical arguments (including
|
|
6
|
+
* repeated *empty* calls and repeated unparseable calls), or emits the same
|
|
7
|
+
* text tokens over and over. This module provides the deterministic detection
|
|
8
|
+
* primitives; `ModelResult` wires them into the loop behind the `doomLoop`
|
|
9
|
+
* option on `callModel`.
|
|
10
|
+
*
|
|
11
|
+
* Design principles:
|
|
12
|
+
*
|
|
13
|
+
* - **Deterministic.** Every verdict is a pure function of the recorded
|
|
14
|
+
* sequence of tool calls / assistant texts. The same scripted transcript
|
|
15
|
+
* produces the same verdicts at the same indices — no wall clocks, no
|
|
16
|
+
* randomness — so the feature is testable without a live model and
|
|
17
|
+
* portable across SDK ports via shared test vectors.
|
|
18
|
+
* - **Cross-port fingerprints.** Key material is canonicalized per RFC 8785
|
|
19
|
+
* (JCS) and hashed with SHA-256 over the UTF-8 bytes. Ports (Python/Go)
|
|
20
|
+
* MUST use a JCS implementation (e.g. pip `jcs`,
|
|
21
|
+
* `cyberphone/json-canonicalization`), not their stdlib JSON serializer —
|
|
22
|
+
* the shared vector file `tests/vectors/doom-loop-fingerprints.json` is
|
|
23
|
+
* the conformance contract.
|
|
24
|
+
* - **Tool-declared identity.** A tool opts into precise loop identity via
|
|
25
|
+
* `loopKey` on its definition: a function computing key material
|
|
26
|
+
* (e.g. `({ command, cwd }) => ({ command, cwd })`), a field-name array
|
|
27
|
+
* (`['command', 'cwd']` — data, not code, so it can ride MCP tool caches
|
|
28
|
+
* and the `_meta['openrouter/loopKey']` wire field), or `false` to exempt
|
|
29
|
+
* the tool. Tools declare *what identifies a call*; this module owns
|
|
30
|
+
* canonicalization and hashing so fingerprints are uniform across tools
|
|
31
|
+
* and ports.
|
|
32
|
+
* - **Round-scoped streaks.** A streak measures the model *re-issuing a call
|
|
33
|
+
* after seeing its result*, which requires a model round trip. N identical
|
|
34
|
+
* calls fanned out in ONE round count once; the duplicates share that
|
|
35
|
+
* round's decision. A round's identity for one tool is the *set* of
|
|
36
|
+
* fingerprints it was called with, so a fan-out of distinct arguments
|
|
37
|
+
* (`read(a), read(b), read(c)`) reissued verbatim accumulates, and every
|
|
38
|
+
* call in the round reports the round's streak. Ports must declare a
|
|
39
|
+
* round's complete set before scoring any of its calls (see
|
|
40
|
+
* `declareRound`): scoring a set as it accumulates makes a superset round
|
|
41
|
+
* transiently match the previous one, which both fires on real progress
|
|
42
|
+
* and makes the outcome depend on emission order.
|
|
43
|
+
* - **Graduated response.** Detection feeds a configurable action ladder
|
|
44
|
+
* (observe → steer → block → stop) rather than killing the run outright.
|
|
45
|
+
* - **Never the cause of failure.** Detection may only affect a run through
|
|
46
|
+
* its defined actions. Any internal error (unhashable key material,
|
|
47
|
+
* throwing `loopKey`, corrupt persisted state) degrades to a fallback
|
|
48
|
+
* identity or skips detection for that call — it never rejects the call
|
|
49
|
+
* or crashes the run.
|
|
50
|
+
*/
|
|
51
|
+
/**
|
|
52
|
+
* Escalation actions, weakest to strongest:
|
|
53
|
+
*
|
|
54
|
+
* - `observe` — emit the `DoomLoopDetected` hook only.
|
|
55
|
+
* - `steer` — inject a corrective user message before the next model turn
|
|
56
|
+
* (same mechanism as the Stop hook's `appendPrompt`); the call still runs.
|
|
57
|
+
* - `escalate` — recover by throwing more intelligence at the NEXT turn:
|
|
58
|
+
* temporarily swap to a stronger model and/or force an `openrouter:advisor`
|
|
59
|
+
* consult, per the `escalation` config. One-turn overrides; the run
|
|
60
|
+
* returns to its configured model afterward. Bounded by
|
|
61
|
+
* `escalation.maxEscalations`; exhausted or unconfigured escalations fall
|
|
62
|
+
* through to the weaker rungs. The call still runs.
|
|
63
|
+
* - `block` — refuse the tool call and synthesize an error
|
|
64
|
+
* `function_call_output` (same shape as a PreToolUse block); the error text
|
|
65
|
+
* is itself steering, delivered where the model looks.
|
|
66
|
+
* - `stop` — halt the run before the next model request
|
|
67
|
+
* (`SessionEnd.reason: 'doom_loop'`).
|
|
68
|
+
*/
|
|
69
|
+
export type DoomLoopAction = 'observe' | 'steer' | 'escalate' | 'block' | 'stop';
|
|
70
|
+
/** Which detector produced a verdict. */
|
|
71
|
+
export type DoomLoopDetectorKind = 'tool-fingerprint' | 'server-tool-fingerprint' | 'text-repetition' | 'text-streak';
|
|
72
|
+
/**
|
|
73
|
+
* A doom-loop detection event.
|
|
74
|
+
*
|
|
75
|
+
* `streak` is the repetition count that crossed a ladder threshold: for
|
|
76
|
+
* fingerprint detectors the number of consecutive rounds in which that tool
|
|
77
|
+
* was called with the same fingerprint *set* (so a repeated fan-out counts,
|
|
78
|
+
* and every call in the round reports the round's count); for
|
|
79
|
+
* `text-repetition` the number of consecutive repeats of a token block within
|
|
80
|
+
* one response; for `text-streak` the number of consecutive steps with
|
|
81
|
+
* identical assistant text.
|
|
82
|
+
*/
|
|
83
|
+
export interface DoomLoopVerdict {
|
|
84
|
+
detector: DoomLoopDetectorKind;
|
|
85
|
+
action: DoomLoopAction;
|
|
86
|
+
streak: number;
|
|
87
|
+
/** Deterministic fingerprint of the repeated unit (call identity or text). */
|
|
88
|
+
fingerprint: string;
|
|
89
|
+
/** Present for fingerprint verdicts. */
|
|
90
|
+
toolName?: string;
|
|
91
|
+
/** Human/model-readable explanation; used verbatim for block outputs and steer messages. */
|
|
92
|
+
message: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Result of recording one tool call with the monitor.
|
|
96
|
+
*
|
|
97
|
+
* `duplicateInRound` is true when the same `(toolName, fingerprint)` was
|
|
98
|
+
* already recorded in this round — the streak did NOT increment and the
|
|
99
|
+
* caller should reuse the decision it applied for the first occurrence
|
|
100
|
+
* rather than re-emitting hooks.
|
|
101
|
+
*/
|
|
102
|
+
export interface DoomLoopCallRecord {
|
|
103
|
+
fingerprint: string;
|
|
104
|
+
streak: number;
|
|
105
|
+
duplicateInRound: boolean;
|
|
106
|
+
verdict?: DoomLoopVerdict;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Streak thresholds for each action. A threshold of `false` disables that
|
|
110
|
+
* rung. When several rungs are crossed the strongest wins
|
|
111
|
+
* (stop > block > escalate > steer > observe). Thresholds compare with
|
|
112
|
+
* `>=`, so a verdict fires on *every* record at or past a rung — escalating
|
|
113
|
+
* as the streak grows.
|
|
114
|
+
*/
|
|
115
|
+
export interface DoomLoopLadder {
|
|
116
|
+
observe?: number | false;
|
|
117
|
+
steer?: number | false;
|
|
118
|
+
escalate?: number | false;
|
|
119
|
+
block?: number | false;
|
|
120
|
+
stop?: number | false;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Recovery configuration for the `escalate` ladder action: what "throw more
|
|
124
|
+
* intelligence at the stuck turn" means for this run. At least one of
|
|
125
|
+
* `model`/`advisor` must be set for the rung to do anything (enabling the
|
|
126
|
+
* rung without a config warns and the rung is skipped).
|
|
127
|
+
*/
|
|
128
|
+
export interface DoomLoopEscalationConfig {
|
|
129
|
+
/**
|
|
130
|
+
* Model slug to run the NEXT turn on (e.g. a frontier model), replacing
|
|
131
|
+
* the request's configured model for one request only. The following
|
|
132
|
+
* turn reverts automatically.
|
|
133
|
+
*/
|
|
134
|
+
model?: string;
|
|
135
|
+
/**
|
|
136
|
+
* Force an `openrouter:advisor` consult on the next turn: the advisor
|
|
137
|
+
* server tool is added to the request with these parameters and
|
|
138
|
+
* `toolChoice` pinned to it, so the stuck model must ask for guidance
|
|
139
|
+
* before doing anything else. The advisor's transcript context defaults
|
|
140
|
+
* to on (`forwardTranscript: true`) so it sees the loop it is diagnosing.
|
|
141
|
+
*
|
|
142
|
+
* `true` uses defaults (advisor model chosen by the platform, transcript
|
|
143
|
+
* forwarded, instructions describing the detected loop); an object is
|
|
144
|
+
* passed through as the advisor tool's `parameters` (missing
|
|
145
|
+
* `instructions`/`forwardTranscript` filled with those defaults).
|
|
146
|
+
*/
|
|
147
|
+
advisor?: boolean | Record<string, unknown>;
|
|
148
|
+
/**
|
|
149
|
+
* Escalations are real spend on a run already suspected of wasting it:
|
|
150
|
+
* cap how many times this run may escalate. When exhausted, `escalate`
|
|
151
|
+
* verdicts fall through to the weaker rungs (steer/observe). Default 2.
|
|
152
|
+
*/
|
|
153
|
+
maxEscalations?: number;
|
|
154
|
+
}
|
|
155
|
+
/** Options for within-response text-repetition detection. */
|
|
156
|
+
export interface DoomLoopTextOptions {
|
|
157
|
+
/** Master switch for both text detectors. Default true. */
|
|
158
|
+
enabled?: boolean;
|
|
159
|
+
/** Longest repeating token block to search for. Default 16. */
|
|
160
|
+
maxPeriodTokens?: number;
|
|
161
|
+
/** Minimum consecutive repeats of a block to count as repetition. Default 4. */
|
|
162
|
+
minRepeats?: number;
|
|
163
|
+
/** Minimum total tokens covered by the repetition. Default 12. */
|
|
164
|
+
minCoveredTokens?: number;
|
|
165
|
+
/** Only the trailing N tokens of a response are scanned. Default 400. */
|
|
166
|
+
maxWindowTokens?: number;
|
|
167
|
+
}
|
|
168
|
+
/** Configuration for doom-loop detection. `doomLoop: true` uses all defaults. */
|
|
169
|
+
export interface DoomLoopConfig {
|
|
170
|
+
ladder?: DoomLoopLadder;
|
|
171
|
+
/** Text-loop detection. `false` disables; an object tunes it. Default on. */
|
|
172
|
+
text?: boolean | DoomLoopTextOptions;
|
|
173
|
+
/** Recovery behavior for the `escalate` rung. Off unless configured. */
|
|
174
|
+
escalation?: DoomLoopEscalationConfig;
|
|
175
|
+
}
|
|
176
|
+
/** The `doomLoop` option on `callModel`: `true` for defaults, or a config object. */
|
|
177
|
+
export type DoomLoopOption = boolean | DoomLoopConfig;
|
|
178
|
+
/** Consecutive-repetition counter for one identity (a tool, or step text). */
|
|
179
|
+
export interface DoomLoopStreak {
|
|
180
|
+
fingerprint: string;
|
|
181
|
+
streak: number;
|
|
182
|
+
/**
|
|
183
|
+
* The full fingerprint set of the tool's last round, present only when that
|
|
184
|
+
* round had more than one distinct call. `fingerprint`+`streak` alone cannot
|
|
185
|
+
* say WHICH set earned a count, so without this a fan-out streak either
|
|
186
|
+
* attached to one arbitrary member (refusing a lesser resumed call on first
|
|
187
|
+
* appearance) or had to be discarded at every save — losing block-level
|
|
188
|
+
* evidence across approval pauses and re-baselining on every per-turn
|
|
189
|
+
* resume. Absent for single-call rounds and in pre-existing blobs, where
|
|
190
|
+
* `fingerprint` fully describes the round. Never present on text streaks.
|
|
191
|
+
*/
|
|
192
|
+
roundFingerprints?: readonly string[];
|
|
193
|
+
/**
|
|
194
|
+
* Per-call streaks for the tool's last round: fingerprint → number of
|
|
195
|
+
* consecutive rounds that exact call has been issued in. This is the
|
|
196
|
+
* evidence for the PER-CALL detector, which catches a call repeating inside
|
|
197
|
+
* rounds whose other members keep changing (`[a,b]`, `[a,c]`, `[a,d]` — the
|
|
198
|
+
* round set differs every time, but `a` is a 3-peat). Persisted so a repeat
|
|
199
|
+
* spanning a save/resume boundary (approval pause, per-turn resume) keeps
|
|
200
|
+
* counting. Bounded by the width of one round; absent in pre-existing
|
|
201
|
+
* blobs, where per-call evidence simply restarts. Never present on text
|
|
202
|
+
* streaks.
|
|
203
|
+
*/
|
|
204
|
+
callStreaks?: Record<string, number>;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Plain-JSON detector state, persisted inside `ConversationState.doomLoop`
|
|
208
|
+
* so loop memory survives serialize → resume: a resumed doom loop is still
|
|
209
|
+
* a doom loop (provided the resuming call passes `doomLoop` again).
|
|
210
|
+
*/
|
|
211
|
+
export interface DoomLoopSerializedState {
|
|
212
|
+
/** Per-tool streaks keyed by tool name. Interleaved calls to other tools do not reset a tool's streak. */
|
|
213
|
+
tools: Record<string, DoomLoopStreak>;
|
|
214
|
+
/** Cross-step assistant-text streak. */
|
|
215
|
+
text?: DoomLoopStreak;
|
|
216
|
+
/**
|
|
217
|
+
* The verdict that condemned this run, when a `stop` action armed. Kept
|
|
218
|
+
* across decision-only resumes (`approveToolCalls`/`rejectToolCalls`) so a
|
|
219
|
+
* condemned run stays halted; cleared by a fresh conversational turn
|
|
220
|
+
* (operator intervention = new information). Streaks are kept either way.
|
|
221
|
+
*/
|
|
222
|
+
stopVerdict?: DoomLoopVerdict;
|
|
223
|
+
/**
|
|
224
|
+
* Steer guidance queued but not yet injected when the run paused. Flushed
|
|
225
|
+
* into the conversation on resume.
|
|
226
|
+
*/
|
|
227
|
+
pendingSteer?: string[];
|
|
228
|
+
/**
|
|
229
|
+
* How many escalation recoveries this conversation has consumed, counted
|
|
230
|
+
* against `escalation.maxEscalations`. Persisted so a resumed run cannot
|
|
231
|
+
* reset its escalation budget by resuming.
|
|
232
|
+
*/
|
|
233
|
+
escalationsUsed?: number;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* The result of resolving a tool's `loopKey` declaration against one call's
|
|
237
|
+
* validated arguments. See {@link resolveLoopKeyMaterial}.
|
|
238
|
+
*/
|
|
239
|
+
export type LoopKeyResolution = {
|
|
240
|
+
kind: 'exempt';
|
|
241
|
+
} | {
|
|
242
|
+
kind: 'key';
|
|
243
|
+
keyMaterial: unknown;
|
|
244
|
+
} | {
|
|
245
|
+
kind: 'fallback';
|
|
246
|
+
keyMaterial: unknown;
|
|
247
|
+
warning: string;
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* Default ladder: observe at 2 consecutive identical rounds, block at 3,
|
|
251
|
+
* stop at 6. Steer is off by default (blocking already delivers feedback in
|
|
252
|
+
* the tool output, where the model looks first).
|
|
253
|
+
*/
|
|
254
|
+
export declare const DEFAULT_DOOM_LOOP_LADDER: Readonly<Required<DoomLoopLadder>>;
|
|
255
|
+
/** Default escalation budget when the rung is enabled without a cap. */
|
|
256
|
+
export declare const DEFAULT_MAX_ESCALATIONS = 2;
|
|
257
|
+
/** Escalation config with the budget resolved. */
|
|
258
|
+
export interface ResolvedEscalationConfig {
|
|
259
|
+
model?: string;
|
|
260
|
+
advisor?: boolean | Record<string, unknown>;
|
|
261
|
+
maxEscalations: number;
|
|
262
|
+
}
|
|
263
|
+
/** Fully-resolved config used by the monitor. */
|
|
264
|
+
export interface ResolvedDoomLoopConfig {
|
|
265
|
+
ladder: Required<DoomLoopLadder>;
|
|
266
|
+
text: Required<DoomLoopTextOptions>;
|
|
267
|
+
escalation: ResolvedEscalationConfig | null;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Normalize the `doomLoop` option. `undefined` / `false` → null (detection
|
|
271
|
+
* off — the SDK's default posture: explicit control over implicit magic).
|
|
272
|
+
*
|
|
273
|
+
* Overloaded so the direct-construction pattern compiles without a null
|
|
274
|
+
* check: `true` or a config object always yields a resolved config, so
|
|
275
|
+
* `new DoomLoopMonitor(resolveDoomLoopOption(true))` is well-typed. Only the
|
|
276
|
+
* engine's pass-through of a caller's raw option can produce `null`.
|
|
277
|
+
*/
|
|
278
|
+
export declare function resolveDoomLoopOption(option: DoomLoopConfig | true): ResolvedDoomLoopConfig;
|
|
279
|
+
export declare function resolveDoomLoopOption(option: DoomLoopOption | undefined): ResolvedDoomLoopConfig | null;
|
|
280
|
+
/**
|
|
281
|
+
* Resolve a tool's `loopKey` declaration (function, `false`, or absent)
|
|
282
|
+
* against one call's validated arguments.
|
|
283
|
+
*
|
|
284
|
+
* - absent (`undefined` declaration) → the full arguments object.
|
|
285
|
+
* - `false` → the tool is statically exempt.
|
|
286
|
+
* - function → called with the arguments, like every other tool hook.
|
|
287
|
+
* `null` exempts THIS call; `undefined` falls back to the full arguments
|
|
288
|
+
* (with a warning — a bare `return;` is almost always a bug, and treating
|
|
289
|
+
* it as key material would collide every call of the tool onto one
|
|
290
|
+
* fingerprint); a throw falls back to the full arguments (detection must
|
|
291
|
+
* never take down a run).
|
|
292
|
+
*/
|
|
293
|
+
export declare function resolveLoopKeyMaterial(loopKey: unknown, args: Record<string, unknown>): LoopKeyResolution;
|
|
294
|
+
/**
|
|
295
|
+
* Maximum nesting depth accepted by {@link canonicalizeKeyMaterial}. Real
|
|
296
|
+
* tool arguments come from parsed JSON and stay shallow; anything deeper is
|
|
297
|
+
* hostile or buggy key material and must fail fast (with a catchable error)
|
|
298
|
+
* instead of overflowing the stack.
|
|
299
|
+
*/
|
|
300
|
+
export declare const MAX_CANONICALIZE_DEPTH = 64;
|
|
301
|
+
/**
|
|
302
|
+
* RFC 8785 (JCS) canonical JSON: object keys sorted by UTF-16 code units
|
|
303
|
+
* (recursively), arrays in order, strings and finite numbers serialized per
|
|
304
|
+
* ECMAScript `JSON.stringify` (which IS the JCS serialization — e.g. `-0`
|
|
305
|
+
* canonicalizes to `0`, `1e21` to `1e+21`, lone surrogates to `\udXXX`
|
|
306
|
+
* escapes). Insensitive to key insertion order, so `{a:1,b:2}` and
|
|
307
|
+
* `{b:2,a:1}` canonicalize identically.
|
|
308
|
+
*
|
|
309
|
+
* This is the cross-port contract: Python and Go ports must produce
|
|
310
|
+
* byte-identical canonical strings for the same key material, which means
|
|
311
|
+
* they MUST use an RFC 8785 implementation (pip `jcs`,
|
|
312
|
+
* `cyberphone/json-canonicalization`), not their stdlib JSON serializer
|
|
313
|
+
* (Python's `json.dumps(-0.0)` is `-0.0`, which is NOT JCS).
|
|
314
|
+
*
|
|
315
|
+
* JSON-data-model semantics for JS-only values:
|
|
316
|
+
* - `undefined` / function / symbol object entries are dropped (as
|
|
317
|
+
* `JSON.stringify` does); in arrays they serialize as `null`.
|
|
318
|
+
*
|
|
319
|
+
* @throws Error on values RFC 8785 cannot represent — non-finite numbers,
|
|
320
|
+
* bigint — plus circular references and nesting deeper than
|
|
321
|
+
* {@link MAX_CANONICALIZE_DEPTH}. Real tool arguments (parsed JSON) can
|
|
322
|
+
* never trigger these; only computed `loopKey` material can, and the engine
|
|
323
|
+
* catches the error and falls back to the full-arguments identity.
|
|
324
|
+
*/
|
|
325
|
+
export declare function canonicalizeKeyMaterial(value: unknown): string;
|
|
326
|
+
/**
|
|
327
|
+
* Fingerprint arbitrary key material: `sha256(utf8(jcs(keyMaterial)))`,
|
|
328
|
+
* lowercase hex (64 chars).
|
|
329
|
+
*/
|
|
330
|
+
export declare function fingerprintKeyMaterial(keyMaterial: unknown): Promise<string>;
|
|
331
|
+
/**
|
|
332
|
+
* Fingerprint a tool call: `sha256(utf8(toolName + '\n' + jcs(keyMaterial)))`,
|
|
333
|
+
* lowercase hex. The tool name participates so `search({q})` and
|
|
334
|
+
* `fetch({q})` with equal arguments never share a fingerprint. This exact
|
|
335
|
+
* construction is the cross-port contract — see
|
|
336
|
+
* `tests/vectors/doom-loop-fingerprints.json`.
|
|
337
|
+
*/
|
|
338
|
+
export declare function fingerprintToolCall(toolName: string, keyMaterial: unknown): Promise<string>;
|
|
339
|
+
/** A detected repeating token block at the tail of a response. */
|
|
340
|
+
export interface TextRepetitionResult {
|
|
341
|
+
/** Consecutive repeats of the block (feeds the ladder as the streak). */
|
|
342
|
+
repeats: number;
|
|
343
|
+
/** Block length in whitespace-delimited tokens. */
|
|
344
|
+
periodTokens: number;
|
|
345
|
+
/** repeats × periodTokens. */
|
|
346
|
+
coveredTokens: number;
|
|
347
|
+
/** The repeating block itself. */
|
|
348
|
+
sample: string;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Detect a period-p token block repeating at the *tail* of `text` — the
|
|
352
|
+
* canonical shape of an in-response token doom loop ("I am stuck. I am
|
|
353
|
+
* stuck. I am stuck. …"). Pure and deterministic: whitespace tokenization,
|
|
354
|
+
* suffix comparison, no heuristics beyond the thresholds.
|
|
355
|
+
*
|
|
356
|
+
* Only the trailing region of the text is examined: a fixed character
|
|
357
|
+
* budget (64 chars per window token) is sliced off the tail before
|
|
358
|
+
* tokenization, so multi-megabyte responses do not pay a full-text token
|
|
359
|
+
* split. The budget is part of the deterministic contract (same text ⇒
|
|
360
|
+
* same slice ⇒ same result).
|
|
361
|
+
*
|
|
362
|
+
* Ties on covered tokens prefer the smallest period (the most repeats), so
|
|
363
|
+
* "no no no no no no" reports p=1 × 6, not p=2 × 3 — the repeat count is
|
|
364
|
+
* what feeds the ladder.
|
|
365
|
+
*
|
|
366
|
+
* Returns null when no block meets `minRepeats` and `minCoveredTokens`
|
|
367
|
+
* within `maxPeriodTokens` / `maxWindowTokens`.
|
|
368
|
+
*
|
|
369
|
+
* KNOWN LIMIT: token blocks must repeat *exactly*. Paraphrased loops ("I am
|
|
370
|
+
* stuck" / "I appear to be stuck" / …) do not trip this detector.
|
|
371
|
+
*/
|
|
372
|
+
export declare function detectTextRepetition(text: string, options?: Partial<DoomLoopTextOptions>): TextRepetitionResult | null;
|
|
373
|
+
/**
|
|
374
|
+
* Map a streak onto the strongest crossed ladder rung.
|
|
375
|
+
*
|
|
376
|
+
* `allowBlock: false` is used for text and server-tool verdicts: the tokens
|
|
377
|
+
* are already emitted / the tool already ran server-side, so there is
|
|
378
|
+
* nothing to block — a block-level streak falls through to escalate/steer
|
|
379
|
+
* (when enabled) or observe, while stop still stops.
|
|
380
|
+
*
|
|
381
|
+
* `allowEscalate: false` disables the escalate rung for this resolution —
|
|
382
|
+
* used when no escalation mechanism is configured or the run's escalation
|
|
383
|
+
* budget is exhausted; the streak falls through to the weaker rungs.
|
|
384
|
+
* Escalation applies to the NEXT model request, so it is available to every
|
|
385
|
+
* detector kind (tool, server-tool, and text verdicts alike).
|
|
386
|
+
*/
|
|
387
|
+
export declare function resolveLadderAction(ladder: Required<DoomLoopLadder>, streak: number, options: {
|
|
388
|
+
allowBlock: boolean;
|
|
389
|
+
allowEscalate?: boolean;
|
|
390
|
+
}): DoomLoopAction | undefined;
|
|
391
|
+
/**
|
|
392
|
+
* Pure state machine over the recorded transcript: feed it tool calls and
|
|
393
|
+
* assistant texts, get verdicts back. Holds no engine concerns (hook
|
|
394
|
+
* emission, blocking, steering, stopping live in `ModelResult`), so its
|
|
395
|
+
* behavior is fully exercisable in unit tests and portable as a spec.
|
|
396
|
+
*
|
|
397
|
+
* State is bounded, plain JSON (one streak entry per distinct tool name +
|
|
398
|
+
* one text streak) and round-trips through `ConversationState`.
|
|
399
|
+
*/
|
|
400
|
+
export declare class DoomLoopMonitor {
|
|
401
|
+
private readonly config;
|
|
402
|
+
private tools;
|
|
403
|
+
private text;
|
|
404
|
+
private escalationsUsed;
|
|
405
|
+
private declaredRound;
|
|
406
|
+
constructor(config: ResolvedDoomLoopConfig, initialState?: unknown);
|
|
407
|
+
/**
|
|
408
|
+
* Declare the complete set of calls a round will make, before any of them
|
|
409
|
+
* is recorded. Each entry is one call's `(toolName, keyMaterial)`; the
|
|
410
|
+
* monitor groups them per tool into that tool's round set.
|
|
411
|
+
*
|
|
412
|
+
* A round's identity is the *set* of fingerprints a tool was called with,
|
|
413
|
+
* so that set has to be known up front. Accumulating it call by call meant
|
|
414
|
+
* a round that is a strict superset of the previous one transiently equaled
|
|
415
|
+
* it while filling — `[a,b]`, `[a,b]`, `[a,b,c]` scored a verdict on the `b`
|
|
416
|
+
* of the third round and refused a call that represented real progress. It
|
|
417
|
+
* was also emission-order dependent: `[c,a,b]` never formed the matching
|
|
418
|
+
* prefix and scored nothing. Declaring the whole set removes both.
|
|
419
|
+
*
|
|
420
|
+
* Idempotent per round, and safe to skip: PER-CALL detection needs no
|
|
421
|
+
* declaration — every repeated `(tool, arguments)` identity accumulates its
|
|
422
|
+
* own consecutive-round count regardless, so an undeclared repeating
|
|
423
|
+
* fan-out still flags each repeated member (server-tool records take that
|
|
424
|
+
* path). What the declaration adds is round-set evidence: the fan-out
|
|
425
|
+
* scored as one unit, with a shared verdict and one steer message, instead
|
|
426
|
+
* of member-by-member. Unhashable key material is skipped here with a
|
|
427
|
+
* warning; the caller's own fallback chain handles it at record time.
|
|
428
|
+
* Never serialized.
|
|
429
|
+
*/
|
|
430
|
+
declareRound(round: number, calls: readonly {
|
|
431
|
+
toolName: string;
|
|
432
|
+
keyMaterial: unknown;
|
|
433
|
+
}[]): Promise<void>;
|
|
434
|
+
/**
|
|
435
|
+
* Fingerprint with a per-object memo. The engine hands the SAME key-material
|
|
436
|
+
* object to `declareRound` and then to `recordToolCall` (the resolved
|
|
437
|
+
* `loopKey` output is cached per call id), so without this every checked
|
|
438
|
+
* call is canonicalized and SHA-256'd twice per round. WeakMap keeps the
|
|
439
|
+
* memo from retaining arguments beyond their natural lifetime; primitive
|
|
440
|
+
* key material (raw-string malformed args) skips the memo — it cannot key a
|
|
441
|
+
* WeakMap, and such calls are rare and small. Callers that mutate key
|
|
442
|
+
* material between declare and record get the declare-time identity, which
|
|
443
|
+
* is the identity the round was declared with — the consistent choice.
|
|
444
|
+
*/
|
|
445
|
+
private readonly fingerprintMemo;
|
|
446
|
+
private fingerprintOnce;
|
|
447
|
+
/**
|
|
448
|
+
* True when the escalate rung can still fire: a mechanism is configured
|
|
449
|
+
* and the budget is not exhausted.
|
|
450
|
+
*/
|
|
451
|
+
canEscalate(): boolean;
|
|
452
|
+
/**
|
|
453
|
+
* Consume one escalation from the budget. The ENGINE calls this when it
|
|
454
|
+
* actually applies the recovery (model swap / advisor forcing) — not at
|
|
455
|
+
* verdict time, so a verdict the engine ends up not honoring (e.g. a hook
|
|
456
|
+
* override) does not burn budget.
|
|
457
|
+
*/
|
|
458
|
+
consumeEscalation(): void;
|
|
459
|
+
/**
|
|
460
|
+
* Snapshot the serializable detector state (deep copy). Round markers are
|
|
461
|
+
* deliberately dropped: rounds are meaningful only within one run.
|
|
462
|
+
* `stopVerdict`/`pendingSteer` are owned by the engine, which merges them
|
|
463
|
+
* into the persisted blob alongside this snapshot.
|
|
464
|
+
*/
|
|
465
|
+
getState(): DoomLoopSerializedState;
|
|
466
|
+
/**
|
|
467
|
+
* Restore persisted state (from `ConversationState.doomLoop`). Invalid
|
|
468
|
+
* blobs are ignored with a warning — a corrupt detector state must never
|
|
469
|
+
* take down a resumed run. Engine-owned fields (`stopVerdict`,
|
|
470
|
+
* `pendingSteer`) are ignored here; the engine restores them itself.
|
|
471
|
+
*/
|
|
472
|
+
restore(state: unknown): void;
|
|
473
|
+
/**
|
|
474
|
+
* Record one tool call and return the streak record plus any verdict.
|
|
475
|
+
*
|
|
476
|
+
* Streak semantics:
|
|
477
|
+
* - Per tool: interleaved calls to *other* tools do not reset a tool's
|
|
478
|
+
* streak (so `search X, read file, search X, read file` still trips).
|
|
479
|
+
* - Per round: the same `(tool, fingerprint)` recorded again in the SAME
|
|
480
|
+
* `round` is a duplicate — the streak does not increment
|
|
481
|
+
* (`duplicateInRound: true`) and the caller should reuse the decision it
|
|
482
|
+
* applied for the first occurrence. A streak measures the model
|
|
483
|
+
* re-issuing a call *after seeing its result*, which requires a round
|
|
484
|
+
* trip; N parallel identical calls in one turn are one piece of
|
|
485
|
+
* evidence, not N.
|
|
486
|
+
* - A round's identity is the *set* of fingerprints the tool was called
|
|
487
|
+
* with, not its last call, so a fan-out of distinct arguments reissued
|
|
488
|
+
* verbatim accumulates. A round whose set differs from the previous
|
|
489
|
+
* round's — in either direction, including a superset — resets to 1.
|
|
490
|
+
* Every call in a round reports that round's streak, so the ladder
|
|
491
|
+
* applies to the round as a unit. See {@link declareRound}: the set must
|
|
492
|
+
* be declared before the round's first call for this to hold for
|
|
493
|
+
* multi-call rounds.
|
|
494
|
+
*
|
|
495
|
+
* Blocked calls are recorded like any other — a model re-issuing a
|
|
496
|
+
* blocked call in a later round is stronger loop evidence, not progress.
|
|
497
|
+
*
|
|
498
|
+
* @throws Whatever {@link canonicalizeKeyMaterial} throws for unhashable
|
|
499
|
+
* key material. Callers (the engine) must catch and fall back — see
|
|
500
|
+
* `resolveLoopKeyMaterial` and the engine's fallback chain.
|
|
501
|
+
*/
|
|
502
|
+
recordToolCall(toolName: string, keyMaterial: unknown, round: number, options?: {
|
|
503
|
+
/** False for post-execution records (server tools): block is meaningless. */
|
|
504
|
+
allowBlock?: boolean;
|
|
505
|
+
/** Verdict detector label; default 'tool-fingerprint'. */
|
|
506
|
+
detector?: Extract<DoomLoopDetectorKind, 'tool-fingerprint' | 'server-tool-fingerprint'>;
|
|
507
|
+
}): Promise<DoomLoopCallRecord>;
|
|
508
|
+
/**
|
|
509
|
+
* Clear the cross-step text streak. Called by the engine when a late
|
|
510
|
+
* async-tool result is injected into the conversation: the run made
|
|
511
|
+
* observable forward progress, so a model that said "still waiting…"
|
|
512
|
+
* between deliveries must not accumulate a repetition streak toward a
|
|
513
|
+
* false-positive stop. Tool streaks are deliberately kept — re-issuing an
|
|
514
|
+
* identical tool call after a delivery is still loop evidence.
|
|
515
|
+
*/
|
|
516
|
+
resetTextStreak(): void;
|
|
517
|
+
/**
|
|
518
|
+
* Record one step's assistant text and return the strongest verdict from
|
|
519
|
+
* the two text detectors:
|
|
520
|
+
*
|
|
521
|
+
* - `text-repetition`: a token block repeating within THIS response; the
|
|
522
|
+
* repeat count feeds the ladder directly, so a single response spinning
|
|
523
|
+
* "I am stuck." dozens of times can stop the run immediately.
|
|
524
|
+
* - `text-streak`: byte-identical (whitespace-normalized) text across
|
|
525
|
+
* consecutive steps. KNOWN LIMIT: paraphrased repetition does not trip.
|
|
526
|
+
*
|
|
527
|
+
* Empty/whitespace-only text (typical for tool-only turns) is a no-op:
|
|
528
|
+
* it neither counts nor resets the cross-step streak, mirroring how
|
|
529
|
+
* interleaved other-tool calls don't reset a tool streak.
|
|
530
|
+
*/
|
|
531
|
+
recordAssistantText(text: string): Promise<DoomLoopVerdict | undefined>;
|
|
532
|
+
}
|
|
533
|
+
//# sourceMappingURL=doom-loop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doom-loop.d.ts","sourceRoot":"","sources":["../../src/lib/doom-loop.ts"],"names":[],"mappings":"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"}
|