illuma-agents 1.0.51 → 1.0.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/graphs/Graph.cjs +27 -16
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/messages/tools.cjs +4 -0
- package/dist/cjs/messages/tools.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +27 -16
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/messages/tools.mjs +4 -0
- package/dist/esm/messages/tools.mjs.map +1 -1
- package/package.json +1 -1
- package/src/graphs/Graph.ts +27 -15
- package/src/llm/bedrock/llm.spec.ts +6 -6
- package/src/messages/tools.ts +2 -0
- package/src/tools/__tests__/BrowserTools.test.ts +6 -4
package/package.json
CHANGED
package/src/graphs/Graph.ts
CHANGED
|
@@ -737,27 +737,30 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
737
737
|
} = structuredOutputConfig;
|
|
738
738
|
|
|
739
739
|
// Determine the method based on mode and provider
|
|
740
|
-
// - 'tool': Use tool calling (works
|
|
741
|
-
// - '
|
|
740
|
+
// - 'tool' / 'functionCalling': Use tool calling (works with OpenAI, Bedrock)
|
|
741
|
+
// - 'provider' / 'jsonMode': Use native JSON mode (OpenAI, Anthropic direct - NOT Bedrock)
|
|
742
742
|
// - 'auto': Auto-detect based on provider
|
|
743
|
+
// NOTE: ChatBedrockConverse does NOT support 'jsonMode' - it only supports tool-based structured output
|
|
743
744
|
let method: 'functionCalling' | 'jsonMode' | 'jsonSchema' | undefined;
|
|
744
745
|
|
|
745
746
|
if (mode === 'tool') {
|
|
746
747
|
method = 'functionCalling';
|
|
747
748
|
} else if (mode === 'provider') {
|
|
748
|
-
// Use native JSON mode -
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
// OpenAI, Azure work better with function calling
|
|
754
|
-
if (provider === Providers.BEDROCK || provider === Providers.ANTHROPIC) {
|
|
755
|
-
method = 'jsonMode';
|
|
756
|
-
} else if (provider === Providers.GOOGLE || provider === Providers.VERTEXAI) {
|
|
757
|
-
// Gemini supports native JSON mode
|
|
749
|
+
// Use native JSON mode - but NOT for Bedrock which doesn't support it
|
|
750
|
+
if (provider === Providers.BEDROCK) {
|
|
751
|
+
// Bedrock only supports function calling for structured output
|
|
752
|
+
method = 'functionCalling';
|
|
753
|
+
} else {
|
|
758
754
|
method = 'jsonMode';
|
|
759
755
|
}
|
|
760
|
-
|
|
756
|
+
} else {
|
|
757
|
+
// Auto mode: use function calling for all providers
|
|
758
|
+
// This is the most compatible approach
|
|
759
|
+
// Bedrock: only supports functionCalling
|
|
760
|
+
// Anthropic direct: supports both but functionCalling is more reliable
|
|
761
|
+
// OpenAI/Azure: supports both, functionCalling is default
|
|
762
|
+
// Google/Vertex: supports jsonMode but functionCalling works too
|
|
763
|
+
method = undefined; // Let LangChain choose the default
|
|
761
764
|
}
|
|
762
765
|
|
|
763
766
|
// Use withStructuredOutput to bind the schema
|
|
@@ -1125,18 +1128,27 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1125
1128
|
// Also disable thinking mode - Anthropic/Bedrock doesn't allow tool_choice with thinking enabled
|
|
1126
1129
|
const structuredClientOptions = { ...agentContext.clientOptions } as t.ClientOptions;
|
|
1127
1130
|
|
|
1131
|
+
// CRITICAL: Disable streaming for structured output
|
|
1132
|
+
// Structured output uses model.invoke() with tool binding, not streaming
|
|
1133
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1134
|
+
(structuredClientOptions as any).streaming = false;
|
|
1135
|
+
|
|
1128
1136
|
// Remove thinking configuration for Bedrock
|
|
1137
|
+
// Bedrock uses additionalModelRequestFields.thinking for extended thinking
|
|
1129
1138
|
if (agentContext.provider === Providers.BEDROCK) {
|
|
1130
1139
|
const bedrockOpts = structuredClientOptions as t.BedrockAnthropicClientOptions;
|
|
1131
|
-
if (bedrockOpts.additionalModelRequestFields
|
|
1140
|
+
if (bedrockOpts.additionalModelRequestFields) {
|
|
1132
1141
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1133
1142
|
const additionalFields = Object.assign({}, bedrockOpts.additionalModelRequestFields) as any;
|
|
1143
|
+
// Remove thinking configuration
|
|
1134
1144
|
delete additionalFields.thinking;
|
|
1145
|
+
// Remove budget tokens which is also related to thinking
|
|
1146
|
+
delete additionalFields.budgetTokens;
|
|
1135
1147
|
bedrockOpts.additionalModelRequestFields = additionalFields;
|
|
1136
1148
|
}
|
|
1137
1149
|
}
|
|
1138
1150
|
|
|
1139
|
-
// Remove thinking configuration for Anthropic
|
|
1151
|
+
// Remove thinking configuration for Anthropic direct API
|
|
1140
1152
|
if (agentContext.provider === Providers.ANTHROPIC) {
|
|
1141
1153
|
const anthropicOpts = structuredClientOptions as t.AnthropicClientOptions;
|
|
1142
1154
|
if (anthropicOpts.thinking) {
|
|
@@ -315,7 +315,7 @@ describe('CustomChatBedrockConverse', () => {
|
|
|
315
315
|
expect(model.removeContentBlockIndex(undefined)).toBeUndefined();
|
|
316
316
|
});
|
|
317
317
|
|
|
318
|
-
test('
|
|
318
|
+
test('processChunk should remove contentBlockIndex from AIMessageChunk response_metadata', () => {
|
|
319
319
|
const model = getModelWithCleanMethods();
|
|
320
320
|
|
|
321
321
|
const chunkWithIndex = new ChatGenerationChunk({
|
|
@@ -329,7 +329,7 @@ describe('CustomChatBedrockConverse', () => {
|
|
|
329
329
|
}),
|
|
330
330
|
});
|
|
331
331
|
|
|
332
|
-
const cleaned = model.
|
|
332
|
+
const cleaned = model.processChunk(chunkWithIndex);
|
|
333
333
|
|
|
334
334
|
expect(cleaned.message.response_metadata).toEqual({
|
|
335
335
|
stopReason: null,
|
|
@@ -340,7 +340,7 @@ describe('CustomChatBedrockConverse', () => {
|
|
|
340
340
|
expect(cleaned.text).toBe('Hello');
|
|
341
341
|
});
|
|
342
342
|
|
|
343
|
-
test('
|
|
343
|
+
test('processChunk should pass through chunks without contentBlockIndex unchanged', () => {
|
|
344
344
|
const model = getModelWithCleanMethods();
|
|
345
345
|
|
|
346
346
|
const chunkWithoutIndex = new ChatGenerationChunk({
|
|
@@ -354,7 +354,7 @@ describe('CustomChatBedrockConverse', () => {
|
|
|
354
354
|
}),
|
|
355
355
|
});
|
|
356
356
|
|
|
357
|
-
const cleaned = model.
|
|
357
|
+
const cleaned = model.processChunk(chunkWithoutIndex);
|
|
358
358
|
|
|
359
359
|
expect(cleaned.message.response_metadata).toEqual({
|
|
360
360
|
stopReason: 'end_turn',
|
|
@@ -362,7 +362,7 @@ describe('CustomChatBedrockConverse', () => {
|
|
|
362
362
|
});
|
|
363
363
|
});
|
|
364
364
|
|
|
365
|
-
test('
|
|
365
|
+
test('processChunk should handle deeply nested contentBlockIndex in response_metadata', () => {
|
|
366
366
|
const model = getModelWithCleanMethods();
|
|
367
367
|
|
|
368
368
|
const chunkWithNestedIndex = new ChatGenerationChunk({
|
|
@@ -381,7 +381,7 @@ describe('CustomChatBedrockConverse', () => {
|
|
|
381
381
|
}),
|
|
382
382
|
});
|
|
383
383
|
|
|
384
|
-
const cleaned = model.
|
|
384
|
+
const cleaned = model.processChunk(chunkWithNestedIndex);
|
|
385
385
|
|
|
386
386
|
expect(cleaned.message.response_metadata).toEqual({
|
|
387
387
|
amazon: {
|
package/src/messages/tools.ts
CHANGED
|
@@ -19,6 +19,7 @@ type ToolSearchArtifact = {
|
|
|
19
19
|
* @returns Array of discovered tool names (empty if no new discoveries)
|
|
20
20
|
*/
|
|
21
21
|
export function extractToolDiscoveries(messages: BaseMessage[]): string[] {
|
|
22
|
+
if (messages.length === 0) return [];
|
|
22
23
|
const lastMessage = messages[messages.length - 1];
|
|
23
24
|
// Use getType() instead of instanceof to avoid module mismatch issues
|
|
24
25
|
if (lastMessage.getType() !== MessageTypes.TOOL) return [];
|
|
@@ -69,6 +70,7 @@ export function extractToolDiscoveries(messages: BaseMessage[]): string[] {
|
|
|
69
70
|
* Quick check to avoid full extraction when not needed.
|
|
70
71
|
*/
|
|
71
72
|
export function hasToolSearchInCurrentTurn(messages: BaseMessage[]): boolean {
|
|
73
|
+
if (messages.length === 0) return false;
|
|
72
74
|
const lastMessage = messages[messages.length - 1];
|
|
73
75
|
// Use getType() instead of instanceof to avoid module mismatch issues
|
|
74
76
|
if (lastMessage.getType() !== MessageTypes.TOOL) return false;
|
|
@@ -19,10 +19,12 @@ describe('BrowserTools', () => {
|
|
|
19
19
|
expect(EBrowserTools.BACK).toBe('browser_back');
|
|
20
20
|
expect(EBrowserTools.SCREENSHOT).toBe('browser_screenshot');
|
|
21
21
|
expect(EBrowserTools.GET_PAGE_STATE).toBe('browser_get_page_state');
|
|
22
|
+
expect(EBrowserTools.KEYPRESS).toBe('browser_keypress');
|
|
23
|
+
expect(EBrowserTools.SWITCH_TAB).toBe('browser_switch_tab');
|
|
22
24
|
});
|
|
23
25
|
|
|
24
|
-
it('should have exactly
|
|
25
|
-
expect(Object.keys(EBrowserTools).length).toBe(
|
|
26
|
+
it('should have exactly 12 browser tools', () => {
|
|
27
|
+
expect(Object.keys(EBrowserTools).length).toBe(12);
|
|
26
28
|
});
|
|
27
29
|
});
|
|
28
30
|
|
|
@@ -82,8 +84,8 @@ describe('BrowserTools', () => {
|
|
|
82
84
|
tools = createBrowserTools();
|
|
83
85
|
});
|
|
84
86
|
|
|
85
|
-
it('should create exactly
|
|
86
|
-
expect(tools.length).toBe(
|
|
87
|
+
it('should create exactly 12 browser tools', () => {
|
|
88
|
+
expect(tools.length).toBe(12);
|
|
87
89
|
});
|
|
88
90
|
|
|
89
91
|
it('should create tools with correct names', () => {
|