@dubeyvishal/orbital-cli 1.6.14 → 1.6.16

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 CHANGED
@@ -25,13 +25,13 @@ Start Orbital:
25
25
  ## 📸 Project Screenshots
26
26
 
27
27
  ### 🔐 Orbital Login Screen
28
- ![Orbital Login Screen](https://res.cloudinary.com/damw21f39/image/upload/v1773569580/pic1_u0wu0y.png)
28
+ ![Orbital Login Screen](https://ik.imagekit.io/55z5toj5e/Orbital-CLI/orbital_login.png?updatedAt=1788983014376)
29
29
 
30
30
  ### 🛠️ Orbital Wakeup – Tools Loaded
31
- ![Orbital Wakeup](https://res.cloudinary.com/damw21f39/image/upload/v1773569581/pic2_mvnpiu.png)
31
+ ![Orbital Wakeup](https://ik.imagekit.io/55z5toj5e/Orbital-CLI/orbital_wakeup.png?updatedAt=1788982937600)
32
32
 
33
33
  ### 🤖 Agentic Mode
34
- ![Agentic Mode](https://res.cloudinary.com/damw21f39/image/upload/v1773569581/pic3_bvidmp.png)
34
+ ![Agentic Mode](https://ik.imagekit.io/55z5toj5e/Orbital-CLI/agentic_mode.png?updatedAt=1788982970736)
35
35
 
36
36
  ------------------------------------------------------------------------
37
37
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dubeyvishal/orbital-cli",
3
- "version": "1.6.14",
3
+ "version": "1.6.16",
4
4
  "description": "A fullstack CLI-based AI platform with chat mode, multi-tool agents, and agentic AI workflows. Includes GitHub login with device authorization, secure authentication, and modular client–server architecture for building intelligent automation tools.",
5
5
  "author": "Vishal Dubey",
6
6
  "license": "MIT",
@@ -21,8 +21,6 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@ai-sdk/google": "^3.0.6",
24
- "@ai-sdk/openai": "^4.0.57",
25
- "@ai-sdk/xai": "^4.0.54",
26
24
  "@clack/prompts": "^0.11.0",
27
25
  "ai": "^6.0.29",
28
26
  "boxen": "^8.0.1",
@@ -51,4 +49,4 @@
51
49
  "client-server",
52
50
  "javascript"
53
51
  ]
54
- }
52
+ }
@@ -1,19 +1,11 @@
1
+ import { google } from "@ai-sdk/google";
1
2
  import { streamText, generateObject } from "ai";
2
3
  import { config } from "../../config/googleConfig.js";
3
4
  import chalk from "chalk";
4
- import {
5
- normalizeProviderName,
6
- getSelectedModelSync,
7
- } from "../../lib/orbitalConfig.js";
8
- import {
9
- AI_PROVIDERS,
10
- createModelInstance,
11
- getModelDisplayName,
12
- parseModelChoice,
13
- } from "../../config/aiConfig.js";
5
+ import { requireGeminiApiKeySync } from "../../lib/orbitalConfig.js";
14
6
 
15
7
  const MAX_RETRIES = 3;
16
- const BASE_DELAY_MS = 3000; // 3 seconds
8
+ const BASE_DELAY_MS = 5000; // 5 seconds
17
9
 
18
10
  const isRateLimitError = (error) => {
19
11
  if (!error) return false;
@@ -31,30 +23,12 @@ const isRateLimitError = (error) => {
31
23
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
32
24
 
33
25
  export class AIService {
34
- constructor(modelConfig = null) {
35
- let resolved;
36
-
37
- if (modelConfig) {
38
- resolved = parseModelChoice(modelConfig);
39
- } else {
40
- const saved = getSelectedModelSync();
41
- const provider = process.env.ORBITAL_PROVIDER || saved?.provider || "gemini";
42
- const model =
43
- process.env.ORBITAL_MODEL ||
44
- saved?.model ||
45
- AI_PROVIDERS[normalizeProviderName(provider)]?.defaultModel ||
46
- "gemini-2.5-flash";
47
- resolved = { provider: normalizeProviderName(provider), model };
26
+ constructor() {
27
+ const apiKey = requireGeminiApiKeySync();
48
28
 
49
- }
50
-
51
- this.provider = resolved.provider;
52
- this.modelName = resolved.model;
53
- this.model = createModelInstance(this.provider, this.modelName);
54
- }
55
-
56
- getDisplayName() {
57
- return getModelDisplayName(this.provider, this.modelName);
29
+ this.model = google(config.model, {
30
+ apiKey,
31
+ });
58
32
  }
59
33
 
60
34
  async sendMessage(messages, onChunk, tools = undefined, onToolCall = null) {
@@ -71,28 +45,22 @@ export class AIService {
71
45
  if (tools && Object.keys(tools).length > 0) {
72
46
  streamConfig.tools = tools;
73
47
  streamConfig.maxSteps = 5;
48
+ if (attempt === 1) {
49
+ console.log(
50
+ chalk.gray(
51
+ `[DEBUG] Tools enabled: ${Object.keys(tools).join(", ")}`
52
+ )
53
+ );
54
+ }
74
55
  }
75
56
 
76
57
  const result = await streamText(streamConfig);
77
58
 
78
59
  let fullResponse = "";
79
60
 
80
- for await (const part of result.fullStream) {
81
- if (part.type === "text-delta") {
82
- const chunk = part.text ?? part.textDelta ?? "";
83
- fullResponse += chunk;
84
- if (onChunk) onChunk(chunk);
85
- }
86
- }
87
-
88
-
89
-
90
- if (!fullResponse) {
91
- try {
92
- fullResponse = (await result.text) || "";
93
- } catch {
94
- // ignore if result.text is not available
95
- }
61
+ for await (const chunk of result.textStream) {
62
+ fullResponse += chunk;
63
+ if (onChunk) onChunk(chunk);
96
64
  }
97
65
 
98
66
  const toolCalls = [];
@@ -123,20 +91,6 @@ export class AIService {
123
91
  }
124
92
  }
125
93
 
126
- if (!fullResponse && toolResults.length > 0) {
127
- fullResponse = toolResults
128
- .map((tr) => {
129
- const output = tr.output ?? tr.result;
130
- const resStr =
131
- typeof output === "object"
132
- ? JSON.stringify(output)
133
- : String(output);
134
- return `Tool ${tr.toolName} output: ${resStr}`;
135
- })
136
- .join("\n");
137
- }
138
-
139
-
140
94
  return {
141
95
  content: fullResponse,
142
96
  finishReason: result.finishReason,
@@ -153,41 +107,36 @@ export class AIService {
153
107
  const delaySec = Math.round(delayMs / 1000);
154
108
  console.log(
155
109
  chalk.yellow(
156
- `\n⚠ Rate limit hit (429) on ${this.getDisplayName()}. Retrying in ${delaySec}s... (attempt ${attempt}/${MAX_RETRIES})`
110
+ `\n⚠ Rate limit hit (429). Retrying in ${delaySec}s... (attempt ${attempt}/${MAX_RETRIES})`
157
111
  )
158
112
  );
159
113
  await sleep(delayMs);
160
114
  continue;
161
115
  }
162
116
 
163
- // Provide actionable provider-specific error messages
117
+ // Provide an actionable message for rate-limit errors.
164
118
  if (isRateLimitError(error)) {
165
- const provInfo = AI_PROVIDERS[this.provider];
166
119
  console.error(
167
120
  chalk.red(
168
- `\n✖ ${this.getDisplayName()} rate limit / quota exhausted. All retry attempts failed.`
121
+ "\n✖ Gemini API quota exhausted. All retry attempts failed."
169
122
  )
170
123
  );
171
124
  console.error(
172
125
  chalk.yellow(
173
- ` Possible fixes:\n` +
174
- ` 1. Wait a moment and try again\n` +
175
- ` 2. Check your quota & billing at: ${provInfo?.docsUrl || "provider portal"}\n` +
176
- ` 3. Switch to another model or update your API key: orbital set-key --provider ${this.provider} <KEY>`
126
+ " Possible fixes:\n" +
127
+ " 1. Wait a few minutes and try again (free-tier resets per minute)\n" +
128
+ " 2. Check your quota: https://ai.google.dev/gemini-api/docs/rate-limits\n" +
129
+ " 3. Upgrade your Gemini API plan for higher limits\n" +
130
+ " 4. Use a different API key with available quota"
177
131
  )
178
132
  );
179
133
  } else {
180
- const detailedMsg =
181
- error?.data?.error?.message ||
182
- error?.message ||
183
- error;
184
134
  console.error(
185
- chalk.red(`AI Service Error (${this.getDisplayName()}):`),
186
- detailedMsg
135
+ chalk.red("AI Service Error:"),
136
+ error?.message || error
187
137
  );
188
138
  }
189
139
 
190
-
191
140
  throw error;
192
141
  }
193
142
  }
@@ -209,10 +158,11 @@ export class AIService {
209
158
  return result.object;
210
159
  } catch (error) {
211
160
  console.log(
212
- chalk.red(`AI Structured Generation Error (${this.getDisplayName()}):`),
161
+ chalk.red("AI Structured Generation Error:"),
213
162
  error?.message || error
214
163
  );
215
164
  throw error;
216
165
  }
217
166
  }
218
167
  }
168
+
@@ -12,12 +12,14 @@ import {
12
12
  } from "../../config/agentConfig.js";
13
13
  import { apiRequestSafe } from "../utils/apiClient.js";
14
14
  import { AIService } from "../ai/googleService.js";
15
- import { requireApiKey, hydrateApiKeyEnv } from "../../lib/orbitalConfig.js";
16
- import { parseModelChoice } from "../../config/aiConfig.js";
17
-
15
+ import { requireGeminiApiKey } from "../../lib/orbitalConfig.js";
18
16
 
19
17
  marked.use(markedTerminal());
20
18
 
19
+ const getEnabledToolNames = () => {
20
+ return [];
21
+ };
22
+
21
23
  const getUserFromToken = async () => {
22
24
  const token = await getStoredToken();
23
25
 
@@ -42,12 +44,7 @@ const getUserFromToken = async () => {
42
44
  }
43
45
  };
44
46
 
45
- const initConversation = async (
46
- userId,
47
- conversationId = null,
48
- mode = "agent",
49
- modelDisplayName = null
50
- ) => {
47
+ const initConversation = async (userId, conversationId = null, mode = "tool") => {
51
48
  const spinner = yoctoSpinner({ text: "Loading conversation..." }).start();
52
49
 
53
50
  const result = await apiRequestSafe("/api/cli/conversations/init", {
@@ -58,14 +55,16 @@ const initConversation = async (
58
55
 
59
56
  spinner.success("Conversation Loaded");
60
57
 
61
- const modelLine = modelDisplayName
62
- ? `\n${chalk.cyan("Model: " + modelDisplayName)}`
63
- : "";
58
+ const enabledToolNames = getEnabledToolNames();
59
+ const toolsDisplay =
60
+ enabledToolNames.length > 0
61
+ ? `\n${chalk.gray("Active Tools:")} ${enabledToolNames.join(", ")}`
62
+ : `\n${chalk.gray("No tools enabled")}`;
64
63
 
65
64
  const conversationInfo = boxen(
66
65
  `${chalk.bold("Conversation")}: ${conversation.title}\n${chalk.gray(
67
66
  "ID: " + conversation.id
68
- )}\n${chalk.gray("Mode: " + conversation.mode)}${modelLine}\n${chalk.cyan(
67
+ )}\n${chalk.gray("Mode: " + conversation.mode)}${toolsDisplay}\n${chalk.cyan(
69
68
  "Working Directory: "
70
69
  )}${process.cwd()}`,
71
70
  {
@@ -89,7 +88,7 @@ const saveMessage = async (conversationId, role, content) => {
89
88
  });
90
89
  };
91
90
 
92
- const agentLoop = async (conversation, modelConfig = null) => {
91
+ const agentLoop = async (conversation) => {
93
92
  const helpBox = boxen(
94
93
  `${chalk.cyan.bold("What can the agent do?")}\n\n` +
95
94
  `${chalk.gray("• Generate complete applications from descriptions")}\n` +
@@ -114,8 +113,8 @@ const agentLoop = async (conversation, modelConfig = null) => {
114
113
 
115
114
  while (true) {
116
115
  const userInput = await text({
117
- message: chalk.magenta("Describe the application you want to build:"),
118
- placeholder: "e.g., A CLI todo app with SQLite, or a React counter app",
116
+ message: chalk.magenta("What would you like to build?"),
117
+ placeholder: "Describe your application...",
119
118
  validate(value) {
120
119
  if (!value || value.trim().length === 0) {
121
120
  return "Description cannot be empty";
@@ -150,8 +149,8 @@ const agentLoop = async (conversation, modelConfig = null) => {
150
149
  await saveMessage(conversation.id, "user", userInput);
151
150
 
152
151
  try {
153
- const aiService = new AIService(modelConfig);
154
- await requireApiKey(aiService.provider);
152
+ await requireGeminiApiKey();
153
+ const aiService = new AIService();
155
154
  const application = await generateApplicationPlan(userInput, aiService);
156
155
 
157
156
  if (!application || !Array.isArray(application.files) || application.files.length === 0) {
@@ -210,17 +209,7 @@ const agentLoop = async (conversation, modelConfig = null) => {
210
209
  }
211
210
  };
212
211
 
213
- export const startAgentChat = async (modelConfigOrConvId = null, convId = null) => {
214
- let modelConfig = null;
215
- let conversationId = null;
216
-
217
- if (typeof modelConfigOrConvId === "string") {
218
- conversationId = modelConfigOrConvId;
219
- } else if (modelConfigOrConvId && typeof modelConfigOrConvId === "object") {
220
- modelConfig = modelConfigOrConvId;
221
- conversationId = convId;
222
- }
223
-
212
+ export const startAgentChat = async (conversationId = null) => {
224
213
  try {
225
214
  intro(
226
215
  boxen(
@@ -234,10 +223,6 @@ export const startAgentChat = async (modelConfigOrConvId = null, convId = null)
234
223
  )
235
224
  );
236
225
 
237
- const { provider } = parseModelChoice(modelConfig);
238
- await hydrateApiKeyEnv(provider);
239
- const aiService = new AIService(modelConfig);
240
-
241
226
  const user = await getUserFromToken();
242
227
 
243
228
  const shouldContinue = await confirm({
@@ -252,13 +237,8 @@ export const startAgentChat = async (modelConfigOrConvId = null, convId = null)
252
237
  process.exit(0);
253
238
  }
254
239
 
255
- const conversation = await initConversation(
256
- user.id,
257
- conversationId,
258
- "agent",
259
- aiService.getDisplayName()
260
- );
261
- await agentLoop(conversation, modelConfig);
240
+ const conversation = await initConversation(user.id, conversationId);
241
+ await agentLoop(conversation);
262
242
 
263
243
  outro(chalk.green.bold("\nThanks for using Agent Mode!"));
264
244
  } catch (error) {
@@ -17,13 +17,11 @@ import {
17
17
  enableTools,
18
18
  getEnabledTools,
19
19
  getEnabledToolNames,
20
- getToolsForProvider,
21
20
  resetTools,
22
21
  } from "../../config/toolConfig.js";
23
22
  import { apiRequestSafe } from "../utils/apiClient.js";
24
23
  import { AIService } from "../ai/googleService.js";
25
- import { requireApiKey, hydrateApiKeyEnv } from "../../lib/orbitalConfig.js";
26
- import { parseModelChoice } from "../../config/aiConfig.js";
24
+ import { requireGeminiApiKey } from "../../lib/orbitalConfig.js";
27
25
 
28
26
  marked.use(
29
27
  markedTerminal({
@@ -69,7 +67,7 @@ const getUserFromToken = async () => {
69
67
  }
70
68
  };
71
69
 
72
- const selectTools = async (provider = "gemini") => {
70
+ const selectTools = async () => {
73
71
  const truncateHint = (text, maxLen = 70) => {
74
72
  if (!text) return "";
75
73
  const singleLine = String(text).replace(/\s+/g, " ").trim();
@@ -77,19 +75,10 @@ const selectTools = async (provider = "gemini") => {
77
75
  return singleLine.slice(0, Math.max(0, maxLen - 3)) + "...";
78
76
  };
79
77
 
80
- const providerTools = getToolsForProvider(provider);
81
-
82
- if (providerTools.length === 0) {
83
- console.log(
84
- chalk.yellow(`\nNo tools available for ${provider}. AI will work without tools.\n`)
85
- );
86
- enableTools([]);
87
- return [];
88
- }
89
-
90
- const toolOptions = providerTools.map((tool) => ({
78
+ const toolOptions = availableTools.map((tool) => ({
91
79
  value: tool.id,
92
80
  label: tool.name,
81
+
93
82
  hint: truncateHint(tool.description),
94
83
  }));
95
84
 
@@ -115,7 +104,7 @@ const selectTools = async (provider = "gemini") => {
115
104
  chalk.green(
116
105
  `Enabled tools:\n${selectedTools
117
106
  .map((id) => {
118
- const tool = providerTools.find((t) => t.id === id);
107
+ const tool = availableTools.find((t) => t.id === id);
119
108
  return tool ? ` • ${tool.name}` : ` • ${id}`;
120
109
  })
121
110
  .join("\n")}`
@@ -135,12 +124,7 @@ const selectTools = async (provider = "gemini") => {
135
124
  return selectedTools;
136
125
  };
137
126
 
138
- const initConversation = async (
139
- userId,
140
- conversationId = null,
141
- mode = "tool",
142
- modelDisplayName = null
143
- ) => {
127
+ const initConversation = async (userId, conversationId = null, mode = "tool") => {
144
128
  const spinner = yoctoSpinner({ text: "Loading conversation..." }).start();
145
129
  const result = await apiRequestSafe("/api/cli/conversations/init", {
146
130
  method: "POST",
@@ -158,14 +142,10 @@ const initConversation = async (
158
142
  ? `\n${chalk.gray("Active Tools:")} ${enabledToolNames.join(", ")}`
159
143
  : `\n${chalk.gray("No tools enabled")}`;
160
144
 
161
- const modelLine = modelDisplayName
162
- ? `\n${chalk.cyan("Model: " + modelDisplayName)}`
163
- : "";
164
-
165
145
  const conversationInfo = boxen(
166
146
  `${chalk.bold("Conversation")}: ${conversation.title}\n${chalk.gray(
167
147
  "ID: " + conversation.id
168
- )}\n${chalk.gray("Mode: " + conversation.mode)}${modelLine}${toolsDisplay}`,
148
+ )}\n${chalk.gray("Mode: " + conversation.mode)}${toolsDisplay}`,
169
149
  {
170
150
  padding: 1,
171
151
  margin: { top: 1, bottom: 1 },
@@ -230,22 +210,8 @@ const saveMessage = async (conversationId, role, content) => {
230
210
  });
231
211
  };
232
212
 
233
- const getAIResponse = async (conversationId, toolIds = [], modelConfig = null) => {
234
- const aiService = new AIService(modelConfig);
235
- await requireApiKey(aiService.provider);
236
-
237
- // Ensure tool state matches what the user selected
238
- resetTools();
239
- if (Array.isArray(toolIds)) enableTools(toolIds);
240
-
241
- const tools = getEnabledTools(aiService.provider);
242
- const enabledNames = getEnabledToolNames();
243
- const toolBadge =
244
- enabledNames.length > 0 ? chalk.dim(` [Tools: ${enabledNames.join(", ")}]`) : "";
245
-
246
- const spinner = yoctoSpinner({
247
- text: `${aiService.getDisplayName()} is thinking...${toolBadge}`,
248
- }).start();
213
+ const getAIResponse = async (conversationId, toolIds = []) => {
214
+ const spinner = yoctoSpinner({ text: "AI is thinking..." }).start();
249
215
  let fullResponse = "";
250
216
  const toolCallsDetected = [];
251
217
 
@@ -258,16 +224,20 @@ const getAIResponse = async (conversationId, toolIds = [], modelConfig = null) =
258
224
  const messages = Array.isArray(messageResult?.messages) ? messageResult.messages : [];
259
225
  const aiMessages = messages.map((m) => ({ role: m.role, content: m.content }));
260
226
 
227
+ // Ensure the API key is present in env before any tools are initialized.
228
+ await requireGeminiApiKey();
229
+
230
+ // Ensure tool state matches what the user selected.
231
+ resetTools();
232
+ if (Array.isArray(toolIds)) enableTools(toolIds);
233
+
234
+ const tools = getEnabledTools();
235
+ const aiService = new AIService();
261
236
  const result = await aiService.sendMessage(aiMessages, null, tools);
262
237
 
263
238
  spinner.stop();
264
239
  console.log("\n");
265
- const toolsHeader =
266
- enabledNames.length > 0 ? chalk.dim(` • Tools: ${enabledNames.join(", ")}`) : "";
267
- console.log(
268
- chalk.green.bold(`Assistant (${aiService.getDisplayName()}):`) +
269
- (toolsHeader ? ` ${toolsHeader}` : "")
270
- );
240
+ console.log(chalk.green.bold("Assistant: "));
271
241
  console.log(chalk.gray("-".repeat(60)));
272
242
 
273
243
  fullResponse = result?.content || "";
@@ -300,20 +270,12 @@ const getAIResponse = async (conversationId, toolIds = [], modelConfig = null) =
300
270
  if (result?.toolResults && result.toolResults.length > 0) {
301
271
  const toolResultBox = boxen(
302
272
  result.toolResults
303
- .map((tr) => {
304
- const output = tr.output ?? tr.result;
305
- const resStr =
306
- output === undefined
307
- ? "Completed"
308
- : typeof output === "object"
309
- ? JSON.stringify(output, null, 2)
310
- : String(output);
311
- const truncated =
312
- resStr.length > 200 ? `${resStr.slice(0, 200)}...` : resStr;
313
- return `${chalk.green("✓ Tool:")} ${tr.toolName}\n${chalk.gray(
314
- "Result:"
315
- )} ${truncated}`;
316
- })
273
+ .map(
274
+ (tr) =>
275
+ `${chalk.green("✓ Tool:")} ${tr.toolName}\n${chalk.gray(
276
+ "Result:"
277
+ )} ${String(JSON.stringify(tr.result, null, 2)).slice(0, 200)}...`
278
+ )
317
279
  .join("\n\n"),
318
280
  {
319
281
  padding: 1,
@@ -338,7 +300,7 @@ const getAIResponse = async (conversationId, toolIds = [], modelConfig = null) =
338
300
  }
339
301
  };
340
302
 
341
- const chatLoop = async (conversation, selectedToolIds = [], modelConfig = null) => {
303
+ const chatLoop = async (conversation, selectedToolIds = []) => {
342
304
  const enabledToolNames = getEnabledToolNames();
343
305
 
344
306
  const helpText = [
@@ -346,29 +308,28 @@ const chatLoop = async (conversation, selectedToolIds = [], modelConfig = null)
346
308
  `• AI has access to: ${
347
309
  enabledToolNames.length > 0 ? enabledToolNames.join(", ") : "No tools"
348
310
  }`,
349
- "• Tools are invoked automatically by AI when needed",
350
- "• Markdown formatting is supported",
351
311
  '• Type "exit" to end conversation',
352
312
  "• Press Ctrl+C to quit anytime",
353
- ].join("\n");
354
-
355
- const helpBox = boxen(chalk.gray(helpText), {
356
- padding: 1,
357
- margin: { bottom: 1 },
358
- borderStyle: "round",
359
- borderColor: "gray",
360
- dimBorder: true,
361
- });
362
- console.log(helpBox);
313
+ ]
314
+ .map((line) => chalk.gray(line))
315
+ .join("\n");
316
+
317
+ console.log(
318
+ boxen(helpText, {
319
+ padding: 1,
320
+ margin: { bottom: 1 },
321
+ borderStyle: "round",
322
+ borderColor: "gray",
323
+ dimBorder: true,
324
+ })
325
+ );
363
326
 
364
327
  while (true) {
365
328
  const userInput = await text({
366
329
  message: chalk.blue("Your message"),
367
- placeholder: "Ask something that requires tools...",
330
+ placeholder: "Type your message...",
368
331
  validate(value) {
369
- if (!value || value.trim().length === 0) {
370
- return "Message cannot be empty";
371
- }
332
+ if (!value || value.trim().length === 0) return "Message cannot be empty";
372
333
  },
373
334
  });
374
335
 
@@ -413,11 +374,7 @@ const chatLoop = async (conversation, selectedToolIds = [], modelConfig = null)
413
374
  { method: "GET" }
414
375
  );
415
376
 
416
- const aiResponse = await getAIResponse(
417
- conversation.id,
418
- selectedToolIds,
419
- modelConfig
420
- );
377
+ const aiResponse = await getAIResponse(conversation.id, selectedToolIds);
421
378
  await saveMessage(conversation.id, "assistant", aiResponse);
422
379
 
423
380
  await updateConversationTitle(
@@ -428,17 +385,7 @@ const chatLoop = async (conversation, selectedToolIds = [], modelConfig = null)
428
385
  }
429
386
  };
430
387
 
431
- export const startToolChat = async (modelConfigOrConvId = null, convId = null) => {
432
- let modelConfig = null;
433
- let conversationId = null;
434
-
435
- if (typeof modelConfigOrConvId === "string") {
436
- conversationId = modelConfigOrConvId;
437
- } else if (modelConfigOrConvId && typeof modelConfigOrConvId === "object") {
438
- modelConfig = modelConfigOrConvId;
439
- conversationId = convId;
440
- }
441
-
388
+ export const startToolChat = async (conversationId) => {
442
389
  try {
443
390
  intro(
444
391
  boxen(chalk.bold.cyan("Orbital AI - Tool Calling Mode"), {
@@ -448,22 +395,13 @@ export const startToolChat = async (modelConfigOrConvId = null, convId = null) =
448
395
  })
449
396
  );
450
397
 
451
- const { provider } = parseModelChoice(modelConfig);
452
- await hydrateApiKeyEnv(provider);
453
- const aiService = new AIService(modelConfig);
454
-
455
398
  const user = await getUserFromToken();
456
399
 
457
- const selectedToolIds = await selectTools(aiService.provider);
400
+ const selectedToolIds = await selectTools();
458
401
 
459
- const conversation = await initConversation(
460
- user.id,
461
- conversationId,
462
- "tool",
463
- aiService.getDisplayName()
464
- );
402
+ const conversation = await initConversation(user.id, conversationId, "tool");
465
403
 
466
- await chatLoop(conversation, selectedToolIds, modelConfig);
404
+ await chatLoop(conversation, selectedToolIds);
467
405
 
468
406
  resetTools();
469
407
  outro(chalk.green("Thanks for using tools"));