@fifthrevision/axle 0.25.5 → 0.26.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.
@@ -773,6 +773,33 @@ interface ContentPartCitation {
773
773
  providerMetadata?: Record<string, unknown>;
774
774
  }
775
775
  //#endregion
776
+ //#region src/messages/compaction.d.ts
777
+ /**
778
+ * Record of one applied compaction: when it happened. Inspection only —
779
+ * records carry no message content and cannot reconstruct the pre-compaction
780
+ * conversation.
781
+ *
782
+ * @experimental Compaction is under active design and may change in any release.
783
+ */
784
+ interface CompactionRecord {
785
+ /** Stable record id. Shared with the compaction turn. */
786
+ id: string;
787
+ /** ISO timestamp for when the compaction ran. */
788
+ at: string;
789
+ }
790
+ /**
791
+ * Validate that a compacted conversation is structurally well-formed.
792
+ *
793
+ * The messages must stand alone: every tool call must be answered by the
794
+ * tool message(s) immediately following it — providers reject conversations
795
+ * that interleave other messages between a call and its result — and every
796
+ * tool result must answer a preceding call.
797
+ *
798
+ * @experimental Compaction is under active design and may change in any release.
799
+ * @throws AxleError with code `COMPACTION_INVALID_MESSAGES`
800
+ */
801
+ declare function validateCompactedMessages(messages: AxleMessage[]): void;
802
+ //#endregion
776
803
  //#region src/turns/types.d.ts
777
804
  /**
778
805
  * Lifecycle state for a renderable turn.
@@ -859,11 +886,16 @@ interface Turn<TAnnotation extends Annotation = Annotation> {
859
886
  timing?: TimingInfo;
860
887
  /** Token usage accumulated for this turn, when available. */
861
888
  usage?: Stats;
889
+ /** Terminal model or provider error associated with this turn. */
890
+ error?: {
891
+ type: string;
892
+ message: string;
893
+ };
862
894
  }
863
895
  /**
864
896
  * Any renderable part within a turn.
865
897
  */
866
- type TurnPart<TAnnotation extends Annotation = Annotation> = TextPart<TAnnotation> | CitationPart<TAnnotation> | FilePart<TAnnotation> | ThinkingPart<TAnnotation> | ActionPart<TAnnotation>;
898
+ type TurnPart<TAnnotation extends Annotation = Annotation> = TextPart<TAnnotation> | CitationPart<TAnnotation> | FilePart<TAnnotation> | ThinkingPart<TAnnotation> | ActionPart<TAnnotation> | CompactionPart<TAnnotation>;
867
899
  /**
868
900
  * Assistant or user text content.
869
901
  */
@@ -938,6 +970,28 @@ interface ThinkingPart<TAnnotation extends Annotation = Annotation> {
938
970
  /** Optional timing metadata. */
939
971
  timing?: TimingInfo;
940
972
  }
