illuma-agents 1.0.7 → 1.0.9

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 (237) hide show
  1. package/LICENSE +1 -5
  2. package/dist/cjs/common/enum.cjs +1 -2
  3. package/dist/cjs/common/enum.cjs.map +1 -1
  4. package/dist/cjs/instrumentation.cjs.map +1 -1
  5. package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
  6. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +79 -2
  7. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  8. package/dist/cjs/llm/anthropic/utils/tools.cjs.map +1 -1
  9. package/dist/cjs/llm/bedrock/index.cjs +99 -0
  10. package/dist/cjs/llm/bedrock/index.cjs.map +1 -0
  11. package/dist/cjs/llm/fake.cjs.map +1 -1
  12. package/dist/cjs/llm/google/index.cjs +78 -9
  13. package/dist/cjs/llm/google/index.cjs.map +1 -1
  14. package/dist/cjs/llm/google/utils/common.cjs +185 -28
  15. package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
  16. package/dist/cjs/llm/providers.cjs +13 -16
  17. package/dist/cjs/llm/providers.cjs.map +1 -1
  18. package/dist/cjs/llm/text.cjs.map +1 -1
  19. package/dist/cjs/messages/core.cjs +14 -14
  20. package/dist/cjs/messages/core.cjs.map +1 -1
  21. package/dist/cjs/messages/ids.cjs.map +1 -1
  22. package/dist/cjs/messages/prune.cjs.map +1 -1
  23. package/dist/cjs/run.cjs +10 -1
  24. package/dist/cjs/run.cjs.map +1 -1
  25. package/dist/cjs/splitStream.cjs.map +1 -1
  26. package/dist/cjs/stream.cjs +4 -1
  27. package/dist/cjs/stream.cjs.map +1 -1
  28. package/dist/cjs/tools/ToolNode.cjs +163 -55
  29. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  30. package/dist/cjs/tools/handlers.cjs +29 -25
  31. package/dist/cjs/tools/handlers.cjs.map +1 -1
  32. package/dist/cjs/tools/search/anthropic.cjs.map +1 -1
  33. package/dist/cjs/tools/search/content.cjs.map +1 -1
  34. package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
  35. package/dist/cjs/tools/search/format.cjs.map +1 -1
  36. package/dist/cjs/tools/search/highlights.cjs.map +1 -1
  37. package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
  38. package/dist/cjs/tools/search/schema.cjs +25 -25
  39. package/dist/cjs/tools/search/schema.cjs.map +1 -1
  40. package/dist/cjs/tools/search/search.cjs +6 -1
  41. package/dist/cjs/tools/search/search.cjs.map +1 -1
  42. package/dist/cjs/tools/search/serper-scraper.cjs.map +1 -1
  43. package/dist/cjs/tools/search/tool.cjs +162 -35
  44. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  45. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  46. package/dist/cjs/utils/graph.cjs.map +1 -1
  47. package/dist/cjs/utils/llm.cjs +0 -1
  48. package/dist/cjs/utils/llm.cjs.map +1 -1
  49. package/dist/cjs/utils/misc.cjs.map +1 -1
  50. package/dist/cjs/utils/run.cjs.map +1 -1
  51. package/dist/cjs/utils/title.cjs +7 -7
  52. package/dist/cjs/utils/title.cjs.map +1 -1
  53. package/dist/esm/common/enum.mjs +1 -2
  54. package/dist/esm/common/enum.mjs.map +1 -1
  55. package/dist/esm/instrumentation.mjs.map +1 -1
  56. package/dist/esm/llm/anthropic/types.mjs.map +1 -1
  57. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +79 -2
  58. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  59. package/dist/esm/llm/anthropic/utils/tools.mjs.map +1 -1
  60. package/dist/esm/llm/bedrock/index.mjs +97 -0
  61. package/dist/esm/llm/bedrock/index.mjs.map +1 -0
  62. package/dist/esm/llm/fake.mjs.map +1 -1
  63. package/dist/esm/llm/google/index.mjs +79 -10
  64. package/dist/esm/llm/google/index.mjs.map +1 -1
  65. package/dist/esm/llm/google/utils/common.mjs +184 -30
  66. package/dist/esm/llm/google/utils/common.mjs.map +1 -1
  67. package/dist/esm/llm/providers.mjs +2 -5
  68. package/dist/esm/llm/providers.mjs.map +1 -1
  69. package/dist/esm/llm/text.mjs.map +1 -1
  70. package/dist/esm/messages/core.mjs +14 -14
  71. package/dist/esm/messages/core.mjs.map +1 -1
  72. package/dist/esm/messages/ids.mjs.map +1 -1
  73. package/dist/esm/messages/prune.mjs.map +1 -1
  74. package/dist/esm/run.mjs +10 -1
  75. package/dist/esm/run.mjs.map +1 -1
  76. package/dist/esm/splitStream.mjs.map +1 -1
  77. package/dist/esm/stream.mjs +4 -1
  78. package/dist/esm/stream.mjs.map +1 -1
  79. package/dist/esm/tools/ToolNode.mjs +164 -56
  80. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  81. package/dist/esm/tools/handlers.mjs +30 -26
  82. package/dist/esm/tools/handlers.mjs.map +1 -1
  83. package/dist/esm/tools/search/anthropic.mjs.map +1 -1
  84. package/dist/esm/tools/search/content.mjs.map +1 -1
  85. package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
  86. package/dist/esm/tools/search/format.mjs.map +1 -1
  87. package/dist/esm/tools/search/highlights.mjs.map +1 -1
  88. package/dist/esm/tools/search/rerankers.mjs.map +1 -1
  89. package/dist/esm/tools/search/schema.mjs +25 -25
  90. package/dist/esm/tools/search/schema.mjs.map +1 -1
  91. package/dist/esm/tools/search/search.mjs +6 -1
  92. package/dist/esm/tools/search/search.mjs.map +1 -1
  93. package/dist/esm/tools/search/serper-scraper.mjs.map +1 -1
  94. package/dist/esm/tools/search/tool.mjs +162 -35
  95. package/dist/esm/tools/search/tool.mjs.map +1 -1
  96. package/dist/esm/tools/search/utils.mjs.map +1 -1
  97. package/dist/esm/utils/graph.mjs.map +1 -1
  98. package/dist/esm/utils/llm.mjs +0 -1
  99. package/dist/esm/utils/llm.mjs.map +1 -1
  100. package/dist/esm/utils/misc.mjs.map +1 -1
  101. package/dist/esm/utils/run.mjs.map +1 -1
  102. package/dist/esm/utils/title.mjs +7 -7
  103. package/dist/esm/utils/title.mjs.map +1 -1
  104. package/dist/types/common/enum.d.ts +1 -2
  105. package/dist/types/llm/bedrock/index.d.ts +36 -0
  106. package/dist/types/llm/google/index.d.ts +10 -0
  107. package/dist/types/llm/google/types.d.ts +11 -1
  108. package/dist/types/llm/google/utils/common.d.ts +17 -2
  109. package/dist/types/tools/ToolNode.d.ts +9 -1
  110. package/dist/types/tools/search/types.d.ts +2 -0
  111. package/dist/types/types/llm.d.ts +3 -8
  112. package/dist/types/types/tools.d.ts +1 -1
  113. package/package.json +15 -11
  114. package/src/common/enum.ts +1 -2
  115. package/src/common/index.ts +1 -1
  116. package/src/instrumentation.ts +22 -22
  117. package/src/llm/anthropic/llm.spec.ts +1442 -1442
  118. package/src/llm/anthropic/types.ts +140 -140
  119. package/src/llm/anthropic/utils/message_inputs.ts +757 -660
  120. package/src/llm/anthropic/utils/output_parsers.ts +133 -133
  121. package/src/llm/anthropic/utils/tools.ts +29 -29
  122. package/src/llm/bedrock/index.ts +128 -0
  123. package/src/llm/fake.ts +133 -133
  124. package/src/llm/google/data/gettysburg10.wav +0 -0
  125. package/src/llm/google/data/hotdog.jpg +0 -0
  126. package/src/llm/google/index.ts +129 -14
  127. package/src/llm/google/llm.spec.ts +932 -0
  128. package/src/llm/google/types.ts +56 -43
  129. package/src/llm/google/utils/common.ts +873 -660
  130. package/src/llm/google/utils/tools.ts +160 -160
  131. package/src/llm/openai/types.ts +24 -24
  132. package/src/llm/openai/utils/isReasoningModel.test.ts +90 -90
  133. package/src/llm/providers.ts +2 -7
  134. package/src/llm/text.ts +94 -94
  135. package/src/messages/core.ts +463 -463
  136. package/src/messages/formatAgentMessages.tools.test.ts +400 -400
  137. package/src/messages/formatMessage.test.ts +693 -693
  138. package/src/messages/ids.ts +26 -26
  139. package/src/messages/prune.ts +567 -567
  140. package/src/messages/shiftIndexTokenCountMap.test.ts +81 -81
  141. package/src/mockStream.ts +98 -98
  142. package/src/prompts/collab.ts +5 -5
  143. package/src/prompts/index.ts +1 -1
  144. package/src/prompts/taskmanager.ts +61 -61
  145. package/src/run.ts +13 -4
  146. package/src/scripts/ant_web_search_edge_case.ts +162 -0
  147. package/src/scripts/ant_web_search_error_edge_case.ts +148 -0
  148. package/src/scripts/args.ts +48 -48
  149. package/src/scripts/caching.ts +123 -123
  150. package/src/scripts/code_exec_files.ts +193 -193
  151. package/src/scripts/empty_input.ts +137 -137
  152. package/src/scripts/image.ts +178 -178
  153. package/src/scripts/memory.ts +97 -97
  154. package/src/scripts/thinking.ts +149 -149
  155. package/src/specs/anthropic.simple.test.ts +67 -0
  156. package/src/specs/spec.utils.ts +3 -3
  157. package/src/specs/token-distribution-edge-case.test.ts +316 -316
  158. package/src/specs/tool-error.test.ts +193 -193
  159. package/src/splitStream.test.ts +691 -691
  160. package/src/splitStream.ts +234 -234
  161. package/src/stream.test.ts +94 -94
  162. package/src/stream.ts +4 -1
  163. package/src/tools/ToolNode.ts +206 -64
  164. package/src/tools/handlers.ts +32 -28
  165. package/src/tools/search/anthropic.ts +51 -51
  166. package/src/tools/search/content.test.ts +173 -173
  167. package/src/tools/search/content.ts +147 -147
  168. package/src/tools/search/direct-url.test.ts +530 -0
  169. package/src/tools/search/firecrawl.ts +210 -210
  170. package/src/tools/search/format.ts +250 -250
  171. package/src/tools/search/highlights.ts +320 -320
  172. package/src/tools/search/index.ts +2 -2
  173. package/src/tools/search/jina-reranker.test.ts +126 -126
  174. package/src/tools/search/output.md +2775 -2775
  175. package/src/tools/search/rerankers.ts +242 -242
  176. package/src/tools/search/schema.ts +63 -63
  177. package/src/tools/search/search.ts +766 -759
  178. package/src/tools/search/serper-scraper.ts +155 -155
  179. package/src/tools/search/test.html +883 -883
  180. package/src/tools/search/test.md +642 -642
  181. package/src/tools/search/test.ts +159 -159
  182. package/src/tools/search/tool.ts +619 -471
  183. package/src/tools/search/types.ts +689 -687
  184. package/src/tools/search/utils.ts +79 -79
  185. package/src/types/index.ts +6 -6
  186. package/src/types/llm.ts +2 -8
  187. package/src/types/tools.ts +80 -80
  188. package/src/utils/graph.ts +10 -10
  189. package/src/utils/llm.ts +26 -27
  190. package/src/utils/llmConfig.ts +5 -3
  191. package/src/utils/logging.ts +48 -48
  192. package/src/utils/misc.ts +57 -57
  193. package/src/utils/run.ts +100 -100
  194. package/src/utils/title.ts +165 -165
  195. package/dist/cjs/llm/ollama/index.cjs +0 -70
  196. package/dist/cjs/llm/ollama/index.cjs.map +0 -1
  197. package/dist/cjs/llm/ollama/utils.cjs +0 -158
  198. package/dist/cjs/llm/ollama/utils.cjs.map +0 -1
  199. package/dist/esm/llm/ollama/index.mjs +0 -68
  200. package/dist/esm/llm/ollama/index.mjs.map +0 -1
  201. package/dist/esm/llm/ollama/utils.mjs +0 -155
  202. package/dist/esm/llm/ollama/utils.mjs.map +0 -1
  203. package/dist/types/llm/ollama/index.d.ts +0 -8
  204. package/dist/types/llm/ollama/utils.d.ts +0 -7
  205. package/src/llm/ollama/index.ts +0 -92
  206. package/src/llm/ollama/utils.ts +0 -193
  207. package/src/proto/CollabGraph.ts +0 -269
  208. package/src/proto/TaskManager.ts +0 -243
  209. package/src/proto/collab.ts +0 -200
  210. package/src/proto/collab_design.ts +0 -184
  211. package/src/proto/collab_design_v2.ts +0 -224
  212. package/src/proto/collab_design_v3.ts +0 -255
  213. package/src/proto/collab_design_v4.ts +0 -220
  214. package/src/proto/collab_design_v5.ts +0 -251
  215. package/src/proto/collab_graph.ts +0 -181
  216. package/src/proto/collab_original.ts +0 -123
  217. package/src/proto/example.ts +0 -93
  218. package/src/proto/example_new.ts +0 -68
  219. package/src/proto/example_old.ts +0 -201
  220. package/src/proto/example_test.ts +0 -152
  221. package/src/proto/example_test_anthropic.ts +0 -100
  222. package/src/proto/log_stream.ts +0 -202
  223. package/src/proto/main_collab_community_event.ts +0 -133
  224. package/src/proto/main_collab_design_v2.ts +0 -96
  225. package/src/proto/main_collab_design_v4.ts +0 -100
  226. package/src/proto/main_collab_design_v5.ts +0 -135
  227. package/src/proto/main_collab_global_analysis.ts +0 -122
  228. package/src/proto/main_collab_hackathon_event.ts +0 -153
  229. package/src/proto/main_collab_space_mission.ts +0 -153
  230. package/src/proto/main_philosophy.ts +0 -210
  231. package/src/proto/original_script.ts +0 -126
  232. package/src/proto/standard.ts +0 -100
  233. package/src/proto/stream.ts +0 -56
  234. package/src/proto/tasks.ts +0 -118
  235. package/src/proto/tools/global_analysis_tools.ts +0 -86
  236. package/src/proto/tools/space_mission_tools.ts +0 -60
  237. package/src/proto/vertexai.ts +0 -54
