@livekit/agents 1.0.14 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/dist/cli.cjs +12 -12
  2. package/dist/cli.cjs.map +1 -1
  3. package/dist/cli.d.cts +3 -3
  4. package/dist/cli.d.ts +3 -3
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +13 -13
  7. package/dist/cli.js.map +1 -1
  8. package/dist/inference/stt.cjs.map +1 -1
  9. package/dist/inference/stt.d.ts.map +1 -1
  10. package/dist/inference/stt.js +1 -1
  11. package/dist/inference/stt.js.map +1 -1
  12. package/dist/inference/tts.cjs.map +1 -1
  13. package/dist/inference/tts.d.cts +2 -1
  14. package/dist/inference/tts.d.ts +2 -1
  15. package/dist/inference/tts.d.ts.map +1 -1
  16. package/dist/inference/tts.js +1 -5
  17. package/dist/inference/tts.js.map +1 -1
  18. package/dist/llm/chat_context.cjs +78 -0
  19. package/dist/llm/chat_context.cjs.map +1 -1
  20. package/dist/llm/chat_context.d.cts +16 -0
  21. package/dist/llm/chat_context.d.ts +16 -0
  22. package/dist/llm/chat_context.d.ts.map +1 -1
  23. package/dist/llm/chat_context.js +78 -0
  24. package/dist/llm/chat_context.js.map +1 -1
  25. package/dist/llm/chat_context.test.cjs +531 -0
  26. package/dist/llm/chat_context.test.cjs.map +1 -1
  27. package/dist/llm/chat_context.test.js +531 -0
  28. package/dist/llm/chat_context.test.js.map +1 -1
  29. package/dist/llm/tool_context.cjs +43 -2
  30. package/dist/llm/tool_context.cjs.map +1 -1
  31. package/dist/llm/tool_context.d.cts +39 -11
  32. package/dist/llm/tool_context.d.ts +39 -11
  33. package/dist/llm/tool_context.d.ts.map +1 -1
  34. package/dist/llm/tool_context.js +42 -3
  35. package/dist/llm/tool_context.js.map +1 -1
  36. package/dist/llm/tool_context.test.cjs +197 -0
  37. package/dist/llm/tool_context.test.cjs.map +1 -1
  38. package/dist/llm/tool_context.test.js +175 -0
  39. package/dist/llm/tool_context.test.js.map +1 -1
  40. package/dist/llm/utils.cjs +17 -11
  41. package/dist/llm/utils.cjs.map +1 -1
  42. package/dist/llm/utils.d.cts +1 -2
  43. package/dist/llm/utils.d.ts +1 -2
  44. package/dist/llm/utils.d.ts.map +1 -1
  45. package/dist/llm/utils.js +17 -11
  46. package/dist/llm/utils.js.map +1 -1
  47. package/dist/llm/zod-utils.cjs +99 -0
  48. package/dist/llm/zod-utils.cjs.map +1 -0
  49. package/dist/llm/zod-utils.d.cts +65 -0
  50. package/dist/llm/zod-utils.d.ts +65 -0
  51. package/dist/llm/zod-utils.d.ts.map +1 -0
  52. package/dist/llm/zod-utils.js +61 -0
  53. package/dist/llm/zod-utils.js.map +1 -0
  54. package/dist/llm/zod-utils.test.cjs +389 -0
  55. package/dist/llm/zod-utils.test.cjs.map +1 -0
  56. package/dist/llm/zod-utils.test.js +372 -0
  57. package/dist/llm/zod-utils.test.js.map +1 -0
  58. package/dist/metrics/base.cjs.map +1 -1
  59. package/dist/metrics/base.d.cts +7 -0
  60. package/dist/metrics/base.d.ts +7 -0
  61. package/dist/metrics/base.d.ts.map +1 -1
  62. package/dist/stt/stt.cjs +1 -0
  63. package/dist/stt/stt.cjs.map +1 -1
  64. package/dist/stt/stt.d.cts +7 -1
  65. package/dist/stt/stt.d.ts +7 -1
  66. package/dist/stt/stt.d.ts.map +1 -1
  67. package/dist/stt/stt.js +1 -0
  68. package/dist/stt/stt.js.map +1 -1
  69. package/dist/vad.cjs +16 -0
  70. package/dist/vad.cjs.map +1 -1
  71. package/dist/vad.d.cts +6 -0
  72. package/dist/vad.d.ts +6 -0
  73. package/dist/vad.d.ts.map +1 -1
  74. package/dist/vad.js +16 -0
  75. package/dist/vad.js.map +1 -1
  76. package/dist/voice/agent_activity.cjs +83 -8
  77. package/dist/voice/agent_activity.cjs.map +1 -1
  78. package/dist/voice/agent_activity.d.cts +6 -2
  79. package/dist/voice/agent_activity.d.ts +6 -2
  80. package/dist/voice/agent_activity.d.ts.map +1 -1
  81. package/dist/voice/agent_activity.js +83 -8
  82. package/dist/voice/agent_activity.js.map +1 -1
  83. package/dist/voice/agent_session.cjs +3 -2
  84. package/dist/voice/agent_session.cjs.map +1 -1
  85. package/dist/voice/agent_session.d.cts +2 -1
  86. package/dist/voice/agent_session.d.ts +2 -1
  87. package/dist/voice/agent_session.d.ts.map +1 -1
  88. package/dist/voice/agent_session.js +3 -2
  89. package/dist/voice/agent_session.js.map +1 -1
  90. package/dist/voice/audio_recognition.cjs +138 -16
  91. package/dist/voice/audio_recognition.cjs.map +1 -1
  92. package/dist/voice/audio_recognition.d.cts +11 -0
  93. package/dist/voice/audio_recognition.d.ts +11 -0
  94. package/dist/voice/audio_recognition.d.ts.map +1 -1
  95. package/dist/voice/audio_recognition.js +138 -16
  96. package/dist/voice/audio_recognition.js.map +1 -1
  97. package/dist/voice/generation.cjs +8 -3
  98. package/dist/voice/generation.cjs.map +1 -1
  99. package/dist/voice/generation.d.ts.map +1 -1
  100. package/dist/voice/generation.js +8 -3
  101. package/dist/voice/generation.js.map +1 -1
  102. package/dist/voice/room_io/_input.cjs.map +1 -1
  103. package/dist/voice/room_io/_input.d.ts.map +1 -1
  104. package/dist/voice/room_io/_input.js +0 -1
  105. package/dist/voice/room_io/_input.js.map +1 -1
  106. package/dist/worker.cjs +17 -11
  107. package/dist/worker.cjs.map +1 -1
  108. package/dist/worker.d.cts +16 -9
  109. package/dist/worker.d.ts +16 -9
  110. package/dist/worker.d.ts.map +1 -1
  111. package/dist/worker.js +16 -12
  112. package/dist/worker.js.map +1 -1
  113. package/package.json +5 -4
  114. package/src/cli.ts +17 -17
  115. package/src/inference/stt.ts +2 -1
  116. package/src/inference/tts.ts +2 -5
  117. package/src/llm/__snapshots__/zod-utils.test.ts.snap +341 -0
  118. package/src/llm/chat_context.test.ts +607 -0
  119. package/src/llm/chat_context.ts +106 -0
  120. package/src/llm/tool_context.test.ts +210 -1
  121. package/src/llm/tool_context.ts +101 -17
  122. package/src/llm/utils.ts +18 -15
  123. package/src/llm/zod-utils.test.ts +476 -0
  124. package/src/llm/zod-utils.ts +144 -0
  125. package/src/metrics/base.ts +7 -0
  126. package/src/stt/stt.ts +6 -0
  127. package/src/vad.ts +18 -0
  128. package/src/voice/agent_activity.ts +119 -9
  129. package/src/voice/agent_session.ts +3 -1
  130. package/src/voice/audio_recognition.ts +235 -57
  131. package/src/voice/generation.ts +8 -3
  132. package/src/voice/room_io/_input.ts +1 -1
  133. package/src/worker.ts +29 -18
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/llm/chat_context.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { describe, expect, it } from 'vitest';\nimport {\n type AudioContent,\n ChatContext,\n type ChatItem,\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n type ImageContent,\n ReadonlyChatContext,\n} from './chat_context.js';\n\ndescribe('ChatContext.toJSON', () => {\n it('should match snapshot for empty context', () => {\n const context = new ChatContext();\n expect(context.toJSON()).toMatchSnapshot();\n });\n\n it('should match snapshot for simple conversation', () => {\n const context = new ChatContext();\n\n context.addMessage({\n id: 'msg_system_1',\n role: 'system',\n content: 'You are a helpful assistant.',\n createdAt: 1000000000,\n });\n\n context.addMessage({\n id: 'msg_user_1',\n role: 'user',\n content: 'Hello, how are you?',\n createdAt: 1000000001,\n });\n\n context.addMessage({\n id: 'msg_assistant_1',\n role: 'assistant',\n content: \"I'm doing well, thank you! How can I help you today?\",\n createdAt: 1000000002,\n });\n\n expect(context.toJSON()).toMatchSnapshot('simple-conversation-no-timestamps');\n\n expect(context.toJSON({ excludeTimestamp: false })).toMatchSnapshot(\n 'simple-conversation-with-timestamps',\n );\n });\n\n it('should match snapshot for multimodal content', () => {\n const context = new ChatContext();\n\n const imageContent: ImageContent = {\n id: 'img_test_1',\n type: 'image_content',\n image: 'https://example.com/test-image.jpg',\n inferenceDetail: 'high',\n inferenceWidth: 1024,\n inferenceHeight: 768,\n mimeType: 'image/jpeg',\n _cache: {},\n };\n\n const audioContent: AudioContent = {\n type: 'audio_content',\n frame: [], // This won't be included in JSON\n transcript: 'This is a test audio transcript',\n };\n\n context.addMessage({\n id: 'msg_user_2',\n role: 'user',\n content: [\n 'Check out this image and audio:',\n imageContent,\n audioContent,\n 'What do you think?',\n ],\n createdAt: 2000000000,\n });\n\n expect(context.toJSON()).toMatchSnapshot('multimodal-default-exclusions');\n\n expect(\n context.toJSON({\n excludeImage: false,\n excludeAudio: true,\n }),\n ).toMatchSnapshot('multimodal-with-images-only');\n\n expect(\n context.toJSON({\n excludeImage: true,\n excludeAudio: false,\n }),\n ).toMatchSnapshot('multimodal-with-audio-only');\n\n expect(\n context.toJSON({\n excludeImage: false,\n excludeAudio: false,\n excludeTimestamp: false,\n }),\n ).toMatchSnapshot('multimodal-full-content');\n });\n\n it('should match snapshot for function calls', () => {\n const context = new ChatContext();\n\n context.addMessage({\n id: 'msg_user_3',\n role: 'user',\n content: \"What's the weather in Paris?\",\n createdAt: 3000000000,\n });\n\n const functionCall = new FunctionCall({\n id: 'func_call_1',\n callId: 'call_weather_123',\n name: 'get_weather',\n args: '{\"location\": \"Paris, France\", \"unit\": \"celsius\"}',\n createdAt: 3000000001,\n });\n context.insert(functionCall);\n\n const functionOutput = new FunctionCallOutput({\n id: 'func_output_1',\n callId: 'call_weather_123',\n name: 'get_weather',\n output: '{\"temperature\": 22, \"condition\": \"partly cloudy\", \"humidity\": 65}',\n isError: false,\n createdAt: 3000000002,\n });\n context.insert(functionOutput);\n\n context.addMessage({\n id: 'msg_assistant_2',\n role: 'assistant',\n content: 'The weather in Paris is currently 22°C and partly cloudy with 65% humidity.',\n createdAt: 3000000003,\n });\n\n expect(context.toJSON()).toMatchSnapshot('conversation-with-function-calls');\n\n expect(\n context.toJSON({\n excludeFunctionCall: true,\n }),\n ).toMatchSnapshot('conversation-without-function-calls');\n\n expect(\n context.toJSON({\n excludeTimestamp: false,\n }),\n ).toMatchSnapshot('conversation-with-function-calls-and-timestamps');\n });\n\n it('should match snapshot for edge cases', () => {\n const context = new ChatContext();\n\n context.addMessage({\n id: 'msg_empty_1',\n role: 'user',\n content: [],\n createdAt: 5000000000,\n });\n\n const silentAudio: AudioContent = {\n type: 'audio_content',\n frame: [],\n transcript: undefined,\n };\n\n context.addMessage({\n id: 'msg_silent_audio',\n role: 'user',\n content: [silentAudio],\n createdAt: 5000000001,\n });\n\n context.addMessage({\n id: 'msg_multi_text',\n role: 'assistant',\n content: ['Part 1. ', 'Part 2. ', 'Part 3.'],\n createdAt: 5000000002,\n });\n\n const minimalCall = new FunctionCall({\n id: 'func_minimal',\n callId: 'minimal',\n name: 'test',\n args: '{}',\n createdAt: 5000000003,\n });\n context.insert(minimalCall);\n\n const namelessOutput = new FunctionCallOutput({\n id: 'func_output_nameless',\n callId: 'minimal',\n output: 'OK',\n isError: false,\n createdAt: 5000000004,\n });\n context.insert(namelessOutput);\n\n context.addMessage({\n id: 'msg_special_chars',\n role: 'user',\n content:\n 'Test with special chars: \\n\\t\\r \"quotes\" \\'apostrophes\\' \\\\backslashes\\\\ {braces} [brackets]',\n createdAt: 5000000005,\n });\n\n expect(context.toJSON()).toMatchSnapshot('edge-cases-default');\n expect(\n context.toJSON({\n excludeTimestamp: false,\n excludeAudio: false,\n }),\n ).toMatchSnapshot('edge-cases-with-details');\n });\n\n it('should match snapshot for message property variations', () => {\n const context = new ChatContext();\n\n context.addMessage({\n id: 'custom-message-id-123',\n role: 'user',\n content: 'Message with custom ID',\n createdAt: 6000000000,\n });\n\n context.addMessage({\n id: 'msg_interrupted',\n role: 'assistant',\n content: 'This response was interrupted...',\n interrupted: true,\n createdAt: 6000000001,\n });\n\n context.addMessage({\n id: 'msg_dev_2',\n role: 'developer',\n content: 'Developer message',\n createdAt: 6000000002,\n });\n\n context.addMessage({\n id: 'msg_system_3',\n role: 'system',\n content: 'System message',\n createdAt: 6000000003,\n });\n\n const detailedImage: ImageContent = {\n id: 'img_detailed',\n type: 'image_content',\n image: 'https://example.com/image.jpg',\n inferenceDetail: 'low',\n inferenceWidth: 512,\n inferenceHeight: 512,\n mimeType: 'image/png',\n _cache: { cached: true },\n };\n\n context.addMessage({\n id: 'msg_with_image',\n role: 'user',\n content: ['Image with all properties:', detailedImage],\n createdAt: 6000000004,\n });\n\n expect(context.toJSON()).toMatchSnapshot('message-properties-default');\n expect(\n context.toJSON({\n excludeImage: false,\n excludeTimestamp: false,\n }),\n ).toMatchSnapshot('message-properties-full');\n });\n});\n\ndescribe('ReadonlyChatContext with immutable array', () => {\n it('should have readonly property set to true', () => {\n const items: ChatItem[] = [\n new ChatMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Test'],\n interrupted: false,\n createdAt: Date.now(),\n }),\n ];\n const readonlyContext = new ReadonlyChatContext(items);\n\n expect(readonlyContext.readonly).toBe(true);\n });\n\n it('should prevent setting items property', () => {\n const items: ChatItem[] = [\n new ChatMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Test'],\n interrupted: false,\n createdAt: Date.now(),\n }),\n ];\n const readonlyContext = new ReadonlyChatContext(items);\n expect(() => {\n readonlyContext.items = [];\n }).toThrow(\n `Cannot set items on a read-only chat context. Please use .copy() and agent.update_chat_ctx() to modify the chat context.`,\n );\n });\n\n it('should prevent modifications through array methods', () => {\n const items: ChatItem[] = [\n new ChatMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Test'],\n interrupted: false,\n createdAt: Date.now(),\n }),\n ];\n const readonlyContext = new ReadonlyChatContext(items);\n const newItem = new ChatMessage({\n id: 'msg_2',\n role: 'assistant',\n content: ['Response'],\n interrupted: false,\n createdAt: Date.now(),\n });\n\n const mutableItems = readonlyContext.items;\n expect(() => mutableItems.push(newItem)).toThrow(\n 'Cannot call push() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.pop()).toThrow(\n 'Cannot call pop() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.shift()).toThrow(\n 'Cannot call shift() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.unshift(newItem)).toThrow(\n 'Cannot call unshift() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.splice(0, 1)).toThrow(\n 'Cannot call splice() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.sort()).toThrow(\n 'Cannot call sort() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.reverse()).toThrow(\n 'Cannot call reverse() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.fill(newItem)).toThrow(\n 'Cannot call fill() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.copyWithin(0, 1)).toThrow(\n 'Cannot call copyWithin() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n });\n\n it('should prevent bracket notation assignment and deletion', () => {\n const items: ChatItem[] = [\n new ChatMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Test'],\n interrupted: false,\n createdAt: Date.now(),\n }),\n ];\n const readonlyContext = new ReadonlyChatContext(items);\n const newItem = new ChatMessage({\n id: 'msg_2',\n role: 'assistant',\n content: ['Response'],\n interrupted: false,\n createdAt: Date.now(),\n });\n\n expect(() => {\n readonlyContext.items[0] = newItem;\n }).toThrow(\n 'Cannot assign to read-only array index \"0\". Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => {\n delete readonlyContext.items[0];\n }).toThrow(\n 'Cannot delete read-only array index \"0\". Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => {\n readonlyContext.items[99] = newItem;\n }).toThrow(\n 'Cannot assign to read-only array index \"99\". Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n });\n\n it('should allow read operations on the immutable array', () => {\n const items: ChatItem[] = [\n new ChatMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Test 1'],\n interrupted: false,\n createdAt: 1000,\n }),\n new ChatMessage({\n id: 'msg_2',\n role: 'assistant',\n content: ['Test 2'],\n interrupted: false,\n createdAt: 2000,\n }),\n ];\n const readonlyContext = new ReadonlyChatContext(items);\n\n expect(readonlyContext.items.length).toBe(2);\n expect(readonlyContext.items[0]).toEqual(items[0]);\n expect(readonlyContext.items[1]).toEqual(items[1]);\n expect(readonlyContext.items.find((item: ChatItem) => item.id === 'msg_2')).toEqual(items[1]);\n expect(readonlyContext.items.map((item: ChatItem) => item.id)).toEqual(['msg_1', 'msg_2']);\n expect(\n readonlyContext.items.filter(\n (item: ChatItem) => item.type === 'message' && item.role === 'user',\n ),\n ).toHaveLength(1);\n\n // forEach should work for reading\n const ids: string[] = [];\n readonlyContext.items.forEach((item) => ids.push(item.id));\n expect(ids).toEqual(['msg_1', 'msg_2']);\n });\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/llm/chat_context.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { describe, expect, it } from 'vitest';\nimport {\n type AudioContent,\n ChatContext,\n type ChatItem,\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n type ImageContent,\n ReadonlyChatContext,\n} from './chat_context.js';\n\ndescribe('ChatContext.toJSON', () => {\n it('should match snapshot for empty context', () => {\n const context = new ChatContext();\n expect(context.toJSON()).toMatchSnapshot();\n });\n\n it('should match snapshot for simple conversation', () => {\n const context = new ChatContext();\n\n context.addMessage({\n id: 'msg_system_1',\n role: 'system',\n content: 'You are a helpful assistant.',\n createdAt: 1000000000,\n });\n\n context.addMessage({\n id: 'msg_user_1',\n role: 'user',\n content: 'Hello, how are you?',\n createdAt: 1000000001,\n });\n\n context.addMessage({\n id: 'msg_assistant_1',\n role: 'assistant',\n content: \"I'm doing well, thank you! How can I help you today?\",\n createdAt: 1000000002,\n });\n\n expect(context.toJSON()).toMatchSnapshot('simple-conversation-no-timestamps');\n\n expect(context.toJSON({ excludeTimestamp: false })).toMatchSnapshot(\n 'simple-conversation-with-timestamps',\n );\n });\n\n it('should match snapshot for multimodal content', () => {\n const context = new ChatContext();\n\n const imageContent: ImageContent = {\n id: 'img_test_1',\n type: 'image_content',\n image: 'https://example.com/test-image.jpg',\n inferenceDetail: 'high',\n inferenceWidth: 1024,\n inferenceHeight: 768,\n mimeType: 'image/jpeg',\n _cache: {},\n };\n\n const audioContent: AudioContent = {\n type: 'audio_content',\n frame: [], // This won't be included in JSON\n transcript: 'This is a test audio transcript',\n };\n\n context.addMessage({\n id: 'msg_user_2',\n role: 'user',\n content: [\n 'Check out this image and audio:',\n imageContent,\n audioContent,\n 'What do you think?',\n ],\n createdAt: 2000000000,\n });\n\n expect(context.toJSON()).toMatchSnapshot('multimodal-default-exclusions');\n\n expect(\n context.toJSON({\n excludeImage: false,\n excludeAudio: true,\n }),\n ).toMatchSnapshot('multimodal-with-images-only');\n\n expect(\n context.toJSON({\n excludeImage: true,\n excludeAudio: false,\n }),\n ).toMatchSnapshot('multimodal-with-audio-only');\n\n expect(\n context.toJSON({\n excludeImage: false,\n excludeAudio: false,\n excludeTimestamp: false,\n }),\n ).toMatchSnapshot('multimodal-full-content');\n });\n\n it('should match snapshot for function calls', () => {\n const context = new ChatContext();\n\n context.addMessage({\n id: 'msg_user_3',\n role: 'user',\n content: \"What's the weather in Paris?\",\n createdAt: 3000000000,\n });\n\n const functionCall = new FunctionCall({\n id: 'func_call_1',\n callId: 'call_weather_123',\n name: 'get_weather',\n args: '{\"location\": \"Paris, France\", \"unit\": \"celsius\"}',\n createdAt: 3000000001,\n });\n context.insert(functionCall);\n\n const functionOutput = new FunctionCallOutput({\n id: 'func_output_1',\n callId: 'call_weather_123',\n name: 'get_weather',\n output: '{\"temperature\": 22, \"condition\": \"partly cloudy\", \"humidity\": 65}',\n isError: false,\n createdAt: 3000000002,\n });\n context.insert(functionOutput);\n\n context.addMessage({\n id: 'msg_assistant_2',\n role: 'assistant',\n content: 'The weather in Paris is currently 22°C and partly cloudy with 65% humidity.',\n createdAt: 3000000003,\n });\n\n expect(context.toJSON()).toMatchSnapshot('conversation-with-function-calls');\n\n expect(\n context.toJSON({\n excludeFunctionCall: true,\n }),\n ).toMatchSnapshot('conversation-without-function-calls');\n\n expect(\n context.toJSON({\n excludeTimestamp: false,\n }),\n ).toMatchSnapshot('conversation-with-function-calls-and-timestamps');\n });\n\n it('should match snapshot for edge cases', () => {\n const context = new ChatContext();\n\n context.addMessage({\n id: 'msg_empty_1',\n role: 'user',\n content: [],\n createdAt: 5000000000,\n });\n\n const silentAudio: AudioContent = {\n type: 'audio_content',\n frame: [],\n transcript: undefined,\n };\n\n context.addMessage({\n id: 'msg_silent_audio',\n role: 'user',\n content: [silentAudio],\n createdAt: 5000000001,\n });\n\n context.addMessage({\n id: 'msg_multi_text',\n role: 'assistant',\n content: ['Part 1. ', 'Part 2. ', 'Part 3.'],\n createdAt: 5000000002,\n });\n\n const minimalCall = new FunctionCall({\n id: 'func_minimal',\n callId: 'minimal',\n name: 'test',\n args: '{}',\n createdAt: 5000000003,\n });\n context.insert(minimalCall);\n\n const namelessOutput = new FunctionCallOutput({\n id: 'func_output_nameless',\n callId: 'minimal',\n output: 'OK',\n isError: false,\n createdAt: 5000000004,\n });\n context.insert(namelessOutput);\n\n context.addMessage({\n id: 'msg_special_chars',\n role: 'user',\n content:\n 'Test with special chars: \\n\\t\\r \"quotes\" \\'apostrophes\\' \\\\backslashes\\\\ {braces} [brackets]',\n createdAt: 5000000005,\n });\n\n expect(context.toJSON()).toMatchSnapshot('edge-cases-default');\n expect(\n context.toJSON({\n excludeTimestamp: false,\n excludeAudio: false,\n }),\n ).toMatchSnapshot('edge-cases-with-details');\n });\n\n it('should match snapshot for message property variations', () => {\n const context = new ChatContext();\n\n context.addMessage({\n id: 'custom-message-id-123',\n role: 'user',\n content: 'Message with custom ID',\n createdAt: 6000000000,\n });\n\n context.addMessage({\n id: 'msg_interrupted',\n role: 'assistant',\n content: 'This response was interrupted...',\n interrupted: true,\n createdAt: 6000000001,\n });\n\n context.addMessage({\n id: 'msg_dev_2',\n role: 'developer',\n content: 'Developer message',\n createdAt: 6000000002,\n });\n\n context.addMessage({\n id: 'msg_system_3',\n role: 'system',\n content: 'System message',\n createdAt: 6000000003,\n });\n\n const detailedImage: ImageContent = {\n id: 'img_detailed',\n type: 'image_content',\n image: 'https://example.com/image.jpg',\n inferenceDetail: 'low',\n inferenceWidth: 512,\n inferenceHeight: 512,\n mimeType: 'image/png',\n _cache: { cached: true },\n };\n\n context.addMessage({\n id: 'msg_with_image',\n role: 'user',\n content: ['Image with all properties:', detailedImage],\n createdAt: 6000000004,\n });\n\n expect(context.toJSON()).toMatchSnapshot('message-properties-default');\n expect(\n context.toJSON({\n excludeImage: false,\n excludeTimestamp: false,\n }),\n ).toMatchSnapshot('message-properties-full');\n });\n});\n\ndescribe('ReadonlyChatContext with immutable array', () => {\n it('should have readonly property set to true', () => {\n const items: ChatItem[] = [\n new ChatMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Test'],\n interrupted: false,\n createdAt: Date.now(),\n }),\n ];\n const readonlyContext = new ReadonlyChatContext(items);\n\n expect(readonlyContext.readonly).toBe(true);\n });\n\n it('should prevent setting items property', () => {\n const items: ChatItem[] = [\n new ChatMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Test'],\n interrupted: false,\n createdAt: Date.now(),\n }),\n ];\n const readonlyContext = new ReadonlyChatContext(items);\n expect(() => {\n readonlyContext.items = [];\n }).toThrow(\n `Cannot set items on a read-only chat context. Please use .copy() and agent.update_chat_ctx() to modify the chat context.`,\n );\n });\n\n it('should prevent modifications through array methods', () => {\n const items: ChatItem[] = [\n new ChatMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Test'],\n interrupted: false,\n createdAt: Date.now(),\n }),\n ];\n const readonlyContext = new ReadonlyChatContext(items);\n const newItem = new ChatMessage({\n id: 'msg_2',\n role: 'assistant',\n content: ['Response'],\n interrupted: false,\n createdAt: Date.now(),\n });\n\n const mutableItems = readonlyContext.items;\n expect(() => mutableItems.push(newItem)).toThrow(\n 'Cannot call push() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.pop()).toThrow(\n 'Cannot call pop() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.shift()).toThrow(\n 'Cannot call shift() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.unshift(newItem)).toThrow(\n 'Cannot call unshift() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.splice(0, 1)).toThrow(\n 'Cannot call splice() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.sort()).toThrow(\n 'Cannot call sort() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.reverse()).toThrow(\n 'Cannot call reverse() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.fill(newItem)).toThrow(\n 'Cannot call fill() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => mutableItems.copyWithin(0, 1)).toThrow(\n 'Cannot call copyWithin() on a read-only array. Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n });\n\n it('should prevent bracket notation assignment and deletion', () => {\n const items: ChatItem[] = [\n new ChatMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Test'],\n interrupted: false,\n createdAt: Date.now(),\n }),\n ];\n const readonlyContext = new ReadonlyChatContext(items);\n const newItem = new ChatMessage({\n id: 'msg_2',\n role: 'assistant',\n content: ['Response'],\n interrupted: false,\n createdAt: Date.now(),\n });\n\n expect(() => {\n readonlyContext.items[0] = newItem;\n }).toThrow(\n 'Cannot assign to read-only array index \"0\". Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => {\n delete readonlyContext.items[0];\n }).toThrow(\n 'Cannot delete read-only array index \"0\". Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n\n expect(() => {\n readonlyContext.items[99] = newItem;\n }).toThrow(\n 'Cannot assign to read-only array index \"99\". Please use .copy() and agent.update_chat_ctx() to modify the chat context.',\n );\n });\n\n it('should allow read operations on the immutable array', () => {\n const items: ChatItem[] = [\n new ChatMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Test 1'],\n interrupted: false,\n createdAt: 1000,\n }),\n new ChatMessage({\n id: 'msg_2',\n role: 'assistant',\n content: ['Test 2'],\n interrupted: false,\n createdAt: 2000,\n }),\n ];\n const readonlyContext = new ReadonlyChatContext(items);\n\n expect(readonlyContext.items.length).toBe(2);\n expect(readonlyContext.items[0]).toEqual(items[0]);\n expect(readonlyContext.items[1]).toEqual(items[1]);\n expect(readonlyContext.items.find((item: ChatItem) => item.id === 'msg_2')).toEqual(items[1]);\n expect(readonlyContext.items.map((item: ChatItem) => item.id)).toEqual(['msg_1', 'msg_2']);\n expect(\n readonlyContext.items.filter(\n (item: ChatItem) => item.type === 'message' && item.role === 'user',\n ),\n ).toHaveLength(1);\n\n // forEach should work for reading\n const ids: string[] = [];\n readonlyContext.items.forEach((item) => ids.push(item.id));\n expect(ids).toEqual(['msg_1', 'msg_2']);\n });\n});\n\ndescribe('ChatContext.isEquivalent', () => {\n it('should return true for same reference', () => {\n const ctx = new ChatContext();\n ctx.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'Hello',\n });\n\n expect(ctx.isEquivalent(ctx)).toBe(true);\n });\n\n it('should return true for identical empty contexts', () => {\n const ctx1 = new ChatContext();\n const ctx2 = new ChatContext();\n\n expect(ctx1.isEquivalent(ctx2)).toBe(true);\n });\n\n it('should return false for contexts with different lengths', () => {\n const ctx1 = new ChatContext();\n ctx1.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'Hello',\n });\n\n const ctx2 = new ChatContext();\n ctx2.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'Hello',\n });\n ctx2.addMessage({\n id: 'msg_2',\n role: 'assistant',\n content: 'Hi',\n });\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n it('should return false for contexts with different item IDs', () => {\n const ctx1 = new ChatContext();\n ctx1.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'Hello',\n });\n\n const ctx2 = new ChatContext();\n ctx2.addMessage({\n id: 'msg_2',\n role: 'user',\n content: 'Hello',\n });\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n it('should return false for contexts with different item types', () => {\n const ctx1 = new ChatContext();\n ctx1.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'Hello',\n });\n\n const ctx2 = new ChatContext();\n ctx2.insert(\n new FunctionCall({\n id: 'msg_1',\n callId: 'call_1',\n name: 'test',\n args: '{}',\n }),\n );\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n describe('message comparison', () => {\n it('should return true for identical messages', () => {\n const ctx1 = new ChatContext();\n ctx1.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'Hello',\n interrupted: false,\n });\n\n const ctx2 = new ChatContext();\n ctx2.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'Hello',\n interrupted: false,\n });\n\n expect(ctx1.isEquivalent(ctx2)).toBe(true);\n });\n\n it('should return false for messages with different roles', () => {\n const ctx1 = new ChatContext();\n ctx1.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'Hello',\n });\n\n const ctx2 = new ChatContext();\n ctx2.addMessage({\n id: 'msg_1',\n role: 'assistant',\n content: 'Hello',\n });\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n it('should return false for messages with different interrupted flags', () => {\n const ctx1 = new ChatContext();\n ctx1.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'Hello',\n interrupted: false,\n });\n\n const ctx2 = new ChatContext();\n ctx2.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'Hello',\n interrupted: true,\n });\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n it('should return false for messages with different content', () => {\n const ctx1 = new ChatContext();\n ctx1.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'Hello',\n });\n\n const ctx2 = new ChatContext();\n ctx2.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'World',\n });\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n it('should return true for messages with identical array content', () => {\n const ctx1 = new ChatContext();\n ctx1.addMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Hello', 'World'],\n });\n\n const ctx2 = new ChatContext();\n ctx2.addMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Hello', 'World'],\n });\n\n expect(ctx1.isEquivalent(ctx2)).toBe(true);\n });\n\n it('should return false for messages with different array content', () => {\n const ctx1 = new ChatContext();\n ctx1.addMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Hello', 'World'],\n });\n\n const ctx2 = new ChatContext();\n ctx2.addMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Hello'],\n });\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n it('should return true for messages with identical image content', () => {\n const imageContent: ImageContent = {\n id: 'img_1',\n type: 'image_content',\n image: 'https://example.com/image.jpg',\n inferenceDetail: 'high',\n inferenceWidth: 1024,\n inferenceHeight: 768,\n mimeType: 'image/jpeg',\n _cache: {},\n };\n\n const ctx1 = new ChatContext();\n ctx1.addMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Check this:', imageContent],\n });\n\n const ctx2 = new ChatContext();\n ctx2.addMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Check this:', { ...imageContent }],\n });\n\n expect(ctx1.isEquivalent(ctx2)).toBe(true);\n });\n\n it('should return false for messages with different image content', () => {\n const imageContent1: ImageContent = {\n id: 'img_1',\n type: 'image_content',\n image: 'https://example.com/image1.jpg',\n inferenceDetail: 'high',\n _cache: {},\n };\n\n const imageContent2: ImageContent = {\n id: 'img_2',\n type: 'image_content',\n image: 'https://example.com/image2.jpg',\n inferenceDetail: 'high',\n _cache: {},\n };\n\n const ctx1 = new ChatContext();\n ctx1.addMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Check this:', imageContent1],\n });\n\n const ctx2 = new ChatContext();\n ctx2.addMessage({\n id: 'msg_1',\n role: 'user',\n content: ['Check this:', imageContent2],\n });\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n });\n\n describe('function call comparison', () => {\n it('should return true for identical function calls', () => {\n const ctx1 = new ChatContext();\n ctx1.insert(\n new FunctionCall({\n id: 'func_1',\n callId: 'call_1',\n name: 'get_weather',\n args: '{\"location\": \"Paris\"}',\n }),\n );\n\n const ctx2 = new ChatContext();\n ctx2.insert(\n new FunctionCall({\n id: 'func_1',\n callId: 'call_1',\n name: 'get_weather',\n args: '{\"location\": \"Paris\"}',\n }),\n );\n\n expect(ctx1.isEquivalent(ctx2)).toBe(true);\n });\n\n it('should return false for function calls with different names', () => {\n const ctx1 = new ChatContext();\n ctx1.insert(\n new FunctionCall({\n id: 'func_1',\n callId: 'call_1',\n name: 'get_weather',\n args: '{}',\n }),\n );\n\n const ctx2 = new ChatContext();\n ctx2.insert(\n new FunctionCall({\n id: 'func_1',\n callId: 'call_1',\n name: 'get_time',\n args: '{}',\n }),\n );\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n it('should return false for function calls with different call IDs', () => {\n const ctx1 = new ChatContext();\n ctx1.insert(\n new FunctionCall({\n id: 'func_1',\n callId: 'call_1',\n name: 'get_weather',\n args: '{}',\n }),\n );\n\n const ctx2 = new ChatContext();\n ctx2.insert(\n new FunctionCall({\n id: 'func_1',\n callId: 'call_2',\n name: 'get_weather',\n args: '{}',\n }),\n );\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n it('should return false for function calls with different arguments', () => {\n const ctx1 = new ChatContext();\n ctx1.insert(\n new FunctionCall({\n id: 'func_1',\n callId: 'call_1',\n name: 'get_weather',\n args: '{\"location\": \"Paris\"}',\n }),\n );\n\n const ctx2 = new ChatContext();\n ctx2.insert(\n new FunctionCall({\n id: 'func_1',\n callId: 'call_1',\n name: 'get_weather',\n args: '{\"location\": \"London\"}',\n }),\n );\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n it('should ignore timestamps', () => {\n const ctx1 = new ChatContext();\n ctx1.insert(\n new FunctionCall({\n id: 'func_1',\n callId: 'call_1',\n name: 'get_weather',\n args: '{}',\n createdAt: 1000,\n }),\n );\n\n const ctx2 = new ChatContext();\n ctx2.insert(\n new FunctionCall({\n id: 'func_1',\n callId: 'call_1',\n name: 'get_weather',\n args: '{}',\n createdAt: 2000,\n }),\n );\n\n expect(ctx1.isEquivalent(ctx2)).toBe(true);\n });\n });\n\n describe('function call output comparison', () => {\n it('should return true for identical function call outputs', () => {\n const ctx1 = new ChatContext();\n ctx1.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_1',\n name: 'get_weather',\n output: '{\"temperature\": 22}',\n isError: false,\n }),\n );\n\n const ctx2 = new ChatContext();\n ctx2.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_1',\n name: 'get_weather',\n output: '{\"temperature\": 22}',\n isError: false,\n }),\n );\n\n expect(ctx1.isEquivalent(ctx2)).toBe(true);\n });\n\n it('should return false for function call outputs with different names', () => {\n const ctx1 = new ChatContext();\n ctx1.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_1',\n name: 'get_weather',\n output: '{}',\n isError: false,\n }),\n );\n\n const ctx2 = new ChatContext();\n ctx2.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_1',\n name: 'get_time',\n output: '{}',\n isError: false,\n }),\n );\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n it('should return false for function call outputs with different call IDs', () => {\n const ctx1 = new ChatContext();\n ctx1.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_1',\n name: 'get_weather',\n output: '{}',\n isError: false,\n }),\n );\n\n const ctx2 = new ChatContext();\n ctx2.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_2',\n name: 'get_weather',\n output: '{}',\n isError: false,\n }),\n );\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n it('should return false for function call outputs with different output values', () => {\n const ctx1 = new ChatContext();\n ctx1.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_1',\n name: 'get_weather',\n output: '{\"temperature\": 22}',\n isError: false,\n }),\n );\n\n const ctx2 = new ChatContext();\n ctx2.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_1',\n name: 'get_weather',\n output: '{\"temperature\": 25}',\n isError: false,\n }),\n );\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n it('should return false for function call outputs with different error flags', () => {\n const ctx1 = new ChatContext();\n ctx1.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_1',\n name: 'get_weather',\n output: 'Error occurred',\n isError: false,\n }),\n );\n\n const ctx2 = new ChatContext();\n ctx2.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_1',\n name: 'get_weather',\n output: 'Error occurred',\n isError: true,\n }),\n );\n\n expect(ctx1.isEquivalent(ctx2)).toBe(false);\n });\n\n it('should ignore timestamps', () => {\n const ctx1 = new ChatContext();\n ctx1.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_1',\n name: 'get_weather',\n output: '{}',\n isError: false,\n createdAt: 1000,\n }),\n );\n\n const ctx2 = new ChatContext();\n ctx2.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_1',\n name: 'get_weather',\n output: '{}',\n isError: false,\n createdAt: 2000,\n }),\n );\n\n expect(ctx1.isEquivalent(ctx2)).toBe(true);\n });\n });\n\n describe('complex context comparison', () => {\n it('should return true for identical complex contexts', () => {\n const ctx1 = new ChatContext();\n ctx1.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'What is the weather?',\n });\n ctx1.insert(\n new FunctionCall({\n id: 'func_1',\n callId: 'call_1',\n name: 'get_weather',\n args: '{\"location\": \"Paris\"}',\n }),\n );\n ctx1.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_1',\n name: 'get_weather',\n output: '{\"temperature\": 22}',\n isError: false,\n }),\n );\n ctx1.addMessage({\n id: 'msg_2',\n role: 'assistant',\n content: 'The weather is 22°C',\n });\n\n const ctx2 = new ChatContext();\n ctx2.addMessage({\n id: 'msg_1',\n role: 'user',\n content: 'What is the weather?',\n });\n ctx2.insert(\n new FunctionCall({\n id: 'func_1',\n callId: 'call_1',\n name: 'get_weather',\n args: '{\"location\": \"Paris\"}',\n }),\n );\n ctx2.insert(\n new FunctionCallOutput({\n id: 'output_1',\n callId: 'call_1',\n name: 'get_weather',\n output: '{\"temperature\": 22}',\n isError: false,\n }),\n );\n ctx2.addMessage({\n id: 'msg_2',\n role: 'assistant',\n content: 'The weather is 22°C',\n });\n\n expect(ctx1.isEquivalent(ctx2)).toBe(true);\n });\n });\n});\n"],"mappings":"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","names":[]}
@@ -23,12 +23,15 @@ __export(tool_context_exports, {
23
23
  isAgentHandoff: () => isAgentHandoff,
24
24
  isFunctionTool: () => isFunctionTool,
25
25
  isProviderDefinedTool: () => isProviderDefinedTool,
26
+ isSameToolChoice: () => isSameToolChoice,
27
+ isSameToolContext: () => isSameToolContext,
26
28
  isTool: () => isTool,
27
29
  isToolError: () => isToolError,
28
30
  tool: () => tool
29
31
  });
30
32
  module.exports = __toCommonJS(tool_context_exports);
31
33
  var import_zod = require("zod");
34
+ var import_zod_utils = require("./zod-utils.cjs");
32
35
  const TOOL_SYMBOL = Symbol("tool");
33
36
  const FUNCTION_TOOL_SYMBOL = Symbol("function_tool");
34
37
  const PROVIDER_DEFINED_TOOL_SYMBOL = Symbol("provider_defined_tool");
@@ -49,13 +52,49 @@ function handoff(options) {
49
52
  [HANDOFF_SYMBOL]: true
50
53
  };
51
54
  }
55
+ function isSameToolContext(ctx1, ctx2) {
56
+ const toolNames = new Set(Object.keys(ctx1));
57
+ const toolNames2 = new Set(Object.keys(ctx2));
58
+ if (toolNames.size !== toolNames2.size) {
59
+ return false;
60
+ }
61
+ for (const name of toolNames) {
62
+ if (!toolNames2.has(name)) {
63
+ return false;
64
+ }
65
+ const tool1 = ctx1[name];
66
+ const tool2 = ctx2[name];
67
+ if (!tool1 || !tool2) {
68
+ return false;
69
+ }
70
+ if (tool1.description !== tool2.description) {
71
+ return false;
72
+ }
73
+ }
74
+ return true;
75
+ }
76
+ function isSameToolChoice(choice1, choice2) {
77
+ if (choice1 === choice2) {
78
+ return true;
79
+ }
80
+ if (choice1 === null || choice2 === null) {
81
+ return false;
82
+ }
83
+ if (typeof choice1 === "string" && typeof choice2 === "string") {
84
+ return choice1 === choice2;
85
+ }
86
+ if (typeof choice1 === "object" && typeof choice2 === "object") {
87
+ return choice1.type === choice2.type && choice1.function.name === choice2.function.name;
88
+ }
89
+ return false;
90
+ }
52
91
  function tool(tool2) {
53
92
  if (tool2.execute !== void 0) {
54
93
  const parameters = tool2.parameters ?? import_zod.z.object({});
55
- if (parameters instanceof import_zod.ZodType && parameters._def.typeName !== "ZodObject") {
94
+ if ((0, import_zod_utils.isZodSchema)(parameters) && !(0, import_zod_utils.isZodObjectSchema)(parameters)) {
56
95
  throw new Error("Tool parameters must be a Zod object schema (z.object(...))");
57
96
  }
58
- if (!(parameters instanceof import_zod.ZodObject) && !(typeof parameters === "object")) {
97
+ if (!(0, import_zod_utils.isZodSchema)(parameters) && !(typeof parameters === "object")) {
59
98
  throw new Error("Tool parameters must be a Zod object schema or a raw JSON schema");
60
99
  }
61
100
  return {
@@ -104,6 +143,8 @@ function isAgentHandoff(handoff2) {
104
143
  isAgentHandoff,
105
144
  isFunctionTool,
106
145
  isProviderDefinedTool,
146
+ isSameToolChoice,
147
+ isSameToolContext,
107
148
  isTool,
108
149
  isToolError,
109
150
  tool
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/llm/tool_context.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { JSONSchema7 } from 'json-schema';\nimport { ZodObject, ZodType, z } from 'zod';\nimport type { Agent } from '../voice/agent.js';\nimport type { RunContext, UnknownUserData } from '../voice/run_context.js';\n\n// heavily inspired by Vercel AI's `tool()`:\n// https://github.com/vercel/ai/blob/3b0983b/packages/ai/core/tool/tool.ts\n\nconst TOOL_SYMBOL = Symbol('tool');\nconst FUNCTION_TOOL_SYMBOL = Symbol('function_tool');\nconst PROVIDER_DEFINED_TOOL_SYMBOL = Symbol('provider_defined_tool');\nconst TOOL_ERROR_SYMBOL = Symbol('tool_error');\nconst HANDOFF_SYMBOL = Symbol('handoff');\n\nexport type JSONValue = null | string | number | boolean | JSONObject | JSONArray;\n\nexport type JSONArray = JSONValue[];\n\nexport type JSONObject = {\n [key: string]: JSONValue;\n};\n\n// TODO(AJS-111): support Zod cross-version compatibility, raw JSON schema, both strict and non-strict versions\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type ToolInputSchema<T extends JSONObject> = ZodObject<any, any, any, T, T> | JSONSchema7;\n\nexport type ToolType = 'function' | 'provider-defined';\n\nexport type ToolChoice =\n | 'auto'\n | 'none'\n | 'required'\n | {\n type: 'function';\n function: {\n name: string;\n };\n };\n\nexport class ToolError extends Error {\n constructor(message: string) {\n super(message);\n\n Object.defineProperty(this, TOOL_ERROR_SYMBOL, {\n value: true,\n });\n }\n}\n\nexport interface AgentHandoff {\n /**\n * The agent to handoff to.\n */\n agent: Agent;\n\n /**\n * The return value of the tool.\n */\n returns?: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n [HANDOFF_SYMBOL]: true;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function handoff(options: { agent: Agent; returns?: any }): AgentHandoff {\n return {\n agent: options.agent,\n returns: options.returns,\n [HANDOFF_SYMBOL]: true,\n };\n}\n\nexport interface ToolOptions<UserData = UnknownUserData> {\n /**\n * RunContext for the current agent session.\n */\n ctx: RunContext<UserData>;\n\n /**\n * The ID of the tool call.\n */\n toolCallId: string;\n\n /**\n * An optional abort signal that indicates that the overall operation should be aborted.\n */\n abortSignal?: AbortSignal;\n}\n\nexport type ToolExecuteFunction<\n Parameters extends JSONObject,\n UserData = UnknownUserData,\n Result = unknown,\n> = (args: Parameters, opts: ToolOptions<UserData>) => Promise<Result>;\n\nexport interface Tool {\n /**\n * The type of the tool.\n * @internal Either user-defined core tool or provider-defined tool.\n */\n type: ToolType;\n\n [TOOL_SYMBOL]: true;\n}\n\n// TODO(AJS-112): support provider-defined tools\nexport interface ProviderDefinedTool extends Tool {\n type: 'provider-defined';\n\n /**\n * The ID of the tool.\n */\n id: string;\n\n /**\n * The configuration of the tool.\n */\n config: Record<string, unknown>;\n\n [PROVIDER_DEFINED_TOOL_SYMBOL]: true;\n}\n\nexport interface FunctionTool<\n Parameters extends JSONObject,\n UserData = UnknownUserData,\n Result = unknown,\n> extends Tool {\n type: 'function';\n\n /**\n * The description of the tool. Will be used by the language model to decide whether to use the tool.\n */\n description: string;\n\n /**\n * The schema of the input that the tool expects. The language model will use this to generate the input.\n * It is also used to validate the output of the language model.\n * Use descriptions to make the input understandable for the language model.\n */\n parameters: ToolInputSchema<Parameters>;\n\n /**\n * An async function that is called with the arguments from the tool call and produces a result.\n * It also carries context about current session, user-defined data, and the tool call id, etc.\n */\n execute: ToolExecuteFunction<Parameters, UserData, Result>;\n\n [FUNCTION_TOOL_SYMBOL]: true;\n}\n\n// TODO(AJS-112): support provider-defined tools in the future)\nexport type ToolContext<UserData = UnknownUserData> = {\n [name: string]: FunctionTool<any, UserData, any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n};\n\n/**\n * Create a function tool.\n *\n * @param description - The description of the tool.\n * @param parameters - The schema of the input that the tool expects. If not provided, defaults to z.object({}).\n * @param execute - The function that is called with the arguments from the tool call and produces a result.\n */\nexport function tool<\n Parameters extends JSONObject = Record<string, never>,\n UserData = UnknownUserData,\n Result = unknown,\n>({\n description,\n parameters,\n execute,\n}: {\n description: string;\n parameters?: ToolInputSchema<Parameters>;\n execute: ToolExecuteFunction<Parameters, UserData, Result>;\n}): FunctionTool<Parameters, UserData, Result>;\n\n/**\n * Create a provider-defined tool.\n *\n * @param id - The ID of the tool.\n * @param config - The configuration of the tool.\n */\nexport function tool({\n id,\n config,\n}: {\n id: string;\n config: Record<string, unknown>;\n}): ProviderDefinedTool;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function tool(tool: any): any {\n if (tool.execute !== undefined) {\n // Default parameters to z.object({}) if not provided\n const parameters = tool.parameters ?? z.object({});\n\n // if parameters is not zod object, throw an error\n if (parameters instanceof ZodType && parameters._def.typeName !== 'ZodObject') {\n throw new Error('Tool parameters must be a Zod object schema (z.object(...))');\n }\n\n if (!(parameters instanceof ZodObject) && !(typeof parameters === 'object')) {\n throw new Error('Tool parameters must be a Zod object schema or a raw JSON schema');\n }\n\n return {\n type: 'function',\n description: tool.description,\n parameters,\n execute: tool.execute,\n [TOOL_SYMBOL]: true,\n [FUNCTION_TOOL_SYMBOL]: true,\n };\n }\n\n if (tool.config !== undefined && tool.id !== undefined) {\n return {\n type: 'provider-defined',\n id: tool.id,\n config: tool.config,\n [TOOL_SYMBOL]: true,\n [PROVIDER_DEFINED_TOOL_SYMBOL]: true,\n };\n }\n\n throw new Error('Invalid tool');\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isTool(tool: any): tool is Tool {\n return tool && tool[TOOL_SYMBOL] === true;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isFunctionTool(tool: any): tool is FunctionTool<any, any, any> {\n const isTool = tool && tool[TOOL_SYMBOL] === true;\n const isFunctionTool = tool[FUNCTION_TOOL_SYMBOL] === true;\n return isTool && isFunctionTool;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isProviderDefinedTool(tool: any): tool is ProviderDefinedTool {\n const isTool = tool && tool[TOOL_SYMBOL] === true;\n const isProviderDefinedTool = tool[PROVIDER_DEFINED_TOOL_SYMBOL] === true;\n return isTool && isProviderDefinedTool;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isToolError(error: any): error is ToolError {\n return error && error[TOOL_ERROR_SYMBOL] === true;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isAgentHandoff(handoff: any): handoff is AgentHandoff {\n return handoff && handoff[HANDOFF_SYMBOL] === true;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,iBAAsC;AAOtC,MAAM,cAAc,OAAO,MAAM;AACjC,MAAM,uBAAuB,OAAO,eAAe;AACnD,MAAM,+BAA+B,OAAO,uBAAuB;AACnE,MAAM,oBAAoB,OAAO,YAAY;AAC7C,MAAM,iBAAiB,OAAO,SAAS;AA2BhC,MAAM,kBAAkB,MAAM;AAAA,EACnC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AAEb,WAAO,eAAe,MAAM,mBAAmB;AAAA,MAC7C,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF;AAiBO,SAAS,QAAQ,SAAwD;AAC9E,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf,SAAS,QAAQ;AAAA,IACjB,CAAC,cAAc,GAAG;AAAA,EACpB;AACF;AAyHO,SAAS,KAAKA,OAAgB;AACnC,MAAIA,MAAK,YAAY,QAAW;AAE9B,UAAM,aAAaA,MAAK,cAAc,aAAE,OAAO,CAAC,CAAC;AAGjD,QAAI,sBAAsB,sBAAW,WAAW,KAAK,aAAa,aAAa;AAC7E,YAAM,IAAI,MAAM,6DAA6D;AAAA,IAC/E;AAEA,QAAI,EAAE,sBAAsB,yBAAc,EAAE,OAAO,eAAe,WAAW;AAC3E,YAAM,IAAI,MAAM,kEAAkE;AAAA,IACpF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAaA,MAAK;AAAA,MAClB;AAAA,MACA,SAASA,MAAK;AAAA,MACd,CAAC,WAAW,GAAG;AAAA,MACf,CAAC,oBAAoB,GAAG;AAAA,IAC1B;AAAA,EACF;AAEA,MAAIA,MAAK,WAAW,UAAaA,MAAK,OAAO,QAAW;AACtD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,IAAIA,MAAK;AAAA,MACT,QAAQA,MAAK;AAAA,MACb,CAAC,WAAW,GAAG;AAAA,MACf,CAAC,4BAA4B,GAAG;AAAA,IAClC;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,cAAc;AAChC;AAGO,SAAS,OAAOA,OAAyB;AAC9C,SAAOA,SAAQA,MAAK,WAAW,MAAM;AACvC;AAGO,SAAS,eAAeA,OAAgD;AAC7E,QAAMC,UAASD,SAAQA,MAAK,WAAW,MAAM;AAC7C,QAAME,kBAAiBF,MAAK,oBAAoB,MAAM;AACtD,SAAOC,WAAUC;AACnB;AAGO,SAAS,sBAAsBF,OAAwC;AAC5E,QAAMC,UAASD,SAAQA,MAAK,WAAW,MAAM;AAC7C,QAAMG,yBAAwBH,MAAK,4BAA4B,MAAM;AACrE,SAAOC,WAAUE;AACnB;AAGO,SAAS,YAAY,OAAgC;AAC1D,SAAO,SAAS,MAAM,iBAAiB,MAAM;AAC/C;AAGO,SAAS,eAAeC,UAAuC;AACpE,SAAOA,YAAWA,SAAQ,cAAc,MAAM;AAChD;","names":["tool","isTool","isFunctionTool","isProviderDefinedTool","handoff"]}
1
+ {"version":3,"sources":["../../src/llm/tool_context.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { JSONSchema7 } from 'json-schema';\nimport { z } from 'zod';\nimport type { Agent } from '../voice/agent.js';\nimport type { RunContext, UnknownUserData } from '../voice/run_context.js';\nimport { isZodObjectSchema, isZodSchema } from './zod-utils.js';\n\n// heavily inspired by Vercel AI's `tool()`:\n// https://github.com/vercel/ai/blob/3b0983b/packages/ai/core/tool/tool.ts\n\nconst TOOL_SYMBOL = Symbol('tool');\nconst FUNCTION_TOOL_SYMBOL = Symbol('function_tool');\nconst PROVIDER_DEFINED_TOOL_SYMBOL = Symbol('provider_defined_tool');\nconst TOOL_ERROR_SYMBOL = Symbol('tool_error');\nconst HANDOFF_SYMBOL = Symbol('handoff');\n\nexport type JSONValue = null | string | number | boolean | JSONObject | JSONArray;\n\nexport type JSONArray = JSONValue[];\n\nexport type JSONObject = {\n [key: string]: JSONValue;\n};\n\n// Supports both Zod v3 and v4 schemas, as well as raw JSON schema\n// Adapted from Vercel AI SDK's FlexibleSchema approach\n// Source: https://github.com/vercel/ai/blob/main/packages/provider-utils/src/schema.ts#L67-L70\n//\n// Vercel uses StandardSchemaV1 from @standard-schema/spec package.\n// We use a simpler approach by directly checking for schema properties:\n// - Zod v3: Has `_output` property\n// - Zod v4: Implements Standard Schema spec with `~standard` property\n// - JSON Schema: Plain object fallback\nexport type ToolInputSchema<T = JSONObject> =\n | {\n // Zod v3 schema - has _output property for type inference\n _output: T;\n }\n | {\n // Zod v4 schema (Standard Schema) - has ~standard property\n '~standard': {\n types?: { output: T };\n };\n }\n | JSONSchema7;\n\n/**\n * Infer the output type from a ToolInputSchema.\n * Adapted from Vercel AI SDK's InferSchema type.\n * Source: https://github.com/vercel/ai/blob/main/packages/provider-utils/src/schema.ts#L72-L79\n */\nexport type InferToolInput<T> = T extends { _output: infer O }\n ? O\n : T extends { '~standard': { types?: { output: infer O } } }\n ? O\n : any; // eslint-disable-line @typescript-eslint/no-explicit-any -- Fallback type for JSON Schema objects without type inference\n\nexport type ToolType = 'function' | 'provider-defined';\n\nexport type ToolChoice =\n | 'auto'\n | 'none'\n | 'required'\n | {\n type: 'function';\n function: {\n name: string;\n };\n };\n\nexport class ToolError extends Error {\n constructor(message: string) {\n super(message);\n\n Object.defineProperty(this, TOOL_ERROR_SYMBOL, {\n value: true,\n });\n }\n}\n\nexport interface AgentHandoff {\n /**\n * The agent to handoff to.\n */\n agent: Agent;\n\n /**\n * The return value of the tool.\n */\n returns?: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n [HANDOFF_SYMBOL]: true;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function handoff(options: { agent: Agent; returns?: any }): AgentHandoff {\n return {\n agent: options.agent,\n returns: options.returns,\n [HANDOFF_SYMBOL]: true,\n };\n}\n\nexport interface ToolOptions<UserData = UnknownUserData> {\n /**\n * RunContext for the current agent session.\n */\n ctx: RunContext<UserData>;\n\n /**\n * The ID of the tool call.\n */\n toolCallId: string;\n\n /**\n * An optional abort signal that indicates that the overall operation should be aborted.\n */\n abortSignal?: AbortSignal;\n}\n\nexport type ToolExecuteFunction<\n Parameters extends JSONObject,\n UserData = UnknownUserData,\n Result = unknown,\n> = (args: Parameters, opts: ToolOptions<UserData>) => Promise<Result>;\n\nexport interface Tool {\n /**\n * The type of the tool.\n * @internal Either user-defined core tool or provider-defined tool.\n */\n type: ToolType;\n\n [TOOL_SYMBOL]: true;\n}\n\n// TODO(AJS-112): support provider-defined tools\nexport interface ProviderDefinedTool extends Tool {\n type: 'provider-defined';\n\n /**\n * The ID of the tool.\n */\n id: string;\n\n /**\n * The configuration of the tool.\n */\n config: Record<string, unknown>;\n\n [PROVIDER_DEFINED_TOOL_SYMBOL]: true;\n}\n\nexport interface FunctionTool<\n Parameters extends JSONObject,\n UserData = UnknownUserData,\n Result = unknown,\n> extends Tool {\n type: 'function';\n\n /**\n * The description of the tool. Will be used by the language model to decide whether to use the tool.\n */\n description: string;\n\n /**\n * The schema of the input that the tool expects. The language model will use this to generate the input.\n * It is also used to validate the output of the language model.\n * Use descriptions to make the input understandable for the language model.\n */\n parameters: ToolInputSchema<Parameters>;\n\n /**\n * An async function that is called with the arguments from the tool call and produces a result.\n * It also carries context about current session, user-defined data, and the tool call id, etc.\n */\n execute: ToolExecuteFunction<Parameters, UserData, Result>;\n\n [FUNCTION_TOOL_SYMBOL]: true;\n}\n\n// TODO(AJS-112): support provider-defined tools in the future)\nexport type ToolContext<UserData = UnknownUserData> = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Generic tool registry needs to accept any parameter/result types\n [name: string]: FunctionTool<any, UserData, any>;\n};\n\nexport function isSameToolContext(ctx1: ToolContext, ctx2: ToolContext): boolean {\n const toolNames = new Set(Object.keys(ctx1));\n const toolNames2 = new Set(Object.keys(ctx2));\n\n if (toolNames.size !== toolNames2.size) {\n return false;\n }\n\n for (const name of toolNames) {\n if (!toolNames2.has(name)) {\n return false;\n }\n\n const tool1 = ctx1[name];\n const tool2 = ctx2[name];\n\n if (!tool1 || !tool2) {\n return false;\n }\n\n if (tool1.description !== tool2.description) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function isSameToolChoice(choice1: ToolChoice | null, choice2: ToolChoice | null): boolean {\n if (choice1 === choice2) {\n return true;\n }\n if (choice1 === null || choice2 === null) {\n return false;\n }\n if (typeof choice1 === 'string' && typeof choice2 === 'string') {\n return choice1 === choice2;\n }\n if (typeof choice1 === 'object' && typeof choice2 === 'object') {\n return choice1.type === choice2.type && choice1.function.name === choice2.function.name;\n }\n return false;\n}\n\n/**\n * Create a function tool with inferred parameters from the schema.\n */\nexport function tool<\n Schema extends ToolInputSchema<any>, // eslint-disable-line @typescript-eslint/no-explicit-any -- Generic constraint needs to accept any JSONObject type\n UserData = UnknownUserData,\n Result = unknown,\n>({\n description,\n parameters,\n execute,\n}: {\n description: string;\n parameters: Schema;\n execute: ToolExecuteFunction<InferToolInput<Schema>, UserData, Result>;\n}): FunctionTool<InferToolInput<Schema>, UserData, Result>;\n\n/**\n * Create a function tool without parameters.\n */\nexport function tool<UserData = UnknownUserData, Result = unknown>({\n description,\n execute,\n}: {\n description: string;\n parameters?: never;\n execute: ToolExecuteFunction<Record<string, never>, UserData, Result>;\n}): FunctionTool<Record<string, never>, UserData, Result>;\n\n/**\n * Create a provider-defined tool.\n *\n * @param id - The ID of the tool.\n * @param config - The configuration of the tool.\n */\nexport function tool({\n id,\n config,\n}: {\n id: string;\n config: Record<string, unknown>;\n}): ProviderDefinedTool;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function tool(tool: any): any {\n if (tool.execute !== undefined) {\n // Default parameters to z.object({}) if not provided\n const parameters = tool.parameters ?? z.object({});\n\n // if parameters is a Zod schema, ensure it's an object schema\n if (isZodSchema(parameters) && !isZodObjectSchema(parameters)) {\n throw new Error('Tool parameters must be a Zod object schema (z.object(...))');\n }\n\n // Ensure parameters is either a Zod schema or a plain object (JSON schema)\n if (!isZodSchema(parameters) && !(typeof parameters === 'object')) {\n throw new Error('Tool parameters must be a Zod object schema or a raw JSON schema');\n }\n\n return {\n type: 'function',\n description: tool.description,\n parameters,\n execute: tool.execute,\n [TOOL_SYMBOL]: true,\n [FUNCTION_TOOL_SYMBOL]: true,\n };\n }\n\n if (tool.config !== undefined && tool.id !== undefined) {\n return {\n type: 'provider-defined',\n id: tool.id,\n config: tool.config,\n [TOOL_SYMBOL]: true,\n [PROVIDER_DEFINED_TOOL_SYMBOL]: true,\n };\n }\n\n throw new Error('Invalid tool');\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isTool(tool: any): tool is Tool {\n return tool && tool[TOOL_SYMBOL] === true;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isFunctionTool(tool: any): tool is FunctionTool<any, any, any> {\n const isTool = tool && tool[TOOL_SYMBOL] === true;\n const isFunctionTool = tool[FUNCTION_TOOL_SYMBOL] === true;\n return isTool && isFunctionTool;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isProviderDefinedTool(tool: any): tool is ProviderDefinedTool {\n const isTool = tool && tool[TOOL_SYMBOL] === true;\n const isProviderDefinedTool = tool[PROVIDER_DEFINED_TOOL_SYMBOL] === true;\n return isTool && isProviderDefinedTool;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isToolError(error: any): error is ToolError {\n return error && error[TOOL_ERROR_SYMBOL] === true;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isAgentHandoff(handoff: any): handoff is AgentHandoff {\n return handoff && handoff[HANDOFF_SYMBOL] === true;\n}\n"],"mappings":"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","names":["tool","isTool","isFunctionTool","isProviderDefinedTool","handoff"]}
@@ -1,5 +1,4 @@
1
1
  import type { JSONSchema7 } from 'json-schema';
2
- import { ZodObject } from 'zod';
3
2
  import type { Agent } from '../voice/agent.js';
4
3
  import type { RunContext, UnknownUserData } from '../voice/run_context.js';
5
4
  declare const TOOL_SYMBOL: unique symbol;
@@ -11,7 +10,29 @@ export type JSONArray = JSONValue[];
11
10
  export type JSONObject = {
12
11
  [key: string]: JSONValue;
13
12
  };
14
- export type ToolInputSchema<T extends JSONObject> = ZodObject<any, any, any, T, T> | JSONSchema7;
13
+ export type ToolInputSchema<T = JSONObject> = {
14
+ _output: T;
15
+ } | {
16
+ '~standard': {
17
+ types?: {
18
+ output: T;
19
+ };
20
+ };
21
+ } | JSONSchema7;
22
+ /**
23
+ * Infer the output type from a ToolInputSchema.
24
+ * Adapted from Vercel AI SDK's InferSchema type.
25
+ * Source: https://github.com/vercel/ai/blob/main/packages/provider-utils/src/schema.ts#L72-L79
26
+ */
27
+ export type InferToolInput<T> = T extends {
28
+ _output: infer O;
29
+ } ? O : T extends {
30
+ '~standard': {
31
+ types?: {
32
+ output: infer O;
33
+ };
34
+ };
35
+ } ? O : any;
15
36
  export type ToolType = 'function' | 'provider-defined';
16
37
  export type ToolChoice = 'auto' | 'none' | 'required' | {
17
38
  type: 'function';
@@ -94,18 +115,25 @@ export interface FunctionTool<Parameters extends JSONObject, UserData = UnknownU
94
115
  export type ToolContext<UserData = UnknownUserData> = {
95
116
  [name: string]: FunctionTool<any, UserData, any>;
96
117
  };
118
+ export declare function isSameToolContext(ctx1: ToolContext, ctx2: ToolContext): boolean;
119
+ export declare function isSameToolChoice(choice1: ToolChoice | null, choice2: ToolChoice | null): boolean;
97
120
  /**
98
- * Create a function tool.
99
- *
100
- * @param description - The description of the tool.
101
- * @param parameters - The schema of the input that the tool expects. If not provided, defaults to z.object({}).
102
- * @param execute - The function that is called with the arguments from the tool call and produces a result.
121
+ * Create a function tool with inferred parameters from the schema.
103
122
  */
104
- export declare function tool<Parameters extends JSONObject = Record<string, never>, UserData = UnknownUserData, Result = unknown>({ description, parameters, execute, }: {
123
+ export declare function tool<Schema extends ToolInputSchema<any>, // eslint-disable-line @typescript-eslint/no-explicit-any -- Generic constraint needs to accept any JSONObject type
124
+ UserData = UnknownUserData, Result = unknown>({ description, parameters, execute, }: {
105
125
  description: string;
106
- parameters?: ToolInputSchema<Parameters>;
107
- execute: ToolExecuteFunction<Parameters, UserData, Result>;
108
- }): FunctionTool<Parameters, UserData, Result>;
126
+ parameters: Schema;
127
+ execute: ToolExecuteFunction<InferToolInput<Schema>, UserData, Result>;
128
+ }): FunctionTool<InferToolInput<Schema>, UserData, Result>;
129
+ /**
130
+ * Create a function tool without parameters.
131
+ */
132
+ export declare function tool<UserData = UnknownUserData, Result = unknown>({ description, execute, }: {
133
+ description: string;
134
+ parameters?: never;
135
+ execute: ToolExecuteFunction<Record<string, never>, UserData, Result>;
136
+ }): FunctionTool<Record<string, never>, UserData, Result>;
109
137
  /**
110
138
  * Create a provider-defined tool.
111
139
  *
@@ -1,5 +1,4 @@
1
1
  import type { JSONSchema7 } from 'json-schema';
2
- import { ZodObject } from 'zod';
3
2
  import type { Agent } from '../voice/agent.js';
4
3
  import type { RunContext, UnknownUserData } from '../voice/run_context.js';
5
4
  declare const TOOL_SYMBOL: unique symbol;
@@ -11,7 +10,29 @@ export type JSONArray = JSONValue[];
11
10
  export type JSONObject = {
12
11
  [key: string]: JSONValue;
13
12
  };
14
- export type ToolInputSchema<T extends JSONObject> = ZodObject<any, any, any, T, T> | JSONSchema7;
13
+ export type ToolInputSchema<T = JSONObject> = {
14
+ _output: T;
15
+ } | {
16
+ '~standard': {
17
+ types?: {
18
+ output: T;
19
+ };
20
+ };
21
+ } | JSONSchema7;
22
+ /**
23
+ * Infer the output type from a ToolInputSchema.
24
+ * Adapted from Vercel AI SDK's InferSchema type.
25
+ * Source: https://github.com/vercel/ai/blob/main/packages/provider-utils/src/schema.ts#L72-L79
26
+ */
27
+ export type InferToolInput<T> = T extends {
28
+ _output: infer O;
29
+ } ? O : T extends {
30
+ '~standard': {
31
+ types?: {
32
+ output: infer O;
33
+ };
34
+ };
35
+ } ? O : any;
15
36
  export type ToolType = 'function' | 'provider-defined';
16
37
  export type ToolChoice = 'auto' | 'none' | 'required' | {
17
38
  type: 'function';
@@ -94,18 +115,25 @@ export interface FunctionTool<Parameters extends JSONObject, UserData = UnknownU
94
115
  export type ToolContext<UserData = UnknownUserData> = {
95
116
  [name: string]: FunctionTool<any, UserData, any>;
96
117
  };
118
+ export declare function isSameToolContext(ctx1: ToolContext, ctx2: ToolContext): boolean;
119
+ export declare function isSameToolChoice(choice1: ToolChoice | null, choice2: ToolChoice | null): boolean;
97
120
  /**
98
- * Create a function tool.
99
- *
100
- * @param description - The description of the tool.
101
- * @param parameters - The schema of the input that the tool expects. If not provided, defaults to z.object({}).
102
- * @param execute - The function that is called with the arguments from the tool call and produces a result.
121
+ * Create a function tool with inferred parameters from the schema.
103
122
  */
104
- export declare function tool<Parameters extends JSONObject = Record<string, never>, UserData = UnknownUserData, Result = unknown>({ description, parameters, execute, }: {
123
+ export declare function tool<Schema extends ToolInputSchema<any>, // eslint-disable-line @typescript-eslint/no-explicit-any -- Generic constraint needs to accept any JSONObject type
124
+ UserData = UnknownUserData, Result = unknown>({ description, parameters, execute, }: {
105
125
  description: string;
106
- parameters?: ToolInputSchema<Parameters>;
107
- execute: ToolExecuteFunction<Parameters, UserData, Result>;
108
- }): FunctionTool<Parameters, UserData, Result>;
126
+ parameters: Schema;
127
+ execute: ToolExecuteFunction<InferToolInput<Schema>, UserData, Result>;
128
+ }): FunctionTool<InferToolInput<Schema>, UserData, Result>;
129
+ /**
130
+ * Create a function tool without parameters.
131
+ */
132
+ export declare function tool<UserData = UnknownUserData, Result = unknown>({ description, execute, }: {
133
+ description: string;
134
+ parameters?: never;
135
+ execute: ToolExecuteFunction<Record<string, never>, UserData, Result>;
136
+ }): FunctionTool<Record<string, never>, UserData, Result>;
109
137
  /**
110
138
  * Create a provider-defined tool.
111
139
  *
@@ -1 +1 @@
1
- {"version":3,"file":"tool_context.d.ts","sourceRoot":"","sources":["../../src/llm/tool_context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tool_context.d.ts","sourceRoot":"","sources":["../../src/llm/tool_context.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import { ZodObject, ZodType, z } from "zod";
1
+ import { z } from "zod";
2
+ import { isZodObjectSchema, isZodSchema } from "./zod-utils.js";
2
3
  const TOOL_SYMBOL = Symbol("tool");
3
4
  const FUNCTION_TOOL_SYMBOL = Symbol("function_tool");
4
5
  const PROVIDER_DEFINED_TOOL_SYMBOL = Symbol("provider_defined_tool");
@@ -19,13 +20,49 @@ function handoff(options) {
19
20
  [HANDOFF_SYMBOL]: true
20
21
  };
21
22
  }
23
+ function isSameToolContext(ctx1, ctx2) {
24
+ const toolNames = new Set(Object.keys(ctx1));
25
+ const toolNames2 = new Set(Object.keys(ctx2));
26
+ if (toolNames.size !== toolNames2.size) {
27
+ return false;
28
+ }
29
+ for (const name of toolNames) {
30
+ if (!toolNames2.has(name)) {
31
+ return false;
32
+ }
33
+ const tool1 = ctx1[name];
34
+ const tool2 = ctx2[name];
35
+ if (!tool1 || !tool2) {
36
+ return false;
37
+ }
38
+ if (tool1.description !== tool2.description) {
39
+ return false;
40
+ }
41
+ }
42
+ return true;
43
+ }
44
+ function isSameToolChoice(choice1, choice2) {
45
+ if (choice1 === choice2) {
46
+ return true;
47
+ }
48
+ if (choice1 === null || choice2 === null) {
49
+ return false;
50
+ }
51
+ if (typeof choice1 === "string" && typeof choice2 === "string") {
52
+ return choice1 === choice2;
53
+ }
54
+ if (typeof choice1 === "object" && typeof choice2 === "object") {
55
+ return choice1.type === choice2.type && choice1.function.name === choice2.function.name;
56
+ }
57
+ return false;
58
+ }
22
59
  function tool(tool2) {
23
60
  if (tool2.execute !== void 0) {
24
61
  const parameters = tool2.parameters ?? z.object({});
25
- if (parameters instanceof ZodType && parameters._def.typeName !== "ZodObject") {
62
+ if (isZodSchema(parameters) && !isZodObjectSchema(parameters)) {
26
63
  throw new Error("Tool parameters must be a Zod object schema (z.object(...))");
27
64
  }
28
- if (!(parameters instanceof ZodObject) && !(typeof parameters === "object")) {
65
+ if (!isZodSchema(parameters) && !(typeof parameters === "object")) {
29
66
  throw new Error("Tool parameters must be a Zod object schema or a raw JSON schema");
30
67
  }
31
68
  return {
@@ -73,6 +110,8 @@ export {
73
110
  isAgentHandoff,
74
111
  isFunctionTool,
75
112
  isProviderDefinedTool,
113
+ isSameToolChoice,
114
+ isSameToolContext,
76
115
  isTool,
77
116
  isToolError,
78
117
  tool
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/llm/tool_context.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { JSONSchema7 } from 'json-schema';\nimport { ZodObject, ZodType, z } from 'zod';\nimport type { Agent } from '../voice/agent.js';\nimport type { RunContext, UnknownUserData } from '../voice/run_context.js';\n\n// heavily inspired by Vercel AI's `tool()`:\n// https://github.com/vercel/ai/blob/3b0983b/packages/ai/core/tool/tool.ts\n\nconst TOOL_SYMBOL = Symbol('tool');\nconst FUNCTION_TOOL_SYMBOL = Symbol('function_tool');\nconst PROVIDER_DEFINED_TOOL_SYMBOL = Symbol('provider_defined_tool');\nconst TOOL_ERROR_SYMBOL = Symbol('tool_error');\nconst HANDOFF_SYMBOL = Symbol('handoff');\n\nexport type JSONValue = null | string | number | boolean | JSONObject | JSONArray;\n\nexport type JSONArray = JSONValue[];\n\nexport type JSONObject = {\n [key: string]: JSONValue;\n};\n\n// TODO(AJS-111): support Zod cross-version compatibility, raw JSON schema, both strict and non-strict versions\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type ToolInputSchema<T extends JSONObject> = ZodObject<any, any, any, T, T> | JSONSchema7;\n\nexport type ToolType = 'function' | 'provider-defined';\n\nexport type ToolChoice =\n | 'auto'\n | 'none'\n | 'required'\n | {\n type: 'function';\n function: {\n name: string;\n };\n };\n\nexport class ToolError extends Error {\n constructor(message: string) {\n super(message);\n\n Object.defineProperty(this, TOOL_ERROR_SYMBOL, {\n value: true,\n });\n }\n}\n\nexport interface AgentHandoff {\n /**\n * The agent to handoff to.\n */\n agent: Agent;\n\n /**\n * The return value of the tool.\n */\n returns?: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n [HANDOFF_SYMBOL]: true;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function handoff(options: { agent: Agent; returns?: any }): AgentHandoff {\n return {\n agent: options.agent,\n returns: options.returns,\n [HANDOFF_SYMBOL]: true,\n };\n}\n\nexport interface ToolOptions<UserData = UnknownUserData> {\n /**\n * RunContext for the current agent session.\n */\n ctx: RunContext<UserData>;\n\n /**\n * The ID of the tool call.\n */\n toolCallId: string;\n\n /**\n * An optional abort signal that indicates that the overall operation should be aborted.\n */\n abortSignal?: AbortSignal;\n}\n\nexport type ToolExecuteFunction<\n Parameters extends JSONObject,\n UserData = UnknownUserData,\n Result = unknown,\n> = (args: Parameters, opts: ToolOptions<UserData>) => Promise<Result>;\n\nexport interface Tool {\n /**\n * The type of the tool.\n * @internal Either user-defined core tool or provider-defined tool.\n */\n type: ToolType;\n\n [TOOL_SYMBOL]: true;\n}\n\n// TODO(AJS-112): support provider-defined tools\nexport interface ProviderDefinedTool extends Tool {\n type: 'provider-defined';\n\n /**\n * The ID of the tool.\n */\n id: string;\n\n /**\n * The configuration of the tool.\n */\n config: Record<string, unknown>;\n\n [PROVIDER_DEFINED_TOOL_SYMBOL]: true;\n}\n\nexport interface FunctionTool<\n Parameters extends JSONObject,\n UserData = UnknownUserData,\n Result = unknown,\n> extends Tool {\n type: 'function';\n\n /**\n * The description of the tool. Will be used by the language model to decide whether to use the tool.\n */\n description: string;\n\n /**\n * The schema of the input that the tool expects. The language model will use this to generate the input.\n * It is also used to validate the output of the language model.\n * Use descriptions to make the input understandable for the language model.\n */\n parameters: ToolInputSchema<Parameters>;\n\n /**\n * An async function that is called with the arguments from the tool call and produces a result.\n * It also carries context about current session, user-defined data, and the tool call id, etc.\n */\n execute: ToolExecuteFunction<Parameters, UserData, Result>;\n\n [FUNCTION_TOOL_SYMBOL]: true;\n}\n\n// TODO(AJS-112): support provider-defined tools in the future)\nexport type ToolContext<UserData = UnknownUserData> = {\n [name: string]: FunctionTool<any, UserData, any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n};\n\n/**\n * Create a function tool.\n *\n * @param description - The description of the tool.\n * @param parameters - The schema of the input that the tool expects. If not provided, defaults to z.object({}).\n * @param execute - The function that is called with the arguments from the tool call and produces a result.\n */\nexport function tool<\n Parameters extends JSONObject = Record<string, never>,\n UserData = UnknownUserData,\n Result = unknown,\n>({\n description,\n parameters,\n execute,\n}: {\n description: string;\n parameters?: ToolInputSchema<Parameters>;\n execute: ToolExecuteFunction<Parameters, UserData, Result>;\n}): FunctionTool<Parameters, UserData, Result>;\n\n/**\n * Create a provider-defined tool.\n *\n * @param id - The ID of the tool.\n * @param config - The configuration of the tool.\n */\nexport function tool({\n id,\n config,\n}: {\n id: string;\n config: Record<string, unknown>;\n}): ProviderDefinedTool;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function tool(tool: any): any {\n if (tool.execute !== undefined) {\n // Default parameters to z.object({}) if not provided\n const parameters = tool.parameters ?? z.object({});\n\n // if parameters is not zod object, throw an error\n if (parameters instanceof ZodType && parameters._def.typeName !== 'ZodObject') {\n throw new Error('Tool parameters must be a Zod object schema (z.object(...))');\n }\n\n if (!(parameters instanceof ZodObject) && !(typeof parameters === 'object')) {\n throw new Error('Tool parameters must be a Zod object schema or a raw JSON schema');\n }\n\n return {\n type: 'function',\n description: tool.description,\n parameters,\n execute: tool.execute,\n [TOOL_SYMBOL]: true,\n [FUNCTION_TOOL_SYMBOL]: true,\n };\n }\n\n if (tool.config !== undefined && tool.id !== undefined) {\n return {\n type: 'provider-defined',\n id: tool.id,\n config: tool.config,\n [TOOL_SYMBOL]: true,\n [PROVIDER_DEFINED_TOOL_SYMBOL]: true,\n };\n }\n\n throw new Error('Invalid tool');\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isTool(tool: any): tool is Tool {\n return tool && tool[TOOL_SYMBOL] === true;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isFunctionTool(tool: any): tool is FunctionTool<any, any, any> {\n const isTool = tool && tool[TOOL_SYMBOL] === true;\n const isFunctionTool = tool[FUNCTION_TOOL_SYMBOL] === true;\n return isTool && isFunctionTool;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isProviderDefinedTool(tool: any): tool is ProviderDefinedTool {\n const isTool = tool && tool[TOOL_SYMBOL] === true;\n const isProviderDefinedTool = tool[PROVIDER_DEFINED_TOOL_SYMBOL] === true;\n return isTool && isProviderDefinedTool;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isToolError(error: any): error is ToolError {\n return error && error[TOOL_ERROR_SYMBOL] === true;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isAgentHandoff(handoff: any): handoff is AgentHandoff {\n return handoff && handoff[HANDOFF_SYMBOL] === true;\n}\n"],"mappings":"AAIA,SAAS,WAAW,SAAS,SAAS;AAOtC,MAAM,cAAc,OAAO,MAAM;AACjC,MAAM,uBAAuB,OAAO,eAAe;AACnD,MAAM,+BAA+B,OAAO,uBAAuB;AACnE,MAAM,oBAAoB,OAAO,YAAY;AAC7C,MAAM,iBAAiB,OAAO,SAAS;AA2BhC,MAAM,kBAAkB,MAAM;AAAA,EACnC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AAEb,WAAO,eAAe,MAAM,mBAAmB;AAAA,MAC7C,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF;AAiBO,SAAS,QAAQ,SAAwD;AAC9E,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf,SAAS,QAAQ;AAAA,IACjB,CAAC,cAAc,GAAG;AAAA,EACpB;AACF;AAyHO,SAAS,KAAKA,OAAgB;AACnC,MAAIA,MAAK,YAAY,QAAW;AAE9B,UAAM,aAAaA,MAAK,cAAc,EAAE,OAAO,CAAC,CAAC;AAGjD,QAAI,sBAAsB,WAAW,WAAW,KAAK,aAAa,aAAa;AAC7E,YAAM,IAAI,MAAM,6DAA6D;AAAA,IAC/E;AAEA,QAAI,EAAE,sBAAsB,cAAc,EAAE,OAAO,eAAe,WAAW;AAC3E,YAAM,IAAI,MAAM,kEAAkE;AAAA,IACpF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAaA,MAAK;AAAA,MAClB;AAAA,MACA,SAASA,MAAK;AAAA,MACd,CAAC,WAAW,GAAG;AAAA,MACf,CAAC,oBAAoB,GAAG;AAAA,IAC1B;AAAA,EACF;AAEA,MAAIA,MAAK,WAAW,UAAaA,MAAK,OAAO,QAAW;AACtD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,IAAIA,MAAK;AAAA,MACT,QAAQA,MAAK;AAAA,MACb,CAAC,WAAW,GAAG;AAAA,MACf,CAAC,4BAA4B,GAAG;AAAA,IAClC;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,cAAc;AAChC;AAGO,SAAS,OAAOA,OAAyB;AAC9C,SAAOA,SAAQA,MAAK,WAAW,MAAM;AACvC;AAGO,SAAS,eAAeA,OAAgD;AAC7E,QAAMC,UAASD,SAAQA,MAAK,WAAW,MAAM;AAC7C,QAAME,kBAAiBF,MAAK,oBAAoB,MAAM;AACtD,SAAOC,WAAUC;AACnB;AAGO,SAAS,sBAAsBF,OAAwC;AAC5E,QAAMC,UAASD,SAAQA,MAAK,WAAW,MAAM;AAC7C,QAAMG,yBAAwBH,MAAK,4BAA4B,MAAM;AACrE,SAAOC,WAAUE;AACnB;AAGO,SAAS,YAAY,OAAgC;AAC1D,SAAO,SAAS,MAAM,iBAAiB,MAAM;AAC/C;AAGO,SAAS,eAAeC,UAAuC;AACpE,SAAOA,YAAWA,SAAQ,cAAc,MAAM;AAChD;","names":["tool","isTool","isFunctionTool","isProviderDefinedTool","handoff"]}
1
+ {"version":3,"sources":["../../src/llm/tool_context.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { JSONSchema7 } from 'json-schema';\nimport { z } from 'zod';\nimport type { Agent } from '../voice/agent.js';\nimport type { RunContext, UnknownUserData } from '../voice/run_context.js';\nimport { isZodObjectSchema, isZodSchema } from './zod-utils.js';\n\n// heavily inspired by Vercel AI's `tool()`:\n// https://github.com/vercel/ai/blob/3b0983b/packages/ai/core/tool/tool.ts\n\nconst TOOL_SYMBOL = Symbol('tool');\nconst FUNCTION_TOOL_SYMBOL = Symbol('function_tool');\nconst PROVIDER_DEFINED_TOOL_SYMBOL = Symbol('provider_defined_tool');\nconst TOOL_ERROR_SYMBOL = Symbol('tool_error');\nconst HANDOFF_SYMBOL = Symbol('handoff');\n\nexport type JSONValue = null | string | number | boolean | JSONObject | JSONArray;\n\nexport type JSONArray = JSONValue[];\n\nexport type JSONObject = {\n [key: string]: JSONValue;\n};\n\n// Supports both Zod v3 and v4 schemas, as well as raw JSON schema\n// Adapted from Vercel AI SDK's FlexibleSchema approach\n// Source: https://github.com/vercel/ai/blob/main/packages/provider-utils/src/schema.ts#L67-L70\n//\n// Vercel uses StandardSchemaV1 from @standard-schema/spec package.\n// We use a simpler approach by directly checking for schema properties:\n// - Zod v3: Has `_output` property\n// - Zod v4: Implements Standard Schema spec with `~standard` property\n// - JSON Schema: Plain object fallback\nexport type ToolInputSchema<T = JSONObject> =\n | {\n // Zod v3 schema - has _output property for type inference\n _output: T;\n }\n | {\n // Zod v4 schema (Standard Schema) - has ~standard property\n '~standard': {\n types?: { output: T };\n };\n }\n | JSONSchema7;\n\n/**\n * Infer the output type from a ToolInputSchema.\n * Adapted from Vercel AI SDK's InferSchema type.\n * Source: https://github.com/vercel/ai/blob/main/packages/provider-utils/src/schema.ts#L72-L79\n */\nexport type InferToolInput<T> = T extends { _output: infer O }\n ? O\n : T extends { '~standard': { types?: { output: infer O } } }\n ? O\n : any; // eslint-disable-line @typescript-eslint/no-explicit-any -- Fallback type for JSON Schema objects without type inference\n\nexport type ToolType = 'function' | 'provider-defined';\n\nexport type ToolChoice =\n | 'auto'\n | 'none'\n | 'required'\n | {\n type: 'function';\n function: {\n name: string;\n };\n };\n\nexport class ToolError extends Error {\n constructor(message: string) {\n super(message);\n\n Object.defineProperty(this, TOOL_ERROR_SYMBOL, {\n value: true,\n });\n }\n}\n\nexport interface AgentHandoff {\n /**\n * The agent to handoff to.\n */\n agent: Agent;\n\n /**\n * The return value of the tool.\n */\n returns?: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n [HANDOFF_SYMBOL]: true;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function handoff(options: { agent: Agent; returns?: any }): AgentHandoff {\n return {\n agent: options.agent,\n returns: options.returns,\n [HANDOFF_SYMBOL]: true,\n };\n}\n\nexport interface ToolOptions<UserData = UnknownUserData> {\n /**\n * RunContext for the current agent session.\n */\n ctx: RunContext<UserData>;\n\n /**\n * The ID of the tool call.\n */\n toolCallId: string;\n\n /**\n * An optional abort signal that indicates that the overall operation should be aborted.\n */\n abortSignal?: AbortSignal;\n}\n\nexport type ToolExecuteFunction<\n Parameters extends JSONObject,\n UserData = UnknownUserData,\n Result = unknown,\n> = (args: Parameters, opts: ToolOptions<UserData>) => Promise<Result>;\n\nexport interface Tool {\n /**\n * The type of the tool.\n * @internal Either user-defined core tool or provider-defined tool.\n */\n type: ToolType;\n\n [TOOL_SYMBOL]: true;\n}\n\n// TODO(AJS-112): support provider-defined tools\nexport interface ProviderDefinedTool extends Tool {\n type: 'provider-defined';\n\n /**\n * The ID of the tool.\n */\n id: string;\n\n /**\n * The configuration of the tool.\n */\n config: Record<string, unknown>;\n\n [PROVIDER_DEFINED_TOOL_SYMBOL]: true;\n}\n\nexport interface FunctionTool<\n Parameters extends JSONObject,\n UserData = UnknownUserData,\n Result = unknown,\n> extends Tool {\n type: 'function';\n\n /**\n * The description of the tool. Will be used by the language model to decide whether to use the tool.\n */\n description: string;\n\n /**\n * The schema of the input that the tool expects. The language model will use this to generate the input.\n * It is also used to validate the output of the language model.\n * Use descriptions to make the input understandable for the language model.\n */\n parameters: ToolInputSchema<Parameters>;\n\n /**\n * An async function that is called with the arguments from the tool call and produces a result.\n * It also carries context about current session, user-defined data, and the tool call id, etc.\n */\n execute: ToolExecuteFunction<Parameters, UserData, Result>;\n\n [FUNCTION_TOOL_SYMBOL]: true;\n}\n\n// TODO(AJS-112): support provider-defined tools in the future)\nexport type ToolContext<UserData = UnknownUserData> = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Generic tool registry needs to accept any parameter/result types\n [name: string]: FunctionTool<any, UserData, any>;\n};\n\nexport function isSameToolContext(ctx1: ToolContext, ctx2: ToolContext): boolean {\n const toolNames = new Set(Object.keys(ctx1));\n const toolNames2 = new Set(Object.keys(ctx2));\n\n if (toolNames.size !== toolNames2.size) {\n return false;\n }\n\n for (const name of toolNames) {\n if (!toolNames2.has(name)) {\n return false;\n }\n\n const tool1 = ctx1[name];\n const tool2 = ctx2[name];\n\n if (!tool1 || !tool2) {\n return false;\n }\n\n if (tool1.description !== tool2.description) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function isSameToolChoice(choice1: ToolChoice | null, choice2: ToolChoice | null): boolean {\n if (choice1 === choice2) {\n return true;\n }\n if (choice1 === null || choice2 === null) {\n return false;\n }\n if (typeof choice1 === 'string' && typeof choice2 === 'string') {\n return choice1 === choice2;\n }\n if (typeof choice1 === 'object' && typeof choice2 === 'object') {\n return choice1.type === choice2.type && choice1.function.name === choice2.function.name;\n }\n return false;\n}\n\n/**\n * Create a function tool with inferred parameters from the schema.\n */\nexport function tool<\n Schema extends ToolInputSchema<any>, // eslint-disable-line @typescript-eslint/no-explicit-any -- Generic constraint needs to accept any JSONObject type\n UserData = UnknownUserData,\n Result = unknown,\n>({\n description,\n parameters,\n execute,\n}: {\n description: string;\n parameters: Schema;\n execute: ToolExecuteFunction<InferToolInput<Schema>, UserData, Result>;\n}): FunctionTool<InferToolInput<Schema>, UserData, Result>;\n\n/**\n * Create a function tool without parameters.\n */\nexport function tool<UserData = UnknownUserData, Result = unknown>({\n description,\n execute,\n}: {\n description: string;\n parameters?: never;\n execute: ToolExecuteFunction<Record<string, never>, UserData, Result>;\n}): FunctionTool<Record<string, never>, UserData, Result>;\n\n/**\n * Create a provider-defined tool.\n *\n * @param id - The ID of the tool.\n * @param config - The configuration of the tool.\n */\nexport function tool({\n id,\n config,\n}: {\n id: string;\n config: Record<string, unknown>;\n}): ProviderDefinedTool;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function tool(tool: any): any {\n if (tool.execute !== undefined) {\n // Default parameters to z.object({}) if not provided\n const parameters = tool.parameters ?? z.object({});\n\n // if parameters is a Zod schema, ensure it's an object schema\n if (isZodSchema(parameters) && !isZodObjectSchema(parameters)) {\n throw new Error('Tool parameters must be a Zod object schema (z.object(...))');\n }\n\n // Ensure parameters is either a Zod schema or a plain object (JSON schema)\n if (!isZodSchema(parameters) && !(typeof parameters === 'object')) {\n throw new Error('Tool parameters must be a Zod object schema or a raw JSON schema');\n }\n\n return {\n type: 'function',\n description: tool.description,\n parameters,\n execute: tool.execute,\n [TOOL_SYMBOL]: true,\n [FUNCTION_TOOL_SYMBOL]: true,\n };\n }\n\n if (tool.config !== undefined && tool.id !== undefined) {\n return {\n type: 'provider-defined',\n id: tool.id,\n config: tool.config,\n [TOOL_SYMBOL]: true,\n [PROVIDER_DEFINED_TOOL_SYMBOL]: true,\n };\n }\n\n throw new Error('Invalid tool');\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isTool(tool: any): tool is Tool {\n return tool && tool[TOOL_SYMBOL] === true;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isFunctionTool(tool: any): tool is FunctionTool<any, any, any> {\n const isTool = tool && tool[TOOL_SYMBOL] === true;\n const isFunctionTool = tool[FUNCTION_TOOL_SYMBOL] === true;\n return isTool && isFunctionTool;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isProviderDefinedTool(tool: any): tool is ProviderDefinedTool {\n const isTool = tool && tool[TOOL_SYMBOL] === true;\n const isProviderDefinedTool = tool[PROVIDER_DEFINED_TOOL_SYMBOL] === true;\n return isTool && isProviderDefinedTool;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isToolError(error: any): error is ToolError {\n return error && error[TOOL_ERROR_SYMBOL] === true;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isAgentHandoff(handoff: any): handoff is AgentHandoff {\n return handoff && handoff[HANDOFF_SYMBOL] === true;\n}\n"],"mappings":"AAIA,SAAS,SAAS;AAGlB,SAAS,mBAAmB,mBAAmB;AAK/C,MAAM,cAAc,OAAO,MAAM;AACjC,MAAM,uBAAuB,OAAO,eAAe;AACnD,MAAM,+BAA+B,OAAO,uBAAuB;AACnE,MAAM,oBAAoB,OAAO,YAAY;AAC7C,MAAM,iBAAiB,OAAO,SAAS;AAwDhC,MAAM,kBAAkB,MAAM;AAAA,EACnC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AAEb,WAAO,eAAe,MAAM,mBAAmB;AAAA,MAC7C,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF;AAiBO,SAAS,QAAQ,SAAwD;AAC9E,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf,SAAS,QAAQ;AAAA,IACjB,CAAC,cAAc,GAAG;AAAA,EACpB;AACF;AAsFO,SAAS,kBAAkB,MAAmB,MAA4B;AAC/E,QAAM,YAAY,IAAI,IAAI,OAAO,KAAK,IAAI,CAAC;AAC3C,QAAM,aAAa,IAAI,IAAI,OAAO,KAAK,IAAI,CAAC;AAE5C,MAAI,UAAU,SAAS,WAAW,MAAM;AACtC,WAAO;AAAA,EACT;AAEA,aAAW,QAAQ,WAAW;AAC5B,QAAI,CAAC,WAAW,IAAI,IAAI,GAAG;AACzB,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,KAAK,IAAI;AACvB,UAAM,QAAQ,KAAK,IAAI;AAEvB,QAAI,CAAC,SAAS,CAAC,OAAO;AACpB,aAAO;AAAA,IACT;AAEA,QAAI,MAAM,gBAAgB,MAAM,aAAa;AAC3C,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,iBAAiB,SAA4B,SAAqC;AAChG,MAAI,YAAY,SAAS;AACvB,WAAO;AAAA,EACT;AACA,MAAI,YAAY,QAAQ,YAAY,MAAM;AACxC,WAAO;AAAA,EACT;AACA,MAAI,OAAO,YAAY,YAAY,OAAO,YAAY,UAAU;AAC9D,WAAO,YAAY;AAAA,EACrB;AACA,MAAI,OAAO,YAAY,YAAY,OAAO,YAAY,UAAU;AAC9D,WAAO,QAAQ,SAAS,QAAQ,QAAQ,QAAQ,SAAS,SAAS,QAAQ,SAAS;AAAA,EACrF;AACA,SAAO;AACT;AA8CO,SAAS,KAAKA,OAAgB;AACnC,MAAIA,MAAK,YAAY,QAAW;AAE9B,UAAM,aAAaA,MAAK,cAAc,EAAE,OAAO,CAAC,CAAC;AAGjD,QAAI,YAAY,UAAU,KAAK,CAAC,kBAAkB,UAAU,GAAG;AAC7D,YAAM,IAAI,MAAM,6DAA6D;AAAA,IAC/E;AAGA,QAAI,CAAC,YAAY,UAAU,KAAK,EAAE,OAAO,eAAe,WAAW;AACjE,YAAM,IAAI,MAAM,kEAAkE;AAAA,IACpF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAaA,MAAK;AAAA,MAClB;AAAA,MACA,SAASA,MAAK;AAAA,MACd,CAAC,WAAW,GAAG;AAAA,MACf,CAAC,oBAAoB,GAAG;AAAA,IAC1B;AAAA,EACF;AAEA,MAAIA,MAAK,WAAW,UAAaA,MAAK,OAAO,QAAW;AACtD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,IAAIA,MAAK;AAAA,MACT,QAAQA,MAAK;AAAA,MACb,CAAC,WAAW,GAAG;AAAA,MACf,CAAC,4BAA4B,GAAG;AAAA,IAClC;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,cAAc;AAChC;AAGO,SAAS,OAAOA,OAAyB;AAC9C,SAAOA,SAAQA,MAAK,WAAW,MAAM;AACvC;AAGO,SAAS,eAAeA,OAAgD;AAC7E,QAAMC,UAASD,SAAQA,MAAK,WAAW,MAAM;AAC7C,QAAME,kBAAiBF,MAAK,oBAAoB,MAAM;AACtD,SAAOC,WAAUC;AACnB;AAGO,SAAS,sBAAsBF,OAAwC;AAC5E,QAAMC,UAASD,SAAQA,MAAK,WAAW,MAAM;AAC7C,QAAMG,yBAAwBH,MAAK,4BAA4B,MAAM;AACrE,SAAOC,WAAUE;AACnB;AAGO,SAAS,YAAY,OAAgC;AAC1D,SAAO,SAAS,MAAM,iBAAiB,MAAM;AAC/C;AAGO,SAAS,eAAeC,UAAuC;AACpE,SAAOA,YAAWA,SAAQ,cAAc,MAAM;AAChD;","names":["tool","isTool","isFunctionTool","isProviderDefinedTool","handoff"]}