jiva-core 0.3.41 → 0.3.42-dev.b6b238d
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/README.md +28 -7
- package/dist/code/agent.d.ts +4 -0
- package/dist/code/agent.d.ts.map +1 -1
- package/dist/code/agent.js +70 -18
- package/dist/code/agent.js.map +1 -1
- package/dist/core/agent-interface.d.ts +8 -0
- package/dist/core/agent-interface.d.ts.map +1 -1
- package/dist/core/agent-spawner.d.ts.map +1 -1
- package/dist/core/agent-spawner.js +2 -1
- package/dist/core/agent-spawner.js.map +1 -1
- package/dist/core/config.d.ts +56 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +4 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/conversation-manager.d.ts +4 -3
- package/dist/core/conversation-manager.d.ts.map +1 -1
- package/dist/core/conversation-manager.js +16 -8
- package/dist/core/conversation-manager.js.map +1 -1
- package/dist/core/dual-agent.d.ts +3 -0
- package/dist/core/dual-agent.d.ts.map +1 -1
- package/dist/core/dual-agent.js +15 -4
- package/dist/core/dual-agent.js.map +1 -1
- package/dist/core/worker-agent.d.ts.map +1 -1
- package/dist/core/worker-agent.js +32 -0
- package/dist/core/worker-agent.js.map +1 -1
- package/dist/core/workspace.d.ts +6 -0
- package/dist/core/workspace.d.ts.map +1 -1
- package/dist/core/workspace.js +18 -0
- package/dist/core/workspace.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/cli/index.js +7 -7
- package/dist/interfaces/cli/index.js.map +1 -1
- package/dist/interfaces/cli/repl.d.ts.map +1 -1
- package/dist/interfaces/cli/repl.js +21 -3
- package/dist/interfaces/cli/repl.js.map +1 -1
- package/dist/interfaces/cli/setup-wizard.d.ts +5 -3
- package/dist/interfaces/cli/setup-wizard.d.ts.map +1 -1
- package/dist/interfaces/cli/setup-wizard.js +265 -288
- package/dist/interfaces/cli/setup-wizard.js.map +1 -1
- package/dist/interfaces/http/middleware/auth.d.ts.map +1 -1
- package/dist/interfaces/http/middleware/auth.js +2 -1
- package/dist/interfaces/http/middleware/auth.js.map +1 -1
- package/dist/interfaces/http/routes/chat.d.ts.map +1 -1
- package/dist/interfaces/http/routes/chat.js +20 -0
- package/dist/interfaces/http/routes/chat.js.map +1 -1
- package/dist/interfaces/http/session-manager.d.ts +6 -0
- package/dist/interfaces/http/session-manager.d.ts.map +1 -1
- package/dist/interfaces/http/session-manager.js +14 -5
- package/dist/interfaces/http/session-manager.js.map +1 -1
- package/dist/interfaces/http/websocket-handler.d.ts.map +1 -1
- package/dist/interfaces/http/websocket-handler.js +12 -0
- package/dist/interfaces/http/websocket-handler.js.map +1 -1
- package/dist/models/krutrim.d.ts +8 -66
- package/dist/models/krutrim.d.ts.map +1 -1
- package/dist/models/krutrim.js +7 -307
- package/dist/models/krutrim.js.map +1 -1
- package/dist/models/model-client.d.ts +95 -0
- package/dist/models/model-client.d.ts.map +1 -0
- package/dist/models/model-client.js +317 -0
- package/dist/models/model-client.js.map +1 -0
- package/dist/models/orchestrator.d.ts +9 -8
- package/dist/models/orchestrator.d.ts.map +1 -1
- package/dist/models/orchestrator.js +2 -1
- package/dist/models/orchestrator.js.map +1 -1
- package/dist/storage/types.d.ts +1 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,22 +1,87 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Setup Wizard for first-time configuration
|
|
3
|
+
*
|
|
4
|
+
* Provider-aware: Krutrim, Groq, Sarvam, OpenAI-Compatible
|
|
5
|
+
* - Auto-fills endpoints and model defaults per provider
|
|
6
|
+
* - Asks API key only once per provider (reuses across model roles)
|
|
7
|
+
* - Sets useHarmonyFormat, reasoningEffortStrategy, defaultMaxTokens automatically
|
|
3
8
|
*/
|
|
4
9
|
import inquirer from 'inquirer';
|
|
5
10
|
import { configManager } from '../../core/config.js';
|
|
6
11
|
import { logger } from '../../utils/logger.js';
|
|
7
12
|
import chalk from 'chalk';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const PROVIDERS = {
|
|
14
|
+
krutrim: {
|
|
15
|
+
label: 'Krutrim',
|
|
16
|
+
endpoint: 'https://cloud.olakrutrim.com/v1/chat/completions',
|
|
17
|
+
reasoningModel: 'gpt-oss-120b',
|
|
18
|
+
multimodalModel: 'Llama-4-Maverick-17B-128E-Instruct',
|
|
19
|
+
toolCallingModel: 'gpt-oss-120b',
|
|
20
|
+
useHarmonyFormat: true,
|
|
21
|
+
reasoningEffortStrategy: 'system_prompt',
|
|
22
|
+
hasMultimodal: true,
|
|
23
|
+
},
|
|
24
|
+
groq: {
|
|
25
|
+
label: 'Groq',
|
|
26
|
+
endpoint: 'https://api.groq.com/openai/v1/chat/completions',
|
|
27
|
+
reasoningModel: 'openai/gpt-oss-120b',
|
|
28
|
+
multimodalModel: 'meta-llama/llama-4-maverick-17b-128e-instruct',
|
|
29
|
+
toolCallingModel: 'meta-llama/llama-4-maverick-17b-128e-instruct',
|
|
30
|
+
useHarmonyFormat: false,
|
|
31
|
+
reasoningEffortStrategy: 'api_param',
|
|
32
|
+
hasMultimodal: true,
|
|
33
|
+
},
|
|
34
|
+
sarvam: {
|
|
35
|
+
label: 'Sarvam',
|
|
36
|
+
endpoint: 'https://api.sarvam.ai/v1/chat/completions',
|
|
37
|
+
reasoningModel: 'sarvam-105b',
|
|
38
|
+
multimodalModel: null, // Sarvam has no multimodal model
|
|
39
|
+
toolCallingModel: 'sarvam-105b',
|
|
40
|
+
useHarmonyFormat: false,
|
|
41
|
+
reasoningEffortStrategy: 'api_param',
|
|
42
|
+
defaultMaxTokens: 8192,
|
|
43
|
+
hasMultimodal: false,
|
|
44
|
+
note: 'Sarvam does not offer a multimodal model. You will need to pick a separate provider for multimodal.',
|
|
45
|
+
},
|
|
46
|
+
'openai-compatible': {
|
|
47
|
+
label: 'OpenAI-Compatible',
|
|
48
|
+
endpoint: '',
|
|
49
|
+
reasoningModel: '',
|
|
50
|
+
multimodalModel: '',
|
|
51
|
+
toolCallingModel: '',
|
|
52
|
+
useHarmonyFormat: false,
|
|
53
|
+
reasoningEffortStrategy: 'both',
|
|
54
|
+
hasMultimodal: true,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
const PROVIDER_CHOICES = Object.entries(PROVIDERS).map(([value, p]) => ({
|
|
58
|
+
name: p.label,
|
|
59
|
+
value: value,
|
|
60
|
+
}));
|
|
61
|
+
const MULTIMODAL_PROVIDER_CHOICES = PROVIDER_CHOICES.filter(c => c.value !== 'sarvam');
|
|
62
|
+
// ── Helpers ────────────────────────────────────────────────────────────────
|
|
63
|
+
async function askApiKey(provider, collectedKeys) {
|
|
64
|
+
if (collectedKeys.has(provider)) {
|
|
65
|
+
console.log(chalk.gray(` Using ${PROVIDERS[provider].label} API key already entered.\n`));
|
|
66
|
+
return collectedKeys.get(provider);
|
|
67
|
+
}
|
|
68
|
+
const { apiKey } = await inquirer.prompt([
|
|
69
|
+
{
|
|
70
|
+
type: 'password',
|
|
71
|
+
name: 'apiKey',
|
|
72
|
+
message: `${PROVIDERS[provider].label} API Key:`,
|
|
73
|
+
validate: (input) => input.length > 0 || 'API key is required',
|
|
74
|
+
},
|
|
75
|
+
]);
|
|
76
|
+
collectedKeys.set(provider, apiKey);
|
|
77
|
+
return apiKey;
|
|
78
|
+
}
|
|
79
|
+
async function askEndpointAndKey(collectedKeys) {
|
|
80
|
+
const answers = await inquirer.prompt([
|
|
15
81
|
{
|
|
16
82
|
type: 'input',
|
|
17
83
|
name: 'endpoint',
|
|
18
84
|
message: 'API Endpoint URL:',
|
|
19
|
-
default: 'https://cloud.olakrutrim.com/v1/chat/completions',
|
|
20
85
|
validate: (input) => {
|
|
21
86
|
try {
|
|
22
87
|
new URL(input);
|
|
@@ -33,151 +98,194 @@ export async function runSetupWizard() {
|
|
|
33
98
|
message: 'API Key:',
|
|
34
99
|
validate: (input) => input.length > 0 || 'API key is required',
|
|
35
100
|
},
|
|
101
|
+
]);
|
|
102
|
+
collectedKeys.set('openai-compatible', answers.apiKey);
|
|
103
|
+
return answers;
|
|
104
|
+
}
|
|
105
|
+
// ── Reasoning model setup ──────────────────────────────────────────────────
|
|
106
|
+
async function setupReasoningModel(collectedKeys) {
|
|
107
|
+
console.log(chalk.bold('\n● Reasoning Model'));
|
|
108
|
+
console.log(chalk.gray('Used for planning and tool calling.\n'));
|
|
109
|
+
const { provider } = await inquirer.prompt([
|
|
36
110
|
{
|
|
37
|
-
type: '
|
|
38
|
-
name: '
|
|
39
|
-
message: '
|
|
40
|
-
|
|
111
|
+
type: 'list',
|
|
112
|
+
name: 'provider',
|
|
113
|
+
message: 'Select provider:',
|
|
114
|
+
choices: PROVIDER_CHOICES,
|
|
41
115
|
},
|
|
42
116
|
]);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
117
|
+
const preset = PROVIDERS[provider];
|
|
118
|
+
if (preset.note) {
|
|
119
|
+
console.log(chalk.yellow(`\n ⚠ ${preset.note}\n`));
|
|
120
|
+
}
|
|
121
|
+
let endpoint = preset.endpoint;
|
|
122
|
+
let apiKey;
|
|
123
|
+
if (provider === 'openai-compatible') {
|
|
124
|
+
const custom = await askEndpointAndKey(collectedKeys);
|
|
125
|
+
endpoint = custom.endpoint;
|
|
126
|
+
apiKey = custom.apiKey;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
console.log(chalk.gray(` Endpoint: ${endpoint}\n`));
|
|
130
|
+
apiKey = await askApiKey(provider, collectedKeys);
|
|
131
|
+
}
|
|
132
|
+
const { model } = await inquirer.prompt([
|
|
49
133
|
{
|
|
50
|
-
type: '
|
|
51
|
-
name: '
|
|
52
|
-
message: '
|
|
53
|
-
default:
|
|
54
|
-
when: () => {
|
|
55
|
-
// Show this prompt for all models, but provide smart default
|
|
56
|
-
console.log(chalk.gray(` Recommended: ${defaultUseHarmony ? 'Yes' : 'No'} (${isKrutrimModel ? 'Krutrim uses Harmony format' : 'Standard OpenAI format'})`));
|
|
57
|
-
return true;
|
|
58
|
-
},
|
|
134
|
+
type: 'input',
|
|
135
|
+
name: 'model',
|
|
136
|
+
message: 'Model name:',
|
|
137
|
+
default: preset.reasoningModel || undefined,
|
|
59
138
|
},
|
|
60
139
|
]);
|
|
61
|
-
|
|
140
|
+
const config = {
|
|
62
141
|
name: 'reasoning',
|
|
63
|
-
endpoint
|
|
64
|
-
apiKey
|
|
142
|
+
endpoint,
|
|
143
|
+
apiKey,
|
|
65
144
|
type: 'reasoning',
|
|
66
|
-
defaultModel:
|
|
67
|
-
useHarmonyFormat,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
145
|
+
defaultModel: model,
|
|
146
|
+
useHarmonyFormat: preset.useHarmonyFormat,
|
|
147
|
+
reasoningEffortStrategy: preset.reasoningEffortStrategy,
|
|
148
|
+
...(preset.defaultMaxTokens ? { defaultMaxTokens: preset.defaultMaxTokens } : {}),
|
|
149
|
+
};
|
|
150
|
+
return { config, provider: provider };
|
|
151
|
+
}
|
|
152
|
+
// ── Multimodal model setup ─────────────────────────────────────────────────
|
|
153
|
+
async function setupMultimodalModel(reasoningProvider, collectedKeys) {
|
|
154
|
+
console.log(chalk.bold('\n● Multimodal Model') + chalk.gray(' (optional)'));
|
|
155
|
+
console.log(chalk.gray('Used for understanding images.\n'));
|
|
156
|
+
if (reasoningProvider === 'sarvam') {
|
|
157
|
+
console.log(chalk.yellow(' ⚠ Sarvam does not have a multimodal model.'));
|
|
158
|
+
console.log(chalk.gray(' Please select a different provider below.\n'));
|
|
159
|
+
}
|
|
160
|
+
const { configure } = await inquirer.prompt([
|
|
74
161
|
{
|
|
75
162
|
type: 'confirm',
|
|
76
|
-
name: '
|
|
77
|
-
message: '
|
|
163
|
+
name: 'configure',
|
|
164
|
+
message: 'Configure a multimodal model?',
|
|
78
165
|
default: true,
|
|
79
166
|
},
|
|
80
167
|
]);
|
|
81
|
-
if (
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
type: 'password',
|
|
100
|
-
name: 'apiKey',
|
|
101
|
-
message: 'Multimodal API Key:',
|
|
102
|
-
default: reasoningAnswers.apiKey,
|
|
103
|
-
validate: (input) => input.length > 0 || 'API key is required',
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
type: 'input',
|
|
107
|
-
name: 'model',
|
|
108
|
-
message: 'Multimodal model name:',
|
|
109
|
-
default: 'Llama-4-Maverick-17B-128E-Instruct',
|
|
110
|
-
},
|
|
111
|
-
]);
|
|
112
|
-
configManager.setMultimodalModel({
|
|
113
|
-
name: 'multimodal',
|
|
114
|
-
endpoint: multimodalAnswers.endpoint,
|
|
115
|
-
apiKey: multimodalAnswers.apiKey,
|
|
116
|
-
type: 'multimodal',
|
|
117
|
-
defaultModel: multimodalAnswers.model,
|
|
118
|
-
});
|
|
119
|
-
logger.success('Multimodal model configured');
|
|
168
|
+
if (!configure)
|
|
169
|
+
return null;
|
|
170
|
+
const { provider } = await inquirer.prompt([
|
|
171
|
+
{
|
|
172
|
+
type: 'list',
|
|
173
|
+
name: 'provider',
|
|
174
|
+
message: 'Select provider:',
|
|
175
|
+
choices: MULTIMODAL_PROVIDER_CHOICES,
|
|
176
|
+
default: reasoningProvider !== 'sarvam' ? reasoningProvider : 'groq',
|
|
177
|
+
},
|
|
178
|
+
]);
|
|
179
|
+
const preset = PROVIDERS[provider];
|
|
180
|
+
let endpoint = preset.endpoint;
|
|
181
|
+
let apiKey;
|
|
182
|
+
if (provider === 'openai-compatible') {
|
|
183
|
+
const custom = await askEndpointAndKey(collectedKeys);
|
|
184
|
+
endpoint = custom.endpoint;
|
|
185
|
+
apiKey = custom.apiKey;
|
|
120
186
|
}
|
|
121
|
-
|
|
122
|
-
|
|
187
|
+
else {
|
|
188
|
+
console.log(chalk.gray(` Endpoint: ${endpoint}\n`));
|
|
189
|
+
apiKey = await askApiKey(provider, collectedKeys);
|
|
190
|
+
}
|
|
191
|
+
const { model } = await inquirer.prompt([
|
|
192
|
+
{
|
|
193
|
+
type: 'input',
|
|
194
|
+
name: 'model',
|
|
195
|
+
message: 'Multimodal model name:',
|
|
196
|
+
default: preset.multimodalModel || undefined,
|
|
197
|
+
},
|
|
198
|
+
]);
|
|
199
|
+
return {
|
|
200
|
+
name: 'multimodal',
|
|
201
|
+
endpoint,
|
|
202
|
+
apiKey,
|
|
203
|
+
type: 'multimodal',
|
|
204
|
+
defaultModel: model,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
// ── Tool-calling model setup ───────────────────────────────────────────────
|
|
208
|
+
async function setupToolCallingModel(reasoningProvider, collectedKeys) {
|
|
209
|
+
console.log(chalk.bold('\n● Tool-Calling Model') + chalk.gray(' (optional)'));
|
|
123
210
|
console.log(chalk.gray('A dedicated model that reliably formats tool calls as standard JSON.'));
|
|
124
|
-
console.log(chalk.gray('When configured it is
|
|
125
|
-
|
|
126
|
-
const { configureToolCalling } = await inquirer.prompt([
|
|
211
|
+
console.log(chalk.gray('When configured it is the PRIMARY model for tool execution;\nthe reasoning model is the fallback.\n'));
|
|
212
|
+
const { configure } = await inquirer.prompt([
|
|
127
213
|
{
|
|
128
214
|
type: 'confirm',
|
|
129
|
-
name: '
|
|
130
|
-
message: '
|
|
215
|
+
name: 'configure',
|
|
216
|
+
message: 'Configure a dedicated tool-calling model?',
|
|
131
217
|
default: false,
|
|
132
218
|
},
|
|
133
219
|
]);
|
|
134
|
-
if (
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
220
|
+
if (!configure)
|
|
221
|
+
return null;
|
|
222
|
+
const { provider } = await inquirer.prompt([
|
|
223
|
+
{
|
|
224
|
+
type: 'list',
|
|
225
|
+
name: 'provider',
|
|
226
|
+
message: 'Select provider:',
|
|
227
|
+
choices: PROVIDER_CHOICES,
|
|
228
|
+
default: reasoningProvider,
|
|
229
|
+
},
|
|
230
|
+
]);
|
|
231
|
+
const preset = PROVIDERS[provider];
|
|
232
|
+
let endpoint = preset.endpoint;
|
|
233
|
+
let apiKey;
|
|
234
|
+
if (provider === 'openai-compatible') {
|
|
235
|
+
const custom = await askEndpointAndKey(collectedKeys);
|
|
236
|
+
endpoint = custom.endpoint;
|
|
237
|
+
apiKey = custom.apiKey;
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
console.log(chalk.gray(` Endpoint: ${endpoint}\n`));
|
|
241
|
+
apiKey = await askApiKey(provider, collectedKeys);
|
|
242
|
+
}
|
|
243
|
+
const { model } = await inquirer.prompt([
|
|
244
|
+
{
|
|
245
|
+
type: 'input',
|
|
246
|
+
name: 'model',
|
|
247
|
+
message: 'Tool-calling model name:',
|
|
248
|
+
default: preset.toolCallingModel || undefined,
|
|
249
|
+
},
|
|
250
|
+
]);
|
|
251
|
+
return {
|
|
252
|
+
name: 'tool-calling',
|
|
253
|
+
endpoint,
|
|
254
|
+
apiKey,
|
|
255
|
+
type: 'tool-calling',
|
|
256
|
+
defaultModel: model,
|
|
257
|
+
useHarmonyFormat: false, // always standard format for tool-calling models
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
// ── Main wizard ────────────────────────────────────────────────────────────
|
|
261
|
+
export async function runSetupWizard() {
|
|
262
|
+
console.log(chalk.bold.cyan('\n∞ Welcome to Jiva Setup Wizard\n'));
|
|
263
|
+
console.log('This wizard will configure your AI providers.\n');
|
|
264
|
+
console.log(chalk.gray('API keys for the same provider are only asked once.\n'));
|
|
265
|
+
// Track API keys keyed by provider so we never ask twice
|
|
266
|
+
const collectedKeys = new Map();
|
|
267
|
+
// 1. Reasoning model
|
|
268
|
+
const { config: reasoningConfig, provider: reasoningProvider } = await setupReasoningModel(collectedKeys);
|
|
269
|
+
configManager.setReasoningModel(reasoningConfig);
|
|
270
|
+
logger.success('Reasoning model configured');
|
|
271
|
+
// 2. Multimodal model (optional)
|
|
272
|
+
const multimodalConfig = await setupMultimodalModel(reasoningProvider, collectedKeys);
|
|
273
|
+
if (multimodalConfig) {
|
|
274
|
+
configManager.setMultimodalModel(multimodalConfig);
|
|
275
|
+
logger.success('Multimodal model configured');
|
|
276
|
+
}
|
|
277
|
+
// 3. Tool-calling model (optional)
|
|
278
|
+
const toolCallingConfig = await setupToolCallingModel(reasoningProvider, collectedKeys);
|
|
279
|
+
if (toolCallingConfig) {
|
|
280
|
+
configManager.setToolCallingModel(toolCallingConfig);
|
|
173
281
|
logger.success('Tool-calling model configured');
|
|
174
282
|
}
|
|
175
|
-
// MCP Servers
|
|
176
|
-
console.log(chalk.bold('\
|
|
283
|
+
// 4. MCP Servers
|
|
284
|
+
console.log(chalk.bold('\n● MCP Servers'));
|
|
177
285
|
console.log(chalk.gray('Setting up default MCP servers (filesystem, mcp-shell-server)...\n'));
|
|
178
286
|
configManager.initializeDefaultServers();
|
|
179
287
|
logger.success('Default MCP servers configured');
|
|
180
|
-
// Debug
|
|
288
|
+
// 5. Debug mode
|
|
181
289
|
const { enableDebug } = await inquirer.prompt([
|
|
182
290
|
{
|
|
183
291
|
type: 'confirm',
|
|
@@ -192,9 +300,7 @@ export async function runSetupWizard() {
|
|
|
192
300
|
console.log('\nYou can now run:', chalk.cyan('jiva'));
|
|
193
301
|
console.log('');
|
|
194
302
|
}
|
|
195
|
-
|
|
196
|
-
* Update existing configuration interactively
|
|
197
|
-
*/
|
|
303
|
+
// ── Update existing configuration ─────────────────────────────────────────
|
|
198
304
|
export async function updateConfiguration() {
|
|
199
305
|
console.log(chalk.bold.cyan('\n🔧 Update Jiva Configuration\n'));
|
|
200
306
|
const { choice } = await inquirer.prompt([
|
|
@@ -214,16 +320,30 @@ export async function updateConfiguration() {
|
|
|
214
320
|
],
|
|
215
321
|
},
|
|
216
322
|
]);
|
|
323
|
+
const collectedKeys = new Map();
|
|
217
324
|
switch (choice) {
|
|
218
|
-
case 'reasoning':
|
|
219
|
-
await
|
|
325
|
+
case 'reasoning': {
|
|
326
|
+
const { config } = await setupReasoningModel(collectedKeys);
|
|
327
|
+
configManager.setReasoningModel(config);
|
|
328
|
+
logger.success('Reasoning model updated');
|
|
220
329
|
break;
|
|
221
|
-
|
|
222
|
-
|
|
330
|
+
}
|
|
331
|
+
case 'multimodal': {
|
|
332
|
+
const config = await setupMultimodalModel('groq', collectedKeys);
|
|
333
|
+
if (config) {
|
|
334
|
+
configManager.setMultimodalModel(config);
|
|
335
|
+
logger.success('Multimodal model updated');
|
|
336
|
+
}
|
|
223
337
|
break;
|
|
224
|
-
|
|
225
|
-
|
|
338
|
+
}
|
|
339
|
+
case 'tool-calling': {
|
|
340
|
+
const config = await setupToolCallingModel('groq', collectedKeys);
|
|
341
|
+
if (config) {
|
|
342
|
+
configManager.setToolCallingModel(config);
|
|
343
|
+
logger.success('Tool-calling model updated');
|
|
344
|
+
}
|
|
226
345
|
break;
|
|
346
|
+
}
|
|
227
347
|
case 'mcp':
|
|
228
348
|
await manageMCPServers();
|
|
229
349
|
break;
|
|
@@ -241,121 +361,7 @@ export async function updateConfiguration() {
|
|
|
241
361
|
break;
|
|
242
362
|
}
|
|
243
363
|
}
|
|
244
|
-
|
|
245
|
-
const current = configManager.getReasoningModel();
|
|
246
|
-
const answers = await inquirer.prompt([
|
|
247
|
-
{
|
|
248
|
-
type: 'input',
|
|
249
|
-
name: 'endpoint',
|
|
250
|
-
message: 'API Endpoint URL:',
|
|
251
|
-
default: current?.endpoint,
|
|
252
|
-
},
|
|
253
|
-
{
|
|
254
|
-
type: 'password',
|
|
255
|
-
name: 'apiKey',
|
|
256
|
-
message: 'API Key:',
|
|
257
|
-
default: current?.apiKey,
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
type: 'input',
|
|
261
|
-
name: 'model',
|
|
262
|
-
message: 'Model name:',
|
|
263
|
-
default: current?.defaultModel,
|
|
264
|
-
},
|
|
265
|
-
]);
|
|
266
|
-
// Detect if Harmony format should be used based on model name
|
|
267
|
-
const isKrutrimModel = answers.model.includes('gpt-oss-120b');
|
|
268
|
-
const defaultUseHarmony = isKrutrimModel;
|
|
269
|
-
console.log(chalk.gray('\nTool Format Configuration'));
|
|
270
|
-
console.log(chalk.gray('Different providers use different formats for tool calling.\n'));
|
|
271
|
-
const { useHarmonyFormat } = await inquirer.prompt([
|
|
272
|
-
{
|
|
273
|
-
type: 'confirm',
|
|
274
|
-
name: 'useHarmonyFormat',
|
|
275
|
-
message: 'Use Harmony format for tool calling?',
|
|
276
|
-
default: current?.useHarmonyFormat ?? defaultUseHarmony,
|
|
277
|
-
when: () => {
|
|
278
|
-
// Show this prompt for all models, but provide smart default
|
|
279
|
-
console.log(chalk.gray(` Recommended: ${defaultUseHarmony ? 'Yes' : 'No'} (${isKrutrimModel ? 'Krutrim uses Harmony format' : 'Standard OpenAI format'})`));
|
|
280
|
-
return true;
|
|
281
|
-
},
|
|
282
|
-
},
|
|
283
|
-
]);
|
|
284
|
-
configManager.setReasoningModel({
|
|
285
|
-
name: 'reasoning',
|
|
286
|
-
endpoint: answers.endpoint,
|
|
287
|
-
apiKey: answers.apiKey,
|
|
288
|
-
type: 'reasoning',
|
|
289
|
-
defaultModel: answers.model,
|
|
290
|
-
useHarmonyFormat,
|
|
291
|
-
});
|
|
292
|
-
logger.success('Reasoning model updated');
|
|
293
|
-
}
|
|
294
|
-
async function updateMultimodalModel() {
|
|
295
|
-
const current = configManager.getMultimodalModel();
|
|
296
|
-
const answers = await inquirer.prompt([
|
|
297
|
-
{
|
|
298
|
-
type: 'input',
|
|
299
|
-
name: 'endpoint',
|
|
300
|
-
message: 'Multimodal API Endpoint URL:',
|
|
301
|
-
default: current?.endpoint || 'https://cloud.olakrutrim.com/v1/chat/completions',
|
|
302
|
-
},
|
|
303
|
-
{
|
|
304
|
-
type: 'password',
|
|
305
|
-
name: 'apiKey',
|
|
306
|
-
message: 'Multimodal API Key:',
|
|
307
|
-
default: current?.apiKey,
|
|
308
|
-
},
|
|
309
|
-
{
|
|
310
|
-
type: 'input',
|
|
311
|
-
name: 'model',
|
|
312
|
-
message: 'Multimodal model name:',
|
|
313
|
-
default: current?.defaultModel || 'Llama-4-Maverick-17B-128E-Instruct',
|
|
314
|
-
},
|
|
315
|
-
]);
|
|
316
|
-
configManager.setMultimodalModel({
|
|
317
|
-
name: 'multimodal',
|
|
318
|
-
endpoint: answers.endpoint,
|
|
319
|
-
apiKey: answers.apiKey,
|
|
320
|
-
type: 'multimodal',
|
|
321
|
-
defaultModel: answers.model,
|
|
322
|
-
});
|
|
323
|
-
logger.success('Multimodal model updated');
|
|
324
|
-
}
|
|
325
|
-
async function updateToolCallingModel() {
|
|
326
|
-
const current = configManager.getToolCallingModel();
|
|
327
|
-
console.log(chalk.gray('\nA dedicated tool-calling model is used as the PRIMARY model for tool'));
|
|
328
|
-
console.log(chalk.gray('execution. The reasoning model acts as the secondary fallback.\n'));
|
|
329
|
-
const answers = await inquirer.prompt([
|
|
330
|
-
{
|
|
331
|
-
type: 'input',
|
|
332
|
-
name: 'endpoint',
|
|
333
|
-
message: 'Tool-Calling API Endpoint URL:',
|
|
334
|
-
default: current?.endpoint || 'https://cloud.olakrutrim.com/v1/chat/completions',
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
type: 'password',
|
|
338
|
-
name: 'apiKey',
|
|
339
|
-
message: 'Tool-Calling API Key:',
|
|
340
|
-
default: current?.apiKey,
|
|
341
|
-
},
|
|
342
|
-
{
|
|
343
|
-
type: 'input',
|
|
344
|
-
name: 'model',
|
|
345
|
-
message: 'Tool-Calling model name:',
|
|
346
|
-
default: current?.defaultModel || 'gpt-4o-mini',
|
|
347
|
-
},
|
|
348
|
-
]);
|
|
349
|
-
configManager.setToolCallingModel({
|
|
350
|
-
name: 'tool-calling',
|
|
351
|
-
endpoint: answers.endpoint,
|
|
352
|
-
apiKey: answers.apiKey,
|
|
353
|
-
type: 'tool-calling',
|
|
354
|
-
defaultModel: answers.model,
|
|
355
|
-
useHarmonyFormat: false,
|
|
356
|
-
});
|
|
357
|
-
logger.success('Tool-calling model updated');
|
|
358
|
-
}
|
|
364
|
+
// ── Sub-functions (MCP, debug, view, reset) ────────────────────────────────
|
|
359
365
|
async function manageMCPServers() {
|
|
360
366
|
const servers = configManager.getMCPServers();
|
|
361
367
|
const serverNames = Object.keys(servers);
|
|
@@ -380,21 +386,9 @@ async function manageMCPServers() {
|
|
|
380
386
|
}
|
|
381
387
|
else if (action === 'add') {
|
|
382
388
|
const answers = await inquirer.prompt([
|
|
383
|
-
{
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
message: 'Server name:',
|
|
387
|
-
},
|
|
388
|
-
{
|
|
389
|
-
type: 'input',
|
|
390
|
-
name: 'command',
|
|
391
|
-
message: 'Command:',
|
|
392
|
-
},
|
|
393
|
-
{
|
|
394
|
-
type: 'input',
|
|
395
|
-
name: 'args',
|
|
396
|
-
message: 'Arguments (space-separated):',
|
|
397
|
-
},
|
|
389
|
+
{ type: 'input', name: 'name', message: 'Server name:' },
|
|
390
|
+
{ type: 'input', name: 'command', message: 'Command:' },
|
|
391
|
+
{ type: 'input', name: 'args', message: 'Arguments (space-separated):' },
|
|
398
392
|
]);
|
|
399
393
|
configManager.addMCPServer(answers.name, {
|
|
400
394
|
command: answers.command,
|
|
@@ -405,43 +399,26 @@ async function manageMCPServers() {
|
|
|
405
399
|
}
|
|
406
400
|
else if (action === 'remove' && serverNames.length > 0) {
|
|
407
401
|
const { serverName } = await inquirer.prompt([
|
|
408
|
-
{
|
|
409
|
-
type: 'list',
|
|
410
|
-
name: 'serverName',
|
|
411
|
-
message: 'Select server to remove:',
|
|
412
|
-
choices: serverNames,
|
|
413
|
-
},
|
|
402
|
+
{ type: 'list', name: 'serverName', message: 'Select server to remove:', choices: serverNames },
|
|
414
403
|
]);
|
|
415
404
|
configManager.removeMCPServer(serverName);
|
|
416
405
|
logger.success(`MCP server '${serverName}' removed`);
|
|
417
406
|
}
|
|
418
407
|
}
|
|
419
408
|
async function toggleDebugMode() {
|
|
420
|
-
const current = configManager.isDebug();
|
|
421
409
|
const { enabled } = await inquirer.prompt([
|
|
422
|
-
{
|
|
423
|
-
type: 'confirm',
|
|
424
|
-
name: 'enabled',
|
|
425
|
-
message: 'Enable debug mode?',
|
|
426
|
-
default: current,
|
|
427
|
-
},
|
|
410
|
+
{ type: 'confirm', name: 'enabled', message: 'Enable debug mode?', default: configManager.isDebug() },
|
|
428
411
|
]);
|
|
429
412
|
configManager.setDebug(enabled);
|
|
430
413
|
logger.success(`Debug mode ${enabled ? 'enabled' : 'disabled'}`);
|
|
431
414
|
}
|
|
432
415
|
function viewConfiguration() {
|
|
433
|
-
const config = configManager.getConfig();
|
|
434
416
|
console.log('\nCurrent Configuration:');
|
|
435
|
-
console.log(JSON.stringify(
|
|
417
|
+
console.log(JSON.stringify(configManager.getConfig(), null, 2));
|
|
436
418
|
}
|
|
437
419
|
async function resetConfiguration() {
|
|
438
420
|
const { confirm } = await inquirer.prompt([
|
|
439
|
-
{
|
|
440
|
-
type: 'confirm',
|
|
441
|
-
name: 'confirm',
|
|
442
|
-
message: chalk.red('Are you sure you want to reset all configuration?'),
|
|
443
|
-
default: false,
|
|
444
|
-
},
|
|
421
|
+
{ type: 'confirm', name: 'confirm', message: chalk.red('Are you sure you want to reset all configuration?'), default: false },
|
|
445
422
|
]);
|
|
446
423
|
if (confirm) {
|
|
447
424
|
configManager.reset();
|