@peopl-health/nexus 4.7.0-dev.451 → 4.7.0-dev.455

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.
@@ -3,6 +3,7 @@ const { OpenAIResponsesProvider } = require('./providers/OpenAIResponsesProvider
3
3
  const { handleFunctionCalls } = require('./providers/OpenAIResponsesProviderTools');
4
4
  const { OpenRouterProvider } = require('./providers/OpenRouterProvider');
5
5
  const { AnthropicProvider } = require('./providers/AnthropicProvider');
6
+ const { GatewayProvider } = require('./providers/GatewayProvider');
6
7
 
7
8
  const { composePrompt, resolveTools, clearCache } = require('./services/promptComposerService');
8
9
  const { createAssistant, preProcessMessages, switchAssistant } = require('./services/assistantService');
@@ -29,6 +30,7 @@ module.exports = {
29
30
  handleFunctionCalls,
30
31
  OpenRouterProvider,
31
32
  AnthropicProvider,
33
+ GatewayProvider,
32
34
  composePrompt,
33
35
  resolveTools,
34
36
  clearCache,
@@ -51,7 +51,7 @@ class BaseLLMProvider {
51
51
 
52
52
  const toolSchemas = this._resolveToolSchemas({ assistant, toolIds, filtered, toolDescriptions });
53
53
  const devContent = this._buildInstructions({ resolvedPrompt, toolSchemas, prePromptResult, additionalInstructions });
54
- const input = this._buildInput({ context, prePromptResult, additionalInstructions, promptVariables });
54
+ const input = this._buildInput({ context, prePromptResult, additionalInstructions, promptVariables, modelConfig });
55
55
 
56
56
  trace?.setPrompt({ resolved: devContent, resolvedPresetId, resolvedPresetVersion });
57
57
 
@@ -137,13 +137,13 @@ class BaseLLMProvider {
137
137
  return { role: 'user', content: CONVERSATION_CONTINUATION };
138
138
  }
139
139
 
140
- _buildInput({ context, prePromptResult, additionalInstructions, promptVariables }) {
140
+ _buildInput({ context, prePromptResult, additionalInstructions, promptVariables, modelConfig = null }) {
141
141
  let messages = this._convertItemsToApiFormat(context || []);
142
142
  if (Array.isArray(prePromptResult?.additionalMessages) && prePromptResult.additionalMessages.length > 0) {
143
143
  messages = [...messages, ...this._convertItemsToApiFormat(prePromptResult.additionalMessages)];
144
144
  }
145
145
  if (additionalInstructions) {
146
- messages = [...messages, this._operatorInstructionTurn(additionalInstructions)];
146
+ messages = [...messages, this._operatorInstructionTurn(additionalInstructions, modelConfig)];
147
147
  }
148
148
  return this._sanitizeInput([...this._buildMemoryMessage(promptVariables), ...messages]);
149
149
  }
@@ -160,6 +160,10 @@ class BaseLLMProvider {
160
160
  throw new Error(`${this.constructor.name} must implement _invokeModel()`);
161
161
  }
162
162
 
163
+ _mapModelConfig(modelConfig) {
164
+ return modelConfig;
165
+ }
166
+
163
167
  async transcribeAudio() {
164
168
  throw new Error(`transcribeAudio is not supported by ${this.constructor.name}`);
165
169
  }
@@ -0,0 +1,84 @@
1
+ const { composePrompt } = require('../services/promptComposerService');
2
+
3
+ const { BaseLLMProvider } = require('./BaseLLMProvider');
4
+
5
+ const VENDOR_VARIANT = {
6
+ openai: 'responses',
7
+ anthropic: 'anthropic',
8
+ openrouter: 'openrouter',
9
+ };
10
+
11
+ class GatewayProvider extends BaseLLMProvider {
12
+ constructor(options = {}) {
13
+ super(options);
14
+ this.variant = 'gateway';
15
+ this.supportsPromptRegistry = true;
16
+ this._subs = {};
17
+ }
18
+
19
+ _defaultSub() {
20
+ return this._sub('openai');
21
+ }
22
+
23
+ getClient() {
24
+ return this._defaultSub().getClient();
25
+ }
26
+
27
+ transcribeAudio(options) {
28
+ return this._defaultSub().transcribeAudio(options);
29
+ }
30
+
31
+ _operatorInstructionTurn(additionalInstructions, modelConfig = null) {
32
+ const { vendor } = this._route(modelConfig?.model);
33
+ return this._sub(vendor)._operatorInstructionTurn(additionalInstructions);
34
+ }
35
+
36
+ _route(model) {
37
+ if (!model) return { vendor: 'openai', model: undefined };
38
+ const slash = model.indexOf('/');
39
+ if (slash === -1) return { vendor: 'openai', model };
40
+ const vendor = model.slice(0, slash);
41
+ if (vendor === 'openai' || vendor === 'anthropic' || vendor === 'openrouter') {
42
+ return { vendor, model: model.slice(slash + 1) };
43
+ }
44
+ return { vendor: 'openrouter', model };
45
+ }
46
+
47
+ _sub(vendor) {
48
+ if (this._subs[vendor]) return this._subs[vendor];
49
+ const variant = VENDOR_VARIANT[vendor];
50
+ const { createLLMProvider } = require('./createLLMProvider');
51
+ try {
52
+ this._subs[vendor] = createLLMProvider({
53
+ variant,
54
+ conversationManager: this.conversationManager,
55
+ sessionManager: this.sessionManager,
56
+ });
57
+ } catch (err) {
58
+ throw new Error(`Gateway routed a model to '${vendor}' but its provider could not be created: ${err.message}`);
59
+ }
60
+ return this._subs[vendor];
61
+ }
62
+
63
+ async _invokeModel(request, options = {}) {
64
+ const { vendor, model } = this._route(request?.modelConfig?.model);
65
+ const modelConfig = { ...request.modelConfig, model };
66
+ return this._sub(vendor)._invokeModel({ ...request, modelConfig }, options);
67
+ }
68
+
69
+ async runStructured(params = {}) {
70
+ const { promptId = null, presetId = null, variables = null } = params;
71
+ let model = null;
72
+ if (promptId || presetId) {
73
+ const composed = await composePrompt({ promptId, presetId, variables });
74
+ model = composed.modelConfig?.model || null;
75
+ }
76
+ const { vendor, model: routedModel } = this._route(model);
77
+ if (vendor !== 'openai') {
78
+ throw new Error(`runStructured is only supported for OpenAI models; routed model '${model}' resolved to '${vendor}'`);
79
+ }
80
+ return this._sub('openai').runStructured({ ...params, model: routedModel });
81
+ }
82
+ }
83
+
84
+ module.exports = { GatewayProvider };
@@ -133,7 +133,7 @@ class OpenAIResponsesProvider extends BaseLLMProvider {
133
133
  return { response: finalResponse, toolCalls: allToolCalls, toolsExecuted: allToolsExecuted, retries: totalRetries, usage: accumulatedUsage };
134
134
  }
135
135
 
136
- async runStructured({ promptId = null, presetId = null, instructions = null, variables = null, input = [], text = null, metadata = null } = {}) {
136
+ async runStructured({ promptId = null, presetId = null, instructions = null, variables = null, input = [], text = null, metadata = null, model = null } = {}) {
137
137
  let modelConfig = null;
138
138
  let resolvedInstructions = instructions;
139
139
  if (promptId || presetId) {
@@ -146,6 +146,7 @@ class OpenAIResponsesProvider extends BaseLLMProvider {
146
146
  ...this._mapModelConfig(modelConfig || {}),
147
147
  instructions: resolvedInstructions || '',
148
148
  };
149
+ if (model) apiConfig.model = model;
149
150
  if (!apiConfig.model) apiConfig.model = this.defaults.responseModel;
150
151
  if (text) apiConfig.text = text;
151
152
  if (metadata) {
@@ -160,10 +161,6 @@ class OpenAIResponsesProvider extends BaseLLMProvider {
160
161
  return result;
161
162
  }
162
163
 
163
- _mapModelConfig(modelConfig) {
164
- return modelConfig;
165
- }
166
-
167
164
  async transcribeAudio({ file, model, language, responseFormat, temperature, prompt } = {}) {
168
165
  return this.client.audio.transcriptions.create({
169
166
  model: model || this.defaults.transcriptionModel,
@@ -6,11 +6,13 @@ const { logger } = require('../../utils/logger');
6
6
  const { OpenAIResponsesProvider } = require('./OpenAIResponsesProvider');
7
7
  const { OpenRouterProvider } = require('./OpenRouterProvider');
8
8
  const { AnthropicProvider } = require('./AnthropicProvider');
9
+ const { GatewayProvider } = require('./GatewayProvider');
9
10
 
10
11
  const PROVIDER_VARIANTS = {
11
12
  responses: OpenAIResponsesProvider,
12
13
  openrouter: OpenRouterProvider,
13
14
  anthropic: AnthropicProvider,
15
+ gateway: GatewayProvider,
14
16
  };
15
17
 
16
18
  const VARIANT_API_KEY = {
package/lib/index.d.ts CHANGED
@@ -278,7 +278,24 @@ declare module '@peopl-health/nexus' {
278
278
  transcribeAudio(options?: any): Promise<any>;
279
279
  }
280
280
 
281
- export function createLLMProvider(config?: { variant?: string; [key: string]: any }): OpenAIResponsesProvider;
281
+ export class GatewayProvider {
282
+ constructor(options?: { conversationManager?: any; sessionManager?: any; [key: string]: any });
283
+ getVariant(): string;
284
+ executeRun(options: { thread: any; assistant: any; message?: string; tools?: any[]; config?: any }): Promise<any>;
285
+ runConversation(config?: any): Promise<any>;
286
+ runStructured(params?: { promptId?: string; presetId?: string; variables?: any; input?: any[]; text?: any; metadata?: any }): Promise<any>;
287
+ }
288
+
289
+ export interface LLMProvider {
290
+ getVariant(): string;
291
+ getClient?(): any;
292
+ executeRun(options: { thread: any; assistant: any; message?: string; tools?: any[]; config?: any }): Promise<any>;
293
+ runConversation(config?: any): Promise<any>;
294
+ runStructured?(params?: { promptId?: string; presetId?: string; variables?: any; input?: any[]; text?: any; metadata?: any }): Promise<any>;
295
+ transcribeAudio?(options?: any): Promise<any>;
296
+ }
297
+
298
+ export function createLLMProvider(config?: { variant?: string; [key: string]: any }): LLMProvider;
282
299
 
283
300
  // Main Nexus Class
284
301
  export interface NexusConfig {
@@ -322,7 +339,7 @@ declare module '@peopl-health/nexus' {
322
339
  getMessaging(): NexusMessaging;
323
340
  getStorage(): MongoStorage | null;
324
341
  getMessageParser(): MessageParser | null;
325
- getLLMProvider(): OpenAIResponsesProvider | null;
342
+ getLLMProvider(): LLMProvider | null;
326
343
  }
327
344
 
328
345
  // Utility Functions
package/lib/index.js CHANGED
@@ -7,6 +7,7 @@ const {
7
7
  OpenAIResponsesProvider,
8
8
  OpenRouterProvider,
9
9
  AnthropicProvider,
10
+ GatewayProvider,
10
11
  configureOpenAIProvider,
11
12
  BaseAssistant,
12
13
  registerAssistant,
@@ -201,6 +202,7 @@ module.exports = {
201
202
  OpenAIResponsesProvider,
202
203
  OpenRouterProvider,
203
204
  AnthropicProvider,
205
+ GatewayProvider,
204
206
  BaseAssistant,
205
207
  registerAssistant,
206
208
  overrideGetAssistantById,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peopl-health/nexus",
3
- "version": "4.7.0-dev.451",
3
+ "version": "4.7.0-dev.455",
4
4
  "description": "Core messaging and assistant library for WhatsApp communication platforms",
5
5
  "keywords": [
6
6
  "whatsapp",