@tanstack/ai-client 0.29.1 → 0.30.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.
@@ -26,6 +26,8 @@ export declare class NoOpChatDevtoolsBridge {
26
26
  resolveStreamId(): string;
27
27
  observeChunk(_chunk: StreamChunk): void;
28
28
  recordMemoryState(_value: unknown): void;
29
+ recordCompactionEvent(_eventType: string, _value: unknown): void;
30
+ recordCompactionState(_value: unknown): void;
29
31
  recordSkillsState(_value: unknown): void;
30
32
  beginRun(_runId: string, _threadId: string): void;
31
33
  getCurrentRunEventContext(): ChatClientRunEventContext | undefined;
@@ -31,6 +31,8 @@ var NoOpChatDevtoolsBridge = class {
31
31
  }
32
32
  observeChunk(_chunk) {}
33
33
  recordMemoryState(_value) {}
34
+ recordCompactionEvent(_eventType, _value) {}
35
+ recordCompactionState(_value) {}
34
36
  recordSkillsState(_value) {}
35
37
  beginRun(_runId, _threadId) {}
36
38
  getCurrentRunEventContext() {}
@@ -1 +1 @@
1
- {"version":3,"file":"devtools-noop.js","names":[],"sources":["../../src/devtools-noop.ts"],"sourcesContent":["// No-op devtools bridge implementations + factories. The chat / generation /\n// video clients import the real bridge classes as types only and accept a\n// factory in options; when no factory is supplied they fall back to the\n// no-op factories here, which never touch `aiEventClient` or any of the\n// heavy preview/fixture machinery in `./devtools`. This keeps `./devtools`\n// outside the main-entry import graph — consumers opt into functional\n// devtools via `@tanstack/ai-client/devtools` (see `package.json#exports`).\nimport { ChatClientEventEmitter } from './events'\nimport type {\n AIDevtoolsToolFixture,\n ChatDevtoolsBridge,\n ChatDevtoolsBridgeOptions,\n GenerationDevtoolsBridge,\n GenerationDevtoolsBridgeOptions,\n VideoDevtoolsBridge,\n VideoDevtoolsBridgeOptions,\n} from './devtools'\nimport type { StreamChunk } from '@tanstack/ai/client'\nimport type {\n ChatClientEventContext,\n ChatClientRunEventContext,\n} from './events'\n\nexport type ChatDevtoolsBridgeFactory = (\n options: ChatDevtoolsBridgeOptions,\n) => ChatDevtoolsBridge\n\nexport type GenerationDevtoolsBridgeFactory = <TOutput>(\n options: GenerationDevtoolsBridgeOptions<TOutput>,\n) => GenerationDevtoolsBridge<TOutput>\n\nexport type VideoDevtoolsBridgeFactory = <TOutput>(\n options: VideoDevtoolsBridgeOptions<TOutput>,\n) => VideoDevtoolsBridge<TOutput>\n\n// ===========================================================================\n// No-op event emitter — extends the abstract base so it satisfies the type\n// without dragging in any of the event-bus runtime cost.\n// ===========================================================================\n\nclass NoOpChatClientEventEmitter extends ChatClientEventEmitter {\n protected emitEvent(): void {\n // intentionally empty\n }\n}\n\n// ===========================================================================\n// No-op bridges. Methods exist to satisfy the structural shape of the real\n// classes; every emit/record call short-circuits.\n// ===========================================================================\n\nexport class NoOpChatDevtoolsBridge {\n readonly events: ChatClientEventEmitter\n\n constructor(options: ChatDevtoolsBridgeOptions) {\n this.events = new NoOpChatClientEventEmitter(options.clientId)\n }\n\n // base bridge surface\n emitRegistered(): void {}\n emitUpdated(): void {}\n emitSnapshot(): void {}\n emitToolsRegistered(): void {}\n emitRunLifecycle(\n _eventType: unknown,\n _runId: string,\n _status: unknown,\n _options?: { error?: string },\n ): void {}\n deactivate(): void {}\n supersede(): void {}\n dispose(): void {}\n\n // chat-specific surface\n mountWithTools(_initialMessageCount: number): void {}\n notifyToolsChanged(): void {}\n setCurrentStreamId(_streamId: string | null): void {}\n recordStreamId(_streamId: string): void {}\n getCurrentStreamId(): string | null {\n return null\n }\n getLastStreamId(): string | null {\n return null\n }\n resolveStreamId(): string {\n return ''\n }\n observeChunk(_chunk: StreamChunk): void {}\n recordMemoryState(_value: unknown): void {}\n recordSkillsState(_value: unknown): void {}\n beginRun(_runId: string, _threadId: string): void {}\n getCurrentRunEventContext(): ChatClientRunEventContext | undefined {\n return undefined\n }\n getCurrentOrLastRunEventContext(): ChatClientRunEventContext | undefined {\n return undefined\n }\n findToolCallContext(toolCallId: string): ChatClientEventContext {\n return { toolCallId }\n }\n async applyFixture(_fixture: AIDevtoolsToolFixture): Promise<void> {\n // intentionally empty\n }\n}\n\nexport class NoOpGenerationDevtoolsBridge<TOutput> {\n constructor(_options: GenerationDevtoolsBridgeOptions<TOutput>) {}\n\n // base bridge surface\n emitRegistered(): void {}\n emitUpdated(): void {}\n emitSnapshot(): void {}\n emitToolsRegistered(): void {}\n emitRunLifecycle(): void {}\n deactivate(): void {}\n supersede(): void {}\n dispose(): void {}\n\n // generation-specific surface\n beginRun(_input: unknown): string {\n // Real factories supply a stable id; the no-op still returns a\n // unique value because the generation client passes this run id to\n // the adapter's RunAgentInputContext.\n return `noop-run-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n }\n ensureRunStarted(_runId: string): void {}\n finishRun(\n _runId: string,\n _eventType: 'run:completed' | 'run:errored' | 'run:cancelled',\n _status: 'completed' | 'errored' | 'cancelled',\n _error?: string,\n ): void {}\n getActiveRunId(): string | null {\n return null\n }\n resetRuns(): void {}\n recordResultChange(): void {}\n recordLoadingChange(): void {}\n recordErrorChange(_error: Error | undefined): void {}\n recordStatusChange(): void {}\n recordProgressChange(): void {}\n emitState(): void {}\n}\n\nexport class NoOpVideoDevtoolsBridge<\n TOutput,\n> extends NoOpGenerationDevtoolsBridge<TOutput> {\n constructor(options: VideoDevtoolsBridgeOptions<TOutput>) {\n super(options)\n }\n\n recordJobIdChange(): void {}\n recordVideoStatusChange(): void {}\n}\n\n// Compile-time parity checks. If a public method is added to the real\n// bridge class without a matching stub on the no-op, the corresponding\n// `Exclude<...>` resolves to a non-`never` union, which violates the\n// `extends never` constraint below and fails the build — surfacing the\n// drift at build time instead of as a runtime TypeError later.\ntype AssertBridgeParity<TMissing extends never> = TMissing\ntype _ChatBridgeMissing = Exclude<\n keyof ChatDevtoolsBridge,\n keyof NoOpChatDevtoolsBridge\n>\ntype _GenerationBridgeMissing = Exclude<\n keyof GenerationDevtoolsBridge<unknown>,\n keyof NoOpGenerationDevtoolsBridge<unknown>\n>\ntype _VideoBridgeMissing = Exclude<\n keyof VideoDevtoolsBridge<unknown>,\n keyof NoOpVideoDevtoolsBridge<unknown>\n>\nconst _bridgeParity:\n | [\n AssertBridgeParity<_ChatBridgeMissing>,\n AssertBridgeParity<_GenerationBridgeMissing>,\n AssertBridgeParity<_VideoBridgeMissing>,\n ]\n | undefined = undefined\nvoid _bridgeParity\n\n// ===========================================================================\n// Factories — these are what the clients call when no real factory was\n// supplied in options.\n// ===========================================================================\n\n// Casts use `unknown` because the no-op classes don't `extend` the real bridge\n// (that would pull the real implementation into the main-entry import graph).\n// Structural parity is enforced by the `_*BridgeMissing` checks above.\n\nexport const createNoOpChatDevtoolsBridge: ChatDevtoolsBridgeFactory = (\n options,\n) =>\n // oxlint-disable-next-line eslint-js/no-restricted-syntax -- see comment above\n new NoOpChatDevtoolsBridge(options) as unknown as ChatDevtoolsBridge\n\nexport const createNoOpGenerationDevtoolsBridge: GenerationDevtoolsBridgeFactory =\n <TOutput>(options: GenerationDevtoolsBridgeOptions<TOutput>) =>\n // oxlint-disable-next-line eslint-js/no-restricted-syntax -- see comment above\n new NoOpGenerationDevtoolsBridge<TOutput>(\n options,\n ) as unknown as GenerationDevtoolsBridge<TOutput>\n\nexport const createNoOpVideoDevtoolsBridge: VideoDevtoolsBridgeFactory = <\n TOutput,\n>(\n options: VideoDevtoolsBridgeOptions<TOutput>,\n) =>\n // oxlint-disable-next-line eslint-js/no-restricted-syntax -- see comment above\n new NoOpVideoDevtoolsBridge<TOutput>(\n options,\n ) as unknown as VideoDevtoolsBridge<TOutput>\n"],"mappings":";;AAwCA,IAAM,6BAAN,cAAyC,uBAAuB;CAC9D,YAA4B,CAE5B;AACF;AAOA,IAAa,yBAAb,MAAoC;CAClC;CAEA,YAAY,SAAoC;EAC9C,KAAK,SAAS,IAAI,2BAA2B,QAAQ,QAAQ;CAC/D;CAGA,iBAAuB,CAAC;CACxB,cAAoB,CAAC;CACrB,eAAqB,CAAC;CACtB,sBAA4B,CAAC;CAC7B,iBACE,YACA,QACA,SACA,UACM,CAAC;CACT,aAAmB,CAAC;CACpB,YAAkB,CAAC;CACnB,UAAgB,CAAC;CAGjB,eAAe,sBAAoC,CAAC;CACpD,qBAA2B,CAAC;CAC5B,mBAAmB,WAAgC,CAAC;CACpD,eAAe,WAAyB,CAAC;CACzC,qBAAoC;EAClC,OAAO;CACT;CACA,kBAAiC;EAC/B,OAAO;CACT;CACA,kBAA0B;EACxB,OAAO;CACT;CACA,aAAa,QAA2B,CAAC;CACzC,kBAAkB,QAAuB,CAAC;CAC1C,kBAAkB,QAAuB,CAAC;CAC1C,SAAS,QAAgB,WAAyB,CAAC;CACnD,4BAAmE,CAEnE;CACA,kCAAyE,CAEzE;CACA,oBAAoB,YAA4C;EAC9D,OAAO,EAAE,WAAW;CACtB;CACA,MAAM,aAAa,UAAgD,CAEnE;AACF;AAEA,IAAa,+BAAb,MAAmD;CACjD,YAAY,UAAoD,CAAC;CAGjE,iBAAuB,CAAC;CACxB,cAAoB,CAAC;CACrB,eAAqB,CAAC;CACtB,sBAA4B,CAAC;CAC7B,mBAAyB,CAAC;CAC1B,aAAmB,CAAC;CACpB,YAAkB,CAAC;CACnB,UAAgB,CAAC;CAGjB,SAAS,QAAyB;EAIhC,OAAO,YAAY,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;CACxE;CACA,iBAAiB,QAAsB,CAAC;CACxC,UACE,QACA,YACA,SACA,QACM,CAAC;CACT,iBAAgC;EAC9B,OAAO;CACT;CACA,YAAkB,CAAC;CACnB,qBAA2B,CAAC;CAC5B,sBAA4B,CAAC;CAC7B,kBAAkB,QAAiC,CAAC;CACpD,qBAA2B,CAAC;CAC5B,uBAA6B,CAAC;CAC9B,YAAkB,CAAC;AACrB;AAEA,IAAa,0BAAb,cAEU,6BAAsC;CAC9C,YAAY,SAA8C;EACxD,MAAM,OAAO;CACf;CAEA,oBAA0B,CAAC;CAC3B,0BAAgC,CAAC;AACnC;AAsCA,IAAa,gCACX,YAGA,IAAI,uBAAuB,OAAO;AAEpC,IAAa,sCACD,YAER,IAAI,6BACF,OACF;AAEJ,IAAa,iCAGX,YAGA,IAAI,wBACF,OACF"}
1
+ {"version":3,"file":"devtools-noop.js","names":[],"sources":["../../src/devtools-noop.ts"],"sourcesContent":["// No-op devtools bridge implementations + factories. The chat / generation /\n// video clients import the real bridge classes as types only and accept a\n// factory in options; when no factory is supplied they fall back to the\n// no-op factories here, which never touch `aiEventClient` or any of the\n// heavy preview/fixture machinery in `./devtools`. This keeps `./devtools`\n// outside the main-entry import graph — consumers opt into functional\n// devtools via `@tanstack/ai-client/devtools` (see `package.json#exports`).\nimport { ChatClientEventEmitter } from './events'\nimport type {\n AIDevtoolsToolFixture,\n ChatDevtoolsBridge,\n ChatDevtoolsBridgeOptions,\n GenerationDevtoolsBridge,\n GenerationDevtoolsBridgeOptions,\n VideoDevtoolsBridge,\n VideoDevtoolsBridgeOptions,\n} from './devtools'\nimport type { StreamChunk } from '@tanstack/ai/client'\nimport type {\n ChatClientEventContext,\n ChatClientRunEventContext,\n} from './events'\n\nexport type ChatDevtoolsBridgeFactory = (\n options: ChatDevtoolsBridgeOptions,\n) => ChatDevtoolsBridge\n\nexport type GenerationDevtoolsBridgeFactory = <TOutput>(\n options: GenerationDevtoolsBridgeOptions<TOutput>,\n) => GenerationDevtoolsBridge<TOutput>\n\nexport type VideoDevtoolsBridgeFactory = <TOutput>(\n options: VideoDevtoolsBridgeOptions<TOutput>,\n) => VideoDevtoolsBridge<TOutput>\n\n// ===========================================================================\n// No-op event emitter — extends the abstract base so it satisfies the type\n// without dragging in any of the event-bus runtime cost.\n// ===========================================================================\n\nclass NoOpChatClientEventEmitter extends ChatClientEventEmitter {\n protected emitEvent(): void {\n // intentionally empty\n }\n}\n\n// ===========================================================================\n// No-op bridges. Methods exist to satisfy the structural shape of the real\n// classes; every emit/record call short-circuits.\n// ===========================================================================\n\nexport class NoOpChatDevtoolsBridge {\n readonly events: ChatClientEventEmitter\n\n constructor(options: ChatDevtoolsBridgeOptions) {\n this.events = new NoOpChatClientEventEmitter(options.clientId)\n }\n\n // base bridge surface\n emitRegistered(): void {}\n emitUpdated(): void {}\n emitSnapshot(): void {}\n emitToolsRegistered(): void {}\n emitRunLifecycle(\n _eventType: unknown,\n _runId: string,\n _status: unknown,\n _options?: { error?: string },\n ): void {}\n deactivate(): void {}\n supersede(): void {}\n dispose(): void {}\n\n // chat-specific surface\n mountWithTools(_initialMessageCount: number): void {}\n notifyToolsChanged(): void {}\n setCurrentStreamId(_streamId: string | null): void {}\n recordStreamId(_streamId: string): void {}\n getCurrentStreamId(): string | null {\n return null\n }\n getLastStreamId(): string | null {\n return null\n }\n resolveStreamId(): string {\n return ''\n }\n observeChunk(_chunk: StreamChunk): void {}\n recordMemoryState(_value: unknown): void {}\n recordCompactionEvent(_eventType: string, _value: unknown): void {}\n recordCompactionState(_value: unknown): void {}\n recordSkillsState(_value: unknown): void {}\n beginRun(_runId: string, _threadId: string): void {}\n getCurrentRunEventContext(): ChatClientRunEventContext | undefined {\n return undefined\n }\n getCurrentOrLastRunEventContext(): ChatClientRunEventContext | undefined {\n return undefined\n }\n findToolCallContext(toolCallId: string): ChatClientEventContext {\n return { toolCallId }\n }\n async applyFixture(_fixture: AIDevtoolsToolFixture): Promise<void> {\n // intentionally empty\n }\n}\n\nexport class NoOpGenerationDevtoolsBridge<TOutput> {\n constructor(_options: GenerationDevtoolsBridgeOptions<TOutput>) {}\n\n // base bridge surface\n emitRegistered(): void {}\n emitUpdated(): void {}\n emitSnapshot(): void {}\n emitToolsRegistered(): void {}\n emitRunLifecycle(): void {}\n deactivate(): void {}\n supersede(): void {}\n dispose(): void {}\n\n // generation-specific surface\n beginRun(_input: unknown): string {\n // Real factories supply a stable id; the no-op still returns a\n // unique value because the generation client passes this run id to\n // the adapter's RunAgentInputContext.\n return `noop-run-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n }\n ensureRunStarted(_runId: string): void {}\n finishRun(\n _runId: string,\n _eventType: 'run:completed' | 'run:errored' | 'run:cancelled',\n _status: 'completed' | 'errored' | 'cancelled',\n _error?: string,\n ): void {}\n getActiveRunId(): string | null {\n return null\n }\n resetRuns(): void {}\n recordResultChange(): void {}\n recordLoadingChange(): void {}\n recordErrorChange(_error: Error | undefined): void {}\n recordStatusChange(): void {}\n recordProgressChange(): void {}\n emitState(): void {}\n}\n\nexport class NoOpVideoDevtoolsBridge<\n TOutput,\n> extends NoOpGenerationDevtoolsBridge<TOutput> {\n constructor(options: VideoDevtoolsBridgeOptions<TOutput>) {\n super(options)\n }\n\n recordJobIdChange(): void {}\n recordVideoStatusChange(): void {}\n}\n\n// Compile-time parity checks. If a public method is added to the real\n// bridge class without a matching stub on the no-op, the corresponding\n// `Exclude<...>` resolves to a non-`never` union, which violates the\n// `extends never` constraint below and fails the build — surfacing the\n// drift at build time instead of as a runtime TypeError later.\ntype AssertBridgeParity<TMissing extends never> = TMissing\ntype _ChatBridgeMissing = Exclude<\n keyof ChatDevtoolsBridge,\n keyof NoOpChatDevtoolsBridge\n>\ntype _GenerationBridgeMissing = Exclude<\n keyof GenerationDevtoolsBridge<unknown>,\n keyof NoOpGenerationDevtoolsBridge<unknown>\n>\ntype _VideoBridgeMissing = Exclude<\n keyof VideoDevtoolsBridge<unknown>,\n keyof NoOpVideoDevtoolsBridge<unknown>\n>\nconst _bridgeParity:\n | [\n AssertBridgeParity<_ChatBridgeMissing>,\n AssertBridgeParity<_GenerationBridgeMissing>,\n AssertBridgeParity<_VideoBridgeMissing>,\n ]\n | undefined = undefined\nvoid _bridgeParity\n\n// ===========================================================================\n// Factories — these are what the clients call when no real factory was\n// supplied in options.\n// ===========================================================================\n\n// Casts use `unknown` because the no-op classes don't `extend` the real bridge\n// (that would pull the real implementation into the main-entry import graph).\n// Structural parity is enforced by the `_*BridgeMissing` checks above.\n\nexport const createNoOpChatDevtoolsBridge: ChatDevtoolsBridgeFactory = (\n options,\n) =>\n // oxlint-disable-next-line eslint-js/no-restricted-syntax -- see comment above\n new NoOpChatDevtoolsBridge(options) as unknown as ChatDevtoolsBridge\n\nexport const createNoOpGenerationDevtoolsBridge: GenerationDevtoolsBridgeFactory =\n <TOutput>(options: GenerationDevtoolsBridgeOptions<TOutput>) =>\n // oxlint-disable-next-line eslint-js/no-restricted-syntax -- see comment above\n new NoOpGenerationDevtoolsBridge<TOutput>(\n options,\n ) as unknown as GenerationDevtoolsBridge<TOutput>\n\nexport const createNoOpVideoDevtoolsBridge: VideoDevtoolsBridgeFactory = <\n TOutput,\n>(\n options: VideoDevtoolsBridgeOptions<TOutput>,\n) =>\n // oxlint-disable-next-line eslint-js/no-restricted-syntax -- see comment above\n new NoOpVideoDevtoolsBridge<TOutput>(\n options,\n ) as unknown as VideoDevtoolsBridge<TOutput>\n"],"mappings":";;AAwCA,IAAM,6BAAN,cAAyC,uBAAuB;CAC9D,YAA4B,CAE5B;AACF;AAOA,IAAa,yBAAb,MAAoC;CAClC;CAEA,YAAY,SAAoC;EAC9C,KAAK,SAAS,IAAI,2BAA2B,QAAQ,QAAQ;CAC/D;CAGA,iBAAuB,CAAC;CACxB,cAAoB,CAAC;CACrB,eAAqB,CAAC;CACtB,sBAA4B,CAAC;CAC7B,iBACE,YACA,QACA,SACA,UACM,CAAC;CACT,aAAmB,CAAC;CACpB,YAAkB,CAAC;CACnB,UAAgB,CAAC;CAGjB,eAAe,sBAAoC,CAAC;CACpD,qBAA2B,CAAC;CAC5B,mBAAmB,WAAgC,CAAC;CACpD,eAAe,WAAyB,CAAC;CACzC,qBAAoC;EAClC,OAAO;CACT;CACA,kBAAiC;EAC/B,OAAO;CACT;CACA,kBAA0B;EACxB,OAAO;CACT;CACA,aAAa,QAA2B,CAAC;CACzC,kBAAkB,QAAuB,CAAC;CAC1C,sBAAsB,YAAoB,QAAuB,CAAC;CAClE,sBAAsB,QAAuB,CAAC;CAC9C,kBAAkB,QAAuB,CAAC;CAC1C,SAAS,QAAgB,WAAyB,CAAC;CACnD,4BAAmE,CAEnE;CACA,kCAAyE,CAEzE;CACA,oBAAoB,YAA4C;EAC9D,OAAO,EAAE,WAAW;CACtB;CACA,MAAM,aAAa,UAAgD,CAEnE;AACF;AAEA,IAAa,+BAAb,MAAmD;CACjD,YAAY,UAAoD,CAAC;CAGjE,iBAAuB,CAAC;CACxB,cAAoB,CAAC;CACrB,eAAqB,CAAC;CACtB,sBAA4B,CAAC;CAC7B,mBAAyB,CAAC;CAC1B,aAAmB,CAAC;CACpB,YAAkB,CAAC;CACnB,UAAgB,CAAC;CAGjB,SAAS,QAAyB;EAIhC,OAAO,YAAY,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;CACxE;CACA,iBAAiB,QAAsB,CAAC;CACxC,UACE,QACA,YACA,SACA,QACM,CAAC;CACT,iBAAgC;EAC9B,OAAO;CACT;CACA,YAAkB,CAAC;CACnB,qBAA2B,CAAC;CAC5B,sBAA4B,CAAC;CAC7B,kBAAkB,QAAiC,CAAC;CACpD,qBAA2B,CAAC;CAC5B,uBAA6B,CAAC;CAC9B,YAAkB,CAAC;AACrB;AAEA,IAAa,0BAAb,cAEU,6BAAsC;CAC9C,YAAY,SAA8C;EACxD,MAAM,OAAO;CACf;CAEA,oBAA0B,CAAC;CAC3B,0BAAgC,CAAC;AACnC;AAsCA,IAAa,gCACX,YAGA,IAAI,uBAAuB,OAAO;AAEpC,IAAa,sCACD,YAER,IAAI,6BACF,OACF;AAEJ,IAAa,iCAGX,YAGA,IAAI,wBACF,OACF"}
@@ -139,7 +139,7 @@ export declare class ClientDevtoolsBridge<TSnapshot extends object> {
139
139
  protected onReplayState(): void;
140
140
  private handleToolFixtureApply;
141
141
  private matchesFixtureTarget;
142
- protected createEnvelope(eventType: 'hook:registered' | 'hook:updated' | 'hook:unregistered' | 'hook:state-snapshot' | 'tools:registered' | 'memory:retrieve:started' | 'memory:retrieve:completed' | 'memory:snapshot' | 'skills:snapshot' | AIDevtoolsRunEventType, visibility?: AIDevtoolsEventVisibility, context?: {
142
+ protected createEnvelope(eventType: 'hook:registered' | 'hook:updated' | 'hook:unregistered' | 'hook:state-snapshot' | 'tools:registered' | 'memory:retrieve:started' | 'memory:retrieve:completed' | 'memory:snapshot' | 'compaction:started' | 'compaction:state' | 'compaction:ended' | 'skills:snapshot' | AIDevtoolsRunEventType, visibility?: AIDevtoolsEventVisibility, context?: {
143
143
  runId?: string;
144
144
  }): import('@tanstack/ai-event-client').AIDevtoolsEventEnvelope;
145
145
  private createMetadataPayload;
@@ -160,6 +160,8 @@ export declare class ChatDevtoolsBridge extends ClientDevtoolsBridge<AIDevtoolsC
160
160
  private lastRunEventContext;
161
161
  /** Last transported `memory:state` value, replayed when a panel opens. */
162
162
  private lastMemoryStateValue;
163
+ /** Transported compaction CUSTOM events, replayed when a panel opens. */
164
+ private readonly lastCompactionEvents;
163
165
  /** Last transported `skills:state` value, replayed when a panel opens. */
164
166
  private lastSkillsStateValue;
165
167
  constructor(options: ChatDevtoolsBridgeOptions);
@@ -196,6 +198,14 @@ export declare class ChatDevtoolsBridge extends ClientDevtoolsBridge<AIDevtoolsC
196
198
  * adapter supports introspection.
197
199
  */
198
200
  private emitMemoryState;
201
+ /**
202
+ * Record a transported compaction CUSTOM event. Called from the chat
203
+ * client's `onCustomEvent` handler so server-side compaction reaches the
204
+ * browser DevTools panel.
205
+ */
206
+ recordCompactionEvent(eventType: string, rawValue: unknown): void;
207
+ recordCompactionState(rawValue: unknown): void;
208
+ private emitCompactionEvent;
199
209
  private emitSkillsState;
200
210
  protected onReplayState(): void;
201
211
  getCurrentRunEventContext(): ChatClientRunEventContext | undefined;
@@ -2,6 +2,55 @@ import { DefaultChatClientEventEmitter } from "./events.js";
2
2
  import { convertSchemaToJsonSchema } from "@tanstack/ai/client";
3
3
  import { aiEventClient, createAIDevtoolsEventEnvelope, emitAIDevtoolsEvent } from "@tanstack/ai-event-client";
4
4
  //#region src/devtools.ts
5
+ function readCompactionBoundaryValue(rawValue) {
6
+ if (!rawValue || typeof rawValue !== "object") return {};
7
+ return {
8
+ ..."before" in rawValue && typeof rawValue.before === "number" ? { before: rawValue.before } : {},
9
+ ..."after" in rawValue && typeof rawValue.after === "number" ? { after: rawValue.after } : {},
10
+ ..."messagesBefore" in rawValue && typeof rawValue.messagesBefore === "number" ? { messagesBefore: rawValue.messagesBefore } : {},
11
+ ..."messagesAfter" in rawValue && typeof rawValue.messagesAfter === "number" ? { messagesAfter: rawValue.messagesAfter } : {},
12
+ ..."reusedCheckpoint" in rawValue && typeof rawValue.reusedCheckpoint === "boolean" ? { reusedCheckpoint: rawValue.reusedCheckpoint } : {},
13
+ ..."maxTokens" in rawValue && typeof rawValue.maxTokens === "number" ? { maxTokens: rawValue.maxTokens } : {},
14
+ ..."strategyKey" in rawValue && typeof rawValue.strategyKey === "string" ? { strategyKey: rawValue.strategyKey } : {},
15
+ ..."durationMs" in rawValue && typeof rawValue.durationMs === "number" ? { durationMs: rawValue.durationMs } : {}
16
+ };
17
+ }
18
+ function readPreviewList(value) {
19
+ if (!Array.isArray(value)) return void 0;
20
+ const previews = [];
21
+ for (const item of value) {
22
+ if (!item || typeof item !== "object") continue;
23
+ if (!("role" in item) || !("tokens" in item) || !("text" in item)) continue;
24
+ if (typeof item.role !== "string" || typeof item.tokens !== "number" || typeof item.text !== "string") continue;
25
+ previews.push({
26
+ role: item.role,
27
+ tokens: item.tokens,
28
+ text: item.text
29
+ });
30
+ }
31
+ return previews;
32
+ }
33
+ function readCompactionStateValue(rawValue) {
34
+ if (!rawValue || typeof rawValue !== "object") return null;
35
+ if (!("before" in rawValue) || !("after" in rawValue) || !("messagesBefore" in rawValue) || !("messagesAfter" in rawValue)) return null;
36
+ if (typeof rawValue.before !== "number" || typeof rawValue.after !== "number" || typeof rawValue.messagesBefore !== "number" || typeof rawValue.messagesAfter !== "number") return null;
37
+ const reusedCheckpoint = "reusedCheckpoint" in rawValue && rawValue.reusedCheckpoint === true;
38
+ const maxTokens = "maxTokens" in rawValue && typeof rawValue.maxTokens === "number" ? rawValue.maxTokens : void 0;
39
+ const strategyKey = "strategyKey" in rawValue && typeof rawValue.strategyKey === "string" ? rawValue.strategyKey : void 0;
40
+ const dropped = "dropped" in rawValue ? readPreviewList(rawValue.dropped) : void 0;
41
+ const result = "result" in rawValue ? readPreviewList(rawValue.result) : void 0;
42
+ return {
43
+ before: rawValue.before,
44
+ after: rawValue.after,
45
+ messagesBefore: rawValue.messagesBefore,
46
+ messagesAfter: rawValue.messagesAfter,
47
+ reusedCheckpoint,
48
+ ...maxTokens !== void 0 ? { maxTokens } : {},
49
+ ...strategyKey ? { strategyKey } : {},
50
+ ...dropped ? { dropped } : {},
51
+ ...result ? { result } : {}
52
+ };
53
+ }
5
54
  function createAIDevtoolsGenerationPreview(input) {
6
55
  if (input.outputKind === "image") return imagePreviewFromResult(input.result);
7
56
  if (input.outputKind === "audio") return audioPreviewFromResult(input.result);
@@ -336,6 +385,8 @@ var ChatDevtoolsBridge = class extends ClientDevtoolsBridge {
336
385
  lastRunEventContext;
337
386
  /** Last transported `memory:state` value, replayed when a panel opens. */
338
387
  lastMemoryStateValue = null;
388
+ /** Transported compaction CUSTOM events, replayed when a panel opens. */
389
+ lastCompactionEvents = [];
339
390
  /** Last transported `skills:state` value, replayed when a panel opens. */
340
391
  lastSkillsStateValue = null;
341
392
  constructor(options) {
@@ -455,6 +506,49 @@ var ChatDevtoolsBridge = class extends ClientDevtoolsBridge {
455
506
  facts: value.snapshot.facts ?? []
456
507
  });
457
508
  }
509
+ /**
510
+ * Record a transported compaction CUSTOM event. Called from the chat
511
+ * client's `onCustomEvent` handler so server-side compaction reaches the
512
+ * browser DevTools panel.
513
+ */
514
+ recordCompactionEvent(eventType, rawValue) {
515
+ this.lastCompactionEvents.push({
516
+ eventType,
517
+ value: rawValue
518
+ });
519
+ if (this.lastCompactionEvents.length > 60) this.lastCompactionEvents.splice(0, this.lastCompactionEvents.length - 60);
520
+ this.emitCompactionEvent(eventType, rawValue);
521
+ }
522
+ recordCompactionState(rawValue) {
523
+ this.recordCompactionEvent("compaction:state", rawValue);
524
+ }
525
+ emitCompactionEvent(eventType, rawValue) {
526
+ const runContext = this.currentRunId ? { runId: this.currentRunId } : {};
527
+ if (eventType === "compaction:started") {
528
+ const value = readCompactionBoundaryValue(rawValue);
529
+ emitAIDevtoolsEvent("compaction:started", {
530
+ ...this.createEnvelope("compaction:started", "client-state", runContext),
531
+ ...value
532
+ });
533
+ return;
534
+ }
535
+ if (eventType === "compaction:ended") {
536
+ const value = readCompactionBoundaryValue(rawValue);
537
+ emitAIDevtoolsEvent("compaction:ended", {
538
+ ...this.createEnvelope("compaction:ended", "client-state", runContext),
539
+ ...value
540
+ });
541
+ return;
542
+ }
543
+ if (eventType === "compaction:state") {
544
+ const value = readCompactionStateValue(rawValue);
545
+ if (!value) return;
546
+ emitAIDevtoolsEvent("compaction:state", {
547
+ ...this.createEnvelope("compaction:state", "client-state", runContext),
548
+ ...value
549
+ });
550
+ }
551
+ }
458
552
  emitSkillsState(rawValue) {
459
553
  if (!rawValue || typeof rawValue !== "object") return;
460
554
  const value = rawValue;
@@ -469,6 +563,7 @@ var ChatDevtoolsBridge = class extends ClientDevtoolsBridge {
469
563
  }
470
564
  onReplayState() {
471
565
  if (this.lastMemoryStateValue != null) this.emitMemoryState(this.lastMemoryStateValue);
566
+ for (const event of this.lastCompactionEvents) this.emitCompactionEvent(event.eventType, event.value);
472
567
  if (this.lastSkillsStateValue != null) this.emitSkillsState(this.lastSkillsStateValue);
473
568
  }
474
569
  getCurrentRunEventContext() {