@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.
@@ -1,98 +1,85 @@
1
1
  import chalk from "chalk";
2
2
  import boxen from "boxen";
3
- import { text, isCancel, intro, outro } from "@clack/prompts";
3
+ import {text , isCancel , cancel , intro , outro }from "@clack/prompts";
4
4
  import yoctoSpinner from "yocto-spinner";
5
- import { marked } from "marked";
6
- import { markedTerminal } from "marked-terminal";
7
- import { getStoredToken } from "../../lib/token.js";
5
+ import {marked} from "marked";
6
+ import {markedTerminal} from "marked-terminal";
7
+ import {getStoredToken} from "../../lib/token.js";
8
8
  import { apiRequestSafe } from "../utils/apiClient.js";
9
9
  import { AIService } from "../ai/googleService.js";
10
- import { requireApiKey, hydrateApiKeyEnv } from "../../lib/orbitalConfig.js";
11
- import { parseModelChoice } from "../../config/aiConfig.js";
12
-
10
+ import { requireGeminiApiKey } from "../../lib/orbitalConfig.js";
13
11
 
14
12
  marked.use(
15
- markedTerminal({
16
- code: chalk.cyan,
17
- blockquote: chalk.gray.italic,
18
- heading: chalk.green.bold,
19
- firstHeading: chalk.magenta.underline.bold,
20
- hr: chalk.reset,
21
- listitem: chalk.reset,
22
- list: chalk.reset,
23
- paragraph: chalk.reset,
24
- strong: chalk.bold,
25
- em: chalk.italic,
26
- codespan: chalk.yellow.bgBlack,
27
- del: chalk.dim.gray.strikethrough,
28
- link: chalk.blue.underline,
29
- href: chalk.blue.underline,
30
- })
31
- );
13
+ markedTerminal({
14
+ code : chalk.cyan ,
15
+ blockquote : chalk.gray.italic ,
16
+ heading : chalk.green.bold ,
17
+ firstHeading: chalk.magenta.underline.bold ,
18
+ hr : chalk.reset ,
19
+ listitem : chalk.reset ,
20
+ list : chalk.reset ,
21
+ paragraph : chalk.reset ,
22
+ strong : chalk.bold ,
23
+ em : chalk.italic ,
24
+ codespan : chalk.yellow.bgBlack ,
25
+ del : chalk.dim.gray.strikethrough ,
26
+ link : chalk.blue.underline ,
27
+ href : chalk.blue.underline
28
+ })
29
+ )
32
30
 
