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.
- package/flutter_app/lib/main.dart +1 -0
- package/flutter_app/lib/main_model_picker.dart +631 -0
- package/flutter_app/lib/main_settings.dart +30 -86
- package/package.json +1 -1
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +58682 -58379
- package/server/services/ai/models.js +53 -0
- package/server/services/ai/providers/nvidia.js +165 -0
- package/server/services/ai/settings.js +10 -0
- package/server/services/integrations/google/provider.js +13 -0
- package/server/services/integrations/manager.js +5 -0
- package/server/services/integrations/trello/provider.js +8 -2
|
@@ -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
|
-
|
|
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);
|