@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.
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
57
|
+
const result = await streamText(streamConfig);
|
|
33
58
|
|
|
34
|
-
|
|
59
|
+
let fullResponse = "";
|
|
35
60
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
61
|
+
for await (const chunk of result.textStream) {
|
|
62
|
+
fullResponse += chunk;
|
|
63
|
+
if (onChunk) onChunk(chunk);
|
|
64
|
+
}
|
|
40
65
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
|
package/server/src/cli/main.js
CHANGED
|
@@ -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(
|
|
33
|
+
program.version(packageJson.version).
|
|
33
34
|
description("Orbital CLI - A CLI Based AI Tool").
|
|
34
35
|
addCommand(login).
|
|
35
36
|
addCommand(logout).
|