@cubicecho/agent-core 2.24.0 → 2.25.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/README.md +10 -7
- package/dist/agent-loop.d.ts +84 -205
- package/dist/agent-loop.js +288 -597
- package/dist/calibration.d.ts +14 -10
- package/dist/calibration.js +30 -23
- package/dist/capabilities.d.ts +111 -42
- package/dist/capabilities.js +281 -138
- package/dist/client.d.ts +104 -35
- package/dist/client.js +205 -74
- package/dist/compaction.d.ts +103 -60
- package/dist/compaction.js +160 -86
- package/dist/config.d.ts +48 -12
- package/dist/config.js +20 -1
- package/dist/continuation.d.ts +24 -16
- package/dist/continuation.js +70 -44
- package/dist/digest.d.ts +7 -0
- package/dist/digest.js +18 -0
- package/dist/errors.d.ts +24 -15
- package/dist/errors.js +23 -15
- package/dist/events.d.ts +100 -63
- package/dist/events.js +250 -120
- package/dist/guards.d.ts +49 -4
- package/dist/guards.js +60 -5
- package/dist/hook-events.d.ts +21 -5
- package/dist/hook-events.js +23 -9
- package/dist/hooks.d.ts +96 -73
- package/dist/hooks.js +202 -116
- package/dist/index.d.ts +30 -26
- package/dist/index.js +29 -24
- package/dist/ledger.d.ts +62 -30
- package/dist/ledger.js +163 -56
- package/dist/platform.d.ts +15 -0
- package/dist/platform.js +15 -0
- package/dist/preselect.d.ts +223 -0
- package/dist/preselect.js +291 -0
- package/dist/request-body.d.ts +32 -0
- package/dist/request-body.js +47 -0
- package/dist/reset.d.ts +1 -0
- package/dist/reset.js +7 -6
- package/dist/retry.d.ts +44 -138
- package/dist/retry.js +83 -281
- package/dist/run-calls.d.ts +123 -0
- package/dist/run-calls.js +351 -0
- package/dist/run-turn.d.ts +36 -15
- package/dist/run-turn.js +74 -37
- package/dist/runtime.d.ts +23 -17
- package/dist/runtime.js +34 -24
- package/dist/schema-compat.d.ts +35 -18
- package/dist/schema-compat.js +346 -176
- package/dist/scope.d.ts +28 -5
- package/dist/scope.js +37 -10
- package/dist/side-task.d.ts +124 -40
- package/dist/side-task.js +186 -66
- package/dist/snapshot.d.ts +10 -5
- package/dist/snapshot.js +73 -30
- package/dist/spec.d.ts +56 -25
- package/dist/spec.js +494 -215
- package/dist/stream.d.ts +66 -16
- package/dist/stream.js +220 -97
- package/dist/thinking.d.ts +23 -8
- package/dist/thinking.js +92 -44
- package/dist/tokens.d.ts +164 -6
- package/dist/tokens.js +319 -6
- package/dist/tool-calls.d.ts +90 -17
- package/dist/tool-calls.js +207 -84
- package/dist/tool-loading.d.ts +101 -189
- package/dist/tool-loading.js +257 -371
- package/dist/wire.d.ts +81 -0
- package/dist/wire.js +73 -0
- package/llms.txt +76 -39
- package/package.json +4 -4
package/dist/continuation.js
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import { modelCapabilitiesFor } from
|
|
2
|
-
import { errorMessage } from
|
|
3
|
-
import { ContextOverflow, refusesRequest } from
|
|
4
|
-
import { runTurn } from
|
|
1
|
+
import { modelCapabilitiesFor } from './capabilities.js';
|
|
2
|
+
import { errorMessage } from './errors.js';
|
|
3
|
+
import { ContextOverflow, refusesRequest } from './retry.js';
|
|
4
|
+
import { modelLabel, runTurn } from './run-turn.js';
|
|
5
|
+
import { addCounts } from './stream.js';
|
|
6
|
+
import { FinishReason, Role } from './wire.js';
|
|
5
7
|
/**
|
|
6
8
|
* Whether a turn is one a continuation can finish: cut off at the ceiling, with an answer begun
|
|
7
9
|
* and no tool call in it.
|
|
8
10
|
*
|
|
11
|
+
* @param turn - The turn as it came back.
|
|
12
|
+
* @returns False for a turn that stopped for any reason but `length`, whose content is blank, or
|
|
13
|
+
* that holds a tool call.
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
9
16
|
* An answer not begun is a turn cut off in its scratchpad, and prefilling a half-closed fence is
|
|
10
17
|
* the template's business rather than something this can do the same way everywhere — llama.cpp
|
|
11
18
|
* refuses a prefill outright on a template with thinking enabled. A tool call is excluded because
|
|
12
19
|
* its arguments are what was cut, and `parseToolArguments` already reports that truncation.
|
|
13
|
-
*
|
|
14
|
-
* @param turn The turn as it came back.
|
|
15
20
|
*/
|
|
16
|
-
export const isContinuable = (turn) => turn.finishReason ===
|
|
21
|
+
export const isContinuable = (turn) => turn.finishReason === FinishReason.Length && turn.content.trim() !== '' && turn.toolCalls.length === 0;
|
|
17
22
|
/** How much of the answer's opening a reply has to repeat to have started over. */
|
|
18
23
|
const RESTART_PROBE = 40;
|
|
19
24
|
/** The shortest opening worth testing for a restart; shorter ones are repeated by chance. */
|
|
@@ -21,6 +26,11 @@ const RESTART_MIN = 12;
|
|
|
21
26
|
/**
|
|
22
27
|
* Whether the continuation began the answer again rather than carrying it on — how a server that
|
|
23
28
|
* ignores the prefill shows itself, since it takes the request without complaint.
|
|
29
|
+
*
|
|
30
|
+
* @param answer - The answer so far, as it was sent back as the prefill.
|
|
31
|
+
* @param continuation - The content the continuation came back with.
|
|
32
|
+
* @returns True where the continuation opens with the answer's own opening, leading whitespace
|
|
33
|
+
* aside on both. Never true for an answer whose opening is shorter than `RESTART_MIN`.
|
|
24
34
|
*/
|
|
25
35
|
const restarted = (answer, continuation) => {
|
|
26
36
|
const opening = answer.trimStart().slice(0, RESTART_PROBE);
|
|
@@ -28,42 +38,48 @@ const restarted = (answer, continuation) => {
|
|
|
28
38
|
};
|
|
29
39
|
/** The fields of a usage that add across two requests, when both reported them. */
|
|
30
40
|
const ADDED = [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
'uncached',
|
|
42
|
+
'reasoningTokens',
|
|
43
|
+
'promptMs',
|
|
44
|
+
'predictedMs',
|
|
45
|
+
'draftTotal',
|
|
46
|
+
'draftAccepted',
|
|
47
|
+
'wallMs',
|
|
48
|
+
'retries',
|
|
49
|
+
'timeouts',
|
|
40
50
|
];
|
|
41
51
|
/** A rate, and the duration it was measured over, which is what weights it in a mean. */
|
|
42
52
|
const RATES = [
|
|
43
|
-
[
|
|
44
|
-
[
|
|
53
|
+
['promptTokensPerSecond', 'promptMs'],
|
|
54
|
+
['tokensPerSecond', 'predictedMs'],
|
|
45
55
|
];
|
|
46
56
|
/**
|
|
47
|
-
* Two requests' usage as one turn's.
|
|
48
|
-
*
|
|
49
|
-
*
|
|
57
|
+
* Two requests' usage as one turn's.
|
|
58
|
+
*
|
|
59
|
+
* @param first - The turn so far, which may itself be a joined one. Not written to.
|
|
60
|
+
* @param next - The continuation's usage. Not written to.
|
|
61
|
+
* @returns A new usage: the four counts summed, `continuations` one more than `first` had, and a
|
|
62
|
+
* rate both requests timed as the mean of the two, weighted by the time each was measured over.
|
|
63
|
+
*
|
|
64
|
+
* @remarks
|
|
65
|
+
* The first request's own measurements and the loop's comparison with the request before it stay
|
|
66
|
+
* as they were; a field only one of them reported is dropped rather than passed off as the total.
|
|
50
67
|
*/
|
|
51
68
|
function joinUsage(first, next) {
|
|
52
69
|
const joined = {
|
|
53
70
|
...first,
|
|
54
|
-
|
|
55
|
-
completion: first.completion + next.completion,
|
|
56
|
-
total: first.total + next.total,
|
|
57
|
-
cached: first.cached + next.cached,
|
|
71
|
+
...addCounts(first, next),
|
|
58
72
|
continuations: (first.continuations ?? 0) + 1,
|
|
59
73
|
};
|
|
60
74
|
for (const field of ADDED) {
|
|
61
75
|
const a = first[field];
|
|
62
76
|
const b = next[field];
|
|
63
|
-
if (a !== undefined && b !== undefined)
|
|
77
|
+
if (a !== undefined && b !== undefined) {
|
|
64
78
|
joined[field] = a + b;
|
|
65
|
-
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
66
81
|
delete joined[field];
|
|
82
|
+
}
|
|
67
83
|
}
|
|
68
84
|
for (const [rate, over] of RATES) {
|
|
69
85
|
const a = first[rate];
|
|
@@ -71,10 +87,13 @@ function joinUsage(first, next) {
|
|
|
71
87
|
const aMs = first[over];
|
|
72
88
|
const bMs = next[over];
|
|
73
89
|
// Tokens over time for both together, which is each rate weighted by the time it held.
|
|
74
|
-
|
|
90
|
+
const bothTimed = a !== undefined && b !== undefined && aMs !== undefined && bMs !== undefined;
|
|
91
|
+
if (bothTimed && aMs + bMs) {
|
|
75
92
|
joined[rate] = (a * aMs + b * bMs) / (aMs + bMs);
|
|
76
|
-
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
77
95
|
delete joined[rate];
|
|
96
|
+
}
|
|
78
97
|
}
|
|
79
98
|
return joined;
|
|
80
99
|
}
|
|
@@ -82,6 +101,17 @@ function joinUsage(first, next) {
|
|
|
82
101
|
* Carries on an answer the token ceiling cut off, by sending the transcript again with the answer
|
|
83
102
|
* so far as a trailing assistant message, and joins the pieces into one turn.
|
|
84
103
|
*
|
|
104
|
+
* @param client - The pooled client for this endpoint.
|
|
105
|
+
* @param supports - What the endpoint has already refused.
|
|
106
|
+
* @param request - Builds the body the cut-off turn was sent, exactly as `runTurn` was given it. The
|
|
107
|
+
* prefill is appended to what it builds.
|
|
108
|
+
* @param turn - The turn that came back cut off.
|
|
109
|
+
* @param [options] - `runTurn`'s options, with `model` needed for the latch — without one nothing is
|
|
110
|
+
* latched and each continuation finds out again — and the cap on continuations.
|
|
111
|
+
* @returns `turn` itself where nothing was joined to it; otherwise a new turn, with the last
|
|
112
|
+
* continuation's `finishReason` and tool calls.
|
|
113
|
+
*
|
|
114
|
+
* @remarks
|
|
85
115
|
* Only a turn `isContinuable` accepts is continued; any other comes back as it was. Content and
|
|
86
116
|
* reasoning are joined in order, the tool calls a continuation makes are kept, and usage is summed
|
|
87
117
|
* across the requests with `continuations` counting them. The continuation is read as starting in
|
|
@@ -95,22 +125,15 @@ function joinUsage(first, next) {
|
|
|
95
125
|
* that check is only as good as a restart being word for word. Either way the answer so far is
|
|
96
126
|
* kept, with a notice. So is it when the continuation fails any other way, since the tokens
|
|
97
127
|
* already in hand are worth more than the error; only a stop is thrown.
|
|
98
|
-
*
|
|
99
|
-
* @param client The pooled client for this endpoint.
|
|
100
|
-
* @param supports What the endpoint has already refused.
|
|
101
|
-
* @param request Builds the body the cut-off turn was sent, exactly as `runTurn` was given it. The
|
|
102
|
-
* prefill is appended to what it builds.
|
|
103
|
-
* @param turn The turn that came back cut off.
|
|
104
|
-
* @param options `runTurn`'s options, with `model` needed for the latch — without one nothing is
|
|
105
|
-
* latched and each continuation finds out again — and the cap on continuations.
|
|
106
128
|
*/
|
|
107
129
|
export async function continueTurn(client, supports, request, turn, { maxContinuations = 1, ...options } = {}) {
|
|
108
130
|
const refused = options.model === undefined ? undefined : modelCapabilitiesFor(supports, options.model);
|
|
109
|
-
const who = options.model
|
|
131
|
+
const who = modelLabel(options.model);
|
|
110
132
|
let joined = turn;
|
|
111
133
|
for (let count = 0; count < maxContinuations && isContinuable(joined); count++) {
|
|
112
|
-
if (refused?.assistantPrefill === false)
|
|
134
|
+
if (refused?.assistantPrefill === false) {
|
|
113
135
|
break;
|
|
136
|
+
}
|
|
114
137
|
const answer = joined.content;
|
|
115
138
|
let next;
|
|
116
139
|
try {
|
|
@@ -118,19 +141,21 @@ export async function continueTurn(client, supports, request, turn, { maxContinu
|
|
|
118
141
|
const body = request(capabilities, forModel);
|
|
119
142
|
return {
|
|
120
143
|
...body,
|
|
121
|
-
messages: [...body.messages, { role:
|
|
144
|
+
messages: [...body.messages, { role: Role.Assistant, content: answer }],
|
|
122
145
|
};
|
|
123
146
|
}, { ...options, startInReasoning: false });
|
|
124
147
|
}
|
|
125
148
|
catch (error) {
|
|
126
|
-
if (options.signal?.aborted)
|
|
149
|
+
if (options.signal?.aborted) {
|
|
127
150
|
throw error;
|
|
151
|
+
}
|
|
128
152
|
if (error instanceof ContextOverflow) {
|
|
129
|
-
options.onNotice?.(
|
|
153
|
+
options.onNotice?.('no room left in the window to continue the cut-off reply');
|
|
130
154
|
}
|
|
131
155
|
else if (refusesRequest(error)) {
|
|
132
|
-
if (refused)
|
|
156
|
+
if (refused) {
|
|
133
157
|
refused.assistantPrefill = false;
|
|
158
|
+
}
|
|
134
159
|
options.onNotice?.(`${who} refused a trailing assistant message (${errorMessage(error)}); keeping the cut-off reply`);
|
|
135
160
|
}
|
|
136
161
|
else {
|
|
@@ -139,8 +164,9 @@ export async function continueTurn(client, supports, request, turn, { maxContinu
|
|
|
139
164
|
break;
|
|
140
165
|
}
|
|
141
166
|
if (restarted(answer, next.content)) {
|
|
142
|
-
if (refused)
|
|
167
|
+
if (refused) {
|
|
143
168
|
refused.assistantPrefill = false;
|
|
169
|
+
}
|
|
144
170
|
options.onNotice?.(`${who} answered afresh instead of continuing its reply; keeping the cut-off reply`);
|
|
145
171
|
break;
|
|
146
172
|
}
|
package/dist/digest.d.ts
ADDED
package/dist/digest.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one digest this package takes, of an endpoint's key and of a turn's text.
|
|
3
|
+
*
|
|
4
|
+
* Apart from `platform.ts` because it loads `node:crypto`, which a browser-safe module must not
|
|
5
|
+
* come to import by reaching for a constant.
|
|
6
|
+
*/
|
|
7
|
+
import { createHash } from 'node:crypto';
|
|
8
|
+
/** The hash every digest here is taken with. */
|
|
9
|
+
const DIGEST_ALGORITHM = 'sha256';
|
|
10
|
+
/** How a digest is written out. */
|
|
11
|
+
const DIGEST_ENCODING = 'hex';
|
|
12
|
+
/**
|
|
13
|
+
* A text's SHA-256, in hex.
|
|
14
|
+
*
|
|
15
|
+
* @param text - What to hash.
|
|
16
|
+
* @returns Sixty-four hex characters, the same for the same text on any machine.
|
|
17
|
+
*/
|
|
18
|
+
export const digestOf = (text) => createHash(DIGEST_ALGORITHM).update(text).digest(DIGEST_ENCODING);
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
import type OpenAI from
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import type {
|
|
1
|
+
import type OpenAI from 'openai';
|
|
2
|
+
import { ContextOverflow } from './retry.ts';
|
|
3
|
+
import type { TurnUsage } from './stream.ts';
|
|
4
|
+
import type { ToolCallOutcome } from './tool-calls.ts';
|
|
5
5
|
/**
|
|
6
6
|
* What went wrong, as a string.
|
|
7
7
|
*
|
|
8
|
+
* @param error - Whatever a `catch` bound. Anything that is not an `Error` is stringified.
|
|
9
|
+
* @returns An `Error`'s `message` as it is, empty included; otherwise `String(error)`, so a thrown
|
|
10
|
+
* `undefined` reads `undefined`.
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
8
13
|
* Almost everything caught here ends up in a run row, a tool result or a log line, and a
|
|
9
14
|
* `catch` binds `unknown` — so the same three-branch ternary was being written at every site
|
|
10
15
|
* that had to say what happened.
|
|
11
|
-
*
|
|
12
|
-
* @param error Whatever a `catch` bound. Anything that is not an `Error` is stringified.
|
|
13
16
|
*/
|
|
14
17
|
export declare const errorMessage: (error: unknown) => string;
|
|
15
18
|
/**
|
|
16
19
|
* A run as it stood when `runAgentLoop` gave up on it.
|
|
17
20
|
*
|
|
21
|
+
* @remarks
|
|
18
22
|
* The loop works on its own copy of the transcript and hands it back only on success, so without
|
|
19
23
|
* this a spent budget, a stop or a refused request took every step before it along — steps whose
|
|
20
24
|
* assistant turns and tool results were real, and that a host storing its transcript has to keep.
|
|
@@ -38,6 +42,7 @@ export interface AgentLoopFailure {
|
|
|
38
42
|
/**
|
|
39
43
|
* What `runAgentLoop` throws, carrying the run as it stood and what was caught as `cause`.
|
|
40
44
|
*
|
|
45
|
+
* @remarks
|
|
41
46
|
* Its own class rather than fields hung on the error that was caught, because a stop throws the
|
|
42
47
|
* signal's reason and that is one object for every run under the signal. The message is the
|
|
43
48
|
* cause's own, so a host that logs `errorMessage(error)` logs what it always did. A stop is told
|
|
@@ -51,15 +56,16 @@ export declare class AgentLoopError extends Error implements AgentLoopFailure {
|
|
|
51
56
|
readonly loaded: string[];
|
|
52
57
|
readonly used: string[];
|
|
53
58
|
/**
|
|
54
|
-
* @param message What went wrong — the cause's own message, where there is a cause.
|
|
55
|
-
* @param run The run as it stood. Held, not copied.
|
|
56
|
-
* @param options The standard `cause`: what the loop caught, absent where the loop itself gave up.
|
|
59
|
+
* @param message - What went wrong — the cause's own message, where there is a cause.
|
|
60
|
+
* @param run - The run as it stood. Held, not copied.
|
|
61
|
+
* @param [options] - The standard `cause`: what the loop caught, absent where the loop itself gave up.
|
|
57
62
|
*/
|
|
58
63
|
constructor(message: string, run: AgentLoopFailure, options?: ErrorOptions);
|
|
59
64
|
}
|
|
60
65
|
/**
|
|
61
66
|
* `maxToolIterations` was spent with the model still asking for tools.
|
|
62
67
|
*
|
|
68
|
+
* @remarks
|
|
63
69
|
* Named so a host can tell it from a failure without matching the message, which is the same
|
|
64
70
|
* sentence it has always been. There is no `cause`: nothing was caught, the loop stopped itself.
|
|
65
71
|
*/
|
|
@@ -69,6 +75,7 @@ export declare class ToolIterationLimit extends AgentLoopError {
|
|
|
69
75
|
/**
|
|
70
76
|
* A `ContextOverflow` out of `runAgentLoop`, carrying the run as it stood.
|
|
71
77
|
*
|
|
78
|
+
* @remarks
|
|
72
79
|
* A subclass of `ContextOverflow` rather than an `AgentLoopError` around one, because
|
|
73
80
|
* `instanceof ContextOverflow` is how a caller knows to compact and send again, and wrapping
|
|
74
81
|
* would have made that test quietly false. The overflow the loop caught is the `cause`, and the
|
|
@@ -81,19 +88,21 @@ export declare class AgentLoopOverflow extends ContextOverflow implements AgentL
|
|
|
81
88
|
readonly loaded: string[];
|
|
82
89
|
readonly used: string[];
|
|
83
90
|
/**
|
|
84
|
-
* @param message The overflow's own message.
|
|
85
|
-
* @param run The run as it stood. Held, not copied.
|
|
86
|
-
* @param options The standard `cause`: the `ContextOverflow` the loop caught.
|
|
91
|
+
* @param message - The overflow's own message.
|
|
92
|
+
* @param run - The run as it stood. Held, not copied.
|
|
93
|
+
* @param [options] - The standard `cause`: the `ContextOverflow` the loop caught.
|
|
87
94
|
*/
|
|
88
95
|
constructor(message: string, run: AgentLoopFailure, options?: ErrorOptions);
|
|
89
96
|
}
|
|
90
97
|
/**
|
|
91
98
|
* The run a failed `runAgentLoop` left behind, read off whatever it threw, or nothing.
|
|
92
99
|
*
|
|
100
|
+
* @param error - Whatever a `catch` around `runAgentLoop` bound. Anything the loop did not throw
|
|
101
|
+
* answers `undefined`.
|
|
102
|
+
* @returns The error itself, read as the run it carries — the same object, not a copy.
|
|
103
|
+
*
|
|
104
|
+
* @remarks
|
|
93
105
|
* Two classes carry it — an overflow has to stay a `ContextOverflow` and so cannot also be an
|
|
94
106
|
* `AgentLoopError` — and a `catch` that only wants the transcript should not have to name both.
|
|
95
|
-
*
|
|
96
|
-
* @param error Whatever a `catch` around `runAgentLoop` bound. Anything the loop did not throw
|
|
97
|
-
* answers `undefined`.
|
|
98
107
|
*/
|
|
99
108
|
export declare const failedRun: (error: unknown) => AgentLoopFailure | undefined;
|
package/dist/errors.js
CHANGED
|
@@ -1,33 +1,37 @@
|
|
|
1
|
-
import { ContextOverflow } from
|
|
1
|
+
import { ContextOverflow } from './retry.js';
|
|
2
2
|
/**
|
|
3
3
|
* What went wrong, as a string.
|
|
4
4
|
*
|
|
5
|
+
* @param error - Whatever a `catch` bound. Anything that is not an `Error` is stringified.
|
|
6
|
+
* @returns An `Error`'s `message` as it is, empty included; otherwise `String(error)`, so a thrown
|
|
7
|
+
* `undefined` reads `undefined`.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
5
10
|
* Almost everything caught here ends up in a run row, a tool result or a log line, and a
|
|
6
11
|
* `catch` binds `unknown` — so the same three-branch ternary was being written at every site
|
|
7
12
|
* that had to say what happened.
|
|
8
|
-
*
|
|
9
|
-
* @param error Whatever a `catch` bound. Anything that is not an `Error` is stringified.
|
|
10
13
|
*/
|
|
11
|
-
export const errorMessage = (error) => error instanceof Error ? error.message : String(error);
|
|
14
|
+
export const errorMessage = (error) => (error instanceof Error ? error.message : String(error));
|
|
12
15
|
/**
|
|
13
16
|
* What `runAgentLoop` throws, carrying the run as it stood and what was caught as `cause`.
|
|
14
17
|
*
|
|
18
|
+
* @remarks
|
|
15
19
|
* Its own class rather than fields hung on the error that was caught, because a stop throws the
|
|
16
20
|
* signal's reason and that is one object for every run under the signal. The message is the
|
|
17
21
|
* cause's own, so a host that logs `errorMessage(error)` logs what it always did. A stop is told
|
|
18
22
|
* the way it was before — by the signal the host aborted, not by the class of what came out.
|
|
19
23
|
*/
|
|
20
24
|
export class AgentLoopError extends Error {
|
|
21
|
-
name =
|
|
25
|
+
name = 'AgentLoopError';
|
|
22
26
|
messages;
|
|
23
27
|
usage;
|
|
24
28
|
toolCalls;
|
|
25
29
|
loaded;
|
|
26
30
|
used;
|
|
27
31
|
/**
|
|
28
|
-
* @param message What went wrong — the cause's own message, where there is a cause.
|
|
29
|
-
* @param run The run as it stood. Held, not copied.
|
|
30
|
-
* @param options The standard `cause`: what the loop caught, absent where the loop itself gave up.
|
|
32
|
+
* @param message - What went wrong — the cause's own message, where there is a cause.
|
|
33
|
+
* @param run - The run as it stood. Held, not copied.
|
|
34
|
+
* @param [options] - The standard `cause`: what the loop caught, absent where the loop itself gave up.
|
|
31
35
|
*/
|
|
32
36
|
constructor(message, run, options) {
|
|
33
37
|
super(message, options);
|
|
@@ -41,15 +45,17 @@ export class AgentLoopError extends Error {
|
|
|
41
45
|
/**
|
|
42
46
|
* `maxToolIterations` was spent with the model still asking for tools.
|
|
43
47
|
*
|
|
48
|
+
* @remarks
|
|
44
49
|
* Named so a host can tell it from a failure without matching the message, which is the same
|
|
45
50
|
* sentence it has always been. There is no `cause`: nothing was caught, the loop stopped itself.
|
|
46
51
|
*/
|
|
47
52
|
export class ToolIterationLimit extends AgentLoopError {
|
|
48
|
-
name =
|
|
53
|
+
name = 'ToolIterationLimit';
|
|
49
54
|
}
|
|
50
55
|
/**
|
|
51
56
|
* A `ContextOverflow` out of `runAgentLoop`, carrying the run as it stood.
|
|
52
57
|
*
|
|
58
|
+
* @remarks
|
|
53
59
|
* A subclass of `ContextOverflow` rather than an `AgentLoopError` around one, because
|
|
54
60
|
* `instanceof ContextOverflow` is how a caller knows to compact and send again, and wrapping
|
|
55
61
|
* would have made that test quietly false. The overflow the loop caught is the `cause`, and the
|
|
@@ -62,9 +68,9 @@ export class AgentLoopOverflow extends ContextOverflow {
|
|
|
62
68
|
loaded;
|
|
63
69
|
used;
|
|
64
70
|
/**
|
|
65
|
-
* @param message The overflow's own message.
|
|
66
|
-
* @param run The run as it stood. Held, not copied.
|
|
67
|
-
* @param options The standard `cause`: the `ContextOverflow` the loop caught.
|
|
71
|
+
* @param message - The overflow's own message.
|
|
72
|
+
* @param run - The run as it stood. Held, not copied.
|
|
73
|
+
* @param [options] - The standard `cause`: the `ContextOverflow` the loop caught.
|
|
68
74
|
*/
|
|
69
75
|
constructor(message, run, options) {
|
|
70
76
|
super(message, options);
|
|
@@ -78,10 +84,12 @@ export class AgentLoopOverflow extends ContextOverflow {
|
|
|
78
84
|
/**
|
|
79
85
|
* The run a failed `runAgentLoop` left behind, read off whatever it threw, or nothing.
|
|
80
86
|
*
|
|
87
|
+
* @param error - Whatever a `catch` around `runAgentLoop` bound. Anything the loop did not throw
|
|
88
|
+
* answers `undefined`.
|
|
89
|
+
* @returns The error itself, read as the run it carries — the same object, not a copy.
|
|
90
|
+
*
|
|
91
|
+
* @remarks
|
|
81
92
|
* Two classes carry it — an overflow has to stay a `ContextOverflow` and so cannot also be an
|
|
82
93
|
* `AgentLoopError` — and a `catch` that only wants the transcript should not have to name both.
|
|
83
|
-
*
|
|
84
|
-
* @param error Whatever a `catch` around `runAgentLoop` bound. Anything the loop did not throw
|
|
85
|
-
* answers `undefined`.
|
|
86
94
|
*/
|
|
87
95
|
export const failedRun = (error) => error instanceof AgentLoopError || error instanceof AgentLoopOverflow ? error : undefined;
|