@livekit/agents 1.0.46 → 1.0.48
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/beta/index.cjs +29 -0
- package/dist/beta/index.cjs.map +1 -0
- package/dist/beta/index.d.cts +2 -0
- package/dist/beta/index.d.ts +2 -0
- package/dist/beta/index.d.ts.map +1 -0
- package/dist/beta/index.js +7 -0
- package/dist/beta/index.js.map +1 -0
- package/dist/beta/workflows/index.cjs +29 -0
- package/dist/beta/workflows/index.cjs.map +1 -0
- package/dist/beta/workflows/index.d.cts +2 -0
- package/dist/beta/workflows/index.d.ts +2 -0
- package/dist/beta/workflows/index.d.ts.map +1 -0
- package/dist/beta/workflows/index.js +7 -0
- package/dist/beta/workflows/index.js.map +1 -0
- package/dist/beta/workflows/task_group.cjs +162 -0
- package/dist/beta/workflows/task_group.cjs.map +1 -0
- package/dist/beta/workflows/task_group.d.cts +32 -0
- package/dist/beta/workflows/task_group.d.ts +32 -0
- package/dist/beta/workflows/task_group.d.ts.map +1 -0
- package/dist/beta/workflows/task_group.js +138 -0
- package/dist/beta/workflows/task_group.js.map +1 -0
- package/dist/cli.cjs +14 -20
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +14 -20
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/inference/api_protos.d.cts +59 -59
- package/dist/inference/api_protos.d.ts +59 -59
- package/dist/ipc/job_proc_lazy_main.cjs +14 -5
- package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
- package/dist/ipc/job_proc_lazy_main.js +14 -5
- package/dist/ipc/job_proc_lazy_main.js.map +1 -1
- package/dist/llm/chat_context.cjs +108 -1
- package/dist/llm/chat_context.cjs.map +1 -1
- package/dist/llm/chat_context.d.cts +14 -1
- package/dist/llm/chat_context.d.ts +14 -1
- package/dist/llm/chat_context.d.ts.map +1 -1
- package/dist/llm/chat_context.js +108 -1
- package/dist/llm/chat_context.js.map +1 -1
- package/dist/llm/chat_context.test.cjs +43 -0
- package/dist/llm/chat_context.test.cjs.map +1 -1
- package/dist/llm/chat_context.test.js +43 -0
- package/dist/llm/chat_context.test.js.map +1 -1
- package/dist/llm/index.cjs +2 -0
- package/dist/llm/index.cjs.map +1 -1
- package/dist/llm/index.d.cts +1 -1
- package/dist/llm/index.d.ts +1 -1
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +3 -1
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/provider_format/index.cjs +2 -0
- package/dist/llm/provider_format/index.cjs.map +1 -1
- package/dist/llm/provider_format/index.d.cts +2 -2
- package/dist/llm/provider_format/index.d.ts +2 -2
- package/dist/llm/provider_format/index.d.ts.map +1 -1
- package/dist/llm/provider_format/index.js +6 -1
- package/dist/llm/provider_format/index.js.map +1 -1
- package/dist/llm/provider_format/openai.cjs +82 -2
- package/dist/llm/provider_format/openai.cjs.map +1 -1
- package/dist/llm/provider_format/openai.d.cts +1 -0
- package/dist/llm/provider_format/openai.d.ts +1 -0
- package/dist/llm/provider_format/openai.d.ts.map +1 -1
- package/dist/llm/provider_format/openai.js +80 -1
- package/dist/llm/provider_format/openai.js.map +1 -1
- package/dist/llm/provider_format/openai.test.cjs +326 -0
- package/dist/llm/provider_format/openai.test.cjs.map +1 -1
- package/dist/llm/provider_format/openai.test.js +327 -1
- package/dist/llm/provider_format/openai.test.js.map +1 -1
- package/dist/llm/provider_format/utils.cjs +4 -3
- package/dist/llm/provider_format/utils.cjs.map +1 -1
- package/dist/llm/provider_format/utils.d.ts.map +1 -1
- package/dist/llm/provider_format/utils.js +4 -3
- package/dist/llm/provider_format/utils.js.map +1 -1
- package/dist/llm/realtime.cjs.map +1 -1
- package/dist/llm/realtime.d.cts +1 -0
- package/dist/llm/realtime.d.ts +1 -0
- package/dist/llm/realtime.d.ts.map +1 -1
- package/dist/llm/realtime.js.map +1 -1
- package/dist/llm/tool_context.cjs +7 -0
- package/dist/llm/tool_context.cjs.map +1 -1
- package/dist/llm/tool_context.d.cts +10 -2
- package/dist/llm/tool_context.d.ts +10 -2
- package/dist/llm/tool_context.d.ts.map +1 -1
- package/dist/llm/tool_context.js +6 -0
- package/dist/llm/tool_context.js.map +1 -1
- package/dist/log.cjs +5 -2
- package/dist/log.cjs.map +1 -1
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js +5 -2
- package/dist/log.js.map +1 -1
- package/dist/stream/deferred_stream.cjs +15 -6
- package/dist/stream/deferred_stream.cjs.map +1 -1
- package/dist/stream/deferred_stream.d.ts.map +1 -1
- package/dist/stream/deferred_stream.js +15 -6
- package/dist/stream/deferred_stream.js.map +1 -1
- package/dist/utils.cjs +32 -2
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +7 -0
- package/dist/utils.d.ts +7 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +32 -2
- package/dist/utils.js.map +1 -1
- package/dist/utils.test.cjs +71 -0
- package/dist/utils.test.cjs.map +1 -1
- package/dist/utils.test.js +71 -0
- package/dist/utils.test.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.cts +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/voice/agent.cjs +153 -12
- package/dist/voice/agent.cjs.map +1 -1
- package/dist/voice/agent.d.cts +30 -4
- package/dist/voice/agent.d.ts +30 -4
- package/dist/voice/agent.d.ts.map +1 -1
- package/dist/voice/agent.js +149 -11
- package/dist/voice/agent.js.map +1 -1
- package/dist/voice/agent.test.cjs +120 -0
- package/dist/voice/agent.test.cjs.map +1 -1
- package/dist/voice/agent.test.js +122 -2
- package/dist/voice/agent.test.js.map +1 -1
- package/dist/voice/agent_activity.cjs +406 -298
- package/dist/voice/agent_activity.cjs.map +1 -1
- package/dist/voice/agent_activity.d.cts +41 -7
- package/dist/voice/agent_activity.d.ts +41 -7
- package/dist/voice/agent_activity.d.ts.map +1 -1
- package/dist/voice/agent_activity.js +407 -294
- package/dist/voice/agent_activity.js.map +1 -1
- package/dist/voice/agent_session.cjs +140 -40
- package/dist/voice/agent_session.cjs.map +1 -1
- package/dist/voice/agent_session.d.cts +19 -7
- package/dist/voice/agent_session.d.ts +19 -7
- package/dist/voice/agent_session.d.ts.map +1 -1
- package/dist/voice/agent_session.js +137 -37
- package/dist/voice/agent_session.js.map +1 -1
- package/dist/voice/audio_recognition.cjs +4 -0
- package/dist/voice/audio_recognition.cjs.map +1 -1
- package/dist/voice/audio_recognition.d.ts.map +1 -1
- package/dist/voice/audio_recognition.js +4 -0
- package/dist/voice/audio_recognition.js.map +1 -1
- package/dist/voice/generation.cjs +39 -19
- package/dist/voice/generation.cjs.map +1 -1
- package/dist/voice/generation.d.ts.map +1 -1
- package/dist/voice/generation.js +44 -20
- package/dist/voice/generation.js.map +1 -1
- package/dist/voice/index.cjs +2 -0
- package/dist/voice/index.cjs.map +1 -1
- package/dist/voice/index.d.cts +1 -1
- package/dist/voice/index.d.ts +1 -1
- package/dist/voice/index.d.ts.map +1 -1
- package/dist/voice/index.js +2 -1
- package/dist/voice/index.js.map +1 -1
- package/dist/voice/room_io/room_io.cjs +11 -2
- package/dist/voice/room_io/room_io.cjs.map +1 -1
- package/dist/voice/room_io/room_io.d.ts.map +1 -1
- package/dist/voice/room_io/room_io.js +12 -3
- package/dist/voice/room_io/room_io.js.map +1 -1
- package/dist/voice/speech_handle.cjs +7 -1
- package/dist/voice/speech_handle.cjs.map +1 -1
- package/dist/voice/speech_handle.d.cts +2 -0
- package/dist/voice/speech_handle.d.ts +2 -0
- package/dist/voice/speech_handle.d.ts.map +1 -1
- package/dist/voice/speech_handle.js +8 -2
- package/dist/voice/speech_handle.js.map +1 -1
- package/dist/voice/testing/fake_llm.cjs +127 -0
- package/dist/voice/testing/fake_llm.cjs.map +1 -0
- package/dist/voice/testing/fake_llm.d.cts +30 -0
- package/dist/voice/testing/fake_llm.d.ts +30 -0
- package/dist/voice/testing/fake_llm.d.ts.map +1 -0
- package/dist/voice/testing/fake_llm.js +103 -0
- package/dist/voice/testing/fake_llm.js.map +1 -0
- package/dist/voice/testing/index.cjs +3 -0
- package/dist/voice/testing/index.cjs.map +1 -1
- package/dist/voice/testing/index.d.cts +1 -0
- package/dist/voice/testing/index.d.ts +1 -0
- package/dist/voice/testing/index.d.ts.map +1 -1
- package/dist/voice/testing/index.js +2 -0
- package/dist/voice/testing/index.js.map +1 -1
- package/dist/voice/testing/run_result.cjs +66 -15
- package/dist/voice/testing/run_result.cjs.map +1 -1
- package/dist/voice/testing/run_result.d.cts +14 -3
- package/dist/voice/testing/run_result.d.ts +14 -3
- package/dist/voice/testing/run_result.d.ts.map +1 -1
- package/dist/voice/testing/run_result.js +66 -15
- package/dist/voice/testing/run_result.js.map +1 -1
- package/package.json +1 -1
- package/src/beta/index.ts +9 -0
- package/src/beta/workflows/index.ts +9 -0
- package/src/beta/workflows/task_group.ts +194 -0
- package/src/cli.ts +20 -33
- package/src/index.ts +2 -1
- package/src/ipc/job_proc_lazy_main.ts +16 -5
- package/src/llm/chat_context.test.ts +48 -0
- package/src/llm/chat_context.ts +158 -0
- package/src/llm/index.ts +1 -0
- package/src/llm/provider_format/index.ts +7 -2
- package/src/llm/provider_format/openai.test.ts +385 -1
- package/src/llm/provider_format/openai.ts +103 -0
- package/src/llm/provider_format/utils.ts +6 -4
- package/src/llm/realtime.ts +1 -0
- package/src/llm/tool_context.ts +14 -0
- package/src/log.ts +5 -2
- package/src/stream/deferred_stream.ts +17 -6
- package/src/utils.test.ts +87 -0
- package/src/utils.ts +41 -2
- package/src/version.ts +1 -1
- package/src/voice/agent.test.ts +140 -2
- package/src/voice/agent.ts +200 -10
- package/src/voice/agent_activity.ts +466 -290
- package/src/voice/agent_session.ts +178 -40
- package/src/voice/audio_recognition.ts +4 -0
- package/src/voice/generation.ts +52 -23
- package/src/voice/index.ts +1 -1
- package/src/voice/room_io/room_io.ts +14 -3
- package/src/voice/speech_handle.ts +9 -2
- package/src/voice/testing/fake_llm.ts +138 -0
- package/src/voice/testing/index.ts +2 -0
- package/src/voice/testing/run_result.ts +81 -23
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AudioFrame, VideoFrame } from '@livekit/rtc-node';
|
|
2
|
+
import type { LLM } from './llm.js';
|
|
2
3
|
import { type ProviderFormat } from './provider_format/index.js';
|
|
3
4
|
import type { JSONObject, JSONValue, ToolContext } from './tool_context.js';
|
|
4
5
|
export type ChatRole = 'developer' | 'system' | 'user' | 'assistant';
|
|
@@ -41,12 +42,14 @@ export declare class ChatMessage {
|
|
|
41
42
|
interrupted: boolean;
|
|
42
43
|
hash?: Uint8Array;
|
|
43
44
|
createdAt: number;
|
|
45
|
+
extra: Record<string, unknown>;
|
|
44
46
|
constructor(params: {
|
|
45
47
|
role: ChatRole;
|
|
46
48
|
content: ChatContent[] | string;
|
|
47
49
|
id?: string;
|
|
48
50
|
interrupted?: boolean;
|
|
49
51
|
createdAt?: number;
|
|
52
|
+
extra?: Record<string, unknown>;
|
|
50
53
|
});
|
|
51
54
|
static create(params: {
|
|
52
55
|
role: ChatRole;
|
|
@@ -54,6 +57,7 @@ export declare class ChatMessage {
|
|
|
54
57
|
id?: string;
|
|
55
58
|
interrupted?: boolean;
|
|
56
59
|
createdAt?: number;
|
|
60
|
+
extra?: Record<string, unknown>;
|
|
57
61
|
}): ChatMessage;
|
|
58
62
|
/**
|
|
59
63
|
* Returns a single string with all text parts of the message joined by new
|
|
@@ -165,6 +169,7 @@ export declare class ChatContext {
|
|
|
165
169
|
id?: string;
|
|
166
170
|
interrupted?: boolean;
|
|
167
171
|
createdAt?: number;
|
|
172
|
+
extra?: Record<string, unknown>;
|
|
168
173
|
}): ChatMessage;
|
|
169
174
|
/**
|
|
170
175
|
* Insert a single item or multiple items based on their `createdAt` field so
|
|
@@ -177,8 +182,13 @@ export declare class ChatContext {
|
|
|
177
182
|
excludeFunctionCall?: boolean;
|
|
178
183
|
excludeInstructions?: boolean;
|
|
179
184
|
excludeEmptyMessage?: boolean;
|
|
185
|
+
excludeHandoff?: boolean;
|
|
180
186
|
toolCtx?: ToolContext<any>;
|
|
181
187
|
}): ChatContext;
|
|
188
|
+
merge(other: ChatContext, options?: {
|
|
189
|
+
excludeFunctionCall?: boolean;
|
|
190
|
+
excludeInstructions?: boolean;
|
|
191
|
+
}): ChatContext;
|
|
182
192
|
truncate(maxItems: number): ChatContext;
|
|
183
193
|
toJSON(options?: {
|
|
184
194
|
excludeImage?: boolean;
|
|
@@ -186,7 +196,7 @@ export declare class ChatContext {
|
|
|
186
196
|
excludeTimestamp?: boolean;
|
|
187
197
|
excludeFunctionCall?: boolean;
|
|
188
198
|
}): JSONObject;
|
|
189
|
-
toProviderFormat(format: ProviderFormat, injectDummyUserMessage?: boolean): Promise<[Record<string, unknown>[], import("./provider_format/google.js").GoogleFormatData]
|
|
199
|
+
toProviderFormat(format: ProviderFormat, injectDummyUserMessage?: boolean): Promise<Record<string, any>[] | [Record<string, unknown>[], import("./provider_format/google.js").GoogleFormatData]>;
|
|
190
200
|
/**
|
|
191
201
|
* Internal helper used by `truncate` & `addMessage` to find the correct
|
|
192
202
|
* insertion index for a timestamp so the list remains sorted.
|
|
@@ -208,6 +218,9 @@ export declare class ChatContext {
|
|
|
208
218
|
* Compare two content arrays for equality.
|
|
209
219
|
*/
|
|
210
220
|
private compareContent;
|
|
221
|
+
_summarize(llm: LLM, options?: {
|
|
222
|
+
keepLastTurns?: number;
|
|
223
|
+
}): Promise<ChatContext>;
|
|
211
224
|
/**
|
|
212
225
|
* Indicates whether the context is read-only
|
|
213
226
|
*/
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AudioFrame, VideoFrame } from '@livekit/rtc-node';
|
|
2
|
+
import type { LLM } from './llm.js';
|
|
2
3
|
import { type ProviderFormat } from './provider_format/index.js';
|
|
3
4
|
import type { JSONObject, JSONValue, ToolContext } from './tool_context.js';
|
|
4
5
|
export type ChatRole = 'developer' | 'system' | 'user' | 'assistant';
|
|
@@ -41,12 +42,14 @@ export declare class ChatMessage {
|
|
|
41
42
|
interrupted: boolean;
|
|
42
43
|
hash?: Uint8Array;
|
|
43
44
|
createdAt: number;
|
|
45
|
+
extra: Record<string, unknown>;
|
|
44
46
|
constructor(params: {
|
|
45
47
|
role: ChatRole;
|
|
46
48
|
content: ChatContent[] | string;
|
|
47
49
|
id?: string;
|
|
48
50
|
interrupted?: boolean;
|
|
49
51
|
createdAt?: number;
|
|
52
|
+
extra?: Record<string, unknown>;
|
|
50
53
|
});
|
|
51
54
|
static create(params: {
|
|
52
55
|
role: ChatRole;
|
|
@@ -54,6 +57,7 @@ export declare class ChatMessage {
|
|
|
54
57
|
id?: string;
|
|
55
58
|
interrupted?: boolean;
|
|
56
59
|
createdAt?: number;
|
|
60
|
+
extra?: Record<string, unknown>;
|
|
57
61
|
}): ChatMessage;
|
|
58
62
|
/**
|
|
59
63
|
* Returns a single string with all text parts of the message joined by new
|
|
@@ -165,6 +169,7 @@ export declare class ChatContext {
|
|
|
165
169
|
id?: string;
|
|
166
170
|
interrupted?: boolean;
|
|
167
171
|
createdAt?: number;
|
|
172
|
+
extra?: Record<string, unknown>;
|
|
168
173
|
}): ChatMessage;
|
|
169
174
|
/**
|
|
170
175
|
* Insert a single item or multiple items based on their `createdAt` field so
|
|
@@ -177,8 +182,13 @@ export declare class ChatContext {
|
|
|
177
182
|
excludeFunctionCall?: boolean;
|
|
178
183
|
excludeInstructions?: boolean;
|
|
179
184
|
excludeEmptyMessage?: boolean;
|
|
185
|
+
excludeHandoff?: boolean;
|
|
180
186
|
toolCtx?: ToolContext<any>;
|
|
181
187
|
}): ChatContext;
|
|
188
|
+
merge(other: ChatContext, options?: {
|
|
189
|
+
excludeFunctionCall?: boolean;
|
|
190
|
+
excludeInstructions?: boolean;
|
|
191
|
+
}): ChatContext;
|
|
182
192
|
truncate(maxItems: number): ChatContext;
|
|
183
193
|
toJSON(options?: {
|
|
184
194
|
excludeImage?: boolean;
|
|
@@ -186,7 +196,7 @@ export declare class ChatContext {
|
|
|
186
196
|
excludeTimestamp?: boolean;
|
|
187
197
|
excludeFunctionCall?: boolean;
|
|
188
198
|
}): JSONObject;
|
|
189
|
-
toProviderFormat(format: ProviderFormat, injectDummyUserMessage?: boolean): Promise<[Record<string, unknown>[], import("./provider_format/google.js").GoogleFormatData]
|
|
199
|
+
toProviderFormat(format: ProviderFormat, injectDummyUserMessage?: boolean): Promise<Record<string, any>[] | [Record<string, unknown>[], import("./provider_format/google.js").GoogleFormatData]>;
|
|
190
200
|
/**
|
|
191
201
|
* Internal helper used by `truncate` & `addMessage` to find the correct
|
|
192
202
|
* insertion index for a timestamp so the list remains sorted.
|
|
@@ -208,6 +218,9 @@ export declare class ChatContext {
|
|
|
208
218
|
* Compare two content arrays for equality.
|
|
209
219
|
*/
|
|
210
220
|
private compareContent;
|
|
221
|
+
_summarize(llm: LLM, options?: {
|
|
222
|
+
keepLastTurns?: number;
|
|
223
|
+
}): Promise<ChatContext>;
|
|
211
224
|
/**
|
|
212
225
|
* Indicates whether the context is read-only
|
|
213
226
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat_context.d.ts","sourceRoot":"","sources":["../../src/llm/chat_context.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEhE,OAAO,EAAE,KAAK,cAAc,EAAa,MAAM,4BAA4B,CAAC;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE5E,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AACrE,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IAEX,IAAI,EAAE,eAAe,CAAC;IAEtB;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,UAAU,CAAC;IAE3B,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;IAEzC,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,eAAe,CAAC;IAEtB,KAAK,EAAE,UAAU,EAAE,CAAC;IAEpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,YAAY,GAAG,MAAM,CAAC;AAE/D,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,KAAK,EAAE,MAAM,GAAG,UAAU,CAAC;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,YAAY,CAoBf;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,YAAY,CAQf;AAED,qBAAa,WAAW;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,QAAQ,CAAC,IAAI,YAAsB;IAEnC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAExB,OAAO,EAAE,WAAW,EAAE,CAAC;IAEvB,WAAW,EAAE,OAAO,CAAC;IAErB,IAAI,CAAC,EAAE,UAAU,CAAC;IAElB,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"chat_context.d.ts","sourceRoot":"","sources":["../../src/llm/chat_context.ts"],"names":[],"mappings":"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"}
|
package/dist/llm/chat_context.js
CHANGED
|
@@ -36,19 +36,22 @@ class ChatMessage {
|
|
|
36
36
|
interrupted;
|
|
37
37
|
hash;
|
|
38
38
|
createdAt;
|
|
39
|
+
extra;
|
|
39
40
|
constructor(params) {
|
|
40
41
|
const {
|
|
41
42
|
role,
|
|
42
43
|
content,
|
|
43
44
|
id = shortuuid("item_"),
|
|
44
45
|
interrupted = false,
|
|
45
|
-
createdAt = Date.now()
|
|
46
|
+
createdAt = Date.now(),
|
|
47
|
+
extra = {}
|
|
46
48
|
} = params;
|
|
47
49
|
this.id = id;
|
|
48
50
|
this.role = role;
|
|
49
51
|
this.content = Array.isArray(content) ? content : [content];
|
|
50
52
|
this.interrupted = interrupted;
|
|
51
53
|
this.createdAt = createdAt;
|
|
54
|
+
this.extra = extra;
|
|
52
55
|
}
|
|
53
56
|
static create(params) {
|
|
54
57
|
return new ChatMessage(params);
|
|
@@ -284,11 +287,13 @@ class ChatContext {
|
|
|
284
287
|
const idx = this._items.findIndex((i) => i.id === itemId);
|
|
285
288
|
return idx !== -1 ? idx : void 0;
|
|
286
289
|
}
|
|
290
|
+
// TODO(parity): Add excludeConfigUpdate option when AgentConfigUpdate is ported
|
|
287
291
|
copy(options = {}) {
|
|
288
292
|
const {
|
|
289
293
|
excludeFunctionCall = false,
|
|
290
294
|
excludeInstructions = false,
|
|
291
295
|
excludeEmptyMessage = false,
|
|
296
|
+
excludeHandoff = false,
|
|
292
297
|
toolCtx
|
|
293
298
|
} = options;
|
|
294
299
|
const items = [];
|
|
@@ -304,6 +309,9 @@ class ChatContext {
|
|
|
304
309
|
if (excludeEmptyMessage && isChatMessage(item) && item.content.length === 0) {
|
|
305
310
|
continue;
|
|
306
311
|
}
|
|
312
|
+
if (excludeHandoff && item.type === "agent_handoff") {
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
307
315
|
if (toolCtx !== void 0 && isToolCallOrOutput(item) && toolCtx[item.name] === void 0) {
|
|
308
316
|
continue;
|
|
309
317
|
}
|
|
@@ -311,6 +319,26 @@ class ChatContext {
|
|
|
311
319
|
}
|
|
312
320
|
return new ChatContext(items);
|
|
313
321
|
}
|
|
322
|
+
// TODO(parity): Add excludeConfigUpdate option when AgentConfigUpdate is ported
|
|
323
|
+
merge(other, options = {}) {
|
|
324
|
+
const { excludeFunctionCall = false, excludeInstructions = false } = options;
|
|
325
|
+
const existingIds = new Set(this._items.map((item) => item.id));
|
|
326
|
+
for (const item of other.items) {
|
|
327
|
+
if (excludeFunctionCall && ["function_call", "function_call_output"].includes(item.type)) {
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
if (excludeInstructions && item.type === "message" && (item.role === "system" || item.role === "developer")) {
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
if (existingIds.has(item.id)) {
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
const idx = this.findInsertionIndex(item.createdAt);
|
|
337
|
+
this._items.splice(idx, 0, item);
|
|
338
|
+
existingIds.add(item.id);
|
|
339
|
+
}
|
|
340
|
+
return this;
|
|
341
|
+
}
|
|
314
342
|
truncate(maxItems) {
|
|
315
343
|
if (maxItems <= 0) return this;
|
|
316
344
|
const instructions = this._items.find((i) => i.type === "message" && i.role === "system");
|
|
@@ -459,6 +487,85 @@ class ChatContext {
|
|
|
459
487
|
}
|
|
460
488
|
return true;
|
|
461
489
|
}
|
|
490
|
+
async _summarize(llm, options = {}) {
|
|
491
|
+
var _a, _b;
|
|
492
|
+
const { keepLastTurns = 2 } = options;
|
|
493
|
+
const toSummarize = [];
|
|
494
|
+
for (const item of this._items) {
|
|
495
|
+
if (item.type !== "message") continue;
|
|
496
|
+
if (item.role !== "user" && item.role !== "assistant") continue;
|
|
497
|
+
if (((_a = item.extra) == null ? void 0 : _a.is_summary) === true) continue;
|
|
498
|
+
const text = (item.textContent ?? "").trim();
|
|
499
|
+
if (text) {
|
|
500
|
+
toSummarize.push(item);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
if (toSummarize.length === 0) {
|
|
504
|
+
return this;
|
|
505
|
+
}
|
|
506
|
+
const tailN = Math.max(0, Math.min(toSummarize.length, keepLastTurns * 2));
|
|
507
|
+
let head;
|
|
508
|
+
let tail;
|
|
509
|
+
if (tailN === 0) {
|
|
510
|
+
head = toSummarize;
|
|
511
|
+
tail = [];
|
|
512
|
+
} else {
|
|
513
|
+
head = toSummarize.slice(0, -tailN);
|
|
514
|
+
tail = toSummarize.slice(-tailN);
|
|
515
|
+
}
|
|
516
|
+
if (head.length === 0) {
|
|
517
|
+
return this;
|
|
518
|
+
}
|
|
519
|
+
const sourceText = head.map((m) => `${m.role}: ${(m.textContent ?? "").trim()}`).join("\n").trim();
|
|
520
|
+
if (!sourceText) {
|
|
521
|
+
return this;
|
|
522
|
+
}
|
|
523
|
+
const promptCtx = new ChatContext();
|
|
524
|
+
promptCtx.addMessage({
|
|
525
|
+
role: "system",
|
|
526
|
+
content: "Compress older chat history into a short, faithful summary.\nFocus on user goals, constraints, decisions, key facts/preferences/entities, and pending tasks.\nExclude chit-chat and greetings. Be concise."
|
|
527
|
+
});
|
|
528
|
+
promptCtx.addMessage({
|
|
529
|
+
role: "user",
|
|
530
|
+
content: `Conversation to summarize:
|
|
531
|
+
|
|
532
|
+
${sourceText}`
|
|
533
|
+
});
|
|
534
|
+
const chunks = [];
|
|
535
|
+
for await (const chunk of llm.chat({ chatCtx: promptCtx })) {
|
|
536
|
+
if ((_b = chunk.delta) == null ? void 0 : _b.content) {
|
|
537
|
+
chunks.push(chunk.delta.content);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
const summary = chunks.join("").trim();
|
|
541
|
+
if (!summary) {
|
|
542
|
+
return this;
|
|
543
|
+
}
|
|
544
|
+
const tailStartTs = tail.length > 0 ? tail[0].createdAt : Infinity;
|
|
545
|
+
const preserved = [];
|
|
546
|
+
for (const it of this._items) {
|
|
547
|
+
if ((it.type === "function_call" || it.type === "function_call_output") && it.createdAt < tailStartTs) {
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
if (it.type === "message" && (it.role === "user" || it.role === "assistant")) {
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
preserved.push(it);
|
|
554
|
+
}
|
|
555
|
+
this._items = preserved;
|
|
556
|
+
const createdAtHint = tail.length > 0 ? tail[0].createdAt - 1e-3 : head[head.length - 1].createdAt + 1e-3;
|
|
557
|
+
this.addMessage({
|
|
558
|
+
role: "assistant",
|
|
559
|
+
content: `[history summary]
|
|
560
|
+
${summary}`,
|
|
561
|
+
createdAt: createdAtHint,
|
|
562
|
+
extra: { is_summary: true }
|
|
563
|
+
});
|
|
564
|
+
for (const msg of tail) {
|
|
565
|
+
this.insert(msg);
|
|
566
|
+
}
|
|
567
|
+
return this;
|
|
568
|
+
}
|
|
462
569
|
/**
|
|
463
570
|
* Indicates whether the context is read-only
|
|
464
571
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/llm/chat_context.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame, VideoFrame } from '@livekit/rtc-node';\nimport { createImmutableArray, shortuuid } from '../utils.js';\nimport { type ProviderFormat, toChatCtx } from './provider_format/index.js';\nimport type { JSONObject, JSONValue, ToolContext } from './tool_context.js';\n\nexport type ChatRole = 'developer' | 'system' | 'user' | 'assistant';\nexport interface ImageContent {\n id: string;\n\n type: 'image_content';\n\n /**\n * Either a string URL or a VideoFrame object.\n */\n image: string | VideoFrame;\n\n inferenceDetail: 'auto' | 'high' | 'low';\n\n inferenceWidth?: number;\n\n inferenceHeight?: number;\n\n mimeType?: string;\n\n _cache: Record<any, any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n}\n\nexport interface AudioContent {\n type: 'audio_content';\n\n frame: AudioFrame[];\n\n transcript?: string;\n}\n\nexport type ChatContent = ImageContent | AudioContent | string;\n\nexport function createImageContent(params: {\n image: string | VideoFrame;\n id?: string;\n inferenceDetail?: 'auto' | 'high' | 'low';\n inferenceWidth?: number;\n inferenceHeight?: number;\n mimeType?: string;\n}): ImageContent {\n const {\n image,\n id = shortuuid('img_'),\n inferenceDetail = 'auto',\n inferenceWidth,\n inferenceHeight,\n mimeType,\n } = params;\n\n return {\n id,\n type: 'image_content',\n image,\n inferenceDetail,\n inferenceWidth,\n inferenceHeight,\n mimeType,\n _cache: {},\n };\n}\n\nexport function createAudioContent(params: {\n frame: AudioFrame[];\n transcript?: string;\n}): AudioContent {\n const { frame, transcript } = params;\n\n return {\n type: 'audio_content',\n frame,\n transcript,\n };\n}\n\nexport class ChatMessage {\n readonly id: string;\n\n readonly type = 'message' as const;\n\n readonly role: ChatRole;\n\n content: ChatContent[];\n\n interrupted: boolean;\n\n hash?: Uint8Array;\n\n createdAt: number;\n\n constructor(params: {\n role: ChatRole;\n content: ChatContent[] | string;\n id?: string;\n interrupted?: boolean;\n createdAt?: number;\n }) {\n const {\n role,\n content,\n id = shortuuid('item_'),\n interrupted = false,\n createdAt = Date.now(),\n } = params;\n this.id = id;\n this.role = role;\n this.content = Array.isArray(content) ? content : [content];\n this.interrupted = interrupted;\n this.createdAt = createdAt;\n }\n\n static create(params: {\n role: ChatRole;\n content: ChatContent[] | string;\n id?: string;\n interrupted?: boolean;\n createdAt?: number;\n }) {\n return new ChatMessage(params);\n }\n\n /**\n * Returns a single string with all text parts of the message joined by new\n * lines. If no string content is present, returns `null`.\n */\n get textContent(): string | undefined {\n const parts = this.content.filter((c): c is string => typeof c === 'string');\n return parts.length > 0 ? parts.join('\\n') : undefined;\n }\n\n toJSONContent(): JSONValue[] {\n return this.content.map((c) => {\n if (typeof c === 'string') {\n return c as JSONValue;\n } else if (c.type === 'image_content') {\n return {\n id: c.id,\n type: c.type,\n image: c.image,\n inferenceDetail: c.inferenceDetail,\n inferenceWidth: c.inferenceWidth,\n inferenceHeight: c.inferenceHeight,\n mimeType: c.mimeType,\n } as JSONObject;\n } else {\n return {\n type: c.type,\n transcript: c.transcript,\n } as JSONObject;\n }\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n toJSON(excludeTimestamp: boolean = false): JSONValue {\n const result: JSONValue = {\n id: this.id,\n type: this.type,\n role: this.role,\n content: this.toJSONContent(),\n interrupted: this.interrupted,\n };\n\n if (!excludeTimestamp) {\n result.createdAt = this.createdAt;\n }\n\n return result;\n }\n}\n\nexport class FunctionCall {\n readonly id: string;\n\n readonly type = 'function_call' as const;\n\n callId: string;\n\n args: string;\n\n name: string;\n\n createdAt: number;\n\n extra: Record<string, unknown>;\n /**\n * Optional grouping identifier for parallel tool calls.\n */\n groupId?: string;\n\n /**\n * Opaque signature for Gemini thinking mode.\n * When using Gemini 3+ models with thinking enabled, this signature must be\n * preserved and returned with function responses to maintain thought context.\n */\n thoughtSignature?: string;\n\n constructor(params: {\n callId: string;\n name: string;\n args: string;\n id?: string;\n createdAt?: number;\n extra?: Record<string, unknown>;\n groupId?: string;\n thoughtSignature?: string;\n }) {\n const {\n callId,\n name,\n args,\n id = shortuuid('item_'),\n createdAt = Date.now(),\n extra = {},\n groupId,\n thoughtSignature,\n } = params;\n this.id = id;\n this.callId = callId;\n this.args = args;\n this.name = name;\n this.createdAt = createdAt;\n this.extra = { ...extra };\n this.groupId = groupId;\n this.thoughtSignature =\n thoughtSignature ??\n (typeof this.extra.google === 'object' && this.extra.google !== null\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this.extra.google as any).thoughtSignature ||\n (this.extra.google as any).thought_signature\n : undefined);\n }\n\n static create(params: {\n callId: string;\n name: string;\n args: string;\n id?: string;\n createdAt?: number;\n extra?: Record<string, unknown>;\n groupId?: string;\n thoughtSignature?: string;\n }) {\n return new FunctionCall(params);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n toJSON(excludeTimestamp: boolean = false): JSONValue {\n const result: JSONValue = {\n id: this.id,\n type: this.type,\n callId: this.callId,\n name: this.name,\n args: this.args,\n };\n\n if (Object.keys(this.extra).length > 0) {\n result.extra = this.extra as JSONValue;\n }\n\n if (this.groupId) {\n result.groupId = this.groupId;\n }\n\n if (this.thoughtSignature) {\n result.thoughtSignature = this.thoughtSignature;\n }\n\n if (!excludeTimestamp) {\n result.createdAt = this.createdAt;\n }\n\n return result;\n }\n}\n\nexport class FunctionCallOutput {\n readonly id: string;\n\n readonly type = 'function_call_output' as const;\n\n name = '';\n\n callId: string;\n\n output: string;\n\n isError: boolean;\n\n createdAt: number;\n\n constructor(params: {\n callId: string;\n output: string;\n isError: boolean;\n id?: string;\n createdAt?: number;\n name?: string;\n }) {\n const {\n callId,\n output,\n isError,\n id = shortuuid('item_'),\n createdAt = Date.now(),\n name = '',\n } = params;\n this.id = id;\n this.callId = callId;\n this.output = output;\n this.isError = isError;\n this.name = name;\n this.createdAt = createdAt;\n }\n\n static create(params: {\n callId: string;\n output: string;\n isError: boolean;\n id?: string;\n createdAt?: number;\n name?: string;\n }) {\n return new FunctionCallOutput(params);\n }\n\n toJSON(excludeTimestamp: boolean = false): JSONValue {\n const result: JSONValue = {\n id: this.id,\n type: this.type,\n name: this.name,\n callId: this.callId,\n output: this.output,\n isError: this.isError,\n };\n\n if (!excludeTimestamp) {\n result.createdAt = this.createdAt;\n }\n\n return result;\n }\n}\n\nexport class AgentHandoffItem {\n readonly id: string;\n\n readonly type = 'agent_handoff' as const;\n\n oldAgentId: string | undefined;\n\n newAgentId: string;\n\n createdAt: number;\n\n constructor(params: {\n oldAgentId?: string;\n newAgentId: string;\n id?: string;\n createdAt?: number;\n }) {\n const { oldAgentId, newAgentId, id = shortuuid('item_'), createdAt = Date.now() } = params;\n this.id = id;\n this.oldAgentId = oldAgentId;\n this.newAgentId = newAgentId;\n this.createdAt = createdAt;\n }\n\n static create(params: {\n oldAgentId?: string;\n newAgentId: string;\n id?: string;\n createdAt?: number;\n }) {\n return new AgentHandoffItem(params);\n }\n\n toJSON(excludeTimestamp: boolean = false): JSONValue {\n const result: JSONValue = {\n id: this.id,\n type: this.type,\n newAgentId: this.newAgentId,\n };\n\n if (this.oldAgentId !== undefined) {\n result.oldAgentId = this.oldAgentId;\n }\n\n if (!excludeTimestamp) {\n result.createdAt = this.createdAt;\n }\n\n return result;\n }\n}\n\nexport type ChatItem = ChatMessage | FunctionCall | FunctionCallOutput | AgentHandoffItem;\n\nexport class ChatContext {\n protected _items: ChatItem[];\n\n constructor(items?: ChatItem[]) {\n this._items = items ? items : [];\n }\n\n static empty(): ChatContext {\n return new ChatContext([]);\n }\n\n get items(): ChatItem[] {\n return this._items;\n }\n\n set items(items: ChatItem[]) {\n this._items = items;\n }\n\n /**\n * Add a new message to the context and return it.\n */\n addMessage(params: {\n role: ChatRole;\n content: ChatContent[] | string;\n id?: string;\n interrupted?: boolean;\n createdAt?: number;\n }): ChatMessage {\n const msg = new ChatMessage(params);\n if (params.createdAt !== undefined) {\n const idx = this.findInsertionIndex(params.createdAt);\n this._items.splice(idx, 0, msg);\n } else {\n this._items.push(msg);\n }\n return msg;\n }\n\n /**\n * Insert a single item or multiple items based on their `createdAt` field so\n * that the array keeps its chronological order.\n */\n insert(item: ChatItem | ChatItem[]): void {\n const arr = Array.isArray(item) ? item : [item];\n for (const it of arr) {\n const idx = this.findInsertionIndex(it.createdAt);\n this._items.splice(idx, 0, it);\n }\n }\n\n getById(itemId: string): ChatItem | undefined {\n return this._items.find((i) => i.id === itemId);\n }\n\n indexById(itemId: string): number | undefined {\n const idx = this._items.findIndex((i) => i.id === itemId);\n return idx !== -1 ? idx : undefined;\n }\n\n copy(\n options: {\n excludeFunctionCall?: boolean;\n excludeInstructions?: boolean;\n excludeEmptyMessage?: boolean;\n toolCtx?: ToolContext<any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n } = {},\n ): ChatContext {\n const {\n excludeFunctionCall = false,\n excludeInstructions = false,\n excludeEmptyMessage = false,\n toolCtx,\n } = options;\n const items: ChatItem[] = [];\n\n const isToolCallOrOutput = (item: ChatItem): item is FunctionCall | FunctionCallOutput =>\n ['function_call', 'function_call_output'].includes(item.type);\n const isChatMessage = (item: ChatItem): item is ChatMessage => item.type === 'message';\n\n for (const item of this._items) {\n if (excludeFunctionCall && isToolCallOrOutput(item)) {\n continue;\n }\n\n if (\n excludeInstructions &&\n isChatMessage(item) &&\n ['system', 'developer'].includes(item.role)\n ) {\n continue;\n }\n\n if (excludeEmptyMessage && isChatMessage(item) && item.content.length === 0) {\n continue;\n }\n\n if (toolCtx !== undefined && isToolCallOrOutput(item) && toolCtx[item.name] === undefined) {\n continue;\n }\n\n items.push(item);\n }\n\n return new ChatContext(items);\n }\n\n truncate(maxItems: number): ChatContext {\n if (maxItems <= 0) return this;\n\n const instructions = this._items.find((i) => i.type === 'message' && i.role === 'system') as\n | ChatMessage\n | undefined;\n\n let newItems = this._items.slice(-maxItems);\n\n // Ensure the first item is not a function-call artefact.\n while (\n newItems.length > 0 &&\n ['function_call', 'function_call_output'].includes(newItems[0]!.type)\n ) {\n newItems.shift();\n }\n\n if (instructions) {\n // At this point `instructions` is defined, so it is safe to pass to `includes`.\n if (!newItems.includes(instructions)) {\n newItems = [instructions, ...newItems];\n }\n }\n\n // replace the items in place to keep the reference\n this._items.splice(0, this._items.length, ...newItems);\n return this;\n }\n\n toJSON(\n options: {\n excludeImage?: boolean;\n excludeAudio?: boolean;\n excludeTimestamp?: boolean;\n excludeFunctionCall?: boolean;\n } = {},\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): JSONObject {\n const {\n excludeImage = true,\n excludeAudio = true,\n excludeTimestamp = true,\n excludeFunctionCall = false,\n } = options;\n\n const items: ChatItem[] = [];\n\n for (const item of this._items) {\n let processedItem = item;\n\n if (excludeFunctionCall && ['function_call', 'function_call_output'].includes(item.type)) {\n continue;\n }\n\n if (item.type === 'message') {\n processedItem = ChatMessage.create({\n role: item.role,\n content: item.content,\n id: item.id,\n interrupted: item.interrupted,\n createdAt: item.createdAt,\n });\n\n // Filter content based on options\n if (excludeImage) {\n processedItem.content = processedItem.content.filter((c) => {\n return !(typeof c === 'object' && c.type === 'image_content');\n });\n }\n\n if (excludeAudio) {\n processedItem.content = processedItem.content.filter((c) => {\n return !(typeof c === 'object' && c.type === 'audio_content');\n });\n }\n }\n\n items.push(processedItem);\n }\n\n return {\n items: items.map((item) => item.toJSON(excludeTimestamp)),\n };\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async toProviderFormat(format: ProviderFormat, injectDummyUserMessage: boolean = true) {\n return await toChatCtx(format, this, injectDummyUserMessage);\n }\n\n /**\n * Internal helper used by `truncate` & `addMessage` to find the correct\n * insertion index for a timestamp so the list remains sorted.\n */\n private findInsertionIndex(createdAt: number): number {\n for (let i = this._items.length - 1; i >= 0; i -= 1) {\n const item = this._items[i];\n if (item!.createdAt <= createdAt) {\n return i + 1;\n }\n }\n return 0;\n }\n\n /**\n * Return true if `other` has the same sequence of items with matching\n * essential fields (IDs, types, and payload) as this context.\n *\n * Comparison rules:\n * - Messages: compares the full `content` list, `role` and `interrupted`.\n * - Function calls: compares `name`, `callId`, and `args`.\n * - Function call outputs: compares `name`, `callId`, `output`, and `isError`.\n *\n * Does not consider timestamps or other metadata.\n */\n isEquivalent(other: ChatContext): boolean {\n if (this === other) {\n return true;\n }\n\n if (this.items.length !== other.items.length) {\n return false;\n }\n\n for (let i = 0; i < this.items.length; i++) {\n const a = this.items[i]!;\n const b = other.items[i]!;\n\n if (a.id !== b.id || a.type !== b.type) {\n return false;\n }\n\n if (a.type === 'message' && b.type === 'message') {\n if (\n a.role !== b.role ||\n a.interrupted !== b.interrupted ||\n !this.compareContent(a.content, b.content)\n ) {\n return false;\n }\n } else if (a.type === 'function_call' && b.type === 'function_call') {\n if (\n a.name !== b.name ||\n a.callId !== b.callId ||\n a.args !== b.args ||\n a.thoughtSignature !== b.thoughtSignature ||\n a.groupId !== b.groupId ||\n JSON.stringify(a.extra) !== JSON.stringify(b.extra)\n ) {\n return false;\n }\n } else if (a.type === 'function_call_output' && b.type === 'function_call_output') {\n if (\n a.name !== b.name ||\n a.callId !== b.callId ||\n a.output !== b.output ||\n a.isError !== b.isError\n ) {\n return false;\n }\n }\n }\n\n return true;\n }\n\n /**\n * Compare two content arrays for equality.\n */\n private compareContent(a: ChatContent[], b: ChatContent[]): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n for (let i = 0; i < a.length; i++) {\n const contentA = a[i]!;\n const contentB = b[i]!;\n\n if (typeof contentA === 'string' && typeof contentB === 'string') {\n if (contentA !== contentB) {\n return false;\n }\n continue;\n }\n\n if (typeof contentA !== typeof contentB) {\n return false;\n }\n\n if (typeof contentA === 'object' && typeof contentB === 'object') {\n if (contentA.type === 'image_content' && contentB.type === 'image_content') {\n if (\n contentA.id !== contentB.id ||\n contentA.image !== contentB.image ||\n contentA.inferenceDetail !== contentB.inferenceDetail ||\n contentA.inferenceWidth !== contentB.inferenceWidth ||\n contentA.inferenceHeight !== contentB.inferenceHeight ||\n contentA.mimeType !== contentB.mimeType\n ) {\n return false;\n }\n } else if (contentA.type === 'audio_content' && contentB.type === 'audio_content') {\n if (contentA.frame.length !== contentB.frame.length) {\n return false;\n }\n if (contentA.transcript !== contentB.transcript) {\n return false;\n }\n } else {\n return false;\n }\n }\n }\n\n return true;\n }\n\n /**\n * Indicates whether the context is read-only\n */\n get readonly(): boolean {\n return false;\n }\n}\n\nexport class ReadonlyChatContext extends ChatContext {\n static readonly errorMsg =\n 'Please use .copy() and agent.update_chat_ctx() to modify the chat context.';\n\n constructor(items: ChatItem[]) {\n super(createImmutableArray(items, ReadonlyChatContext.errorMsg));\n }\n\n get items(): ChatItem[] {\n return this._items;\n }\n\n set items(items: ChatItem[]) {\n throw new Error(\n `Cannot set items on a read-only chat context. ${ReadonlyChatContext.errorMsg}`,\n );\n }\n\n get readonly(): boolean {\n return true;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/llm/chat_context.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame, VideoFrame } from '@livekit/rtc-node';\nimport { createImmutableArray, shortuuid } from '../utils.js';\nimport type { LLM } from './llm.js';\nimport { type ProviderFormat, toChatCtx } from './provider_format/index.js';\nimport type { JSONObject, JSONValue, ToolContext } from './tool_context.js';\n\nexport type ChatRole = 'developer' | 'system' | 'user' | 'assistant';\nexport interface ImageContent {\n id: string;\n\n type: 'image_content';\n\n /**\n * Either a string URL or a VideoFrame object.\n */\n image: string | VideoFrame;\n\n inferenceDetail: 'auto' | 'high' | 'low';\n\n inferenceWidth?: number;\n\n inferenceHeight?: number;\n\n mimeType?: string;\n\n _cache: Record<any, any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n}\n\nexport interface AudioContent {\n type: 'audio_content';\n\n frame: AudioFrame[];\n\n transcript?: string;\n}\n\nexport type ChatContent = ImageContent | AudioContent | string;\n\nexport function createImageContent(params: {\n image: string | VideoFrame;\n id?: string;\n inferenceDetail?: 'auto' | 'high' | 'low';\n inferenceWidth?: number;\n inferenceHeight?: number;\n mimeType?: string;\n}): ImageContent {\n const {\n image,\n id = shortuuid('img_'),\n inferenceDetail = 'auto',\n inferenceWidth,\n inferenceHeight,\n mimeType,\n } = params;\n\n return {\n id,\n type: 'image_content',\n image,\n inferenceDetail,\n inferenceWidth,\n inferenceHeight,\n mimeType,\n _cache: {},\n };\n}\n\nexport function createAudioContent(params: {\n frame: AudioFrame[];\n transcript?: string;\n}): AudioContent {\n const { frame, transcript } = params;\n\n return {\n type: 'audio_content',\n frame,\n transcript,\n };\n}\n\nexport class ChatMessage {\n readonly id: string;\n\n readonly type = 'message' as const;\n\n readonly role: ChatRole;\n\n content: ChatContent[];\n\n interrupted: boolean;\n\n hash?: Uint8Array;\n\n createdAt: number;\n\n extra: Record<string, unknown>;\n\n constructor(params: {\n role: ChatRole;\n content: ChatContent[] | string;\n id?: string;\n interrupted?: boolean;\n createdAt?: number;\n extra?: Record<string, unknown>;\n }) {\n const {\n role,\n content,\n id = shortuuid('item_'),\n interrupted = false,\n createdAt = Date.now(),\n extra = {},\n } = params;\n this.id = id;\n this.role = role;\n this.content = Array.isArray(content) ? content : [content];\n this.interrupted = interrupted;\n this.createdAt = createdAt;\n this.extra = extra;\n }\n\n static create(params: {\n role: ChatRole;\n content: ChatContent[] | string;\n id?: string;\n interrupted?: boolean;\n createdAt?: number;\n extra?: Record<string, unknown>;\n }) {\n return new ChatMessage(params);\n }\n\n /**\n * Returns a single string with all text parts of the message joined by new\n * lines. If no string content is present, returns `null`.\n */\n get textContent(): string | undefined {\n const parts = this.content.filter((c): c is string => typeof c === 'string');\n return parts.length > 0 ? parts.join('\\n') : undefined;\n }\n\n toJSONContent(): JSONValue[] {\n return this.content.map((c) => {\n if (typeof c === 'string') {\n return c as JSONValue;\n } else if (c.type === 'image_content') {\n return {\n id: c.id,\n type: c.type,\n image: c.image,\n inferenceDetail: c.inferenceDetail,\n inferenceWidth: c.inferenceWidth,\n inferenceHeight: c.inferenceHeight,\n mimeType: c.mimeType,\n } as JSONObject;\n } else {\n return {\n type: c.type,\n transcript: c.transcript,\n } as JSONObject;\n }\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n toJSON(excludeTimestamp: boolean = false): JSONValue {\n const result: JSONValue = {\n id: this.id,\n type: this.type,\n role: this.role,\n content: this.toJSONContent(),\n interrupted: this.interrupted,\n };\n\n if (!excludeTimestamp) {\n result.createdAt = this.createdAt;\n }\n\n return result;\n }\n}\n\nexport class FunctionCall {\n readonly id: string;\n\n readonly type = 'function_call' as const;\n\n callId: string;\n\n args: string;\n\n name: string;\n\n createdAt: number;\n\n extra: Record<string, unknown>;\n /**\n * Optional grouping identifier for parallel tool calls.\n */\n groupId?: string;\n\n /**\n * Opaque signature for Gemini thinking mode.\n * When using Gemini 3+ models with thinking enabled, this signature must be\n * preserved and returned with function responses to maintain thought context.\n */\n thoughtSignature?: string;\n\n constructor(params: {\n callId: string;\n name: string;\n args: string;\n id?: string;\n createdAt?: number;\n extra?: Record<string, unknown>;\n groupId?: string;\n thoughtSignature?: string;\n }) {\n const {\n callId,\n name,\n args,\n id = shortuuid('item_'),\n createdAt = Date.now(),\n extra = {},\n groupId,\n thoughtSignature,\n } = params;\n this.id = id;\n this.callId = callId;\n this.args = args;\n this.name = name;\n this.createdAt = createdAt;\n this.extra = { ...extra };\n this.groupId = groupId;\n this.thoughtSignature =\n thoughtSignature ??\n (typeof this.extra.google === 'object' && this.extra.google !== null\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this.extra.google as any).thoughtSignature ||\n (this.extra.google as any).thought_signature\n : undefined);\n }\n\n static create(params: {\n callId: string;\n name: string;\n args: string;\n id?: string;\n createdAt?: number;\n extra?: Record<string, unknown>;\n groupId?: string;\n thoughtSignature?: string;\n }) {\n return new FunctionCall(params);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n toJSON(excludeTimestamp: boolean = false): JSONValue {\n const result: JSONValue = {\n id: this.id,\n type: this.type,\n callId: this.callId,\n name: this.name,\n args: this.args,\n };\n\n if (Object.keys(this.extra).length > 0) {\n result.extra = this.extra as JSONValue;\n }\n\n if (this.groupId) {\n result.groupId = this.groupId;\n }\n\n if (this.thoughtSignature) {\n result.thoughtSignature = this.thoughtSignature;\n }\n\n if (!excludeTimestamp) {\n result.createdAt = this.createdAt;\n }\n\n return result;\n }\n}\n\nexport class FunctionCallOutput {\n readonly id: string;\n\n readonly type = 'function_call_output' as const;\n\n name = '';\n\n callId: string;\n\n output: string;\n\n isError: boolean;\n\n createdAt: number;\n\n constructor(params: {\n callId: string;\n output: string;\n isError: boolean;\n id?: string;\n createdAt?: number;\n name?: string;\n }) {\n const {\n callId,\n output,\n isError,\n id = shortuuid('item_'),\n createdAt = Date.now(),\n name = '',\n } = params;\n this.id = id;\n this.callId = callId;\n this.output = output;\n this.isError = isError;\n this.name = name;\n this.createdAt = createdAt;\n }\n\n static create(params: {\n callId: string;\n output: string;\n isError: boolean;\n id?: string;\n createdAt?: number;\n name?: string;\n }) {\n return new FunctionCallOutput(params);\n }\n\n toJSON(excludeTimestamp: boolean = false): JSONValue {\n const result: JSONValue = {\n id: this.id,\n type: this.type,\n name: this.name,\n callId: this.callId,\n output: this.output,\n isError: this.isError,\n };\n\n if (!excludeTimestamp) {\n result.createdAt = this.createdAt;\n }\n\n return result;\n }\n}\n\nexport class AgentHandoffItem {\n readonly id: string;\n\n readonly type = 'agent_handoff' as const;\n\n oldAgentId: string | undefined;\n\n newAgentId: string;\n\n createdAt: number;\n\n constructor(params: {\n oldAgentId?: string;\n newAgentId: string;\n id?: string;\n createdAt?: number;\n }) {\n const { oldAgentId, newAgentId, id = shortuuid('item_'), createdAt = Date.now() } = params;\n this.id = id;\n this.oldAgentId = oldAgentId;\n this.newAgentId = newAgentId;\n this.createdAt = createdAt;\n }\n\n static create(params: {\n oldAgentId?: string;\n newAgentId: string;\n id?: string;\n createdAt?: number;\n }) {\n return new AgentHandoffItem(params);\n }\n\n toJSON(excludeTimestamp: boolean = false): JSONValue {\n const result: JSONValue = {\n id: this.id,\n type: this.type,\n newAgentId: this.newAgentId,\n };\n\n if (this.oldAgentId !== undefined) {\n result.oldAgentId = this.oldAgentId;\n }\n\n if (!excludeTimestamp) {\n result.createdAt = this.createdAt;\n }\n\n return result;\n }\n}\n\n// TODO(parity): Add AgentConfigUpdate type to ChatItem union\nexport type ChatItem = ChatMessage | FunctionCall | FunctionCallOutput | AgentHandoffItem;\n\nexport class ChatContext {\n protected _items: ChatItem[];\n\n constructor(items?: ChatItem[]) {\n this._items = items ? items : [];\n }\n\n static empty(): ChatContext {\n return new ChatContext([]);\n }\n\n get items(): ChatItem[] {\n return this._items;\n }\n\n set items(items: ChatItem[]) {\n this._items = items;\n }\n\n /**\n * Add a new message to the context and return it.\n */\n addMessage(params: {\n role: ChatRole;\n content: ChatContent[] | string;\n id?: string;\n interrupted?: boolean;\n createdAt?: number;\n extra?: Record<string, unknown>;\n }): ChatMessage {\n const msg = new ChatMessage(params);\n if (params.createdAt !== undefined) {\n const idx = this.findInsertionIndex(params.createdAt);\n this._items.splice(idx, 0, msg);\n } else {\n this._items.push(msg);\n }\n return msg;\n }\n\n /**\n * Insert a single item or multiple items based on their `createdAt` field so\n * that the array keeps its chronological order.\n */\n insert(item: ChatItem | ChatItem[]): void {\n const arr = Array.isArray(item) ? item : [item];\n for (const it of arr) {\n const idx = this.findInsertionIndex(it.createdAt);\n this._items.splice(idx, 0, it);\n }\n }\n\n getById(itemId: string): ChatItem | undefined {\n return this._items.find((i) => i.id === itemId);\n }\n\n indexById(itemId: string): number | undefined {\n const idx = this._items.findIndex((i) => i.id === itemId);\n return idx !== -1 ? idx : undefined;\n }\n\n // TODO(parity): Add excludeConfigUpdate option when AgentConfigUpdate is ported\n copy(\n options: {\n excludeFunctionCall?: boolean;\n excludeInstructions?: boolean;\n excludeEmptyMessage?: boolean;\n excludeHandoff?: boolean;\n toolCtx?: ToolContext<any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n } = {},\n ): ChatContext {\n const {\n excludeFunctionCall = false,\n excludeInstructions = false,\n excludeEmptyMessage = false,\n excludeHandoff = false,\n toolCtx,\n } = options;\n const items: ChatItem[] = [];\n\n const isToolCallOrOutput = (item: ChatItem): item is FunctionCall | FunctionCallOutput =>\n ['function_call', 'function_call_output'].includes(item.type);\n const isChatMessage = (item: ChatItem): item is ChatMessage => item.type === 'message';\n\n for (const item of this._items) {\n if (excludeFunctionCall && isToolCallOrOutput(item)) {\n continue;\n }\n\n if (\n excludeInstructions &&\n isChatMessage(item) &&\n ['system', 'developer'].includes(item.role)\n ) {\n continue;\n }\n\n if (excludeEmptyMessage && isChatMessage(item) && item.content.length === 0) {\n continue;\n }\n\n if (excludeHandoff && item.type === 'agent_handoff') {\n continue;\n }\n\n if (toolCtx !== undefined && isToolCallOrOutput(item) && toolCtx[item.name] === undefined) {\n continue;\n }\n\n items.push(item);\n }\n\n return new ChatContext(items);\n }\n\n // TODO(parity): Add excludeConfigUpdate option when AgentConfigUpdate is ported\n merge(\n other: ChatContext,\n options: {\n excludeFunctionCall?: boolean;\n excludeInstructions?: boolean;\n } = {},\n ): ChatContext {\n const { excludeFunctionCall = false, excludeInstructions = false } = options;\n const existingIds = new Set(this._items.map((item) => item.id));\n\n for (const item of other.items) {\n if (excludeFunctionCall && ['function_call', 'function_call_output'].includes(item.type)) {\n continue;\n }\n\n if (\n excludeInstructions &&\n item.type === 'message' &&\n (item.role === 'system' || item.role === 'developer')\n ) {\n continue;\n }\n\n if (existingIds.has(item.id)) {\n continue;\n }\n\n const idx = this.findInsertionIndex(item.createdAt);\n this._items.splice(idx, 0, item);\n existingIds.add(item.id);\n }\n\n return this;\n }\n\n truncate(maxItems: number): ChatContext {\n if (maxItems <= 0) return this;\n\n const instructions = this._items.find((i) => i.type === 'message' && i.role === 'system') as\n | ChatMessage\n | undefined;\n\n let newItems = this._items.slice(-maxItems);\n\n // Ensure the first item is not a function-call artefact.\n while (\n newItems.length > 0 &&\n ['function_call', 'function_call_output'].includes(newItems[0]!.type)\n ) {\n newItems.shift();\n }\n\n if (instructions) {\n // At this point `instructions` is defined, so it is safe to pass to `includes`.\n if (!newItems.includes(instructions)) {\n newItems = [instructions, ...newItems];\n }\n }\n\n // replace the items in place to keep the reference\n this._items.splice(0, this._items.length, ...newItems);\n return this;\n }\n\n toJSON(\n options: {\n excludeImage?: boolean;\n excludeAudio?: boolean;\n excludeTimestamp?: boolean;\n excludeFunctionCall?: boolean;\n } = {},\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): JSONObject {\n const {\n excludeImage = true,\n excludeAudio = true,\n excludeTimestamp = true,\n excludeFunctionCall = false,\n } = options;\n\n const items: ChatItem[] = [];\n\n for (const item of this._items) {\n let processedItem = item;\n\n if (excludeFunctionCall && ['function_call', 'function_call_output'].includes(item.type)) {\n continue;\n }\n\n if (item.type === 'message') {\n processedItem = ChatMessage.create({\n role: item.role,\n content: item.content,\n id: item.id,\n interrupted: item.interrupted,\n createdAt: item.createdAt,\n });\n\n // Filter content based on options\n if (excludeImage) {\n processedItem.content = processedItem.content.filter((c) => {\n return !(typeof c === 'object' && c.type === 'image_content');\n });\n }\n\n if (excludeAudio) {\n processedItem.content = processedItem.content.filter((c) => {\n return !(typeof c === 'object' && c.type === 'audio_content');\n });\n }\n }\n\n items.push(processedItem);\n }\n\n return {\n items: items.map((item) => item.toJSON(excludeTimestamp)),\n };\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async toProviderFormat(format: ProviderFormat, injectDummyUserMessage: boolean = true) {\n return await toChatCtx(format, this, injectDummyUserMessage);\n }\n\n /**\n * Internal helper used by `truncate` & `addMessage` to find the correct\n * insertion index for a timestamp so the list remains sorted.\n */\n private findInsertionIndex(createdAt: number): number {\n for (let i = this._items.length - 1; i >= 0; i -= 1) {\n const item = this._items[i];\n if (item!.createdAt <= createdAt) {\n return i + 1;\n }\n }\n return 0;\n }\n\n /**\n * Return true if `other` has the same sequence of items with matching\n * essential fields (IDs, types, and payload) as this context.\n *\n * Comparison rules:\n * - Messages: compares the full `content` list, `role` and `interrupted`.\n * - Function calls: compares `name`, `callId`, and `args`.\n * - Function call outputs: compares `name`, `callId`, `output`, and `isError`.\n *\n * Does not consider timestamps or other metadata.\n */\n isEquivalent(other: ChatContext): boolean {\n if (this === other) {\n return true;\n }\n\n if (this.items.length !== other.items.length) {\n return false;\n }\n\n for (let i = 0; i < this.items.length; i++) {\n const a = this.items[i]!;\n const b = other.items[i]!;\n\n if (a.id !== b.id || a.type !== b.type) {\n return false;\n }\n\n if (a.type === 'message' && b.type === 'message') {\n if (\n a.role !== b.role ||\n a.interrupted !== b.interrupted ||\n !this.compareContent(a.content, b.content)\n ) {\n return false;\n }\n } else if (a.type === 'function_call' && b.type === 'function_call') {\n if (\n a.name !== b.name ||\n a.callId !== b.callId ||\n a.args !== b.args ||\n a.thoughtSignature !== b.thoughtSignature ||\n a.groupId !== b.groupId ||\n JSON.stringify(a.extra) !== JSON.stringify(b.extra)\n ) {\n return false;\n }\n } else if (a.type === 'function_call_output' && b.type === 'function_call_output') {\n if (\n a.name !== b.name ||\n a.callId !== b.callId ||\n a.output !== b.output ||\n a.isError !== b.isError\n ) {\n return false;\n }\n }\n }\n\n return true;\n }\n\n /**\n * Compare two content arrays for equality.\n */\n private compareContent(a: ChatContent[], b: ChatContent[]): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n for (let i = 0; i < a.length; i++) {\n const contentA = a[i]!;\n const contentB = b[i]!;\n\n if (typeof contentA === 'string' && typeof contentB === 'string') {\n if (contentA !== contentB) {\n return false;\n }\n continue;\n }\n\n if (typeof contentA !== typeof contentB) {\n return false;\n }\n\n if (typeof contentA === 'object' && typeof contentB === 'object') {\n if (contentA.type === 'image_content' && contentB.type === 'image_content') {\n if (\n contentA.id !== contentB.id ||\n contentA.image !== contentB.image ||\n contentA.inferenceDetail !== contentB.inferenceDetail ||\n contentA.inferenceWidth !== contentB.inferenceWidth ||\n contentA.inferenceHeight !== contentB.inferenceHeight ||\n contentA.mimeType !== contentB.mimeType\n ) {\n return false;\n }\n } else if (contentA.type === 'audio_content' && contentB.type === 'audio_content') {\n if (contentA.frame.length !== contentB.frame.length) {\n return false;\n }\n if (contentA.transcript !== contentB.transcript) {\n return false;\n }\n } else {\n return false;\n }\n }\n }\n\n return true;\n }\n\n async _summarize(llm: LLM, options: { keepLastTurns?: number } = {}): Promise<ChatContext> {\n const { keepLastTurns = 2 } = options;\n\n const toSummarize: ChatMessage[] = [];\n for (const item of this._items) {\n if (item.type !== 'message') continue;\n if (item.role !== 'user' && item.role !== 'assistant') continue;\n if (item.extra?.is_summary === true) continue;\n\n const text = (item.textContent ?? '').trim();\n if (text) {\n toSummarize.push(item);\n }\n }\n\n if (toSummarize.length === 0) {\n return this;\n }\n\n const tailN = Math.max(0, Math.min(toSummarize.length, keepLastTurns * 2));\n let head: ChatMessage[];\n let tail: ChatMessage[];\n if (tailN === 0) {\n head = toSummarize;\n tail = [];\n } else {\n head = toSummarize.slice(0, -tailN);\n tail = toSummarize.slice(-tailN);\n }\n\n if (head.length === 0) {\n return this;\n }\n\n const sourceText = head\n .map((m) => `${m.role}: ${(m.textContent ?? '').trim()}`)\n .join('\\n')\n .trim();\n\n if (!sourceText) {\n return this;\n }\n\n // TODO: refactor this into LLMStream.collect API.\n const promptCtx = new ChatContext();\n promptCtx.addMessage({\n role: 'system',\n content:\n 'Compress older chat history into a short, faithful summary.\\n' +\n 'Focus on user goals, constraints, decisions, key facts/preferences/entities, and pending tasks.\\n' +\n 'Exclude chit-chat and greetings. Be concise.',\n });\n promptCtx.addMessage({\n role: 'user',\n content: `Conversation to summarize:\\n\\n${sourceText}`,\n });\n\n const chunks: string[] = [];\n for await (const chunk of llm.chat({ chatCtx: promptCtx })) {\n if (chunk.delta?.content) {\n chunks.push(chunk.delta.content);\n }\n }\n\n const summary = chunks.join('').trim();\n if (!summary) {\n return this;\n }\n\n const tailStartTs = tail.length > 0 ? tail[0]!.createdAt : Infinity;\n\n const preserved: ChatItem[] = [];\n for (const it of this._items) {\n if (\n (it.type === 'function_call' || it.type === 'function_call_output') &&\n it.createdAt < tailStartTs\n ) {\n continue;\n }\n\n if (it.type === 'message' && (it.role === 'user' || it.role === 'assistant')) {\n continue;\n }\n\n preserved.push(it);\n }\n\n this._items = preserved;\n\n const createdAtHint =\n tail.length > 0 ? tail[0]!.createdAt - 1e-3 : head[head.length - 1]!.createdAt + 1e-3;\n\n this.addMessage({\n role: 'assistant',\n content: `[history summary]\\n${summary}`,\n createdAt: createdAtHint,\n extra: { is_summary: true },\n });\n\n for (const msg of tail) {\n this.insert(msg);\n }\n\n return this;\n }\n\n /**\n * Indicates whether the context is read-only\n */\n get readonly(): boolean {\n return false;\n }\n}\n\nexport class ReadonlyChatContext extends ChatContext {\n static readonly errorMsg =\n 'Please use .copy() and agent.update_chat_ctx() to modify the chat context.';\n\n constructor(items: ChatItem[]) {\n super(createImmutableArray(items, ReadonlyChatContext.errorMsg));\n }\n\n get items(): ChatItem[] {\n return this._items;\n }\n\n set items(items: ChatItem[]) {\n throw new Error(\n `Cannot set items on a read-only chat context. ${ReadonlyChatContext.errorMsg}`,\n );\n }\n\n get readonly(): boolean {\n return true;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var import_vitest = require("vitest");
|
|
3
|
+
var import_log = require("../log.cjs");
|
|
4
|
+
var import_fake_llm = require("../voice/testing/fake_llm.cjs");
|
|
3
5
|
var import_chat_context = require("./chat_context.cjs");
|
|
6
|
+
(0, import_log.initializeLogger)({ pretty: false, level: "error" });
|
|
4
7
|
(0, import_vitest.describe)("ChatContext.toJSON", () => {
|
|
5
8
|
(0, import_vitest.it)("should match snapshot for empty context", () => {
|
|
6
9
|
const context = new import_chat_context.ChatContext();
|
|
@@ -232,6 +235,46 @@ var import_chat_context = require("./chat_context.cjs");
|
|
|
232
235
|
).toMatchSnapshot("message-properties-full");
|
|
233
236
|
});
|
|
234
237
|
});
|
|
238
|
+
(0, import_vitest.describe)("ChatContext._summarize", () => {
|
|
239
|
+
(0, import_vitest.it)("keeps chronological timestamps with summary + tail", async () => {
|
|
240
|
+
const ctx = new import_chat_context.ChatContext();
|
|
241
|
+
ctx.addMessage({ role: "system", content: "System prompt", createdAt: 0 });
|
|
242
|
+
ctx.addMessage({ role: "user", content: "hello", createdAt: 1e3 });
|
|
243
|
+
ctx.addMessage({ role: "assistant", content: "hi there", createdAt: 2e3 });
|
|
244
|
+
ctx.insert(
|
|
245
|
+
new import_chat_context.FunctionCallOutput({
|
|
246
|
+
callId: "call_1",
|
|
247
|
+
name: "lookup",
|
|
248
|
+
output: '{"ok":true}',
|
|
249
|
+
isError: false,
|
|
250
|
+
createdAt: 3500
|
|
251
|
+
})
|
|
252
|
+
);
|
|
253
|
+
ctx.addMessage({ role: "user", content: "my color is blue", createdAt: 3e3 });
|
|
254
|
+
ctx.addMessage({ role: "assistant", content: "noted", createdAt: 4e3 });
|
|
255
|
+
const fake = new import_fake_llm.FakeLLM([
|
|
256
|
+
{
|
|
257
|
+
input: "Conversation to summarize:\n\nuser: hello\nassistant: hi there",
|
|
258
|
+
content: "condensed head"
|
|
259
|
+
}
|
|
260
|
+
]);
|
|
261
|
+
await ctx._summarize(fake, { keepLastTurns: 1 });
|
|
262
|
+
const summary = ctx.items.find(
|
|
263
|
+
(item) => {
|
|
264
|
+
var _a;
|
|
265
|
+
return item.type === "message" && item.role === "assistant" && ((_a = item.extra) == null ? void 0 : _a.is_summary) === true;
|
|
266
|
+
}
|
|
267
|
+
);
|
|
268
|
+
(0, import_vitest.expect)(summary).toBeDefined();
|
|
269
|
+
if (!summary || summary.type !== "message") {
|
|
270
|
+
throw new Error("summary message is missing");
|
|
271
|
+
}
|
|
272
|
+
(0, import_vitest.expect)(summary.createdAt).toBeCloseTo(2999.999, 6);
|
|
273
|
+
const createdAts = ctx.items.map((item) => item.createdAt);
|
|
274
|
+
const sorted = [...createdAts].sort((a, b) => a - b);
|
|
275
|
+
(0, import_vitest.expect)(createdAts).toEqual(sorted);
|
|
276
|
+
});
|
|
277
|
+
});
|
|
235
278
|
(0, import_vitest.describe)("ReadonlyChatContext with immutable array", () => {
|
|
236
279
|
(0, import_vitest.it)("should have readonly property set to true", () => {
|
|
237
280
|
const items = [
|