package/src/llm/fake.ts CHANGED
@@ -1,133 +1,133 @@
1
- import { ChatGenerationChunk } from '@langchain/core/outputs';
2
- import { AIMessageChunk } from '@langchain/core/messages';
3
- import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
4
- import type { BaseMessage } from '@langchain/core/messages';
5
- import { FakeListChatModel } from '@langchain/core/utils/testing';
6
- import { ToolCall, ToolCallChunk } from '@langchain/core/messages/tool';
7
-
8
- type SplitStrategy = {
9
- type: 'regex' | 'fixed';
10
- value: RegExp | number;
11
- };
12
-
13
- export class FakeChatModel extends FakeListChatModel {
14
- private splitStrategy: SplitStrategy;
15
- private toolCalls: ToolCall[] = [];
16
- private addedToolCalls: boolean = false;
17
-
18
- constructor({
19
- responses,
20
- sleep,
21
- emitCustomEvent,
22
- splitStrategy = { type: 'regex', value: /(?<=\s+)|(?=\s+)/ },
23
- toolCalls = []
24
- }: {
25
- responses: string[];
26
- sleep?: number;
27
- emitCustomEvent?: boolean;
28
- splitStrategy?: SplitStrategy;
29
- toolCalls?: ToolCall[];
30
- }) {
31
- super({ responses, sleep, emitCustomEvent });
32
- this.splitStrategy = splitStrategy;
33
- this.toolCalls = toolCalls;
34
- }
35
-
36
- private splitText(text: string): string[] {
37
- if (this.splitStrategy.type === 'regex') {
38
- return text.split(this.splitStrategy.value as RegExp);
39
- } else {
40
- const chunkSize = this.splitStrategy.value as number;
41
- const chunks: string[] = [];
42
- for (let i = 0; i < text.length; i += chunkSize) {
43
- chunks.push(text.slice(i, i + chunkSize));
44
- }
45
- return chunks;
46
- }
47
- }
48
- _createResponseChunk(text: string, tool_call_chunks?: ToolCallChunk[]): ChatGenerationChunk {
49
- return new ChatGenerationChunk({
50
- text,
51
- generationInfo: {},
52
- message: new AIMessageChunk({
53
- content: text,
54
- tool_call_chunks,
55
- additional_kwargs: tool_call_chunks ? {
56
- tool_calls: tool_call_chunks.map((toolCall) => ({
57
- index: toolCall.index ?? 0,
58
- id: toolCall.id ?? '',
59
- type: 'function',
60
- function: {
61
- name: toolCall.name ?? '',
62
- arguments: toolCall.args ?? '',
63
- },
64
- })),
65
- } : undefined,
66
- })});
67
- }
68
-
69
- async *_streamResponseChunks(
70
- _messages: BaseMessage[],
71
- options: this['ParsedCallOptions'],
72
- runManager?: CallbackManagerForLLMRun
73
- ): AsyncGenerator<ChatGenerationChunk> {
74
- const response = this._currentResponse();
75
- this._incrementResponse();
76
-
77
- if (this.emitCustomEvent) {
78
- await runManager?.handleCustomEvent('some_test_event', {
79
- someval: true,
80
- });
81
- }
82
-
83
- const chunks = this.splitText(response);
84
- for await (const chunk of chunks) {
85
- await this._sleepIfRequested();
86
-
87
- if (options.thrownErrorString != null && options.thrownErrorString) {
88
- throw new Error(options.thrownErrorString);
89
- }
90
-
91
- const responseChunk = super._createResponseChunk(chunk);
92
- yield responseChunk;
93
- void runManager?.handleLLMNewToken(chunk);
94
- }
95
-
96
- await this._sleepIfRequested();
97
- if (this.toolCalls.length > 0 && !this.addedToolCalls) {
98
- this.addedToolCalls = true;
99
- const toolCallChunks = this.toolCalls.map((toolCall) => {;
100
- return {
101
- name: toolCall.name,
102
- args: JSON.stringify(toolCall.args),
103
- id: toolCall.id,
104
- type: 'tool_call_chunk',
105
- } as ToolCallChunk;
106
- });
107
- const responseChunk = this._createResponseChunk('', toolCallChunks);
108
- yield responseChunk;
109
- void runManager?.handleLLMNewToken('');
110
- }
111
- }
112
- }
113
-
114
- export function createFakeStreamingLLM({
115
- responses,
116
- sleep,
117
- splitStrategy,
118
- toolCalls,
119
- } : {
120
- responses: string[],
121
- sleep?: number,
122
- splitStrategy?: SplitStrategy,
123
- toolCalls?: ToolCall[]
124
- }
125
- ): FakeChatModel {
126
- return new FakeChatModel({
127
- sleep,
128
- responses,
129
- emitCustomEvent: true,
130
- splitStrategy,
131
- toolCalls,
132
- });
133
- }
1
+ import { ChatGenerationChunk } from '@langchain/core/outputs';
2
+ import { AIMessageChunk } from '@langchain/core/messages';
3
+ import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
4
+ import type { BaseMessage } from '@langchain/core/messages';
5
+ import { FakeListChatModel } from '@langchain/core/utils/testing';
6
+ import { ToolCall, ToolCallChunk } from '@langchain/core/messages/tool';
7
+
8
+ type SplitStrategy = {
9
+ type: 'regex' | 'fixed';
10
+ value: RegExp | number;
11
+ };
12
+
13
+ export class FakeChatModel extends FakeListChatModel {
14
+ private splitStrategy: SplitStrategy;
15
+ private toolCalls: ToolCall[] = [];
16
+ private addedToolCalls: boolean = false;
17
+
18
+ constructor({
19
+ responses,
20
+ sleep,
21
+ emitCustomEvent,
22
+ splitStrategy = { type: 'regex', value: /(?<=\s+)|(?=\s+)/ },
23
+ toolCalls = []
24
+ }: {
25
+ responses: string[];
26
+ sleep?: number;
27
+ emitCustomEvent?: boolean;
28
+ splitStrategy?: SplitStrategy;
29
+ toolCalls?: ToolCall[];
30
+ }) {
31
+ super({ responses, sleep, emitCustomEvent });
32
+ this.splitStrategy = splitStrategy;
33
+ this.toolCalls = toolCalls;
34
+ }
35
+
36
+ private splitText(text: string): string[] {
37
+ if (this.splitStrategy.type === 'regex') {
38
+ return text.split(this.splitStrategy.value as RegExp);
39
+ } else {
40
+ const chunkSize = this.splitStrategy.value as number;
41
+ const chunks: string[] = [];
42
+ for (let i = 0; i < text.length; i += chunkSize) {
43
+ chunks.push(text.slice(i, i + chunkSize));
44
+ }
45
+ return chunks;
46
+ }
47
+ }
48
+ _createResponseChunk(text: string, tool_call_chunks?: ToolCallChunk[]): ChatGenerationChunk {
49
+ return new ChatGenerationChunk({
50
+ text,
51
+ generationInfo: {},
52
+ message: new AIMessageChunk({
53
+ content: text,
54
+ tool_call_chunks,
55
+ additional_kwargs: tool_call_chunks ? {
56
+ tool_calls: tool_call_chunks.map((toolCall) => ({
57
+ index: toolCall.index ?? 0,
58
+ id: toolCall.id ?? '',
59
+ type: 'function',
60
+ function: {
61
+ name: toolCall.name ?? '',
62
+ arguments: toolCall.args ?? '',
63
+ },
64
+ })),
65
+ } : undefined,
66
+ })});
67
+ }
68
+
69
+ async *_streamResponseChunks(
70
+ _messages: BaseMessage[],
71
+ options: this['ParsedCallOptions'],
72
+ runManager?: CallbackManagerForLLMRun
73
+ ): AsyncGenerator<ChatGenerationChunk> {
74
+ const response = this._currentResponse();
75
+ this._incrementResponse();
76
+
77
+ if (this.emitCustomEvent) {
78
+ await runManager?.handleCustomEvent('some_test_event', {
79
+ someval: true,
80
+ });
81
+ }
82
+
83
+ const chunks = this.splitText(response);
84
+ for await (const chunk of chunks) {
85
+ await this._sleepIfRequested();
86
+
87
+ if (options.thrownErrorString != null && options.thrownErrorString) {
88
+ throw new Error(options.thrownErrorString);
89
+ }
90
+
91
+ const responseChunk = super._createResponseChunk(chunk);
92
+ yield responseChunk;
93
+ void runManager?.handleLLMNewToken(chunk);
94
+ }
95
+
96
+ await this._sleepIfRequested();
97
+ if (this.toolCalls.length > 0 && !this.addedToolCalls) {
98
+ this.addedToolCalls = true;
99
+ const toolCallChunks = this.toolCalls.map((toolCall) => {;
100
+ return {
101
+ name: toolCall.name,
102
+ args: JSON.stringify(toolCall.args),
103
+ id: toolCall.id,
104
+ type: 'tool_call_chunk',
105
+ } as ToolCallChunk;
106
+ });
107
+ const responseChunk = this._createResponseChunk('', toolCallChunks);
108
+ yield responseChunk;
109
+ void runManager?.handleLLMNewToken('');
110
+ }
111
+ }
112
+ }
113
+
114
+ export function createFakeStreamingLLM({
115
+ responses,
116
+ sleep,
117
+ splitStrategy,
118
+ toolCalls,
119
+ } : {
120
+ responses: string[],
121
+ sleep?: number,
122
+ splitStrategy?: SplitStrategy,
123
+ toolCalls?: ToolCall[]
124
+ }
125
+ ): FakeChatModel {
126
+ return new FakeChatModel({
127
+ sleep,
128
+ responses,
129
+ emitCustomEvent: true,
130
+ splitStrategy,
131
+ toolCalls,
132
+ });
133
+ }
Binary file
@@ -11,15 +11,30 @@ import type {
11
11
  import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
12
12
  import type { BaseMessage, UsageMetadata } from '@langchain/core/messages';
13
13
  import type { GeminiGenerationConfig } from '@langchain/google-common';
14
- import type { GeminiApiUsageMetadata } from './types';
14
+ import type { GeminiApiUsageMetadata, InputTokenDetails } from './types';
15
15
  import type { GoogleClientOptions } from '@/types';
16
16
  import {
17
17
  convertResponseContentToChatGenerationChunk,
18
18
  convertBaseMessagesToContent,
19
+ mapGenerateContentResultToChatResult,
19
20
  } from './utils/common';
20
21
 
21
22
  export class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {
22
23
  thinkingConfig?: GeminiGenerationConfig['thinkingConfig'];
24
+
25
+ /**
26
+ * Override to add gemini-3 model support for multimodal and function calling thought signatures
27
+ */
28
+ get _isMultimodalModel(): boolean {
29
+ return (
30
+ this.model.startsWith('gemini-1.5') ||
31
+ this.model.startsWith('gemini-2') ||
32
+ (this.model.startsWith('gemma-3-') &&
33
+ !this.model.startsWith('gemma-3-1b')) ||
34
+ this.model.startsWith('gemini-3')
35
+ );
36
+ }
37
+
23
38
  constructor(fields: GoogleClientOptions) {
24
39
  super(fields);
25
40
 
@@ -111,6 +126,59 @@ export class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {
111
126
  return 'IllumaGoogleGenerativeAI';
112
127
  }
113
128
 
129
+ /**
130
+ * Helper function to convert Gemini API usage metadata to LangChain format
131
+ * Includes support for cached tokens and tier-based tracking for gemini-3-pro-preview
132
+ */
133
+ private _convertToUsageMetadata(
134
+ usageMetadata: GeminiApiUsageMetadata | undefined,
135
+ model: string
136
+ ): UsageMetadata | undefined {
137
+ if (!usageMetadata) {
138
+ return undefined;
139
+ }
140
+
141
+ const output: UsageMetadata = {
142
+ input_tokens: usageMetadata.promptTokenCount ?? 0,
143
+ output_tokens:
144
+ (usageMetadata.candidatesTokenCount ?? 0) +
145
+ (usageMetadata.thoughtsTokenCount ?? 0),
146
+ total_tokens: usageMetadata.totalTokenCount ?? 0,
147
+ };
148
+
149
+ if (usageMetadata.cachedContentTokenCount) {
150
+ output.input_token_details ??= {};
151
+ output.input_token_details.cache_read =
152
+ usageMetadata.cachedContentTokenCount;
153
+ }
154
+
155
+ // gemini-3-pro-preview has bracket based tracking of tokens per request
156
+ if (model === 'gemini-3-pro-preview') {
157
+ const over200k = Math.max(
158
+ 0,
159
+ (usageMetadata.promptTokenCount ?? 0) - 200000
160
+ );
161
+ const cachedOver200k = Math.max(
162
+ 0,
163
+ (usageMetadata.cachedContentTokenCount ?? 0) - 200000
164
+ );
165
+ if (over200k) {
166
+ output.input_token_details = {
167
+ ...output.input_token_details,
168
+ over_200k: over200k,
169
+ } as InputTokenDetails;
170
+ }
171
+ if (cachedOver200k) {
172
+ output.input_token_details = {
173
+ ...output.input_token_details,
174
+ cache_read_over_200k: cachedOver200k,
175
+ } as InputTokenDetails;
176
+ }
177
+ }
178
+
179
+ return output;
180
+ }
181
+
114
182
  invocationParams(
115
183
  options?: this['ParsedCallOptions']
116
184
  ): Omit<GenerateContentRequest, 'contents'> {
@@ -127,6 +195,60 @@ export class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {
127
195
  return params;
128
196
  }
129
197
 
198
+ async _generate(
199
+ messages: BaseMessage[],
200
+ options: this['ParsedCallOptions'],
201
+ runManager?: CallbackManagerForLLMRun
202
+ ): Promise<import('@langchain/core/outputs').ChatResult> {
203
+ const prompt = convertBaseMessagesToContent(
204
+ messages,
205
+ this._isMultimodalModel,
206
+ this.useSystemInstruction,
207
+ this.model
208
+ );
209
+ let actualPrompt = prompt;
210
+ if (prompt?.[0].role === 'system') {
211
+ const [systemInstruction] = prompt;
212
+ /** @ts-ignore */
213
+ this.client.systemInstruction = systemInstruction;
214
+ actualPrompt = prompt.slice(1);
215
+ }
216
+ const parameters = this.invocationParams(options);
217
+ const request = {
218
+ ...parameters,
219
+ contents: actualPrompt,
220
+ };
221
+
222
+ const res = await this.caller.callWithOptions(
223
+ { signal: options.signal },
224
+ async () =>
225
+ /** @ts-ignore */
226
+ this.client.generateContent(request)
227
+ );
228
+
229
+ const response = res.response;
230
+ const usageMetadata = this._convertToUsageMetadata(
231
+ /** @ts-ignore */
232
+ response.usageMetadata,
233
+ this.model
234
+ );
235
+
236
+ /** @ts-ignore */
237
+ const generationResult = mapGenerateContentResultToChatResult(response, {
238
+ usageMetadata,
239
+ });
240
+
241
+ await runManager?.handleLLMNewToken(
242
+ generationResult.generations[0].text || '',
243
+ undefined,
244
+ undefined,
245
+ undefined,
246
+ undefined,
247
+ undefined
248
+ );
249
+ return generationResult;
250
+ }
251
+
130
252
  async *_streamResponseChunks(
131
253
  messages: BaseMessage[],
132
254
  options: this['ParsedCallOptions'],
@@ -135,7 +257,8 @@ export class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {
135
257
  const prompt = convertBaseMessagesToContent(
136
258
  messages,
137
259
  this._isMultimodalModel,
138
- this.useSystemInstruction
260
+ this.useSystemInstruction,
261
+ this.model
139
262
  );
140
263
  let actualPrompt = prompt;
141
264
  if (prompt?.[0].role === 'system') {
@@ -166,18 +289,10 @@ export class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {
166
289
  this.streamUsage !== false &&
167
290
  options.streamUsage !== false
168
291
  ) {
169
- const genAIUsageMetadata = response.usageMetadata as
170
- | GeminiApiUsageMetadata
171
- | undefined;
172
-
173
- const output_tokens =
174
- (genAIUsageMetadata?.candidatesTokenCount ?? 0) +
175
- (genAIUsageMetadata?.thoughtsTokenCount ?? 0);
176
- lastUsageMetadata = {
177
- input_tokens: genAIUsageMetadata?.promptTokenCount ?? 0,
178
- output_tokens,
179
- total_tokens: genAIUsageMetadata?.totalTokenCount ?? 0,
180
- };
292
+ lastUsageMetadata = this._convertToUsageMetadata(
293
+ response.usageMetadata as GeminiApiUsageMetadata | undefined,
294
+ this.model
295
+ );
181
296
  }
182
297
 
183
298
  const chunk = convertResponseContentToChatGenerationChunk(response, {