973
+ /**
974
+ * Part marking a compaction of the model-facing conversation.
975
+ *
976
+ * Compaction renders as an agent turn containing this single part. The turn's
977
+ * `status` carries the lifecycle: `"streaming"` while the compaction callback
978
+ * runs, `"complete"` once applied, `"error"` on failure. Skipped compactions
979
+ * are removed from the turns, not settled.
980
+ *
981
+ * @experimental Compaction is under active design and may change in any release.
982
+ */
983
+ interface CompactionPart<TAnnotation extends Annotation = Annotation> {
984
+ /** Stable part id. Shared with the compaction record. */
985
+ id: string;
986
+ /** Part discriminator. */
987
+ type: "compaction";
988
+ /** The applied record, present once the compaction completes. */
989
+ record?: CompactionRecord;
990
+ /** Annotations attached to this part. */
991
+ annotations?: TAnnotation[];
992
+ /** Optional timing metadata. */
993
+ timing?: TimingInfo;
994
+ }
941
995
  /**
942
996
  * Shared fields for tool, subagent, and provider-managed actions.
943
997
  *
@@ -1056,6 +1110,16 @@ type TurnEvent<TAnnotation extends Annotation = Annotation> = {
1056
1110
  status: TurnStatus;
1057
1111
  usage: Stats;
1058
1112
  timing?: TimingInfo;
1113
+ } | {
1114
+ type: "compaction:start";
1115
+ id: string;
1116
+ timing?: TimingInfo;
1117
+ } | {
1118
+ type: "compaction:end";
1119
+ id: string;
1120
+ outcome: "complete" | "skipped" | "error";
1121
+ record?: CompactionRecord;
1122
+ timing?: TimingInfo;
1059
1123
  } | {
1060
1124
  type: "part:start";
1061
1125
  turnId: string;
@@ -1130,6 +1194,7 @@ type TurnEvent<TAnnotation extends Annotation = Annotation> = {
1130
1194
  event: TurnEvent<TAnnotation>;
1131
1195
  } | AnnotationEvent<TAnnotation> | {
1132
1196
  type: "error";
1197
+ turnId?: string;
1133
1198
  error: {
1134
1199
  type: string;
1135
1200
  message: string;
@@ -1222,6 +1287,7 @@ declare class TurnAccumulator<TAnnotation extends Annotation = Annotation, THost
1222
1287
  constructor(init?: TurnAccumulatorState<TAnnotation>);
1223
1288
  get state(): TurnAccumulatorState<TAnnotation>;
1224
1289
  apply(event: AccumulatableEvent<TAnnotation, THostEvent>): TurnAccumulatorResult<TAnnotation, THostEvent>;
1290
+ private applyTurnEvent;
1225
1291
  private replaceState;
1226
1292
  private replaceTurns;
1227
1293
  private updateTurn;
@@ -1231,4 +1297,4 @@ declare class TurnAccumulator<TAnnotation extends Annotation = Annotation, THost
1231
1297
  private handled;
1232
1298
  }
1233
1299
  //#endregion
1234
- export { AxleStopReason as $, TurnPart as A, TokenUsage as At, ContentPart as B, SubagentAction as C, Span as Ct, ToolAction as D, SpanResult as Dt, TimingInfo as E, SpanOptions as Et, AxleToolCallResult as F, ContentPartThinking as G, ContentPartFile as H, AxleUserMessage as I, MessageMetadata as J, ContentPartToolCall as K, Citation as L, AxleAssistantMessage as M, TraceWriter as Mt, AxleMessage as N, Turn as O, SpanStatus as Ot, AxleToolCallMessage as P, AxleModelRequestOptions as Q, CitationOutputSpan as R, ProviderToolAction as S, LLMResult as St, ThinkingPart as T, SpanEvent as Tt, ContentPartProviderTool as U, ContentPartCitation as V, ContentPartText as W, ToolResultPart as X, ThinkingContinuity as Y, AIProvider as Z, Annotation as _, TokenStats as _t, UnknownEvent as a, ResolvedProviderTool as at, CitationPart as b, LLMRequest as bt, ToolContext as c, FileInfo as ct, ToolRegistry as d, FileResolveFormat as dt, ContextUsage as et, AnnotationEvent as f, FileResolveRequest as ft, ActionResult as g, Stats as gt, ActionPart as h, loadFileContent as ht, TurnAccumulatorState as i, ProviderOptions as it, TurnStatus as j, ToolResult as jt, TurnMetadata as k, SpanType as kt, ToolDefinition as l, FileKind as lt, TurnEvent as m, ResolvedFileSource as mt, TurnAccumulator as n, ModelResult as nt, ExecutableTool as o, ToolChoice as ot, AnnotationTarget as p, FileResolver as pt, DocumentLocator as q, TurnAccumulatorResult as r, ProviderClientOptions as rt, ProviderTool as s, DeferredFileInfo as st, AccumulatableEvent as t, ModelError as tt, ToolProgressChunk as u, FileProviderId as ut, AnnotationPlacement as v, UsageEntry as vt, TextPart as w, SpanData as wt, FilePart as x, LLMResponse as xt, AnnotationStatus as y, EventLevel as yt, CitationSource as z };
1300
+ export { ToolResultPart as $, TurnMetadata as A, SpanResult as At, Citation as B, ProviderToolAction as C, LLMRequest as Ct, TimingInfo as D, SpanData as Dt, ThinkingPart as E, Span as Et, AxleAssistantMessage as F, TraceWriter as Ft, ContentPartFile as G, CitationSource as H, AxleMessage as I, ContentPartThinking as J, ContentPartProviderTool as K, AxleToolCallMessage as L, TurnStatus as M, SpanType as Mt, CompactionRecord as N, TokenUsage as Nt, ToolAction as O, SpanEvent as Ot, validateCompactedMessages as P, ToolResult as Pt, ThinkingContinuity as Q, AxleToolCallResult as R, FilePart as S, EventLevel as St, TextPart as T, LLMResult as Tt, ContentPart as U, CitationOutputSpan as V, ContentPartCitation as W, DocumentLocator as X, ContentPartToolCall as Y, MessageMetadata as Z, Annotation as _, ResolvedFileSource as _t, UnknownEvent as a, ModelResult as at, CitationPart as b, TokenStats as bt, ToolContext as c, ResolvedProviderTool as ct, ToolRegistry as d, FileInfo as dt, AIProvider as et, AnnotationEvent as f, FileKind as ft, ActionResult as g, FileResolver as gt, ActionPart as h, FileResolveRequest as ht, TurnAccumulatorState as i, ModelError as it, TurnPart as j, SpanStatus as jt, Turn as k, SpanOptions as kt, ToolDefinition as l, ToolChoice as lt, TurnEvent as m, FileResolveFormat as mt, TurnAccumulator as n, AxleStopReason as nt, ExecutableTool as o, ProviderClientOptions as ot, AnnotationTarget as p, FileProviderId as pt, ContentPartText as q, TurnAccumulatorResult as r, ContextUsage as rt, ProviderTool as s, ProviderOptions as st, AccumulatableEvent as t, AxleModelRequestOptions as tt, ToolProgressChunk as u, DeferredFileInfo as ut, AnnotationPlacement as v, loadFileContent as vt, SubagentAction as w, LLMResponse as wt, CompactionPart as x, UsageEntry as xt, AnnotationStatus as y, Stats as yt, AxleUserMessage as z };
@@ -0,0 +1 @@
1
+ const e=new Set(Object.keys({"session:restore":!0,"turn:user":!0,"turn:start":!0,"turn:end":!0,"compaction:start":!0,"compaction:end":!0,"part:start":!0,"text:delta":!0,"text:citation":!0,"thinking:delta":!0,"thinking:summary-delta":!0,"thinking:update":!0,"part:end":!0,"action:args-delta":!0,"action:running":!0,"action:progress":!0,"action:complete":!0,"action:error":!0,"action:child-event":!0,"annotation:start":!0,"annotation:update":!0,"annotation:end":!0,error:!0}));function t(t){return e.has(t.type)}var n=class e{_state;constructor(e){this._state={turns:e?.turns??[],sessionAnnotations:e?.sessionAnnotations}}get state(){return this._state}apply(e){return t(e)?this.applyTurnEvent(e):{handled:!1,state:this._state,event:e}}applyTurnEvent(t){switch(t.type){case`session:restore`:return this.replaceState({turns:t.turns??[],sessionAnnotations:t.sessionAnnotations},t);case`turn:user`:return this.replaceTurns([...this._state.turns,t.turn],t);case`turn:start`:{let e={id:t.turnId,owner:`agent`,parts:[],status:`streaming`,...t.timing?{timing:t.timing}:{}};return this.replaceTurns([...this._state.turns,e],t)}case`compaction:start`:{let e={id:t.id,owner:`agent`,parts:[{id:t.id,type:`compaction`}],status:`streaming`,...t.timing?{timing:t.timing}:{}};return this.replaceTurns([...this._state.turns,e],t)}case`compaction:end`:{if(t.outcome===`skipped`){let e=this._state.turns.filter(e=>e.id!==t.id);return e.length===this._state.turns.length?this.handled(t):this.replaceTurns(e,t)}let e=t.outcome===`complete`?`complete`:`error`,n=!1,r=this._state.turns.map(r=>r.id===t.id?(n=!0,{...r,status:e,parts:r.parts.map(e=>e.type===`compaction`&&t.record?{...e,record:t.record}:e),timing:t.timing??r.timing}):r);return n?this.replaceTurns(r,t):this.handled(t)}case`part:start`:return this.updateTurn(t.turnId,t,e=>({...e,parts:[...e.parts,t.part]}));case`text:delta`:return this.updatePart(t.turnId,t.partId,t,e=>e.type===`text`?{...e,text:e.text+t.delta}:e);case`text:citation`:return this.updatePart(t.turnId,t.partId,t,e=>e.type===`text`?{...e,citations:[...e.citations??[],t.citation]}:e);case`thinking:delta`:return this.updatePart(t.turnId,t.partId,t,e=>e.type===`thinking`?{...e,text:(e.text??``)+t.delta}:e);case`thinking:summary-delta`:return this.updatePart(t.turnId,t.partId,t,e=>e.type===`thinking`?{...e,summary:(e.summary??``)+t.delta}:e);case`thinking:update`:return this.updatePart(t.turnId,t.partId,t,e=>e.type===`thinking`?{...e,...t.redacted===void 0?{}:{redacted:t.redacted},...t.continuity?{continuity:t.continuity}:{},...t.providerMetadata?{providerMetadata:t.providerMetadata}:{}}:e);case`part:end`:return this.updatePart(t.turnId,t.partId,t,e=>({...e,timing:t.timing??e.timing}));case`action:args-delta`:return this.updatePart(t.turnId,t.partId,t,e=>e.type!==`action`||e.kind!==`tool`?e:{...e,detail:{...e.detail,pendingArgs:t.accumulated}});case`action:running`:return this.updatePart(t.turnId,t.partId,t,e=>{if(e.type!==`action`)return e;if(e.kind===`tool`){let{pendingArgs:n,...r}=e.detail;return{...e,status:`running`,detail:t.parameters?{...r,parameters:t.parameters}:r}}return{...e,status:`running`}});case`action:progress`:return this.updatePart(t.turnId,t.partId,t,e=>{if(e.type!==`action`)return e;let n=e.detail.result,r=n?.type===`in-progress`?n.content:``;return{...e,detail:{...e.detail,result:{type:`in-progress`,content:r+t.chunk}}}});case`action:complete`:return this.updatePart(t.turnId,t.partId,t,e=>e.type===`action`?{...e,status:`complete`,detail:{...e.detail,result:t.result},timing:t.timing??e.timing}:e);case`action:error`:return this.updatePart(t.turnId,t.partId,t,e=>e.type===`action`?{...e,status:`error`,detail:{...e.detail,result:{type:`error`,error:t.error}},timing:t.timing??e.timing}:e);case`turn:end`:return this.updateTurn(t.turnId,t,e=>({...e,status:t.status,usage:t.usage,timing:t.timing??e.timing}));case`annotation:start`:return this.addAnnotation(t);case`annotation:update`:return this.replaceAnnotation(t,!1);case`annotation:end`:return this.replaceAnnotation(t,!0);case`error`:return t.turnId?this.updateTurn(t.turnId,t,e=>({...e,error:t.error})):this.handled(t);case`action:child-event`:return this.updatePart(t.turnId,t.partId,t,n=>{if(n.type!==`action`||n.kind!==`agent`)return n;let r=new e({turns:n.detail.children}).apply(t.event);return{...n,detail:{...n.detail,children:r.state.turns}}});default:return this.handled(t)}}replaceState(e,t){return this._state=e,this.handled(t)}replaceTurns(e,t){return this.replaceState({...this._state,turns:e},t)}updateTurn(e,t,n){let r=!1,i=this._state.turns.map(t=>{if(t.id!==e)return t;let i=n(t);return i===t?t:(r=!0,i)});return r?this.replaceTurns(i,t):this.handled(t)}updatePart(e,t,n,r){return this.updateTurn(e,n,e=>{let n=!1,i=e.parts.map(e=>{if(e.id!==t)return e;let i=r(e);return i===e?e:(n=!0,i)});return n?{...e,parts:i}:e})}addAnnotation(e){let t=e.target,n=r(e.annotation);return n?t.type===`session`?this.replaceState({...this._state,sessionAnnotations:[...this._state.sessionAnnotations??[],n]},e):t.type===`turn`?this.updateTurn(t.turnId,e,e=>({...e,annotations:[...e.annotations??[],n]})):this.updatePart(t.turnId,t.partId,e,e=>({...e,annotations:[...e.annotations??[],n]})):this.handled(e)}replaceAnnotation(e,t){let n=e.target,a=r(e.annotation,t);if(!a)return this.handled(e);if(n.type===`session`){let t=i(this._state.sessionAnnotations,a);return t?this.replaceState({...this._state,sessionAnnotations:t},e):this.handled(e)}return n.type===`turn`?this.updateTurn(n.turnId,e,e=>{let t=i(e.annotations,a);return t?{...e,annotations:t}:e}):this.updatePart(n.turnId,n.partId,e,e=>{let t=i(e.annotations,a);return t?{...e,annotations:t}:e})}handled(e){return{handled:!0,state:this._state,event:e}}};function r(e,t=!1){if(!e)return;let n=t?e.status??`complete`:e.status,r={...e,placement:e.placement??`after`};return n?{...r,status:n}:r}function i(e,t){if(!e)return;let n=!1,r=e.map(e=>e.id===t.id?(n=!0,t):e);return n?r:void 0}export{n as t};
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as AxleStopReason, A as TurnPart, At as TokenUsage, B as ContentPart, C as SubagentAction, Ct as Span, D as ToolAction, Dt as SpanResult, Et as SpanOptions, F as AxleToolCallResult, G as ContentPartThinking, H as ContentPartFile, I as AxleUserMessage, J as MessageMetadata, K as ContentPartToolCall, L as Citation, M as AxleAssistantMessage, Mt as TraceWriter, N as AxleMessage, O as Turn, Ot as SpanStatus, P as AxleToolCallMessage, Q as AxleModelRequestOptions, R as CitationOutputSpan, S as ProviderToolAction, St as LLMResult, T as ThinkingPart, Tt as SpanEvent, U as ContentPartProviderTool, V as ContentPartCitation, W as ContentPartText, X as ToolResultPart, Y as ThinkingContinuity, Z as AIProvider, _ as Annotation, _t as TokenStats, at as ResolvedProviderTool, b as CitationPart, bt as LLMRequest, c as ToolContext, ct as FileInfo, d as ToolRegistry, dt as FileResolveFormat, et as ContextUsage, f as AnnotationEvent, ft as FileResolveRequest, g as ActionResult, gt as Stats, h as ActionPart, ht as loadFileContent, i as TurnAccumulatorState, it as ProviderOptions, j as TurnStatus, jt as ToolResult, k as TurnMetadata, kt as SpanType, l as ToolDefinition, lt as FileKind, m as TurnEvent, mt as ResolvedFileSource, n as TurnAccumulator, nt as ModelResult, o as ExecutableTool, ot as ToolChoice, p as AnnotationTarget, pt as FileResolver, q as DocumentLocator, r as TurnAccumulatorResult, rt as ProviderClientOptions, s as ProviderTool, st as DeferredFileInfo, t as AccumulatableEvent, tt as ModelError, u as ToolProgressChunk, ut as FileProviderId, v as AnnotationPlacement, vt as UsageEntry, w as TextPart, wt as SpanData, x as FilePart, xt as LLMResponse, y as AnnotationStatus, yt as EventLevel, z as CitationSource } from "./accumulator-yYlD8Bfm.js";
1
+ import { $ as ToolResultPart, A as TurnMetadata, At as SpanResult, B as Citation, C as ProviderToolAction, Ct as LLMRequest, Dt as SpanData, E as ThinkingPart, Et as Span, F as AxleAssistantMessage, Ft as TraceWriter, G as ContentPartFile, H as CitationSource, I as AxleMessage, J as ContentPartThinking, K as ContentPartProviderTool, L as AxleToolCallMessage, M as TurnStatus, Mt as SpanType, N as CompactionRecord, Nt as TokenUsage, O as ToolAction, Ot as SpanEvent, P as validateCompactedMessages, Pt as ToolResult, Q as ThinkingContinuity, R as AxleToolCallResult, S as FilePart, St as EventLevel, T as TextPart, Tt as LLMResult, U as ContentPart, V as CitationOutputSpan, W as ContentPartCitation, X as DocumentLocator, Y as ContentPartToolCall, Z as MessageMetadata, _ as Annotation, _t as ResolvedFileSource, at as ModelResult, b as CitationPart, bt as TokenStats, c as ToolContext, ct as ResolvedProviderTool, d as ToolRegistry, dt as FileInfo, et as AIProvider, f as AnnotationEvent, ft as FileKind, g as ActionResult, gt as FileResolver, h as ActionPart, ht as FileResolveRequest, i as TurnAccumulatorState, it as ModelError, j as TurnPart, jt as SpanStatus, k as Turn, kt as SpanOptions, l as ToolDefinition, lt as ToolChoice, m as TurnEvent, mt as FileResolveFormat, n as TurnAccumulator, nt as AxleStopReason, o as ExecutableTool, ot as ProviderClientOptions, p as AnnotationTarget, pt as FileProviderId, q as ContentPartText, r as TurnAccumulatorResult, rt as ContextUsage, s as ProviderTool, st as ProviderOptions, t as AccumulatableEvent, tt as AxleModelRequestOptions, u as ToolProgressChunk, ut as DeferredFileInfo, v as AnnotationPlacement, vt as loadFileContent, w as SubagentAction, wt as LLMResponse, x as CompactionPart, xt as UsageEntry, y as AnnotationStatus, yt as Stats, z as AxleUserMessage } from "./accumulator-B2Zr6tOY.js";
2
2
  import * as z$2 from "zod";
3
3
  import { ZodObject, z } from "zod";
4
4
 
@@ -142,32 +142,72 @@ declare class Instruct<TSchema extends OutputSchema | undefined = undefined> {
142
142
  //#endregion
143
143
  //#region src/core/agent/history.d.ts
144
144
  /**
145
- * In-memory conversation and presentation history for an agent.
145
+ * Complete state for constructing a `History`. Reconstructing from a saved
146
+ * session goes through the constructor — there is no field-by-field mutation.
147
+ */
148
+ interface HistoryInit<TAnnotation extends Annotation = Annotation> {
149
+ turns?: Turn<TAnnotation>[];
150
+ messages?: AxleMessage[];
151
+ archive?: AxleMessage[];
152
+ compactions?: CompactionRecord[];
153
+ sessionAnnotations?: TAnnotation[];
154
+ }
155
+ /**
156
+ * In-memory conversation and presentation state for an agent.
157
+ *
158
+ * All state is private; reads return copies and writes go through
159
+ * use-case-specific methods:
146
160
  *
147
- * `log` is the canonical model-facing message history. `turns` and
148
- * `sessionAnnotations` are renderable presentation state for consumers.
161
+ * - `messages` the active, model-facing conversation. Requests are built
162
+ * from it; compaction replaces it.
163
+ * - `archive` — every message ever appended, in order, untouched by
164
+ * compaction. The chronological record, for inspection only.
165
+ * - `turns` — the renderable session turns: user/agent entries and compaction entries.
166
+ * Forever-accumulating; consumers decide how to render or prune it.
167
+ * - `compactions` — receipts for each applied compaction.
168
+ * - `sessionAnnotations` — session-level render annotations.
149
169
  *
150
170
  * @typeParam TAnnotation - Annotation union supported by the host renderer.
151
171
  */
