illuma-agents 1.0.5 → 1.0.7

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 (37) hide show
  1. package/dist/cjs/events.cjs +34 -10
  2. package/dist/cjs/events.cjs.map +1 -1
  3. package/dist/cjs/graphs/Graph.cjs +6 -4
  4. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  5. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
  6. package/dist/cjs/main.cjs +3 -0
  7. package/dist/cjs/main.cjs.map +1 -1
  8. package/dist/cjs/messages/cache.cjs +87 -14
  9. package/dist/cjs/messages/cache.cjs.map +1 -1
  10. package/dist/cjs/messages/format.cjs +188 -7
  11. package/dist/cjs/messages/format.cjs.map +1 -1
  12. package/dist/esm/events.mjs +34 -10
  13. package/dist/esm/events.mjs.map +1 -1
  14. package/dist/esm/graphs/Graph.mjs +6 -4
  15. package/dist/esm/graphs/Graph.mjs.map +1 -1
  16. package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
  17. package/dist/esm/main.mjs +2 -2
  18. package/dist/esm/messages/cache.mjs +86 -15
  19. package/dist/esm/messages/cache.mjs.map +1 -1
  20. package/dist/esm/messages/format.mjs +188 -8
  21. package/dist/esm/messages/format.mjs.map +1 -1
  22. package/dist/types/events.d.ts +3 -1
  23. package/dist/types/messages/cache.d.ts +16 -0
  24. package/dist/types/messages/format.d.ts +21 -1
  25. package/dist/types/types/stream.d.ts +1 -1
  26. package/package.json +6 -3
  27. package/src/events.ts +37 -15
  28. package/src/graphs/Graph.ts +8 -4
  29. package/src/llm/anthropic/utils/message_outputs.ts +289 -289
  30. package/src/messages/cache.test.ts +499 -3
  31. package/src/messages/cache.ts +115 -25
  32. package/src/messages/ensureThinkingBlock.test.ts +75 -0
  33. package/src/messages/format.ts +240 -7
  34. package/src/messages/labelContentByAgent.test.ts +887 -0
  35. package/src/scripts/test-multi-agent-list-handoff.ts +116 -10
  36. package/src/scripts/test-parallel-agent-labeling.ts +325 -0
  37. package/src/types/stream.ts +1 -1
