neoagent 2.4.1-beta.12 → 2.4.1-beta.13

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.
@@ -7,6 +7,7 @@ const { GithubCopilotProvider } = require('./providers/githubCopilot');
7
7
  const { OpenAICodexProvider } = require('./providers/openaiCodex');
8
8
  const { ClaudeCodeProvider } = require('./providers/claudeCode');
9
9
  const { GrokOAuthProvider } = require('./providers/grokOauth');
10
+ const { NvidiaProvider } = require('./providers/nvidia');
10
11
  const {
11
12
  AI_PROVIDER_DEFINITIONS,
12
13
  getProviderConfigs,
@@ -62,6 +63,56 @@ const STATIC_MODELS = [
62
63
  provider: 'openai-codex',
63
64
  purpose: 'general'
64
65
  },
66
+ // — NVIDIA NIM — free tier ————————————————————————————————————————————
67
+ {
68
+ id: 'nvidia/nemotron-3-super-120b-a12b',
69
+ label: 'Nemotron Super 120B (NVIDIA / Free)',
70
+ provider: 'nvidia',
71
+ purpose: 'general'
72
+ },
73
+ {
74
+ id: 'moonshotai/kimi-k2.5',
75
+ label: 'Kimi K2.5 (NVIDIA NIM / Free)',
76
+ provider: 'nvidia',
77
+ purpose: 'coding'
78
+ },
79
+ {
80
+ id: 'minimaxai/minimax-m2.5',
81
+ label: 'MiniMax M2.5 (NVIDIA NIM / Free)',
82
+ provider: 'nvidia',
83
+ purpose: 'planning'
84
+ },
85
+ {
86
+ id: 'z-ai/glm5',
87
+ label: 'GLM 5 (NVIDIA NIM / Free)',
88
+ provider: 'nvidia',
89
+ purpose: 'fast'
90
+ },
91
+ // — NVIDIA NIM — notable models ————————————————————————————————————————
92
+ {
93
+ id: 'meta/llama-4-maverick-17b-128e-instruct',
94
+ label: 'Llama 4 Maverick 17B (NVIDIA NIM)',
95
+ provider: 'nvidia',
96
+ purpose: 'general'
97
+ },
98
+ {
99
+ id: 'meta/llama-4-scout-17b-16e-instruct',
100
+ label: 'Llama 4 Scout 17B (NVIDIA NIM)',
101
+ provider: 'nvidia',
102
+ purpose: 'planning'
103
+ },
104
+ {
105
+ id: 'deepseek-ai/deepseek-r1-0528',
106
+ label: 'DeepSeek R1 0528 (NVIDIA NIM)',
107
+ provider: 'nvidia',
108
+ purpose: 'general'
109
+ },
110
+ {
111
+ id: 'qwen/qwq-32b',
112
+ label: 'QwQ 32B (NVIDIA NIM)',
113
+ provider: 'nvidia',
114
+ purpose: 'planning'
115
+ },
65
116
  {
66
117
  id: 'gpt-5-nano',
67
118
  label: 'GPT-5 Nano (Fast / Subagents)',
@@ -374,6 +425,8 @@ function createProviderInstance(providerStr, userId = null, configOverrides = {}
374
425
  return new ClaudeCodeProvider({ apiKey: runtime.apiKey, ...providerOverrides });
375
426
  } else if (providerStr === 'grok-oauth') {
376
427
  return new GrokOAuthProvider({ apiKey: runtime.apiKey, ...providerOverrides });
428
+ } else if (providerStr === 'nvidia') {
429
+ return new NvidiaProvider({ apiKey: runtime.apiKey, baseUrl: runtime.baseUrl, ...providerOverrides });
377
430
  }
378
431
  throw new Error(`Unknown provider: ${providerStr}`);
379
432
  }
@@ -0,0 +1,165 @@
1
+ const OpenAI = require('openai');
2
+ const { BaseProvider } = require('./base');
3
+
4
+ const NVIDIA_BASE_URL = 'https://integrate.api.nvidia.com/v1';
5
+
6
+ // Context windows per model (tokens)
7
+ const CONTEXT_WINDOWS = {
8
+ 'nvidia/nemotron-3-super-120b-a12b': 262144,
9
+ 'moonshotai/kimi-k2.5': 262144,
10
+ 'minimaxai/minimax-m2.5': 196608,
11
+ 'z-ai/glm5': 202752,
12
+ 'meta/llama-4-maverick-17b-128e-instruct': 1048576,
13
+ 'meta/llama-4-scout-17b-16e-instruct': 1048576,
14
+ 'deepseek-ai/deepseek-r1-0528': 163840,
15
+ 'qwen/qwq-32b': 131072,
16
+ };
17
+
18
+ // Reasoning models: no temperature, no top_p
19
+ const REASONING_MODELS = new Set([
20
+ 'deepseek-ai/deepseek-r1-0528',
21
+ 'qwen/qwq-32b',
22
+ ]);
23
+
24
+ class NvidiaProvider extends BaseProvider {
25
+ constructor(config = {}) {
26
+ super(config);
27
+ this.name = 'nvidia';
28
+ this.models = Object.keys(CONTEXT_WINDOWS);
29
+ this.client = new OpenAI({
30
+ apiKey: config.apiKey || process.env.NVIDIA_API_KEY,
31
+ baseURL: config.baseUrl || NVIDIA_BASE_URL,
32
+ });
33
+ }
34
+
35
+ getContextWindow(model) {
36
+ return CONTEXT_WINDOWS[model] ?? 131072;
37
+ }
38
+
39
+ _isReasoningModel(model) {
40
+ return REASONING_MODELS.has(model);
41
+ }
42
+
43
+ _buildParams(model, messages, tools, options) {
44
+ const params = {
45
+ model,
46
+ messages,
47
+ max_tokens: options.maxTokens || 8192,
48
+ };
49
+
50
+ if (!this._isReasoningModel(model)) {
51
+ params.temperature = options.temperature ?? 0.6;
52
+ }
53
+
54
+ if (tools && tools.length > 0) {
55
+ params.tools = this.formatTools(tools);
56
+ params.tool_choice = 'auto';
57
+ }
58
+
59
+ return params;
60
+ }
61
+
62
+ async chat(messages, tools = [], options = {}) {
63
+ const model = options.model || this.getDefaultModel();
64
+ const params = this._buildParams(model, messages, tools, options);
65
+ let response;
66
+ try {
67
+ response = await this.client.chat.completions.create(params);
68
+ } catch (err) {
69
+ throw new Error(`NVIDIA NIM request failed: ${err?.message || String(err)}`);
70
+ }
71
+ return this._normalizeResponse(response);
72
+ }
73
+
74
+ async *stream(messages, tools = [], options = {}) {
75
+ const model = options.model || this.getDefaultModel();
76
+ const params = {
77
+ ...this._buildParams(model, messages, tools, options),
78
+ stream: true,
79
+ stream_options: { include_usage: true },
80
+ };
81
+
82
+ let stream;
83
+ try {
84
+ stream = await this.client.chat.completions.create(params);
85
+ } catch (err) {
86
+ throw new Error(`NVIDIA NIM request failed: ${err?.message || String(err)}`);
87
+ }
88
+
89
+ let toolCalls = [];
90
+ let content = '';
91
+ let finalUsage = null;
92
+
93
+ for await (const chunk of stream) {
94
+ if (chunk.usage && (!chunk.choices || chunk.choices.length === 0)) {
95
+ finalUsage = this._normalizeUsage(chunk.usage);
96
+ continue;
97
+ }
98
+
99
+ const delta = chunk.choices?.[0]?.delta;
100
+ if (!delta) continue;
101
+
102
+ if (delta.content) {
103
+ content += delta.content;
104
+ yield { type: 'content', content: delta.content };
105
+ }
106
+
107
+ if (delta.tool_calls) {
108
+ for (const tc of delta.tool_calls) {
109
+ if (!toolCalls[tc.index]) {
110
+ toolCalls[tc.index] = {
111
+ id: tc.id || '',
112
+ type: 'function',
113
+ function: { name: tc.function?.name || '', arguments: '' },
114
+ };
115
+ }
116
+ if (tc.id) toolCalls[tc.index].id = tc.id;
117
+ if (tc.function?.name) toolCalls[tc.index].function.name = tc.function.name;
118
+ if (tc.function?.arguments) toolCalls[tc.index].function.arguments += tc.function.arguments;
119
+ }
120
+ }
121
+
122
+ const finishReason = chunk.choices[0]?.finish_reason;
123
+ if (finishReason === 'tool_calls' || (finishReason === 'stop' && toolCalls.length > 0)) {
124
+ yield { type: 'tool_calls', toolCalls, content, usage: this._normalizeUsage(chunk.usage) || finalUsage };
125
+ return;
126
+ }
127
+ if (finishReason === 'stop') {
128
+ yield { type: 'done', content, usage: this._normalizeUsage(chunk.usage) || finalUsage };
129
+ return;
130
+ }
131
+ }
132
+
133
+ if (toolCalls.length > 0) {
134
+ yield { type: 'tool_calls', toolCalls, content, usage: finalUsage };
135
+ } else {
136
+ yield { type: 'done', content, usage: finalUsage };
137
+ }
138
+ }
139
+
140
+ _normalizeResponse(response) {
141
+ const choice = response.choices[0];
142
+ const msg = choice.message;
143
+ return {
144
+ content: msg.content || '',
145
+ toolCalls: msg.tool_calls?.map((tc) => ({
146
+ id: tc.id,
147
+ type: 'function',
148
+ function: { name: tc.function.name, arguments: tc.function.arguments },
149
+ })) || [],
150
+ finishReason: choice.finish_reason,
151
+ usage: this._normalizeUsage(response.usage),
152
+ };
153
+ }
154
+
155
+ _normalizeUsage(usage) {
156
+ if (!usage) return null;
157
+ return {
158
+ promptTokens: usage.prompt_tokens ?? 0,
159
+ completionTokens: usage.completion_tokens ?? 0,
160
+ totalTokens: usage.total_tokens ?? 0,
161
+ };
162
+ }
163
+ }
164
+
165
+ module.exports = { NvidiaProvider };
@@ -59,6 +59,16 @@ const AI_PROVIDER_DEFINITIONS = Object.freeze({
59
59
  defaultEnabled: false,
60
60
  defaultBaseUrl: ''
61
61
  },
62
+ nvidia: {
63
+ id: 'nvidia',
64
+ label: 'NVIDIA NIM',
65
+ description: 'NVIDIA-hosted models including free-tier Nemotron, Kimi, Llama 4, and DeepSeek. Get a key at build.nvidia.com.',
66
+ envKey: 'NVIDIA_API_KEY',
67
+ supportsApiKey: true,
68
+ supportsBaseUrl: true,
69
+ defaultEnabled: false,
70
+ defaultBaseUrl: 'https://integrate.api.nvidia.com/v1'
71
+ },
62
72
  minimax: {
63
73
  id: 'minimax',
64
74
  label: 'MiniMax Code',
@@ -129,6 +129,19 @@ async function buildAuthorizedClient(connection) {
129
129
  credentials = {};
130
130
  }
131
131
  client.setCredentials(credentials);
132
+ // Capture any token refresh that happens during the request so the new
133
+ // access_token + expiry_date are always available on client.credentials.
134
+ // The library preserves refresh_token internally; this listener just ensures
135
+ // client.credentials stays in sync when refreshes happen inside deep call stacks.
136
+ client.on('tokens', (tokens) => {
137
+ if (tokens.access_token) {
138
+ client.setCredentials({
139
+ ...client.credentials,
140
+ ...tokens,
141
+ refresh_token: tokens.refresh_token || client.credentials.refresh_token,
142
+ });
143
+ }
144
+ });
132
145
  return client;
133
146
  }
134
147
 
@@ -679,6 +679,11 @@ class IntegrationManager {
679
679
  userId,
680
680
  resolveAgentId(userId, agentId),
681
681
  );
682
+ return {
683
+ error: `Your ${provider.label} account connection has expired and needs to be reconnected. Open Official Integrations to reconnect your account.`,
684
+ expired: true,
685
+ connectionId: selection.connection.id,
686
+ };
682
687
  }
683
688
  return { error: err?.message || 'execution_error' };
684
689
  }
@@ -9,7 +9,7 @@ const {
9
9
  } = require('../provider_config_store');
10
10
  const { getConnectionAccessMode } = require('../access');
11
11
  const { fetchJson } = require('../oauth_provider');
12
- const { encryptValue } = require('../secrets');
12
+ const { encryptValue, decryptValue } = require('../secrets');
13
13
 
14
14
  const TRELLO_APP = {
15
15
  id: 'trello',
@@ -732,7 +732,13 @@ function createTrelloProvider() {
732
732
  return 'Trello: native Trello access is connected in this run with one Trello account for board, list, card, comment, and search tools.';
733
733
  },
734
734
  async executeTool(toolName, args, connection) {
735
- return executeTrelloTool(toolName, args, connection);
735
+ let credentials = {};
736
+ try {
737
+ credentials = JSON.parse(decryptValue(connection.credentials_json || '{}') || '{}');
738
+ } catch {
739
+ credentials = {};
740
+ }
741
+ return executeTrelloTool(toolName, args, { connection, credentials });
736
742
  },
737
743
  getUserConfig({ userId, agentId }) {
738
744
  const normalizedUserId = Number(userId);