33
- const getUserFromToken = async () => {
34
- const token = await getStoredToken();
35
- if (!token?.access_token) {
36
- throw new Error("Not authenticated. Please run 'orbital login' first.");
37
- }
31
+ const getUserFromToken = async()=>{
32
+ const token = await getStoredToken()
33
+ if(!token?.access_token){
34
+ throw new Error("Not authenticated. Please run 'orbital login' first.");
35
+ }
38
36
 
39
- const spinner = yoctoSpinner({ text: "Authenticating..." }).start();
40
- try {
41
- const result = await apiRequestSafe("/api/cli/me");
42
- const user = result?.user;
43
- if (!user) {
44
- spinner.error("User not found");
45
- throw new Error("User not found. Please login again");
37
+ const spinner = yoctoSpinner({text: "Authenticating..."}).start();
38
+ try {
39
+ const result = await apiRequestSafe("/api/cli/me");
40
+ const user = result?.user;
41
+ if(!user){
42
+ spinner.error("User not found");
43
+ throw new Error("User not found. Please login again");
44
+ }
45
+ spinner.success(`Welcome back , ${user.name}!`);
46
+ return user;
47
+ } finally {
48
+ spinner.stop();
46
49
  }
47
- spinner.success(`Welcome back, ${user.name}!`);
48
- return user;
49
- } finally {
50
- spinner.stop();
51
- }
52
- };
50
+ }
53
51
 
54
- const initConversation = async (
55
- userId,
56
- conversationId = null,
57
- mode = "chat",
58
- modelDisplayName = null
59
- ) => {
60
- const spinner = yoctoSpinner({ text: "Loading conversation..." }).start();
52
+ const initConversation = async(userId , conversationId = null , mode = "chat")=>{
53
+ const spinner = yoctoSpinner({text : "Loading conservation ..."}).start();
61
54
 
62
- const result = await apiRequestSafe("/api/cli/conversations/init", {
63
- method: "POST",
64
- body: { conversationId, mode },
65
- });
66
- const conversation = result?.conversation;
67
- const messages = result?.messages || [];
68
- spinner.success("Conversation Loaded");
55
+ const result = await apiRequestSafe("/api/cli/conversations/init", {
56
+ method: "POST",
57
+ body: { conversationId, mode },
58
+ });
59
+ const conversation = result?.conversation;
60
+ const messages = result?.messages || [];
61
+ spinner.success("Conversation Loaded");
69
62
 
70
- const modelLine = modelDisplayName
71
- ? `\n ${chalk.cyan("Model: " + modelDisplayName)}`
72
- : "";
63
+ const conversationInfo = boxen(
64
+ `${chalk.bold("Conversation")} : ${conversation.title}\n ${chalk.gray("ID: " + conversation.id)} \n ${chalk.gray("Mode: " + conversation.mode)}`,
65
+ {
66
+ padding : 1 ,
67
+ margin : {top: 1 , bottom : 1} ,
68
+ borderStyle : "round" ,
69
+ borderColor : "cyan" ,
70
+ title : "Chat Settion",
71
+ titleAlignment : "center"
72
+ }
73
+ );
74
+ console.log(conversationInfo);
73
75
 
74
- const conversationInfo = boxen(
75
- `${chalk.bold("Conversation")}: ${conversation.title}\n ${chalk.gray(
76
- "ID: " + conversation.id
77
- )}\n ${chalk.gray("Mode: " + conversation.mode)}${modelLine}`,
78
- {
79
- padding: 1,
80
- margin: { top: 1, bottom: 1 },
81
- borderStyle: "round",
82
- borderColor: "cyan",
83
- title: "Chat Session",
84
- titleAlignment: "center",
76
+ if(messages.length > 0){
77
+ console.log(chalk.yellow("Previous Messsages: \n"));
78
+ displayMessages(messages);
85
79
  }
86
- );
87
- console.log(conversationInfo);
88
80
 
89
- if (messages.length > 0) {
90
- console.log(chalk.yellow("Previous Messages:\n"));
91
- displayMessages(messages);
92
- }
93
-
94
- return conversation;
95
- };
81
+ return conversation ;
82
+ }
96
83
 
97
84
  const displayMessages = (messages) => {
98
85
  messages.forEach((msg) => {
@@ -121,175 +108,153 @@ const displayMessages = (messages) => {
121
108
  });
122
109
  };
123
110
 
124
- const saveMessage = async (conversationId, role, content) => {
125
- return await apiRequestSafe("/api/cli/messages", {
126
- method: "POST",
127
- body: { conversationId, role, content },
128
- });
129
- };
111
+ const saveMessage = async(conversationId , role , content) =>{
112
+ return await apiRequestSafe("/api/cli/messages", {
113
+ method: "POST",
114
+ body: { conversationId, role, content },
115
+ });
116
+ }
130
117
 
131
- const getAIResponse = async (conversationId, modelConfig = null) => {
132
- const aiService = new AIService(modelConfig);
133
- await requireApiKey(aiService.provider);
118
+ const getAIResponse = async(conversationId)=>{
119
+ const spinner = yoctoSpinner({
120
+ text : "AI is thinking...",
121
+ color: "cyan"
122
+ }).start();
134
123
 
135
- const spinner = yoctoSpinner({
136
- text: `${aiService.getDisplayName()} is thinking...`,
137
- color: "cyan",
138
- }).start();
124
+ let fullResponse = "";
125
+ try{
126
+ const messageResult = await apiRequestSafe(
127
+ `/api/cli/messages?conversationId=${encodeURIComponent(conversationId)}`,
128
+ { method: "GET" }
129
+ );
139
130
 
140
- let fullResponse = "";
141
- try {
142
- const messageResult = await apiRequestSafe(
143
- `/api/cli/messages?conversationId=${encodeURIComponent(conversationId)}`,
144
- { method: "GET" }
145
- );
131
+ const messages = Array.isArray(messageResult?.messages) ? messageResult.messages : [];
132
+ const aiMessages = messages.map((m) => ({ role: m.role, content: m.content }));
146
133
 
147
- const messages = Array.isArray(messageResult?.messages)
148
- ? messageResult.messages
149
- : [];
150
- const aiMessages = messages.map((m) => ({
151
- role: m.role,
152
- content: m.content,
153
- }));
134
+ await requireGeminiApiKey();
135
+ const aiService = new AIService();
136
+ const result = await aiService.sendMessage(aiMessages);
154
137
 
155
- const result = await aiService.sendMessage(aiMessages);
138
+ spinner.stop();
139
+ console.log("\n");
140
+ const header = chalk.green.bold("Assistent: ");
141
+ console.log(header);
142
+ console.log(chalk.gray("-".repeat(60)));
156
143
 
157
- spinner.stop();
158
- console.log("\n");
159
- const header = chalk.green.bold(`Assistant (${aiService.getDisplayName()}):`);
160
- console.log(header);
161
- console.log(chalk.gray("-".repeat(60)));
144
+ fullResponse = result?.content || "";
145
+ console.log("\n");
146
+ const renderMarkdown = marked.parse(fullResponse);
147
+ console.log(renderMarkdown);
148
+ console.log(chalk.gray("-".repeat(60)));
149
+ console.log("\n");
162
150
 
163
- fullResponse = result?.content || "";
164
- console.log("\n");
165
- const renderMarkdown = marked.parse(fullResponse);
166
- console.log(renderMarkdown);
167
- console.log(chalk.gray("-".repeat(60)));
168
- console.log("\n");
151
+ return fullResponse ;
152
+ }
153
+ catch(error){
154
+ spinner.error("Failed to get AI response");
155
+ throw error ;
156
+ }
157
+ }
169
158
 
170
- return fullResponse;
171
- } catch (error) {
172
- spinner.error("Failed to get AI response");
173
- throw error;
174
- }
175
- };
159
+ const updateConversationTitle = async(conversationId , userInput , messageCount)=>{
160
+ if(messageCount ===1){
161
+ const title = userInput.slice(0,50) + (userInput.length > 50 ? "..." : "");
162
+ await apiRequestSafe(`/api/cli/conversations/${conversationId}/title`, {
163
+ method: "PATCH",
164
+ body: { title },
165
+ });
166
+ }
167
+ }
176
168
 
177
- const updateConversationTitle = async (
178
- conversationId,
179
- userInput,
180
- messageCount
181
- ) => {
182
- if (messageCount === 1) {
183
- const title =
184
- userInput.slice(0, 50) + (userInput.length > 50 ? "..." : "");
185
- await apiRequestSafe(`/api/cli/conversations/${conversationId}/title`, {
186
- method: "PATCH",
187
- body: { title },
188
- });
189
- }
190
- };
169
+ const chatLoop = async(conversation)=>{
170
+ const helpBox = boxen(
171
+ `${chalk.gray(`* Type your message and press Enter`)}\n ${chalk.gray(`* Markdown formatting is supported in response`)}
172
+ \n${chalk.gray(`*Type "exit" to end conversation`)}\n ${chalk.gray(`*Please ctrl + C to quit anytime`)}`,
173
+ {
174
+ padding : 1 ,
175
+ margin : {bottom : 1},
176
+ borderStyle : "round" ,
177
+ borderColor : "gray" ,
178
+ dimBorder : true
179
+ }
180
+ );
181
+ console.log(helpBox);
191
182
 
192
- const chatLoop = async (conversation, modelConfig = null) => {
193
- const helpBox = boxen(
194
- `${chalk.gray(`* Type your message and press Enter`)}\n${chalk.gray(
195
- `* Markdown formatting is supported in response`
196
- )}\n${chalk.gray(`* Type "exit" to end conversation`)}\n${chalk.gray(
197
- `* Press Ctrl + C to quit anytime`
198
- )}`,
199
- {
200
- padding: 1,
201
- margin: { bottom: 1 },
202
- borderStyle: "round",
203
- borderColor: "gray",
204
- dimBorder: true,
205
- }
206
- );
207
- console.log(helpBox);
183
+ while(true){
184
+ const userInput = await text({
185
+ message: chalk.blue("Your message"),
186
+ placeholder : "Type your message...",
187
+ validate(value){
188
+ if(!value || value.trim().length ===0){
189
+ return "Message cannot be empty";
190
+ }
191
+ },
192
+ });
208
193
 
209
- while (true) {
210
- const userInput = await text({
211
- message: chalk.blue("Your message"),
212
- placeholder: "Type your message...",
213
- validate(value) {
214
- if (!value || value.trim().length === 0) {
215
- return "Message cannot be empty";
194
+ if(isCancel(userInput)){
195
+ const exitBox = boxen(chalk.yellow("Chat session ended. GoodBye! "),{
196
+ padding : 1 ,
197
+ margin : 1,
198
+ borderStyle : "round" ,
199
+ borderColor : "yellow" ,
200
+ });
201
+ console.log(exitBox);
202
+ process.exit(0);
216
203
  }
217
- },
218
- });
204
+ if(userInput.trim().toLowerCase() === "exit"){
205
+ const exitBox = boxen(chalk.yellow("Chat session ended. GoodBye! "),{
206
+ padding : 1 ,
207
+ margin : 1,
208
+ borderStyle : "round" ,
209
+ borderColor : "yellow" ,
210
+ });
211
+ console.log(exitBox);
212
+ break ;
213
+ }
214
+ await saveMessage(conversation.id , "user" , userInput);
215
+ const messageResult = await apiRequestSafe(
216
+ `/api/cli/messages?conversationId=${encodeURIComponent(conversation.id)}`,
217
+ { method: "GET" }
218
+ );
219
219
 
220
- if (isCancel(userInput)) {
221
- const exitBox = boxen(chalk.yellow("Chat session ended. Goodbye!"), {
222
- padding: 1,
223
- margin: 1,
224
- borderStyle: "round",
225
- borderColor: "yellow",
226
- });
227
- console.log(exitBox);
228
- process.exit(0);
229
- }
230
- if (userInput.trim().toLowerCase() === "exit") {
231
- const exitBox = boxen(chalk.yellow("Chat session ended. Goodbye!"), {
232
- padding: 1,
233
- margin: 1,
234
- borderStyle: "round",
235
- borderColor: "yellow",
236
- });
237
- console.log(exitBox);
238
- break;
239
- }
240
- await saveMessage(conversation.id, "user", userInput);
241
- const messageResult = await apiRequestSafe(
242
- `/api/cli/messages?conversationId=${encodeURIComponent(conversation.id)}`,
243
- { method: "GET" }
244
- );
220
+ const aiResponse = await getAIResponse(conversation.id);
221
+ await saveMessage(conversation.id , "assistant" , aiResponse);
245
222
 
246
- const aiResponse = await getAIResponse(conversation.id, modelConfig);
247
- await saveMessage(conversation.id, "assistant", aiResponse);
223
+ await updateConversationTitle(
224
+ conversation.id ,
225
+ userInput ,
226
+ messageResult?.messages?.length || 0
227
+ )
228
+ }
229
+ }
248
230
 
249
- await updateConversationTitle(
250
- conversation.id,
251
- userInput,
252
- messageResult?.messages?.length || 0
253
- );
254
- }
255
- };
256
231
 
257
- export const startChat = async (
258
- mode = "chat",
259
- conversationId = null,
260
- modelConfig = null
261
- ) => {
262
- try {
263
- intro(
264
- boxen(chalk.bold.cyan("Orbital AI Chat"), {
265
- padding: 1,
266
- borderStyle: "double",
267
- borderColor: "cyan",
268
- })
269
- );
270
232
 
271
- const { provider } = parseModelChoice(modelConfig);
272
- await hydrateApiKeyEnv(provider);
273
- const aiService = new AIService(modelConfig);
233
+ export const startChat = async(mode="chat" , conversationId = null)=>{
234
+ try{
235
+ intro(
236
+ boxen(chalk.bold.cyan("Orbital AI Chat") , {
237
+ padding: 1 ,
238
+ borderStyle : "double",
239
+ borderColor: "cyan"
240
+ })
241
+ )
274
242
 
275
- const user = await getUserFromToken();
276
- const conversation = await initConversation(
277
- user.id,
278
- conversationId,
279
- mode,
280
- aiService.getDisplayName()
281
- );
282
- await chatLoop(conversation, modelConfig);
243
+ const user = await getUserFromToken()
244
+ const conversation = await initConversation(user.id , conversationId , mode);
245
+ await chatLoop(conversation)
283
246
 
284
- outro(chalk.green("Thanks for chatting"));
285
- } catch (error) {
286
- const errorBox = boxen(chalk.red(`Error: ${error.message}`), {
287
- padding: 1,
288
- margin: 1,
289
- borderStyle: "round",
290
- borderColor: "red",
291
- });
292
- console.log(errorBox);
293
- process.exit(1);
294
- }
295
- };
247
+ outro(chalk.green("Thanks for chatting"))
248
+ }
249
+ catch(error){
250
+ const errorBox = boxen(chalk.red(`Error: ${error.message}`),{
251
+ padding : 1 ,
252
+ margin : 1 ,
253
+ borderStyle : "round",
254
+ borderColor : "red",
255
+
256
+ });
257
+ console.log(errorBox);
258
+ process.exit(1);
259
+ }
260
+ }