@livekit/agents 1.0.18 → 1.0.19

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.
Files changed (152) hide show
  1. package/dist/index.cjs +3 -0
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +2 -1
  4. package/dist/index.d.ts +2 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +2 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/inference/api_protos.d.cts +12 -12
  9. package/dist/inference/api_protos.d.ts +12 -12
  10. package/dist/inference/tts.cjs +1 -1
  11. package/dist/inference/tts.cjs.map +1 -1
  12. package/dist/inference/tts.js +1 -1
  13. package/dist/inference/tts.js.map +1 -1
  14. package/dist/ipc/job_proc_lazy_main.cjs +6 -2
  15. package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
  16. package/dist/ipc/job_proc_lazy_main.js +6 -2
  17. package/dist/ipc/job_proc_lazy_main.js.map +1 -1
  18. package/dist/job.cjs +31 -0
  19. package/dist/job.cjs.map +1 -1
  20. package/dist/job.d.cts +6 -0
  21. package/dist/job.d.ts +6 -0
  22. package/dist/job.d.ts.map +1 -1
  23. package/dist/job.js +31 -0
  24. package/dist/job.js.map +1 -1
  25. package/dist/llm/chat_context.cjs +33 -0
  26. package/dist/llm/chat_context.cjs.map +1 -1
  27. package/dist/llm/chat_context.d.cts +22 -2
  28. package/dist/llm/chat_context.d.ts +22 -2
  29. package/dist/llm/chat_context.d.ts.map +1 -1
  30. package/dist/llm/chat_context.js +32 -0
  31. package/dist/llm/chat_context.js.map +1 -1
  32. package/dist/llm/index.cjs +2 -0
  33. package/dist/llm/index.cjs.map +1 -1
  34. package/dist/llm/index.d.cts +1 -1
  35. package/dist/llm/index.d.ts +1 -1
  36. package/dist/llm/index.d.ts.map +1 -1
  37. package/dist/llm/index.js +2 -0
  38. package/dist/llm/index.js.map +1 -1
  39. package/dist/llm/llm.cjs.map +1 -1
  40. package/dist/llm/llm.d.ts.map +1 -1
  41. package/dist/llm/llm.js.map +1 -1
  42. package/dist/llm/provider_format/google.test.cjs +48 -0
  43. package/dist/llm/provider_format/google.test.cjs.map +1 -1
  44. package/dist/llm/provider_format/google.test.js +54 -1
  45. package/dist/llm/provider_format/google.test.js.map +1 -1
  46. package/dist/llm/provider_format/index.d.cts +1 -1
  47. package/dist/llm/provider_format/index.d.ts +1 -1
  48. package/dist/llm/provider_format/openai.cjs +1 -2
  49. package/dist/llm/provider_format/openai.cjs.map +1 -1
  50. package/dist/llm/provider_format/openai.js +1 -2
  51. package/dist/llm/provider_format/openai.js.map +1 -1
  52. package/dist/llm/provider_format/openai.test.cjs +32 -0
  53. package/dist/llm/provider_format/openai.test.cjs.map +1 -1
  54. package/dist/llm/provider_format/openai.test.js +38 -1
  55. package/dist/llm/provider_format/openai.test.js.map +1 -1
  56. package/dist/log.cjs.map +1 -1
  57. package/dist/log.d.ts.map +1 -1
  58. package/dist/log.js.map +1 -1
  59. package/dist/telemetry/index.cjs +51 -0
  60. package/dist/telemetry/index.cjs.map +1 -0
  61. package/dist/telemetry/index.d.cts +4 -0
  62. package/dist/telemetry/index.d.ts +4 -0
  63. package/dist/telemetry/index.d.ts.map +1 -0
  64. package/dist/telemetry/index.js +12 -0
  65. package/dist/telemetry/index.js.map +1 -0
  66. package/dist/telemetry/trace_types.cjs +191 -0
  67. package/dist/telemetry/trace_types.cjs.map +1 -0
  68. package/dist/telemetry/trace_types.d.cts +56 -0
  69. package/dist/telemetry/trace_types.d.ts +56 -0
  70. package/dist/telemetry/trace_types.d.ts.map +1 -0
  71. package/dist/telemetry/trace_types.js +113 -0
  72. package/dist/telemetry/trace_types.js.map +1 -0
  73. package/dist/telemetry/traces.cjs +196 -0
  74. package/dist/telemetry/traces.cjs.map +1 -0
  75. package/dist/telemetry/traces.d.cts +97 -0
  76. package/dist/telemetry/traces.d.ts +97 -0
  77. package/dist/telemetry/traces.d.ts.map +1 -0
  78. package/dist/telemetry/traces.js +173 -0
  79. package/dist/telemetry/traces.js.map +1 -0
  80. package/dist/telemetry/utils.cjs +86 -0
  81. package/dist/telemetry/utils.cjs.map +1 -0
  82. package/dist/telemetry/utils.d.cts +5 -0
  83. package/dist/telemetry/utils.d.ts +5 -0
  84. package/dist/telemetry/utils.d.ts.map +1 -0
  85. package/dist/telemetry/utils.js +51 -0
  86. package/dist/telemetry/utils.js.map +1 -0
  87. package/dist/tts/tts.cjs.map +1 -1
  88. package/dist/tts/tts.d.ts.map +1 -1
  89. package/dist/tts/tts.js.map +1 -1
  90. package/dist/voice/agent.cjs +15 -0
  91. package/dist/voice/agent.cjs.map +1 -1
  92. package/dist/voice/agent.d.cts +4 -1
  93. package/dist/voice/agent.d.ts +4 -1
  94. package/dist/voice/agent.d.ts.map +1 -1
  95. package/dist/voice/agent.js +15 -0
  96. package/dist/voice/agent.js.map +1 -1
  97. package/dist/voice/agent_activity.cjs +2 -0
  98. package/dist/voice/agent_activity.cjs.map +1 -1
  99. package/dist/voice/agent_activity.d.ts.map +1 -1
  100. package/dist/voice/agent_activity.js +2 -0
  101. package/dist/voice/agent_activity.js.map +1 -1
  102. package/dist/voice/agent_session.cjs +29 -1
  103. package/dist/voice/agent_session.cjs.map +1 -1
  104. package/dist/voice/agent_session.d.cts +6 -2
  105. package/dist/voice/agent_session.d.ts +6 -2
  106. package/dist/voice/agent_session.d.ts.map +1 -1
  107. package/dist/voice/agent_session.js +30 -2
  108. package/dist/voice/agent_session.js.map +1 -1
  109. package/dist/voice/audio_recognition.cjs.map +1 -1
  110. package/dist/voice/audio_recognition.d.ts.map +1 -1
  111. package/dist/voice/audio_recognition.js.map +1 -1
  112. package/dist/voice/generation.cjs.map +1 -1
  113. package/dist/voice/generation.d.ts.map +1 -1
  114. package/dist/voice/generation.js.map +1 -1
  115. package/dist/voice/index.cjs +2 -0
  116. package/dist/voice/index.cjs.map +1 -1
  117. package/dist/voice/index.d.cts +1 -0
  118. package/dist/voice/index.d.ts +1 -0
  119. package/dist/voice/index.d.ts.map +1 -1
  120. package/dist/voice/index.js +1 -0
  121. package/dist/voice/index.js.map +1 -1
  122. package/dist/voice/report.cjs +69 -0
  123. package/dist/voice/report.cjs.map +1 -0
  124. package/dist/voice/report.d.cts +26 -0
  125. package/dist/voice/report.d.ts +26 -0
  126. package/dist/voice/report.d.ts.map +1 -0
  127. package/dist/voice/report.js +44 -0
  128. package/dist/voice/report.js.map +1 -0
  129. package/package.json +10 -3
  130. package/src/index.ts +2 -1
  131. package/src/inference/tts.ts +1 -1
  132. package/src/ipc/job_proc_lazy_main.ts +10 -2
  133. package/src/job.ts +48 -0
  134. package/src/llm/chat_context.ts +53 -1
  135. package/src/llm/index.ts +1 -0
  136. package/src/llm/llm.ts +2 -0
  137. package/src/llm/provider_format/google.test.ts +72 -1
  138. package/src/llm/provider_format/openai.test.ts +55 -1
  139. package/src/llm/provider_format/openai.ts +3 -2
  140. package/src/log.ts +1 -0
  141. package/src/telemetry/index.ts +10 -0
  142. package/src/telemetry/trace_types.ts +88 -0
  143. package/src/telemetry/traces.ts +266 -0
  144. package/src/telemetry/utils.ts +61 -0
  145. package/src/tts/tts.ts +4 -0
  146. package/src/voice/agent.ts +22 -0
  147. package/src/voice/agent_activity.ts +6 -0
  148. package/src/voice/agent_session.ts +44 -1
  149. package/src/voice/audio_recognition.ts +2 -0
  150. package/src/voice/generation.ts +3 -0
  151. package/src/voice/index.ts +1 -0
  152. package/src/voice/report.ts +77 -0
@@ -112,7 +112,27 @@ export declare class FunctionCallOutput {
112
112
  }): FunctionCallOutput;
113
113
  toJSON(excludeTimestamp?: boolean): JSONValue;
114
114
  }
