@dubeyvishal/orbital-cli 1.6.11 → 1.6.13

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dubeyvishal/orbital-cli",
3
- "version": "1.6.11",
3
+ "version": "1.6.13",
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",
@@ -4,6 +4,24 @@ import { config } from "../../config/googleConfig.js";
4
4
  import chalk from "chalk";
5
5
  import { requireGeminiApiKeySync } from "../../lib/orbitalConfig.js";
6
6
 
7
+ const MAX_RETRIES = 3;
8
+ const BASE_DELAY_MS = 5000; // 5 seconds
9
+
10
+ const isRateLimitError = (error) => {
11
+ if (!error) return false;
12
+ const message = (error?.message || "").toLowerCase();
13
+ const statusCode = error?.status || error?.statusCode || error?.data?.code;
14
+ return (
15
+ statusCode === 429 ||
16
+ message.includes("429") ||
17
+ message.includes("resource_exhausted") ||
18
+ message.includes("rate limit") ||
19
+ message.includes("quota")
20
+ );
21
+ };
22
+
23
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
24
+
7
25
  export class AIService {
8
26
  constructor() {
9
27
  const apiKey = requireGeminiApiKeySync();
@@ -14,69 +32,113 @@ export class AIService {
14
32
  }
15
33
 
16
34
  async sendMessage(messages, onChunk, tools = undefined, onToolCall = null) {
17
- try {
18
- const streamConfig = {
19
- model: this.model,
20
- messages,
21
- temperature: config.temperature,
22
- };
23
-
24
- if (tools && Object.keys(tools).length > 0) {
25
- streamConfig.tools = tools;
26
- streamConfig.maxSteps = 5;
27
- console.log(
28
- chalk.gray(`[DEBUG] Tools enabled: ${Object.keys(tools).join(", ")}`)
29
- );
30
- }
35
+ let lastError = null;
36
+
37
+ for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
38
+ try {
39
+ const streamConfig = {
40
+ model: this.model,
41
+ messages,
42
+ temperature: config.temperature,
43
+ };
44
+
45
+ if (tools && Object.keys(tools).length > 0) {
46
+ streamConfig.tools = tools;
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
+ }
55
+ }
31
56
 
32
- const result = await streamText(streamConfig);
57
+ const result = await streamText(streamConfig);
33
58
 
34
- let fullResponse = "";
59
+ let fullResponse = "";
35
60
 
36
- for await (const chunk of result.textStream) {
37
- fullResponse += chunk;
38
- if (onChunk) onChunk(chunk);
39
- }
61
+ for await (const chunk of result.textStream) {
62
+ fullResponse += chunk;
63
+ if (onChunk) onChunk(chunk);
64
+ }
40
65
 
41
- const toolCalls = [];
42
- const toolResults = [];
43
-
44
- const steps = await Promise.resolve(result.steps);
45
-
46
- if (Array.isArray(steps)) {
47
- for (const step of steps) {
48
- if (
49
- step?.toolCalls &&
50
- Array.isArray(step.toolCalls) &&
51
- step.toolCalls.length > 0
52
- ) {
53
- for (const toolCall of step.toolCalls) {
54
- toolCalls.push(toolCall);
55
- if (onToolCall) onToolCall(toolCall);
66
+ const toolCalls = [];
67
+ const toolResults = [];
68
+
69
+ const steps = await Promise.resolve(result.steps);
70
+
71
+ if (Array.isArray(steps)) {
72
+ for (const step of steps) {
73
+ if (
74
+ step?.toolCalls &&
75
+ Array.isArray(step.toolCalls) &&
76
+ step.toolCalls.length > 0
77
+ ) {
78
+ for (const toolCall of step.toolCalls) {
79
+ toolCalls.push(toolCall);
80
+ if (onToolCall) onToolCall(toolCall);
81
+ }
56
82
  }
57
- }
58
83
 
59
- if (
60
- step?.toolResults &&
61
- Array.isArray(step.toolResults) &&
62
- step.toolResults.length > 0
63
- ) {
64
- toolResults.push(...step.toolResults);
84
+ if (
85
+ step?.toolResults &&
86
+ Array.isArray(step.toolResults) &&
87
+ step.toolResults.length > 0
88
+ ) {
89
+ toolResults.push(...step.toolResults);
90
+ }
65
91
  }
66
92
  }
67
- }
68
93
 
69
- return {
70
- content: fullResponse,
71
- finishReason: result.finishReason,
72
- usage: result.usage,
73
- toolCalls,
74
- toolResults,
75
- steps,
76
- };
77
- } catch (error) {
78
- console.error(chalk.red("AI Service Error:"), error?.message || error);
79
- throw error;
94
+ return {
95
+ content: fullResponse,
96
+ finishReason: result.finishReason,
97
+ usage: result.usage,
98
+ toolCalls,
99
+ toolResults,
100
+ steps,
101
+ };
102
+ } catch (error) {
103
+ lastError = error;
104
+
105
+ if (isRateLimitError(error) && attempt < MAX_RETRIES) {
106
+ const delayMs = BASE_DELAY_MS * Math.pow(2, attempt - 1);
107
+ const delaySec = Math.round(delayMs / 1000);
108
+ console.log(
109
+ chalk.yellow(
110
+ `\n⚠ Rate limit hit (429). Retrying in ${delaySec}s... (attempt ${attempt}/${MAX_RETRIES})`
111
+ )
112
+ );
113
+ await sleep(delayMs);
114
+ continue;
115
+ }
116
+
117
+ // Provide an actionable message for rate-limit errors.
118
+ if (isRateLimitError(error)) {
119
+ console.error(
120
+ chalk.red(
121
+ "\n✖ Gemini API quota exhausted. All retry attempts failed."
122
+ )
123
+ );
124
+ console.error(
125
+ chalk.yellow(
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"
131
+ )
132
+ );
133
+ } else {
134
+ console.error(
135
+ chalk.red("AI Service Error:"),
136
+ error?.message || error
137
+ );
138
+ }
139
+
140
+ throw error;
141
+ }
80
142
  }
81
143
  }
82
144
 
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  import "../config/env.js";
4
4
  import chalk from "chalk";
@@ -12,6 +12,7 @@ import {setkey} from "./commands/config/setkey.js"
12
12
  import {launch} from "./commands/General/openApp.js"
13
13
  import {search} from "./commands/General/searchYoutube.js"
14
14
  import {play} from "./commands/General/playSong.js"
15
+ import {packageJson} from "./package.json";
15
16
 
16
17
  const main = async()=>{
17
18
 
@@ -29,7 +30,7 @@ const main = async()=>{
29
30
 
30
31
 
31
32
 
32
- program.version("0.0.1").
33
+ program.version(packageJson.version).
33
34
  description("Orbital CLI - A CLI Based AI Tool").
34
35
  addCommand(login).
35
36
  addCommand(logout).
@@ -2,5 +2,5 @@ import "./env.js";
2
2
 
3
3
  export const config = {
4
4
  googleApiKey : process.env.GOOGLE_GENERATIVE_AI_API_KEY || "",
5
- model : process.env.ORBITAL_MODEL || "gemini-2.5-flash"
6
- }
5
+ model : process.env.ORBITAL_MODEL || "gemini-3.5-flash-lite"
6
+ }