@livekit/agents 1.0.34 → 1.0.36-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +3 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/inference/api_protos.d.cts +4 -4
- package/dist/inference/api_protos.d.ts +4 -4
- package/dist/inference/interruption/AdaptiveInterruptionDetector.cjs +152 -0
- package/dist/inference/interruption/AdaptiveInterruptionDetector.cjs.map +1 -0
- package/dist/inference/interruption/AdaptiveInterruptionDetector.d.cts +50 -0
- package/dist/inference/interruption/AdaptiveInterruptionDetector.d.ts +50 -0
- package/dist/inference/interruption/AdaptiveInterruptionDetector.d.ts.map +1 -0
- package/dist/inference/interruption/AdaptiveInterruptionDetector.js +125 -0
- package/dist/inference/interruption/AdaptiveInterruptionDetector.js.map +1 -0
- package/dist/inference/interruption/InterruptionStream.cjs +310 -0
- package/dist/inference/interruption/InterruptionStream.cjs.map +1 -0
- package/dist/inference/interruption/InterruptionStream.d.cts +57 -0
- package/dist/inference/interruption/InterruptionStream.d.ts +57 -0
- package/dist/inference/interruption/InterruptionStream.d.ts.map +1 -0
- package/dist/inference/interruption/InterruptionStream.js +288 -0
- package/dist/inference/interruption/InterruptionStream.js.map +1 -0
- package/dist/inference/interruption/defaults.cjs +76 -0
- package/dist/inference/interruption/defaults.cjs.map +1 -0
- package/dist/inference/interruption/defaults.d.cts +14 -0
- package/dist/inference/interruption/defaults.d.ts +14 -0
- package/dist/inference/interruption/defaults.d.ts.map +1 -0
- package/dist/inference/interruption/defaults.js +42 -0
- package/dist/inference/interruption/defaults.js.map +1 -0
- package/dist/inference/interruption/errors.cjs +2 -0
- package/dist/inference/interruption/errors.cjs.map +1 -0
- package/dist/inference/interruption/errors.d.cts +2 -0
- package/dist/inference/interruption/errors.d.ts +2 -0
- package/dist/inference/interruption/errors.d.ts.map +1 -0
- package/dist/inference/interruption/errors.js +1 -0
- package/dist/inference/interruption/errors.js.map +1 -0
- package/dist/inference/interruption/http_transport.cjs +57 -0
- package/dist/inference/interruption/http_transport.cjs.map +1 -0
- package/dist/inference/interruption/http_transport.d.cts +23 -0
- package/dist/inference/interruption/http_transport.d.ts +23 -0
- package/dist/inference/interruption/http_transport.d.ts.map +1 -0
- package/dist/inference/interruption/http_transport.js +33 -0
- package/dist/inference/interruption/http_transport.js.map +1 -0
- package/dist/inference/interruption/index.cjs +34 -0
- package/dist/inference/interruption/index.cjs.map +1 -0
- package/dist/inference/interruption/index.d.cts +5 -0
- package/dist/inference/interruption/index.d.ts +5 -0
- package/dist/inference/interruption/index.d.ts.map +1 -0
- package/dist/inference/interruption/index.js +7 -0
- package/dist/inference/interruption/index.js.map +1 -0
- package/dist/inference/interruption/interruption.cjs +85 -0
- package/dist/inference/interruption/interruption.cjs.map +1 -0
- package/dist/inference/interruption/interruption.d.cts +48 -0
- package/dist/inference/interruption/interruption.d.ts +48 -0
- package/dist/inference/interruption/interruption.d.ts.map +1 -0
- package/dist/inference/interruption/interruption.js +59 -0
- package/dist/inference/interruption/interruption.js.map +1 -0
- package/dist/inference/llm.cjs +30 -3
- package/dist/inference/llm.cjs.map +1 -1
- package/dist/inference/llm.d.cts +3 -1
- package/dist/inference/llm.d.ts +3 -1
- package/dist/inference/llm.d.ts.map +1 -1
- package/dist/inference/llm.js +30 -3
- package/dist/inference/llm.js.map +1 -1
- package/dist/inference/utils.cjs +15 -2
- package/dist/inference/utils.cjs.map +1 -1
- package/dist/inference/utils.d.cts +1 -0
- package/dist/inference/utils.d.ts +1 -0
- package/dist/inference/utils.d.ts.map +1 -1
- package/dist/inference/utils.js +13 -1
- package/dist/inference/utils.js.map +1 -1
- package/dist/inference/utils.test.cjs +20 -0
- package/dist/inference/utils.test.cjs.map +1 -0
- package/dist/inference/utils.test.js +19 -0
- package/dist/inference/utils.test.js.map +1 -0
- package/dist/ipc/inference_proc_executor.cjs.map +1 -1
- package/dist/ipc/job_proc_executor.cjs.map +1 -1
- package/dist/ipc/job_proc_lazy_main.cjs +1 -1
- package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
- package/dist/ipc/job_proc_lazy_main.js +1 -1
- package/dist/ipc/job_proc_lazy_main.js.map +1 -1
- package/dist/llm/chat_context.cjs +20 -2
- package/dist/llm/chat_context.cjs.map +1 -1
- package/dist/llm/chat_context.d.cts +9 -0
- package/dist/llm/chat_context.d.ts +9 -0
- package/dist/llm/chat_context.d.ts.map +1 -1
- package/dist/llm/chat_context.js +20 -2
- package/dist/llm/chat_context.js.map +1 -1
- package/dist/llm/llm.cjs.map +1 -1
- package/dist/llm/llm.d.cts +1 -0
- package/dist/llm/llm.d.ts +1 -0
- package/dist/llm/llm.d.ts.map +1 -1
- package/dist/llm/llm.js.map +1 -1
- package/dist/llm/provider_format/openai.cjs +43 -20
- package/dist/llm/provider_format/openai.cjs.map +1 -1
- package/dist/llm/provider_format/openai.d.ts.map +1 -1
- package/dist/llm/provider_format/openai.js +43 -20
- package/dist/llm/provider_format/openai.js.map +1 -1
- package/dist/llm/provider_format/openai.test.cjs +35 -0
- package/dist/llm/provider_format/openai.test.cjs.map +1 -1
- package/dist/llm/provider_format/openai.test.js +35 -0
- package/dist/llm/provider_format/openai.test.js.map +1 -1
- package/dist/llm/provider_format/utils.cjs +1 -1
- package/dist/llm/provider_format/utils.cjs.map +1 -1
- package/dist/llm/provider_format/utils.d.ts.map +1 -1
- package/dist/llm/provider_format/utils.js +1 -1
- package/dist/llm/provider_format/utils.js.map +1 -1
- package/dist/stream/stream_channel.cjs +3 -0
- package/dist/stream/stream_channel.cjs.map +1 -1
- package/dist/stream/stream_channel.d.cts +3 -2
- package/dist/stream/stream_channel.d.ts +3 -2
- package/dist/stream/stream_channel.d.ts.map +1 -1
- package/dist/stream/stream_channel.js +3 -0
- package/dist/stream/stream_channel.js.map +1 -1
- package/dist/telemetry/trace_types.cjs +15 -0
- package/dist/telemetry/trace_types.cjs.map +1 -1
- package/dist/telemetry/trace_types.d.cts +5 -0
- package/dist/telemetry/trace_types.d.ts +5 -0
- package/dist/telemetry/trace_types.d.ts.map +1 -1
- package/dist/telemetry/trace_types.js +10 -0
- package/dist/telemetry/trace_types.js.map +1 -1
- package/dist/utils/ws_transport.cjs +51 -0
- package/dist/utils/ws_transport.cjs.map +1 -0
- package/dist/utils/ws_transport.d.cts +9 -0
- package/dist/utils/ws_transport.d.ts +9 -0
- package/dist/utils/ws_transport.d.ts.map +1 -0
- package/dist/utils/ws_transport.js +17 -0
- package/dist/utils/ws_transport.js.map +1 -0
- package/dist/utils/ws_transport.test.cjs +212 -0
- package/dist/utils/ws_transport.test.cjs.map +1 -0
- package/dist/utils/ws_transport.test.js +211 -0
- package/dist/utils/ws_transport.test.js.map +1 -0
- package/dist/voice/agent_activity.cjs +49 -0
- package/dist/voice/agent_activity.cjs.map +1 -1
- package/dist/voice/agent_activity.d.cts +14 -0
- package/dist/voice/agent_activity.d.ts +14 -0
- package/dist/voice/agent_activity.d.ts.map +1 -1
- package/dist/voice/agent_activity.js +49 -0
- package/dist/voice/agent_activity.js.map +1 -1
- package/dist/voice/agent_session.cjs +12 -1
- package/dist/voice/agent_session.cjs.map +1 -1
- package/dist/voice/agent_session.d.cts +3 -0
- package/dist/voice/agent_session.d.ts +3 -0
- package/dist/voice/agent_session.d.ts.map +1 -1
- package/dist/voice/agent_session.js +12 -1
- package/dist/voice/agent_session.js.map +1 -1
- package/dist/voice/audio_recognition.cjs +124 -2
- package/dist/voice/audio_recognition.cjs.map +1 -1
- package/dist/voice/audio_recognition.d.cts +32 -1
- package/dist/voice/audio_recognition.d.ts +32 -1
- package/dist/voice/audio_recognition.d.ts.map +1 -1
- package/dist/voice/audio_recognition.js +127 -2
- package/dist/voice/audio_recognition.js.map +1 -1
- package/dist/voice/background_audio.cjs.map +1 -1
- package/dist/voice/generation.cjs +2 -1
- package/dist/voice/generation.cjs.map +1 -1
- package/dist/voice/generation.d.ts.map +1 -1
- package/dist/voice/generation.js +2 -1
- package/dist/voice/generation.js.map +1 -1
- package/package.json +2 -1
- package/src/index.ts +2 -0
- package/src/inference/interruption/AdaptiveInterruptionDetector.ts +166 -0
- package/src/inference/interruption/InterruptionStream.ts +397 -0
- package/src/inference/interruption/defaults.ts +33 -0
- package/src/inference/interruption/errors.ts +0 -0
- package/src/inference/interruption/http_transport.ts +61 -0
- package/src/inference/interruption/index.ts +4 -0
- package/src/inference/interruption/interruption.ts +88 -0
- package/src/inference/llm.ts +42 -3
- package/src/inference/utils.test.ts +31 -0
- package/src/inference/utils.ts +15 -0
- package/src/ipc/job_proc_lazy_main.ts +1 -1
- package/src/llm/chat_context.ts +32 -2
- package/src/llm/llm.ts +1 -0
- package/src/llm/provider_format/openai.test.ts +40 -0
- package/src/llm/provider_format/openai.ts +46 -19
- package/src/llm/provider_format/utils.ts +5 -1
- package/src/stream/stream_channel.ts +6 -2
- package/src/telemetry/trace_types.ts +7 -0
- package/src/utils/ws_transport.test.ts +282 -0
- package/src/utils/ws_transport.ts +22 -0
- package/src/voice/agent_activity.ts +61 -0
- package/src/voice/agent_session.ts +22 -2
- package/src/voice/audio_recognition.ts +161 -1
- package/src/voice/generation.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/llm/provider_format/openai.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { VideoBufferType, VideoFrame } from '@livekit/rtc-node';\nimport { beforeEach, describe, expect, it, vi } from 'vitest';\nimport { initializeLogger } from '../../log.js';\nimport {\n AgentHandoffItem,\n ChatContext,\n FunctionCall,\n FunctionCallOutput,\n} from '../chat_context.js';\nimport { serializeImage } from '../utils.js';\nimport { toChatCtx } from './openai.js';\n\n// Mock the serializeImage function\nvi.mock('../utils.js', () => ({\n serializeImage: vi.fn(),\n}));\n\ndescribe('toChatCtx', () => {\n const serializeImageMock = vi.mocked(serializeImage);\n\n // initialize logger at start of test\n initializeLogger({ level: 'silent', pretty: false });\n\n beforeEach(async () => {\n vi.clearAllMocks();\n });\n\n it('should convert simple text messages', async () => {\n const ctx = ChatContext.empty();\n ctx.addMessage({ role: 'user', content: 'Hello' });\n ctx.addMessage({ role: 'assistant', content: 'Hi there!' });\n\n const result = await toChatCtx(ctx);\n\n // Messages should be in the result, order may vary due to ID-based sorting\n expect(result).toHaveLength(2);\n expect(result[0]).toEqual({ role: 'user', content: 'Hello' });\n expect(result[1]).toEqual({ role: 'assistant', content: 'Hi there!' });\n });\n\n it('should handle system messages', async () => {\n const ctx = ChatContext.empty();\n ctx.addMessage({ role: 'system', content: 'You are a helpful assistant' });\n ctx.addMessage({ role: 'user', content: 'Hello' });\n\n const result = await toChatCtx(ctx);\n\n // Messages should be in the result, order may vary due to ID-based sorting\n expect(result).toHaveLength(2);\n expect(result[0]).toEqual({ role: 'system', content: 'You are a helpful assistant' });\n expect(result[1]).toEqual({ role: 'user', content: 'Hello' });\n });\n\n it('should handle multi-line text content', async () => {\n const ctx = ChatContext.empty();\n ctx.addMessage({ role: 'user', content: ['Line 1', 'Line 2', 'Line 3'] });\n\n const result = await toChatCtx(ctx);\n\n expect(result).toHaveLength(1);\n expect(result[0]).toEqual({ role: 'user', content: 'Line 1\\nLine 2\\nLine 3' });\n });\n\n it('should handle messages with external URL images', async () => {\n serializeImageMock.mockResolvedValue({\n inferenceDetail: 'high',\n externalUrl: 'https://example.com/image.jpg',\n });\n\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'user',\n content: [\n 'Check out this image:',\n {\n id: 'img1',\n type: 'image_content',\n image: 'https://example.com/image.jpg',\n inferenceDetail: 'high',\n _cache: {},\n },\n ],\n });\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: 'https://example.com/image.jpg',\n detail: 'high',\n },\n },\n { type: 'text', text: 'Check out this image:' },\n ],\n },\n ]);\n });\n\n it('should handle messages with base64 images', async () => {\n serializeImageMock.mockResolvedValue({\n inferenceDetail: 'auto',\n mimeType: 'image/png',\n base64Data: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB',\n });\n\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'assistant',\n content: [\n {\n id: 'img1',\n type: 'image_content',\n image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB',\n inferenceDetail: 'auto',\n _cache: {},\n },\n 'Here is the image you requested',\n ],\n });\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'assistant',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB',\n detail: 'auto',\n },\n },\n { type: 'text', text: 'Here is the image you requested' },\n ],\n },\n ]);\n });\n\n it('should handle VideoFrame images', async () => {\n serializeImageMock.mockResolvedValue({\n inferenceDetail: 'low',\n mimeType: 'image/jpeg',\n base64Data: '/9j/4AAQSkZJRg==',\n });\n\n const frameData = new Uint8Array(4 * 4 * 4); // 4x4 RGBA\n const videoFrame = new VideoFrame(frameData, 4, 4, VideoBufferType.RGBA);\n\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'user',\n content: [\n {\n id: 'frame1',\n type: 'image_content',\n image: videoFrame,\n inferenceDetail: 'low',\n _cache: {},\n },\n ],\n });\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: 'data:image/jpeg;base64,/9j/4AAQSkZJRg==',\n detail: 'low',\n },\n },\n ],\n },\n ]);\n });\n\n it('should cache serialized images', async () => {\n serializeImageMock.mockResolvedValue({\n inferenceDetail: 'high',\n mimeType: 'image/png',\n base64Data: 'cached-data',\n });\n\n const imageContent = {\n id: 'img1',\n type: 'image_content' as const,\n image: 'https://example.com/image.jpg',\n inferenceDetail: 'high' as const,\n _cache: {},\n };\n\n const ctx = ChatContext.empty();\n ctx.addMessage({ role: 'user', content: [imageContent] });\n\n // Call twice to test caching\n await toChatCtx(ctx);\n await toChatCtx(ctx);\n\n // serializeImage should only be called once due to caching\n expect(serializeImageMock).toHaveBeenCalledTimes(1);\n expect(imageContent._cache).toHaveProperty('serialized_image');\n });\n\n it('should handle tool calls and outputs', async () => {\n const ctx = ChatContext.empty();\n\n // Add an assistant message with tool calls\n const msg = ctx.addMessage({ role: 'assistant', content: 'Let me help you with that.' });\n const toolCall = FunctionCall.create({\n id: msg.id + '/tool_1',\n callId: 'call_123',\n name: 'get_weather',\n args: '{\"location\": \"San Francisco\"}',\n });\n const toolOutput = FunctionCallOutput.create({\n callId: 'call_123',\n output: '{\"temperature\": 72, \"condition\": \"sunny\"}',\n isError: false,\n });\n\n ctx.insert([toolCall, toolOutput]);\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'assistant',\n content: 'Let me help you with that.',\n tool_calls: [\n {\n type: 'function',\n id: 'call_123',\n function: {\n name: 'get_weather',\n arguments: '{\"location\": \"San Francisco\"}',\n },\n },\n ],\n },\n {\n role: 'tool',\n tool_call_id: 'call_123',\n content: '{\"temperature\": 72, \"condition\": \"sunny\"}',\n },\n ]);\n });\n\n it('should handle multiple tool calls in one message', async () => {\n const ctx = ChatContext.empty();\n\n const msg = ctx.addMessage({ role: 'assistant', content: \"I'll check both locations.\" });\n const toolCall1 = new FunctionCall({\n id: msg.id + '/tool_1',\n callId: 'call_1',\n name: 'get_weather',\n args: '{\"location\": \"NYC\"}',\n });\n const toolCall2 = new FunctionCall({\n id: msg.id + '/tool_2',\n callId: 'call_2',\n name: 'get_weather',\n args: '{\"location\": \"LA\"}',\n });\n const toolOutput1 = new FunctionCallOutput({\n callId: 'call_1',\n output: '{\"temperature\": 65}',\n isError: false,\n });\n const toolOutput2 = new FunctionCallOutput({\n callId: 'call_2',\n output: '{\"temperature\": 78}',\n isError: false,\n });\n\n ctx.insert([toolCall1, toolCall2, toolOutput1, toolOutput2]);\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'assistant',\n content: \"I'll check both locations.\",\n tool_calls: [\n {\n type: 'function',\n id: 'call_1',\n function: { name: 'get_weather', arguments: '{\"location\": \"NYC\"}' },\n },\n {\n type: 'function',\n id: 'call_2',\n function: { name: 'get_weather', arguments: '{\"location\": \"LA\"}' },\n },\n ],\n },\n {\n role: 'tool',\n tool_call_id: 'call_1',\n content: '{\"temperature\": 65}',\n },\n {\n role: 'tool',\n tool_call_id: 'call_2',\n content: '{\"temperature\": 78}',\n },\n ]);\n });\n\n it('should handle tool calls without accompanying message', async () => {\n const ctx = ChatContext.empty();\n\n const toolCall = new FunctionCall({\n id: 'func_123',\n callId: 'call_456',\n name: 'calculate',\n args: '{\"a\": 5, \"b\": 3}',\n });\n const toolOutput = new FunctionCallOutput({\n callId: 'call_456',\n output: '{\"result\": 8}',\n isError: false,\n });\n\n ctx.insert([toolCall, toolOutput]);\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'assistant',\n tool_calls: [\n {\n type: 'function',\n id: 'call_456',\n function: { name: 'calculate', arguments: '{\"a\": 5, \"b\": 3}' },\n },\n ],\n },\n {\n role: 'tool',\n tool_call_id: 'call_456',\n content: '{\"result\": 8}',\n },\n ]);\n });\n\n it('should skip empty groups', async () => {\n const ctx = ChatContext.empty();\n ctx.addMessage({ role: 'user', content: 'Hello', createdAt: 1000 });\n\n // Create an isolated tool output without corresponding call (will be filtered)\n const orphanOutput = new FunctionCallOutput({\n callId: 'orphan_call',\n output: 'This should be ignored',\n isError: false,\n createdAt: 2000,\n });\n ctx.insert(orphanOutput);\n\n ctx.addMessage({ role: 'assistant', content: 'Hi!', createdAt: 3000 });\n\n const result = await toChatCtx(ctx);\n\n // Messages should be in the result, orphan output should be filtered out\n expect(result).toHaveLength(2);\n expect(result).toContainEqual({ role: 'user', content: 'Hello' });\n expect(result).toContainEqual({ role: 'assistant', content: 'Hi!' });\n });\n\n it('should handle mixed content with text and multiple images', async () => {\n serializeImageMock\n .mockResolvedValueOnce({\n inferenceDetail: 'high',\n externalUrl: 'https://example.com/image1.jpg',\n })\n .mockResolvedValueOnce({\n inferenceDetail: 'low',\n mimeType: 'image/png',\n base64Data: 'base64data',\n });\n\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'user',\n content: [\n 'Here are two images:',\n {\n id: 'img1',\n type: 'image_content',\n image: 'https://example.com/image1.jpg',\n inferenceDetail: 'high',\n _cache: {},\n },\n 'And the second one:',\n {\n id: 'img2',\n type: 'image_content',\n image: 'data:image/png;base64,base64data',\n inferenceDetail: 'low',\n _cache: {},\n },\n 'What do you think?',\n ],\n });\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: 'https://example.com/image1.jpg',\n detail: 'high',\n },\n },\n {\n type: 'image_url',\n image_url: {\n url: 'data:image/png;base64,base64data',\n detail: 'low',\n },\n },\n {\n type: 'text',\n text: 'Here are two images:\\nAnd the second one:\\nWhat do you think?',\n },\n ],\n },\n ]);\n });\n\n it('should handle content with only images and no text', async () => {\n serializeImageMock.mockResolvedValue({\n inferenceDetail: 'auto',\n externalUrl: 'https://example.com/image.jpg',\n });\n\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'user',\n content: [\n {\n id: 'img1',\n type: 'image_content',\n image: 'https://example.com/image.jpg',\n inferenceDetail: 'auto',\n _cache: {},\n },\n ],\n });\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: 'https://example.com/image.jpg',\n detail: 'auto',\n },\n },\n ],\n },\n ]);\n });\n\n it('should throw error for unsupported content type', async () => {\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'user',\n content: [\n {\n type: 'audio_content',\n frame: [],\n },\n ],\n });\n\n await expect(toChatCtx(ctx)).rejects.toThrow('Unsupported content type: audio_content');\n });\n\n it('should throw error when serialized image has no data', async () => {\n serializeImageMock.mockResolvedValue({\n inferenceDetail: 'high',\n // No base64Data or externalUrl\n });\n\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'user',\n content: [\n {\n id: 'img1',\n type: 'image_content',\n image: 'invalid-image',\n inferenceDetail: 'high',\n _cache: {},\n },\n ],\n });\n\n await expect(toChatCtx(ctx)).rejects.toThrow('Serialized image has no data bytes');\n });\n\n it('should filter out standalone function calls without outputs', async () => {\n const ctx = ChatContext.empty();\n\n // Add standalone function call without output\n const funcCall = new FunctionCall({\n id: 'func_standalone',\n callId: 'call_999',\n name: 'standalone_function',\n args: '{}',\n });\n\n ctx.insert(funcCall);\n\n const result = await toChatCtx(ctx);\n\n // Standalone function calls without outputs are filtered out by groupToolCalls\n expect(result).toEqual([]);\n });\n\n it('should handle function call output correctly', async () => {\n const ctx = ChatContext.empty();\n\n // First add a function call\n const funcCall = new FunctionCall({\n id: 'func_1',\n callId: 'call_output_test',\n name: 'test_function',\n args: '{}',\n });\n\n // Then add its output\n const funcOutput = new FunctionCallOutput({\n callId: 'call_output_test',\n output: 'Function executed successfully',\n isError: false,\n });\n\n ctx.insert([funcCall, funcOutput]);\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'assistant',\n tool_calls: [\n {\n id: 'call_output_test',\n type: 'function',\n function: {\n name: 'test_function',\n arguments: '{}',\n },\n },\n ],\n },\n {\n role: 'tool',\n tool_call_id: 'call_output_test',\n content: 'Function executed successfully',\n },\n ]);\n });\n\n it('should filter out agent handoff items', async () => {\n const ctx = ChatContext.empty();\n\n ctx.addMessage({ role: 'user', content: 'Hello' });\n\n // Insert an agent handoff item\n const handoff = new AgentHandoffItem({\n oldAgentId: 'agent_1',\n newAgentId: 'agent_2',\n });\n ctx.insert(handoff);\n\n ctx.addMessage({ role: 'assistant', content: 'Hi there!' });\n\n const result = await toChatCtx(ctx);\n\n // Agent handoff should be filtered out, only messages should remain\n expect(result).toEqual([\n { role: 'user', content: 'Hello' },\n { role: 'assistant', content: 'Hi there!' },\n ]);\n });\n\n it('should handle multiple agent handoffs without errors', async () => {\n const ctx = ChatContext.empty();\n\n ctx.addMessage({ role: 'user', content: 'Start' });\n\n // Multiple handoffs\n ctx.insert(new AgentHandoffItem({ oldAgentId: undefined, newAgentId: 'agent_1' }));\n ctx.addMessage({ role: 'assistant', content: 'Response from agent 1' });\n\n ctx.insert(new AgentHandoffItem({ oldAgentId: 'agent_1', newAgentId: 'agent_2' }));\n ctx.addMessage({ role: 'assistant', content: 'Response from agent 2' });\n\n ctx.insert(new AgentHandoffItem({ oldAgentId: 'agent_2', newAgentId: 'agent_3' }));\n ctx.addMessage({ role: 'assistant', content: 'Response from agent 3' });\n\n const result = await toChatCtx(ctx);\n\n // All handoffs should be filtered out\n expect(result).toEqual([\n { role: 'user', content: 'Start' },\n { role: 'assistant', content: 'Response from agent 1' },\n { role: 'assistant', content: 'Response from agent 2' },\n { role: 'assistant', content: 'Response from agent 3' },\n ]);\n });\n});\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/llm/provider_format/openai.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { VideoBufferType, VideoFrame } from '@livekit/rtc-node';\nimport { beforeEach, describe, expect, it, vi } from 'vitest';\nimport { initializeLogger } from '../../log.js';\nimport {\n AgentHandoffItem,\n ChatContext,\n FunctionCall,\n FunctionCallOutput,\n} from '../chat_context.js';\nimport { serializeImage } from '../utils.js';\nimport { toChatCtx } from './openai.js';\n\n// Mock the serializeImage function\nvi.mock('../utils.js', () => ({\n serializeImage: vi.fn(),\n}));\n\ndescribe('toChatCtx', () => {\n const serializeImageMock = vi.mocked(serializeImage);\n\n // initialize logger at start of test\n initializeLogger({ level: 'silent', pretty: false });\n\n beforeEach(async () => {\n vi.clearAllMocks();\n });\n\n it('should convert simple text messages', async () => {\n const ctx = ChatContext.empty();\n ctx.addMessage({ role: 'user', content: 'Hello' });\n ctx.addMessage({ role: 'assistant', content: 'Hi there!' });\n\n const result = await toChatCtx(ctx);\n\n // Messages should be in the result, order may vary due to ID-based sorting\n expect(result).toHaveLength(2);\n expect(result[0]).toEqual({ role: 'user', content: 'Hello' });\n expect(result[1]).toEqual({ role: 'assistant', content: 'Hi there!' });\n });\n\n it('should handle system messages', async () => {\n const ctx = ChatContext.empty();\n ctx.addMessage({ role: 'system', content: 'You are a helpful assistant' });\n ctx.addMessage({ role: 'user', content: 'Hello' });\n\n const result = await toChatCtx(ctx);\n\n // Messages should be in the result, order may vary due to ID-based sorting\n expect(result).toHaveLength(2);\n expect(result[0]).toEqual({ role: 'system', content: 'You are a helpful assistant' });\n expect(result[1]).toEqual({ role: 'user', content: 'Hello' });\n });\n\n it('should handle multi-line text content', async () => {\n const ctx = ChatContext.empty();\n ctx.addMessage({ role: 'user', content: ['Line 1', 'Line 2', 'Line 3'] });\n\n const result = await toChatCtx(ctx);\n\n expect(result).toHaveLength(1);\n expect(result[0]).toEqual({ role: 'user', content: 'Line 1\\nLine 2\\nLine 3' });\n });\n\n it('should handle messages with external URL images', async () => {\n serializeImageMock.mockResolvedValue({\n inferenceDetail: 'high',\n externalUrl: 'https://example.com/image.jpg',\n });\n\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'user',\n content: [\n 'Check out this image:',\n {\n id: 'img1',\n type: 'image_content',\n image: 'https://example.com/image.jpg',\n inferenceDetail: 'high',\n _cache: {},\n },\n ],\n });\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: 'https://example.com/image.jpg',\n detail: 'high',\n },\n },\n { type: 'text', text: 'Check out this image:' },\n ],\n },\n ]);\n });\n\n it('should handle messages with base64 images', async () => {\n serializeImageMock.mockResolvedValue({\n inferenceDetail: 'auto',\n mimeType: 'image/png',\n base64Data: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB',\n });\n\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'assistant',\n content: [\n {\n id: 'img1',\n type: 'image_content',\n image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB',\n inferenceDetail: 'auto',\n _cache: {},\n },\n 'Here is the image you requested',\n ],\n });\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'assistant',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB',\n detail: 'auto',\n },\n },\n { type: 'text', text: 'Here is the image you requested' },\n ],\n },\n ]);\n });\n\n it('should handle VideoFrame images', async () => {\n serializeImageMock.mockResolvedValue({\n inferenceDetail: 'low',\n mimeType: 'image/jpeg',\n base64Data: '/9j/4AAQSkZJRg==',\n });\n\n const frameData = new Uint8Array(4 * 4 * 4); // 4x4 RGBA\n const videoFrame = new VideoFrame(frameData, 4, 4, VideoBufferType.RGBA);\n\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'user',\n content: [\n {\n id: 'frame1',\n type: 'image_content',\n image: videoFrame,\n inferenceDetail: 'low',\n _cache: {},\n },\n ],\n });\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: 'data:image/jpeg;base64,/9j/4AAQSkZJRg==',\n detail: 'low',\n },\n },\n ],\n },\n ]);\n });\n\n it('should cache serialized images', async () => {\n serializeImageMock.mockResolvedValue({\n inferenceDetail: 'high',\n mimeType: 'image/png',\n base64Data: 'cached-data',\n });\n\n const imageContent = {\n id: 'img1',\n type: 'image_content' as const,\n image: 'https://example.com/image.jpg',\n inferenceDetail: 'high' as const,\n _cache: {},\n };\n\n const ctx = ChatContext.empty();\n ctx.addMessage({ role: 'user', content: [imageContent] });\n\n // Call twice to test caching\n await toChatCtx(ctx);\n await toChatCtx(ctx);\n\n // serializeImage should only be called once due to caching\n expect(serializeImageMock).toHaveBeenCalledTimes(1);\n expect(imageContent._cache).toHaveProperty('serialized_image');\n });\n\n it('should handle tool calls and outputs', async () => {\n const ctx = ChatContext.empty();\n\n // Add an assistant message with tool calls\n const msg = ctx.addMessage({ role: 'assistant', content: 'Let me help you with that.' });\n const toolCall = FunctionCall.create({\n id: msg.id + '/tool_1',\n callId: 'call_123',\n name: 'get_weather',\n args: '{\"location\": \"San Francisco\"}',\n });\n const toolOutput = FunctionCallOutput.create({\n callId: 'call_123',\n output: '{\"temperature\": 72, \"condition\": \"sunny\"}',\n isError: false,\n });\n\n ctx.insert([toolCall, toolOutput]);\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'assistant',\n content: 'Let me help you with that.',\n tool_calls: [\n {\n type: 'function',\n id: 'call_123',\n function: {\n name: 'get_weather',\n arguments: '{\"location\": \"San Francisco\"}',\n },\n },\n ],\n },\n {\n role: 'tool',\n tool_call_id: 'call_123',\n content: '{\"temperature\": 72, \"condition\": \"sunny\"}',\n },\n ]);\n });\n\n it('should include provider-specific extra content on tool calls', async () => {\n const ctx = ChatContext.empty();\n const msg = ctx.addMessage({ role: 'assistant', content: 'Running tool' });\n\n const toolCall = FunctionCall.create({\n id: `${msg.id}/tool_1`,\n callId: 'call_789',\n name: 'google_call',\n args: '{}',\n extra: { google: { thoughtSignature: 'sig-123' } },\n });\n const toolOutput = FunctionCallOutput.create({\n callId: 'call_789',\n output: '{\"result\": \"ok\"}',\n isError: false,\n });\n\n ctx.insert([toolCall, toolOutput]);\n\n const result = await toChatCtx(ctx);\n\n expect(result[0]).toEqual({\n role: 'assistant',\n content: 'Running tool',\n tool_calls: [\n {\n type: 'function',\n id: 'call_789',\n function: { name: 'google_call', arguments: '{}' },\n extra_content: { google: { thoughtSignature: 'sig-123' } },\n },\n ],\n });\n expect(result[1]).toEqual({\n role: 'tool',\n tool_call_id: 'call_789',\n content: '{\"result\": \"ok\"}',\n });\n });\n\n it('should handle multiple tool calls in one message', async () => {\n const ctx = ChatContext.empty();\n\n const msg = ctx.addMessage({ role: 'assistant', content: \"I'll check both locations.\" });\n const toolCall1 = new FunctionCall({\n id: msg.id + '/tool_1',\n callId: 'call_1',\n name: 'get_weather',\n args: '{\"location\": \"NYC\"}',\n });\n const toolCall2 = new FunctionCall({\n id: msg.id + '/tool_2',\n callId: 'call_2',\n name: 'get_weather',\n args: '{\"location\": \"LA\"}',\n });\n const toolOutput1 = new FunctionCallOutput({\n callId: 'call_1',\n output: '{\"temperature\": 65}',\n isError: false,\n });\n const toolOutput2 = new FunctionCallOutput({\n callId: 'call_2',\n output: '{\"temperature\": 78}',\n isError: false,\n });\n\n ctx.insert([toolCall1, toolCall2, toolOutput1, toolOutput2]);\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'assistant',\n content: \"I'll check both locations.\",\n tool_calls: [\n {\n type: 'function',\n id: 'call_1',\n function: { name: 'get_weather', arguments: '{\"location\": \"NYC\"}' },\n },\n {\n type: 'function',\n id: 'call_2',\n function: { name: 'get_weather', arguments: '{\"location\": \"LA\"}' },\n },\n ],\n },\n {\n role: 'tool',\n tool_call_id: 'call_1',\n content: '{\"temperature\": 65}',\n },\n {\n role: 'tool',\n tool_call_id: 'call_2',\n content: '{\"temperature\": 78}',\n },\n ]);\n });\n\n it('should handle tool calls without accompanying message', async () => {\n const ctx = ChatContext.empty();\n\n const toolCall = new FunctionCall({\n id: 'func_123',\n callId: 'call_456',\n name: 'calculate',\n args: '{\"a\": 5, \"b\": 3}',\n });\n const toolOutput = new FunctionCallOutput({\n callId: 'call_456',\n output: '{\"result\": 8}',\n isError: false,\n });\n\n ctx.insert([toolCall, toolOutput]);\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'assistant',\n tool_calls: [\n {\n type: 'function',\n id: 'call_456',\n function: { name: 'calculate', arguments: '{\"a\": 5, \"b\": 3}' },\n },\n ],\n },\n {\n role: 'tool',\n tool_call_id: 'call_456',\n content: '{\"result\": 8}',\n },\n ]);\n });\n\n it('should skip empty groups', async () => {\n const ctx = ChatContext.empty();\n ctx.addMessage({ role: 'user', content: 'Hello', createdAt: 1000 });\n\n // Create an isolated tool output without corresponding call (will be filtered)\n const orphanOutput = new FunctionCallOutput({\n callId: 'orphan_call',\n output: 'This should be ignored',\n isError: false,\n createdAt: 2000,\n });\n ctx.insert(orphanOutput);\n\n ctx.addMessage({ role: 'assistant', content: 'Hi!', createdAt: 3000 });\n\n const result = await toChatCtx(ctx);\n\n // Messages should be in the result, orphan output should be filtered out\n expect(result).toHaveLength(2);\n expect(result).toContainEqual({ role: 'user', content: 'Hello' });\n expect(result).toContainEqual({ role: 'assistant', content: 'Hi!' });\n });\n\n it('should handle mixed content with text and multiple images', async () => {\n serializeImageMock\n .mockResolvedValueOnce({\n inferenceDetail: 'high',\n externalUrl: 'https://example.com/image1.jpg',\n })\n .mockResolvedValueOnce({\n inferenceDetail: 'low',\n mimeType: 'image/png',\n base64Data: 'base64data',\n });\n\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'user',\n content: [\n 'Here are two images:',\n {\n id: 'img1',\n type: 'image_content',\n image: 'https://example.com/image1.jpg',\n inferenceDetail: 'high',\n _cache: {},\n },\n 'And the second one:',\n {\n id: 'img2',\n type: 'image_content',\n image: 'data:image/png;base64,base64data',\n inferenceDetail: 'low',\n _cache: {},\n },\n 'What do you think?',\n ],\n });\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: 'https://example.com/image1.jpg',\n detail: 'high',\n },\n },\n {\n type: 'image_url',\n image_url: {\n url: 'data:image/png;base64,base64data',\n detail: 'low',\n },\n },\n {\n type: 'text',\n text: 'Here are two images:\\nAnd the second one:\\nWhat do you think?',\n },\n ],\n },\n ]);\n });\n\n it('should handle content with only images and no text', async () => {\n serializeImageMock.mockResolvedValue({\n inferenceDetail: 'auto',\n externalUrl: 'https://example.com/image.jpg',\n });\n\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'user',\n content: [\n {\n id: 'img1',\n type: 'image_content',\n image: 'https://example.com/image.jpg',\n inferenceDetail: 'auto',\n _cache: {},\n },\n ],\n });\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: 'https://example.com/image.jpg',\n detail: 'auto',\n },\n },\n ],\n },\n ]);\n });\n\n it('should throw error for unsupported content type', async () => {\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'user',\n content: [\n {\n type: 'audio_content',\n frame: [],\n },\n ],\n });\n\n await expect(toChatCtx(ctx)).rejects.toThrow('Unsupported content type: audio_content');\n });\n\n it('should throw error when serialized image has no data', async () => {\n serializeImageMock.mockResolvedValue({\n inferenceDetail: 'high',\n // No base64Data or externalUrl\n });\n\n const ctx = ChatContext.empty();\n ctx.addMessage({\n role: 'user',\n content: [\n {\n id: 'img1',\n type: 'image_content',\n image: 'invalid-image',\n inferenceDetail: 'high',\n _cache: {},\n },\n ],\n });\n\n await expect(toChatCtx(ctx)).rejects.toThrow('Serialized image has no data bytes');\n });\n\n it('should filter out standalone function calls without outputs', async () => {\n const ctx = ChatContext.empty();\n\n // Add standalone function call without output\n const funcCall = new FunctionCall({\n id: 'func_standalone',\n callId: 'call_999',\n name: 'standalone_function',\n args: '{}',\n });\n\n ctx.insert(funcCall);\n\n const result = await toChatCtx(ctx);\n\n // Standalone function calls without outputs are filtered out by groupToolCalls\n expect(result).toEqual([]);\n });\n\n it('should handle function call output correctly', async () => {\n const ctx = ChatContext.empty();\n\n // First add a function call\n const funcCall = new FunctionCall({\n id: 'func_1',\n callId: 'call_output_test',\n name: 'test_function',\n args: '{}',\n });\n\n // Then add its output\n const funcOutput = new FunctionCallOutput({\n callId: 'call_output_test',\n output: 'Function executed successfully',\n isError: false,\n });\n\n ctx.insert([funcCall, funcOutput]);\n\n const result = await toChatCtx(ctx);\n\n expect(result).toEqual([\n {\n role: 'assistant',\n tool_calls: [\n {\n id: 'call_output_test',\n type: 'function',\n function: {\n name: 'test_function',\n arguments: '{}',\n },\n },\n ],\n },\n {\n role: 'tool',\n tool_call_id: 'call_output_test',\n content: 'Function executed successfully',\n },\n ]);\n });\n\n it('should filter out agent handoff items', async () => {\n const ctx = ChatContext.empty();\n\n ctx.addMessage({ role: 'user', content: 'Hello' });\n\n // Insert an agent handoff item\n const handoff = new AgentHandoffItem({\n oldAgentId: 'agent_1',\n newAgentId: 'agent_2',\n });\n ctx.insert(handoff);\n\n ctx.addMessage({ role: 'assistant', content: 'Hi there!' });\n\n const result = await toChatCtx(ctx);\n\n // Agent handoff should be filtered out, only messages should remain\n expect(result).toEqual([\n { role: 'user', content: 'Hello' },\n { role: 'assistant', content: 'Hi there!' },\n ]);\n });\n\n it('should handle multiple agent handoffs without errors', async () => {\n const ctx = ChatContext.empty();\n\n ctx.addMessage({ role: 'user', content: 'Start' });\n\n // Multiple handoffs\n ctx.insert(new AgentHandoffItem({ oldAgentId: undefined, newAgentId: 'agent_1' }));\n ctx.addMessage({ role: 'assistant', content: 'Response from agent 1' });\n\n ctx.insert(new AgentHandoffItem({ oldAgentId: 'agent_1', newAgentId: 'agent_2' }));\n ctx.addMessage({ role: 'assistant', content: 'Response from agent 2' });\n\n ctx.insert(new AgentHandoffItem({ oldAgentId: 'agent_2', newAgentId: 'agent_3' }));\n ctx.addMessage({ role: 'assistant', content: 'Response from agent 3' });\n\n const result = await toChatCtx(ctx);\n\n // All handoffs should be filtered out\n expect(result).toEqual([\n { role: 'user', content: 'Start' },\n { role: 'assistant', content: 'Response from agent 1' },\n { role: 'assistant', content: 'Response from agent 2' },\n { role: 'assistant', content: 'Response from agent 3' },\n ]);\n });\n});\n"],"mappings":"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","names":[]}
|
|
@@ -103,7 +103,7 @@ function groupToolCalls(chatCtx) {
|
|
|
103
103
|
const isFunctionCall = item.type === "function_call";
|
|
104
104
|
const isFunctionCallOutput = item.type === "function_call_output";
|
|
105
105
|
if (isAssistantMessage || isFunctionCall) {
|
|
106
|
-
const groupId = item.id.split("/")[0];
|
|
106
|
+
const groupId = item.type === "function_call" && item.groupId ? item.groupId : item.id.split("/")[0];
|
|
107
107
|
if (itemGroups[groupId] === void 0) {
|
|
108
108
|
itemGroups[groupId] = ChatItemGroup.create();
|
|
109
109
|
insertionOrder[groupId] = insertionIndex;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/llm/provider_format/utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { log } from '../../log.js';\nimport type {\n ChatContext,\n ChatItem,\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n} from '../chat_context.js';\n\nclass ChatItemGroup {\n message?: ChatMessage;\n toolCalls: FunctionCall[];\n toolOutputs: FunctionCallOutput[];\n logger = log();\n\n constructor(params: {\n message?: ChatMessage;\n toolCalls: FunctionCall[];\n toolOutputs: FunctionCallOutput[];\n }) {\n this.message = params.message;\n this.toolCalls = params.toolCalls;\n this.toolOutputs = params.toolOutputs;\n }\n\n static create(params?: {\n message?: ChatMessage;\n toolCalls?: FunctionCall[];\n toolOutputs?: FunctionCallOutput[];\n }) {\n const { message, toolCalls = [], toolOutputs = [] } = params ?? {};\n return new ChatItemGroup({ message, toolCalls, toolOutputs });\n }\n\n get isEmpty() {\n return (\n this.message === undefined && this.toolCalls.length === 0 && this.toolOutputs.length === 0\n );\n }\n\n add(item: ChatItem) {\n if (item.type === 'message') {\n if (this.message) {\n throw new Error('only one message is allowed in a group');\n }\n this.message = item;\n } else if (item.type === 'function_call') {\n this.toolCalls.push(item);\n } else if (item.type === 'function_call_output') {\n this.toolOutputs.push(item);\n }\n return this;\n }\n\n removeInvalidToolCalls() {\n if (this.toolCalls.length === this.toolOutputs.length) {\n return;\n }\n\n const toolCallIds = new Set(this.toolCalls.map((call) => call.callId));\n const toolOutputIds = new Set(this.toolOutputs.map((output) => output.callId));\n\n // intersection of tool call ids and tool output ids\n const validCallIds = intersection(toolCallIds, toolOutputIds);\n\n // filter out tool calls that don't have a corresponding tool output\n this.toolCalls = this.toolCalls.filter((call) => {\n if (validCallIds.has(call.callId)) return true;\n this.logger.warn(\n {\n callId: call.callId,\n toolName: call.name,\n },\n 'function call missing the corresponding function output, ignoring',\n );\n return false;\n });\n\n // filter out tool outputs that don't have a corresponding tool call\n this.toolOutputs = this.toolOutputs.filter((output) => {\n if (validCallIds.has(output.callId)) return true;\n this.logger.warn(\n {\n callId: output.callId,\n toolName: output.name,\n },\n 'function output missing the corresponding function call, ignoring',\n );\n return false;\n });\n }\n\n flatten() {\n const items: ChatItem[] = [];\n if (this.message) items.push(this.message);\n items.push(...this.toolCalls, ...this.toolOutputs);\n return items;\n }\n}\n\nfunction intersection<T>(set1: Set<T>, set2: Set<T>): Set<T> {\n return new Set([...set1].filter((item) => set2.has(item)));\n}\n\n/**\n * Group chat items (messages, function calls, and function outputs)\n * into coherent groups based on their item IDs and call IDs.\n *\n * Each group will contain:\n * - Zero or one assistant message\n * - Zero or more function/tool calls\n * - The corresponding function/tool outputs matched by call_id\n *\n * User and system messages are placed in their own individual groups.\n *\n * @param chatCtx - The chat context containing all conversation items\n * @returns A list of ChatItemGroup objects representing the grouped conversation\n */\nexport function groupToolCalls(chatCtx: ChatContext) {\n const itemGroups: Record<string, ChatItemGroup> = {};\n const insertionOrder: Record<string, number> = {};\n const toolOutputs: FunctionCallOutput[] = [];\n const logger = log();\n\n let insertionIndex = 0;\n for (const item of chatCtx.items) {\n const isAssistantMessage = item.type === 'message' && item.role === 'assistant';\n const isFunctionCall = item.type === 'function_call';\n const isFunctionCallOutput = item.type === 'function_call_output';\n\n if (isAssistantMessage || isFunctionCall) {\n // only assistant messages and function calls can be grouped\n const groupId
|
|
1
|
+
{"version":3,"sources":["../../../src/llm/provider_format/utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { log } from '../../log.js';\nimport type {\n ChatContext,\n ChatItem,\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n} from '../chat_context.js';\n\nclass ChatItemGroup {\n message?: ChatMessage;\n toolCalls: FunctionCall[];\n toolOutputs: FunctionCallOutput[];\n logger = log();\n\n constructor(params: {\n message?: ChatMessage;\n toolCalls: FunctionCall[];\n toolOutputs: FunctionCallOutput[];\n }) {\n this.message = params.message;\n this.toolCalls = params.toolCalls;\n this.toolOutputs = params.toolOutputs;\n }\n\n static create(params?: {\n message?: ChatMessage;\n toolCalls?: FunctionCall[];\n toolOutputs?: FunctionCallOutput[];\n }) {\n const { message, toolCalls = [], toolOutputs = [] } = params ?? {};\n return new ChatItemGroup({ message, toolCalls, toolOutputs });\n }\n\n get isEmpty() {\n return (\n this.message === undefined && this.toolCalls.length === 0 && this.toolOutputs.length === 0\n );\n }\n\n add(item: ChatItem) {\n if (item.type === 'message') {\n if (this.message) {\n throw new Error('only one message is allowed in a group');\n }\n this.message = item;\n } else if (item.type === 'function_call') {\n this.toolCalls.push(item);\n } else if (item.type === 'function_call_output') {\n this.toolOutputs.push(item);\n }\n return this;\n }\n\n removeInvalidToolCalls() {\n if (this.toolCalls.length === this.toolOutputs.length) {\n return;\n }\n\n const toolCallIds = new Set(this.toolCalls.map((call) => call.callId));\n const toolOutputIds = new Set(this.toolOutputs.map((output) => output.callId));\n\n // intersection of tool call ids and tool output ids\n const validCallIds = intersection(toolCallIds, toolOutputIds);\n\n // filter out tool calls that don't have a corresponding tool output\n this.toolCalls = this.toolCalls.filter((call) => {\n if (validCallIds.has(call.callId)) return true;\n this.logger.warn(\n {\n callId: call.callId,\n toolName: call.name,\n },\n 'function call missing the corresponding function output, ignoring',\n );\n return false;\n });\n\n // filter out tool outputs that don't have a corresponding tool call\n this.toolOutputs = this.toolOutputs.filter((output) => {\n if (validCallIds.has(output.callId)) return true;\n this.logger.warn(\n {\n callId: output.callId,\n toolName: output.name,\n },\n 'function output missing the corresponding function call, ignoring',\n );\n return false;\n });\n }\n\n flatten() {\n const items: ChatItem[] = [];\n if (this.message) items.push(this.message);\n items.push(...this.toolCalls, ...this.toolOutputs);\n return items;\n }\n}\n\nfunction intersection<T>(set1: Set<T>, set2: Set<T>): Set<T> {\n return new Set([...set1].filter((item) => set2.has(item)));\n}\n\n/**\n * Group chat items (messages, function calls, and function outputs)\n * into coherent groups based on their item IDs and call IDs.\n *\n * Each group will contain:\n * - Zero or one assistant message\n * - Zero or more function/tool calls\n * - The corresponding function/tool outputs matched by call_id\n *\n * User and system messages are placed in their own individual groups.\n *\n * @param chatCtx - The chat context containing all conversation items\n * @returns A list of ChatItemGroup objects representing the grouped conversation\n */\nexport function groupToolCalls(chatCtx: ChatContext) {\n const itemGroups: Record<string, ChatItemGroup> = {};\n const insertionOrder: Record<string, number> = {};\n const toolOutputs: FunctionCallOutput[] = [];\n const logger = log();\n\n let insertionIndex = 0;\n for (const item of chatCtx.items) {\n const isAssistantMessage = item.type === 'message' && item.role === 'assistant';\n const isFunctionCall = item.type === 'function_call';\n const isFunctionCallOutput = item.type === 'function_call_output';\n\n if (isAssistantMessage || isFunctionCall) {\n // only assistant messages and function calls can be grouped\n // For function calls, use group_id if available (for parallel function calls),\n // otherwise fall back to id-based grouping for backwards compatibility\n const groupId =\n item.type === 'function_call' && item.groupId ? item.groupId : item.id.split('/')[0]!;\n\n if (itemGroups[groupId] === undefined) {\n itemGroups[groupId] = ChatItemGroup.create();\n\n // we use insertion order to sort the groups as they are added to the context\n // simulating the OrderedDict in python\n insertionOrder[groupId] = insertionIndex;\n insertionIndex++;\n }\n itemGroups[groupId]!.add(item);\n } else if (isFunctionCallOutput) {\n toolOutputs.push(item);\n } else {\n itemGroups[item.id] = ChatItemGroup.create().add(item);\n }\n }\n\n // add tool outputs to their corresponding groups\n const callIdToGroup: Record<string, ChatItemGroup> = {};\n for (const group of Object.values(itemGroups)) {\n for (const toolCall of group.toolCalls) {\n callIdToGroup[toolCall.callId] = group;\n }\n }\n\n for (const toolOutput of toolOutputs) {\n const group = callIdToGroup[toolOutput.callId];\n if (group === undefined) {\n logger.warn(\n { callId: toolOutput.callId, toolName: toolOutput.name },\n 'function output missing the corresponding function call, ignoring',\n );\n continue;\n }\n group.add(toolOutput);\n }\n\n // validate that each group and remove invalid tool calls and tool outputs\n for (const group of Object.values(itemGroups)) {\n group.removeInvalidToolCalls();\n }\n\n // sort groups by their item id\n const orderedGroups = Object.entries(itemGroups)\n .sort((a, b) => insertionOrder[a[0]]! - insertionOrder[b[0]]!)\n .map(([, group]) => group);\n return orderedGroups;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/llm/provider_format/utils.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAE5B,cAAM,aAAa;IACjB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,WAAW,EAAE,kBAAkB,EAAE,CAAC;IAClC,MAAM,wBAAS;gBAEH,MAAM,EAAE;QAClB,OAAO,CAAC,EAAE,WAAW,CAAC;QACtB,SAAS,EAAE,YAAY,EAAE,CAAC;QAC1B,WAAW,EAAE,kBAAkB,EAAE,CAAC;KACnC;IAMD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;QACrB,OAAO,CAAC,EAAE,WAAW,CAAC;QACtB,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;QAC3B,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;KACpC;IAKD,IAAI,OAAO,YAIV;IAED,GAAG,CAAC,IAAI,EAAE,QAAQ;IAclB,sBAAsB;IAsCtB,OAAO;CAMR;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/llm/provider_format/utils.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAE5B,cAAM,aAAa;IACjB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,WAAW,EAAE,kBAAkB,EAAE,CAAC;IAClC,MAAM,wBAAS;gBAEH,MAAM,EAAE;QAClB,OAAO,CAAC,EAAE,WAAW,CAAC;QACtB,SAAS,EAAE,YAAY,EAAE,CAAC;QAC1B,WAAW,EAAE,kBAAkB,EAAE,CAAC;KACnC;IAMD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;QACrB,OAAO,CAAC,EAAE,WAAW,CAAC;QACtB,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;QAC3B,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;KACpC;IAKD,IAAI,OAAO,YAIV;IAED,GAAG,CAAC,IAAI,EAAE,QAAQ;IAclB,sBAAsB;IAsCtB,OAAO;CAMR;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,mBAiElD"}
|
|
@@ -80,7 +80,7 @@ function groupToolCalls(chatCtx) {
|
|
|
80
80
|
const isFunctionCall = item.type === "function_call";
|
|
81
81
|
const isFunctionCallOutput = item.type === "function_call_output";
|
|
82
82
|
if (isAssistantMessage || isFunctionCall) {
|
|
83
|
-
const groupId = item.id.split("/")[0];
|
|
83
|
+
const groupId = item.type === "function_call" && item.groupId ? item.groupId : item.id.split("/")[0];
|
|
84
84
|
if (itemGroups[groupId] === void 0) {
|
|
85
85
|
itemGroups[groupId] = ChatItemGroup.create();
|
|
86
86
|
insertionOrder[groupId] = insertionIndex;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/llm/provider_format/utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { log } from '../../log.js';\nimport type {\n ChatContext,\n ChatItem,\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n} from '../chat_context.js';\n\nclass ChatItemGroup {\n message?: ChatMessage;\n toolCalls: FunctionCall[];\n toolOutputs: FunctionCallOutput[];\n logger = log();\n\n constructor(params: {\n message?: ChatMessage;\n toolCalls: FunctionCall[];\n toolOutputs: FunctionCallOutput[];\n }) {\n this.message = params.message;\n this.toolCalls = params.toolCalls;\n this.toolOutputs = params.toolOutputs;\n }\n\n static create(params?: {\n message?: ChatMessage;\n toolCalls?: FunctionCall[];\n toolOutputs?: FunctionCallOutput[];\n }) {\n const { message, toolCalls = [], toolOutputs = [] } = params ?? {};\n return new ChatItemGroup({ message, toolCalls, toolOutputs });\n }\n\n get isEmpty() {\n return (\n this.message === undefined && this.toolCalls.length === 0 && this.toolOutputs.length === 0\n );\n }\n\n add(item: ChatItem) {\n if (item.type === 'message') {\n if (this.message) {\n throw new Error('only one message is allowed in a group');\n }\n this.message = item;\n } else if (item.type === 'function_call') {\n this.toolCalls.push(item);\n } else if (item.type === 'function_call_output') {\n this.toolOutputs.push(item);\n }\n return this;\n }\n\n removeInvalidToolCalls() {\n if (this.toolCalls.length === this.toolOutputs.length) {\n return;\n }\n\n const toolCallIds = new Set(this.toolCalls.map((call) => call.callId));\n const toolOutputIds = new Set(this.toolOutputs.map((output) => output.callId));\n\n // intersection of tool call ids and tool output ids\n const validCallIds = intersection(toolCallIds, toolOutputIds);\n\n // filter out tool calls that don't have a corresponding tool output\n this.toolCalls = this.toolCalls.filter((call) => {\n if (validCallIds.has(call.callId)) return true;\n this.logger.warn(\n {\n callId: call.callId,\n toolName: call.name,\n },\n 'function call missing the corresponding function output, ignoring',\n );\n return false;\n });\n\n // filter out tool outputs that don't have a corresponding tool call\n this.toolOutputs = this.toolOutputs.filter((output) => {\n if (validCallIds.has(output.callId)) return true;\n this.logger.warn(\n {\n callId: output.callId,\n toolName: output.name,\n },\n 'function output missing the corresponding function call, ignoring',\n );\n return false;\n });\n }\n\n flatten() {\n const items: ChatItem[] = [];\n if (this.message) items.push(this.message);\n items.push(...this.toolCalls, ...this.toolOutputs);\n return items;\n }\n}\n\nfunction intersection<T>(set1: Set<T>, set2: Set<T>): Set<T> {\n return new Set([...set1].filter((item) => set2.has(item)));\n}\n\n/**\n * Group chat items (messages, function calls, and function outputs)\n * into coherent groups based on their item IDs and call IDs.\n *\n * Each group will contain:\n * - Zero or one assistant message\n * - Zero or more function/tool calls\n * - The corresponding function/tool outputs matched by call_id\n *\n * User and system messages are placed in their own individual groups.\n *\n * @param chatCtx - The chat context containing all conversation items\n * @returns A list of ChatItemGroup objects representing the grouped conversation\n */\nexport function groupToolCalls(chatCtx: ChatContext) {\n const itemGroups: Record<string, ChatItemGroup> = {};\n const insertionOrder: Record<string, number> = {};\n const toolOutputs: FunctionCallOutput[] = [];\n const logger = log();\n\n let insertionIndex = 0;\n for (const item of chatCtx.items) {\n const isAssistantMessage = item.type === 'message' && item.role === 'assistant';\n const isFunctionCall = item.type === 'function_call';\n const isFunctionCallOutput = item.type === 'function_call_output';\n\n if (isAssistantMessage || isFunctionCall) {\n // only assistant messages and function calls can be grouped\n const groupId
|
|
1
|
+
{"version":3,"sources":["../../../src/llm/provider_format/utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { log } from '../../log.js';\nimport type {\n ChatContext,\n ChatItem,\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n} from '../chat_context.js';\n\nclass ChatItemGroup {\n message?: ChatMessage;\n toolCalls: FunctionCall[];\n toolOutputs: FunctionCallOutput[];\n logger = log();\n\n constructor(params: {\n message?: ChatMessage;\n toolCalls: FunctionCall[];\n toolOutputs: FunctionCallOutput[];\n }) {\n this.message = params.message;\n this.toolCalls = params.toolCalls;\n this.toolOutputs = params.toolOutputs;\n }\n\n static create(params?: {\n message?: ChatMessage;\n toolCalls?: FunctionCall[];\n toolOutputs?: FunctionCallOutput[];\n }) {\n const { message, toolCalls = [], toolOutputs = [] } = params ?? {};\n return new ChatItemGroup({ message, toolCalls, toolOutputs });\n }\n\n get isEmpty() {\n return (\n this.message === undefined && this.toolCalls.length === 0 && this.toolOutputs.length === 0\n );\n }\n\n add(item: ChatItem) {\n if (item.type === 'message') {\n if (this.message) {\n throw new Error('only one message is allowed in a group');\n }\n this.message = item;\n } else if (item.type === 'function_call') {\n this.toolCalls.push(item);\n } else if (item.type === 'function_call_output') {\n this.toolOutputs.push(item);\n }\n return this;\n }\n\n removeInvalidToolCalls() {\n if (this.toolCalls.length === this.toolOutputs.length) {\n return;\n }\n\n const toolCallIds = new Set(this.toolCalls.map((call) => call.callId));\n const toolOutputIds = new Set(this.toolOutputs.map((output) => output.callId));\n\n // intersection of tool call ids and tool output ids\n const validCallIds = intersection(toolCallIds, toolOutputIds);\n\n // filter out tool calls that don't have a corresponding tool output\n this.toolCalls = this.toolCalls.filter((call) => {\n if (validCallIds.has(call.callId)) return true;\n this.logger.warn(\n {\n callId: call.callId,\n toolName: call.name,\n },\n 'function call missing the corresponding function output, ignoring',\n );\n return false;\n });\n\n // filter out tool outputs that don't have a corresponding tool call\n this.toolOutputs = this.toolOutputs.filter((output) => {\n if (validCallIds.has(output.callId)) return true;\n this.logger.warn(\n {\n callId: output.callId,\n toolName: output.name,\n },\n 'function output missing the corresponding function call, ignoring',\n );\n return false;\n });\n }\n\n flatten() {\n const items: ChatItem[] = [];\n if (this.message) items.push(this.message);\n items.push(...this.toolCalls, ...this.toolOutputs);\n return items;\n }\n}\n\nfunction intersection<T>(set1: Set<T>, set2: Set<T>): Set<T> {\n return new Set([...set1].filter((item) => set2.has(item)));\n}\n\n/**\n * Group chat items (messages, function calls, and function outputs)\n * into coherent groups based on their item IDs and call IDs.\n *\n * Each group will contain:\n * - Zero or one assistant message\n * - Zero or more function/tool calls\n * - The corresponding function/tool outputs matched by call_id\n *\n * User and system messages are placed in their own individual groups.\n *\n * @param chatCtx - The chat context containing all conversation items\n * @returns A list of ChatItemGroup objects representing the grouped conversation\n */\nexport function groupToolCalls(chatCtx: ChatContext) {\n const itemGroups: Record<string, ChatItemGroup> = {};\n const insertionOrder: Record<string, number> = {};\n const toolOutputs: FunctionCallOutput[] = [];\n const logger = log();\n\n let insertionIndex = 0;\n for (const item of chatCtx.items) {\n const isAssistantMessage = item.type === 'message' && item.role === 'assistant';\n const isFunctionCall = item.type === 'function_call';\n const isFunctionCallOutput = item.type === 'function_call_output';\n\n if (isAssistantMessage || isFunctionCall) {\n // only assistant messages and function calls can be grouped\n // For function calls, use group_id if available (for parallel function calls),\n // otherwise fall back to id-based grouping for backwards compatibility\n const groupId =\n item.type === 'function_call' && item.groupId ? item.groupId : item.id.split('/')[0]!;\n\n if (itemGroups[groupId] === undefined) {\n itemGroups[groupId] = ChatItemGroup.create();\n\n // we use insertion order to sort the groups as they are added to the context\n // simulating the OrderedDict in python\n insertionOrder[groupId] = insertionIndex;\n insertionIndex++;\n }\n itemGroups[groupId]!.add(item);\n } else if (isFunctionCallOutput) {\n toolOutputs.push(item);\n } else {\n itemGroups[item.id] = ChatItemGroup.create().add(item);\n }\n }\n\n // add tool outputs to their corresponding groups\n const callIdToGroup: Record<string, ChatItemGroup> = {};\n for (const group of Object.values(itemGroups)) {\n for (const toolCall of group.toolCalls) {\n callIdToGroup[toolCall.callId] = group;\n }\n }\n\n for (const toolOutput of toolOutputs) {\n const group = callIdToGroup[toolOutput.callId];\n if (group === undefined) {\n logger.warn(\n { callId: toolOutput.callId, toolName: toolOutput.name },\n 'function output missing the corresponding function call, ignoring',\n );\n continue;\n }\n group.add(toolOutput);\n }\n\n // validate that each group and remove invalid tool calls and tool outputs\n for (const group of Object.values(itemGroups)) {\n group.removeInvalidToolCalls();\n }\n\n // sort groups by their item id\n const orderedGroups = Object.entries(itemGroups)\n .sort((a, b) => insertionOrder[a[0]]! - insertionOrder[b[0]]!)\n .map(([, group]) => group);\n return orderedGroups;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/stream/stream_channel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { ReadableStream } from 'node:stream/web';\nimport { IdentityTransform } from './identity_transform.js';\n\nexport interface StreamChannel<T> {\n write(chunk: T): Promise<void>;\n close(): Promise<void>;\n stream(): ReadableStream<T>;\n readonly closed: boolean;\n}\n\nexport function createStreamChannel<T>(): StreamChannel<T> {\n const transform = new IdentityTransform<T>();\n const writer = transform.writable.getWriter();\n let isClosed = false;\n\n return {\n write: (chunk: T) => writer.write(chunk),\n stream: () => transform.readable,\n close: async () => {\n try {\n const result = await writer.close();\n isClosed = true;\n return result;\n } catch (e) {\n if (e instanceof Error && e.name === 'TypeError') {\n // Ignore error if the stream is already closed\n isClosed = true;\n return;\n }\n throw e;\n }\n },\n get closed() {\n return isClosed;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,gCAAkC;
|
|
1
|
+
{"version":3,"sources":["../../src/stream/stream_channel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { ReadableStream } from 'node:stream/web';\nimport { IdentityTransform } from './identity_transform.js';\n\nexport interface StreamChannel<T, E extends Error = Error> {\n write(chunk: T): Promise<void>;\n close(): Promise<void>;\n stream(): ReadableStream<T>;\n abort(error: E): Promise<void>;\n readonly closed: boolean;\n}\n\nexport function createStreamChannel<T, E extends Error = Error>(): StreamChannel<T, E> {\n const transform = new IdentityTransform<T>();\n const writer = transform.writable.getWriter();\n let isClosed = false;\n\n return {\n write: (chunk: T) => writer.write(chunk),\n stream: () => transform.readable,\n abort: (error: E) => {\n return writer.abort(error);\n },\n close: async () => {\n try {\n const result = await writer.close();\n isClosed = true;\n return result;\n } catch (e) {\n if (e instanceof Error && e.name === 'TypeError') {\n // Ignore error if the stream is already closed\n isClosed = true;\n return;\n }\n throw e;\n }\n },\n get closed() {\n return isClosed;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,gCAAkC;AAU3B,SAAS,sBAAuE;AACrF,QAAM,YAAY,IAAI,4CAAqB;AAC3C,QAAM,SAAS,UAAU,SAAS,UAAU;AAC5C,MAAI,WAAW;AAEf,SAAO;AAAA,IACL,OAAO,CAAC,UAAa,OAAO,MAAM,KAAK;AAAA,IACvC,QAAQ,MAAM,UAAU;AAAA,IACxB,OAAO,CAAC,UAAa;AACnB,aAAO,OAAO,MAAM,KAAK;AAAA,IAC3B;AAAA,IACA,OAAO,YAAY;AACjB,UAAI;AACF,cAAM,SAAS,MAAM,OAAO,MAAM;AAClC,mBAAW;AACX,eAAO;AAAA,MACT,SAAS,GAAG;AACV,YAAI,aAAa,SAAS,EAAE,SAAS,aAAa;AAEhD,qBAAW;AACX;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,IAAI,SAAS;AACX,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import type { ReadableStream } from 'node:stream/web';
|
|
3
|
-
export interface StreamChannel<T> {
|
|
3
|
+
export interface StreamChannel<T, E extends Error = Error> {
|
|
4
4
|
write(chunk: T): Promise<void>;
|
|
5
5
|
close(): Promise<void>;
|
|
6
6
|
stream(): ReadableStream<T>;
|
|
7
|
+
abort(error: E): Promise<void>;
|
|
7
8
|
readonly closed: boolean;
|
|
8
9
|
}
|
|
9
|
-
export declare function createStreamChannel<T>(): StreamChannel<T>;
|
|
10
|
+
export declare function createStreamChannel<T, E extends Error = Error>(): StreamChannel<T, E>;
|
|
10
11
|
//# sourceMappingURL=stream_channel.d.ts.map
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import type { ReadableStream } from 'node:stream/web';
|
|
3
|
-
export interface StreamChannel<T> {
|
|
3
|
+
export interface StreamChannel<T, E extends Error = Error> {
|
|
4
4
|
write(chunk: T): Promise<void>;
|
|
5
5
|
close(): Promise<void>;
|
|
6
6
|
stream(): ReadableStream<T>;
|
|
7
|
+
abort(error: E): Promise<void>;
|
|
7
8
|
readonly closed: boolean;
|
|
8
9
|
}
|
|
9
|
-
export declare function createStreamChannel<T>(): StreamChannel<T>;
|
|
10
|
+
export declare function createStreamChannel<T, E extends Error = Error>(): StreamChannel<T, E>;
|
|
10
11
|
//# sourceMappingURL=stream_channel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream_channel.d.ts","sourceRoot":"","sources":["../../src/stream/stream_channel.ts"],"names":[],"mappings":";AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtD,MAAM,WAAW,aAAa,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"stream_channel.d.ts","sourceRoot":"","sources":["../../src/stream/stream_channel.ts"],"names":[],"mappings":";AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtD,MAAM,WAAW,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,KAAK,GAAG,KAAK;IACvD,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC;IAC5B,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,CAAC,SAAS,KAAK,GAAG,KAAK,KAAK,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CA6BrF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/stream/stream_channel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { ReadableStream } from 'node:stream/web';\nimport { IdentityTransform } from './identity_transform.js';\n\nexport interface StreamChannel<T> {\n write(chunk: T): Promise<void>;\n close(): Promise<void>;\n stream(): ReadableStream<T>;\n readonly closed: boolean;\n}\n\nexport function createStreamChannel<T>(): StreamChannel<T> {\n const transform = new IdentityTransform<T>();\n const writer = transform.writable.getWriter();\n let isClosed = false;\n\n return {\n write: (chunk: T) => writer.write(chunk),\n stream: () => transform.readable,\n close: async () => {\n try {\n const result = await writer.close();\n isClosed = true;\n return result;\n } catch (e) {\n if (e instanceof Error && e.name === 'TypeError') {\n // Ignore error if the stream is already closed\n isClosed = true;\n return;\n }\n throw e;\n }\n },\n get closed() {\n return isClosed;\n },\n };\n}\n"],"mappings":"AAIA,SAAS,yBAAyB;
|
|
1
|
+
{"version":3,"sources":["../../src/stream/stream_channel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { ReadableStream } from 'node:stream/web';\nimport { IdentityTransform } from './identity_transform.js';\n\nexport interface StreamChannel<T, E extends Error = Error> {\n write(chunk: T): Promise<void>;\n close(): Promise<void>;\n stream(): ReadableStream<T>;\n abort(error: E): Promise<void>;\n readonly closed: boolean;\n}\n\nexport function createStreamChannel<T, E extends Error = Error>(): StreamChannel<T, E> {\n const transform = new IdentityTransform<T>();\n const writer = transform.writable.getWriter();\n let isClosed = false;\n\n return {\n write: (chunk: T) => writer.write(chunk),\n stream: () => transform.readable,\n abort: (error: E) => {\n return writer.abort(error);\n },\n close: async () => {\n try {\n const result = await writer.close();\n isClosed = true;\n return result;\n } catch (e) {\n if (e instanceof Error && e.name === 'TypeError') {\n // Ignore error if the stream is already closed\n isClosed = true;\n return;\n }\n throw e;\n }\n },\n get closed() {\n return isClosed;\n },\n };\n}\n"],"mappings":"AAIA,SAAS,yBAAyB;AAU3B,SAAS,sBAAuE;AACrF,QAAM,YAAY,IAAI,kBAAqB;AAC3C,QAAM,SAAS,UAAU,SAAS,UAAU;AAC5C,MAAI,WAAW;AAEf,SAAO;AAAA,IACL,OAAO,CAAC,UAAa,OAAO,MAAM,KAAK;AAAA,IACvC,QAAQ,MAAM,UAAU;AAAA,IACxB,OAAO,CAAC,UAAa;AACnB,aAAO,OAAO,MAAM,KAAK;AAAA,IAC3B;AAAA,IACA,OAAO,YAAY;AACjB,UAAI;AACF,cAAM,SAAS,MAAM,OAAO,MAAM;AAClC,mBAAW;AACX,eAAO;AAAA,MACT,SAAS,GAAG;AACV,YAAI,aAAa,SAAS,EAAE,SAAS,aAAa;AAEhD,qBAAW;AACX;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,IAAI,SAAS;AACX,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
|
|
@@ -45,6 +45,11 @@ __export(trace_types_exports, {
|
|
|
45
45
|
ATTR_GEN_AI_USAGE_OUTPUT_TEXT_TOKENS: () => ATTR_GEN_AI_USAGE_OUTPUT_TEXT_TOKENS,
|
|
46
46
|
ATTR_GEN_AI_USAGE_OUTPUT_TOKENS: () => ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,
|
|
47
47
|
ATTR_INSTRUCTIONS: () => ATTR_INSTRUCTIONS,
|
|
48
|
+
ATTR_INTERRUPTION_DETECTION_DELAY: () => ATTR_INTERRUPTION_DETECTION_DELAY,
|
|
49
|
+
ATTR_INTERRUPTION_PREDICTION_DURATION: () => ATTR_INTERRUPTION_PREDICTION_DURATION,
|
|
50
|
+
ATTR_INTERRUPTION_PROBABILITY: () => ATTR_INTERRUPTION_PROBABILITY,
|
|
51
|
+
ATTR_INTERRUPTION_TOTAL_DURATION: () => ATTR_INTERRUPTION_TOTAL_DURATION,
|
|
52
|
+
ATTR_IS_INTERRUPTION: () => ATTR_IS_INTERRUPTION,
|
|
48
53
|
ATTR_JOB_ID: () => ATTR_JOB_ID,
|
|
49
54
|
ATTR_LANGFUSE_COMPLETION_START_TIME: () => ATTR_LANGFUSE_COMPLETION_START_TIME,
|
|
50
55
|
ATTR_LLM_METRICS: () => ATTR_LLM_METRICS,
|
|
@@ -109,6 +114,11 @@ const ATTR_USER_TRANSCRIPT = "lk.user_transcript";
|
|
|
109
114
|
const ATTR_TRANSCRIPT_CONFIDENCE = "lk.transcript_confidence";
|
|
110
115
|
const ATTR_TRANSCRIPTION_DELAY = "lk.transcription_delay";
|
|
111
116
|
const ATTR_END_OF_TURN_DELAY = "lk.end_of_turn_delay";
|
|
117
|
+
const ATTR_IS_INTERRUPTION = "lk.is_interruption";
|
|
118
|
+
const ATTR_INTERRUPTION_PROBABILITY = "lk.interruption.probability";
|
|
119
|
+
const ATTR_INTERRUPTION_TOTAL_DURATION = "lk.interruption.total_duration";
|
|
120
|
+
const ATTR_INTERRUPTION_PREDICTION_DURATION = "lk.interruption.prediction_duration";
|
|
121
|
+
const ATTR_INTERRUPTION_DETECTION_DELAY = "lk.interruption.detection_delay";
|
|
112
122
|
const ATTR_LLM_METRICS = "lk.llm_metrics";
|
|
113
123
|
const ATTR_TTS_METRICS = "lk.tts_metrics";
|
|
114
124
|
const ATTR_REALTIME_MODEL_METRICS = "lk.realtime_model_metrics";
|
|
@@ -159,6 +169,11 @@ const ATTR_LANGFUSE_COMPLETION_START_TIME = "langfuse.observation.completion_sta
|
|
|
159
169
|
ATTR_GEN_AI_USAGE_OUTPUT_TEXT_TOKENS,
|
|
160
170
|
ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,
|
|
161
171
|
ATTR_INSTRUCTIONS,
|
|
172
|
+
ATTR_INTERRUPTION_DETECTION_DELAY,
|
|
173
|
+
ATTR_INTERRUPTION_PREDICTION_DURATION,
|
|
174
|
+
ATTR_INTERRUPTION_PROBABILITY,
|
|
175
|
+
ATTR_INTERRUPTION_TOTAL_DURATION,
|
|
176
|
+
ATTR_IS_INTERRUPTION,
|
|
162
177
|
ATTR_JOB_ID,
|
|
163
178
|
ATTR_LANGFUSE_COMPLETION_START_TIME,
|
|
164
179
|
ATTR_LLM_METRICS,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/telemetry/trace_types.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\n// LiveKit custom attributes\nexport const ATTR_SPEECH_ID = 'lk.speech_id';\nexport const ATTR_AGENT_LABEL = 'lk.agent_label';\nexport const ATTR_START_TIME = 'lk.start_time';\nexport const ATTR_END_TIME = 'lk.end_time';\nexport const ATTR_RETRY_COUNT = 'lk.retry_count';\n\nexport const ATTR_PARTICIPANT_ID = 'lk.participant_id';\nexport const ATTR_PARTICIPANT_IDENTITY = 'lk.participant_identity';\nexport const ATTR_PARTICIPANT_KIND = 'lk.participant_kind';\n\n// session start\nexport const ATTR_JOB_ID = 'lk.job_id';\nexport const ATTR_AGENT_NAME = 'lk.agent_name';\nexport const ATTR_ROOM_NAME = 'lk.room_name';\nexport const ATTR_SESSION_OPTIONS = 'lk.session_options';\n\n// assistant turn\nexport const ATTR_USER_INPUT = 'lk.user_input';\nexport const ATTR_INSTRUCTIONS = 'lk.instructions';\nexport const ATTR_SPEECH_INTERRUPTED = 'lk.interrupted';\n\n// llm node\nexport const ATTR_CHAT_CTX = 'lk.chat_ctx';\nexport const ATTR_FUNCTION_TOOLS = 'lk.function_tools';\nexport const ATTR_RESPONSE_TEXT = 'lk.response.text';\nexport const ATTR_RESPONSE_FUNCTION_CALLS = 'lk.response.function_calls';\n\n// function tool\nexport const ATTR_FUNCTION_TOOL_NAME = 'lk.function_tool.name';\nexport const ATTR_FUNCTION_TOOL_ARGS = 'lk.function_tool.arguments';\nexport const ATTR_FUNCTION_TOOL_IS_ERROR = 'lk.function_tool.is_error';\nexport const ATTR_FUNCTION_TOOL_OUTPUT = 'lk.function_tool.output';\n\n// tts node\nexport const ATTR_TTS_INPUT_TEXT = 'lk.input_text';\nexport const ATTR_TTS_STREAMING = 'lk.tts.streaming';\nexport const ATTR_TTS_LABEL = 'lk.tts.label';\n\n// eou detection\nexport const ATTR_EOU_PROBABILITY = 'lk.eou.probability';\nexport const ATTR_EOU_UNLIKELY_THRESHOLD = 'lk.eou.unlikely_threshold';\nexport const ATTR_EOU_DELAY = 'lk.eou.endpointing_delay';\nexport const ATTR_EOU_LANGUAGE = 'lk.eou.language';\nexport const ATTR_USER_TRANSCRIPT = 'lk.user_transcript';\nexport const ATTR_TRANSCRIPT_CONFIDENCE = 'lk.transcript_confidence';\nexport const ATTR_TRANSCRIPTION_DELAY = 'lk.transcription_delay';\nexport const ATTR_END_OF_TURN_DELAY = 'lk.end_of_turn_delay';\n\n// metrics\nexport const ATTR_LLM_METRICS = 'lk.llm_metrics';\nexport const ATTR_TTS_METRICS = 'lk.tts_metrics';\nexport const ATTR_REALTIME_MODEL_METRICS = 'lk.realtime_model_metrics';\n\n// OpenTelemetry GenAI attributes\n// OpenTelemetry specification: https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/\nexport const ATTR_GEN_AI_OPERATION_NAME = 'gen_ai.operation.name';\nexport const ATTR_GEN_AI_REQUEST_MODEL = 'gen_ai.request.model';\nexport const ATTR_GEN_AI_USAGE_INPUT_TOKENS = 'gen_ai.usage.input_tokens';\nexport const ATTR_GEN_AI_USAGE_OUTPUT_TOKENS = 'gen_ai.usage.output_tokens';\n\n// Unofficial OpenTelemetry GenAI attributes, recognized by LangFuse\n// https://langfuse.com/integrations/native/opentelemetry#usage\n// but not yet in the official OpenTelemetry specification.\nexport const ATTR_GEN_AI_USAGE_INPUT_TEXT_TOKENS = 'gen_ai.usage.input_text_tokens';\nexport const ATTR_GEN_AI_USAGE_INPUT_AUDIO_TOKENS = 'gen_ai.usage.input_audio_tokens';\nexport const ATTR_GEN_AI_USAGE_INPUT_CACHED_TOKENS = 'gen_ai.usage.input_cached_tokens';\nexport const ATTR_GEN_AI_USAGE_OUTPUT_TEXT_TOKENS = 'gen_ai.usage.output_text_tokens';\nexport const ATTR_GEN_AI_USAGE_OUTPUT_AUDIO_TOKENS = 'gen_ai.usage.output_audio_tokens';\n\n// OpenTelemetry GenAI event names (for structured logging)\nexport const EVENT_GEN_AI_SYSTEM_MESSAGE = 'gen_ai.system.message';\nexport const EVENT_GEN_AI_USER_MESSAGE = 'gen_ai.user.message';\nexport const EVENT_GEN_AI_ASSISTANT_MESSAGE = 'gen_ai.assistant.message';\nexport const EVENT_GEN_AI_TOOL_MESSAGE = 'gen_ai.tool.message';\nexport const EVENT_GEN_AI_CHOICE = 'gen_ai.choice';\n\n// Exception attributes\nexport const ATTR_EXCEPTION_TRACE = 'exception.stacktrace';\nexport const ATTR_EXCEPTION_TYPE = 'exception.type';\nexport const ATTR_EXCEPTION_MESSAGE = 'exception.message';\n\n// Platform-specific attributes\nexport const ATTR_LANGFUSE_COMPLETION_START_TIME = 'langfuse.observation.completion_start_time';\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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKO,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AACxB,MAAM,gBAAgB;AACtB,MAAM,mBAAmB;AAEzB,MAAM,sBAAsB;AAC5B,MAAM,4BAA4B;AAClC,MAAM,wBAAwB;AAG9B,MAAM,cAAc;AACpB,MAAM,kBAAkB;AACxB,MAAM,iBAAiB;AACvB,MAAM,uBAAuB;AAG7B,MAAM,kBAAkB;AACxB,MAAM,oBAAoB;AAC1B,MAAM,0BAA0B;AAGhC,MAAM,gBAAgB;AACtB,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,+BAA+B;AAGrC,MAAM,0BAA0B;AAChC,MAAM,0BAA0B;AAChC,MAAM,8BAA8B;AACpC,MAAM,4BAA4B;AAGlC,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,iBAAiB;AAGvB,MAAM,uBAAuB;AAC7B,MAAM,8BAA8B;AACpC,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAC1B,MAAM,uBAAuB;AAC7B,MAAM,6BAA6B;AACnC,MAAM,2BAA2B;AACjC,MAAM,yBAAyB;AAG/B,MAAM,mBAAmB;AACzB,MAAM,mBAAmB;AACzB,MAAM,8BAA8B;AAIpC,MAAM,6BAA6B;AACnC,MAAM,4BAA4B;AAClC,MAAM,iCAAiC;AACvC,MAAM,kCAAkC;AAKxC,MAAM,sCAAsC;AAC5C,MAAM,uCAAuC;AAC7C,MAAM,wCAAwC;AAC9C,MAAM,uCAAuC;AAC7C,MAAM,wCAAwC;AAG9C,MAAM,8BAA8B;AACpC,MAAM,4BAA4B;AAClC,MAAM,iCAAiC;AACvC,MAAM,4BAA4B;AAClC,MAAM,sBAAsB;AAG5B,MAAM,uBAAuB;AAC7B,MAAM,sBAAsB;AAC5B,MAAM,yBAAyB;AAG/B,MAAM,sCAAsC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/telemetry/trace_types.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\n// LiveKit custom attributes\nexport const ATTR_SPEECH_ID = 'lk.speech_id';\nexport const ATTR_AGENT_LABEL = 'lk.agent_label';\nexport const ATTR_START_TIME = 'lk.start_time';\nexport const ATTR_END_TIME = 'lk.end_time';\nexport const ATTR_RETRY_COUNT = 'lk.retry_count';\n\nexport const ATTR_PARTICIPANT_ID = 'lk.participant_id';\nexport const ATTR_PARTICIPANT_IDENTITY = 'lk.participant_identity';\nexport const ATTR_PARTICIPANT_KIND = 'lk.participant_kind';\n\n// session start\nexport const ATTR_JOB_ID = 'lk.job_id';\nexport const ATTR_AGENT_NAME = 'lk.agent_name';\nexport const ATTR_ROOM_NAME = 'lk.room_name';\nexport const ATTR_SESSION_OPTIONS = 'lk.session_options';\n\n// assistant turn\nexport const ATTR_USER_INPUT = 'lk.user_input';\nexport const ATTR_INSTRUCTIONS = 'lk.instructions';\nexport const ATTR_SPEECH_INTERRUPTED = 'lk.interrupted';\n\n// llm node\nexport const ATTR_CHAT_CTX = 'lk.chat_ctx';\nexport const ATTR_FUNCTION_TOOLS = 'lk.function_tools';\nexport const ATTR_RESPONSE_TEXT = 'lk.response.text';\nexport const ATTR_RESPONSE_FUNCTION_CALLS = 'lk.response.function_calls';\n\n// function tool\nexport const ATTR_FUNCTION_TOOL_NAME = 'lk.function_tool.name';\nexport const ATTR_FUNCTION_TOOL_ARGS = 'lk.function_tool.arguments';\nexport const ATTR_FUNCTION_TOOL_IS_ERROR = 'lk.function_tool.is_error';\nexport const ATTR_FUNCTION_TOOL_OUTPUT = 'lk.function_tool.output';\n\n// tts node\nexport const ATTR_TTS_INPUT_TEXT = 'lk.input_text';\nexport const ATTR_TTS_STREAMING = 'lk.tts.streaming';\nexport const ATTR_TTS_LABEL = 'lk.tts.label';\n\n// eou detection\nexport const ATTR_EOU_PROBABILITY = 'lk.eou.probability';\nexport const ATTR_EOU_UNLIKELY_THRESHOLD = 'lk.eou.unlikely_threshold';\nexport const ATTR_EOU_DELAY = 'lk.eou.endpointing_delay';\nexport const ATTR_EOU_LANGUAGE = 'lk.eou.language';\nexport const ATTR_USER_TRANSCRIPT = 'lk.user_transcript';\nexport const ATTR_TRANSCRIPT_CONFIDENCE = 'lk.transcript_confidence';\nexport const ATTR_TRANSCRIPTION_DELAY = 'lk.transcription_delay';\nexport const ATTR_END_OF_TURN_DELAY = 'lk.end_of_turn_delay';\n\n// Adaptive Interruption attributes\nexport const ATTR_IS_INTERRUPTION = 'lk.is_interruption';\nexport const ATTR_INTERRUPTION_PROBABILITY = 'lk.interruption.probability';\nexport const ATTR_INTERRUPTION_TOTAL_DURATION = 'lk.interruption.total_duration';\nexport const ATTR_INTERRUPTION_PREDICTION_DURATION = 'lk.interruption.prediction_duration';\nexport const ATTR_INTERRUPTION_DETECTION_DELAY = 'lk.interruption.detection_delay';\n\n// metrics\nexport const ATTR_LLM_METRICS = 'lk.llm_metrics';\nexport const ATTR_TTS_METRICS = 'lk.tts_metrics';\nexport const ATTR_REALTIME_MODEL_METRICS = 'lk.realtime_model_metrics';\n\n// OpenTelemetry GenAI attributes\n// OpenTelemetry specification: https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/\nexport const ATTR_GEN_AI_OPERATION_NAME = 'gen_ai.operation.name';\nexport const ATTR_GEN_AI_REQUEST_MODEL = 'gen_ai.request.model';\nexport const ATTR_GEN_AI_USAGE_INPUT_TOKENS = 'gen_ai.usage.input_tokens';\nexport const ATTR_GEN_AI_USAGE_OUTPUT_TOKENS = 'gen_ai.usage.output_tokens';\n\n// Unofficial OpenTelemetry GenAI attributes, recognized by LangFuse\n// https://langfuse.com/integrations/native/opentelemetry#usage\n// but not yet in the official OpenTelemetry specification.\nexport const ATTR_GEN_AI_USAGE_INPUT_TEXT_TOKENS = 'gen_ai.usage.input_text_tokens';\nexport const ATTR_GEN_AI_USAGE_INPUT_AUDIO_TOKENS = 'gen_ai.usage.input_audio_tokens';\nexport const ATTR_GEN_AI_USAGE_INPUT_CACHED_TOKENS = 'gen_ai.usage.input_cached_tokens';\nexport const ATTR_GEN_AI_USAGE_OUTPUT_TEXT_TOKENS = 'gen_ai.usage.output_text_tokens';\nexport const ATTR_GEN_AI_USAGE_OUTPUT_AUDIO_TOKENS = 'gen_ai.usage.output_audio_tokens';\n\n// OpenTelemetry GenAI event names (for structured logging)\nexport const EVENT_GEN_AI_SYSTEM_MESSAGE = 'gen_ai.system.message';\nexport const EVENT_GEN_AI_USER_MESSAGE = 'gen_ai.user.message';\nexport const EVENT_GEN_AI_ASSISTANT_MESSAGE = 'gen_ai.assistant.message';\nexport const EVENT_GEN_AI_TOOL_MESSAGE = 'gen_ai.tool.message';\nexport const EVENT_GEN_AI_CHOICE = 'gen_ai.choice';\n\n// Exception attributes\nexport const ATTR_EXCEPTION_TRACE = 'exception.stacktrace';\nexport const ATTR_EXCEPTION_TYPE = 'exception.type';\nexport const ATTR_EXCEPTION_MESSAGE = 'exception.message';\n\n// Platform-specific attributes\nexport const ATTR_LANGFUSE_COMPLETION_START_TIME = 'langfuse.observation.completion_start_time';\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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKO,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AACxB,MAAM,gBAAgB;AACtB,MAAM,mBAAmB;AAEzB,MAAM,sBAAsB;AAC5B,MAAM,4BAA4B;AAClC,MAAM,wBAAwB;AAG9B,MAAM,cAAc;AACpB,MAAM,kBAAkB;AACxB,MAAM,iBAAiB;AACvB,MAAM,uBAAuB;AAG7B,MAAM,kBAAkB;AACxB,MAAM,oBAAoB;AAC1B,MAAM,0BAA0B;AAGhC,MAAM,gBAAgB;AACtB,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,+BAA+B;AAGrC,MAAM,0BAA0B;AAChC,MAAM,0BAA0B;AAChC,MAAM,8BAA8B;AACpC,MAAM,4BAA4B;AAGlC,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,iBAAiB;AAGvB,MAAM,uBAAuB;AAC7B,MAAM,8BAA8B;AACpC,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAC1B,MAAM,uBAAuB;AAC7B,MAAM,6BAA6B;AACnC,MAAM,2BAA2B;AACjC,MAAM,yBAAyB;AAG/B,MAAM,uBAAuB;AAC7B,MAAM,gCAAgC;AACtC,MAAM,mCAAmC;AACzC,MAAM,wCAAwC;AAC9C,MAAM,oCAAoC;AAG1C,MAAM,mBAAmB;AACzB,MAAM,mBAAmB;AACzB,MAAM,8BAA8B;AAIpC,MAAM,6BAA6B;AACnC,MAAM,4BAA4B;AAClC,MAAM,iCAAiC;AACvC,MAAM,kCAAkC;AAKxC,MAAM,sCAAsC;AAC5C,MAAM,uCAAuC;AAC7C,MAAM,wCAAwC;AAC9C,MAAM,uCAAuC;AAC7C,MAAM,wCAAwC;AAG9C,MAAM,8BAA8B;AACpC,MAAM,4BAA4B;AAClC,MAAM,iCAAiC;AACvC,MAAM,4BAA4B;AAClC,MAAM,sBAAsB;AAG5B,MAAM,uBAAuB;AAC7B,MAAM,sBAAsB;AAC5B,MAAM,yBAAyB;AAG/B,MAAM,sCAAsC;","names":[]}
|
|
@@ -32,6 +32,11 @@ export declare const ATTR_USER_TRANSCRIPT = "lk.user_transcript";
|
|
|
32
32
|
export declare const ATTR_TRANSCRIPT_CONFIDENCE = "lk.transcript_confidence";
|
|
33
33
|
export declare const ATTR_TRANSCRIPTION_DELAY = "lk.transcription_delay";
|
|
34
34
|
export declare const ATTR_END_OF_TURN_DELAY = "lk.end_of_turn_delay";
|
|
35
|
+
export declare const ATTR_IS_INTERRUPTION = "lk.is_interruption";
|
|
36
|
+
export declare const ATTR_INTERRUPTION_PROBABILITY = "lk.interruption.probability";
|
|
37
|
+
export declare const ATTR_INTERRUPTION_TOTAL_DURATION = "lk.interruption.total_duration";
|
|
38
|
+
export declare const ATTR_INTERRUPTION_PREDICTION_DURATION = "lk.interruption.prediction_duration";
|
|
39
|
+
export declare const ATTR_INTERRUPTION_DETECTION_DELAY = "lk.interruption.detection_delay";
|
|
35
40
|
export declare const ATTR_LLM_METRICS = "lk.llm_metrics";
|
|
36
41
|
export declare const ATTR_TTS_METRICS = "lk.tts_metrics";
|
|
37
42
|
export declare const ATTR_REALTIME_MODEL_METRICS = "lk.realtime_model_metrics";
|
|
@@ -32,6 +32,11 @@ export declare const ATTR_USER_TRANSCRIPT = "lk.user_transcript";
|
|
|
32
32
|
export declare const ATTR_TRANSCRIPT_CONFIDENCE = "lk.transcript_confidence";
|
|
33
33
|
export declare const ATTR_TRANSCRIPTION_DELAY = "lk.transcription_delay";
|
|
34
34
|
export declare const ATTR_END_OF_TURN_DELAY = "lk.end_of_turn_delay";
|
|
35
|
+
export declare const ATTR_IS_INTERRUPTION = "lk.is_interruption";
|
|
36
|
+
export declare const ATTR_INTERRUPTION_PROBABILITY = "lk.interruption.probability";
|
|
37
|
+
export declare const ATTR_INTERRUPTION_TOTAL_DURATION = "lk.interruption.total_duration";
|
|
38
|
+
export declare const ATTR_INTERRUPTION_PREDICTION_DURATION = "lk.interruption.prediction_duration";
|
|
39
|
+
export declare const ATTR_INTERRUPTION_DETECTION_DELAY = "lk.interruption.detection_delay";
|
|
35
40
|
export declare const ATTR_LLM_METRICS = "lk.llm_metrics";
|
|
36
41
|
export declare const ATTR_TTS_METRICS = "lk.tts_metrics";
|
|
37
42
|
export declare const ATTR_REALTIME_MODEL_METRICS = "lk.realtime_model_metrics";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace_types.d.ts","sourceRoot":"","sources":["../../src/telemetry/trace_types.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAC7C,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AACjD,eAAO,MAAM,eAAe,kBAAkB,CAAC;AAC/C,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAC3C,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAEjD,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AACvD,eAAO,MAAM,yBAAyB,4BAA4B,CAAC;AACnE,eAAO,MAAM,qBAAqB,wBAAwB,CAAC;AAG3D,eAAO,MAAM,WAAW,cAAc,CAAC;AACvC,eAAO,MAAM,eAAe,kBAAkB,CAAC;AAC/C,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAC7C,eAAO,MAAM,oBAAoB,uBAAuB,CAAC;AAGzD,eAAO,MAAM,eAAe,kBAAkB,CAAC;AAC/C,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AACnD,eAAO,MAAM,uBAAuB,mBAAmB,CAAC;AAGxD,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAC3C,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AACvD,eAAO,MAAM,kBAAkB,qBAAqB,CAAC;AACrD,eAAO,MAAM,4BAA4B,+BAA+B,CAAC;AAGzE,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAC/D,eAAO,MAAM,uBAAuB,+BAA+B,CAAC;AACpE,eAAO,MAAM,2BAA2B,8BAA8B,CAAC;AACvE,eAAO,MAAM,yBAAyB,4BAA4B,CAAC;AAGnE,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,kBAAkB,qBAAqB,CAAC;AACrD,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAG7C,eAAO,MAAM,oBAAoB,uBAAuB,CAAC;AACzD,eAAO,MAAM,2BAA2B,8BAA8B,CAAC;AACvE,eAAO,MAAM,cAAc,6BAA6B,CAAC;AACzD,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AACnD,eAAO,MAAM,oBAAoB,uBAAuB,CAAC;AACzD,eAAO,MAAM,0BAA0B,6BAA6B,CAAC;AACrE,eAAO,MAAM,wBAAwB,2BAA2B,CAAC;AACjE,eAAO,MAAM,sBAAsB,yBAAyB,CAAC;AAG7D,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AACjD,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AACjD,eAAO,MAAM,2BAA2B,8BAA8B,CAAC;AAIvE,eAAO,MAAM,0BAA0B,0BAA0B,CAAC;AAClE,eAAO,MAAM,yBAAyB,yBAAyB,CAAC;AAChE,eAAO,MAAM,8BAA8B,8BAA8B,CAAC;AAC1E,eAAO,MAAM,+BAA+B,+BAA+B,CAAC;AAK5E,eAAO,MAAM,mCAAmC,mCAAmC,CAAC;AACpF,eAAO,MAAM,oCAAoC,oCAAoC,CAAC;AACtF,eAAO,MAAM,qCAAqC,qCAAqC,CAAC;AACxF,eAAO,MAAM,oCAAoC,oCAAoC,CAAC;AACtF,eAAO,MAAM,qCAAqC,qCAAqC,CAAC;AAGxF,eAAO,MAAM,2BAA2B,0BAA0B,CAAC;AACnE,eAAO,MAAM,yBAAyB,wBAAwB,CAAC;AAC/D,eAAO,MAAM,8BAA8B,6BAA6B,CAAC;AACzE,eAAO,MAAM,yBAAyB,wBAAwB,CAAC;AAC/D,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AAGnD,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAC3D,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AACpD,eAAO,MAAM,sBAAsB,sBAAsB,CAAC;AAG1D,eAAO,MAAM,mCAAmC,+CAA+C,CAAC"}
|
|
1
|
+
{"version":3,"file":"trace_types.d.ts","sourceRoot":"","sources":["../../src/telemetry/trace_types.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,6 +32,11 @@ const ATTR_USER_TRANSCRIPT = "lk.user_transcript";
|
|
|
32
32
|
const ATTR_TRANSCRIPT_CONFIDENCE = "lk.transcript_confidence";
|
|
33
33
|
const ATTR_TRANSCRIPTION_DELAY = "lk.transcription_delay";
|
|
34
34
|
const ATTR_END_OF_TURN_DELAY = "lk.end_of_turn_delay";
|
|
35
|
+
const ATTR_IS_INTERRUPTION = "lk.is_interruption";
|
|
36
|
+
const ATTR_INTERRUPTION_PROBABILITY = "lk.interruption.probability";
|
|
37
|
+
const ATTR_INTERRUPTION_TOTAL_DURATION = "lk.interruption.total_duration";
|
|
38
|
+
const ATTR_INTERRUPTION_PREDICTION_DURATION = "lk.interruption.prediction_duration";
|
|
39
|
+
const ATTR_INTERRUPTION_DETECTION_DELAY = "lk.interruption.detection_delay";
|
|
35
40
|
const ATTR_LLM_METRICS = "lk.llm_metrics";
|
|
36
41
|
const ATTR_TTS_METRICS = "lk.tts_metrics";
|
|
37
42
|
const ATTR_REALTIME_MODEL_METRICS = "lk.realtime_model_metrics";
|
|
@@ -81,6 +86,11 @@ export {
|
|
|
81
86
|
ATTR_GEN_AI_USAGE_OUTPUT_TEXT_TOKENS,
|
|
82
87
|
ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,
|
|
83
88
|
ATTR_INSTRUCTIONS,
|
|
89
|
+
ATTR_INTERRUPTION_DETECTION_DELAY,
|
|
90
|
+
ATTR_INTERRUPTION_PREDICTION_DURATION,
|
|
91
|
+
ATTR_INTERRUPTION_PROBABILITY,
|
|
92
|
+
ATTR_INTERRUPTION_TOTAL_DURATION,
|
|
93
|
+
ATTR_IS_INTERRUPTION,
|
|
84
94
|
ATTR_JOB_ID,
|
|
85
95
|
ATTR_LANGFUSE_COMPLETION_START_TIME,
|
|
86
96
|
ATTR_LLM_METRICS,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/telemetry/trace_types.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\n// LiveKit custom attributes\nexport const ATTR_SPEECH_ID = 'lk.speech_id';\nexport const ATTR_AGENT_LABEL = 'lk.agent_label';\nexport const ATTR_START_TIME = 'lk.start_time';\nexport const ATTR_END_TIME = 'lk.end_time';\nexport const ATTR_RETRY_COUNT = 'lk.retry_count';\n\nexport const ATTR_PARTICIPANT_ID = 'lk.participant_id';\nexport const ATTR_PARTICIPANT_IDENTITY = 'lk.participant_identity';\nexport const ATTR_PARTICIPANT_KIND = 'lk.participant_kind';\n\n// session start\nexport const ATTR_JOB_ID = 'lk.job_id';\nexport const ATTR_AGENT_NAME = 'lk.agent_name';\nexport const ATTR_ROOM_NAME = 'lk.room_name';\nexport const ATTR_SESSION_OPTIONS = 'lk.session_options';\n\n// assistant turn\nexport const ATTR_USER_INPUT = 'lk.user_input';\nexport const ATTR_INSTRUCTIONS = 'lk.instructions';\nexport const ATTR_SPEECH_INTERRUPTED = 'lk.interrupted';\n\n// llm node\nexport const ATTR_CHAT_CTX = 'lk.chat_ctx';\nexport const ATTR_FUNCTION_TOOLS = 'lk.function_tools';\nexport const ATTR_RESPONSE_TEXT = 'lk.response.text';\nexport const ATTR_RESPONSE_FUNCTION_CALLS = 'lk.response.function_calls';\n\n// function tool\nexport const ATTR_FUNCTION_TOOL_NAME = 'lk.function_tool.name';\nexport const ATTR_FUNCTION_TOOL_ARGS = 'lk.function_tool.arguments';\nexport const ATTR_FUNCTION_TOOL_IS_ERROR = 'lk.function_tool.is_error';\nexport const ATTR_FUNCTION_TOOL_OUTPUT = 'lk.function_tool.output';\n\n// tts node\nexport const ATTR_TTS_INPUT_TEXT = 'lk.input_text';\nexport const ATTR_TTS_STREAMING = 'lk.tts.streaming';\nexport const ATTR_TTS_LABEL = 'lk.tts.label';\n\n// eou detection\nexport const ATTR_EOU_PROBABILITY = 'lk.eou.probability';\nexport const ATTR_EOU_UNLIKELY_THRESHOLD = 'lk.eou.unlikely_threshold';\nexport const ATTR_EOU_DELAY = 'lk.eou.endpointing_delay';\nexport const ATTR_EOU_LANGUAGE = 'lk.eou.language';\nexport const ATTR_USER_TRANSCRIPT = 'lk.user_transcript';\nexport const ATTR_TRANSCRIPT_CONFIDENCE = 'lk.transcript_confidence';\nexport const ATTR_TRANSCRIPTION_DELAY = 'lk.transcription_delay';\nexport const ATTR_END_OF_TURN_DELAY = 'lk.end_of_turn_delay';\n\n// metrics\nexport const ATTR_LLM_METRICS = 'lk.llm_metrics';\nexport const ATTR_TTS_METRICS = 'lk.tts_metrics';\nexport const ATTR_REALTIME_MODEL_METRICS = 'lk.realtime_model_metrics';\n\n// OpenTelemetry GenAI attributes\n// OpenTelemetry specification: https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/\nexport const ATTR_GEN_AI_OPERATION_NAME = 'gen_ai.operation.name';\nexport const ATTR_GEN_AI_REQUEST_MODEL = 'gen_ai.request.model';\nexport const ATTR_GEN_AI_USAGE_INPUT_TOKENS = 'gen_ai.usage.input_tokens';\nexport const ATTR_GEN_AI_USAGE_OUTPUT_TOKENS = 'gen_ai.usage.output_tokens';\n\n// Unofficial OpenTelemetry GenAI attributes, recognized by LangFuse\n// https://langfuse.com/integrations/native/opentelemetry#usage\n// but not yet in the official OpenTelemetry specification.\nexport const ATTR_GEN_AI_USAGE_INPUT_TEXT_TOKENS = 'gen_ai.usage.input_text_tokens';\nexport const ATTR_GEN_AI_USAGE_INPUT_AUDIO_TOKENS = 'gen_ai.usage.input_audio_tokens';\nexport const ATTR_GEN_AI_USAGE_INPUT_CACHED_TOKENS = 'gen_ai.usage.input_cached_tokens';\nexport const ATTR_GEN_AI_USAGE_OUTPUT_TEXT_TOKENS = 'gen_ai.usage.output_text_tokens';\nexport const ATTR_GEN_AI_USAGE_OUTPUT_AUDIO_TOKENS = 'gen_ai.usage.output_audio_tokens';\n\n// OpenTelemetry GenAI event names (for structured logging)\nexport const EVENT_GEN_AI_SYSTEM_MESSAGE = 'gen_ai.system.message';\nexport const EVENT_GEN_AI_USER_MESSAGE = 'gen_ai.user.message';\nexport const EVENT_GEN_AI_ASSISTANT_MESSAGE = 'gen_ai.assistant.message';\nexport const EVENT_GEN_AI_TOOL_MESSAGE = 'gen_ai.tool.message';\nexport const EVENT_GEN_AI_CHOICE = 'gen_ai.choice';\n\n// Exception attributes\nexport const ATTR_EXCEPTION_TRACE = 'exception.stacktrace';\nexport const ATTR_EXCEPTION_TYPE = 'exception.type';\nexport const ATTR_EXCEPTION_MESSAGE = 'exception.message';\n\n// Platform-specific attributes\nexport const ATTR_LANGFUSE_COMPLETION_START_TIME = 'langfuse.observation.completion_start_time';\n"],"mappings":"AAKO,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AACxB,MAAM,gBAAgB;AACtB,MAAM,mBAAmB;AAEzB,MAAM,sBAAsB;AAC5B,MAAM,4BAA4B;AAClC,MAAM,wBAAwB;AAG9B,MAAM,cAAc;AACpB,MAAM,kBAAkB;AACxB,MAAM,iBAAiB;AACvB,MAAM,uBAAuB;AAG7B,MAAM,kBAAkB;AACxB,MAAM,oBAAoB;AAC1B,MAAM,0BAA0B;AAGhC,MAAM,gBAAgB;AACtB,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,+BAA+B;AAGrC,MAAM,0BAA0B;AAChC,MAAM,0BAA0B;AAChC,MAAM,8BAA8B;AACpC,MAAM,4BAA4B;AAGlC,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,iBAAiB;AAGvB,MAAM,uBAAuB;AAC7B,MAAM,8BAA8B;AACpC,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAC1B,MAAM,uBAAuB;AAC7B,MAAM,6BAA6B;AACnC,MAAM,2BAA2B;AACjC,MAAM,yBAAyB;AAG/B,MAAM,mBAAmB;AACzB,MAAM,mBAAmB;AACzB,MAAM,8BAA8B;AAIpC,MAAM,6BAA6B;AACnC,MAAM,4BAA4B;AAClC,MAAM,iCAAiC;AACvC,MAAM,kCAAkC;AAKxC,MAAM,sCAAsC;AAC5C,MAAM,uCAAuC;AAC7C,MAAM,wCAAwC;AAC9C,MAAM,uCAAuC;AAC7C,MAAM,wCAAwC;AAG9C,MAAM,8BAA8B;AACpC,MAAM,4BAA4B;AAClC,MAAM,iCAAiC;AACvC,MAAM,4BAA4B;AAClC,MAAM,sBAAsB;AAG5B,MAAM,uBAAuB;AAC7B,MAAM,sBAAsB;AAC5B,MAAM,yBAAyB;AAG/B,MAAM,sCAAsC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/telemetry/trace_types.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\n// LiveKit custom attributes\nexport const ATTR_SPEECH_ID = 'lk.speech_id';\nexport const ATTR_AGENT_LABEL = 'lk.agent_label';\nexport const ATTR_START_TIME = 'lk.start_time';\nexport const ATTR_END_TIME = 'lk.end_time';\nexport const ATTR_RETRY_COUNT = 'lk.retry_count';\n\nexport const ATTR_PARTICIPANT_ID = 'lk.participant_id';\nexport const ATTR_PARTICIPANT_IDENTITY = 'lk.participant_identity';\nexport const ATTR_PARTICIPANT_KIND = 'lk.participant_kind';\n\n// session start\nexport const ATTR_JOB_ID = 'lk.job_id';\nexport const ATTR_AGENT_NAME = 'lk.agent_name';\nexport const ATTR_ROOM_NAME = 'lk.room_name';\nexport const ATTR_SESSION_OPTIONS = 'lk.session_options';\n\n// assistant turn\nexport const ATTR_USER_INPUT = 'lk.user_input';\nexport const ATTR_INSTRUCTIONS = 'lk.instructions';\nexport const ATTR_SPEECH_INTERRUPTED = 'lk.interrupted';\n\n// llm node\nexport const ATTR_CHAT_CTX = 'lk.chat_ctx';\nexport const ATTR_FUNCTION_TOOLS = 'lk.function_tools';\nexport const ATTR_RESPONSE_TEXT = 'lk.response.text';\nexport const ATTR_RESPONSE_FUNCTION_CALLS = 'lk.response.function_calls';\n\n// function tool\nexport const ATTR_FUNCTION_TOOL_NAME = 'lk.function_tool.name';\nexport const ATTR_FUNCTION_TOOL_ARGS = 'lk.function_tool.arguments';\nexport const ATTR_FUNCTION_TOOL_IS_ERROR = 'lk.function_tool.is_error';\nexport const ATTR_FUNCTION_TOOL_OUTPUT = 'lk.function_tool.output';\n\n// tts node\nexport const ATTR_TTS_INPUT_TEXT = 'lk.input_text';\nexport const ATTR_TTS_STREAMING = 'lk.tts.streaming';\nexport const ATTR_TTS_LABEL = 'lk.tts.label';\n\n// eou detection\nexport const ATTR_EOU_PROBABILITY = 'lk.eou.probability';\nexport const ATTR_EOU_UNLIKELY_THRESHOLD = 'lk.eou.unlikely_threshold';\nexport const ATTR_EOU_DELAY = 'lk.eou.endpointing_delay';\nexport const ATTR_EOU_LANGUAGE = 'lk.eou.language';\nexport const ATTR_USER_TRANSCRIPT = 'lk.user_transcript';\nexport const ATTR_TRANSCRIPT_CONFIDENCE = 'lk.transcript_confidence';\nexport const ATTR_TRANSCRIPTION_DELAY = 'lk.transcription_delay';\nexport const ATTR_END_OF_TURN_DELAY = 'lk.end_of_turn_delay';\n\n// Adaptive Interruption attributes\nexport const ATTR_IS_INTERRUPTION = 'lk.is_interruption';\nexport const ATTR_INTERRUPTION_PROBABILITY = 'lk.interruption.probability';\nexport const ATTR_INTERRUPTION_TOTAL_DURATION = 'lk.interruption.total_duration';\nexport const ATTR_INTERRUPTION_PREDICTION_DURATION = 'lk.interruption.prediction_duration';\nexport const ATTR_INTERRUPTION_DETECTION_DELAY = 'lk.interruption.detection_delay';\n\n// metrics\nexport const ATTR_LLM_METRICS = 'lk.llm_metrics';\nexport const ATTR_TTS_METRICS = 'lk.tts_metrics';\nexport const ATTR_REALTIME_MODEL_METRICS = 'lk.realtime_model_metrics';\n\n// OpenTelemetry GenAI attributes\n// OpenTelemetry specification: https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/\nexport const ATTR_GEN_AI_OPERATION_NAME = 'gen_ai.operation.name';\nexport const ATTR_GEN_AI_REQUEST_MODEL = 'gen_ai.request.model';\nexport const ATTR_GEN_AI_USAGE_INPUT_TOKENS = 'gen_ai.usage.input_tokens';\nexport const ATTR_GEN_AI_USAGE_OUTPUT_TOKENS = 'gen_ai.usage.output_tokens';\n\n// Unofficial OpenTelemetry GenAI attributes, recognized by LangFuse\n// https://langfuse.com/integrations/native/opentelemetry#usage\n// but not yet in the official OpenTelemetry specification.\nexport const ATTR_GEN_AI_USAGE_INPUT_TEXT_TOKENS = 'gen_ai.usage.input_text_tokens';\nexport const ATTR_GEN_AI_USAGE_INPUT_AUDIO_TOKENS = 'gen_ai.usage.input_audio_tokens';\nexport const ATTR_GEN_AI_USAGE_INPUT_CACHED_TOKENS = 'gen_ai.usage.input_cached_tokens';\nexport const ATTR_GEN_AI_USAGE_OUTPUT_TEXT_TOKENS = 'gen_ai.usage.output_text_tokens';\nexport const ATTR_GEN_AI_USAGE_OUTPUT_AUDIO_TOKENS = 'gen_ai.usage.output_audio_tokens';\n\n// OpenTelemetry GenAI event names (for structured logging)\nexport const EVENT_GEN_AI_SYSTEM_MESSAGE = 'gen_ai.system.message';\nexport const EVENT_GEN_AI_USER_MESSAGE = 'gen_ai.user.message';\nexport const EVENT_GEN_AI_ASSISTANT_MESSAGE = 'gen_ai.assistant.message';\nexport const EVENT_GEN_AI_TOOL_MESSAGE = 'gen_ai.tool.message';\nexport const EVENT_GEN_AI_CHOICE = 'gen_ai.choice';\n\n// Exception attributes\nexport const ATTR_EXCEPTION_TRACE = 'exception.stacktrace';\nexport const ATTR_EXCEPTION_TYPE = 'exception.type';\nexport const ATTR_EXCEPTION_MESSAGE = 'exception.message';\n\n// Platform-specific attributes\nexport const ATTR_LANGFUSE_COMPLETION_START_TIME = 'langfuse.observation.completion_start_time';\n"],"mappings":"AAKO,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AACxB,MAAM,gBAAgB;AACtB,MAAM,mBAAmB;AAEzB,MAAM,sBAAsB;AAC5B,MAAM,4BAA4B;AAClC,MAAM,wBAAwB;AAG9B,MAAM,cAAc;AACpB,MAAM,kBAAkB;AACxB,MAAM,iBAAiB;AACvB,MAAM,uBAAuB;AAG7B,MAAM,kBAAkB;AACxB,MAAM,oBAAoB;AAC1B,MAAM,0BAA0B;AAGhC,MAAM,gBAAgB;AACtB,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,+BAA+B;AAGrC,MAAM,0BAA0B;AAChC,MAAM,0BAA0B;AAChC,MAAM,8BAA8B;AACpC,MAAM,4BAA4B;AAGlC,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,iBAAiB;AAGvB,MAAM,uBAAuB;AAC7B,MAAM,8BAA8B;AACpC,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAC1B,MAAM,uBAAuB;AAC7B,MAAM,6BAA6B;AACnC,MAAM,2BAA2B;AACjC,MAAM,yBAAyB;AAG/B,MAAM,uBAAuB;AAC7B,MAAM,gCAAgC;AACtC,MAAM,mCAAmC;AACzC,MAAM,wCAAwC;AAC9C,MAAM,oCAAoC;AAG1C,MAAM,mBAAmB;AACzB,MAAM,mBAAmB;AACzB,MAAM,8BAA8B;AAIpC,MAAM,6BAA6B;AACnC,MAAM,4BAA4B;AAClC,MAAM,iCAAiC;AACvC,MAAM,kCAAkC;AAKxC,MAAM,sCAAsC;AAC5C,MAAM,uCAAuC;AAC7C,MAAM,wCAAwC;AAC9C,MAAM,uCAAuC;AAC7C,MAAM,wCAAwC;AAG9C,MAAM,8BAA8B;AACpC,MAAM,4BAA4B;AAClC,MAAM,iCAAiC;AACvC,MAAM,4BAA4B;AAClC,MAAM,sBAAsB;AAG5B,MAAM,uBAAuB;AAC7B,MAAM,sBAAsB;AAC5B,MAAM,yBAAyB;AAG/B,MAAM,sCAAsC;","names":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var ws_transport_exports = {};
|
|
30
|
+
__export(ws_transport_exports, {
|
|
31
|
+
webSocketStream: () => webSocketStream
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(ws_transport_exports);
|
|
34
|
+
var import_node_stream = require("node:stream");
|
|
35
|
+
var import_ws = __toESM(require("ws"), 1);
|
|
36
|
+
function webSocketStream(wsUrl) {
|
|
37
|
+
const ws = new import_ws.default(wsUrl);
|
|
38
|
+
const duplex = (0, import_ws.createWebSocketStream)(ws);
|
|
39
|
+
duplex.on("error", console.error);
|
|
40
|
+
duplex.on("end", () => {
|
|
41
|
+
duplex.end();
|
|
42
|
+
});
|
|
43
|
+
const writable = import_node_stream.Writable.toWeb(duplex);
|
|
44
|
+
const readable = import_node_stream.Readable.toWeb(duplex);
|
|
45
|
+
return { readable, writable, close: ws.close };
|
|
46
|
+
}
|
|
47
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
48
|
+
0 && (module.exports = {
|
|
49
|
+
webSocketStream
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=ws_transport.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/ws_transport.ts"],"sourcesContent":["import { Readable, Writable } from 'node:stream';\nimport WebSocket, { createWebSocketStream } from 'ws';\n\nexport function webSocketStream(wsUrl: string) {\n const ws = new WebSocket(wsUrl);\n const duplex = createWebSocketStream(ws);\n duplex.on('error', console.error);\n\n // End the write side when the read side ends to properly close the stream.\n // This is needed because Readable.toWeb() waits for both sides of the duplex\n // to close before signaling done on the ReadableStream.\n duplex.on('end', () => {\n duplex.end();\n });\n\n // Convert the writable side\n const writable = Writable.toWeb(duplex);\n // Convert the readable side\n const readable = Readable.toWeb(duplex);\n\n return { readable, writable, close: ws.close };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAmC;AACnC,gBAAiD;AAE1C,SAAS,gBAAgB,OAAe;AAC7C,QAAM,KAAK,IAAI,UAAAA,QAAU,KAAK;AAC9B,QAAM,aAAS,iCAAsB,EAAE;AACvC,SAAO,GAAG,SAAS,QAAQ,KAAK;AAKhC,SAAO,GAAG,OAAO,MAAM;AACrB,WAAO,IAAI;AAAA,EACb,CAAC;AAGD,QAAM,WAAW,4BAAS,MAAM,MAAM;AAEtC,QAAM,WAAW,4BAAS,MAAM,MAAM;AAEtC,SAAO,EAAE,UAAU,UAAU,OAAO,GAAG,MAAM;AAC/C;","names":["WebSocket"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
3
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
4
|
+
export declare function webSocketStream(wsUrl: string): {
|
|
5
|
+
readable: import("stream/web").ReadableStream<any>;
|
|
6
|
+
writable: import("stream/web").WritableStream<any>;
|
|
7
|
+
close: (code?: number | undefined, data?: string | Buffer | undefined) => void;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=ws_transport.d.ts.map
|