@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 +3 -3
- package/package.json +2 -4
- package/server/src/cli/ai/googleService.js +30 -80
- package/server/src/cli/chat/chat-with-ai-agent.js +20 -40
- package/server/src/cli/chat/chat-with-ai-tools.js +46 -108
- package/server/src/cli/chat/chat-with-ai.js +197 -232
- package/server/src/cli/commands/ai/wakeUp.js +78 -139
- package/server/src/cli/commands/auth/login.js +7 -1
- package/server/src/cli/commands/config/setkey.js +6 -57
- package/server/src/cli/main.js +1 -1
- package/server/src/config/googleConfig.js +1 -1
- package/server/src/config/toolConfig.js +44 -25
- package/server/src/controllers/aiController.js +6 -10
- package/server/src/lib/credentialStore.js +14 -47
- package/server/src/lib/orbitalConfig.js +38 -144
- package/server/src/service/aiService.js +2 -2
- package/server/src/config/aiConfig.js +0 -159
|
@@ -1,145 +1,84 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import {
|
|
3
|
-
import yoctoSpinner
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
2
|
+
import {Command} from "commander";
|
|
3
|
+
import yoctoSpinner from "yocto-spinner";
|
|
4
|
+
import {getStoredToken} from "../../../lib/token.js"
|
|
5
|
+
import {select} from "@clack/prompts";
|
|
6
|
+
import {startChat} from "../../../cli/chat/chat-with-ai.js";
|
|
7
|
+
import {startToolChat} from "../../../cli/chat/chat-with-ai-tools.js";
|
|
8
|
+
import {startAgentChat} from "../../../cli/chat/chat-with-ai-agent.js";
|
|
9
9
|
import { apiRequestSafe } from "../../utils/apiClient.js";
|
|
10
|
-
import {
|
|
11
|
-
getApiKey,
|
|
12
|
-
setApiKey,
|
|
13
|
-
getSelectedModel,
|
|
14
|
-
saveSelectedModel,
|
|
15
|
-
} from "../../../lib/orbitalConfig.js";
|
|
16
|
-
import {
|
|
17
|
-
AI_PROVIDERS,
|
|
18
|
-
getModelSelectOptions,
|
|
19
|
-
parseModelChoice,
|
|
20
|
-
getModelDisplayName,
|
|
21
|
-
} from "../../../config/aiConfig.js";
|
|
10
|
+
import { requireGeminiApiKey } from "../../../lib/orbitalConfig.js";
|
|
22
11
|
|
|
23
|
-
const wakeUpAction = async () => {
|
|
24
|
-
const token = await getStoredToken();
|
|
25
|
-
if (!token?.access_token) {
|
|
26
|
-
console.log(chalk.red("Not Authenticated. Please run 'orbital login' first."));
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
12
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
user = result?.user;
|
|
37
|
-
} finally {
|
|
38
|
-
spinner.stop();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (!user) {
|
|
42
|
-
console.log(chalk.red("User not found. Please log in again with 'orbital login'."));
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
console.log(chalk.green(`Welcome back, ${user.name}! \n`));
|
|
47
|
-
|
|
48
|
-
// 1. Ask user to select the AI model FIRST
|
|
49
|
-
const savedModel = await getSelectedModel();
|
|
50
|
-
const modelOptions = getModelSelectOptions();
|
|
51
|
-
const defaultModelValue = `${savedModel.provider}:${savedModel.model}`;
|
|
52
|
-
|
|
53
|
-
const selectedModelChoice = await select({
|
|
54
|
-
message: "Select an AI Model:",
|
|
55
|
-
options: modelOptions,
|
|
56
|
-
initialValue: modelOptions.some((o) => o.value === defaultModelValue)
|
|
57
|
-
? defaultModelValue
|
|
58
|
-
: undefined,
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
if (isCancel(selectedModelChoice)) {
|
|
62
|
-
cancel("Model selection cancelled.");
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const { provider, model } = parseModelChoice(selectedModelChoice);
|
|
67
|
-
await saveSelectedModel({ provider, model });
|
|
68
|
-
|
|
69
|
-
// 2. Ensure API key is configured for the chosen model/provider
|
|
70
|
-
let apiKey = await getApiKey(provider);
|
|
71
|
-
if (!apiKey) {
|
|
72
|
-
const provInfo = AI_PROVIDERS[provider];
|
|
73
|
-
console.log(
|
|
74
|
-
chalk.yellow(
|
|
75
|
-
`\n${provInfo?.name || provider} API key is required. (Obtain one at: ${provInfo?.docsUrl || "provider portal"})`
|
|
76
|
-
)
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
const enteredKey = await password({
|
|
80
|
-
message: `Enter your ${provInfo?.name || provider} API key:`,
|
|
81
|
-
validate(value) {
|
|
82
|
-
if (!value || !value.trim()) return "API key cannot be empty";
|
|
83
|
-
},
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
if (isCancel(enteredKey)) {
|
|
87
|
-
cancel("Operation cancelled.");
|
|
88
|
-
return;
|
|
13
|
+
const wakeUpAction = async()=>{
|
|
14
|
+
try {
|
|
15
|
+
await requireGeminiApiKey();
|
|
16
|
+
} catch {
|
|
17
|
+
console.log(chalk.red("Gemini API key not set. Run: orbital set-key <API_KEY>"));
|
|
18
|
+
return;
|
|
89
19
|
}
|
|
90
20
|
|
|
91
|
-
await
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
21
|
+
const token = await getStoredToken();
|
|
22
|
+
if(!token?.access_token){
|
|
23
|
+
console.log(chalk.red("Not Authenticated. please login"))
|
|
24
|
+
return ;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const spinner = yoctoSpinner({text: "Fetching user information ..."})
|
|
28
|
+
spinner.start()
|
|
29
|
+
|
|
30
|
+
let user;
|
|
31
|
+
try{
|
|
32
|
+
const result = await apiRequestSafe("/api/cli/me");
|
|
33
|
+
user = result?.user;
|
|
34
|
+
}
|
|
35
|
+
finally{
|
|
36
|
+
spinner.stop();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if(!user){
|
|
40
|
+
console.log(chalk.red("User not found."))
|
|
41
|
+
return ;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log(chalk.green(`Welcome back, ${user.name}! \n`));
|
|
45
|
+
|
|
46
|
+
const choice = await select({
|
|
47
|
+
message : "Select an Option",
|
|
48
|
+
options : [
|
|
49
|
+
{
|
|
50
|
+
value : "chat",
|
|
51
|
+
label: "Chat",
|
|
52
|
+
hint : "Simple chat with AI"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
value : "tool",
|
|
56
|
+
label: "Tool Calling",
|
|
57
|
+
hint : "Chat with tools (Google Search , Code Execution"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
value : "agent",
|
|
61
|
+
label: "Agentic Mode",
|
|
62
|
+
hint : "Advanced AI Agent"
|
|
63
|
+
},
|
|
64
|
+
]
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
switch(choice){
|
|
68
|
+
case "chat":
|
|
69
|
+
await startChat("chat");
|
|
70
|
+
break ;
|
|
71
|
+
case "tool":
|
|
72
|
+
await startToolChat();
|
|
73
|
+
break ;
|
|
74
|
+
case "agent":
|
|
75
|
+
await startAgentChat();
|
|
76
|
+
break ;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const wakeUp = new Command("wakeup").
|
|
81
|
+
description("Wake up the AI").
|
|
82
|
+
alias("wake-up").
|
|
83
|
+
alias("wakup").
|
|
84
|
+
action(wakeUpAction)
|
|
@@ -11,6 +11,7 @@ import { fileURLToPath } from "url";
|
|
|
11
11
|
import { getStoredToken, isTokenExpired, storeToken ,TOKEN_FILE } from "../../../lib/token.js";
|
|
12
12
|
import { API_BASE } from "../../../config/api.js";
|
|
13
13
|
import { apiRequestSafe } from "../../utils/apiClient.js";
|
|
14
|
+
import { requireGeminiApiKey } from "../../../lib/orbitalConfig.js";
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -92,7 +93,12 @@ const resolveClientId = async (cliClientId) => {
|
|
|
92
93
|
|
|
93
94
|
|
|
94
95
|
export const loginAction = async (cmdOptions) => {
|
|
95
|
-
|
|
96
|
+
try {
|
|
97
|
+
await requireGeminiApiKey();
|
|
98
|
+
} catch {
|
|
99
|
+
console.log(chalk.red("Gemini API key not set. Run: orbital set-key <API_KEY>"));
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
96
102
|
|
|
97
103
|
const schema = z.object({
|
|
98
104
|
serverUrl: z.string().optional(),
|
|
@@ -1,58 +1,12 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import chalk from "chalk";
|
|
3
|
-
import {
|
|
4
|
-
import { setApiKey, normalizeProviderName } from "../../../lib/orbitalConfig.js";
|
|
3
|
+
import { setGeminiApiKey } from "../../../lib/orbitalConfig.js";
|
|
5
4
|
import { getCredentialServiceName } from "../../../lib/credentialStore.js";
|
|
6
|
-
import { AI_PROVIDERS } from "../../../config/aiConfig.js";
|
|
7
5
|
|
|
8
|
-
const setKeyAction = async (
|
|
6
|
+
const setKeyAction = async (apiKey) => {
|
|
9
7
|
try {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
// Interactive mode if key was not supplied via command line argument
|
|
14
|
-
if (!apiKey) {
|
|
15
|
-
if (!provider) {
|
|
16
|
-
const provChoice = await select({
|
|
17
|
-
message: "Select AI Provider to configure API key for:",
|
|
18
|
-
options: [
|
|
19
|
-
{ value: "gemini", label: "Google Gemini", hint: "AI Studio API key" },
|
|
20
|
-
{ value: "openai", label: "OpenAI", hint: "platform.openai.com key" },
|
|
21
|
-
{ value: "grok", label: "Grok (xAI)", hint: "console.x.ai key" },
|
|
22
|
-
],
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
if (isCancel(provChoice)) {
|
|
26
|
-
cancel("Operation cancelled.");
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
provider = provChoice;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const provInfo = AI_PROVIDERS[normalizeProviderName(provider)];
|
|
33
|
-
const enteredKey = await password({
|
|
34
|
-
message: `Enter your ${provInfo?.name || provider} API key:`,
|
|
35
|
-
validate(value) {
|
|
36
|
-
if (!value || !value.trim()) return "API key cannot be empty";
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
if (isCancel(enteredKey)) {
|
|
41
|
-
cancel("Operation cancelled.");
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
apiKey = enteredKey;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const norm = normalizeProviderName(provider || "gemini");
|
|
49
|
-
const provInfo = AI_PROVIDERS[norm];
|
|
50
|
-
|
|
51
|
-
await setApiKey(norm, apiKey);
|
|
52
|
-
|
|
53
|
-
console.log(
|
|
54
|
-
chalk.green(`\n✔ ${provInfo?.name || norm} API key saved successfully.`)
|
|
55
|
-
);
|
|
8
|
+
await setGeminiApiKey(apiKey);
|
|
9
|
+
console.log(chalk.green("Gemini API key saved."));
|
|
56
10
|
console.log(
|
|
57
11
|
chalk.gray(
|
|
58
12
|
`Stored securely in your OS credential manager (service: ${getCredentialServiceName()}).`
|
|
@@ -65,13 +19,8 @@ const setKeyAction = async (apiKeyArg, cmdOptions) => {
|
|
|
65
19
|
};
|
|
66
20
|
|
|
67
21
|
export const setkey = new Command("set-key")
|
|
68
|
-
.description("Store your
|
|
69
|
-
.argument("
|
|
70
|
-
.option(
|
|
71
|
-
"-p, --provider <provider>",
|
|
72
|
-
"AI provider: gemini (default), openai, or grok",
|
|
73
|
-
"gemini"
|
|
74
|
-
)
|
|
22
|
+
.description("Store your Gemini API key securely (keytar)")
|
|
23
|
+
.argument("<API_KEY>", "Your Gemini API key")
|
|
75
24
|
.alias("set")
|
|
76
25
|
.alias("setkey")
|
|
77
26
|
.action(setKeyAction);
|
package/server/src/cli/main.js
CHANGED
|
@@ -13,10 +13,10 @@ 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
15
|
import { createRequire } from "module";
|
|
16
|
+
|
|
16
17
|
const require = createRequire(import.meta.url);
|
|
17
18
|
const packageJson = require("../../../package.json");
|
|
18
19
|
|
|
19
|
-
|
|
20
20
|
const main = async()=>{
|
|
21
21
|
|
|
22
22
|
console.log(
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
import { google } from "@ai-sdk/google";
|
|
2
2
|
import chalk from "chalk";
|
|
3
|
-
import {
|
|
4
|
-
normalizeProviderName,
|
|
5
|
-
requireApiKeySync,
|
|
6
|
-
hasApiKeySync,
|
|
7
|
-
} from "../lib/orbitalConfig.js";
|
|
3
|
+
import { requireGeminiApiKeySync } from "../lib/orbitalConfig.js";
|
|
8
4
|
|
|
9
5
|
export const availableTools = [
|
|
10
|
-
// Google Gemini Native Tools
|
|
11
6
|
{
|
|
12
7
|
id: "google_search",
|
|
13
8
|
name: "Google Search",
|
|
14
9
|
description:
|
|
15
10
|
"Access the latest information using Google Search. Useful for current events, news, and real-time information",
|
|
16
|
-
provider: "gemini",
|
|
17
11
|
getTool: () => google.tools.googleSearch({}),
|
|
18
12
|
enabled: false,
|
|
19
13
|
},
|
|
@@ -22,7 +16,6 @@ export const availableTools = [
|
|
|
22
16
|
name: "Code Execution",
|
|
23
17
|
description:
|
|
24
18
|
"Generate and execute Python code to perform calculations, solve problems or provide accurate information",
|
|
25
|
-
provider: "gemini",
|
|
26
19
|
getTool: () => google.tools.codeExecution({}),
|
|
27
20
|
enabled: false,
|
|
28
21
|
},
|
|
@@ -31,41 +24,45 @@ export const availableTools = [
|
|
|
31
24
|
name: "URL Context",
|
|
32
25
|
description:
|
|
33
26
|
"Provide specific URLs that you want the model to analyse directly from the prompt. Supports up to 20 URLs per request.",
|
|
34
|
-
provider: "gemini",
|
|
35
27
|
getTool: () => google.tools.urlContext({}),
|
|
36
28
|
enabled: false,
|
|
37
29
|
},
|
|
38
30
|
];
|
|
39
31
|
|
|
40
|
-
export const
|
|
41
|
-
const norm = normalizeProviderName(provider);
|
|
42
|
-
return availableTools.filter(
|
|
43
|
-
(tool) => tool.provider === "all" || tool.provider === norm
|
|
44
|
-
);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export const getEnabledTools = (provider = "gemini") => {
|
|
48
|
-
const norm = normalizeProviderName(provider);
|
|
32
|
+
export const getEnabledTools = () => {
|
|
49
33
|
const tools = {};
|
|
50
34
|
|
|
51
35
|
try {
|
|
52
|
-
const
|
|
36
|
+
const enabledToolCount = availableTools.filter((t) => t.enabled).length;
|
|
37
|
+
if (enabledToolCount > 0 && !process.env.GOOGLE_GENERATIVE_AI_API_KEY) {
|
|
38
|
+
|
|
39
|
+
requireGeminiApiKeySync();
|
|
40
|
+
}
|
|
53
41
|
|
|
54
|
-
for (const toolConfig of
|
|
42
|
+
for (const toolConfig of availableTools) {
|
|
55
43
|
if (toolConfig.enabled) {
|
|
56
|
-
if (toolConfig.provider === "gemini" && !hasApiKeySync("gemini")) {
|
|
57
|
-
requireApiKeySync("gemini");
|
|
58
|
-
}
|
|
59
44
|
tools[toolConfig.id] = toolConfig.getTool();
|
|
60
45
|
}
|
|
61
46
|
}
|
|
62
47
|
|
|
48
|
+
if (Object.keys(tools).length > 0) {
|
|
49
|
+
console.log(
|
|
50
|
+
chalk.gray(`[DEBUG] Enabled tools: ${Object.keys(tools).join(", ")}`)
|
|
51
|
+
);
|
|
52
|
+
} else {
|
|
53
|
+
console.log(chalk.yellow(`[DEBUG] No tools enabled`));
|
|
54
|
+
}
|
|
55
|
+
|
|
63
56
|
return Object.keys(tools).length > 0 ? tools : undefined;
|
|
64
57
|
} catch (error) {
|
|
65
58
|
console.error(
|
|
66
59
|
chalk.red(`[ERROR] Failed to initialize tools:`),
|
|
67
60
|
error?.message || error
|
|
68
61
|
);
|
|
62
|
+
console.error(
|
|
63
|
+
chalk.yellow(`Make sure you have @ai-sdk/google version 2.0+ installed`)
|
|
64
|
+
);
|
|
65
|
+
console.error(chalk.yellow(`Run: npm install @ai-sdk/google@latest`));
|
|
69
66
|
return undefined;
|
|
70
67
|
}
|
|
71
68
|
};
|
|
@@ -75,27 +72,49 @@ export const toggleTool = (toolId) => {
|
|
|
75
72
|
|
|
76
73
|
if (tool) {
|
|
77
74
|
tool.enabled = !tool.enabled;
|
|
75
|
+
console.log(
|
|
76
|
+
chalk.gray(`[DEBUG] Tool ${toolId} toggled to ${tool.enabled}`)
|
|
77
|
+
);
|
|
78
78
|
return tool.enabled;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
console.log(chalk.red(`[DEBUG] Tool ${toolId} not found`));
|
|
81
82
|
return false;
|
|
82
83
|
};
|
|
83
84
|
|
|
84
85
|
export const toogleTool = toggleTool;
|
|
85
86
|
|
|
86
87
|
export const enableTools = (toolIds = []) => {
|
|
88
|
+
console.log(chalk.gray(`[DEBUG] enableTools called with:`), toolIds);
|
|
89
|
+
|
|
87
90
|
availableTools.forEach((tool) => {
|
|
91
|
+
const wasEnabled = tool.enabled;
|
|
88
92
|
tool.enabled = toolIds.includes(tool.id);
|
|
93
|
+
|
|
94
|
+
if (tool.enabled !== wasEnabled) {
|
|
95
|
+
console.log(
|
|
96
|
+
chalk.gray(`[DEBUG] ${tool.id}: ${wasEnabled} -> ${tool.enabled}`)
|
|
97
|
+
);
|
|
98
|
+
}
|
|
89
99
|
});
|
|
100
|
+
|
|
101
|
+
const enabledCount = availableTools.filter((t) => t.enabled).length;
|
|
102
|
+
console.log(
|
|
103
|
+
chalk.gray(
|
|
104
|
+
`[DEBUG] Total tools enabled: ${enabledCount} / ${availableTools.length}`
|
|
105
|
+
)
|
|
106
|
+
);
|
|
90
107
|
};
|
|
91
108
|
|
|
92
109
|
export const getEnabledToolNames = () => {
|
|
93
|
-
|
|
110
|
+
const names = availableTools.filter((t) => t.enabled).map((t) => t.name);
|
|
111
|
+
console.log(chalk.gray(`[DEBUG] getEnabledToolNames returning:`), names);
|
|
112
|
+
return names;
|
|
94
113
|
};
|
|
95
114
|
|
|
96
115
|
export const resetTools = () => {
|
|
97
116
|
availableTools.forEach((tool) => {
|
|
98
117
|
tool.enabled = false;
|
|
99
118
|
});
|
|
119
|
+
console.log(chalk.gray(`[DEBUG] All tools have been reset (disabled)`));
|
|
100
120
|
};
|
|
101
|
-
|
|
@@ -7,7 +7,7 @@ const chatService = new ChatService();
|
|
|
7
7
|
|
|
8
8
|
export const respond = async (req, res, next) => {
|
|
9
9
|
try {
|
|
10
|
-
const { conversationId, mode, toolIds
|
|
10
|
+
const { conversationId, mode, toolIds } = req.body || {};
|
|
11
11
|
|
|
12
12
|
if (!conversationId) {
|
|
13
13
|
return res.status(400).json({ error: "conversationId is required" });
|
|
@@ -16,18 +16,16 @@ export const respond = async (req, res, next) => {
|
|
|
16
16
|
const messages = await chatService.getMessages(conversationId);
|
|
17
17
|
const aiMessages = chatService.formatMessageForAI(messages);
|
|
18
18
|
|
|
19
|
-
const modelConfig = provider || model ? { provider, model } : null;
|
|
20
|
-
const aiService = getAIService(modelConfig);
|
|
21
|
-
|
|
22
19
|
let tools;
|
|
23
20
|
if (mode === "tool") {
|
|
24
21
|
resetTools();
|
|
25
22
|
if (Array.isArray(toolIds)) {
|
|
26
23
|
enableTools(toolIds);
|
|
27
24
|
}
|
|
28
|
-
tools = getEnabledTools(
|
|
25
|
+
tools = getEnabledTools();
|
|
29
26
|
}
|
|
30
27
|
|
|
28
|
+
const aiService = getAIService();
|
|
31
29
|
const result = await aiService.sendMessage(aiMessages, null, tools);
|
|
32
30
|
|
|
33
31
|
await chatService.addMessage(conversationId, "assistant", result.content);
|
|
@@ -36,7 +34,6 @@ export const respond = async (req, res, next) => {
|
|
|
36
34
|
content: result.content,
|
|
37
35
|
toolCalls: result.toolCalls || [],
|
|
38
36
|
toolResults: result.toolResults || [],
|
|
39
|
-
model: aiService.getDisplayName(),
|
|
40
37
|
});
|
|
41
38
|
} catch (error) {
|
|
42
39
|
return next(error);
|
|
@@ -45,17 +42,16 @@ export const respond = async (req, res, next) => {
|
|
|
45
42
|
|
|
46
43
|
export const generateAgentPlan = async (req, res, next) => {
|
|
47
44
|
try {
|
|
48
|
-
const { description
|
|
45
|
+
const { description } = req.body || {};
|
|
49
46
|
|
|
50
47
|
if (!description || typeof description !== "string") {
|
|
51
48
|
return res.status(400).json({ error: "description is required" });
|
|
52
49
|
}
|
|
53
50
|
|
|
54
|
-
const
|
|
55
|
-
const aiService = getAIService(modelConfig);
|
|
51
|
+
const aiService = getAIService();
|
|
56
52
|
const application = await generateApplicationPlan(description, aiService);
|
|
57
53
|
|
|
58
|
-
return res.json({ application
|
|
54
|
+
return res.json({ application });
|
|
59
55
|
} catch (error) {
|
|
60
56
|
return next(error);
|
|
61
57
|
}
|
|
@@ -16,65 +16,32 @@ const loadKeytar = async () => {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
export const getCredentialServiceName = () => ORBITAL_KEYTAR_SERVICE;
|
|
19
|
-
export const getApiKeyAccountName = (
|
|
20
|
-
const p = (provider || "gemini").toLowerCase().trim();
|
|
21
|
-
if (p === "google" || p === "gemini") return "api-key-gemini";
|
|
22
|
-
if (p === "openai") return "api-key-openai";
|
|
23
|
-
if (p === "xai" || p === "grok") return "api-key-grok";
|
|
24
|
-
return `api-key-${p}`;
|
|
25
|
-
};
|
|
19
|
+
export const getApiKeyAccountName = () => ORBITAL_API_KEY_ACCOUNT;
|
|
26
20
|
|
|
27
|
-
export const getStoredApiKey = async (
|
|
21
|
+
export const getStoredApiKey = async () => {
|
|
28
22
|
const keytar = await loadKeytar();
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const p = (provider || "gemini").toLowerCase().trim();
|
|
34
|
-
if (!value && (p === "gemini" || p === "google")) {
|
|
35
|
-
value = await keytar.getPassword(
|
|
36
|
-
ORBITAL_KEYTAR_SERVICE,
|
|
37
|
-
ORBITAL_API_KEY_ACCOUNT
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
23
|
+
const value = await keytar.getPassword(
|
|
24
|
+
ORBITAL_KEYTAR_SERVICE,
|
|
25
|
+
ORBITAL_API_KEY_ACCOUNT
|
|
26
|
+
);
|
|
41
27
|
return typeof value === "string" ? value.trim() : "";
|
|
42
28
|
};
|
|
43
29
|
|
|
44
|
-
export const storeApiKey = async (apiKey
|
|
30
|
+
export const storeApiKey = async (apiKey) => {
|
|
45
31
|
const trimmed = typeof apiKey === "string" ? apiKey.trim() : "";
|
|
46
32
|
if (!trimmed) throw new Error("API key is required");
|
|
47
33
|
|
|
48
34
|
const keytar = await loadKeytar();
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (p === "gemini" || p === "google") {
|
|
55
|
-
await keytar.setPassword(
|
|
56
|
-
ORBITAL_KEYTAR_SERVICE,
|
|
57
|
-
ORBITAL_API_KEY_ACCOUNT,
|
|
58
|
-
trimmed
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
35
|
+
await keytar.setPassword(
|
|
36
|
+
ORBITAL_KEYTAR_SERVICE,
|
|
37
|
+
ORBITAL_API_KEY_ACCOUNT,
|
|
38
|
+
trimmed
|
|
39
|
+
);
|
|
62
40
|
return true;
|
|
63
41
|
};
|
|
64
42
|
|
|
65
|
-
export const deleteStoredApiKey = async (
|
|
43
|
+
export const deleteStoredApiKey = async () => {
|
|
66
44
|
const keytar = await loadKeytar();
|
|
67
|
-
|
|
68
|
-
await keytar.deletePassword(ORBITAL_KEYTAR_SERVICE, account);
|
|
69
|
-
|
|
70
|
-
const p = (provider || "gemini").toLowerCase().trim();
|
|
71
|
-
if (p === "gemini" || p === "google") {
|
|
72
|
-
await keytar.deletePassword(
|
|
73
|
-
ORBITAL_KEYTAR_SERVICE,
|
|
74
|
-
ORBITAL_API_KEY_ACCOUNT
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
45
|
+
await keytar.deletePassword(ORBITAL_KEYTAR_SERVICE, ORBITAL_API_KEY_ACCOUNT);
|
|
78
46
|
return true;
|
|
79
47
|
};
|
|
80
|
-
|