@@ -1,289 +1,289 @@
1
- /**
2
- * This util file contains functions for converting Anthropic messages to LangChain messages.
3
- */
4
- import Anthropic from '@anthropic-ai/sdk';
5
- import {
6
- AIMessage,
7
- AIMessageChunk,
8
- UsageMetadata,
9
- } from '@langchain/core/messages';
10
- import type { ToolCallChunk } from '@langchain/core/messages/tool';
11
- import { ChatGeneration } from '@langchain/core/outputs';
12
- import { extractToolCalls } from './output_parsers';
13
- import { AnthropicMessageResponse } from '../types';
14
-
15
- export function _makeMessageChunkFromAnthropicEvent(
16
- data: Anthropic.Messages.RawMessageStreamEvent,
17
- fields: {
18
- streamUsage: boolean;
19
- coerceContentToString: boolean;
20
- }
21
- ): {
22
- chunk: AIMessageChunk;
23
- } | null {
24
- if (data.type === 'message_start') {
25
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
- const { content, usage, ...additionalKwargs } = data.message;
27
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
- const filteredAdditionalKwargs: Record<string, any> = {};
29
- for (const [key, value] of Object.entries(additionalKwargs)) {
30
- if (value !== undefined && value !== null) {
31
- filteredAdditionalKwargs[key] = value;
32
- }
33
- }
34
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
- const { input_tokens, output_tokens, ...rest }: Record<string, any> =
36
- usage ?? {};
37
- const usageMetadata: UsageMetadata = {
38
- input_tokens,
39
- output_tokens,
40
- total_tokens: input_tokens + output_tokens,
41
- input_token_details: {
42
- cache_creation: rest.cache_creation_input_tokens,
43
- cache_read: rest.cache_read_input_tokens,
44
- },
45
- };
46
- return {
47
- chunk: new AIMessageChunk({
48
- content: fields.coerceContentToString ? '' : [],
49
- additional_kwargs: filteredAdditionalKwargs,
50
- usage_metadata: fields.streamUsage ? usageMetadata : undefined,
51
- response_metadata: {
52
- usage: {
53
- ...rest,
54
- },
55
- },
56
- id: data.message.id,
57
- }),
58
- };
59
- } else if (data.type === 'message_delta') {
60
- const usageMetadata: UsageMetadata = {
61
- input_tokens: 0,
62
- output_tokens: data.usage.output_tokens,
63
- total_tokens: data.usage.output_tokens,
64
- input_token_details: {
65
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
- cache_creation: (data.usage as any).cache_creation_input_tokens,
67
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
- cache_read: (data.usage as any).cache_read_input_tokens,
69
- },
70
- };
71
- return {
72
- chunk: new AIMessageChunk({
73
- content: fields.coerceContentToString ? '' : [],
74
- additional_kwargs: { ...data.delta },
75
- usage_metadata: fields.streamUsage ? usageMetadata : undefined,
76
- }),
77
- };
78
- } else if (
79
- data.type === 'content_block_start' &&
80
- [
81
- 'tool_use',
82
- 'document',
83
- 'server_tool_use',
84
- 'web_search_tool_result',
85
- ].includes(data.content_block.type)
86
- ) {
87
- const contentBlock = data.content_block;
88
- let toolCallChunks: ToolCallChunk[];
89
- if (contentBlock.type === 'tool_use') {
90
- toolCallChunks = [
91
- {
92
- id: contentBlock.id,
93
- index: data.index,
94
- name: contentBlock.name,
95
- args: '',
96
- },
97
- ];
98
- } else if (contentBlock.type === 'server_tool_use') {
99
- // Handle anthropic built-in server tool use (like web search)
100
- toolCallChunks = [
101
- {
102
- id: contentBlock.id,
103
- index: data.index,
104
- name: contentBlock.name,
105
- args: '',
106
- },
107
- ];
108
- } else {
109
- toolCallChunks = [];
110
- }
111
- return {
112
- chunk: new AIMessageChunk({
113
- content: fields.coerceContentToString
114
- ? ''
115
- : [
116
- {
117
- index: data.index,
118
- ...data.content_block,
119
- input:
120
- contentBlock.type === 'server_tool_use' ||
121
- contentBlock.type === 'tool_use'
122
- ? ''
123
- : undefined,
124
- },
125
- ],
126
- additional_kwargs: {},
127
- tool_call_chunks: toolCallChunks,
128
- }),
129
- };
130
- } else if (
131
- data.type === 'content_block_delta' &&
132
- [
133
- 'text_delta',
134
- 'citations_delta',
135
- 'thinking_delta',
136
- 'signature_delta',
137
- ].includes(data.delta.type)
138
- ) {
139
- if (fields.coerceContentToString && 'text' in data.delta) {
140
- return {
141
- chunk: new AIMessageChunk({
142
- content: data.delta.text,
143
- }),
144
- };
145
- } else {
146
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
147
- const contentBlock: Record<string, any> = data.delta;
148
- if ('citation' in contentBlock) {
149
- contentBlock.citations = [contentBlock.citation];
150
- delete contentBlock.citation;
151
- }
152
- if (
153
- contentBlock.type === 'thinking_delta' ||
154
- contentBlock.type === 'signature_delta'
155
- ) {
156
- return {
157
- chunk: new AIMessageChunk({
158
- content: [{ index: data.index, ...contentBlock, type: 'thinking' }],
159
- }),
160
- };
161
- }
162
-
163
- return {
164
- chunk: new AIMessageChunk({
165
- content: [{ index: data.index, ...contentBlock, type: 'text' }],
166
- }),
167
- };
168
- }
169
- } else if (
170
- data.type === 'content_block_delta' &&
171
- data.delta.type === 'input_json_delta'
172
- ) {
173
- return {
174
- chunk: new AIMessageChunk({
175
- content: fields.coerceContentToString
176
- ? ''
177
- : [
178
- {
179
- index: data.index,
180
- input: data.delta.partial_json,
181
- type: data.delta.type,
182
- },
183
- ],
184
- additional_kwargs: {},
185
- tool_call_chunks: [
186
- {
187
- index: data.index,
188
- args: data.delta.partial_json,
189
- },
190
- ],
191
- }),
192
- };
193
- } else if (
194
- data.type === 'content_block_start' &&
195
- data.content_block.type === 'text'
196
- ) {
197
- const content = data.content_block.text;
198
- if (content !== undefined) {
199
- return {
200
- chunk: new AIMessageChunk({
201
- content: fields.coerceContentToString
202
- ? content
203
- : [
204
- {
205
- index: data.index,
206
- ...data.content_block,
207
- },
208
- ],
209
- additional_kwargs: {},
210
- }),
211
- };
212
- }
213
- } else if (
214
- data.type === 'content_block_start' &&
215
- data.content_block.type === 'redacted_thinking'
216
- ) {
217
- return {
218
- chunk: new AIMessageChunk({
219
- content: fields.coerceContentToString
220
- ? ''
221
- : [{ index: data.index, ...data.content_block }],
222
- }),
223
- };
224
- } else if (
225
- data.type === 'content_block_start' &&
226
- data.content_block.type === 'thinking'
227
- ) {
228
- const content = data.content_block.thinking;
229
- return {
230
- chunk: new AIMessageChunk({
231
- content: fields.coerceContentToString
232
- ? content
233
- : [{ index: data.index, ...data.content_block }],
234
- }),
235
- };
236
- }
237
- return null;
238
- }
239
-
240
- export function anthropicResponseToChatMessages(
241
- messages: AnthropicMessageResponse[],
242
- additionalKwargs: Record<string, unknown>
243
- ): ChatGeneration[] {
244
- const usage: Record<string, number> | null | undefined =
245
- additionalKwargs.usage as Record<string, number> | null | undefined;
246
- const usageMetadata =
247
- usage != null
248
- ? {
249
- input_tokens: usage.input_tokens ?? 0,
250
- output_tokens: usage.output_tokens ?? 0,
251
- total_tokens: (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),
252
- input_token_details: {
253
- cache_creation: usage.cache_creation_input_tokens,
254
- cache_read: usage.cache_read_input_tokens,
255
- },
256
- }
257
- : undefined;
258
- if (messages.length === 1 && messages[0].type === 'text') {
259
- return [
260
- {
261
- text: messages[0].text,
262
- message: new AIMessage({
263
- content: messages[0].text,
264
- additional_kwargs: additionalKwargs,
265
- usage_metadata: usageMetadata,
266
- response_metadata: additionalKwargs,
267
- id: additionalKwargs.id as string,
268
- }),
269
- },
270
- ];
271
- } else {
272
- const toolCalls = extractToolCalls(messages);
273
- const generations: ChatGeneration[] = [
274
- {
275
- text: '',
276
- message: new AIMessage({
277
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
278
- content: messages as any,
279
- additional_kwargs: additionalKwargs,
280
- tool_calls: toolCalls,
281
- usage_metadata: usageMetadata,
282
- response_metadata: additionalKwargs,
283
- id: additionalKwargs.id as string,
284
- }),
285
- },
286
- ];
287
- return generations;
288
- }
289
- }
1
+ /**
2
+ * This util file contains functions for converting Anthropic messages to LangChain messages.
3
+ */
4
+ import Anthropic from '@anthropic-ai/sdk';
5
+ import {
6
+ AIMessage,
7
+ AIMessageChunk,
8
+ UsageMetadata,
9
+ } from '@langchain/core/messages';
10
+ import type { ToolCallChunk } from '@langchain/core/messages/tool';
11
+ import { ChatGeneration } from '@langchain/core/outputs';
12
+ import { extractToolCalls } from './output_parsers';
13
+ import { AnthropicMessageResponse } from '../types';
14
+
15
+ export function _makeMessageChunkFromAnthropicEvent(
16
+ data: Anthropic.Messages.RawMessageStreamEvent,
17
+ fields: {
18
+ streamUsage: boolean;
19
+ coerceContentToString: boolean;
20
+ }
21
+ ): {
22
+ chunk: AIMessageChunk;
23
+ } | null {
24
+ if (data.type === 'message_start') {
25
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
+ const { content, usage, ...additionalKwargs } = data.message;
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ const filteredAdditionalKwargs: Record<string, any> = {};
29
+ for (const [key, value] of Object.entries(additionalKwargs)) {
30
+ if (value !== undefined && value !== null) {
31
+ filteredAdditionalKwargs[key] = value;
32
+ }
33
+ }
34
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
+ const { input_tokens, output_tokens, ...rest }: Record<string, any> =
36
+ usage ?? {};
37
+ const usageMetadata: UsageMetadata = {
38
+ input_tokens,
39
+ output_tokens,
40
+ total_tokens: input_tokens + output_tokens,
41
+ input_token_details: {
42
+ cache_creation: rest.cache_creation_input_tokens,
43
+ cache_read: rest.cache_read_input_tokens,
44
+ },
45
+ };
46
+ return {
47
+ chunk: new AIMessageChunk({
48
+ content: fields.coerceContentToString ? '' : [],
49
+ additional_kwargs: filteredAdditionalKwargs,
50
+ usage_metadata: fields.streamUsage ? usageMetadata : undefined,
51
+ response_metadata: {
52
+ usage: {
53
+ ...rest,
54
+ },
55
+ },
56
+ id: data.message.id,
57
+ }),
58
+ };
59
+ } else if (data.type === 'message_delta') {
60
+ const usageMetadata: UsageMetadata = {
61
+ input_tokens: 0,
62
+ output_tokens: data.usage.output_tokens,
63
+ total_tokens: data.usage.output_tokens,
64
+ input_token_details: {
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ cache_creation: (data.usage as any).cache_creation_input_tokens,
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ cache_read: (data.usage as any).cache_read_input_tokens,
69
+ },
70
+ };
71
+ return {
72
+ chunk: new AIMessageChunk({
73
+ content: fields.coerceContentToString ? '' : [],
74
+ additional_kwargs: { ...data.delta },
75
+ usage_metadata: fields.streamUsage ? usageMetadata : undefined,
76
+ }),
77
+ };
78
+ } else if (
79
+ data.type === 'content_block_start' &&
80
+ [
81
+ 'tool_use',
82
+ 'document',
83
+ 'server_tool_use',
84
+ 'web_search_tool_result',
85
+ ].includes(data.content_block.type)
86
+ ) {
87
+ const contentBlock = data.content_block;
88
+ let toolCallChunks: ToolCallChunk[];
89
+ if (contentBlock.type === 'tool_use') {
90
+ toolCallChunks = [
91
+ {
92
+ id: contentBlock.id,
93
+ index: data.index,
94
+ name: contentBlock.name,
95
+ args: '',
96
+ },
97
+ ];
98
+ } else if (contentBlock.type === 'server_tool_use') {
99
+ // Handle anthropic built-in server tool use (like web search)
100
+ toolCallChunks = [
101
+ {
102
+ id: contentBlock.id,
103
+ index: data.index,
104
+ name: contentBlock.name,
105
+ args: '',
106
+ },
107
+ ];
108
+ } else {
109
+ toolCallChunks = [];
110
+ }
111
+ return {
112
+ chunk: new AIMessageChunk({
113
+ content: fields.coerceContentToString
114
+ ? ''
115
+ : [
116
+ {
117
+ index: data.index,
118
+ ...data.content_block,
119
+ input:
120
+ contentBlock.type === 'server_tool_use' ||
121
+ contentBlock.type === 'tool_use'
122
+ ? ''
123
+ : undefined,
124
+ },
125
+ ],
126
+ additional_kwargs: {},
127
+ tool_call_chunks: toolCallChunks,
128
+ }),
129
+ };
130
+ } else if (
131
+ data.type === 'content_block_delta' &&
132
+ [
133
+ 'text_delta',
134
+ 'citations_delta',
135
+ 'thinking_delta',
136
+ 'signature_delta',
137
+ ].includes(data.delta.type)
138
+ ) {
139
+ if (fields.coerceContentToString && 'text' in data.delta) {
140
+ return {
141
+ chunk: new AIMessageChunk({
142
+ content: data.delta.text,
143
+ }),
144
+ };
145
+ } else {
146
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
147
+ const contentBlock: Record<string, any> = data.delta;
148
+ if ('citation' in contentBlock) {
149
+ contentBlock.citations = [contentBlock.citation];
150
+ delete contentBlock.citation;
151
+ }
152
+ if (
153
+ contentBlock.type === 'thinking_delta' ||
154
+ contentBlock.type === 'signature_delta'
155
+ ) {
156
+ return {
157
+ chunk: new AIMessageChunk({
158
+ content: [{ index: data.index, ...contentBlock, type: 'thinking' }],
159
+ }),
160
+ };
161
+ }
162
+
163
+ return {
164
+ chunk: new AIMessageChunk({
165
+ content: [{ index: data.index, ...contentBlock, type: 'text' }],
166
+ }),
167
+ };
168
+ }
169
+ } else if (
170
+ data.type === 'content_block_delta' &&
171
+ data.delta.type === 'input_json_delta'
172
+ ) {
173
+ return {
174
+ chunk: new AIMessageChunk({
175
+ content: fields.coerceContentToString
176
+ ? ''
177
+ : [
178
+ {
179
+ index: data.index,
180
+ input: data.delta.partial_json,
181
+ type: data.delta.type,
182
+ },
183
+ ],
184
+ additional_kwargs: {},
185
+ tool_call_chunks: [
186
+ {
187
+ index: data.index,
188
+ args: data.delta.partial_json,
189
+ },
190
+ ],
191
+ }),
192
+ };
193
+ } else if (
194
+ data.type === 'content_block_start' &&
195
+ data.content_block.type === 'text'
196
+ ) {
197
+ const content = data.content_block.text;
198
+ if (content !== undefined) {
199
+ return {
200
+ chunk: new AIMessageChunk({
201
+ content: fields.coerceContentToString
202
+ ? content
203
+ : [
204
+ {
205
+ index: data.index,
206
+ ...data.content_block,
207
+ },
208
+ ],
209
+ additional_kwargs: {},
210
+ }),
211
+ };
212
+ }
213
+ } else if (
214
+ data.type === 'content_block_start' &&
215
+ data.content_block.type === 'redacted_thinking'
216
+ ) {
217
+ return {
218
+ chunk: new AIMessageChunk({
219
+ content: fields.coerceContentToString
220
+ ? ''
221
+ : [{ index: data.index, ...data.content_block }],
222
+ }),
223
+ };
224
+ } else if (
225
+ data.type === 'content_block_start' &&
226
+ data.content_block.type === 'thinking'
227
+ ) {
228
+ const content = data.content_block.thinking;
229
+ return {
230
+ chunk: new AIMessageChunk({
231
+ content: fields.coerceContentToString
232
+ ? content
233
+ : [{ index: data.index, ...data.content_block }],
234
+ }),
235
+ };
236
+ }
237
+ return null;
238
+ }
239
+
240
+ export function anthropicResponseToChatMessages(
241
+ messages: AnthropicMessageResponse[],
242
+ additionalKwargs: Record<string, unknown>
243
+ ): ChatGeneration[] {
244
+ const usage: Record<string, number> | null | undefined =
245
+ additionalKwargs.usage as Record<string, number> | null | undefined;
246
+ const usageMetadata =
247
+ usage != null
248
+ ? {
249
+ input_tokens: usage.input_tokens ?? 0,
250
+ output_tokens: usage.output_tokens ?? 0,
251
+ total_tokens: (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),
252
+ input_token_details: {
253
+ cache_creation: usage.cache_creation_input_tokens,
254
+ cache_read: usage.cache_read_input_tokens,
255
+ },
256
+ }
257
+ : undefined;
258
+ if (messages.length === 1 && messages[0].type === 'text') {
259
+ return [
260
+ {
261
+ text: messages[0].text,
262
+ message: new AIMessage({
263
+ content: messages[0].text,
264
+ additional_kwargs: additionalKwargs,
265
+ usage_metadata: usageMetadata,
266
+ response_metadata: additionalKwargs,
267
+ id: additionalKwargs.id as string,
268
+ }),
269
+ },
270
+ ];
271
+ } else {
272
+ const toolCalls = extractToolCalls(messages);
273
+ const generations: ChatGeneration[] = [
274
+ {
275
+ text: '',
276
+ message: new AIMessage({
277
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
278
+ content: messages as any,
279
+ additional_kwargs: additionalKwargs,
280
+ tool_calls: toolCalls,
281
+ usage_metadata: usageMetadata,
282
+ response_metadata: additionalKwargs,
283
+ id: additionalKwargs.id as string,
284
+ }),
285
+ },
286
+ ];
287
+ return generations;
288
+ }
289
+ }