152
172
  declare class History<TAnnotation extends Annotation = Annotation> {
153
173
  private _turns;
154
- private _log;
174
+ private _messages;
175
+ private _archive;
176
+ private _compactions;
155
177
  private _sessionAnnotations;
156
- constructor(init?: {
157
- turns?: Turn<TAnnotation>[];
158
- log?: AxleMessage[];
159
- sessionAnnotations?: TAnnotation[];
160
- });
178
+ constructor(init?: HistoryInit<TAnnotation>);
161
179
  get turns(): Turn<TAnnotation>[];
162
- get log(): AxleMessage[];
180
+ get messages(): AxleMessage[];
181
+ get archive(): AxleMessage[];
182
+ get compactions(): CompactionRecord[];
163
183
  get sessionAnnotations(): TAnnotation[];
164
- addTurn(turn: Turn<TAnnotation>): void;
165
- replaceTurns(turns: Turn<TAnnotation>[]): void;
166
- replaceLog(messages: AxleMessage[]): void;
167
- replaceSessionAnnotations(annotations?: TAnnotation[]): void;
168
- appendToLog(messages: AxleMessage | AxleMessage[]): void;
169
- latestTurn(): Turn<TAnnotation> | undefined;
170
- toString(): string;
184
+ /**
185
+ * Append conversation messages. Every appended message goes to both the
186
+ * active conversation and the archive, so the archive is always the
187
+ * complete chronological record regardless of compaction.
188
+ *
189
+ * @internal The Agent is History's only writer. Direct writes bypass the
190
+ * work queue and the event fold, desynchronizing engine state.
191
+ */
192
+ append(messages: AxleMessage | AxleMessage[]): void;
193
+ /**
194
+ * Replace the renderable turn state wholesale. Used to sync the
195
+ * accumulated state after applying a turn event.
196
+ *
197
+ * @internal The Agent is History's only writer. External writes are
198
+ * overwritten by the agent's accumulator on the next event.
199
+ */
200
+ replaceTurns(turns: Turn<TAnnotation>[], sessionAnnotations: TAnnotation[]): void;
201
+ /**
202
+ * Apply a compaction: the new state replaces the active conversation and
203
+ * the record is kept. The archive is untouched — it already holds
204
+ * everything ever appended. The corresponding compaction turn arrives
205
+ * through the event fold, not here.
206
+ *
207
+ * @internal The Agent is History's only writer; use `agent.compact()`.
208
+ * @experimental Compaction is under active design and may change in any release.
209
+ */
210
+ compact(messages: AxleMessage[], record: CompactionRecord): void;
171
211
  }
