@exreve/exk 1.0.66 → 1.0.68

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.
@@ -60,6 +60,8 @@ const DEFAULT_AI_MODEL = 'glm-5.1';
60
60
  /** TTL cache for ai-config.json reads to avoid hitting disk on every call */
61
61
  let _aiConfigCache = null;
62
62
  const AI_CONFIG_TTL_MS = 5_000;
63
+ // Provider registry — built dynamically from server-provided model list.
64
+ // Falls back to a minimal default set if config not yet fetched.
63
65
  const PROVIDERS = {
64
66
  zai: {
65
67
  apiKey: process.env.ZHIPU_API_KEY || '',
@@ -67,26 +69,52 @@ const PROVIDERS = {
67
69
  models: ['glm-5.1', 'glm-4.7', 'glm-4.5-air'],
68
70
  },
69
71
  minimax: {
70
- apiKey: '', // Populated from ai-config.json (served by backend)
72
+ apiKey: '',
71
73
  baseUrl: 'https://api.minimax.io/anthropic',
72
74
  models: ['MiniMax-M2.7', 'MiniMax-M2.7-highspeed'],
73
75
  },
74
76
  openrouter: {
75
- apiKey: '', // Populated from ai-config.json openrouterApiKey (served by backend)
77
+ apiKey: '',
76
78
  baseUrl: 'https://openrouter.ai/api',
77
79
  models: ['gpt-oss-120b:cerebras'],
78
80
  },
79
81
  cerebras: {
80
- apiKey: '', // Populated from ai-config.json cerebrasApiKey (served by backend)
81
- baseUrl: '', // Set dynamically when proxy starts
82
+ apiKey: '',
83
+ baseUrl: '',
82
84
  models: ['zai-glm-4.7'],
83
85
  },
84
86
  kimi: {
85
- apiKey: '', // Populated from ai-config.json kimiApiKey (served by backend)
87
+ apiKey: '',
86
88
  baseUrl: 'https://api.kimi.com/coding',
87
- models: ['kimi-k2.6'],
89
+ models: ['kimi-for-coding'],
88
90
  },
89
91
  };
92
+ /** Rebuild PROVIDERS from the models array saved in ai-config.json */
93
+ function rebuildProvidersFromConfig(models) {
94
+ if (!models || models.length === 0)
95
+ return;
96
+ // Group models by provider
97
+ const providerModels = {};
98
+ const providerUrls = {};
99
+ for (const m of models) {
100
+ if (!providerModels[m.provider])
101
+ providerModels[m.provider] = [];
102
+ if (!providerModels[m.provider].includes(m.id))
103
+ providerModels[m.provider].push(m.id);
104
+ if (m.providerBaseUrl)
105
+ providerUrls[m.provider] = m.providerBaseUrl;
106
+ }
107
+ // Update existing providers and add new ones
108
+ for (const [providerId, modelIds] of Object.entries(providerModels)) {
109
+ if (!PROVIDERS[providerId]) {
110
+ PROVIDERS[providerId] = { apiKey: '', baseUrl: providerUrls[providerId] || '', models: [] };
111
+ }
112
+ PROVIDERS[providerId].models = modelIds;
113
+ if (providerUrls[providerId] && providerId !== 'cerebras') {
114
+ PROVIDERS[providerId].baseUrl = providerUrls[providerId];
115
+ }
116
+ }
117
+ }
90
118
  /** Resolve which provider to use based on model name or explicit provider ID.
91
119
  * 1. Populate provider API keys from ai-config.json (served by backend).
92
120
  * 2. If explicit providerId is given and has an API key configured, use that provider.
@@ -136,12 +164,17 @@ function loadAiConfig() {
136
164
  const openrouterApiKey = typeof config.openrouterApiKey === 'string' ? config.openrouterApiKey.trim() : '';
137
165
  const cerebrasApiKey = typeof config.cerebrasApiKey === 'string' ? config.cerebrasApiKey.trim() : '';
138
166
  const kimiApiKey = typeof config.kimiApiKey === 'string' ? config.kimiApiKey.trim() : '';
139
- const result = { apiKey, baseUrl, model, proxy, minimaxApiKey, openrouterApiKey, cerebrasApiKey, kimiApiKey };
167
+ const models = config.models;
168
+ // Rebuild provider registry from server-provided model list
169
+ if (models && models.length > 0) {
170
+ rebuildProvidersFromConfig(models);
171
+ }
172
+ const result = { apiKey, baseUrl, model, proxy, minimaxApiKey, openrouterApiKey, cerebrasApiKey, kimiApiKey, models };
140
173
  _aiConfigCache = { data: result, ts: now };
141
174
  return result;
142
175
  }
143
176
  catch {
144
- const fallback = { apiKey: '', baseUrl: '', model: DEFAULT_AI_MODEL, proxy: '', minimaxApiKey: '', openrouterApiKey: '', cerebrasApiKey: '', kimiApiKey: '' };
177
+ const fallback = { apiKey: '', baseUrl: '', model: DEFAULT_AI_MODEL, proxy: '', minimaxApiKey: '', openrouterApiKey: '', cerebrasApiKey: '', kimiApiKey: '', models: [] };
145
178
  _aiConfigCache = { data: fallback, ts: now };
146
179
  return fallback;
147
180
  }
@@ -84,7 +84,9 @@ async function fetchAiConfig(authToken) {
84
84
  console.log('[fetchAiConfig] No AI config available for this user');
85
85
  return false;
86
86
  }
87
- await fs.writeFile(AI_CONFIG_FILE, JSON.stringify(data.aiConfig, null, 2));
87
+ // Save aiConfig + models together so agentSession can build provider registry dynamically
88
+ const configPayload = { ...data.aiConfig, models: data.models || [] };
89
+ await fs.writeFile(AI_CONFIG_FILE, JSON.stringify(configPayload, null, 2));
88
90
  console.log('[fetchAiConfig] AI config saved successfully');
89
91
  return true;
90
92
  }
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exreve/exk",
3
- "version": "1.0.66",
3
+ "version": "1.0.68",
4
4
  "description": "exk - Control Claude CLI with voice and programmable interfaces",
5
5
  "type": "module",
6
6
  "bin": {