115
- export type ChatItem = ChatMessage | FunctionCall | FunctionCallOutput;
115
+ export declare class AgentHandoffItem {
116
+ readonly id: string;
117
+ readonly type: "agent_handoff";
118
+ oldAgentId: string | undefined;
119
+ newAgentId: string;
120
+ createdAt: number;
121
+ constructor(params: {
122
+ oldAgentId?: string;
123
+ newAgentId: string;
124
+ id?: string;
125
+ createdAt?: number;
126
+ });
127
+ static create(params: {
128
+ oldAgentId?: string;
129
+ newAgentId: string;
130
+ id?: string;
131
+ createdAt?: number;
132
+ }): AgentHandoffItem;
133
+ toJSON(excludeTimestamp?: boolean): JSONValue;
134
+ }
135
+ export type ChatItem = ChatMessage | FunctionCall | FunctionCallOutput | AgentHandoffItem;
116
136
  export declare class ChatContext {
117
137
  protected _items: ChatItem[];
118
138
  constructor(items?: ChatItem[]);
@@ -149,7 +169,7 @@ export declare class ChatContext {
149
169
  excludeTimestamp?: boolean;
150
170
  excludeFunctionCall?: boolean;
151
171
  }): JSONObject;
152
- toProviderFormat(format: ProviderFormat, injectDummyUserMessage?: boolean): Promise<Record<string, any>[] | [Record<string, unknown>[], import("./provider_format/google.js").GoogleFormatData]>;
172
+ toProviderFormat(format: ProviderFormat, injectDummyUserMessage?: boolean): Promise<[Record<string, unknown>[], import("./provider_format/google.js").GoogleFormatData] | Record<string, any>[]>;
153
173
  /**
154
174
  * Internal helper used by `truncate` & `addMessage` to find the correct
155
175
  * insertion index for a timestamp so the list remains sorted.
@@ -1 +1 @@
1
- {"version":3,"file":"chat_context.d.ts","sourceRoot":"","sources":["../../src/llm/chat_context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat_context.d.ts","sourceRoot":"","sources":["../../src/llm/chat_context.ts"],"names":[],"mappings":"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"}
@@ -173,6 +173,37 @@ class FunctionCallOutput {
173
173
  return result;
174
174
  }
175
175
  }
176
+ class AgentHandoffItem {
177
+ id;
178
+ type = "agent_handoff";
179
+ oldAgentId;
180
+ newAgentId;
181
+ createdAt;
182
+ constructor(params) {
183
+ const { oldAgentId, newAgentId, id = shortuuid("item_"), createdAt = Date.now() } = params;
184
+ this.id = id;
185
+ this.oldAgentId = oldAgentId;
186
+ this.newAgentId = newAgentId;
187
+ this.createdAt = createdAt;
188
+ }
189
+ static create(params) {
190
+ return new AgentHandoffItem(params);
191
+ }
192
+ toJSON(excludeTimestamp = false) {
193
+ const result = {
194
+ id: this.id,
195
+ type: this.type,
196
+ newAgentId: this.newAgentId
197
+ };
198
+ if (this.oldAgentId !== void 0) {
199
+ result.oldAgentId = this.oldAgentId;
200
+ }
201
+ if (!excludeTimestamp) {
202
+ result.createdAt = this.createdAt;
203
+ }
204
+ return result;
205
+ }
206
+ }
176
207
  class ChatContext {
177
208
  _items;
178
209
  constructor(items) {
@@ -418,6 +449,7 @@ class ReadonlyChatContext extends ChatContext {
418
449
  }
419
450
  }
420
451
  export {
452
+ AgentHandoffItem,
421
453
  ChatContext,
422
454
  ChatMessage,
423
455
  FunctionCall,
@@ -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 constructor(params: {\n callId: string;\n name: string;\n args: string;\n id?: string;\n createdAt?: number;\n }) {\n const { callId, name, args, id = shortuuid('item_'), createdAt = Date.now() } = params;\n this.id = id;\n this.callId = callId;\n this.args = args;\n this.name = name;\n this.createdAt = createdAt;\n }\n\n static create(params: {\n callId: string;\n name: string;\n args: string;\n id?: string;\n createdAt?: number;\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 (!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 type ChatItem = ChatMessage | FunctionCall | FunctionCallOutput;\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 (a.name !== b.name || a.callId !== b.callId || a.args !== b.args) {\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 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 constructor(params: {\n callId: string;\n name: string;\n args: string;\n id?: string;\n createdAt?: number;\n }) {\n const { callId, name, args, id = shortuuid('item_'), createdAt = Date.now() } = params;\n this.id = id;\n this.callId = callId;\n this.args = args;\n this.name = name;\n this.createdAt = createdAt;\n }\n\n static create(params: {\n callId: string;\n name: string;\n args: string;\n id?: string;\n createdAt?: number;\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 (!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 (a.name !== b.name || a.callId !== b.callId || a.args !== b.args) {\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":"AAIA,SAAS,sBAAsB,iBAAiB;AAChD,SAA8B,iBAAiB;AAmCxC,SAAS,mBAAmB,QAOlB;AACf,QAAM;AAAA,IACJ;AAAA,IACA,KAAK,UAAU,MAAM;AAAA,IACrB,kBAAkB;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,CAAC;AAAA,EACX;AACF;AAEO,SAAS,mBAAmB,QAGlB;AACf,QAAM,EAAE,OAAO,WAAW,IAAI;AAE9B,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACF;AACF;AAEO,MAAM,YAAY;AAAA,EACd;AAAA,EAEA,OAAO;AAAA,EAEP;AAAA,EAET;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA,YAAY,QAMT;AACD,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,KAAK,UAAU,OAAO;AAAA,MACtB,cAAc;AAAA,MACd,YAAY,KAAK,IAAI;AAAA,IACvB,IAAI;AACJ,SAAK,KAAK;AACV,SAAK,OAAO;AACZ,SAAK,UAAU,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;AAC1D,SAAK,cAAc;AACnB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,OAAO,OAAO,QAMX;AACD,WAAO,IAAI,YAAY,MAAM;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,cAAkC;AACpC,UAAM,QAAQ,KAAK,QAAQ,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ;AAC3E,WAAO,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI;AAAA,EAC/C;AAAA,EAEA,gBAA6B;AAC3B,WAAO,KAAK,QAAQ,IAAI,CAAC,MAAM;AAC7B,UAAI,OAAO,MAAM,UAAU;AACzB,eAAO;AAAA,MACT,WAAW,EAAE,SAAS,iBAAiB;AACrC,eAAO;AAAA,UACL,IAAI,EAAE;AAAA,UACN,MAAM,EAAE;AAAA,UACR,OAAO,EAAE;AAAA,UACT,iBAAiB,EAAE;AAAA,UACnB,gBAAgB,EAAE;AAAA,UAClB,iBAAiB,EAAE;AAAA,UACnB,UAAU,EAAE;AAAA,QACd;AAAA,MACF,OAAO;AACL,eAAO;AAAA,UACL,MAAM,EAAE;AAAA,UACR,YAAY,EAAE;AAAA,QAChB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,OAAO,mBAA4B,OAAkB;AACnD,UAAM,SAAoB;AAAA,MACxB,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,SAAS,KAAK,cAAc;AAAA,MAC5B,aAAa,KAAK;AAAA,IACpB;AAEA,QAAI,CAAC,kBAAkB;AACrB,aAAO,YAAY,KAAK;AAAA,IAC1B;AAEA,WAAO;AAAA,EACT;AACF;AAEO,MAAM,aAAa;AAAA,EACf;AAAA,EAEA,OAAO;AAAA,EAEhB;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA,YAAY,QAMT;AACD,UAAM,EAAE,QAAQ,MAAM,MAAM,KAAK,UAAU,OAAO,GAAG,YAAY,KAAK,IAAI,EAAE,IAAI;AAChF,SAAK,KAAK;AACV,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,OAAO,OAAO,QAMX;AACD,WAAO,IAAI,aAAa,MAAM;AAAA,EAChC;AAAA;AAAA,EAGA,OAAO,mBAA4B,OAAkB;AACnD,UAAM,SAAoB;AAAA,MACxB,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,IACb;AAEA,QAAI,CAAC,kBAAkB;AACrB,aAAO,YAAY,KAAK;AAAA,IAC1B;AAEA,WAAO;AAAA,EACT;AACF;AAEO,MAAM,mBAAmB;AAAA,EACrB;AAAA,EAEA,OAAO;AAAA,EAEhB,OAAO;AAAA,EAEP;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA,YAAY,QAOT;AACD,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,UAAU,OAAO;AAAA,MACtB,YAAY,KAAK,IAAI;AAAA,MACrB,OAAO;AAAA,IACT,IAAI;AACJ,SAAK,KAAK;AACV,SAAK,SAAS;AACd,SAAK,SAAS;AACd,SAAK,UAAU;AACf,SAAK,OAAO;AACZ,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,OAAO,OAAO,QAOX;AACD,WAAO,IAAI,mBAAmB,MAAM;AAAA,EACtC;AAAA,EAEA,OAAO,mBAA4B,OAAkB;AACnD,UAAM,SAAoB;AAAA,MACxB,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,IAChB;AAEA,QAAI,CAAC,kBAAkB;AACrB,aAAO,YAAY,KAAK;AAAA,IAC1B;AAEA,WAAO;AAAA,EACT;AACF;AAEO,MAAM,iBAAiB;AAAA,EACnB;AAAA,EAEA,OAAO;AAAA,EAEhB;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA,YAAY,QAKT;AACD,UAAM,EAAE,YAAY,YAAY,KAAK,UAAU,OAAO,GAAG,YAAY,KAAK,IAAI,EAAE,IAAI;AACpF,SAAK,KAAK;AACV,SAAK,aAAa;AAClB,SAAK,aAAa;AAClB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,OAAO,OAAO,QAKX;AACD,WAAO,IAAI,iBAAiB,MAAM;AAAA,EACpC;AAAA,EAEA,OAAO,mBAA4B,OAAkB;AACnD,UAAM,SAAoB;AAAA,MACxB,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX,YAAY,KAAK;AAAA,IACnB;AAEA,QAAI,KAAK,eAAe,QAAW;AACjC,aAAO,aAAa,KAAK;AAAA,IAC3B;AAEA,QAAI,CAAC,kBAAkB;AACrB,aAAO,YAAY,KAAK;AAAA,IAC1B;AAEA,WAAO;AAAA,EACT;AACF;AAIO,MAAM,YAAY;AAAA,EACb;AAAA,EAEV,YAAY,OAAoB;AAC9B,SAAK,SAAS,QAAQ,QAAQ,CAAC;AAAA,EACjC;AAAA,EAEA,OAAO,QAAqB;AAC1B,WAAO,IAAI,YAAY,CAAC,CAAC;AAAA,EAC3B;AAAA,EAEA,IAAI,QAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,MAAM,OAAmB;AAC3B,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,QAMK;AACd,UAAM,MAAM,IAAI,YAAY,MAAM;AAClC,QAAI,OAAO,cAAc,QAAW;AAClC,YAAM,MAAM,KAAK,mBAAmB,OAAO,SAAS;AACpD,WAAK,OAAO,OAAO,KAAK,GAAG,GAAG;AAAA,IAChC,OAAO;AACL,WAAK,OAAO,KAAK,GAAG;AAAA,IACtB;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,MAAmC;AACxC,UAAM,MAAM,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;AAC9C,eAAW,MAAM,KAAK;AACpB,YAAM,MAAM,KAAK,mBAAmB,GAAG,SAAS;AAChD,WAAK,OAAO,OAAO,KAAK,GAAG,EAAE;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,QAAQ,QAAsC;AAC5C,WAAO,KAAK,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AAAA,EAChD;AAAA,EAEA,UAAU,QAAoC;AAC5C,UAAM,MAAM,KAAK,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,MAAM;AACxD,WAAO,QAAQ,KAAK,MAAM;AAAA,EAC5B;AAAA,EAEA,KACE,UAKI,CAAC,GACQ;AACb,UAAM;AAAA,MACJ,sBAAsB;AAAA,MACtB,sBAAsB;AAAA,MACtB,sBAAsB;AAAA,MACtB;AAAA,IACF,IAAI;AACJ,UAAM,QAAoB,CAAC;AAE3B,UAAM,qBAAqB,CAAC,SAC1B,CAAC,iBAAiB,sBAAsB,EAAE,SAAS,KAAK,IAAI;AAC9D,UAAM,gBAAgB,CAAC,SAAwC,KAAK,SAAS;AAE7E,eAAW,QAAQ,KAAK,QAAQ;AAC9B,UAAI,uBAAuB,mBAAmB,IAAI,GAAG;AACnD;AAAA,MACF;AAEA,UACE,uBACA,cAAc,IAAI,KAClB,CAAC,UAAU,WAAW,EAAE,SAAS,KAAK,IAAI,GAC1C;AACA;AAAA,MACF;AAEA,UAAI,uBAAuB,cAAc,IAAI,KAAK,KAAK,QAAQ,WAAW,GAAG;AAC3E;AAAA,MACF;AAEA,UAAI,YAAY,UAAa,mBAAmB,IAAI,KAAK,QAAQ,KAAK,IAAI,MAAM,QAAW;AACzF;AAAA,MACF;AAEA,YAAM,KAAK,IAAI;AAAA,IACjB;AAEA,WAAO,IAAI,YAAY,KAAK;AAAA,EAC9B;AAAA,EAEA,SAAS,UAA+B;AACtC,QAAI,YAAY,EAAG,QAAO;AAE1B,UAAM,eAAe,KAAK,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,SAAS,QAAQ;AAIxF,QAAI,WAAW,KAAK,OAAO,MAAM,CAAC,QAAQ;AAG1C,WACE,SAAS,SAAS,KAClB,CAAC,iBAAiB,sBAAsB,EAAE,SAAS,SAAS,CAAC,EAAG,IAAI,GACpE;AACA,eAAS,MAAM;AAAA,IACjB;AAEA,QAAI,cAAc;AAEhB,UAAI,CAAC,SAAS,SAAS,YAAY,GAAG;AACpC,mBAAW,CAAC,cAAc,GAAG,QAAQ;AAAA,MACvC;AAAA,IACF;AAGA,SAAK,OAAO,OAAO,GAAG,KAAK,OAAO,QAAQ,GAAG,QAAQ;AACrD,WAAO;AAAA,EACT;AAAA,EAEA,OACE,UAKI,CAAC,GAEO;AACZ,UAAM;AAAA,MACJ,eAAe;AAAA,MACf,eAAe;AAAA,MACf,mBAAmB;AAAA,MACnB,sBAAsB;AAAA,IACxB,IAAI;AAEJ,UAAM,QAAoB,CAAC;AAE3B,eAAW,QAAQ,KAAK,QAAQ;AAC9B,UAAI,gBAAgB;AAEpB,UAAI,uBAAuB,CAAC,iBAAiB,sBAAsB,EAAE,SAAS,KAAK,IAAI,GAAG;AACxF;AAAA,MACF;AAEA,UAAI,KAAK,SAAS,WAAW;AAC3B,wBAAgB,YAAY,OAAO;AAAA,UACjC,MAAM,KAAK;AAAA,UACX,SAAS,KAAK;AAAA,UACd,IAAI,KAAK;AAAA,UACT,aAAa,KAAK;AAAA,UAClB,WAAW,KAAK;AAAA,QAClB,CAAC;AAGD,YAAI,cAAc;AAChB,wBAAc,UAAU,cAAc,QAAQ,OAAO,CAAC,MAAM;AAC1D,mBAAO,EAAE,OAAO,MAAM,YAAY,EAAE,SAAS;AAAA,UAC/C,CAAC;AAAA,QACH;AAEA,YAAI,cAAc;AAChB,wBAAc,UAAU,cAAc,QAAQ,OAAO,CAAC,MAAM;AAC1D,mBAAO,EAAE,OAAO,MAAM,YAAY,EAAE,SAAS;AAAA,UAC/C,CAAC;AAAA,QACH;AAAA,MACF;AAEA,YAAM,KAAK,aAAa;AAAA,IAC1B;AAEA,WAAO;AAAA,MACL,OAAO,MAAM,IAAI,CAAC,SAAS,KAAK,OAAO,gBAAgB,CAAC;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,iBAAiB,QAAwB,yBAAkC,MAAM;AACrF,WAAO,MAAM,UAAU,QAAQ,MAAM,sBAAsB;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,WAA2B;AACpD,aAAS,IAAI,KAAK,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AACnD,YAAM,OAAO,KAAK,OAAO,CAAC;AAC1B,UAAI,KAAM,aAAa,WAAW;AAChC,eAAO,IAAI;AAAA,MACb;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,aAAa,OAA6B;AACxC,QAAI,SAAS,OAAO;AAClB,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,MAAM,WAAW,MAAM,MAAM,QAAQ;AAC5C,aAAO;AAAA,IACT;AAEA,aAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC1C,YAAM,IAAI,KAAK,MAAM,CAAC;AACtB,YAAM,IAAI,MAAM,MAAM,CAAC;AAEvB,UAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;AACtC,eAAO;AAAA,MACT;AAEA,UAAI,EAAE,SAAS,aAAa,EAAE,SAAS,WAAW;AAChD,YACE,EAAE,SAAS,EAAE,QACb,EAAE,gBAAgB,EAAE,eACpB,CAAC,KAAK,eAAe,EAAE,SAAS,EAAE,OAAO,GACzC;AACA,iBAAO;AAAA,QACT;AAAA,MACF,WAAW,EAAE,SAAS,mBAAmB,EAAE,SAAS,iBAAiB;AACnE,YAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM;AACnE,iBAAO;AAAA,QACT;AAAA,MACF,WAAW,EAAE,SAAS,0BAA0B,EAAE,SAAS,wBAAwB;AACjF,YACE,EAAE,SAAS,EAAE,QACb,EAAE,WAAW,EAAE,UACf,EAAE,WAAW,EAAE,UACf,EAAE,YAAY,EAAE,SAChB;AACA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,GAAkB,GAA2B;AAClE,QAAI,EAAE,WAAW,EAAE,QAAQ;AACzB,aAAO;AAAA,IACT;AAEA,aAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,YAAM,WAAW,EAAE,CAAC;AACpB,YAAM,WAAW,EAAE,CAAC;AAEpB,UAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UAAU;AAChE,YAAI,aAAa,UAAU;AACzB,iBAAO;AAAA,QACT;AACA;AAAA,MACF;AAEA,UAAI,OAAO,aAAa,OAAO,UAAU;AACvC,eAAO;AAAA,MACT;AAEA,UAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UAAU;AAChE,YAAI,SAAS,SAAS,mBAAmB,SAAS,SAAS,iBAAiB;AAC1E,cACE,SAAS,OAAO,SAAS,MACzB,SAAS,UAAU,SAAS,SAC5B,SAAS,oBAAoB,SAAS,mBACtC,SAAS,mBAAmB,SAAS,kBACrC,SAAS,oBAAoB,SAAS,mBACtC,SAAS,aAAa,SAAS,UAC/B;AACA,mBAAO;AAAA,UACT;AAAA,QACF,WAAW,SAAS,SAAS,mBAAmB,SAAS,SAAS,iBAAiB;AACjF,cAAI,SAAS,MAAM,WAAW,SAAS,MAAM,QAAQ;AACnD,mBAAO;AAAA,UACT;AACA,cAAI,SAAS,eAAe,SAAS,YAAY;AAC/C,mBAAO;AAAA,UACT;AAAA,QACF,OAAO;AACL,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAAoB;AACtB,WAAO;AAAA,EACT;AACF;AAEO,MAAM,4BAA4B,YAAY;AAAA,EACnD,OAAgB,WACd;AAAA,EAEF,YAAY,OAAmB;AAC7B,UAAM,qBAAqB,OAAO,oBAAoB,QAAQ,CAAC;AAAA,EACjE;AAAA,EAEA,IAAI,QAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,MAAM,OAAmB;AAC3B,UAAM,IAAI;AAAA,MACR,iDAAiD,oBAAoB,QAAQ;AAAA,IAC/E;AAAA,EACF;AAAA,EAEA,IAAI,WAAoB;AACtB,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -18,6 +18,7 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var llm_exports = {};
20
20
  __export(llm_exports, {
21
+ AgentHandoffItem: () => import_chat_context.AgentHandoffItem,
21
22
  ChatContext: () => import_chat_context.ChatContext,
22
23
  ChatMessage: () => import_chat_context.ChatMessage,
23
24
  FunctionCall: () => import_chat_context.FunctionCall,
@@ -49,6 +50,7 @@ var import_remote_chat_context = require("./remote_chat_context.cjs");
49
50
  var import_utils = require("./utils.cjs");
50
51
  // Annotate the CommonJS export names for ESM import in node:
51
52
  0 && (module.exports = {
53
+ AgentHandoffItem,
52
54
  ChatContext,
53
55
  ChatMessage,
54
56
  FunctionCall,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/llm/index.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nexport {\n handoff,\n isFunctionTool,\n tool,\n ToolError,\n type AgentHandoff,\n type FunctionTool,\n type ProviderDefinedTool,\n type Tool,\n type ToolChoice,\n type ToolContext,\n type ToolOptions,\n type ToolType,\n} from './tool_context.js';\n\nexport {\n ChatContext,\n ChatMessage,\n createAudioContent,\n createImageContent,\n FunctionCall,\n FunctionCallOutput,\n type AudioContent,\n type ChatContent,\n type ChatItem,\n type ChatRole,\n type ImageContent,\n} from './chat_context.js';\n\nexport type { ProviderFormat } from './provider_format/index.js';\n\nexport {\n LLM,\n LLMStream,\n type ChatChunk,\n type ChoiceDelta,\n type CompletionUsage,\n type LLMCallbacks,\n} from './llm.js';\n\nexport {\n RealtimeModel,\n RealtimeSession,\n type GenerationCreatedEvent,\n type InputSpeechStartedEvent,\n type InputSpeechStoppedEvent,\n type InputTranscriptionCompleted,\n type MessageGeneration,\n type RealtimeCapabilities,\n type RealtimeModelError,\n type RealtimeSessionReconnectedEvent,\n} from './realtime.js';\n\nexport { RemoteChatContext } from './remote_chat_context.js';\n\nexport {\n computeChatCtxDiff,\n createToolOptions,\n executeToolCall,\n oaiBuildFunctionInfo,\n oaiParams,\n toJsonSchema,\n type OpenAIFunctionParameters,\n} from './utils.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,0BAaO;AAEP,0BAYO;AAIP,iBAOO;AAEP,sBAWO;AAEP,iCAAkC;AAElC,mBAQO;","names":[]}
1
+ {"version":3,"sources":["../../src/llm/index.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nexport {\n handoff,\n isFunctionTool,\n tool,\n ToolError,\n type AgentHandoff,\n type FunctionTool,\n type ProviderDefinedTool,\n type Tool,\n type ToolChoice,\n type ToolContext,\n type ToolOptions,\n type ToolType,\n} from './tool_context.js';\n\nexport {\n AgentHandoffItem,\n ChatContext,\n ChatMessage,\n createAudioContent,\n createImageContent,\n FunctionCall,\n FunctionCallOutput,\n type AudioContent,\n type ChatContent,\n type ChatItem,\n type ChatRole,\n type ImageContent,\n} from './chat_context.js';\n\nexport type { ProviderFormat } from './provider_format/index.js';\n\nexport {\n LLM,\n LLMStream,\n type ChatChunk,\n type ChoiceDelta,\n type CompletionUsage,\n type LLMCallbacks,\n} from './llm.js';\n\nexport {\n RealtimeModel,\n RealtimeSession,\n type GenerationCreatedEvent,\n type InputSpeechStartedEvent,\n type InputSpeechStoppedEvent,\n type InputTranscriptionCompleted,\n type MessageGeneration,\n type RealtimeCapabilities,\n type RealtimeModelError,\n type RealtimeSessionReconnectedEvent,\n} from './realtime.js';\n\nexport { RemoteChatContext } from './remote_chat_context.js';\n\nexport {\n computeChatCtxDiff,\n createToolOptions,\n executeToolCall,\n oaiBuildFunctionInfo,\n oaiParams,\n toJsonSchema,\n type OpenAIFunctionParameters,\n} from './utils.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,0BAaO;AAEP,0BAaO;AAIP,iBAOO;AAEP,sBAWO;AAEP,iCAAkC;AAElC,mBAQO;","names":[]}
@@ -1,5 +1,5 @@
1
1
  export { handoff, isFunctionTool, tool, ToolError, type AgentHandoff, type FunctionTool, type ProviderDefinedTool, type Tool, type ToolChoice, type ToolContext, type ToolOptions, type ToolType, } from './tool_context.js';
2
- export { ChatContext, ChatMessage, createAudioContent, createImageContent, FunctionCall, FunctionCallOutput, type AudioContent, type ChatContent, type ChatItem, type ChatRole, type ImageContent, } from './chat_context.js';
2
+ export { AgentHandoffItem, ChatContext, ChatMessage, createAudioContent, createImageContent, FunctionCall, FunctionCallOutput, type AudioContent, type ChatContent, type ChatItem, type ChatRole, type ImageContent, } from './chat_context.js';
3
3
  export type { ProviderFormat } from './provider_format/index.js';
4
4
  export { LLM, LLMStream, type ChatChunk, type ChoiceDelta, type CompletionUsage, type LLMCallbacks, } from './llm.js';
5
5
  export { RealtimeModel, RealtimeSession, type GenerationCreatedEvent, type InputSpeechStartedEvent, type InputSpeechStoppedEvent, type InputTranscriptionCompleted, type MessageGeneration, type RealtimeCapabilities, type RealtimeModelError, type RealtimeSessionReconnectedEvent, } from './realtime.js';
@@ -1,5 +1,5 @@
1
1
  export { handoff, isFunctionTool, tool, ToolError, type AgentHandoff, type FunctionTool, type ProviderDefinedTool, type Tool, type ToolChoice, type ToolContext, type ToolOptions, type ToolType, } from './tool_context.js';
2
- export { ChatContext, ChatMessage, createAudioContent, createImageContent, FunctionCall, FunctionCallOutput, type AudioContent, type ChatContent, type ChatItem, type ChatRole, type ImageContent, } from './chat_context.js';
2
+ export { AgentHandoffItem, ChatContext, ChatMessage, createAudioContent, createImageContent, FunctionCall, FunctionCallOutput, type AudioContent, type ChatContent, type ChatItem, type ChatRole, type ImageContent, } from './chat_context.js';
3
3
  export type { ProviderFormat } from './provider_format/index.js';
4
4
  export { LLM, LLMStream, type ChatChunk, type ChoiceDelta, type CompletionUsage, type LLMCallbacks, } from './llm.js';
5
5
  export { RealtimeModel, RealtimeSession, type GenerationCreatedEvent, type InputSpeechStartedEvent, type InputSpeechStoppedEvent, type InputTranscriptionCompleted, type MessageGeneration, type RealtimeCapabilities, type RealtimeModelError, type RealtimeSessionReconnectedEvent, } from './realtime.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,OAAO,EACP,cAAc,EACd,IAAI,EACJ,SAAS,EACT,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,IAAI,EACT,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,QAAQ,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,YAAY,GAClB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EACL,GAAG,EACH,SAAS,EACT,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,aAAa,EACb,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,2BAA2B,EAChC,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,+BAA+B,GACrC,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,SAAS,EACT,YAAY,EACZ,KAAK,wBAAwB,GAC9B,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,OAAO,EACP,cAAc,EACd,IAAI,EACJ,SAAS,EACT,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,IAAI,EACT,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,QAAQ,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,YAAY,GAClB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EACL,GAAG,EACH,SAAS,EACT,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,aAAa,EACb,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,2BAA2B,EAChC,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,+BAA+B,GACrC,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,SAAS,EACT,YAAY,EACZ,KAAK,wBAAwB,GAC9B,MAAM,YAAY,CAAC"}
package/dist/llm/index.js CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  ToolError
6
6
  } from "./tool_context.js";
7
7
  import {
8
+ AgentHandoffItem,
8
9
  ChatContext,
9
10
  ChatMessage,
10
11
  createAudioContent,
@@ -30,6 +31,7 @@ import {
30
31
  toJsonSchema
31
32
  } from "./utils.js";
32
33
  export {
34
+ AgentHandoffItem,
33
35
  ChatContext,
34
36
  ChatMessage,
35
37
  FunctionCall,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/llm/index.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nexport {\n handoff,\n isFunctionTool,\n tool,\n ToolError,\n type AgentHandoff,\n type FunctionTool,\n type ProviderDefinedTool,\n type Tool,\n type ToolChoice,\n type ToolContext,\n type ToolOptions,\n type ToolType,\n} from './tool_context.js';\n\nexport {\n ChatContext,\n ChatMessage,\n createAudioContent,\n createImageContent,\n FunctionCall,\n FunctionCallOutput,\n type AudioContent,\n type ChatContent,\n type ChatItem,\n type ChatRole,\n type ImageContent,\n} from './chat_context.js';\n\nexport type { ProviderFormat } from './provider_format/index.js';\n\nexport {\n LLM,\n LLMStream,\n type ChatChunk,\n type ChoiceDelta,\n type CompletionUsage,\n type LLMCallbacks,\n} from './llm.js';\n\nexport {\n RealtimeModel,\n RealtimeSession,\n type GenerationCreatedEvent,\n type InputSpeechStartedEvent,\n type InputSpeechStoppedEvent,\n type InputTranscriptionCompleted,\n type MessageGeneration,\n type RealtimeCapabilities,\n type RealtimeModelError,\n type RealtimeSessionReconnectedEvent,\n} from './realtime.js';\n\nexport { RemoteChatContext } from './remote_chat_context.js';\n\nexport {\n computeChatCtxDiff,\n createToolOptions,\n executeToolCall,\n oaiBuildFunctionInfo,\n oaiParams,\n toJsonSchema,\n type OpenAIFunctionParameters,\n} from './utils.js';\n"],"mappings":"AAGA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OASK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAMK;AAIP;AAAA,EACE;AAAA,EACA;AAAA,OAKK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,OASK;AAEP,SAAS,yBAAyB;AAElC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;","names":[]}
1
+ {"version":3,"sources":["../../src/llm/index.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nexport {\n handoff,\n isFunctionTool,\n tool,\n ToolError,\n type AgentHandoff,\n type FunctionTool,\n type ProviderDefinedTool,\n type Tool,\n type ToolChoice,\n type ToolContext,\n type ToolOptions,\n type ToolType,\n} from './tool_context.js';\n\nexport {\n AgentHandoffItem,\n ChatContext,\n ChatMessage,\n createAudioContent,\n createImageContent,\n FunctionCall,\n FunctionCallOutput,\n type AudioContent,\n type ChatContent,\n type ChatItem,\n type ChatRole,\n type ImageContent,\n} from './chat_context.js';\n\nexport type { ProviderFormat } from './provider_format/index.js';\n\nexport {\n LLM,\n LLMStream,\n type ChatChunk,\n type ChoiceDelta,\n type CompletionUsage,\n type LLMCallbacks,\n} from './llm.js';\n\nexport {\n RealtimeModel,\n RealtimeSession,\n type GenerationCreatedEvent,\n type InputSpeechStartedEvent,\n type InputSpeechStoppedEvent,\n type InputTranscriptionCompleted,\n type MessageGeneration,\n type RealtimeCapabilities,\n type RealtimeModelError,\n type RealtimeSessionReconnectedEvent,\n} from './realtime.js';\n\nexport { RemoteChatContext } from './remote_chat_context.js';\n\nexport {\n computeChatCtxDiff,\n createToolOptions,\n executeToolCall,\n oaiBuildFunctionInfo,\n oaiParams,\n toJsonSchema,\n type OpenAIFunctionParameters,\n} from './utils.js';\n"],"mappings":"AAGA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OASK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAMK;AAIP;AAAA,EACE;AAAA,EACA;AAAA,OAKK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,OASK;AAEP,SAAS,yBAAyB;AAElC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/llm/llm.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { EventEmitter } from 'node:events';\nimport { APIConnectionError, APIError } from '../_exceptions.js';\nimport { log } from '../log.js';\nimport type { LLMMetrics } from '../metrics/base.js';\nimport type { APIConnectOptions } from '../types.js';\nimport { AsyncIterableQueue, delay, startSoon, toError } from '../utils.js';\nimport { type ChatContext, type ChatRole, type FunctionCall } from './chat_context.js';\nimport type { ToolChoice, ToolContext } from './tool_context.js';\n\nexport interface ChoiceDelta {\n role: ChatRole;\n content?: string;\n toolCalls?: FunctionCall[];\n}\n\nexport interface CompletionUsage {\n completionTokens: number;\n promptTokens: number;\n promptCachedTokens: number;\n totalTokens: number;\n}\n\nexport interface ChatChunk {\n id: string;\n delta?: ChoiceDelta;\n usage?: CompletionUsage;\n}\n\nexport interface LLMError {\n type: 'llm_error';\n timestamp: number;\n label: string;\n error: Error;\n recoverable: boolean;\n}\n\nexport type LLMCallbacks = {\n ['metrics_collected']: (metrics: LLMMetrics) => void;\n ['error']: (error: LLMError) => void;\n};\n\nexport abstract class LLM extends (EventEmitter as new () => TypedEmitter<LLMCallbacks>) {\n constructor() {\n super();\n }\n\n abstract label(): string;\n\n /**\n * Get the model name/identifier for this LLM instance.\n *\n * @returns The model name if available, \"unknown\" otherwise.\n *\n * @remarks\n * Plugins should override this property to provide their model information.\n */\n get model(): string {\n return 'unknown';\n }\n\n /**\n * Returns a {@link LLMStream} that can be used to push text and receive LLM responses.\n */\n abstract chat({\n chatCtx,\n toolCtx,\n connOptions,\n parallelToolCalls,\n toolChoice,\n extraKwargs,\n }: {\n chatCtx: ChatContext;\n toolCtx?: ToolContext;\n connOptions?: APIConnectOptions;\n parallelToolCalls?: boolean;\n toolChoice?: ToolChoice;\n extraKwargs?: Record<string, unknown>;\n }): LLMStream;\n\n /**\n * Pre-warm connection to the LLM service\n */\n prewarm(): void {\n // Default implementation - subclasses can override\n }\n\n async aclose(): Promise<void> {\n // Default implementation - subclasses can override\n }\n}\n\nexport abstract class LLMStream implements AsyncIterableIterator<ChatChunk> {\n protected output = new AsyncIterableQueue<ChatChunk>();\n protected queue = new AsyncIterableQueue<ChatChunk>();\n protected closed = false;\n protected abortController = new AbortController();\n protected _connOptions: APIConnectOptions;\n protected logger = log();\n\n #llm: LLM;\n #chatCtx: ChatContext;\n #toolCtx?: ToolContext;\n\n constructor(\n llm: LLM,\n {\n chatCtx,\n toolCtx,\n connOptions,\n }: {\n chatCtx: ChatContext;\n toolCtx?: ToolContext;\n connOptions: APIConnectOptions;\n },\n ) {\n this.#llm = llm;\n this.#chatCtx = chatCtx;\n this.#toolCtx = toolCtx;\n this._connOptions = connOptions;\n this.monitorMetrics();\n this.abortController.signal.addEventListener('abort', () => {\n // TODO (AJS-37) clean this up when we refactor with streams\n this.output.close();\n this.closed = true;\n });\n\n // this is a hack to immitate asyncio.create_task so that mainTask\n // is run **after** the constructor has finished. Otherwise we get\n // runtime error when trying to access class variables in the\n // `run` method.\n startSoon(() => this.mainTask().then(() => this.queue.close()));\n }\n\n private async mainTask() {\n for (let i = 0; i < this._connOptions.maxRetry + 1; i++) {\n try {\n return await this.run();\n } catch (error) {\n if (error instanceof APIError) {\n const retryInterval = this._connOptions._intervalForRetry(i);\n\n if (this._connOptions.maxRetry === 0 || !error.retryable) {\n this.emitError({ error, recoverable: false });\n throw error;\n } else if (i === this._connOptions.maxRetry) {\n this.emitError({ error, recoverable: false });\n throw new APIConnectionError({\n message: `failed to generate LLM completion after ${this._connOptions.maxRetry + 1} attempts`,\n options: { retryable: false },\n });\n } else {\n this.emitError({ error, recoverable: true });\n this.logger.warn(\n { llm: this.#llm.label(), attempt: i + 1, error },\n `failed to generate LLM completion, retrying in ${retryInterval}s`,\n );\n }\n\n if (retryInterval > 0) {\n await delay(retryInterval);\n }\n } else {\n this.emitError({ error: toError(error), recoverable: false });\n throw error;\n }\n }\n }\n }\n\n private emitError({ error, recoverable }: { error: Error; recoverable: boolean }) {\n this.#llm.emit('error', {\n type: 'llm_error',\n timestamp: Date.now(),\n label: this.#llm.label(),\n error,\n recoverable,\n });\n }\n\n protected async monitorMetrics() {\n const startTime = process.hrtime.bigint();\n let ttft: bigint = BigInt(-1);\n let requestId = '';\n let usage: CompletionUsage | undefined;\n\n for await (const ev of this.queue) {\n if (this.abortController.signal.aborted) {\n break;\n }\n this.output.put(ev);\n requestId = ev.id;\n if (ttft === BigInt(-1)) {\n ttft = process.hrtime.bigint() - startTime;\n }\n if (ev.usage) {\n usage = ev.usage;\n }\n }\n this.output.close();\n\n const duration = process.hrtime.bigint() - startTime;\n const durationMs = Math.trunc(Number(duration / BigInt(1000000)));\n const metrics: LLMMetrics = {\n type: 'llm_metrics',\n timestamp: Date.now(),\n requestId,\n ttftMs: ttft === BigInt(-1) ? -1 : Math.trunc(Number(ttft / BigInt(1000000))),\n durationMs,\n cancelled: this.abortController.signal.aborted,\n label: this.#llm.label(),\n completionTokens: usage?.completionTokens || 0,\n promptTokens: usage?.promptTokens || 0,\n promptCachedTokens: usage?.promptCachedTokens || 0,\n totalTokens: usage?.totalTokens || 0,\n tokensPerSecond: (() => {\n if (durationMs <= 0) {\n return 0;\n }\n return (usage?.completionTokens || 0) / (durationMs / 1000);\n })(),\n };\n this.#llm.emit('metrics_collected', metrics);\n }\n\n protected abstract run(): Promise<void>;\n\n /** The function context of this stream. */\n get toolCtx(): ToolContext | undefined {\n return this.#toolCtx;\n }\n\n /** The initial chat context of this stream. */\n get chatCtx(): ChatContext {\n return this.#chatCtx;\n }\n\n /** The connection options for this stream. */\n get connOptions(): APIConnectOptions {\n return this._connOptions;\n }\n\n next(): Promise<IteratorResult<ChatChunk>> {\n return this.output.next();\n }\n\n close() {\n this.abortController.abort();\n }\n\n [Symbol.asyncIterator](): LLMStream {\n return this;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/llm/llm.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { EventEmitter } from 'node:events';\nimport { APIConnectionError, APIError } from '../_exceptions.js';\nimport { log } from '../log.js';\nimport type { LLMMetrics } from '../metrics/base.js';\nimport type { APIConnectOptions } from '../types.js';\nimport { AsyncIterableQueue, delay, startSoon, toError } from '../utils.js';\nimport { type ChatContext, type ChatRole, type FunctionCall } from './chat_context.js';\nimport type { ToolChoice, ToolContext } from './tool_context.js';\n\nexport interface ChoiceDelta {\n role: ChatRole;\n content?: string;\n toolCalls?: FunctionCall[];\n}\n\nexport interface CompletionUsage {\n completionTokens: number;\n promptTokens: number;\n promptCachedTokens: number;\n totalTokens: number;\n}\n\nexport interface ChatChunk {\n id: string;\n delta?: ChoiceDelta;\n usage?: CompletionUsage;\n}\n\nexport interface LLMError {\n type: 'llm_error';\n timestamp: number;\n label: string;\n error: Error;\n recoverable: boolean;\n}\n\nexport type LLMCallbacks = {\n ['metrics_collected']: (metrics: LLMMetrics) => void;\n ['error']: (error: LLMError) => void;\n};\n\nexport abstract class LLM extends (EventEmitter as new () => TypedEmitter<LLMCallbacks>) {\n constructor() {\n super();\n }\n\n abstract label(): string;\n\n /**\n * Get the model name/identifier for this LLM instance.\n *\n * @returns The model name if available, \"unknown\" otherwise.\n *\n * @remarks\n * Plugins should override this property to provide their model information.\n */\n get model(): string {\n return 'unknown';\n }\n\n /**\n * Returns a {@link LLMStream} that can be used to push text and receive LLM responses.\n */\n abstract chat({\n chatCtx,\n toolCtx,\n connOptions,\n parallelToolCalls,\n toolChoice,\n extraKwargs,\n }: {\n chatCtx: ChatContext;\n toolCtx?: ToolContext;\n connOptions?: APIConnectOptions;\n parallelToolCalls?: boolean;\n toolChoice?: ToolChoice;\n extraKwargs?: Record<string, unknown>;\n }): LLMStream;\n\n /**\n * Pre-warm connection to the LLM service\n */\n prewarm(): void {\n // Default implementation - subclasses can override\n }\n\n async aclose(): Promise<void> {\n // Default implementation - subclasses can override\n }\n}\n\nexport abstract class LLMStream implements AsyncIterableIterator<ChatChunk> {\n protected output = new AsyncIterableQueue<ChatChunk>();\n protected queue = new AsyncIterableQueue<ChatChunk>();\n protected closed = false;\n protected abortController = new AbortController();\n protected _connOptions: APIConnectOptions;\n protected logger = log();\n\n #llm: LLM;\n #chatCtx: ChatContext;\n #toolCtx?: ToolContext;\n\n constructor(\n llm: LLM,\n {\n chatCtx,\n toolCtx,\n connOptions,\n }: {\n chatCtx: ChatContext;\n toolCtx?: ToolContext;\n connOptions: APIConnectOptions;\n },\n ) {\n this.#llm = llm;\n this.#chatCtx = chatCtx;\n this.#toolCtx = toolCtx;\n this._connOptions = connOptions;\n this.monitorMetrics();\n this.abortController.signal.addEventListener('abort', () => {\n // TODO (AJS-37) clean this up when we refactor with streams\n this.output.close();\n this.closed = true;\n });\n\n // this is a hack to immitate asyncio.create_task so that mainTask\n // is run **after** the constructor has finished. Otherwise we get\n // runtime error when trying to access class variables in the\n // `run` method.\n startSoon(() => this.mainTask().then(() => this.queue.close()));\n }\n\n private async mainTask() {\n // TODO(brian): PR3 - Add span wrapping: tracer.startActiveSpan('llm_request', ..., { endOnExit: false })\n for (let i = 0; i < this._connOptions.maxRetry + 1; i++) {\n try {\n // TODO(brian): PR3 - Add span for retry attempts: tracer.startActiveSpan('llm_request_run', ...)\n return await this.run();\n } catch (error) {\n if (error instanceof APIError) {\n const retryInterval = this._connOptions._intervalForRetry(i);\n\n if (this._connOptions.maxRetry === 0 || !error.retryable) {\n this.emitError({ error, recoverable: false });\n throw error;\n } else if (i === this._connOptions.maxRetry) {\n this.emitError({ error, recoverable: false });\n throw new APIConnectionError({\n message: `failed to generate LLM completion after ${this._connOptions.maxRetry + 1} attempts`,\n options: { retryable: false },\n });\n } else {\n this.emitError({ error, recoverable: true });\n this.logger.warn(\n { llm: this.#llm.label(), attempt: i + 1, error },\n `failed to generate LLM completion, retrying in ${retryInterval}s`,\n );\n }\n\n if (retryInterval > 0) {\n await delay(retryInterval);\n }\n } else {\n this.emitError({ error: toError(error), recoverable: false });\n throw error;\n }\n }\n }\n }\n\n private emitError({ error, recoverable }: { error: Error; recoverable: boolean }) {\n this.#llm.emit('error', {\n type: 'llm_error',\n timestamp: Date.now(),\n label: this.#llm.label(),\n error,\n recoverable,\n });\n }\n\n protected async monitorMetrics() {\n const startTime = process.hrtime.bigint();\n let ttft: bigint = BigInt(-1);\n let requestId = '';\n let usage: CompletionUsage | undefined;\n\n for await (const ev of this.queue) {\n if (this.abortController.signal.aborted) {\n break;\n }\n this.output.put(ev);\n requestId = ev.id;\n if (ttft === BigInt(-1)) {\n ttft = process.hrtime.bigint() - startTime;\n }\n if (ev.usage) {\n usage = ev.usage;\n }\n }\n this.output.close();\n\n const duration = process.hrtime.bigint() - startTime;\n const durationMs = Math.trunc(Number(duration / BigInt(1000000)));\n const metrics: LLMMetrics = {\n type: 'llm_metrics',\n timestamp: Date.now(),\n requestId,\n ttftMs: ttft === BigInt(-1) ? -1 : Math.trunc(Number(ttft / BigInt(1000000))),\n durationMs,\n cancelled: this.abortController.signal.aborted,\n label: this.#llm.label(),\n completionTokens: usage?.completionTokens || 0,\n promptTokens: usage?.promptTokens || 0,\n promptCachedTokens: usage?.promptCachedTokens || 0,\n totalTokens: usage?.totalTokens || 0,\n tokensPerSecond: (() => {\n if (durationMs <= 0) {\n return 0;\n }\n return (usage?.completionTokens || 0) / (durationMs / 1000);\n })(),\n };\n this.#llm.emit('metrics_collected', metrics);\n }\n\n protected abstract run(): Promise<void>;\n\n /** The function context of this stream. */\n get toolCtx(): ToolContext | undefined {\n return this.#toolCtx;\n }\n\n /** The initial chat context of this stream. */\n get chatCtx(): ChatContext {\n return this.#chatCtx;\n }\n\n /** The connection options for this stream. */\n get connOptions(): APIConnectOptions {\n return this._connOptions;\n }\n\n next(): Promise<IteratorResult<ChatChunk>> {\n return this.output.next();\n }\n\n close() {\n this.abortController.abort();\n }\n\n [Symbol.asyncIterator](): LLMStream {\n return this;\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../src/llm/llm.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,IAAI,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAIhF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAA6B,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACvF,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEjE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,CAAC,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IACrD,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;CACtC,CAAC;kCAE2D,aAAa,YAAY,CAAC;AAAvF,8BAAsB,GAAI,SAAQ,QAAsD;;IAKtF,QAAQ,CAAC,KAAK,IAAI,MAAM;IAExB;;;;;;;OAOG;IACH,IAAI,KAAK,IAAI,MAAM,CAElB;IAED;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EACZ,OAAO,EACP,OAAO,EACP,WAAW,EACX,iBAAiB,EACjB,UAAU,EACV,WAAW,GACZ,EAAE;QACD,OAAO,EAAE,WAAW,CAAC;QACrB,OAAO,CAAC,EAAE,WAAW,CAAC;QACtB,WAAW,CAAC,EAAE,iBAAiB,CAAC;QAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,UAAU,CAAC,EAAE,UAAU,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACvC,GAAG,SAAS;IAEb;;OAEG;IACH,OAAO,IAAI,IAAI;IAIT,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAG9B;AAED,8BAAsB,SAAU,YAAW,qBAAqB,CAAC,SAAS,CAAC;;IACzE,SAAS,CAAC,MAAM,gCAAuC;IACvD,SAAS,CAAC,KAAK,gCAAuC;IACtD,SAAS,CAAC,MAAM,UAAS;IACzB,SAAS,CAAC,eAAe,kBAAyB;IAClD,SAAS,CAAC,YAAY,EAAE,iBAAiB,CAAC;IAC1C,SAAS,CAAC,MAAM,wBAAS;gBAOvB,GAAG,EAAE,GAAG,EACR,EACE,OAAO,EACP,OAAO,EACP,WAAW,GACZ,EAAE;QACD,OAAO,EAAE,WAAW,CAAC;QACrB,OAAO,CAAC,EAAE,WAAW,CAAC;QACtB,WAAW,EAAE,iBAAiB,CAAC;KAChC;YAoBW,QAAQ;IAoCtB,OAAO,CAAC,SAAS;cAUD,cAAc;IA6C9B,SAAS,CAAC,QAAQ,CAAC,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAEvC,2CAA2C;IAC3C,IAAI,OAAO,IAAI,WAAW,GAAG,SAAS,CAErC;IAED,+CAA+C;IAC/C,IAAI,OAAO,IAAI,WAAW,CAEzB;IAED,8CAA8C;IAC9C,IAAI,WAAW,IAAI,iBAAiB,CAEnC;IAED,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAI1C,KAAK;IAIL,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,SAAS;CAGpC"}
1
+ {"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../src/llm/llm.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/llm/llm.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { EventEmitter } from 'node:events';\nimport { APIConnectionError, APIError } from '../_exceptions.js';\nimport { log } from '../log.js';\nimport type { LLMMetrics } from '../metrics/base.js';\nimport type { APIConnectOptions } from '../types.js';\nimport { AsyncIterableQueue, delay, startSoon, toError } from '../utils.js';\nimport { type ChatContext, type ChatRole, type FunctionCall } from './chat_context.js';\nimport type { ToolChoice, ToolContext } from './tool_context.js';\n\nexport interface ChoiceDelta {\n role: ChatRole;\n content?: string;\n toolCalls?: FunctionCall[];\n}\n\nexport interface CompletionUsage {\n completionTokens: number;\n promptTokens: number;\n promptCachedTokens: number;\n totalTokens: number;\n}\n\nexport interface ChatChunk {\n id: string;\n delta?: ChoiceDelta;\n usage?: CompletionUsage;\n}\n\nexport interface LLMError {\n type: 'llm_error';\n timestamp: number;\n label: string;\n error: Error;\n recoverable: boolean;\n}\n\nexport type LLMCallbacks = {\n ['metrics_collected']: (metrics: LLMMetrics) => void;\n ['error']: (error: LLMError) => void;\n};\n\nexport abstract class LLM extends (EventEmitter as new () => TypedEmitter<LLMCallbacks>) {\n constructor() {\n super();\n }\n\n abstract label(): string;\n\n /**\n * Get the model name/identifier for this LLM instance.\n *\n * @returns The model name if available, \"unknown\" otherwise.\n *\n * @remarks\n * Plugins should override this property to provide their model information.\n */\n get model(): string {\n return 'unknown';\n }\n\n /**\n * Returns a {@link LLMStream} that can be used to push text and receive LLM responses.\n */\n abstract chat({\n chatCtx,\n toolCtx,\n connOptions,\n parallelToolCalls,\n toolChoice,\n extraKwargs,\n }: {\n chatCtx: ChatContext;\n toolCtx?: ToolContext;\n connOptions?: APIConnectOptions;\n parallelToolCalls?: boolean;\n toolChoice?: ToolChoice;\n extraKwargs?: Record<string, unknown>;\n }): LLMStream;\n\n /**\n * Pre-warm connection to the LLM service\n */\n prewarm(): void {\n // Default implementation - subclasses can override\n }\n\n async aclose(): Promise<void> {\n // Default implementation - subclasses can override\n }\n}\n\nexport abstract class LLMStream implements AsyncIterableIterator<ChatChunk> {\n protected output = new AsyncIterableQueue<ChatChunk>();\n protected queue = new AsyncIterableQueue<ChatChunk>();\n protected closed = false;\n protected abortController = new AbortController();\n protected _connOptions: APIConnectOptions;\n protected logger = log();\n\n #llm: LLM;\n #chatCtx: ChatContext;\n #toolCtx?: ToolContext;\n\n constructor(\n llm: LLM,\n {\n chatCtx,\n toolCtx,\n connOptions,\n }: {\n chatCtx: ChatContext;\n toolCtx?: ToolContext;\n connOptions: APIConnectOptions;\n },\n ) {\n this.#llm = llm;\n this.#chatCtx = chatCtx;\n this.#toolCtx = toolCtx;\n this._connOptions = connOptions;\n this.monitorMetrics();\n this.abortController.signal.addEventListener('abort', () => {\n // TODO (AJS-37) clean this up when we refactor with streams\n this.output.close();\n this.closed = true;\n });\n\n // this is a hack to immitate asyncio.create_task so that mainTask\n // is run **after** the constructor has finished. Otherwise we get\n // runtime error when trying to access class variables in the\n // `run` method.\n startSoon(() => this.mainTask().then(() => this.queue.close()));\n }\n\n private async mainTask() {\n for (let i = 0; i < this._connOptions.maxRetry + 1; i++) {\n try {\n return await this.run();\n } catch (error) {\n if (error instanceof APIError) {\n const retryInterval = this._connOptions._intervalForRetry(i);\n\n if (this._connOptions.maxRetry === 0 || !error.retryable) {\n this.emitError({ error, recoverable: false });\n throw error;\n } else if (i === this._connOptions.maxRetry) {\n this.emitError({ error, recoverable: false });\n throw new APIConnectionError({\n message: `failed to generate LLM completion after ${this._connOptions.maxRetry + 1} attempts`,\n options: { retryable: false },\n });\n } else {\n this.emitError({ error, recoverable: true });\n this.logger.warn(\n { llm: this.#llm.label(), attempt: i + 1, error },\n `failed to generate LLM completion, retrying in ${retryInterval}s`,\n );\n }\n\n if (retryInterval > 0) {\n await delay(retryInterval);\n }\n } else {\n this.emitError({ error: toError(error), recoverable: false });\n throw error;\n }\n }\n }\n }\n\n private emitError({ error, recoverable }: { error: Error; recoverable: boolean }) {\n this.#llm.emit('error', {\n type: 'llm_error',\n timestamp: Date.now(),\n label: this.#llm.label(),\n error,\n recoverable,\n });\n }\n\n protected async monitorMetrics() {\n const startTime = process.hrtime.bigint();\n let ttft: bigint = BigInt(-1);\n let requestId = '';\n let usage: CompletionUsage | undefined;\n\n for await (const ev of this.queue) {\n if (this.abortController.signal.aborted) {\n break;\n }\n this.output.put(ev);\n requestId = ev.id;\n if (ttft === BigInt(-1)) {\n ttft = process.hrtime.bigint() - startTime;\n }\n if (ev.usage) {\n usage = ev.usage;\n }\n }\n this.output.close();\n\n const duration = process.hrtime.bigint() - startTime;\n const durationMs = Math.trunc(Number(duration / BigInt(1000000)));\n const metrics: LLMMetrics = {\n type: 'llm_metrics',\n timestamp: Date.now(),\n requestId,\n ttftMs: ttft === BigInt(-1) ? -1 : Math.trunc(Number(ttft / BigInt(1000000))),\n durationMs,\n cancelled: this.abortController.signal.aborted,\n label: this.#llm.label(),\n completionTokens: usage?.completionTokens || 0,\n promptTokens: usage?.promptTokens || 0,\n promptCachedTokens: usage?.promptCachedTokens || 0,\n totalTokens: usage?.totalTokens || 0,\n tokensPerSecond: (() => {\n if (durationMs <= 0) {\n return 0;\n }\n return (usage?.completionTokens || 0) / (durationMs / 1000);\n })(),\n };\n this.#llm.emit('metrics_collected', metrics);\n }\n\n protected abstract run(): Promise<void>;\n\n /** The function context of this stream. */\n get toolCtx(): ToolContext | undefined {\n return this.#toolCtx;\n }\n\n /** The initial chat context of this stream. */\n get chatCtx(): ChatContext {\n return this.#chatCtx;\n }\n\n /** The connection options for this stream. */\n get connOptions(): APIConnectOptions {\n return this._connOptions;\n }\n\n next(): Promise<IteratorResult<ChatChunk>> {\n return this.output.next();\n }\n\n close() {\n this.abortController.abort();\n }\n\n [Symbol.asyncIterator](): LLMStream {\n return this;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/llm/llm.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { EventEmitter } from 'node:events';\nimport { APIConnectionError, APIError } from '../_exceptions.js';\nimport { log } from '../log.js';\nimport type { LLMMetrics } from '../metrics/base.js';\nimport type { APIConnectOptions } from '../types.js';\nimport { AsyncIterableQueue, delay, startSoon, toError } from '../utils.js';\nimport { type ChatContext, type ChatRole, type FunctionCall } from './chat_context.js';\nimport type { ToolChoice, ToolContext } from './tool_context.js';\n\nexport interface ChoiceDelta {\n role: ChatRole;\n content?: string;\n toolCalls?: FunctionCall[];\n}\n\nexport interface CompletionUsage {\n completionTokens: number;\n promptTokens: number;\n promptCachedTokens: number;\n totalTokens: number;\n}\n\nexport interface ChatChunk {\n id: string;\n delta?: ChoiceDelta;\n usage?: CompletionUsage;\n}\n\nexport interface LLMError {\n type: 'llm_error';\n timestamp: number;\n label: string;\n error: Error;\n recoverable: boolean;\n}\n\nexport type LLMCallbacks = {\n ['metrics_collected']: (metrics: LLMMetrics) => void;\n ['error']: (error: LLMError) => void;\n};\n\nexport abstract class LLM extends (EventEmitter as new () => TypedEmitter<LLMCallbacks>) {\n constructor() {\n super();\n }\n\n abstract label(): string;\n\n /**\n * Get the model name/identifier for this LLM instance.\n *\n * @returns The model name if available, \"unknown\" otherwise.\n *\n * @remarks\n * Plugins should override this property to provide their model information.\n */\n get model(): string {\n return 'unknown';\n }\n\n /**\n * Returns a {@link LLMStream} that can be used to push text and receive LLM responses.\n */\n abstract chat({\n chatCtx,\n toolCtx,\n connOptions,\n parallelToolCalls,\n toolChoice,\n extraKwargs,\n }: {\n chatCtx: ChatContext;\n toolCtx?: ToolContext;\n connOptions?: APIConnectOptions;\n parallelToolCalls?: boolean;\n toolChoice?: ToolChoice;\n extraKwargs?: Record<string, unknown>;\n }): LLMStream;\n\n /**\n * Pre-warm connection to the LLM service\n */\n prewarm(): void {\n // Default implementation - subclasses can override\n }\n\n async aclose(): Promise<void> {\n // Default implementation - subclasses can override\n }\n}\n\nexport abstract class LLMStream implements AsyncIterableIterator<ChatChunk> {\n protected output = new AsyncIterableQueue<ChatChunk>();\n protected queue = new AsyncIterableQueue<ChatChunk>();\n protected closed = false;\n protected abortController = new AbortController();\n protected _connOptions: APIConnectOptions;\n protected logger = log();\n\n #llm: LLM;\n #chatCtx: ChatContext;\n #toolCtx?: ToolContext;\n\n constructor(\n llm: LLM,\n {\n chatCtx,\n toolCtx,\n connOptions,\n }: {\n chatCtx: ChatContext;\n toolCtx?: ToolContext;\n connOptions: APIConnectOptions;\n },\n ) {\n this.#llm = llm;\n this.#chatCtx = chatCtx;\n this.#toolCtx = toolCtx;\n this._connOptions = connOptions;\n this.monitorMetrics();\n this.abortController.signal.addEventListener('abort', () => {\n // TODO (AJS-37) clean this up when we refactor with streams\n this.output.close();\n this.closed = true;\n });\n\n // this is a hack to immitate asyncio.create_task so that mainTask\n // is run **after** the constructor has finished. Otherwise we get\n // runtime error when trying to access class variables in the\n // `run` method.\n startSoon(() => this.mainTask().then(() => this.queue.close()));\n }\n\n private async mainTask() {\n // TODO(brian): PR3 - Add span wrapping: tracer.startActiveSpan('llm_request', ..., { endOnExit: false })\n for (let i = 0; i < this._connOptions.maxRetry + 1; i++) {\n try {\n // TODO(brian): PR3 - Add span for retry attempts: tracer.startActiveSpan('llm_request_run', ...)\n return await this.run();\n } catch (error) {\n if (error instanceof APIError) {\n const retryInterval = this._connOptions._intervalForRetry(i);\n\n if (this._connOptions.maxRetry === 0 || !error.retryable) {\n this.emitError({ error, recoverable: false });\n throw error;\n } else if (i === this._connOptions.maxRetry) {\n this.emitError({ error, recoverable: false });\n throw new APIConnectionError({\n message: `failed to generate LLM completion after ${this._connOptions.maxRetry + 1} attempts`,\n options: { retryable: false },\n });\n } else {\n this.emitError({ error, recoverable: true });\n this.logger.warn(\n { llm: this.#llm.label(), attempt: i + 1, error },\n `failed to generate LLM completion, retrying in ${retryInterval}s`,\n );\n }\n\n if (retryInterval > 0) {\n await delay(retryInterval);\n }\n } else {\n this.emitError({ error: toError(error), recoverable: false });\n throw error;\n }\n }\n }\n }\n\n private emitError({ error, recoverable }: { error: Error; recoverable: boolean }) {\n this.#llm.emit('error', {\n type: 'llm_error',\n timestamp: Date.now(),\n label: this.#llm.label(),\n error,\n recoverable,\n });\n }\n\n protected async monitorMetrics() {\n const startTime = process.hrtime.bigint();\n let ttft: bigint = BigInt(-1);\n let requestId = '';\n let usage: CompletionUsage | undefined;\n\n for await (const ev of this.queue) {\n if (this.abortController.signal.aborted) {\n break;\n }\n this.output.put(ev);\n requestId = ev.id;\n if (ttft === BigInt(-1)) {\n ttft = process.hrtime.bigint() - startTime;\n }\n if (ev.usage) {\n usage = ev.usage;\n }\n }\n this.output.close();\n\n const duration = process.hrtime.bigint() - startTime;\n const durationMs = Math.trunc(Number(duration / BigInt(1000000)));\n const metrics: LLMMetrics = {\n type: 'llm_metrics',\n timestamp: Date.now(),\n requestId,\n ttftMs: ttft === BigInt(-1) ? -1 : Math.trunc(Number(ttft / BigInt(1000000))),\n durationMs,\n cancelled: this.abortController.signal.aborted,\n label: this.#llm.label(),\n completionTokens: usage?.completionTokens || 0,\n promptTokens: usage?.promptTokens || 0,\n promptCachedTokens: usage?.promptCachedTokens || 0,\n totalTokens: usage?.totalTokens || 0,\n tokensPerSecond: (() => {\n if (durationMs <= 0) {\n return 0;\n }\n return (usage?.completionTokens || 0) / (durationMs / 1000);\n })(),\n };\n this.#llm.emit('metrics_collected', metrics);\n }\n\n protected abstract run(): Promise<void>;\n\n /** The function context of this stream. */\n get toolCtx(): ToolContext | undefined {\n return this.#toolCtx;\n }\n\n /** The initial chat context of this stream. */\n get chatCtx(): ChatContext {\n return this.#chatCtx;\n }\n\n /** The connection options for this stream. */\n get connOptions(): APIConnectOptions {\n return this._connOptions;\n }\n\n next(): Promise<IteratorResult<ChatChunk>> {\n return this.output.next();\n }\n\n close() {\n this.abortController.abort();\n }\n\n [Symbol.asyncIterator](): LLMStream {\n return this;\n }\n}\n"],"mappings":"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","names":[]}
@@ -672,5 +672,53 @@ import_vitest.vi.mock("../utils.js", () => ({
672
672
  ]);
673
673
  (0, import_vitest.expect)(formatData.systemMessages).toBeNull();
674
674
  });
