@dubeyvishal/orbital-cli 1.6.14 → 1.6.15

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.
@@ -86,73 +86,10 @@ export const updateOrbitalConfig = async (patch = {}) => {
86
86
  return nextConfig;
87
87
  };
88
88
 
89
- // --- Model Preference Persistence ---
90
-
91
- export const getSelectedModel = async () => {
92
- const cfg = await readOrbitalConfig();
93
- let model = cfg.selectedModel || "gemini-2.5-flash";
94
- if (model.includes("gemini-2.0")) model = "gemini-2.5-flash";
95
- return {
96
- provider: cfg.selectedProvider || "gemini",
97
- model,
98
- };
99
- };
100
-
101
- export const getSelectedModelSync = () => {
102
- const cfg = readOrbitalConfigSync();
103
- let model = cfg.selectedModel || "gemini-2.5-flash";
104
- if (model.includes("gemini-2.0")) model = "gemini-2.5-flash";
105
- return {
106
- provider: cfg.selectedProvider || "gemini",
107
- model,
108
- };
109
- };
110
-
111
- export const saveSelectedModel = async ({ provider, model }) => {
112
- return await updateOrbitalConfig({
113
- selectedProvider: provider,
114
- selectedModel: model,
115
- });
116
- };
117
-
118
- // --- Multi-Provider API Key Management ---
119
-
120
- export const normalizeProviderName = (provider = "gemini") => {
121
- const p = (provider || "gemini").toLowerCase().trim();
122
- if (p === "google" || p === "gemini") return "gemini";
123
- if (p === "openai") return "openai";
124
- if (p === "xai" || p === "grok") return "grok";
125
- return p;
126
- };
127
-
128
- export const getApiKeyFromEnvSync = (provider = "gemini") => {
129
- const norm = normalizeProviderName(provider);
130
- if (norm === "gemini") {
131
- return (
132
- (typeof process.env.GOOGLE_GENERATIVE_AI_API_KEY === "string" &&
133
- process.env.GOOGLE_GENERATIVE_AI_API_KEY.trim()) ||
134
- (typeof process.env.GEMINI_API_KEY === "string" &&
135
- process.env.GEMINI_API_KEY.trim()) ||
136
- ""
137
- );
138
- }
139
- if (norm === "openai") {
140
- return (
141
- (typeof process.env.OPENAI_API_KEY === "string" &&
142
- process.env.OPENAI_API_KEY.trim()) ||
143
- ""
144
- );
145
- }
146
- if (norm === "grok") {
147
- return (
148
- (typeof process.env.XAI_API_KEY === "string" &&
149
- process.env.XAI_API_KEY.trim()) ||
150
- (typeof process.env.GROK_API_KEY === "string" &&
151
- process.env.GROK_API_KEY.trim()) ||
152
- ""
153
- );
154
- }
155
- return "";
89
+ const getGeminiApiKeyFromEnvSync = () => {
90
+ return typeof process.env.GOOGLE_GENERATIVE_AI_API_KEY === "string"
91
+ ? process.env.GOOGLE_GENERATIVE_AI_API_KEY.trim()
92
+ : "";
156
93
  };
157
94
 
158
95
  const getLegacyGeminiApiKeyFromConfigSync = () => {
@@ -176,123 +113,80 @@ const removeLegacyGeminiApiKeyFromConfig = async () => {
176
113
  return true;
177
114
  };
178
115
 
179
- export const hydrateApiKeyEnv = async (provider = "gemini") => {
180
- const norm = normalizeProviderName(provider);
181
- const already = getApiKeyFromEnvSync(norm);
116
+ export const hydrateGeminiApiKeyEnv = async () => {
117
+ const already = getGeminiApiKeyFromEnvSync();
182
118
  if (already) return already;
183
119
 
184
- // OS credential manager via keytar
120
+ // Primary: OS credential manager via keytar.
185
121
  try {
186
- const fromKeytar = await getStoredApiKey(norm);
122
+ const fromKeytar = await getStoredApiKey();
187
123
  if (fromKeytar) {
188
- if (norm === "gemini") {
189
- process.env.GOOGLE_GENERATIVE_AI_API_KEY = fromKeytar;
190
- } else if (norm === "openai") {
191
- process.env.OPENAI_API_KEY = fromKeytar;
192
- } else if (norm === "grok") {
193
- process.env.XAI_API_KEY = fromKeytar;
194
- }
124
+ process.env.GOOGLE_GENERATIVE_AI_API_KEY = fromKeytar;
195
125
  return fromKeytar;
196
126
  }
197
127
  } catch {
198
- // Ignore keytar error; will be handled in requireApiKey
128
+ // ignore here; requireGeminiApiKey will surface a helpful error
199
129
  }
200
130
 
201
- // One-time migration for legacy Gemini key on disk
202
- if (norm === "gemini") {
203
- const legacy = getLegacyGeminiApiKeyFromConfigSync();
204
- if (legacy) {
205
- await storeApiKey(legacy, "gemini");
206
- await removeLegacyGeminiApiKeyFromConfig().catch(() => {});
207
- process.env.GOOGLE_GENERATIVE_AI_API_KEY = legacy;
208
- return legacy;
209
- }
131
+ // One-time migration: if the key exists in legacy ~/.orbital/config.json,
132
+ // move it into keytar and remove it from disk.
133
+ const legacy = getLegacyGeminiApiKeyFromConfigSync();
134
+ if (legacy) {
135
+ await storeApiKey(legacy);
136
+ await removeLegacyGeminiApiKeyFromConfig().catch(() => {});
137
+ process.env.GOOGLE_GENERATIVE_AI_API_KEY = legacy;
138
+ return legacy;
210
139
  }
211
140
 
212
141
  return "";
213
142
  };
214
143
 
215
- export const hydrateAllApiKeysEnv = async () => {
216
- await Promise.all([
217
- hydrateApiKeyEnv("gemini"),
218
- hydrateApiKeyEnv("openai"),
219
- hydrateApiKeyEnv("grok"),
220
- ]);
221
- };
222
-
223
- export const getApiKeySync = (provider = "gemini") => {
224
- return getApiKeyFromEnvSync(provider);
225
- };
144
+ export const getGeminiApiKeySync = () => getGeminiApiKeyFromEnvSync();
226
145
 
227
- export const getApiKey = async (provider = "gemini") => {
228
- const norm = normalizeProviderName(provider);
229
- const fromEnv = getApiKeyFromEnvSync(norm);
146
+ export const getGeminiApiKey = async () => {
147
+ const fromEnv = getGeminiApiKeyFromEnvSync();
230
148
  if (fromEnv) return fromEnv;
231
- return await hydrateApiKeyEnv(norm);
149
+ return await hydrateGeminiApiKeyEnv();
232
150
  };
233
151
 
234
- export const hasApiKeySync = (provider = "gemini") => {
235
- return Boolean(getApiKeyFromEnvSync(provider));
236
- };
152
+ export const hasGeminiApiKeySync = () => Boolean(getGeminiApiKeyFromEnvSync());
237
153
 
238
- export const requireApiKeySync = (provider = "gemini") => {
239
- const norm = normalizeProviderName(provider);
240
- const apiKey = getApiKeyFromEnvSync(norm);
154
+ export const requireGeminiApiKeySync = () => {
155
+ const apiKey = getGeminiApiKeyFromEnvSync();
241
156
  if (!apiKey) {
242
- const displayName =
243
- norm === "gemini" ? "Gemini" : norm === "openai" ? "OpenAI" : "Grok (xAI)";
244
157
  const err = new Error(
245
- `${displayName} API key not set. Run: orbital set-key --provider ${norm} <API_KEY>`
158
+ "Gemini API key not set. Run: orbital set-key <API_KEY>"
246
159
  );
247
- err.code = `ORBITAL_${norm.toUpperCase()}_API_KEY_NOT_SET`;
160
+ err.code = "ORBITAL_GEMINI_API_KEY_NOT_SET";
248
161
  throw err;
249
162
  }
250
163
  return apiKey;
251
164
  };
252
165
 
253
- export const requireApiKey = async (provider = "gemini") => {
254
- const norm = normalizeProviderName(provider);
255
- const apiKey = await getApiKey(norm);
166
+ export const requireGeminiApiKey = async () => {
167
+ const apiKey = await getGeminiApiKey();
256
168
  if (!apiKey) {
257
- const displayName =
258
- norm === "gemini" ? "Gemini" : norm === "openai" ? "OpenAI" : "Grok (xAI)";
259
169
  const err = new Error(
260
- `${displayName} API key not set. Run: orbital set-key --provider ${norm} <API_KEY>`
170
+ "Gemini API key not set. Run: orbital set-key <API_KEY>"
261
171
  );
262
- err.code = `ORBITAL_${norm.toUpperCase()}_API_KEY_NOT_SET`;
172
+ err.code = "ORBITAL_GEMINI_API_KEY_NOT_SET";
263
173
  throw err;
264
174
  }
265
175
  return apiKey;
266
176
  };
267
177
 
268
- export const setApiKey = async (provider = "gemini", apiKey) => {
269
- const norm = normalizeProviderName(provider);
178
+ export const setGeminiApiKey = async (apiKey) => {
270
179
  const trimmed = typeof apiKey === "string" ? apiKey.trim() : "";
271
180
  if (!trimmed) throw new Error("API key is required");
272
181
 
273
- await storeApiKey(trimmed, norm);
274
-
275
- if (norm === "gemini") {
276
- await removeLegacyGeminiApiKeyFromConfig().catch(() => {});
277
- process.env.GOOGLE_GENERATIVE_AI_API_KEY = trimmed;
278
- process.env.GEMINI_API_KEY = trimmed;
279
- } else if (norm === "openai") {
280
- process.env.OPENAI_API_KEY = trimmed;
281
- } else if (norm === "grok") {
282
- process.env.XAI_API_KEY = trimmed;
283
- process.env.GROK_API_KEY = trimmed;
284
- }
182
+ await storeApiKey(trimmed);
183
+ // Ensure any legacy on-disk key is removed.
184
+ await removeLegacyGeminiApiKeyFromConfig().catch(() => {});
285
185
 
186
+ process.env.GOOGLE_GENERATIVE_AI_API_KEY = trimmed;
286
187
  return true;
287
188
  };
288
189
 
289
- // --- Back-compatibility exports for Gemini ---
290
-
291
- export const hydrateGeminiApiKeyEnv = () => hydrateApiKeyEnv("gemini");
292
- export const getGeminiApiKeySync = () => getApiKeySync("gemini");
293
- export const getGeminiApiKey = () => getApiKey("gemini");
294
- export const hasGeminiApiKeySync = () => hasApiKeySync("gemini");
295
- export const requireGeminiApiKeySync = () => requireApiKeySync("gemini");
296
- export const requireGeminiApiKey = () => requireApiKey("gemini");
297
- export const setGeminiApiKey = (apiKey) => setApiKey("gemini", apiKey);
190
+ // Back-compat exports (no longer reads from config specifically).
298
191
  export const requireGeminiApiKeyFromConfigSync = requireGeminiApiKeySync;
192
+
@@ -1,5 +1,5 @@
1
1
  import { AIService } from "../cli/ai/googleService.js";
2
2
 
3
- export const getAIService = (modelConfig = null) => {
4
- return new AIService(modelConfig);
3
+ export const getAIService = () => {
4
+ return new AIService();
5
5
  };
@@ -1,159 +0,0 @@
1
- import "./env.js";
2
- import { createGoogleGenerativeAI } from "@ai-sdk/google";
3
- import { createOpenAI } from "@ai-sdk/openai";
4
- import { createXai } from "@ai-sdk/xai";
5
- import { normalizeProviderName, requireApiKeySync } from "../lib/orbitalConfig.js";
6
-
7
- export const AI_PROVIDERS = {
8
- gemini: {
9
- id: "gemini",
10
- name: "Google Gemini",
11
- defaultModel: "gemini-2.5-flash",
12
- envKey: "GOOGLE_GENERATIVE_AI_API_KEY",
13
- docsUrl: "https://aistudio.google.com/app/apikey",
14
- models: [
15
- {
16
- id: "gemini-2.5-flash",
17
- name: "Gemini 2.5 Flash",
18
- hint: "Google (Fast & versatile - Recommended)",
19
- isDefault: true,
20
- },
21
- {
22
- id: "gemini-2.5-pro",
23
- name: "Gemini 2.5 Pro",
24
- hint: "Google (Complex reasoning & large context)",
25
- },
26
- {
27
- id: "gemini-1.5-flash",
28
- name: "Gemini 1.5 Flash",
29
- hint: "Google (Lightweight & efficient)",
30
- },
31
- {
32
- id: "gemini-1.5-pro",
33
- name: "Gemini 1.5 Pro",
34
- hint: "Google (Extended analysis)",
35
- },
36
- ],
37
- },
38
- openai: {
39
- id: "openai",
40
- name: "OpenAI",
41
- defaultModel: "gpt-4o",
42
- envKey: "OPENAI_API_KEY",
43
- docsUrl: "https://platform.openai.com/api-keys",
44
- models: [
45
- {
46
- id: "gpt-4o",
47
- name: "GPT-4o",
48
- hint: "OpenAI (Flagship multimodal intelligence)",
49
- isDefault: true,
50
- },
51
- {
52
- id: "gpt-4o-mini",
53
- name: "GPT-4o Mini",
54
- hint: "OpenAI (Fast & cost-effective)",
55
- },
56
- ],
57
- },
58
- grok: {
59
- id: "grok",
60
- name: "Grok (xAI)",
61
- defaultModel: "grok-2-latest",
62
- envKey: "XAI_API_KEY",
63
- docsUrl: "https://console.x.ai/",
64
- models: [
65
- {
66
- id: "grok-2-latest",
67
- name: "Grok 2",
68
- hint: "xAI (Frontier model with advanced reasoning)",
69
- isDefault: true,
70
- },
71
- {
72
- id: "grok-beta",
73
- name: "Grok Beta",
74
- hint: "xAI (Experimental release)",
75
- },
76
- ],
77
- },
78
- };
79
-
80
- /**
81
- * Returns options list suitable for @clack/prompts select()
82
- */
83
- export const getModelSelectOptions = () => {
84
- const options = [];
85
- for (const provider of Object.values(AI_PROVIDERS)) {
86
- for (const model of provider.models) {
87
- options.push({
88
- value: `${provider.id}:${model.id}`,
89
- label: `${provider.name} - ${model.name}`,
90
- hint: model.hint,
91
- });
92
- }
93
- }
94
- return options;
95
- };
96
-
97
- /**
98
- * Parse a compound value like "openai:gpt-4o" or separate provider/model inputs
99
- */
100
- export const parseModelChoice = (choice) => {
101
- if (!choice) return { provider: "gemini", model: "gemini-2.5-flash" };
102
- if (typeof choice === "object") {
103
- const provider = normalizeProviderName(choice.provider || "gemini");
104
- const defaultModel = AI_PROVIDERS[provider]?.defaultModel || "gemini-2.5-flash";
105
- let model = choice.model || defaultModel;
106
- if (model.includes("gemini-2.0")) model = "gemini-2.5-flash";
107
- return {
108
- provider,
109
- model,
110
- };
111
- }
112
-
113
- if (typeof choice === "string" && choice.includes(":")) {
114
- const [p, m] = choice.split(":");
115
- const provider = normalizeProviderName(p);
116
- const model = m.includes("gemini-2.0") ? "gemini-2.5-flash" : m;
117
- return { provider, model };
118
- }
119
-
120
- // If only provider name is given
121
- const provider = normalizeProviderName(choice);
122
- return {
123
- provider,
124
- model: AI_PROVIDERS[provider]?.defaultModel || choice,
125
- };
126
- };
127
-
128
-
129
- export const getModelDisplayName = (provider, modelId) => {
130
- const norm = normalizeProviderName(provider);
131
- const provInfo = AI_PROVIDERS[norm];
132
- if (!provInfo) return `${provider} (${modelId})`;
133
- const modelInfo = provInfo.models.find((m) => m.id === modelId);
134
- return modelInfo ? `${provInfo.name} (${modelInfo.name})` : `${provInfo.name} (${modelId})`;
135
- };
136
-
137
- /**
138
- * Creates a language model instance for Vercel AI SDK
139
- */
140
- export const createModelInstance = (provider, modelName, apiKey = null) => {
141
- const norm = normalizeProviderName(provider);
142
- const key = apiKey || requireApiKeySync(norm);
143
-
144
- switch (norm) {
145
- case "openai": {
146
- const openai = createOpenAI({ apiKey: key });
147
- return openai(modelName);
148
- }
149
- case "grok": {
150
- const xai = createXai({ apiKey: key });
151
- return xai(modelName);
152
- }
153
- case "gemini":
154
- default: {
155
- const google = createGoogleGenerativeAI({ apiKey: key });
156
- return google(modelName);
157
- }
158
- }
159
- };