@smythos/sre 1.5.39 → 1.5.40

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.
@@ -0,0 +1,19 @@
1
+ import Joi from 'joi';
2
+ import { IAgent as Agent } from '@sre/types/Agent.types';
3
+ import { Component } from './Component.class';
4
+ export declare class MemoryDeleteKeyVal extends Component {
5
+ protected configSchema: Joi.ObjectSchema<any>;
6
+ constructor();
7
+ init(): void;
8
+ process(input: any, config: any, agent: Agent): Promise<{
9
+ Key: string;
10
+ deleted: boolean;
11
+ _debug: string;
12
+ _error?: undefined;
13
+ } | {
14
+ _error: any;
15
+ _debug: string;
16
+ Key?: undefined;
17
+ deleted?: undefined;
18
+ }>;
19
+ }
@@ -0,0 +1,17 @@
1
+ import Joi from 'joi';
2
+ import { IAgent as Agent } from '@sre/types/Agent.types';
3
+ import { Component } from './Component.class';
4
+ export declare class MemoryReadKeyVal extends Component {
5
+ protected configSchema: Joi.ObjectSchema<any>;
6
+ constructor();
7
+ init(): void;
8
+ process(input: any, config: any, agent: Agent): Promise<{
9
+ Value: any;
10
+ _debug: string;
11
+ _error?: undefined;
12
+ } | {
13
+ _error: any;
14
+ _debug: string;
15
+ Value?: undefined;
16
+ }>;
17
+ }
@@ -0,0 +1,17 @@
1
+ import Joi from 'joi';
2
+ import { IAgent as Agent } from '@sre/types/Agent.types';
3
+ import { Component } from './Component.class';
4
+ export declare class MemoryWriteKeyVal extends Component {
5
+ protected configSchema: Joi.ObjectSchema<any>;
6
+ constructor();
7
+ init(): void;
8
+ process(input: any, config: any, agent: Agent): Promise<{
9
+ Key: string;
10
+ _debug: string;
11
+ _error?: undefined;
12
+ } | {
13
+ _error: any;
14
+ _debug: string;
15
+ Key?: undefined;
16
+ }>;
17
+ }
@@ -0,0 +1,19 @@
1
+ import Joi from 'joi';
2
+ import { IAgent as Agent } from '@sre/types/Agent.types';
3
+ import { Component } from './Component.class';
4
+ export declare class MemoryWriteObject extends Component {
5
+ protected configSchema: Joi.ObjectSchema<any>;
6
+ constructor();
7
+ init(): void;
8
+ process(input: any, config: any, agent: Agent): Promise<{
9
+ Keys: string[];
10
+ Count: number;
11
+ _debug: string;
12
+ _error?: undefined;
13
+ } | {
14
+ _error: any;
15
+ _debug: string;
16
+ Keys?: undefined;
17
+ Count?: undefined;
18
+ }>;
19
+ }
@@ -38,6 +38,10 @@ import { ImageGenerator } from './ImageGenerator.class';
38
38
  import { MCPClient } from './MCPClient.class';
39
39
  import { OpenAPI } from './OpenAPI.class';
40
40
  import { ECMASandbox } from './ECMASandbox.class';
