@tanstack/ai-client 0.29.0 → 0.29.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/chat-client.d.ts +6 -0
- package/dist/esm/chat-client.js +28 -4
- package/dist/esm/chat-client.js.map +1 -1
- package/dist/esm/connection-adapters.js +15 -0
- package/dist/esm/connection-adapters.js.map +1 -1
- package/dist/esm/devtools-noop.d.ts +3 -0
- package/dist/esm/devtools-noop.js +3 -0
- package/dist/esm/devtools-noop.js.map +1 -1
- package/dist/esm/devtools.d.ts +15 -1
- package/dist/esm/devtools.js +149 -10
- package/dist/esm/devtools.js.map +1 -1
- package/package.json +3 -3
- package/src/chat-client.ts +50 -8
- package/src/connection-adapters.ts +23 -0
- package/src/devtools-noop.ts +3 -0
- package/src/devtools.ts +280 -12
|
@@ -26,6 +26,9 @@ 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;
|
|
31
|
+
recordSkillsState(_value: unknown): void;
|
|
29
32
|
beginRun(_runId: string, _threadId: string): void;
|
|
30
33
|
getCurrentRunEventContext(): ChatClientRunEventContext | undefined;
|
|
31
34
|
getCurrentOrLastRunEventContext(): ChatClientRunEventContext | undefined;
|
|
@@ -31,6 +31,9 @@ var NoOpChatDevtoolsBridge = class {
|
|
|
31
31
|
}
|
|
32
32
|
observeChunk(_chunk) {}
|
|
33
33
|
recordMemoryState(_value) {}
|
|
34
|
+
recordCompactionEvent(_eventType, _value) {}
|
|
35
|
+
recordCompactionState(_value) {}
|
|
36
|
+
recordSkillsState(_value) {}
|
|
34
37
|
beginRun(_runId, _threadId) {}
|
|
35
38
|
getCurrentRunEventContext() {}
|
|
36
39
|
getCurrentOrLastRunEventContext() {}
|
|
@@ -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 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,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"}
|
package/dist/esm/devtools.d.ts
CHANGED
|
@@ -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' | 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,10 @@ 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;
|
|
165
|
+
/** Last transported `skills:state` value, replayed when a panel opens. */
|
|
166
|
+
private lastSkillsStateValue;
|
|
163
167
|
constructor(options: ChatDevtoolsBridgeOptions);
|
|
164
168
|
setCurrentStreamId(streamId: string | null): void;
|
|
165
169
|
/**
|
|
@@ -185,6 +189,7 @@ export declare class ChatDevtoolsBridge extends ClientDevtoolsBridge<AIDevtoolsC
|
|
|
185
189
|
* `recordResultChange` / `recordProgressChange`.
|
|
186
190
|
*/
|
|
187
191
|
recordMemoryState(rawValue: unknown): void;
|
|
192
|
+
recordSkillsState(rawValue: unknown): void;
|
|
188
193
|
/**
|
|
189
194
|
* Re-emit the browser-side `memory:*` events from a transported
|
|
190
195
|
* `memory:state` value. The devtools store consumes these to render the
|
|
@@ -193,6 +198,15 @@ export declare class ChatDevtoolsBridge extends ClientDevtoolsBridge<AIDevtoolsC
|
|
|
193
198
|
* adapter supports introspection.
|
|
194
199
|
*/
|
|
195
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;
|
|
209
|
+
private emitSkillsState;
|
|
196
210
|
protected onReplayState(): void;
|
|
197
211
|
getCurrentRunEventContext(): ChatClientRunEventContext | undefined;
|
|
198
212
|
getCurrentOrLastRunEventContext(): ChatClientRunEventContext | undefined;
|
package/dist/esm/devtools.js
CHANGED
|
@@ -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);
|
|
@@ -136,6 +185,28 @@ function getActiveBridgeRegistry() {
|
|
|
136
185
|
global[activeBridgeRegistryKey] = registry;
|
|
137
186
|
return registry;
|
|
138
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* `{...options}` turns `get hookId()` into a data property. Chat/generation
|
|
190
|
+
* clients mint `threadId` after construct (`ensureThreadId` on mount), so a
|
|
191
|
+
* spread would freeze `hookId: ''` and DevTools could never select the hook.
|
|
192
|
+
*/
|
|
193
|
+
function withLiveClientIdentity(identity, rest) {
|
|
194
|
+
return {
|
|
195
|
+
get hookId() {
|
|
196
|
+
return identity.hookId;
|
|
197
|
+
},
|
|
198
|
+
get clientId() {
|
|
199
|
+
return identity.clientId;
|
|
200
|
+
},
|
|
201
|
+
get threadId() {
|
|
202
|
+
return identity.threadId;
|
|
203
|
+
},
|
|
204
|
+
metadata: identity.metadata,
|
|
205
|
+
getSnapshot: rest.getSnapshot,
|
|
206
|
+
...rest.getTools || identity.getTools ? { getTools: rest.getTools ?? identity.getTools } : {},
|
|
207
|
+
...rest.applyToolFixture || identity.applyToolFixture ? { applyToolFixture: rest.applyToolFixture ?? identity.applyToolFixture } : {}
|
|
208
|
+
};
|
|
209
|
+
}
|
|
139
210
|
var ClientDevtoolsBridge = class {
|
|
140
211
|
options;
|
|
141
212
|
unsubscribers = [];
|
|
@@ -314,13 +385,17 @@ var ChatDevtoolsBridge = class extends ClientDevtoolsBridge {
|
|
|
314
385
|
lastRunEventContext;
|
|
315
386
|
/** Last transported `memory:state` value, replayed when a panel opens. */
|
|
316
387
|
lastMemoryStateValue = null;
|
|
388
|
+
/** Transported compaction CUSTOM events, replayed when a panel opens. */
|
|
389
|
+
lastCompactionEvents = [];
|
|
390
|
+
/** Last transported `skills:state` value, replayed when a panel opens. */
|
|
391
|
+
lastSkillsStateValue = null;
|
|
317
392
|
constructor(options) {
|
|
318
|
-
super({
|
|
319
|
-
|
|
393
|
+
super(withLiveClientIdentity(options, {
|
|
394
|
+
getSnapshot: options.getSnapshot,
|
|
320
395
|
applyToolFixture: (fixture) => this.applyFixture(fixture)
|
|
321
|
-
});
|
|
396
|
+
}));
|
|
322
397
|
this.chatOptions = options;
|
|
323
|
-
this.events = new ChatDevtoolsAwareEventEmitter(options.clientId, this);
|
|
398
|
+
this.events = new ChatDevtoolsAwareEventEmitter(() => options.clientId, this);
|
|
324
399
|
}
|
|
325
400
|
setCurrentStreamId(streamId) {
|
|
326
401
|
this.currentStreamId = streamId;
|
|
@@ -389,6 +464,10 @@ var ChatDevtoolsBridge = class extends ClientDevtoolsBridge {
|
|
|
389
464
|
this.lastMemoryStateValue = rawValue;
|
|
390
465
|
this.emitMemoryState(rawValue);
|
|
391
466
|
}
|
|
467
|
+
recordSkillsState(rawValue) {
|
|
468
|
+
this.lastSkillsStateValue = rawValue;
|
|
469
|
+
this.emitSkillsState(rawValue);
|
|
470
|
+
}
|
|
392
471
|
/**
|
|
393
472
|
* Re-emit the browser-side `memory:*` events from a transported
|
|
394
473
|
* `memory:state` value. The devtools store consumes these to render the
|
|
@@ -427,8 +506,65 @@ var ChatDevtoolsBridge = class extends ClientDevtoolsBridge {
|
|
|
427
506
|
facts: value.snapshot.facts ?? []
|
|
428
507
|
});
|
|
429
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
|
+
}
|
|
552
|
+
emitSkillsState(rawValue) {
|
|
553
|
+
if (!rawValue || typeof rawValue !== "object") return;
|
|
554
|
+
const value = rawValue;
|
|
555
|
+
const catalog = Array.isArray(value.catalog) ? value.catalog : [];
|
|
556
|
+
const activated = Array.isArray(value.activated) ? value.activated : [];
|
|
557
|
+
const runContext = this.currentRunId ? { runId: this.currentRunId } : {};
|
|
558
|
+
emitAIDevtoolsEvent("skills:snapshot", {
|
|
559
|
+
...this.createEnvelope("skills:snapshot", "client-state", runContext),
|
|
560
|
+
catalog,
|
|
561
|
+
activated
|
|
562
|
+
});
|
|
563
|
+
}
|
|
430
564
|
onReplayState() {
|
|
431
565
|
if (this.lastMemoryStateValue != null) this.emitMemoryState(this.lastMemoryStateValue);
|
|
566
|
+
for (const event of this.lastCompactionEvents) this.emitCompactionEvent(event.eventType, event.value);
|
|
567
|
+
if (this.lastSkillsStateValue != null) this.emitSkillsState(this.lastSkillsStateValue);
|
|
432
568
|
}
|
|
433
569
|
getCurrentRunEventContext() {
|
|
434
570
|
if (!this.currentRunId) return void 0;
|
|
@@ -709,10 +845,7 @@ var GenerationDevtoolsBridge = class extends ClientDevtoolsBridge {
|
|
|
709
845
|
maxRuns;
|
|
710
846
|
getCoreState;
|
|
711
847
|
constructor(options) {
|
|
712
|
-
super({
|
|
713
|
-
...options,
|
|
714
|
-
getSnapshot: () => this.buildSnapshot()
|
|
715
|
-
});
|
|
848
|
+
super(withLiveClientIdentity(options, { getSnapshot: () => this.buildSnapshot() }));
|
|
716
849
|
this.maxRuns = options.maxRuns ?? 20;
|
|
717
850
|
this.getCoreState = options.getCoreState;
|
|
718
851
|
}
|
|
@@ -936,11 +1069,17 @@ var VideoDevtoolsBridge = class extends GenerationDevtoolsBridge {
|
|
|
936
1069
|
}
|
|
937
1070
|
};
|
|
938
1071
|
var ChatDevtoolsAwareEventEmitter = class extends DefaultChatClientEventEmitter {
|
|
1072
|
+
getClientId;
|
|
939
1073
|
helper;
|
|
940
|
-
constructor(
|
|
941
|
-
super(
|
|
1074
|
+
constructor(getClientId, helper) {
|
|
1075
|
+
super(getClientId());
|
|
1076
|
+
this.getClientId = getClientId;
|
|
942
1077
|
this.helper = helper;
|
|
943
1078
|
}
|
|
1079
|
+
emitEvent(eventName, data) {
|
|
1080
|
+
this.clientId = this.getClientId();
|
|
1081
|
+
super.emitEvent(eventName, data);
|
|
1082
|
+
}
|
|
944
1083
|
afterEmit(streamId) {
|
|
945
1084
|
if (streamId) this.helper.recordStreamId(streamId);
|
|
946
1085
|
this.helper.emitSnapshot();
|