675
+ (0, import_vitest.it)("should filter out agent handoff items", async () => {
676
+ const ctx = import_chat_context.ChatContext.empty();
677
+ ctx.addMessage({ role: "user", content: "Hello" });
678
+ const handoff = new import_chat_context.AgentHandoffItem({
679
+ oldAgentId: "agent_1",
680
+ newAgentId: "agent_2"
681
+ });
682
+ ctx.insert(handoff);
683
+ ctx.addMessage({ role: "assistant", content: "Hi there!" });
684
+ const [result, formatData] = await (0, import_google.toChatCtx)(ctx, false);
685
+ (0, import_vitest.expect)(result).toEqual([
686
+ {
687
+ role: "user",
688
+ parts: [{ text: "Hello" }]
689
+ },
690
+ {
691
+ role: "model",
692
+ parts: [{ text: "Hi there!" }]
693
+ }
694
+ ]);
695
+ (0, import_vitest.expect)(formatData.systemMessages).toBeNull();
696
+ });
697
+ (0, import_vitest.it)("should handle multiple agent handoffs without errors", async () => {
698
+ const ctx = import_chat_context.ChatContext.empty();
699
+ ctx.addMessage({ role: "user", content: "Start" });
700
+ ctx.insert(new import_chat_context.AgentHandoffItem({ oldAgentId: void 0, newAgentId: "agent_1" }));
701
+ ctx.addMessage({ role: "assistant", content: "Response from agent 1" });
702
+ ctx.insert(new import_chat_context.AgentHandoffItem({ oldAgentId: "agent_1", newAgentId: "agent_2" }));
703
+ ctx.addMessage({ role: "assistant", content: "Response from agent 2" });
704
+ ctx.insert(new import_chat_context.AgentHandoffItem({ oldAgentId: "agent_2", newAgentId: "agent_3" }));
705
+ ctx.addMessage({ role: "assistant", content: "Response from agent 3" });
706
+ const [result, formatData] = await (0, import_google.toChatCtx)(ctx, false);
707
+ (0, import_vitest.expect)(result).toEqual([
708
+ {
709
+ role: "user",
710
+ parts: [{ text: "Start" }]
711
+ },
712
+ {
713
+ role: "model",
714
+ parts: [
715
+ { text: "Response from agent 1" },
716
+ { text: "Response from agent 2" },
717
+ { text: "Response from agent 3" }
718
+ ]
719
+ }
720
+ ]);
721
+ (0, import_vitest.expect)(formatData.systemMessages).toBeNull();
722
+ });
675
723
  });
676
724
  //# sourceMappingURL=google.test.cjs.map