illuma-agents 1.0.50 → 1.0.52

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.
@@ -43,9 +43,27 @@ export class AgentContext {
43
43
  reasoningKey,
44
44
  useLegacyContent,
45
45
  dynamicContext,
46
- structuredOutput,
46
+ structuredOutput: structuredOutputCamel,
47
+ // eslint-disable-next-line @typescript-eslint/naming-convention
48
+ structured_output: structuredOutputSnake,
47
49
  } = agentConfig;
48
50
 
51
+ // Normalize structured output: support both camelCase and snake_case inputs
52
+ // Priority: structuredOutput (camelCase) > structured_output (snake_case with enabled check)
53
+ let structuredOutput: t.StructuredOutputConfig | undefined;
54
+ if (structuredOutputCamel) {
55
+ structuredOutput = structuredOutputCamel;
56
+ } else if (structuredOutputSnake?.enabled && structuredOutputSnake.schema) {
57
+ // Convert snake_case input to StructuredOutputConfig
58
+ structuredOutput = {
59
+ schema: structuredOutputSnake.schema,
60
+ name: structuredOutputSnake.name,
61
+ description: structuredOutputSnake.description,
62
+ mode: structuredOutputSnake.mode,
63
+ strict: structuredOutputSnake.strict,
64
+ };
65
+ }
66
+
49
67
  const agentContext = new AgentContext({
50
68
  agentId,
51
69
  name: name ?? agentId,
@@ -700,11 +700,13 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
700
700
  finalMessages,
701
701
  schema,
702
702
  structuredOutputConfig,
703
+ provider,
703
704
  }: {
704
705
  currentModel: t.ChatModelInstance;
705
706
  finalMessages: BaseMessage[];
706
707
  schema: Record<string, unknown>;
707
708
  structuredOutputConfig: t.StructuredOutputConfig;
709
+ provider?: Providers;
708
710
  },
709
711
  config?: RunnableConfig
710
712
  ): Promise<{
@@ -728,15 +730,44 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
728
730
 
729
731
  const {
730
732
  name = 'StructuredResponse',
733
+ mode = 'auto',
731
734
  includeRaw = false,
732
735
  handleErrors = true,
733
736
  maxRetries = 2,
734
737
  } = structuredOutputConfig;
735
738
 
739
+ // Determine the method based on mode and provider
740
+ // - 'tool' / 'functionCalling': Use tool calling (works with OpenAI, Bedrock)
741
+ // - 'provider' / 'jsonMode': Use native JSON mode (OpenAI, Anthropic direct - NOT Bedrock)
742
+ // - 'auto': Auto-detect based on provider
743
+ // NOTE: ChatBedrockConverse does NOT support 'jsonMode' - it only supports tool-based structured output
744
+ let method: 'functionCalling' | 'jsonMode' | 'jsonSchema' | undefined;
745
+
746
+ if (mode === 'tool') {
747
+ method = 'functionCalling';
748
+ } else if (mode === 'provider') {
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 {
754
+ method = 'jsonMode';
755
+ }
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
764
+ }
765
+
736
766
  // Use withStructuredOutput to bind the schema
737
767
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
738
768
  const structuredModel = (model as any).withStructuredOutput(schema, {
739
769
  name,
770
+ method,
740
771
  includeRaw,
741
772
  strict: structuredOutputConfig.strict !== false,
742
773
  });
@@ -1098,17 +1129,21 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
1098
1129
  const structuredClientOptions = { ...agentContext.clientOptions } as t.ClientOptions;
1099
1130
 
1100
1131
  // Remove thinking configuration for Bedrock
1132
+ // Bedrock uses additionalModelRequestFields.thinking for extended thinking
1101
1133
  if (agentContext.provider === Providers.BEDROCK) {
1102
1134
  const bedrockOpts = structuredClientOptions as t.BedrockAnthropicClientOptions;
1103
- if (bedrockOpts.additionalModelRequestFields?.['thinking']) {
1135
+ if (bedrockOpts.additionalModelRequestFields) {
1104
1136
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1105
1137
  const additionalFields = Object.assign({}, bedrockOpts.additionalModelRequestFields) as any;
1138
+ // Remove thinking configuration
1106
1139
  delete additionalFields.thinking;
1140
+ // Remove budget tokens which is also related to thinking
1141
+ delete additionalFields.budgetTokens;
1107
1142
  bedrockOpts.additionalModelRequestFields = additionalFields;
1108
1143
  }
1109
1144
  }
1110
1145
 
1111
- // Remove thinking configuration for Anthropic
1146
+ // Remove thinking configuration for Anthropic direct API
1112
1147
  if (agentContext.provider === Providers.ANTHROPIC) {
1113
1148
  const anthropicOpts = structuredClientOptions as t.AnthropicClientOptions;
1114
1149
  if (anthropicOpts.thinking) {
@@ -1116,6 +1151,8 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
1116
1151
  }
1117
1152
  }
1118
1153
 
1154
+ console.log('[Graph] Creating structured model for provider:', agentContext.provider, 'with options:', JSON.stringify(structuredClientOptions, null, 2));
1155
+
1119
1156
  const structuredModel = this.getNewModel({
1120
1157
  provider: agentContext.provider,
1121
1158
  clientOptions: structuredClientOptions,
@@ -1128,6 +1165,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
1128
1165
  finalMessages,
1129
1166
  schema,
1130
1167
  structuredOutputConfig: agentContext.structuredOutput,
1168
+ provider: agentContext.provider,
1131
1169
  },
1132
1170
  config
1133
1171
  );
@@ -420,6 +420,25 @@ export interface StructuredOutputConfig {
420
420
  includeRaw?: boolean;
421
421
  }
422
422
 
423
+ /**
424
+ * Database/API structured output format (snake_case with enabled flag).
425
+ * This matches the format stored in MongoDB and sent from frontends.
426
+ */
427
+ export interface StructuredOutputInput {
428
+ /** Whether structured output is enabled */
429
+ enabled?: boolean;
430
+ /** JSON Schema defining the expected response structure */
431
+ schema?: Record<string, unknown>;
432
+ /** Name identifier for the structured output */
433
+ name?: string;
434
+ /** Description of what the structured output represents */
435
+ description?: string;
436
+ /** Mode for structured output: 'tool' | 'provider' | 'auto' */
437
+ mode?: StructuredOutputMode;
438
+ /** Whether to enforce strict schema validation */
439
+ strict?: boolean;
440
+ }
441
+
423
442
  export interface AgentInputs {
424
443
  agentId: string;
425
444
  /** Human-readable name for the agent (used in handoff context). Defaults to agentId if not provided. */
@@ -450,11 +469,18 @@ export interface AgentInputs {
450
469
  */
451
470
  dynamicContext?: string;
452
471
  /**
453
- * Structured output configuration.
472
+ * Structured output configuration (camelCase).
454
473
  * When set, disables streaming and returns a validated JSON response
455
474
  * conforming to the specified schema.
456
475
  */
457
476
  structuredOutput?: StructuredOutputConfig;
477
+ /**
478
+ * Structured output configuration (snake_case - database/API format).
479
+ * Alternative to structuredOutput for compatibility with MongoDB/frontend.
480
+ * Uses an `enabled` flag to control activation.
481
+ * @deprecated Use structuredOutput instead when possible
482
+ */
483
+ structured_output?: StructuredOutputInput;
458
484
  /**
459
485
  * Serializable tool definitions for event-driven execution.
460
486
  * When provided, ToolNode operates in event-driven mode, dispatching