41
+ import { MemoryWriteKeyVal } from './MemoryWriteKeyVal.class';
42
+ import { MemoryReadKeyVal } from './MemoryReadKeyVal.class';
43
+ import { MemoryDeleteKeyVal } from './MemoryDeleteKeyVal.class';
44
+ import { MemoryWriteObject } from './MemoryWriteObject.class';
41
45
  export declare const ComponentInstances: {
42
46
  Component: Component;
43
47
  Note: Component;
@@ -83,4 +87,8 @@ export declare const ComponentInstances: {
83
87
  MCPClient: MCPClient;
84
88
  OpenAPI: OpenAPI;
85
89
  ECMASandbox: ECMASandbox;
90
+ MemoryWriteKeyVal: MemoryWriteKeyVal;
91
+ MemoryReadKeyVal: MemoryReadKeyVal;
92
+ MemoryDeleteKeyVal: MemoryDeleteKeyVal;
93
+ MemoryWriteObject: MemoryWriteObject;
86
94
  };
@@ -32,6 +32,10 @@ export * from './Components/LogicAtMost.class';
32
32
  export * from './Components/LogicOR.class';
33
33
  export * from './Components/LogicXOR.class';
34
34
  export * from './Components/MCPClient.class';
35
+ export * from './Components/MemoryDeleteKeyVal.class';
36
+ export * from './Components/MemoryReadKeyVal.class';
37
+ export * from './Components/MemoryWriteKeyVal.class';
38
+ export * from './Components/MemoryWriteObject.class';
35
39
  export * from './Components/MultimodalLLM.class';
36
40
  export * from './Components/PromptGenerator.class';
37
41
  export * from './Components/ScrapflyWebScrape.class';
@@ -1,16 +1,14 @@
1
1
  import { type UsageMetadata } from '@google-cloud/vertexai';
2
2
  import EventEmitter from 'events';
3
- import { APIKeySource, ILLMRequestFuncParams, TGoogleAIRequestBody, TLLMPreparedParams, TLLMMessageBlock, ToolData, TLLMToolResultMessageBlock, TLLMMessageRole } from '@sre/types/LLM.types';
3
+ import { APIKeySource, ILLMRequestFuncParams, TGoogleAIRequestBody, TLLMPreparedParams, TLLMMessageBlock, ToolData, TLLMToolResultMessageBlock, TLLMChatResponse } from '@sre/types/LLM.types';
4
4
  import { LLMConnector } from '../LLMConnector';
5
5
  export declare class VertexAIConnector extends LLMConnector {
6
6
  name: string;
7
7
  private getClient;
8
- protected request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<any>;
8
+ protected request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse>;
9
9
  protected streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter>;
10
10
  protected reqBodyAdapter(params: TLLMPreparedParams): Promise<TGoogleAIRequestBody>;
11
- protected reportUsage(usage: UsageMetadata & {
12
- cachedContentTokenCount?: number;
13
- }, metadata: {
11
+ protected reportUsage(usage: UsageMetadata, metadata: {
14
12
  modelEntryName: string;
15
13
  keySource: APIKeySource;
16
14
  agentId: string;
@@ -25,7 +23,10 @@ export declare class VertexAIConnector extends LLMConnector {
25
23
  agentId: string;
26
24
  teamId: string;
27
25
  };
28
- private sanitizeFunctionName;
26
+ private prepareMessages;
27
+ private processFiles;
28
+ private convertMessagesToVertexAIFormat;
29
+ private formatToolsForVertexAI;
29
30
  formatToolsConfig({ toolDefinitions, toolChoice }: {
30
31
  toolDefinitions: any;
31
32
  toolChoice?: string;
@@ -39,8 +40,4 @@ export declare class VertexAIConnector extends LLMConnector {
39
40
  messageBlock: TLLMMessageBlock;
40
41
  toolsData: ToolData[];
41
42
  }): TLLMToolResultMessageBlock[];
42
- getConsistentMessages(messages: any): {
43
- role: TLLMMessageRole;
44
- parts: any[];
45
- }[];
46
43
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smythos/sre",
3
- "version": "1.5.39",
3
+ "version": "1.5.40",
4
4
  "description": "Smyth Runtime Environment",
5
5
  "author": "Alaa-eddine KADDOURI",
6
6
  "license": "MIT",
@@ -0,0 +1,70 @@
1
+ import Joi from 'joi';
2
+
3
+ import { IAgent as Agent } from '@sre/types/Agent.types';
4
+ import { Component } from './Component.class';
5
+ import { ConnectorService } from '@sre/Core/ConnectorsService';
6
+ import { TemplateString } from '@sre/helpers/TemplateString.helper';
7
+ import { ICacheRequest } from '@sre/MemoryManager/Cache.service/CacheConnector';
8
+
9
+ export class MemoryDeleteKeyVal extends Component {
10
+ protected configSchema = Joi.object({
11
+ memoryName: Joi.string().max(255).allow('').label('Memory Name'),
12
+ key: Joi.string().max(255).allow('').label('Key'),
13
+ });
14
+ constructor() {
15
+ super();
16
+ }
17
+ init() {}
18
+ async process(input, config, agent: Agent) {
19
+ await super.process(input, config, agent);
20
+
21
+ const logger = this.createComponentLogger(agent, config);
22
+
23
+ try {
24
+ const cacheConnector = ConnectorService.getCacheConnector();
25
+ const connectorRequester: ICacheRequest = cacheConnector.agent(agent.id);
26
+ const teamId = agent.teamId;
27
+ const agentId = agent.id;
28
+
29
+ const memoryName = config.data.memoryName;
30
+ const key = TemplateString(config.data.key).parse(input).result;
31
+
32
+ const sessionId = agent.sessionId;
33
+ const workflowId = agent.agentRuntime.workflowReqId;
34
+
35
+ logger.debug(`Reading Scope Data for deletion`);
36
+ const scopeKeyId = `${agentId}:${memoryName}:${key}_scope`;
37
+ const scopeStrData = await connectorRequester.get(scopeKeyId);
38
+
39
+ if (!scopeStrData) {
40
+ return { _error: 'key not found', _debug: logger.output };
41
+ }
42
+
43
+ logger.debug(`Checking Scope for deletion`);
44
+ const scopeData = JSON.parse(scopeStrData);
45
+ const scopeKey = scopeData.value;
46
+
47
+ // Validate scope access like in MemoryReadKeyVal
48
+ if (scopeData.scope === 'session' && scopeKey !== sessionId) {
49
+ return { _error: 'key not found', _debug: logger.output };
50
+ }
51
+
52
+ if (scopeData.scope === 'request' && scopeKey !== workflowId) {
53
+ return { _error: 'key not found', _debug: logger.output };
54
+ }
55
+
56
+ logger.debug(`Deleting memory value and scope data`);
57
+
58
+ // Delete the actual value
59
+ const fullKey = `${agentId}:${scopeKey}:${memoryName}:${key}`;
60
+ await connectorRequester.delete(fullKey);
61
+
62
+ // Delete the scope metadata
63
+ await connectorRequester.delete(scopeKeyId);
64
+
65
+ return { Key: key, deleted: true, _debug: logger.output };
66
+ } catch (error: any) {
67
+ return { _error: error.message, _debug: logger.output };
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,66 @@
1
+ import Joi from 'joi';
2
+
3
+ import { IAgent as Agent } from '@sre/types/Agent.types';
4
+ import { Component } from './Component.class';
5
+ import { ConnectorService } from '@sre/Core/ConnectorsService';
6
+ import { TemplateString } from '@sre/helpers/TemplateString.helper';
7
+ import { ICacheRequest } from '@sre/MemoryManager/Cache.service/CacheConnector';
8
+
9
+ const memory = {};
10
+ export class MemoryReadKeyVal extends Component {
11
+ protected configSchema = Joi.object({
12
+ memoryName: Joi.string().max(255).allow('').label('Memory Name'),
13
+ });
14
+ constructor() {
15
+ super();
16
+ }
17
+ init() {}
18
+ async process(input, config, agent: Agent) {
19
+ await super.process(input, config, agent);
20
+
21
+ const logger = this.createComponentLogger(agent, config);
22
+
23
+ try {
24
+ const cacheConnector = ConnectorService.getCacheConnector();
25
+ const connectorRequester: ICacheRequest = cacheConnector.agent(agent.id);
26
+ const teamId = agent.teamId;
27
+ const agentId = agent.id;
28
+
29
+ const memoryName = config.data.memoryName;
30
+
31
+ const key = input.Key;
32
+
33
+ const sessionId = agent.sessionId;
34
+ const workflowId = agent.agentRuntime.workflowReqId;
35
+
36
+ logger.debug(`Reading Scope Data`);
37
+ const scopeKeyId = `${agentId}:${memoryName}:${key}_scope`;
38
+ const scopeStrData = await connectorRequester.get(scopeKeyId);
39
+
40
+ if (!scopeStrData) {
41
+ return { _error: 'key not found', _debug: logger.output };
42
+ }
43
+
44
+ logger.debug(`Checking Scope`);
45
+ const scopeData = JSON.parse(scopeStrData);
46
+ const scopeKey = scopeData.value;
47
+ if (scopeData.scope === 'session' && scopeKey !== sessionId) {
48
+ return { _error: 'key not found', _debug: logger.output };
49
+ }
50
+
51
+ if (scopeData.scope === 'request' && scopeKey !== workflowId) {
52
+ return { _error: 'key not found', _debug: logger.output };
53
+ }
54
+
55
+ logger.debug(`Reading Value`);
56
+
57
+ const fullKey = `${agentId}:${scopeKey}:${memoryName}:${key}`;
58
+
59
+ const value = await connectorRequester.get(fullKey);
60
+
61
+ return { Value: value, _debug: logger.output };
62
+ } catch (error: any) {
63
+ return { _error: error.message, _debug: logger.output };
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,62 @@
1
+ import Joi from 'joi';
2
+
3
+ import { IAgent as Agent } from '@sre/types/Agent.types';
4
+ import { Component } from './Component.class';
5
+ import { ConnectorService } from '@sre/Core/ConnectorsService';
6
+ import { TemplateString } from '@sre/helpers/TemplateString.helper';
7
+ import { ICacheRequest } from '@sre/MemoryManager/Cache.service/CacheConnector';
8
+
9
+ const memory = {};
10
+ export class MemoryWriteKeyVal extends Component {
11
+ protected configSchema = Joi.object({
12
+ memoryName: Joi.string().max(255).allow('').label('Memory Name'),
13
+ key: Joi.string().max(255).allow('').label('Key'),
14
+ value: Joi.string().max(100000).allow('').label('Value'),
15
+ scope: Joi.string().max(20).allow('').label('Scope'),
16
+ ttl: Joi.number().min(300).max(604800).allow('').label('TTL'),
17
+ });
18
+ constructor() {
19
+ super();
20
+ }
21
+ init() {}
22
+ async process(input, config, agent: Agent) {
23
+ await super.process(input, config, agent);
24
+
25
+ const logger = this.createComponentLogger(agent, config);
26
+
27
+ try {
28
+ const cacheConnector = ConnectorService.getCacheConnector();
29
+ const connectorRequester: ICacheRequest = cacheConnector.agent(agent.id);
30
+ const teamId = agent.teamId;
31
+ const agentId = agent.id;
32
+
33
+ const memoryName = config.data.memoryName;
34
+ const key = TemplateString(config.data.key).parse(input).result;
35
+ const value = TemplateString(config.data.value).parse(input).result;
36
+ const scope = config.data.scope;
37
+ const ttl = scope === 'ttl' ? config?.data?.ttl : 3 * 60 * 60; // 3 hours default ttl
38
+
39
+ const sessionId = agent.sessionId;
40
+ const workflowId = agent.agentRuntime.workflowReqId;
41
+
42
+ let scopeKey = '';
43
+ if (scope === 'session') {
44
+ scopeKey = sessionId;
45
+ } else if (scope === 'request') {
46
+ scopeKey = workflowId;
47
+ } else if (scope === 'ttl') {
48
+ scopeKey = 'ttl';
49
+ }
50
+
51
+ const scopeKeyId = `${agentId}:${memoryName}:${key}_scope`;
52
+ await connectorRequester.set(scopeKeyId, JSON.stringify({ scope, value: scopeKey }), null, null, ttl);
53
+
54
+ const fullKey = `${agentId}:${scopeKey}:${memoryName}:${key}`;
55
+ await connectorRequester.set(fullKey, value, null, null, ttl);
56
+
57
+ return { Key: key, _debug: logger.output };
58
+ } catch (error: any) {
59
+ return { _error: error.message, _debug: logger.output };
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,97 @@
1
+ import Joi from 'joi';
2
+
3
+ import { IAgent as Agent } from '@sre/types/Agent.types';
4
+ import { Component } from './Component.class';
5
+ import { ConnectorService } from '@sre/Core/ConnectorsService';
6
+ import { TemplateString } from '@sre/helpers/TemplateString.helper';
7
+ import { ICacheRequest } from '@sre/MemoryManager/Cache.service/CacheConnector';
8
+
9
+ export class MemoryWriteObject extends Component {
10
+ protected configSchema = Joi.object({
11
+ memoryName: Joi.string().max(255).allow('').label('Memory Name'),
12
+ scope: Joi.string().max(20).allow('').label('Scope'),
13
+ ttl: Joi.number().min(300).max(604800).allow('').label('TTL'),
14
+ });
15
+ constructor() {
16
+ super();
17
+ }
18
+ init() {}
19
+ async process(input, config, agent: Agent) {
20
+ await super.process(input, config, agent);
21
+
22
+ const logger = this.createComponentLogger(agent, config);
23
+
24
+ try {
25
+ const cacheConnector = ConnectorService.getCacheConnector();
26
+ const connectorRequester: ICacheRequest = cacheConnector.agent(agent.id);
27
+ const teamId = agent.teamId;
28
+ const agentId = agent.id;
29
+
30
+ const memoryName = config.data.memoryName;
31
+ const dataString = input.Data;
32
+ const scope = config.data.scope;
33
+ const ttl = scope === 'ttl' ? config?.data?.ttl : 3 * 60 * 60; // 3 hours default ttl
34
+
35
+ // Parse the JSON data
36
+ let dataObject;
37
+ try {
38
+ dataObject = JSON.parse(dataString);
39
+ } catch (parseError) {
40
+ return { _error: 'Invalid JSON data provided', _debug: logger.output };
41
+ }
42
+
43
+ // Validate that the parsed data is an object
44
+ if (typeof dataObject !== 'object' || dataObject === null || Array.isArray(dataObject)) {
45
+ return { _error: 'Data must be a valid JSON object', _debug: logger.output };
46
+ }
47
+
48
+ const sessionId = agent.sessionId;
49
+ const workflowId = agent.agentRuntime.workflowReqId;
50
+
51
+ let scopeKey = '';
52
+ if (scope === 'session') {
53
+ scopeKey = sessionId;
54
+ } else if (scope === 'request') {
55
+ scopeKey = workflowId;
56
+ } else if (scope === 'ttl') {
57
+ scopeKey = 'ttl';
58
+ }
59
+
60
+ // Get all keys from the data object
61
+ const keys = Object.keys(dataObject);
62
+ logger.debug(`Writing ${keys.length} key-value pairs to memory`);
63
+
64
+ // Create promises for parallel execution
65
+ const writePromises = keys.map(async (key) => {
66
+ const value = String(dataObject[key]); // Convert value to string
67
+
68
+ // Write scope metadata
69
+ const scopeKeyId = `${agentId}:${memoryName}:${key}_scope`;
70
+ const scopePromise = connectorRequester.set(scopeKeyId, JSON.stringify({ scope, value: scopeKey }), null, null, ttl);
71
+
72
+ // Write actual value
73
+ const fullKey = `${agentId}:${scopeKey}:${memoryName}:${key}`;
74
+ const valuePromise = connectorRequester.set(fullKey, value, null, null, ttl);
75
+
76
+ // Wait for both operations to complete for this key
77
+ await Promise.all([scopePromise, valuePromise]);
78
+
79
+ return { key, success: true };
80
+ });
81
+
82
+ // Execute all write operations in parallel
83
+ const results = await Promise.all(writePromises);
84
+ const successfulKeys = results.filter((result) => result.success).map((result) => result.key);
85
+
86
+ logger.debug(`Successfully wrote ${successfulKeys.length} keys to memory`);
87
+
88
+ return {
89
+ Keys: successfulKeys,
90
+ Count: successfulKeys.length,
91
+ _debug: logger.output,
92
+ };
93
+ } catch (error: any) {
94
+ return { _error: error.message, _debug: logger.output };
95
+ }
96
+ }
97
+ }
@@ -38,6 +38,10 @@ import { ImageGenerator } from './ImageGenerator.class'; // Legacy
38
38
  import { MCPClient } from './MCPClient.class';
39
39
  import { OpenAPI } from './OpenAPI.class';
40
40
  import { ECMASandbox } from './ECMASandbox.class';
41
+ import { MemoryWriteKeyVal } from './MemoryWriteKeyVal.class';
42
+ import { MemoryReadKeyVal } from './MemoryReadKeyVal.class';
43
+ import { MemoryDeleteKeyVal } from './MemoryDeleteKeyVal.class';
44
+ import { MemoryWriteObject } from './MemoryWriteObject.class';
41
45
 
42
46
  const components = {
43
47
  Component: new Component(),
@@ -84,6 +88,10 @@ const components = {
84
88
  MCPClient: new MCPClient(),
85
89
  OpenAPI: new OpenAPI(),
86
90
  ECMASandbox: new ECMASandbox(),
91
+ MemoryWriteKeyVal: new MemoryWriteKeyVal(),
92
+ MemoryReadKeyVal: new MemoryReadKeyVal(),
93
+ MemoryDeleteKeyVal: new MemoryDeleteKeyVal(),
94
+ MemoryWriteObject: new MemoryWriteObject(),
87
95
  };
88
96
 
89
97
  export const ComponentInstances = components;
@@ -130,8 +130,14 @@ export class Conversation extends EventEmitter {
130
130
  this._lastError = error;
131
131
  console.warn('Conversation Error: ', error?.message);
132
132
  });
133
- if (_settings?.maxContextSize) this._maxContextSize = _settings.maxContextSize;
134
- if (_settings?.maxOutputTokens) this._maxOutputTokens = _settings.maxOutputTokens;
133
+ this._maxContextSize =
134
+ _settings.maxContextSize || (this._model as TLLMModel).tokens || (this._model as TLLMModel).keyOptions?.tokens || this._maxContextSize;
135
+ this._maxOutputTokens =
136
+ _settings.maxOutputTokens ||
137
+ (this._model as TLLMModel).completionTokens ||
138
+ (this._model as TLLMModel).keyOptions?.completionTokens ||
139
+ this._maxOutputTokens;
140
+
135
141
  if (_settings?.systemPrompt) {
136
142
  this.userDefinedSystemPrompt = _settings.systemPrompt;
137
143
  }
@@ -490,9 +496,11 @@ export class Conversation extends EventEmitter {
490
496
  //this._context.addAssistantMessage(passThroughContent, message_id);
491
497
  llmMessage.content += '\n' + passThroughContent;
492
498
  this._context.addToolMessage(llmMessage, processedToolsData, message_id);
499
+
500
+ //this._context.addAssistantMessage(passThroughContent, message_id, { passthrough: true });
493
501
  //this should not be stored in the persistent conversation store
494
502
  //it's just a workaround to avoid generating more content after passthrough content
495
- this._context.addUserMessage(passThroughtContinueMessage, message_id, { internal: true });
503
+ //this._context.addUserMessage(passThroughtContinueMessage, message_id, { internal: true });
496
504
  //toolHeaders['x-passthrough'] = 'true';
497
505
  }
498
506
 
package/src/index.ts CHANGED
@@ -38,6 +38,10 @@ export * from './Components/LogicAtMost.class';
38
38
  export * from './Components/LogicOR.class';
39
39
  export * from './Components/LogicXOR.class';
40
40
  export * from './Components/MCPClient.class';
41
+ export * from './Components/MemoryDeleteKeyVal.class';
42
+ export * from './Components/MemoryReadKeyVal.class';
43
+ export * from './Components/MemoryWriteKeyVal.class';
44
+ export * from './Components/MemoryWriteObject.class';
41
45
  export * from './Components/MultimodalLLM.class';
42
46
  export * from './Components/PromptGenerator.class';
43
47
  export * from './Components/ScrapflyWebScrape.class';
package/src/index.ts.bak CHANGED
@@ -38,6 +38,10 @@ export * from './Components/LogicAtMost.class';
38
38
  export * from './Components/LogicOR.class';
39
39
  export * from './Components/LogicXOR.class';
40
40
  export * from './Components/MCPClient.class';
41
+ export * from './Components/MemoryDeleteKeyVal.class';
42
+ export * from './Components/MemoryReadKeyVal.class';
43
+ export * from './Components/MemoryWriteKeyVal.class';
44
+ export * from './Components/MemoryWriteObject.class';
41
45
  export * from './Components/MultimodalLLM.class';
42
46
  export * from './Components/PromptGenerator.class';
43
47
  export * from './Components/ScrapflyWebScrape.class';
@@ -315,8 +315,10 @@ export abstract class LLMConnector extends Connector {
315
315
  imageGeneration: features.includes('image-generation'),
316
316
  };
317
317
 
318
- // * We may have other tools info like file search, image generation, etc.
319
- // Organize web search parameters from both flat and nested structures
318
+ // We're using an object with providers instead of setting toolsInfo directly based on the provider,
319
+ // so the code stays clean and easy to read in connectors like toolsInfo.openai.webSearch or toolsInfo.xai.search.
320
+ // it helps prevent errors such as mistakenly using toolsInfo.search in the OpenAI connector and similar cases.
321
+ // This also helps enable autocomplete, so when typing toolsInfo.openai, it shows suggestions like webSearch.
320
322
  _params.toolsInfo = {
321
323
  openai: await this.prepareOpenAIToolsInfo(_params),
322
324
  xai: await this.prepareXAIToolsInfo(_params),
@@ -440,9 +440,11 @@ export class AnthropicConnector extends LLMConnector {
440
440
  }
441
441
  //#endregion Prepare system message and add JSON response instruction if needed
442
442
 
443
- if (params?.temperature !== undefined) body.temperature = params.temperature;
444
- if (params?.topP !== undefined) body.top_p = params.topP;
445
- if (params?.topK !== undefined) body.top_k = params.topK;
443
+ const isReasoningModel = params?.capabilities?.reasoning;
444
+
445
+ if (params?.temperature !== undefined && !isReasoningModel) body.temperature = params.temperature;
446
+ if (params?.topP !== undefined && !isReasoningModel) body.top_p = params.topP;
447
+ if (params?.topK !== undefined && !isReasoningModel) body.top_k = params.topK;
446
448
  if (params?.stopSequences?.length) body.stop_sequences = params.stopSequences;
447
449
 
448
450
  // #region Tools
@@ -3,7 +3,7 @@ import path from 'path';
3
3
  import EventEmitter from 'events';
4
4
  import fs from 'fs';
5
5
 
6
- import { GoogleGenerativeAI, ModelParams, GenerationConfig, GenerateContentRequest, UsageMetadata } from '@google/generative-ai';
6
+ import { GoogleGenerativeAI, ModelParams, GenerationConfig, GenerateContentRequest, UsageMetadata, FunctionCallingMode } from '@google/generative-ai';
7
7
  import { GoogleAIFileManager, FileState } from '@google/generative-ai/server';
8
8
  import { GoogleGenAI } from '@google/genai';
9
9
 
@@ -397,7 +397,7 @@ export class GoogleAIConnector extends LLMConnector {
397
397
 
398
398
  const transformedToolsData = toolsData.map(
399
399
  (toolData): TLLMToolResultMessageBlock => ({
400
- role: TLLMMessageRole.Function,
400
+ role: TLLMMessageRole.User,
401
401
  parts: [
402
402
  {
403
403
  functionResponse: {
@@ -565,8 +565,23 @@ export class GoogleAIConnector extends LLMConnector {
565
565
 
566
566
  if (params?.toolsConfig?.tools) toolsPrompt.tools = params?.toolsConfig?.tools as any;
567
567
  if (params?.toolsConfig?.tool_choice) {
568
+ // Map tool choice to valid Google AI function calling modes
569
+ let mode: FunctionCallingMode = FunctionCallingMode.AUTO; // default
570
+ const toolChoice = params?.toolsConfig?.tool_choice;
571
+
572
+ if (toolChoice === 'auto') {
573
+ mode = FunctionCallingMode.AUTO;
574
+ } else if (toolChoice === 'required') {
575
+ mode = FunctionCallingMode.ANY;
576
+ } else if (toolChoice === 'none') {
577
+ mode = FunctionCallingMode.NONE;
578
+ } else if (typeof toolChoice === 'object' && toolChoice.type === 'function') {
579
+ // Handle OpenAI-style named tool choice - force any function call
580
+ mode = FunctionCallingMode.ANY;
581
+ }
582
+
568
583
  toolsPrompt.toolConfig = {
569
- functionCallingConfig: { mode: (params?.toolsConfig?.tool_choice as any) || 'auto' },
584
+ functionCallingConfig: { mode },
570
585
  };
571
586
  }
572
587