@fifthrevision/axle 0.25.4 → 0.26.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.
@@ -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.
@@ -863,7 +890,7 @@ interface Turn<TAnnotation extends Annotation = Annotation> {
863
890
  /**
864
891
  * Any renderable part within a turn.
865
892
  */
866
- type TurnPart<TAnnotation extends Annotation = Annotation> = TextPart<TAnnotation> | CitationPart<TAnnotation> | FilePart<TAnnotation> | ThinkingPart<TAnnotation> | ActionPart<TAnnotation>;
893
+ type TurnPart<TAnnotation extends Annotation = Annotation> = TextPart<TAnnotation> | CitationPart<TAnnotation> | FilePart<TAnnotation> | ThinkingPart<TAnnotation> | ActionPart<TAnnotation> | CompactionPart<TAnnotation>;
867
894
  /**
868
895
  * Assistant or user text content.
869
896
  */
@@ -938,6 +965,28 @@ interface ThinkingPart<TAnnotation extends Annotation = Annotation> {
938
965
  /** Optional timing metadata. */
939
966
  timing?: TimingInfo;
940
967
  }
968
+ /**
969
+ * Part marking a compaction of the model-facing conversation.
970
+ *
971
+ * Compaction renders as an agent turn containing this single part. The turn's
972
+ * `status` carries the lifecycle: `"streaming"` while the compaction callback
973
+ * runs, `"complete"` once applied, `"error"` on failure. Skipped compactions
974
+ * are removed from the turns, not settled.
975
+ *
976
+ * @experimental Compaction is under active design and may change in any release.
977
+ */
978
+ interface CompactionPart<TAnnotation extends Annotation = Annotation> {
979
+ /** Stable part id. Shared with the compaction record. */
980
+ id: string;
981
+ /** Part discriminator. */
982
+ type: "compaction";
983
+ /** The applied record, present once the compaction completes. */
984
+ record?: CompactionRecord;
985
+ /** Annotations attached to this part. */
986
+ annotations?: TAnnotation[];
987
+ /** Optional timing metadata. */
988
+ timing?: TimingInfo;
989
+ }
941
990
  /**
942
991
  * Shared fields for tool, subagent, and provider-managed actions.
943
992
  *
@@ -1056,6 +1105,16 @@ type TurnEvent<TAnnotation extends Annotation = Annotation> = {
1056
1105
  status: TurnStatus;
1057
1106
  usage: Stats;
1058
1107
  timing?: TimingInfo;
1108
+ } | {
1109
+ type: "compaction:start";
1110
+ id: string;
1111
+ timing?: TimingInfo;
1112
+ } | {
1113
+ type: "compaction:end";
1114
+ id: string;
1115
+ outcome: "complete" | "skipped" | "error";
1116
+ record?: CompactionRecord;
1117
+ timing?: TimingInfo;
1059
1118
  } | {
1060
1119
  type: "part:start";
1061
1120
  turnId: string;
@@ -1222,6 +1281,7 @@ declare class TurnAccumulator<TAnnotation extends Annotation = Annotation, THost
1222
1281
  constructor(init?: TurnAccumulatorState<TAnnotation>);
1223
1282
  get state(): TurnAccumulatorState<TAnnotation>;
1224
1283
  apply(event: AccumulatableEvent<TAnnotation, THostEvent>): TurnAccumulatorResult<TAnnotation, THostEvent>;
1284
+ private applyTurnEvent;
1225
1285
  private replaceState;
1226
1286
  private replaceTurns;
1227
1287
  private updateTurn;
@@ -1231,4 +1291,4 @@ declare class TurnAccumulator<TAnnotation extends Annotation = Annotation, THost
1231
1291
  private handled;
1232
1292
  }
1233
1293
  //#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 };
1294
+ 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 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-BQ_1i4qv.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
@@ -340,6 +380,13 @@ type GenerateResult<TResponse = AxleAssistantMessage> = {
340
380
  messages: AxleMessage[];
341
381
  final: AxleAssistantMessage;
342
382
  usage?: Stats;
383
+ /**
384
+ * Present when a configured limit ended the tool loop at a request
385
+ * boundary. The conversation is well-formed and continuable;
386
+ * `final.finishReason` keeps the provider's own reason for the last
387
+ * message (typically `FunctionCall` — the model wanted to continue).
388
+ */
389
+ stopped?: "max-iterations" | "token-limit";
343
390
  } | {
344
391
  ok: false;
345
392
  response?: undefined;
@@ -347,6 +394,12 @@ type GenerateResult<TResponse = AxleAssistantMessage> = {
347
394
  messages: AxleMessage[];
348
395
  error: GenerateError;
349
396
  usage?: Stats;
397
+ /**
398
+ * Present on a `parse` error when a loop limit ended an Instruct call
399
+ * before the model produced parseable output. The conversation is still
400
+ * well-formed and continuable.
401
+ */
402
+ stopped?: "max-iterations" | "token-limit";
350
403
  };
351
404
  type StreamResult<TResponse = AxleAssistantMessage> = GenerateResult<TResponse>;
352
405
  //#endregion
@@ -355,16 +408,6 @@ interface Handle<T> {
355
408
  cancel(reason?: unknown): void;
356
409
  readonly final: Promise<T>;
357
410
  }
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
411
  //#endregion
369
412
  //#region src/core/agent/types.d.ts
370
413
  /**
@@ -505,7 +548,7 @@ type AgentDefinitionResolver = (definition: AgentDefinition) => MaybePromise<Res
505
548
  * renderable turn state. It intentionally does not include executable runtime
506
549
  * objects such as providers, tools, MCP clients, memory implementations, file
507
550
  * resolvers, or tracers. Recreate those from host-owned configuration, then
508
- * call `agent.restore(session)`.
551
+ * construct a new agent with the session: `new Agent(config, session)`.
509
552
  *
510
553
  * @typeParam TAnnotation - Annotation union supported by the host renderer.
511
554
  */
@@ -514,8 +557,12 @@ interface AgentSession<TAnnotation extends Annotation = Annotation> {
514
557
  version: 1;
515
558
  /** Stable conversation/session id. */
516
559
  sessionId: string;
517
- /** Canonical model-facing message history used for continuation. */
560
+ /** Active model-facing conversation used for continuation. */
518
561
  messages: AxleMessage[];
562
+ /** Complete chronological record of every appended message, untouched by compaction. May be empty; absent in pre-compaction snapshots. */
563
+ archive?: AxleMessage[];
564
+ /** Compaction records, in order. Empty when no compaction has run; absent in pre-compaction snapshots. */
565
+ compactions?: CompactionRecord[];
519
566
  /** Renderable turn state for exact UI restoration. */
520
567
  turns?: Turn<TAnnotation>[];
521
568
  /** Session-level annotations for generic renderer state. */
@@ -545,6 +592,22 @@ interface AgentErrorResult {
545
592
  }
546
593
  type AgentHandle<T = string> = Handle<AgentResult<T> | AgentErrorResult>;
547
594
  type TurnEventCallback = (event: TurnEvent) => void;
595
+ /**
596
+ * Caller-supplied compaction policy and strategy.
597
+ *
598
+ * The callback owns the decision: return `null` for "not now" (cheap — the
599
+ * usage estimate is local), or the complete new active conversation. The
600
+ * engine owns validation, record stamping, state processing, and event
601
+ * emission.
602
+ *
603
+ * @experimental Compaction is under active design and may change in any release.
604
+ */
605
+ type CompactionCallback = (state: {
606
+ messages: AxleMessage[];
607
+ }, context: {
608
+ usage: ContextUsage;
609
+ signal?: AbortSignal;
610
+ }) => MaybePromise<AxleMessage[] | null>;
548
611
  interface SendMessageOptions extends AxleModelRequestOptions {
549
612
  fileResolver?: FileResolver;
550
613
  /**
@@ -571,7 +634,9 @@ declare class Agent {
571
634
  private spanParent?;
572
635
  private ownedTracer?;
573
636
  private eventCallbacks;
574
- private sendQueue;
637
+ private compactionCallback?;
638
+ private workQueue;
639
+ private accumulator;
575
640
  /**
576
641
  * Create an agent from runtime config and, optionally, restore saved session state.
577
642
  *
@@ -584,25 +649,63 @@ declare class Agent {
584
649
  hasTools(): boolean;
585
650
  on(callback: TurnEventCallback): () => void;
586
651
  context(): ContextUsage;
652
+ private estimateContext;
587
653
  /**
588
- * Capture the serializable session state for later continuation.
654
+ * Register the compaction callback: the policy and strategy for shrinking
655
+ * the active conversation. One callback per agent; registering again
656
+ * replaces it.
657
+ */
658
+ onCompaction(callback: CompactionCallback): void;
659
+ /**
660
+ * Run the registered compaction callback against the active conversation.
661
+ *
662
+ * Compaction is optional: with no callback registered this is a no-op that
663
+ * resolves `null`. Otherwise the call is enqueued behind in-flight sends so
664
+ * compaction never races a turn. The callback may return `null` to skip;
665
+ * cancellation also resolves `null`. Errors propagate — a manual compact
666
+ * was explicitly requested.
589
667
  *
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.
668
+ * Do not await this from inside a running send (a tool's `execute`,
669
+ * `onToolCall`, or a compaction callback): the send holds the queue, so the
670
+ * nested call deadlocks.
593
671
  */
594
- snapshot(): AgentSession;
672
+ compact(options?: {
673
+ signal?: AbortSignal;
674
+ }): Promise<CompactionRecord | null>;
595
675
  /**
596
- * Replace the agent's continuation and render state from a saved session.
676
+ * Capture the serializable session state for later continuation.
597
677
  *
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.
678
+ * Enqueued behind in-flight sends and compactions, so the capture is
679
+ * always at rest a snapshot never contains a streaming or running turn.
680
+ * The returned object contains message history and renderable turn state,
681
+ * but not executable configuration such as providers, tools, MCP clients,
682
+ * memory, or tracers.
683
+ *
684
+ * Do not await this from inside a running send (a tool's `execute`,
685
+ * `onToolCall`, or a compaction callback): the send holds the queue, so the
686
+ * nested call deadlocks.
601
687
  */
602
- restore(session: AgentSession): void;
688
+ snapshot(): Promise<AgentSession>;
603
689
  send(message: string | Instruct<undefined>, options?: SendMessageOptions): AgentHandle<string>;
604
690
  send<TSchema extends OutputSchema>(instruct: Instruct<TSchema>, options?: SendMessageOptions): AgentHandle<ParsedSchema<TSchema>>;
691
+ /**
692
+ * Enqueue work behind everything already queued on this agent. Sends and
693
+ * compactions share one queue, so they never overlap.
694
+ *
695
+ * The work is exposed as two promises: `final` carries the outcome to the
696
+ * caller; `workQueue` carries only sequencing, with the outcome stripped —
697
+ * a rejected `final` in the queue would poison the chain and block all
698
+ * later work. Cancelled work still runs in order, but with an
699
+ * already-aborted signal.
700
+ */
701
+ private queue;
605
702
  private resolveMcpTools;
703
+ /**
704
+ * The single write path for renderable turn state: every event folds
705
+ * through the agent-lifetime accumulator, History mirrors the result, and
706
+ * subscribers are notified. Engine-internal state and consumer-folded
707
+ * state agree by construction because they run the same fold.
708
+ */
606
709
  private emitEvent;
607
710
  private toToolDefinitions;
608
711
  private run;
@@ -679,6 +782,8 @@ declare function anthropic(apiKey: string, options?: ProviderClientOptions): AIP
679
782
  //#region src/providers/anthropic/index.d.ts
680
783
  declare const Anthropic: {
681
784
  readonly Models: {
785
+ readonly CLAUDE_SONNET_5: "claude-sonnet-5";
786
+ readonly CLAUDE_FABLE_5: "claude-fable-5";
682
787
  readonly CLAUDE_OPUS_4_8: "claude-opus-4-8";
683
788
  readonly CLAUDE_OPUS_4_7: "claude-opus-4-7";
684
789
  readonly CLAUDE_SONNET_4_6: "claude-sonnet-4-6";
@@ -728,6 +833,8 @@ declare function gemini(apiKey: string, options?: ProviderClientOptions): AIProv
728
833
  //#region src/providers/gemini/index.d.ts
729
834
  declare const Gemini: {
730
835
  readonly Models: {
836
+ readonly GEMINI_3_5_PRO: "gemini-3.5-pro";
837
+ readonly GEMINI_3_5_FLASH: "gemini-3.5-flash";
731
838
  readonly GEMINI_3_1_PRO_PREVIEW: "gemini-3.1-pro-preview";
732
839
  readonly GEMINI_3_1_PRO: "gemini-3.1-pro-preview";
733
840
  readonly GEMINI_3_1_PRO_PREVIEW_CUSTOMTOOLS: "gemini-3.1-pro-preview-customtools";
@@ -737,7 +844,6 @@ declare const Gemini: {
737
844
  readonly GEMINI_3_PRO: "gemini-3-pro-preview";
738
845
  readonly GEMINI_3_FLASH_PREVIEW: "gemini-3-flash-preview";
739
846
  readonly GEMINI_3_FLASH: "gemini-3-flash-preview";
740
- readonly GEMINI_3_5_FLASH: "gemini-3.5-flash";
741
847
  readonly GEMINI_2_5_PRO: "gemini-2.5-pro";
742
848
  readonly GEMINI_2_5_FLASH: "gemini-2.5-flash";
743
849
  readonly GEMINI_2_5_FLASH_LITE: "gemini-2.5-flash-lite";
@@ -763,6 +869,13 @@ interface GenerateParams extends AxleModelRequestOptions {
763
869
  registry?: ToolRegistry;
764
870
  onToolCall?: ToolCallCallback;
765
871
  maxIterations?: number;
872
+ /**
873
+ * Context budget for the tool loop, in tokens. Checked at each request
874
+ * boundary against the previous model call's reported usage (effective
875
+ * input + output); when crossed, the loop returns `stopped: "token-limit"`
876
+ * with everything accumulated so far.
877
+ */
878
+ maxContextTokens?: number;
766
879
  span?: Span;
767
880
  fileResolver?: FileResolver;
768
881
  }
@@ -804,87 +917,71 @@ type StreamEvent = {
804
917
  message: AxleToolCallMessage;
805
918
  } | {
806
919
  type: "text:start";
807
- index: number;
808
920
  } | {
809
921
  type: "text:delta";
810
- index: number;
811
922
  delta: string;
812
923
  accumulated: string;
813
924
  } | {
814
925
  type: "text:citation";
815
- index: number;
816
926
  citation: Citation;
817
927
  citations: Citation[];
818
928
  } | {
819
929
  type: "text:end";
820
- index: number;
821
930
  final: string;
822
931
  } | {
823
932
  type: "citation";
824
- index: number;
825
933
  citations: Citation[];
826
934
  providerMetadata?: Record<string, unknown>;
827
935
  } | {
828
936
  type: "thinking:start";
829
- index: number;
830
937
  redacted?: boolean;
831
938
  continuity?: ThinkingContinuity;
832
939
  providerMetadata?: Record<string, unknown>;
833
940
  } | {
834
941
  type: "thinking:delta";
835
- index: number;
836
942
  delta: string;
837
943
  accumulated: string;
838
944
  } | {
839
945
  type: "thinking:summary-delta";
840
- index: number;
841
946
  delta: string;
842
947
  accumulated: string;
843
948
  } | {
844
949
  type: "thinking:update";
845
- index: number;
846
950
  redacted?: boolean;
847
951
  continuity?: ThinkingContinuity;
848
952
  providerMetadata?: Record<string, unknown>;
849
953
  } | {
850
954
  type: "thinking:end";
851
- index: number;
852
955
  final: string;
853
956
  } | {
854
957
  type: "tool:request";
855
- index: number;
856
958
  id: string;
857
959
  name: string;
858
960
  kind?: "tool" | "agent";
859
961
  } | {
860
962
  type: "tool:args-delta";
861
- index: number;
862
963
  id: string;
863
964
  name: string;
864
965
  delta: string;
865
966
  accumulated: string;
866
967
  } | {
867
968
  type: "tool:exec-start";
868
- index: number;
869
969
  id: string;
870
970
  name: string;
871
971
  parameters: Record<string, unknown>;
872
972
  } | {
873
973
  type: "tool:exec-delta";
874
- index: number;
875
974
  id: string;
876
975
  name: string;
877
976
  chunk: ToolProgressChunk;
878
977
  } | {
879
978
  type: "tool:exec-complete";
880
- index: number;
881
979
  id: string;
882
980
  name: string;
883
981
  result: ToolCallResult;
884
982
  usage?: Stats;
885
983
  } | {
886
984
  type: "tool:exec-error";
887
- index: number;
888
985
  id: string;
889
986
  name: string;
890
987
  error: {
@@ -894,12 +991,10 @@ type StreamEvent = {
894
991
  usage?: Stats;
895
992
  } | {
896
993
  type: "provider-tool:start";
897
- index: number;
898
994
  id: string;
899
995
  name: string;
900
996
  } | {
901
997
  type: "provider-tool:complete";
902
- index: number;
903
998
  id: string;
904
999
  name: string;
905
1000
  output?: unknown;
@@ -918,6 +1013,14 @@ interface StreamParams extends AxleModelRequestOptions {
918
1013
  registry?: ToolRegistry;
919
1014
  onToolCall?: ToolCallCallback;
920
1015
  maxIterations?: number;
1016
+ /**
1017
+ * Context budget for the tool loop, in tokens. Checked after each turn's
1018
+ * tools are answered, against that turn's reported usage (effective input
1019
+ * + output); when crossed, the loop returns `stopped: "token-limit"` with
1020
+ * everything accumulated so far. The caller decides what to do — e.g.
1021
+ * compact the conversation and start a new stream.
1022
+ */
1023
+ maxContextTokens?: number;
921
1024
  span?: Span;
922
1025
  fileResolver?: FileResolver;
923
1026
  }
@@ -1137,4 +1240,4 @@ declare function createStats(): Stats;
1137
1240
  declare function addStats(total: Stats, usage?: Stats): void;
1138
1241
  declare function mergeStats(...usages: Array<Stats | undefined>): Stats;
1139
1242
  //#endregion
1140
- 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 };
1243
+ 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 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 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 };