@cubicecho/agent-core 2.24.0 → 2.25.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 +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 +35 -4
- package/dist/guards.js +38 -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 +13 -0
- package/dist/platform.js +13 -0
- package/dist/preselect.d.ts +222 -0
- package/dist/preselect.js +290 -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 +29 -138
- package/dist/retry.js +69 -282
- 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 +340 -175
- package/dist/scope.d.ts +28 -5
- package/dist/scope.js +37 -10
- package/dist/side-task.d.ts +123 -40
- package/dist/side-task.js +181 -63
- 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 +82 -17
- package/dist/tool-calls.js +198 -83
- package/dist/tool-loading.d.ts +101 -189
- package/dist/tool-loading.js +277 -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/guards.d.ts
CHANGED
|
@@ -3,20 +3,51 @@
|
|
|
3
3
|
*
|
|
4
4
|
* A leaf with no imports, because the modules that need these — a browser-safe `spec`, the schema
|
|
5
5
|
* walk, the tool-call reader, the snapshot importer — otherwise share nothing, and each had grown
|
|
6
|
-
* its own copy.
|
|
6
|
+
* its own copy. `getOrCreate` and `counted` are here for the same reason and are the two things that
|
|
7
|
+
* are not checks: every cache in the package fills itself on a miss, and each had written that
|
|
8
|
+
* out, and a notice that counts something is written in more than one module.
|
|
7
9
|
*/
|
|
8
10
|
/**
|
|
9
11
|
* Whether a value is a plain keyed object: not null, and not an array.
|
|
10
12
|
*
|
|
11
|
-
* @param value Anything, usually just parsed. An array is an object to `typeof` and not to this.
|
|
13
|
+
* @param value - Anything, usually just parsed. An array is an object to `typeof` and not to this.
|
|
14
|
+
* @returns True for anything else `typeof` calls an object — a `Date`, a `Map` and a class
|
|
15
|
+
* instance included, since the prototype is not looked at.
|
|
12
16
|
*/
|
|
13
17
|
export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
|
|
14
18
|
/**
|
|
15
19
|
* Whether a value is a number above zero, which is what a limit has to be to be one.
|
|
16
20
|
*
|
|
21
|
+
* @param value - Anything, usually a setting that may be absent, zero or mistyped.
|
|
22
|
+
* @returns True only for a `number` greater than zero: a numeric string or a `bigint` is not one.
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
17
25
|
* `Infinity` passes and `NaN` does not, so a caller lifting a bound and one handing over a
|
|
18
26
|
* half-built config are told apart without either being asked.
|
|
19
|
-
*
|
|
20
|
-
* @param value Anything, usually a setting that may be absent, zero or mistyped.
|
|
21
27
|
*/
|
|
22
28
|
export declare const isPositive: (value: unknown) => value is number;
|
|
29
|
+
/** What `getOrCreate` needs of a map, so a `WeakMap` serves as well as a `Map`. */
|
|
30
|
+
interface Lookup<K, V> {
|
|
31
|
+
get(key: K): V | undefined;
|
|
32
|
+
set(key: K, value: V): unknown;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* What a map holds under a key, made and stored first where it holds nothing.
|
|
36
|
+
*
|
|
37
|
+
* @param map - Where to look. Gains an entry on a miss, which is the point of calling this.
|
|
38
|
+
* @param key - What to look under.
|
|
39
|
+
* @param create - Builds the value on a miss, and is not called on a hit. A stored `undefined`
|
|
40
|
+
* reads as a miss, so one that returns it is called every time.
|
|
41
|
+
* @returns What the map holds under the key afterwards: the held value itself on a hit, what
|
|
42
|
+
* `create` returned on a miss.
|
|
43
|
+
*/
|
|
44
|
+
export declare function getOrCreate<K, V>(map: Lookup<K, V>, key: K, create: () => V): V;
|
|
45
|
+
/**
|
|
46
|
+
* A count and its noun, plural unless the count is one: `1 tool`, `3 tools`.
|
|
47
|
+
*
|
|
48
|
+
* @param count - How many.
|
|
49
|
+
* @param noun - The singular, which takes an `s` and nothing cleverer.
|
|
50
|
+
* @returns The phrase. Only a count of exactly one is singular: zero reads `0 tools`.
|
|
51
|
+
*/
|
|
52
|
+
export declare const counted: (count: number, noun: string) => string;
|
|
53
|
+
export {};
|
package/dist/guards.js
CHANGED
|
@@ -3,20 +3,53 @@
|
|
|
3
3
|
*
|
|
4
4
|
* A leaf with no imports, because the modules that need these — a browser-safe `spec`, the schema
|
|
5
5
|
* walk, the tool-call reader, the snapshot importer — otherwise share nothing, and each had grown
|
|
6
|
-
* its own copy.
|
|
6
|
+
* its own copy. `getOrCreate` and `counted` are here for the same reason and are the two things that
|
|
7
|
+
* are not checks: every cache in the package fills itself on a miss, and each had written that
|
|
8
|
+
* out, and a notice that counts something is written in more than one module.
|
|
7
9
|
*/
|
|
8
10
|
/**
|
|
9
11
|
* Whether a value is a plain keyed object: not null, and not an array.
|
|
10
12
|
*
|
|
11
|
-
* @param value Anything, usually just parsed. An array is an object to `typeof` and not to this.
|
|
13
|
+
* @param value - Anything, usually just parsed. An array is an object to `typeof` and not to this.
|
|
14
|
+
* @returns True for anything else `typeof` calls an object — a `Date`, a `Map` and a class
|
|
15
|
+
* instance included, since the prototype is not looked at.
|
|
12
16
|
*/
|
|
13
|
-
export const isRecord = (value) => typeof value ===
|
|
17
|
+
export const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
14
18
|
/**
|
|
15
19
|
* Whether a value is a number above zero, which is what a limit has to be to be one.
|
|
16
20
|
*
|
|
21
|
+
* @param value - Anything, usually a setting that may be absent, zero or mistyped.
|
|
22
|
+
* @returns True only for a `number` greater than zero: a numeric string or a `bigint` is not one.
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
17
25
|
* `Infinity` passes and `NaN` does not, so a caller lifting a bound and one handing over a
|
|
18
26
|
* half-built config are told apart without either being asked.
|
|
27
|
+
*/
|
|
28
|
+
export const isPositive = (value) => typeof value === 'number' && value > 0;
|
|
29
|
+
/**
|
|
30
|
+
* What a map holds under a key, made and stored first where it holds nothing.
|
|
31
|
+
*
|
|
32
|
+
* @param map - Where to look. Gains an entry on a miss, which is the point of calling this.
|
|
33
|
+
* @param key - What to look under.
|
|
34
|
+
* @param create - Builds the value on a miss, and is not called on a hit. A stored `undefined`
|
|
35
|
+
* reads as a miss, so one that returns it is called every time.
|
|
36
|
+
* @returns What the map holds under the key afterwards: the held value itself on a hit, what
|
|
37
|
+
* `create` returned on a miss.
|
|
38
|
+
*/
|
|
39
|
+
export function getOrCreate(map, key, create) {
|
|
40
|
+
const held = map.get(key);
|
|
41
|
+
if (held !== undefined) {
|
|
42
|
+
return held;
|
|
43
|
+
}
|
|
44
|
+
const made = create();
|
|
45
|
+
map.set(key, made);
|
|
46
|
+
return made;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A count and its noun, plural unless the count is one: `1 tool`, `3 tools`.
|
|
19
50
|
*
|
|
20
|
-
* @param
|
|
51
|
+
* @param count - How many.
|
|
52
|
+
* @param noun - The singular, which takes an `s` and nothing cleverer.
|
|
53
|
+
* @returns The phrase. Only a count of exactly one is singular: zero reads `0 tools`.
|
|
21
54
|
*/
|
|
22
|
-
export const
|
|
55
|
+
export const counted = (count, noun) => `${count} ${noun}${count === 1 ? '' : 's'}`;
|
package/dist/hook-events.d.ts
CHANGED
|
@@ -7,12 +7,28 @@
|
|
|
7
7
|
* one pair together and nothing holding the other.
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* The points in a session a hook can be bound to, in the order a session meets them.
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* Named after Claude Code's hooks of the same shape, which each member names, plus
|
|
14
|
+
* `sessionDelete`, which has no counterpart there.
|
|
14
15
|
*/
|
|
15
|
-
export
|
|
16
|
+
export declare const HookEvent: {
|
|
17
|
+
/** A session opened. Claude Code's SessionStart. */
|
|
18
|
+
readonly SessionStart: 'sessionStart';
|
|
19
|
+
/** A turn is about to be requested. Claude Code's UserPromptSubmit. */
|
|
20
|
+
readonly BeforeTurn: 'beforeTurn';
|
|
21
|
+
/** A turn was answered. Claude Code's Stop. */
|
|
22
|
+
readonly AfterTurn: 'afterTurn';
|
|
23
|
+
/** Part of the transcript is about to be summarised away. Claude Code's PreCompact. */
|
|
24
|
+
readonly BeforeCompact: 'beforeCompact';
|
|
25
|
+
/** A session closed. Claude Code's SessionEnd. */
|
|
26
|
+
readonly SessionEnd: 'sessionEnd';
|
|
27
|
+
/** The host deleted a session's record. */
|
|
28
|
+
readonly SessionDelete: 'sessionDelete';
|
|
29
|
+
};
|
|
30
|
+
/** Any one of the events in `HookEvent`. */
|
|
31
|
+
export type HookEvent = (typeof HookEvent)[keyof typeof HookEvent];
|
|
16
32
|
/** Every event a hook can be bound to, in the order a session meets them. */
|
|
17
33
|
export declare const HOOK_EVENTS: readonly HookEvent[];
|
|
18
34
|
/**
|
package/dist/hook-events.js
CHANGED
|
@@ -6,17 +6,31 @@
|
|
|
6
6
|
* has to stay importable in a browser. Before this each kept its own copy, with a test holding
|
|
7
7
|
* one pair together and nothing holding the other.
|
|
8
8
|
*/
|
|
9
|
+
/**
|
|
10
|
+
* The points in a session a hook can be bound to, in the order a session meets them.
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* Named after Claude Code's hooks of the same shape, which each member names, plus
|
|
14
|
+
* `sessionDelete`, which has no counterpart there.
|
|
15
|
+
*/
|
|
16
|
+
export const HookEvent = {
|
|
17
|
+
/** A session opened. Claude Code's SessionStart. */
|
|
18
|
+
SessionStart: 'sessionStart',
|
|
19
|
+
/** A turn is about to be requested. Claude Code's UserPromptSubmit. */
|
|
20
|
+
BeforeTurn: 'beforeTurn',
|
|
21
|
+
/** A turn was answered. Claude Code's Stop. */
|
|
22
|
+
AfterTurn: 'afterTurn',
|
|
23
|
+
/** Part of the transcript is about to be summarised away. Claude Code's PreCompact. */
|
|
24
|
+
BeforeCompact: 'beforeCompact',
|
|
25
|
+
/** A session closed. Claude Code's SessionEnd. */
|
|
26
|
+
SessionEnd: 'sessionEnd',
|
|
27
|
+
/** The host deleted a session's record. */
|
|
28
|
+
SessionDelete: 'sessionDelete',
|
|
29
|
+
};
|
|
9
30
|
/** Every event a hook can be bound to, in the order a session meets them. */
|
|
10
|
-
export const HOOK_EVENTS =
|
|
11
|
-
"sessionStart",
|
|
12
|
-
"beforeTurn",
|
|
13
|
-
"afterTurn",
|
|
14
|
-
"beforeCompact",
|
|
15
|
-
"sessionEnd",
|
|
16
|
-
"sessionDelete",
|
|
17
|
-
];
|
|
31
|
+
export const HOOK_EVENTS = Object.values(HookEvent);
|
|
18
32
|
/**
|
|
19
33
|
* The events whose hooks run before a request, and so the only ones whose output can reach it.
|
|
20
34
|
* Anything later runs once the model has already answered.
|
|
21
35
|
*/
|
|
22
|
-
export const INJECT_EVENTS = new Set([
|
|
36
|
+
export const INJECT_EVENTS = new Set([HookEvent.SessionStart, HookEvent.BeforeTurn]);
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type OpenAI from
|
|
2
|
-
import { type HookEvent } from
|
|
1
|
+
import type OpenAI from 'openai';
|
|
2
|
+
import { type HookEvent } from './hook-events.ts';
|
|
3
3
|
/**
|
|
4
4
|
* Lifecycle hooks, from the host's side: what a session looks like to them, where their context
|
|
5
5
|
* lands in a request, and what is said about each one.
|
|
@@ -50,7 +50,7 @@ export interface HookContext {
|
|
|
50
50
|
through: number;
|
|
51
51
|
};
|
|
52
52
|
/** How a run ended. */
|
|
53
|
-
status?:
|
|
53
|
+
status?: 'ok' | 'stopped' | 'error';
|
|
54
54
|
/** The host's own extras — a card id, a task step. */
|
|
55
55
|
vars?: Record<string, unknown>;
|
|
56
56
|
}
|
|
@@ -83,6 +83,8 @@ export interface HookOutcome {
|
|
|
83
83
|
*/
|
|
84
84
|
veto?: boolean;
|
|
85
85
|
}
|
|
86
|
+
/** Hears each `HookNote` as it is made, the one signature every function that raises them takes. */
|
|
87
|
+
export type OnNote = (note: HookNote) => void;
|
|
86
88
|
/**
|
|
87
89
|
* One hook's line for whoever is watching: the context it added, or why it added none. A hook
|
|
88
90
|
* that worked and added nothing gets no note — a remember that succeeded is not news.
|
|
@@ -105,6 +107,7 @@ export interface HookNote {
|
|
|
105
107
|
* Runs one event's hooks. Should resolve rather than reject — a hook failing is an outcome — but
|
|
106
108
|
* `gather` and `notify` survive one that does not.
|
|
107
109
|
*
|
|
110
|
+
* @remarks
|
|
108
111
|
* The pool's `runHooks` fits as it is; wrap it to pass its scope or `onNotice`.
|
|
109
112
|
*/
|
|
110
113
|
export type HookRunner = (event: HookEvent, context: HookContext, options: {
|
|
@@ -119,6 +122,7 @@ export interface Gathered {
|
|
|
119
122
|
/**
|
|
120
123
|
* The most context all of a request's hooks add between them by default, in estimated tokens.
|
|
121
124
|
*
|
|
125
|
+
* @remarks
|
|
122
126
|
* Enough for a handful of recalled memories, and small against any window worth running an agent
|
|
123
127
|
* in. The point is that a generous hook cannot crowd out the conversation it was meant to inform.
|
|
124
128
|
* `configureHooks` moves it for a process, and `gather` and `assembleContext` for one request.
|
|
@@ -147,16 +151,17 @@ export interface HookOptions {
|
|
|
147
151
|
* Changes what hooks are held to, for a process whose windows are not the size these defaults
|
|
148
152
|
* were chosen for, or whose host wants its own name above the context.
|
|
149
153
|
*
|
|
150
|
-
*
|
|
151
|
-
* deployment's settings, said once at startup. A caller that sizes the budget per model or per agent — a 128k
|
|
152
|
-
* window can afford more recall than an 8k one — passes `maxTokens` to `gather` instead, and a
|
|
153
|
-
* `preface` passed to `withContext` or `runAgentLoop`'s hooks wins over this one the same way.
|
|
154
|
-
*
|
|
155
|
-
* @param options The settings to change. A field left out keeps what it has, and so does one given
|
|
154
|
+
* @param [options] - The settings to change. A field left out keeps what it has, and so does one given
|
|
156
155
|
* the wrong kind of value — `contextTokens` anything but a number above zero, `preface` anything
|
|
157
156
|
* but a string — so a half-built config narrows nothing. `Infinity` is a number above zero, and
|
|
158
157
|
* lifts the shared budget entirely. An empty `preface` is a string, and turns the preface off.
|
|
159
158
|
* @returns Everything in force afterwards, including what this call did not change.
|
|
159
|
+
*
|
|
160
|
+
* @remarks
|
|
161
|
+
* One setting per runtime for the same reason `configureEvents` is: a budget and a preface are a
|
|
162
|
+
* deployment's settings, said once at startup. A caller that sizes the budget per model or per agent — a 128k
|
|
163
|
+
* window can afford more recall than an 8k one — passes `maxTokens` to `gather` instead, and a
|
|
164
|
+
* `preface` passed to `withContext` or `runAgentLoop`'s hooks wins over this one the same way.
|
|
160
165
|
*/
|
|
161
166
|
export declare function configureHooks(options?: HookOptions): Required<HookOptions>;
|
|
162
167
|
/**
|
|
@@ -168,6 +173,14 @@ export declare const resetHooks: () => void;
|
|
|
168
173
|
/**
|
|
169
174
|
* Builds the context a set of outcomes adds and the notes that go with it.
|
|
170
175
|
*
|
|
176
|
+
* @param outcomes - What the runners returned. An injecting outcome on an event that cannot inject
|
|
177
|
+
* adds nothing; a failed one is noted wherever it falls, including past the budget.
|
|
178
|
+
* @param [maxTokens] - The budget every block shares. Absent, or not a number above zero, is what
|
|
179
|
+
* `configureHooks` last set — `HOOK_CONTEXT_TOKENS` unless something moved it.
|
|
180
|
+
* @returns The blocks joined by a blank line — an empty string when nothing was injected — and the
|
|
181
|
+
* notes in the order of `outcomes`.
|
|
182
|
+
*
|
|
183
|
+
* @remarks
|
|
171
184
|
* Each injected outcome is wrapped in `<context source="…">` naming its label, so a model reading
|
|
172
185
|
* a recalled line can tell it is a memory rather than something the user said. Each is held to
|
|
173
186
|
* its own `maxTokens` and the whole to `maxTokens` here, and a block past the total is dropped
|
|
@@ -177,16 +190,22 @@ export declare const resetHooks: () => void;
|
|
|
177
190
|
*
|
|
178
191
|
* The note keeps each hook's text as it was cut, so a host can show exactly what the model was
|
|
179
192
|
* given without re-deriving the caps or parsing the wrapper back off.
|
|
180
|
-
*
|
|
181
|
-
* @param outcomes What the runners returned. An injecting outcome on an event that cannot inject
|
|
182
|
-
* adds nothing; a failed one is noted wherever it falls, including past the budget.
|
|
183
|
-
* @param maxTokens The budget every block shares. Absent, or not a number above zero, is what
|
|
184
|
-
* `configureHooks` last set — `HOOK_CONTEXT_TOKENS` unless something moved it.
|
|
185
193
|
*/
|
|
186
194
|
export declare function assembleContext(outcomes: readonly HookOutcome[], maxTokens?: number): Gathered;
|
|
187
195
|
/**
|
|
188
196
|
* The request, with the hooks' context added to this turn's question.
|
|
189
197
|
*
|
|
198
|
+
* @param history - The request's messages. Neither the array nor any message in it is changed.
|
|
199
|
+
* @param index - Where the question sits in `history` — which is not where it sits in the
|
|
200
|
+
* session once a compaction has folded the head into a summary. Anything but a user message there
|
|
201
|
+
* leaves the request as it was.
|
|
202
|
+
* @param context - What `assembleContext` built, this turn or the turn the question was asked.
|
|
203
|
+
* Empty returns `history` itself.
|
|
204
|
+
* @param [preface] - Said above the blocks. Empty says nothing, rather than leaving a blank line
|
|
205
|
+
* where it was.
|
|
206
|
+
* @returns `history` when there was nothing to add or nowhere to add it, otherwise a new array.
|
|
207
|
+
*
|
|
208
|
+
* @remarks
|
|
190
209
|
* It goes on the question and not in the system prompt, because it is about the question — and a
|
|
191
210
|
* system prompt that changed every turn would miss the prompt cache every turn. Nothing is written
|
|
192
211
|
* back: a host that stores what the user typed never remembers the context as something they said.
|
|
@@ -195,21 +214,12 @@ export declare function assembleContext(outcomes: readonly HookOutcome[], maxTok
|
|
|
195
214
|
* it was said under, beside the question and calls this for each stored one on every later request
|
|
196
215
|
* — a question sent with its blocks one turn and bare the next is a different prompt from that
|
|
197
216
|
* message on, and loses the server's prefix cache behind it.
|
|
198
|
-
*
|
|
199
|
-
* @param history The request's messages. Neither the array nor any message in it is changed.
|
|
200
|
-
* @param index Where the question sits in `history` — which is not where it sits in the
|
|
201
|
-
* session once a compaction has folded the head into a summary. Anything but a user message there
|
|
202
|
-
* leaves the request as it was.
|
|
203
|
-
* @param context What `assembleContext` built, this turn or the turn the question was asked.
|
|
204
|
-
* Empty returns `history` itself.
|
|
205
|
-
* @param preface Said above the blocks. Absent is what `configureHooks` last set — `HOOK_PREFACE`
|
|
206
|
-
* unless something moved it. Empty says nothing, rather than leaving a blank line where it was.
|
|
207
|
-
* @returns `history` when there was nothing to add or nowhere to add it, otherwise a new array.
|
|
208
217
|
*/
|
|
209
218
|
export declare function withContext(history: OpenAI.ChatCompletionMessageParam[], index: number, context: string, preface?: string): OpenAI.ChatCompletionMessageParam[];
|
|
210
219
|
/**
|
|
211
220
|
* One sentence for a system prompt, saying what an `untrusted` block is.
|
|
212
221
|
*
|
|
222
|
+
* @remarks
|
|
213
223
|
* It belongs in the system prompt rather than beside each block, because it is a standing rule
|
|
214
224
|
* about every block the session will ever carry, and said once there it costs the prompt cache
|
|
215
225
|
* nothing. Like `HOOK_PREFACE` it names no host.
|
|
@@ -219,6 +229,12 @@ export declare const UNTRUSTED_PREFACE: string;
|
|
|
219
229
|
* Fences text nobody trusted — a fetched page, an email, a submitted card, a tool result — so the
|
|
220
230
|
* model can see where it starts and ends and read it as data rather than as instructions.
|
|
221
231
|
*
|
|
232
|
+
* @param text - What came in. Kept whole, apart from the escaped tags.
|
|
233
|
+
* @param [options] - `source` names where it came from, for the model and for whoever reads the
|
|
234
|
+
* transcript later — a URL, a sender, a tool's name. Left out, the block carries no attribute.
|
|
235
|
+
* @returns The block, with the text on its own lines between the tags.
|
|
236
|
+
*
|
|
237
|
+
* @remarks
|
|
222
238
|
* A fence the text can close is no fence, so every `untrusted` tag inside it, opening or closing
|
|
223
239
|
* and in any case, has its `<` escaped: a page that writes `</untrusted>` and then an instruction
|
|
224
240
|
* leaves that instruction inside the block where it began. Nothing else is touched, so the text
|
|
@@ -226,11 +242,6 @@ export declare const UNTRUSTED_PREFACE: string;
|
|
|
226
242
|
*
|
|
227
243
|
* This is one layer and not a defence on its own. A model can still be talked out of a fence it
|
|
228
244
|
* can see; what the text is allowed to make the agent do is the tool policy's to decide.
|
|
229
|
-
*
|
|
230
|
-
* @param text What came in. Kept whole, apart from the escaped tags.
|
|
231
|
-
* @param options `source` names where it came from, for the model and for whoever reads the
|
|
232
|
-
* transcript later — a URL, a sender, a tool's name. Left out, the block carries no attribute.
|
|
233
|
-
* @returns The block, with the text on its own lines between the tags.
|
|
234
245
|
*/
|
|
235
246
|
export declare function untrusted(text: string, { source }?: {
|
|
236
247
|
source?: string;
|
|
@@ -238,19 +249,34 @@ export declare function untrusted(text: string, { source }?: {
|
|
|
238
249
|
/**
|
|
239
250
|
* A message's text, whether its content is a string or a list of parts.
|
|
240
251
|
*
|
|
252
|
+
* @param content - A message's `content`, in any of the shapes the API allows. One that is neither
|
|
253
|
+
* a string nor a list reads as empty.
|
|
254
|
+
* @returns The text, untrimmed. A string comes back as it is, and a list with no text part is
|
|
255
|
+
* empty.
|
|
256
|
+
*
|
|
257
|
+
* @remarks
|
|
241
258
|
* Parts are joined with nothing between them, because they are one text an API split rather than
|
|
242
259
|
* several: a space put in is a character the sender never wrote, and `turnMessages` hashes this
|
|
243
260
|
* into the uuid a memory server dedups on. Compaction reads the same function, so the summariser
|
|
244
261
|
* and the hook told about a fold see one message the same way. A refusal part is left out.
|
|
245
|
-
*
|
|
246
|
-
* @param content A message's `content`, in any of the shapes the API allows. One that is neither
|
|
247
|
-
* a string nor a list reads as empty.
|
|
248
262
|
*/
|
|
249
263
|
export declare const textOf: (content: unknown) => string;
|
|
250
264
|
/**
|
|
251
265
|
* A stretch of a transcript as a hook reads it: what the user and the assistant said, and nothing
|
|
252
266
|
* else.
|
|
253
267
|
*
|
|
268
|
+
* @param sessionId - Prefixes every uuid, so two sessions never share one.
|
|
269
|
+
* @param messages - The transcript, in whatever shape the host stores it, so long as each message
|
|
270
|
+
* has an OpenAI-style `role` and `content`.
|
|
271
|
+
* @param from - The first index, inclusive. Below zero reads from the start.
|
|
272
|
+
* @param [to] - The end, exclusive. Absent, or past the end, reads to the end.
|
|
273
|
+
* @param [options] - `offset` is what the array's first message is numbered as in the uuids — the
|
|
274
|
+
* stored index of `messages[0]`, when `messages` is a request a fold has shifted. Zero numbers
|
|
275
|
+
* by position. `from` and `to` stay array indexes either way.
|
|
276
|
+
* @returns One entry per user or assistant message in the range that has text once trimmed, in
|
|
277
|
+
* transcript order. Empty when there is none.
|
|
278
|
+
*
|
|
279
|
+
* @remarks
|
|
254
280
|
* Tool calls and their results are left out. They are the model's working rather than the
|
|
255
281
|
* conversation, and most of a transcript's characters; a memory server that filed them would
|
|
256
282
|
* recall a directory listing ahead of the decision it led to.
|
|
@@ -267,15 +293,6 @@ export declare const textOf: (content: unknown) => string;
|
|
|
267
293
|
* and again when it is compacted, would arrive under two uuids and be remembered twice. `offset`
|
|
268
294
|
* is what puts the numbering back on the host's own indexes; passing the stored transcript rather
|
|
269
295
|
* than the request avoids the question entirely.
|
|
270
|
-
*
|
|
271
|
-
* @param sessionId Prefixes every uuid, so two sessions never share one.
|
|
272
|
-
* @param messages The transcript, in whatever shape the host stores it, so long as each message
|
|
273
|
-
* has an OpenAI-style `role` and `content`.
|
|
274
|
-
* @param from The first index, inclusive. Below zero reads from the start.
|
|
275
|
-
* @param to The end, exclusive. Absent, or past the end, reads to the end.
|
|
276
|
-
* @param options `offset` is what the array's first message is numbered as in the uuids — the
|
|
277
|
-
* stored index of `messages[0]`, when `messages` is a request a fold has shifted. Zero by default,
|
|
278
|
-
* which numbers by position as before. `from` and `to` stay array indexes either way.
|
|
279
296
|
*/
|
|
280
297
|
export declare function turnMessages(sessionId: string, messages: readonly {
|
|
281
298
|
role: string;
|
|
@@ -286,15 +303,16 @@ export declare function turnMessages(sessionId: string, messages: readonly {
|
|
|
286
303
|
/**
|
|
287
304
|
* Which turn of a session begins at a point, from 0: the user messages ahead of it.
|
|
288
305
|
*
|
|
306
|
+
* @param messages - The transcript.
|
|
307
|
+
* @param [before] - Where the turn begins.
|
|
308
|
+
* @param [offset] - Turns already folded away and so not in `messages`.
|
|
309
|
+
* @returns `offset` plus the count of user messages before `before`.
|
|
310
|
+
*
|
|
311
|
+
* @remarks
|
|
289
312
|
* Counted over what it is given, which is the session only while nothing has been folded away — a
|
|
290
313
|
* compacted request has lost the questions the summary now stands for, and turn eleven counting
|
|
291
314
|
* itself as turn two is the kind of thing a hook writes into a memory. Count over the stored
|
|
292
315
|
* transcript, or add what the fold took as `offset`.
|
|
293
|
-
*
|
|
294
|
-
* @param messages The transcript.
|
|
295
|
-
* @param before Where the turn begins. Absent is the end, which is the index of a turn whose
|
|
296
|
-
* question has not been appended yet.
|
|
297
|
-
* @param offset Turns already folded away and so not in `messages`. Zero by default.
|
|
298
316
|
*/
|
|
299
317
|
export declare const turnIndex: (messages: readonly {
|
|
300
318
|
role: string;
|
|
@@ -302,59 +320,64 @@ export declare const turnIndex: (messages: readonly {
|
|
|
302
320
|
/**
|
|
303
321
|
* Runs the hooks ahead of a request and builds what they add to it.
|
|
304
322
|
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
* rejects outright is noted once for its event, with an empty `hookId` and `source`, and the rest
|
|
308
|
-
* go ahead. Bounding each hook's time is the runner's job; `signal` is how the turn ends all of
|
|
309
|
-
* them.
|
|
310
|
-
*
|
|
311
|
-
* @param run Runs one event's hooks.
|
|
312
|
-
* @param events Which to run: `["beforeTurn"]` ordinarily, and `sessionStart` ahead of it on a
|
|
323
|
+
* @param run - Runs one event's hooks.
|
|
324
|
+
* @param events - Which to run: `["beforeTurn"]` ordinarily, and `sessionStart` ahead of it on a
|
|
313
325
|
* session's first turn. The outcomes are assembled in this order, so it is also the order the
|
|
314
326
|
* budget is spent in.
|
|
315
|
-
* @param context What the hooks are told.
|
|
316
|
-
* @param options `signal` is handed to the runner, and should be the turn's own: a user who
|
|
327
|
+
* @param context - What the hooks are told.
|
|
328
|
+
* @param [options] - `signal` is handed to the runner, and should be the turn's own: a user who
|
|
317
329
|
* stopped the turn stopped its recall. `onNote` hears each note as the whole is assembled.
|
|
318
330
|
* `maxTokens` is the shared budget for this request, read as `assembleContext` reads it: absent
|
|
319
331
|
* or unusable is the process's, from `configureHooks`.
|
|
332
|
+
* @returns What `assembleContext` built from every event's outcomes together. Does not reject for a
|
|
333
|
+
* runner that did.
|
|
334
|
+
*
|
|
335
|
+
* @remarks
|
|
336
|
+
* This is on the path of the first token, so the events run together rather than one after the
|
|
337
|
+
* other, and a hook that fails costs the turn its context and never the turn — a runner that
|
|
338
|
+
* rejects outright is noted once for its event, with an empty `hookId` and `source`, and the rest
|
|
339
|
+
* go ahead. Bounding each hook's time is the runner's job; `signal` is how the turn ends all of
|
|
340
|
+
* them.
|
|
320
341
|
*/
|
|
321
|
-
export declare function gather(run: HookRunner, events: readonly HookEvent[], context: HookContext, { signal, onNote, maxTokens
|
|
342
|
+
export declare function gather(run: HookRunner, events: readonly HookEvent[], context: HookContext, { signal, onNote, maxTokens }?: {
|
|
322
343
|
signal?: AbortSignal;
|
|
323
|
-
onNote?:
|
|
344
|
+
onNote?: OnNote;
|
|
324
345
|
maxTokens?: number;
|
|
325
346
|
}): Promise<Gathered>;
|
|
326
347
|
/**
|
|
327
348
|
* Runs the hooks for an event that reads what happened and adds nothing to a request. Never
|
|
328
349
|
* rejects, so a host can fire it without awaiting it.
|
|
329
350
|
*
|
|
351
|
+
* @param run - Runs the event's hooks.
|
|
352
|
+
* @param event - `afterTurn`, `beforeCompact`, `sessionEnd` or `sessionDelete`. An injecting event
|
|
353
|
+
* works too, but what its hooks return is dropped, since there is no request here to add it to.
|
|
354
|
+
* @param context - What the hooks are told.
|
|
355
|
+
* @param [onNote] - Hears each note — which, with nothing injected, is only ever a failure.
|
|
356
|
+
* @returns The same notes.
|
|
357
|
+
*
|
|
358
|
+
* @remarks
|
|
330
359
|
* No signal: these run once the turn has been answered, and a reader who stops listening at that
|
|
331
360
|
* point has not asked for the turn not to be remembered. Nor is a `veto` read, since whatever it
|
|
332
361
|
* would stop is already under way; `consult` is the one that waits for it.
|
|
333
|
-
*
|
|
334
|
-
* @param run Runs the event's hooks.
|
|
335
|
-
* @param event `afterTurn`, `beforeCompact`, `sessionEnd` or `sessionDelete`. An injecting event
|
|
336
|
-
* works too, but what its hooks return is dropped, since there is no request here to add it to.
|
|
337
|
-
* @param context What the hooks are told.
|
|
338
|
-
* @param onNote Hears each note — which, with nothing injected, is only ever a failure.
|
|
339
|
-
* @returns The same notes.
|
|
340
362
|
*/
|
|
341
|
-
export declare function notify(run: HookRunner, event: HookEvent, context: HookContext, onNote?:
|
|
363
|
+
export declare function notify(run: HookRunner, event: HookEvent, context: HookContext, onNote?: OnNote): Promise<HookNote[]>;
|
|
342
364
|
/**
|
|
343
365
|
* Runs an event's hooks and waits for their say, for a host that will hold off when one of them
|
|
344
366
|
* vetoes.
|
|
345
367
|
*
|
|
368
|
+
* @param run - Runs the event's hooks.
|
|
369
|
+
* @param event - What is about to happen. Only `beforeCompact` has anything a veto can stop.
|
|
370
|
+
* @param context - What the hooks are told.
|
|
371
|
+
* @param [onNote] - Hears each note: every failure, and every veto, naming the hook that made it.
|
|
372
|
+
* @returns The same notes, and `vetoed` when any `ok` outcome carried `veto`.
|
|
373
|
+
*
|
|
374
|
+
* @remarks
|
|
346
375
|
* `notify` runs beside the thing it announces and cannot stop it; this runs ahead of it, so each
|
|
347
376
|
* hook's time is added to whatever waits on the answer. A host that does not mean to act on a
|
|
348
377
|
* veto should call `notify` instead. Never rejects: a runner that throws is noted as a failure,
|
|
349
378
|
* and a failure is not a veto — a memory server that is down has not asked for anything.
|
|
350
|
-
*
|
|
351
|
-
* @param run Runs the event's hooks.
|
|
352
|
-
* @param event What is about to happen. Only `beforeCompact` has anything a veto can stop.
|
|
353
|
-
* @param context What the hooks are told.
|
|
354
|
-
* @param onNote Hears each note: every failure, and every veto, naming the hook that made it.
|
|
355
|
-
* @returns The same notes, and `vetoed` when any `ok` outcome carried `veto`.
|
|
356
379
|
*/
|
|
357
|
-
export declare function consult(run: HookRunner, event: HookEvent, context: HookContext, onNote?:
|
|
380
|
+
export declare function consult(run: HookRunner, event: HookEvent, context: HookContext, onNote?: OnNote): Promise<{
|
|
358
381
|
notes: HookNote[];
|
|
359
382
|
vetoed: boolean;
|
|
360
383
|
}>;
|