172
212
  //#endregion
173
213
  //#region src/memory/types.d.ts
@@ -320,33 +360,50 @@ type ToolCallResult = {
320
360
  };
321
361
  };
322
362
  type ToolCallCallback = (name: string, parameters: Record<string, unknown>, ctx: ToolContext) => Promise<ToolCallResult | null | undefined>;
323
- type GenerateError = {
363
+ type AxleFailure = {
324
364
  kind: "model";
325
365
  error: ModelError;
366
+ message: string;
326
367
  } | {
327
368
  kind: "tool";
328
369
  error: {
329
370
  name: string;
330
371
  message: string;
331
372
  };
373
+ message: string;
332
374
  } | {
333
375
  kind: "parse";
334
376
  error: unknown;
335
377
  message: string;
336
378
  };
379
+ /** @deprecated Use AxleFailure. */
380
+ type GenerateError = AxleFailure;
337
381
  type GenerateResult<TResponse = AxleAssistantMessage> = {
338
382
  ok: true;
339
383
  response: TResponse;
340
384
  messages: AxleMessage[];
341
385
  final: AxleAssistantMessage;
342
386
  usage?: Stats;
387
+ /**
388
+ * Present when a configured limit ended the tool loop at a request
389
+ * boundary. The conversation is well-formed and continuable;
390
+ * `final.finishReason` keeps the provider's own reason for the last
391
+ * message (typically `FunctionCall` — the model wanted to continue).
392
+ */
393
+ stopped?: "max-iterations" | "token-limit";
343
394
  } | {
344
395
  ok: false;
345
396
  response?: undefined;
346
397
  final?: AxleAssistantMessage;
347
398
  messages: AxleMessage[];
348
- error: GenerateError;
399
+ error: AxleFailure;
349
400
  usage?: Stats;
401
+ /**
402
+ * Present on a `parse` error when a loop limit ended an Instruct call
403
+ * before the model produced parseable output. The conversation is still
404
+ * well-formed and continuable.
405
+ */
406
+ stopped?: "max-iterations" | "token-limit";
350
407
  };
351
408
  type StreamResult<TResponse = AxleAssistantMessage> = GenerateResult<TResponse>;
352
409
  //#endregion
@@ -355,16 +412,6 @@ interface Handle<T> {
355
412
  cancel(reason?: unknown): void;
356
413
  readonly final: Promise<T>;
357
414
  }
358
- /**
359
- * Creates a cancellable, queued async handle.
360
- * Waits for `queue` before running `work`, merges an optional external signal
361
- * with an internal abort controller, and returns the handle + settled promise
362
- * for queue chaining.
363
- */
364
- declare function createHandle<T>(queue: Promise<void>, work: (signal: AbortSignal) => Promise<T>, externalSignal?: AbortSignal): {
365
- handle: Handle<T>;
366
- settled: Promise<void>;
367
- };
368
415
  //#endregion
369
416
  //#region src/core/agent/types.d.ts
370
417
  /**
@@ -505,7 +552,7 @@ type AgentDefinitionResolver = (definition: AgentDefinition) => MaybePromise<Res
505
552
  * renderable turn state. It intentionally does not include executable runtime
506
553
  * objects such as providers, tools, MCP clients, memory implementations, file
507
554
  * resolvers, or tracers. Recreate those from host-owned configuration, then
508
- * call `agent.restore(session)`.
555
+ * construct a new agent with the session: `new Agent(config, session)`.
509
556
  *
510
557
  * @typeParam TAnnotation - Annotation union supported by the host renderer.
511
558
  */
@@ -514,8 +561,12 @@ interface AgentSession<TAnnotation extends Annotation = Annotation> {
514
561
  version: 1;
515
562
  /** Stable conversation/session id. */
516
563
  sessionId: string;
517
- /** Canonical model-facing message history used for continuation. */
564
+ /** Active model-facing conversation used for continuation. */
518
565
  messages: AxleMessage[];
566
+ /** Complete chronological record of every appended message, untouched by compaction. May be empty; absent in pre-compaction snapshots. */
567
+ archive?: AxleMessage[];
568
+ /** Compaction records, in order. Empty when no compaction has run; absent in pre-compaction snapshots. */
569
+ compactions?: CompactionRecord[];
519
570
  /** Renderable turn state for exact UI restoration. */
520
571
  turns?: Turn<TAnnotation>[];
521
572
  /** Session-level annotations for generic renderer state. */
@@ -539,12 +590,28 @@ interface AgentResult<T = string> {
539
590
  interface AgentErrorResult {
540
591
  ok: false;
541
592
  response?: undefined;
542
- error: GenerateError;
593
+ error: AxleFailure;
543
594
  turn: Turn | undefined;
544
595
  usage: Stats;
545
596
  }
546
597
  type AgentHandle<T = string> = Handle<AgentResult<T> | AgentErrorResult>;
547
598
  type TurnEventCallback = (event: TurnEvent) => void;
599
+ /**
600
+ * Caller-supplied compaction policy and strategy.
601
+ *
602
+ * The callback owns the decision: return `null` for "not now" (cheap — the
603
+ * usage estimate is local), or the complete new active conversation. The
604
+ * engine owns validation, record stamping, state processing, and event
605
+ * emission.
606
+ *
607
+ * @experimental Compaction is under active design and may change in any release.
608
+ */
609
+ type CompactionCallback = (state: {
610
+ messages: AxleMessage[];
611
+ }, context: {
612
+ usage: ContextUsage;
613
+ signal?: AbortSignal;
614
+ }) => MaybePromise<AxleMessage[] | null>;
548
615
  interface SendMessageOptions extends AxleModelRequestOptions {
549
616
  fileResolver?: FileResolver;
550
617
  /**
@@ -571,7 +638,9 @@ declare class Agent {
571
638
  private spanParent?;
572
639
  private ownedTracer?;
573
640
  private eventCallbacks;
574
- private sendQueue;
641
+ private compactionCallback?;
642
+ private workQueue;
643
+ private accumulator;
575
644
  /**
576
645
  * Create an agent from runtime config and, optionally, restore saved session state.
577
646
  *
@@ -584,25 +653,63 @@ declare class Agent {
584
653
  hasTools(): boolean;
585
654
  on(callback: TurnEventCallback): () => void;
586
655
  context(): ContextUsage;
656
+ private estimateContext;
587
657
  /**
588
- * Capture the serializable session state for later continuation.
658
+ * Register the compaction callback: the policy and strategy for shrinking
659
+ * the active conversation. One callback per agent; registering again
660
+ * replaces it.
661
+ */
662
+ onCompaction(callback: CompactionCallback): void;
663
+ /**
664
+ * Run the registered compaction callback against the active conversation.
665
+ *
666
+ * Compaction is optional: with no callback registered this is a no-op that
667
+ * resolves `null`. Otherwise the call is enqueued behind in-flight sends so
668
+ * compaction never races a turn. The callback may return `null` to skip;
669
+ * cancellation also resolves `null`. Errors propagate — a manual compact
670
+ * was explicitly requested.
589
671
  *
590
- * The returned object contains message history and renderable turn state, but
591
- * not executable configuration such as providers, tools, MCP clients, memory,
592
- * or tracers.
672
+ * Do not await this from inside a running send (a tool's `execute`,
673
+ * `onToolCall`, or a compaction callback): the send holds the queue, so the
674
+ * nested call deadlocks.
593
675
  */
594
- snapshot(): AgentSession;
676
+ compact(options?: {
677
+ signal?: AbortSignal;
678
+ }): Promise<CompactionRecord | null>;
595
679
  /**
596
- * Replace the agent's continuation and render state from a saved session.
680
+ * Capture the serializable session state for later continuation.
597
681
  *
598
- * Restore does not change runtime configuration. The current provider, model,
599
- * tools, MCP clients, memory, and other constructor-supplied objects remain in
600
- * effect.
682
+ * Enqueued behind in-flight sends and compactions, so the capture is
683
+ * always at rest a snapshot never contains a streaming or running turn.
684
+ * The returned object contains message history and renderable turn state,
685
+ * but not executable configuration such as providers, tools, MCP clients,
686
+ * memory, or tracers.
687
+ *
688
+ * Do not await this from inside a running send (a tool's `execute`,
689
+ * `onToolCall`, or a compaction callback): the send holds the queue, so the
690
+ * nested call deadlocks.
601
691
  */
602
- restore(session: AgentSession): void;
692
+ snapshot(): Promise<AgentSession>;
603
693
  send(message: string | Instruct<undefined>, options?: SendMessageOptions): AgentHandle<string>;
604
694
  send<TSchema extends OutputSchema>(instruct: Instruct<TSchema>, options?: SendMessageOptions): AgentHandle<ParsedSchema<TSchema>>;
695
+ /**
696
+ * Enqueue work behind everything already queued on this agent. Sends and
697
+ * compactions share one queue, so they never overlap.
698
+ *
699
+ * The work is exposed as two promises: `final` carries the outcome to the
700
+ * caller; `workQueue` carries only sequencing, with the outcome stripped —
701
+ * a rejected `final` in the queue would poison the chain and block all
702
+ * later work. Cancelled work still runs in order, but with an
703
+ * already-aborted signal.
704
+ */
705
+ private queue;
605
706
  private resolveMcpTools;
707
+ /**
708
+ * The single write path for renderable turn state: every event folds
709
+ * through the agent-lifetime accumulator, History mirrors the result, and
710
+ * subscribers are notified. Engine-internal state and consumer-folded
711
+ * state agree by construction because they run the same fold.
712
+ */
606
713
  private emitEvent;
607
714
  private toToolDefinitions;
608
715
  private run;
@@ -730,7 +837,6 @@ declare function gemini(apiKey: string, options?: ProviderClientOptions): AIProv
730
837
  //#region src/providers/gemini/index.d.ts
731
838
  declare const Gemini: {
732
839
  readonly Models: {
733
- readonly GEMINI_3_5_PRO: "gemini-3.5-pro";
734
840
  readonly GEMINI_3_5_FLASH: "gemini-3.5-flash";
735
841
  readonly GEMINI_3_1_PRO_PREVIEW: "gemini-3.1-pro-preview";
736
842
  readonly GEMINI_3_1_PRO: "gemini-3.1-pro-preview";
@@ -766,6 +872,13 @@ interface GenerateParams extends AxleModelRequestOptions {
766
872
  registry?: ToolRegistry;
767
873
  onToolCall?: ToolCallCallback;
768
874
  maxIterations?: number;
875
+ /**
876
+ * Context budget for the tool loop, in tokens. Checked at each request
877
+ * boundary against the previous model call's reported usage (effective
878
+ * input + output); when crossed, the loop returns `stopped: "token-limit"`
879
+ * with everything accumulated so far.
880
+ */
881
+ maxContextTokens?: number;
769
882
  span?: Span;
770
883
  fileResolver?: FileResolver;
771
884
  }
@@ -807,87 +920,71 @@ type StreamEvent = {
807
920
  message: AxleToolCallMessage;
808
921
  } | {
809
922
  type: "text:start";
810
- index: number;
811
923
  } | {
812
924
  type: "text:delta";
813
- index: number;
814
925
  delta: string;
815
926
  accumulated: string;
816
927
  } | {
817
928
  type: "text:citation";
818
- index: number;
819
929
  citation: Citation;
820
930
  citations: Citation[];
821
931
  } | {
822
932
  type: "text:end";
823
- index: number;
824
933
  final: string;
825
934
  } | {
826
935
  type: "citation";
827
- index: number;
828
936
  citations: Citation[];
829
937
  providerMetadata?: Record<string, unknown>;
830
938
  } | {
831
939
  type: "thinking:start";
832
- index: number;
833
940
  redacted?: boolean;
834
941
  continuity?: ThinkingContinuity;
835
942
  providerMetadata?: Record<string, unknown>;
836
943
  } | {
837
944
  type: "thinking:delta";
838
- index: number;
839
945
  delta: string;
840
946
  accumulated: string;
841
947
  } | {
842
948
  type: "thinking:summary-delta";
843
- index: number;
844
949
  delta: string;
845
950
  accumulated: string;
846
951
  } | {
847
952
  type: "thinking:update";
848
- index: number;
849
953
  redacted?: boolean;
850
954
  continuity?: ThinkingContinuity;
851
955
  providerMetadata?: Record<string, unknown>;
852
956
  } | {
853
957
  type: "thinking:end";
854
- index: number;
855
958
  final: string;
856
959
  } | {
857
960
  type: "tool:request";
858
- index: number;
859
961
  id: string;
860
962
  name: string;
861
963
  kind?: "tool" | "agent";
862
964
  } | {
863
965
  type: "tool:args-delta";
864
- index: number;
865
966
  id: string;
866
967
  name: string;
867
968
  delta: string;
868
969
  accumulated: string;
869
970
  } | {
870
971
  type: "tool:exec-start";
871
- index: number;
872
972
  id: string;
873
973
  name: string;
874
974
  parameters: Record<string, unknown>;
875
975
  } | {
876
976
  type: "tool:exec-delta";
877
- index: number;
878
977
  id: string;
879
978
  name: string;
880
979
  chunk: ToolProgressChunk;
881
980
  } | {
882
981
  type: "tool:exec-complete";
883
- index: number;
884
982
  id: string;
885
983
  name: string;
886
984
  result: ToolCallResult;
887
985
  usage?: Stats;
888
986
  } | {
889
987
  type: "tool:exec-error";
890
- index: number;
891
988
  id: string;
892
989
  name: string;
893
990
  error: {
@@ -897,18 +994,16 @@ type StreamEvent = {
897
994
  usage?: Stats;
898
995
  } | {
899
996
  type: "provider-tool:start";
900
- index: number;
901
997
  id: string;
902
998
  name: string;
903
999
  } | {
904
1000
  type: "provider-tool:complete";
905
- index: number;
906
1001
  id: string;
907
1002
  name: string;
908
1003
  output?: unknown;
909
1004
  } | {
910
1005
  type: "error";
911
- error: GenerateError;
1006
+ error: AxleFailure;
912
1007
  };
913
1008
  type StreamEventCallback = (event: StreamEvent) => void;
914
1009
  interface StreamParams extends AxleModelRequestOptions {
@@ -921,6 +1016,14 @@ interface StreamParams extends AxleModelRequestOptions {
921
1016
  registry?: ToolRegistry;
922
1017
  onToolCall?: ToolCallCallback;
923
1018
  maxIterations?: number;
1019
+ /**
1020
+ * Context budget for the tool loop, in tokens. Checked after each turn's
1021
+ * tools are answered, against that turn's reported usage (effective input
1022
+ * + output); when crossed, the loop returns `stopped: "token-limit"` with
1023
+ * everything accumulated so far. The caller decides what to do — e.g.
1024
+ * compact the conversation and start a new stream.
1025
+ */
1026
+ maxContextTokens?: number;
924
1027
  span?: Span;
925
1028
  fileResolver?: FileResolver;
926
1029
  }
@@ -1140,4 +1243,4 @@ declare function createStats(): Stats;
1140
1243
  declare function addStats(total: Stats, usage?: Stats): void;
1141
1244
  declare function mergeStats(...usages: Array<Stats | undefined>): Stats;
1142
1245
  //#endregion
1143
- export { type AIProvider, type AccumulatableEvent, type ActionPart, type ActionResult, Agent, type AgentConfig, type AgentDefinition, type AgentDefinitionRequestOptions, type AgentDefinitionResolver, type AgentErrorResult, type AgentHandle, type AgentMemory, type AgentResult, type AgentSession, type Annotation, type AnnotationEvent, type AnnotationPlacement, type AnnotationStatus, type AnnotationTarget, Anthropic, AxleAbortError, AxleAgentAbortError, type AxleAssistantMessage, type AxleConfiguration, AxleError, type AxleMessage, type AxleModelRequestOptions, AxleStopReason, type AxleToolCallMessage, type AxleToolCallResult, AxleToolFatalError, type AxleUserMessage, type BraveWebSearchOptions, type ChatCompletionsOptions, type ChatCompletionsVendor, type Citation, type CitationOutputSpan, type CitationPart, type CitationSource, type ContentPart, type ContentPartCitation, type ContentPartFile, type ContentPartProviderTool, type ContentPartText, type ContentPartThinking, type ContentPartToolCall, type ContextUsage, type CreateAgentToolOptions, type DeferredFileInfo, type DocumentLocator, type EventLevel, type ExecutableTool, type FileInfo, type FileKind, type FilePart, type FileProviderId, type FileResolveFormat, type FileResolveRequest, type FileResolver, type FileStore, Gemini, type GenerateInstructParams, type GenerateInstructResult, type GenerateParams, type Handle, History, Instruct, type InstructContextSection, type InstructInputs, type InstructOptions, type InstructResponse, InstructVariableError, type InstructVarsMode, type LLMRequest, type LLMResponse, type LLMResult, type LogEntry, type LogFn, LogWriter, MCP, type MCPConfig, type MCPHttpConfig, type MCPStdioConfig, type MaybePromise, type MemoryContext, type MessageMetadata, type ObservabilityOptions, OpenAI, type OutputSchema, type ParallelToolResult, type ParallelizeOptions, type ParsedSchema, type ProviderClientOptions, type ProviderDefinition, type ProviderOptions, type ProviderTool, type ProviderToolAction, type ProviderToolDefinitionRef, type RecallResult, type ResolvedAgentDefinition, type ResolvedFileSource, type SavedAgent, type SendMessageOptions, SimpleWriter, type SimpleWriterOptions, type Span, type SpanData, type SpanEvent, type SpanOptions, type SpanResult, type SpanStatus, type SpanType, type Stats, type StreamEvent, type StreamEventCallback, type StreamHandle, type StreamInstructHandle, type StreamInstructParams, type StreamInstructResult, type StreamParams, type StreamResult, type SubagentAction, TaskError, type TextPart, type ThinkingContinuity, type ThinkingPart, type TokenStats, type TokenUsage, type ToolAction, type ToolChoice, type ToolContext, type ToolDefinition, type ToolDefinitionRef, type ToolProgressChunk, ToolRegistry, type ToolResult, type ToolResultPart, type TraceWriter, Tracer, type TracerOptions, type Turn, TurnAccumulator, type TurnAccumulatorResult, type TurnAccumulatorState, type TurnEvent, TurnEventBuilder, type TurnEventCallback, type TurnMetadata, type TurnPart, type TurnStatus, type UsageEntry, type WebSearchBackend, type WebSearchBackendContext, type WebSearchRequest, type WebSearchResponse, type WebSearchResult, addStats, anthropic, braveWebSearch, chatCompletions, configureAxle, createAgentConfig, createAgentTool, createHandle, createStats, estimateContextUsage, gemini, generate, generateTurn, loadFileContent, mergeStats, openai, parallelize, parseResponse, stream };
1246
+ export { type AIProvider, type AccumulatableEvent, type ActionPart, type ActionResult, Agent, type AgentConfig, type AgentDefinition, type AgentDefinitionRequestOptions, type AgentDefinitionResolver, type AgentErrorResult, type AgentHandle, type AgentMemory, type AgentResult, type AgentSession, type Annotation, type AnnotationEvent, type AnnotationPlacement, type AnnotationStatus, type AnnotationTarget, Anthropic, AxleAbortError, AxleAgentAbortError, type AxleAssistantMessage, type AxleConfiguration, AxleError, type AxleFailure, type AxleMessage, type AxleModelRequestOptions, AxleStopReason, type AxleToolCallMessage, type AxleToolCallResult, AxleToolFatalError, type AxleUserMessage, type BraveWebSearchOptions, type ChatCompletionsOptions, type ChatCompletionsVendor, type Citation, type CitationOutputSpan, type CitationPart, type CitationSource, type CompactionCallback, type CompactionPart, type CompactionRecord, type ContentPart, type ContentPartCitation, type ContentPartFile, type ContentPartProviderTool, type ContentPartText, type ContentPartThinking, type ContentPartToolCall, type ContextUsage, type CreateAgentToolOptions, type DeferredFileInfo, type DocumentLocator, type EventLevel, type ExecutableTool, type FileInfo, type FileKind, type FilePart, type FileProviderId, type FileResolveFormat, type FileResolveRequest, type FileResolver, type FileStore, Gemini, type GenerateError, type GenerateInstructParams, type GenerateInstructResult, type GenerateParams, type Handle, History, Instruct, type InstructContextSection, type InstructInputs, type InstructOptions, type InstructResponse, InstructVariableError, type InstructVarsMode, type LLMRequest, type LLMResponse, type LLMResult, type LogEntry, type LogFn, LogWriter, MCP, type MCPConfig, type MCPHttpConfig, type MCPStdioConfig, type MaybePromise, type MemoryContext, type MessageMetadata, type ObservabilityOptions, OpenAI, type OutputSchema, type ParallelToolResult, type ParallelizeOptions, type ParsedSchema, type ProviderClientOptions, type ProviderDefinition, type ProviderOptions, type ProviderTool, type ProviderToolAction, type ProviderToolDefinitionRef, type RecallResult, type ResolvedAgentDefinition, type ResolvedFileSource, type SavedAgent, type SendMessageOptions, SimpleWriter, type SimpleWriterOptions, type Span, type SpanData, type SpanEvent, type SpanOptions, type SpanResult, type SpanStatus, type SpanType, type Stats, type StreamEvent, type StreamEventCallback, type StreamHandle, type StreamInstructHandle, type StreamInstructParams, type StreamInstructResult, type StreamParams, type StreamResult, type SubagentAction, TaskError, type TextPart, type ThinkingContinuity, type ThinkingPart, type TokenStats, type TokenUsage, type ToolAction, type ToolChoice, type ToolContext, type ToolDefinition, type ToolDefinitionRef, type ToolProgressChunk, ToolRegistry, type ToolResult, type ToolResultPart, type TraceWriter, Tracer, type TracerOptions, type Turn, TurnAccumulator, type TurnAccumulatorResult, type TurnAccumulatorState, type TurnEvent, TurnEventBuilder, type TurnEventCallback, type TurnMetadata, type TurnPart, type TurnStatus, type UsageEntry, type WebSearchBackend, type WebSearchBackendContext, type WebSearchRequest, type WebSearchResponse, type WebSearchResult, addStats, anthropic, braveWebSearch, chatCompletions, configureAxle, createAgentConfig, createAgentTool, createStats, estimateContextUsage, gemini, generate, generateTurn, loadFileContent, mergeStats, openai, parallelize, parseResponse, stream, validateCompactedMessages };