@ducci/jarvis 1.0.58 → 1.0.60
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/package.json +1 -1
- package/src/scripts/onboarding.js +83 -2
- package/src/server/config.js +3 -0
- package/src/server/provider.js +6 -0
- package/src/server/tools.js +1 -1
package/package.json
CHANGED
|
@@ -89,6 +89,21 @@ async function fetchAnthropicModels(apiKey) {
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
async function fetchZaiModels(apiKey) {
|
|
93
|
+
console.log(chalk.blue('Fetching models from Z.AI...'));
|
|
94
|
+
try {
|
|
95
|
+
const response = await fetch('https://api.z.ai/api/paas/v4/models', {
|
|
96
|
+
headers: { 'Authorization': `Bearer ${apiKey}` }
|
|
97
|
+
});
|
|
98
|
+
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
|
99
|
+
const data = await response.json();
|
|
100
|
+
return data.data || [];
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error(chalk.red('Failed to fetch Z.AI models:'), error.message);
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
92
107
|
async function run() {
|
|
93
108
|
ensureDirectories();
|
|
94
109
|
|
|
@@ -105,6 +120,7 @@ async function run() {
|
|
|
105
120
|
choices: [
|
|
106
121
|
{ name: 'OpenRouter (access many models via one key)', value: 'openrouter' },
|
|
107
122
|
{ name: 'Anthropic Direct (use your Anthropic API key)', value: 'anthropic' },
|
|
123
|
+
{ name: 'Z.AI Direct (GLM models, use your Z.AI API key)', value: 'z-ai' },
|
|
108
124
|
],
|
|
109
125
|
default: settings.provider || 'openrouter',
|
|
110
126
|
}
|
|
@@ -142,6 +158,35 @@ async function run() {
|
|
|
142
158
|
saveEnvVar('ANTHROPIC_API_KEY', apiKey);
|
|
143
159
|
console.log(chalk.green('Anthropic API key saved.'));
|
|
144
160
|
}
|
|
161
|
+
} else if (provider === 'z-ai') {
|
|
162
|
+
const existingKey = loadEnvVar('ZAI_API_KEY');
|
|
163
|
+
apiKey = existingKey;
|
|
164
|
+
|
|
165
|
+
if (existingKey) {
|
|
166
|
+
const { keepKey } = await inquirer.prompt([
|
|
167
|
+
{
|
|
168
|
+
type: 'confirm',
|
|
169
|
+
name: 'keepKey',
|
|
170
|
+
message: 'A ZAI_API_KEY is already configured. Do you want to keep it?',
|
|
171
|
+
default: true,
|
|
172
|
+
}
|
|
173
|
+
]);
|
|
174
|
+
if (!keepKey) apiKey = null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (!apiKey) {
|
|
178
|
+
const { newKey } = await inquirer.prompt([
|
|
179
|
+
{
|
|
180
|
+
type: 'password',
|
|
181
|
+
name: 'newKey',
|
|
182
|
+
message: 'Enter your Z.AI API key (from open.bigmodel.cn):',
|
|
183
|
+
validate: (input) => input.length >= 10 || 'API key must be at least 10 characters long.',
|
|
184
|
+
}
|
|
185
|
+
]);
|
|
186
|
+
apiKey = newKey;
|
|
187
|
+
saveEnvVar('ZAI_API_KEY', apiKey);
|
|
188
|
+
console.log(chalk.green('Z.AI API key saved.'));
|
|
189
|
+
}
|
|
145
190
|
} else {
|
|
146
191
|
const existingKey = loadEnvVar('OPENROUTER_API_KEY');
|
|
147
192
|
apiKey = existingKey;
|
|
@@ -193,7 +238,41 @@ async function run() {
|
|
|
193
238
|
}
|
|
194
239
|
|
|
195
240
|
if (!selectedModel) {
|
|
196
|
-
if (provider === '
|
|
241
|
+
if (provider === 'z-ai') {
|
|
242
|
+
const models = await fetchZaiModels(apiKey);
|
|
243
|
+
let choices;
|
|
244
|
+
if (models.length > 0) {
|
|
245
|
+
choices = models.map(m => ({ name: m.id, value: m.id }));
|
|
246
|
+
} else {
|
|
247
|
+
console.log(chalk.yellow('Falling back to manual entry due to fetch failure.'));
|
|
248
|
+
choices = [];
|
|
249
|
+
}
|
|
250
|
+
choices.push({ name: 'Enter model ID manually', value: '__manual__' });
|
|
251
|
+
|
|
252
|
+
const { browsedModel } = await inquirer.prompt([
|
|
253
|
+
{
|
|
254
|
+
type: 'list',
|
|
255
|
+
name: 'browsedModel',
|
|
256
|
+
message: 'Select a Z.AI model:',
|
|
257
|
+
choices,
|
|
258
|
+
pageSize: 20,
|
|
259
|
+
}
|
|
260
|
+
]);
|
|
261
|
+
|
|
262
|
+
if (browsedModel === '__manual__') {
|
|
263
|
+
const { manualModel } = await inquirer.prompt([
|
|
264
|
+
{
|
|
265
|
+
type: 'input',
|
|
266
|
+
name: 'manualModel',
|
|
267
|
+
message: 'Enter Z.AI model ID (e.g., glm-5):',
|
|
268
|
+
validate: (input) => input.trim().length > 0 || 'Model ID cannot be empty.',
|
|
269
|
+
}
|
|
270
|
+
]);
|
|
271
|
+
selectedModel = manualModel.trim();
|
|
272
|
+
} else {
|
|
273
|
+
selectedModel = browsedModel;
|
|
274
|
+
}
|
|
275
|
+
} else if (provider === 'anthropic') {
|
|
197
276
|
console.log(chalk.blue('Fetching available Claude models...'));
|
|
198
277
|
const models = await fetchAnthropicModels(apiKey);
|
|
199
278
|
const choices = models.map(m => ({
|
|
@@ -293,7 +372,9 @@ async function run() {
|
|
|
293
372
|
settings.selectedModel = selectedModel;
|
|
294
373
|
// Reset fallback to provider-appropriate default when switching providers or on first run
|
|
295
374
|
if (!settings.fallbackModel || previousProvider !== provider) {
|
|
296
|
-
|
|
375
|
+
if (provider === 'anthropic') settings.fallbackModel = 'claude-haiku-4-5-20251001';
|
|
376
|
+
else if (provider === 'z-ai') settings.fallbackModel = 'glm-4-flash';
|
|
377
|
+
else settings.fallbackModel = 'openrouter/free';
|
|
297
378
|
}
|
|
298
379
|
if (settings.maxIterations === undefined) {
|
|
299
380
|
settings.maxIterations = 10;
|
package/src/server/config.js
CHANGED
|
@@ -46,6 +46,9 @@ export function loadConfig() {
|
|
|
46
46
|
if (provider === 'anthropic') {
|
|
47
47
|
apiKey = process.env.ANTHROPIC_API_KEY;
|
|
48
48
|
if (!apiKey) throw new Error('ANTHROPIC_API_KEY not found. Run `jarvis setup` first.');
|
|
49
|
+
} else if (provider === 'z-ai') {
|
|
50
|
+
apiKey = process.env.ZAI_API_KEY;
|
|
51
|
+
if (!apiKey) throw new Error('ZAI_API_KEY not found. Add it to ~/.jarvis/.env first.');
|
|
49
52
|
} else {
|
|
50
53
|
apiKey = process.env.OPENROUTER_API_KEY;
|
|
51
54
|
if (!apiKey) throw new Error('OPENROUTER_API_KEY not found. Run `jarvis setup` first.');
|
package/src/server/provider.js
CHANGED
|
@@ -149,6 +149,12 @@ export function createClient(config) {
|
|
|
149
149
|
if (config.provider === 'anthropic') {
|
|
150
150
|
return createAnthropicClient(config.apiKey);
|
|
151
151
|
}
|
|
152
|
+
if (config.provider === 'z-ai') {
|
|
153
|
+
return new OpenAI({
|
|
154
|
+
baseURL: 'https://api.z.ai/api/paas/v4/',
|
|
155
|
+
apiKey: config.apiKey,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
152
158
|
// Default: OpenRouter (OpenAI-compatible)
|
|
153
159
|
return new OpenAI({
|
|
154
160
|
baseURL: 'https://openrouter.ai/api/v1',
|
package/src/server/tools.js
CHANGED
|
@@ -548,7 +548,7 @@ const SEED_TOOLS = {
|
|
|
548
548
|
const logFile = path.join(logDir, String(chatId) + '-' + prefix + '.log');
|
|
549
549
|
const ts = new Date().toISOString();
|
|
550
550
|
await fs.promises.mkdir(logDir, { recursive: true });
|
|
551
|
-
await fs.promises.appendFile(logFile, ts + ' [CRON] ' + String(args.message).replace(
|
|
551
|
+
await fs.promises.appendFile(logFile, ts + ' [CRON] ' + String(args.message).replace(/\\n/g, ' ') + '\\n', 'utf8');
|
|
552
552
|
} catch {}
|
|
553
553
|
return { status: 'ok', chatId };
|
|
554
554
|
`,
|