@theoremjs/agents 0.3.4-next.407.gd93ec2c → 0.3.4-next.413.gb7a2b75
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/esm/src/interface/blocks.js +71 -44
- package/esm/src/interface/history.js +7 -0
- package/esm/src/kernel/engine/runner/stages.d.ts +0 -2
- package/esm/src/kernel/engine/runner/stages.js +1 -0
- package/esm/src/kernel/stages.d.ts +8 -5
- package/esm/src/kernel/stages.js +2 -2
- package/esm/src/kernel/turn-events.d.ts +10 -4
- package/esm/src/kernel/turn-events.js +1 -1
- package/esm/src/kernel/types.d.ts +2 -2
- package/package.json +1 -1
|
@@ -152,6 +152,36 @@ function appendPromotedToolMedia(blocks, tool, idPrefix, seenUrls) {
|
|
|
152
152
|
});
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* A named inject's user messages as the user's own blocks, where the reply took them in: its
|
|
157
|
+
* text, then a block per file. A message from anyone else (a host's note) is not the user's to show.
|
|
158
|
+
*/
|
|
159
|
+
function injectedBlocks(inject, idPrefix) {
|
|
160
|
+
return inject.messages.flatMap((message) => {
|
|
161
|
+
if (message.role !== 'user')
|
|
162
|
+
return [];
|
|
163
|
+
const parts = message.parts ?? [];
|
|
164
|
+
const text = [message.content ?? '', ...parts.map((part) => ('text' in part ? part.text : ''))]
|
|
165
|
+
.join('')
|
|
166
|
+
.trim();
|
|
167
|
+
return [
|
|
168
|
+
...(text ? [{ id: nextBlockId(idPrefix), kind: 'user-text', text }] : []),
|
|
169
|
+
...parts.flatMap((part) => 'text' in part
|
|
170
|
+
? []
|
|
171
|
+
: [
|
|
172
|
+
{
|
|
173
|
+
id: nextBlockId(idPrefix),
|
|
174
|
+
kind: part.type === 'audio' ? 'user-voice' : 'user-attachment',
|
|
175
|
+
name: part.mimeType,
|
|
176
|
+
mimeType: part.mimeType,
|
|
177
|
+
...('data' in part
|
|
178
|
+
? { sizeBytes: Math.floor((part.data.length * 3) / 4), data: part.data }
|
|
179
|
+
: { sizeBytes: 0 }),
|
|
180
|
+
},
|
|
181
|
+
]),
|
|
182
|
+
];
|
|
183
|
+
});
|
|
184
|
+
}
|
|
155
185
|
/** Turns a user draft into transcript blocks: a `user-text` block for the trimmed text, then one block per attachment and per voice clip. */
|
|
156
186
|
function buildUserTurnBlocks(draft, idPrefix = 'user') {
|
|
157
187
|
const blocks = [];
|
|
@@ -185,6 +215,39 @@ function buildUserTurnBlocks(draft, idPrefix = 'user') {
|
|
|
185
215
|
}
|
|
186
216
|
return blocks;
|
|
187
217
|
}
|
|
218
|
+
/** The block an event adds on its own, beside the blocks before it; `undefined` for one that adds none. */
|
|
219
|
+
function standaloneBlock(event, idPrefix) {
|
|
220
|
+
switch (event.type) {
|
|
221
|
+
case 'media':
|
|
222
|
+
return event.media
|
|
223
|
+
? {
|
|
224
|
+
id: nextBlockId(idPrefix),
|
|
225
|
+
kind: 'media',
|
|
226
|
+
mimeType: event.media.mimeType,
|
|
227
|
+
data: event.media.data,
|
|
228
|
+
}
|
|
229
|
+
: undefined;
|
|
230
|
+
case 'grounding':
|
|
231
|
+
return { id: nextBlockId(idPrefix), kind: 'grounding', grounding: event.grounding };
|
|
232
|
+
case 'evidence':
|
|
233
|
+
return { id: nextBlockId(idPrefix), kind: 'evidence', evidence: event.evidence };
|
|
234
|
+
case 'error':
|
|
235
|
+
return event.error
|
|
236
|
+
? { id: nextBlockId(idPrefix), kind: 'error', message: event.error }
|
|
237
|
+
: undefined;
|
|
238
|
+
case 'done':
|
|
239
|
+
return {
|
|
240
|
+
id: nextBlockId(idPrefix),
|
|
241
|
+
kind: 'turn-done',
|
|
242
|
+
stop: event.stop,
|
|
243
|
+
tokens: event.tokens,
|
|
244
|
+
interactionId: event.interactionId,
|
|
245
|
+
compaction: event.compaction !== undefined,
|
|
246
|
+
};
|
|
247
|
+
default:
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
188
251
|
/** Resets only the turn id sequence, so streaming refolds keep stable `turn-*` keys. */
|
|
189
252
|
function foldTurnEvents(events, options = {}) {
|
|
190
253
|
const idPrefix = options.idPrefix ?? 'turn';
|
|
@@ -217,33 +280,9 @@ function foldTurnEvents(events, options = {}) {
|
|
|
217
280
|
case 'structured':
|
|
218
281
|
settleStructured(blocks, event.structured, idPrefix);
|
|
219
282
|
break;
|
|
220
|
-
case 'media':
|
|
221
|
-
if (event.media) {
|
|
222
|
-
blocks.push({
|
|
223
|
-
id: nextBlockId(idPrefix),
|
|
224
|
-
kind: 'media',
|
|
225
|
-
mimeType: event.media.mimeType,
|
|
226
|
-
data: event.media.data,
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
break;
|
|
230
|
-
case 'grounding':
|
|
231
|
-
blocks.push({
|
|
232
|
-
id: nextBlockId(idPrefix),
|
|
233
|
-
kind: 'grounding',
|
|
234
|
-
grounding: event.grounding,
|
|
235
|
-
});
|
|
236
|
-
break;
|
|
237
283
|
case 'citation':
|
|
238
284
|
foldCitation(blocks, event, idPrefix);
|
|
239
285
|
break;
|
|
240
|
-
case 'evidence':
|
|
241
|
-
blocks.push({
|
|
242
|
-
id: nextBlockId(idPrefix),
|
|
243
|
-
kind: 'evidence',
|
|
244
|
-
evidence: event.evidence,
|
|
245
|
-
});
|
|
246
|
-
break;
|
|
247
286
|
case 'guardrail':
|
|
248
287
|
addGuardrailBlock(blocks, {
|
|
249
288
|
id: nextBlockId(idPrefix),
|
|
@@ -251,27 +290,15 @@ function foldTurnEvents(events, options = {}) {
|
|
|
251
290
|
guardrail: event.guardrail,
|
|
252
291
|
});
|
|
253
292
|
break;
|
|
254
|
-
case '
|
|
255
|
-
|
|
256
|
-
blocks.push(
|
|
257
|
-
id: nextBlockId(idPrefix),
|
|
258
|
-
kind: 'error',
|
|
259
|
-
message: event.error,
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
break;
|
|
263
|
-
case 'done':
|
|
264
|
-
blocks.push({
|
|
265
|
-
id: nextBlockId(idPrefix),
|
|
266
|
-
kind: 'turn-done',
|
|
267
|
-
stop: event.stop,
|
|
268
|
-
tokens: event.tokens,
|
|
269
|
-
interactionId: event.interactionId,
|
|
270
|
-
compaction: event.compaction !== undefined,
|
|
271
|
-
});
|
|
272
|
-
break;
|
|
273
|
-
default:
|
|
293
|
+
case 'stage':
|
|
294
|
+
for (const steer of event.injected ?? [])
|
|
295
|
+
blocks.push(...injectedBlocks(steer, idPrefix));
|
|
274
296
|
break;
|
|
297
|
+
default: {
|
|
298
|
+
const block = standaloneBlock(event, idPrefix);
|
|
299
|
+
if (block)
|
|
300
|
+
blocks.push(block);
|
|
301
|
+
}
|
|
275
302
|
}
|
|
276
303
|
}
|
|
277
304
|
return blocks;
|
|
@@ -165,6 +165,13 @@ function foldAssistantEvents(history, events, gated) {
|
|
|
165
165
|
textBuf += event.text;
|
|
166
166
|
continue;
|
|
167
167
|
}
|
|
168
|
+
if (event.type === 'stage' && event.injected) {
|
|
169
|
+
// why: A steer is a message in the conversation, after what the reply said and did before it.
|
|
170
|
+
flushStep();
|
|
171
|
+
flushText();
|
|
172
|
+
next = [...next, ...event.injected.flatMap((inject) => inject.messages)];
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
168
175
|
if (event.type === 'structured' && event.structured !== undefined) {
|
|
169
176
|
flushStep();
|
|
170
177
|
// why: The streamed text is this reply's JSON as the model wrote it; the structured output is the reply as kept.
|
|
@@ -12,8 +12,6 @@ export interface ApplyTurnStageArgs extends StageCallBag {
|
|
|
12
12
|
/** Another provider step would exceed maxSteps — reject inject. */
|
|
13
13
|
injectWouldExceedMaxSteps?: boolean;
|
|
14
14
|
host?: unknown;
|
|
15
|
-
/** `before_end`: the answer the model just wrote, which goes into turn history ahead of an inject. */
|
|
16
|
-
reply?: readonly TurnHistoryMessage[];
|
|
17
15
|
/** Where that answer's text begins in the attempt's reply. */
|
|
18
16
|
replyAt?: number;
|
|
19
17
|
}
|
|
@@ -2,7 +2,7 @@ import type { SpanHandle } from '../observability/trace-span.js';
|
|
|
2
2
|
import type { StageApplyWarningCode, TurnStage } from './schema.js';
|
|
3
3
|
import type { TurnStop } from './stop.js';
|
|
4
4
|
import type { ModelToolResult, ToolFailure, ToolGate } from './tools/types.js';
|
|
5
|
-
import type { AwaitingUserInput, StageApplyWarning, TurnEventOf } from './turn-events.js';
|
|
5
|
+
import type { AwaitingUserInput, InjectedMessages, StageApplyWarning, TurnEventOf } from './turn-events.js';
|
|
6
6
|
import type { Profile, TurnEvent, TurnHistoryMessage } from './types.js';
|
|
7
7
|
export type { AwaitingUserInput, ToolGate };
|
|
8
8
|
/**
|
|
@@ -37,6 +37,11 @@ export type StageCallBag = {
|
|
|
37
37
|
awaiting?: boolean;
|
|
38
38
|
stop?: TurnStop;
|
|
39
39
|
gate?: ToolGate;
|
|
40
|
+
/**
|
|
41
|
+
* `before_end` on text: the answer the model just wrote, before any guardrail verdict on it and
|
|
42
|
+
* not yet in `history`. Its last step wrote no text when no message here carries any.
|
|
43
|
+
*/
|
|
44
|
+
reply?: readonly TurnHistoryMessage[];
|
|
40
45
|
};
|
|
41
46
|
/** What a stage handler is given: the stage, the step, and what has happened so far. */
|
|
42
47
|
export interface StageContext extends StageCallBag {
|
|
@@ -145,9 +150,7 @@ export type StageEventExtra = {
|
|
|
145
150
|
awaiting?: boolean;
|
|
146
151
|
gate?: ToolGate;
|
|
147
152
|
stop?: TurnStop;
|
|
148
|
-
injected?:
|
|
149
|
-
id: string;
|
|
150
|
-
}[];
|
|
153
|
+
injected?: InjectedMessages[];
|
|
151
154
|
released?: number;
|
|
152
155
|
};
|
|
153
156
|
/** Build a stream `stage` event. Unknown extra keys are not copied. */
|
|
@@ -155,7 +158,7 @@ export declare function stageEventFields(stage: TurnStage, extra?: Partial<Stage
|
|
|
155
158
|
export declare function injectMessages(units: readonly InjectUnit[]): TurnHistoryMessage[];
|
|
156
159
|
/**
|
|
157
160
|
* The `stage` event recording that `units` landed, naming the ones the host
|
|
158
|
-
* named, and the reply text the user has when they dropped a draft (`released`);
|
|
161
|
+
* named with the messages they put in the conversation, and the reply text the user has when they dropped a draft (`released`);
|
|
159
162
|
* `undefined` when there is neither. Emit it where the messages land, never
|
|
160
163
|
* before: an inject that never lands is never reported.
|
|
161
164
|
*/
|
package/esm/src/kernel/stages.js
CHANGED
|
@@ -328,12 +328,12 @@ export function injectMessages(units) {
|
|
|
328
328
|
}
|
|
329
329
|
/**
|
|
330
330
|
* The `stage` event recording that `units` landed, naming the ones the host
|
|
331
|
-
* named, and the reply text the user has when they dropped a draft (`released`);
|
|
331
|
+
* named with the messages they put in the conversation, and the reply text the user has when they dropped a draft (`released`);
|
|
332
332
|
* `undefined` when there is neither. Emit it where the messages land, never
|
|
333
333
|
* before: an inject that never lands is never reported.
|
|
334
334
|
*/
|
|
335
335
|
export function injectedStageEvent(stage, units, extra) {
|
|
336
|
-
const injected = units.flatMap((unit) =>
|
|
336
|
+
const injected = units.flatMap((unit) => unit.id === undefined ? [] : [{ id: unit.id, messages: unit.messages }]);
|
|
337
337
|
if (injected.length === 0 && extra?.released === undefined)
|
|
338
338
|
return undefined;
|
|
339
339
|
return stageEventFields(stage, { ...extra, ...(injected.length > 0 ? { injected } : {}) });
|
|
@@ -67,6 +67,14 @@ export interface TurnHistoryMessage {
|
|
|
67
67
|
}
|
|
68
68
|
/** The schema a history message parses against. */
|
|
69
69
|
export declare const turnHistoryMessageSchema: z.ZodType<TurnHistoryMessage>;
|
|
70
|
+
/**
|
|
71
|
+
* A named inject as it landed: the host's id for it and the messages it added to the conversation,
|
|
72
|
+
* after the `injected` guardrails, so a steer reads as the model read it.
|
|
73
|
+
*/
|
|
74
|
+
export interface InjectedMessages {
|
|
75
|
+
id: string;
|
|
76
|
+
messages: TurnHistoryMessage[];
|
|
77
|
+
}
|
|
70
78
|
/** Why a turn or live utterance ended. */
|
|
71
79
|
export interface TurnStop {
|
|
72
80
|
kind: TurnStopKind;
|
|
@@ -686,10 +694,8 @@ export type TurnEvent = {
|
|
|
686
694
|
stop?: TurnStop;
|
|
687
695
|
/** Stage result fields the kernel dropped. */
|
|
688
696
|
stageWarnings?: StageApplyWarning[];
|
|
689
|
-
/** The named injects (`StageResult.injectId`) that landed in the conversation at this stage. */
|
|
690
|
-
injected?:
|
|
691
|
-
id: string;
|
|
692
|
-
}[];
|
|
697
|
+
/** The named injects (`StageResult.injectId`) that landed in the conversation at this stage, each with the messages it added. */
|
|
698
|
+
injected?: InjectedMessages[];
|
|
693
699
|
/**
|
|
694
700
|
* An inject at this stage dropped a draft the user never got: of the reply text since the
|
|
695
701
|
* turn began or its last `attempt`, only the first `released` characters stay the reply.
|
|
@@ -461,7 +461,7 @@ const TURN_EVENTS = {
|
|
|
461
461
|
stop: turnStop.optional(),
|
|
462
462
|
stageWarnings: z.array(stageApplyWarning).optional(),
|
|
463
463
|
injected: z
|
|
464
|
-
.array(z.object({ id: z.string().regex(/\S/) }))
|
|
464
|
+
.array(z.object({ id: z.string().regex(/\S/), messages: z.array(turnHistoryMessage) }))
|
|
465
465
|
.min(1)
|
|
466
466
|
.optional(),
|
|
467
467
|
released: z.number().int().nonnegative().optional(),
|
|
@@ -5,8 +5,8 @@ import type { StageHandler } from './stages.js';
|
|
|
5
5
|
import type { GateDecision } from './tools/gate-answer.js';
|
|
6
6
|
import type { PageToolExecution, ToolExecutionCoordinator } from './tools/operation.js';
|
|
7
7
|
import type { AgentCall, AgentCallHook, AgentCallRequest, AgentToolDef, AgentToolInput, AgentToolOutput, HostProfileToolsSpec, InvokeToolRequest, InvokeToolResume, InvokeToolStepCall, InvokeToolStepRequest, LiveProfileToolsSpec, ModelToolResult, PageAnswer, ProfileToolsSpec, RegisteredTool, ToolCallEvent, ToolFailure, ToolGate, ToolLoadContext, ToolPolicy, TurnToolSnapshot, WireFunctionTool } from './tools/types.js';
|
|
8
|
-
import type { AttemptReason, CallDone, CompactionFailure, CompactionResult, CompactionSignal, DoneFields, GroundingEvent, InteractionMediaPart, InteractionMediaRefPart, InteractionPart, InteractionTextPart, InvalidField, ModelEvent, ProviderEvidence, RemovedItem, SessionEnded, SessionEvent, SessionEventKind, SessionEventOf, Source, TurnCost, TurnEvent, TurnEventOf, TurnEventType, TurnGroundingCount, TurnHistoryMessage, TurnResponse, TurnTokenSide, TurnTokens } from './turn-events.js';
|
|
9
|
-
export type { AgentCall, AgentCallHook, AgentCallRequest, AgentToolDef, AgentToolInput, AgentToolOutput, AttemptReason, CacheMode, CacheTtl, CallDone, CompactionFailure, CompactionMeter, CompactionOutcome, CompactionResult, CompactionSignal, CompactionTiming, ContinueStopKind, DoneFields, FieldMeta, GroundingEvent, HostProfileToolsSpec, InteractionMediaPart, InteractionMediaRefPart, InteractionPart, InteractionTextPart, InvalidField, InvokeToolRequest, InvokeToolResume, InvokeToolStepCall, InvokeToolStepRequest, KeySlot, KeyVault, LiveActivityHandling, LiveEndSensitivity, LiveProfileToolsSpec, LiveStartSensitivity, MediaInputKind, ModelEvent, ProfileToolsSpec, ProfileType, ProviderEvidence, RegisteredTool, RemovedItem, SessionEnded, SessionEvent, SessionEventKind, SessionEventOf, Source, SpeechAudioFormat, StreamMode, SummaryMode, ThinkingLevel, ToolCallEvent, ToolFailure, ToolGate, ToolLoadContext, ToolLoadTier, ToolPolicy, TurnCost, TurnEvent, TurnEventOf, TurnEventType, TurnGroundingCount, TurnHistoryMessage, TurnResponse, TurnStage, TurnStopKind, TurnTokenSide, TurnTokens, TurnToolSnapshot, WireFunctionTool, };
|
|
8
|
+
import type { AttemptReason, CallDone, CompactionFailure, CompactionResult, CompactionSignal, DoneFields, GroundingEvent, InjectedMessages, InteractionMediaPart, InteractionMediaRefPart, InteractionPart, InteractionTextPart, InvalidField, ModelEvent, ProviderEvidence, RemovedItem, SessionEnded, SessionEvent, SessionEventKind, SessionEventOf, Source, TurnCost, TurnEvent, TurnEventOf, TurnEventType, TurnGroundingCount, TurnHistoryMessage, TurnResponse, TurnTokenSide, TurnTokens } from './turn-events.js';
|
|
9
|
+
export type { AgentCall, AgentCallHook, AgentCallRequest, AgentToolDef, AgentToolInput, AgentToolOutput, AttemptReason, CacheMode, CacheTtl, CallDone, CompactionFailure, CompactionMeter, CompactionOutcome, CompactionResult, CompactionSignal, CompactionTiming, ContinueStopKind, DoneFields, FieldMeta, GroundingEvent, HostProfileToolsSpec, InjectedMessages, InteractionMediaPart, InteractionMediaRefPart, InteractionPart, InteractionTextPart, InvalidField, InvokeToolRequest, InvokeToolResume, InvokeToolStepCall, InvokeToolStepRequest, KeySlot, KeyVault, LiveActivityHandling, LiveEndSensitivity, LiveProfileToolsSpec, LiveStartSensitivity, MediaInputKind, ModelEvent, ProfileToolsSpec, ProfileType, ProviderEvidence, RegisteredTool, RemovedItem, SessionEnded, SessionEvent, SessionEventKind, SessionEventOf, Source, SpeechAudioFormat, StreamMode, SummaryMode, ThinkingLevel, ToolCallEvent, ToolFailure, ToolGate, ToolLoadContext, ToolLoadTier, ToolPolicy, TurnCost, TurnEvent, TurnEventOf, TurnEventType, TurnGroundingCount, TurnHistoryMessage, TurnResponse, TurnStage, TurnStopKind, TurnTokenSide, TurnTokens, TurnToolSnapshot, WireFunctionTool, };
|
|
10
10
|
/** A host-chosen key naming one model binding in a profile's `models`. */
|
|
11
11
|
export type ModelId = string;
|
|
12
12
|
/** The id of a provider-side tool such as web search. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theoremjs/agents",
|
|
3
|
-
"version": "0.3.4-next.
|
|
3
|
+
"version": "0.3.4-next.413.gb7a2b75",
|
|
4
4
|
"description": "A flat TypeScript agent kernel for typed profiles, deterministic turn execution, registered tools, provider adapters, guardrails, and host-injected traces.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|