orbital-cli-agent 1.0.0

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.
@@ -0,0 +1,371 @@
1
+ import chalk from "chalk";
2
+ import boxen from "boxen";
3
+ import { text, isCancel, cancel, intro, outro, multiselect } from "@clack/prompts";
4
+ import yoctoSpinner from "yocto-spinner";
5
+ import { marked } from "marked";
6
+ import { markedTerminal } from "marked-terminal";
7
+ import { AIService } from "../ai/google-service.js";
8
+ import { getStoredToken } from "../commands/auth/login.js";
9
+ import * as apiClient from "../api/api-client.js";
10
+ import {
11
+ availableTools,
12
+ getEnabledTools,
13
+ enableTools,
14
+ getEnabledToolNames,
15
+ resetTools
16
+ } from "../../config/tool.config.js";
17
+
18
+ // Configure marked for terminal
19
+ marked.use(
20
+ markedTerminal({
21
+ code: chalk.cyan,
22
+ blockquote: chalk.gray.italic,
23
+ heading: chalk.green.bold,
24
+ firstHeading: chalk.magenta.underline.bold,
25
+ hr: chalk.reset,
26
+ listitem: chalk.reset,
27
+ list: chalk.reset,
28
+ paragraph: chalk.reset,
29
+ strong: chalk.bold,
30
+ em: chalk.italic,
31
+ codespan: chalk.yellow.bgBlack,
32
+ del: chalk.dim.gray.strikethrough,
33
+ link: chalk.blue.underline,
34
+ href: chalk.blue.underline,
35
+ })
36
+ );
37
+
38
+ const aiService = new AIService();
39
+
40
+ async function getUserFromToken() {
41
+ const token = await getStoredToken();
42
+
43
+ if (!token?.access_token) {
44
+ throw new Error("Not authenticated. Please run 'orbit login' first.");
45
+ }
46
+
47
+ const spinner = yoctoSpinner({ text: "Authenticating..." }).start();
48
+
49
+ const user = await apiClient.getUserFromApi(token.access_token);
50
+
51
+ if (!user) {
52
+ spinner.error("User not found");
53
+ throw new Error("User not found. Please login again.");
54
+ }
55
+
56
+ spinner.success(`Welcome back, ${user.name}!`);
57
+ return { user, token };
58
+ }
59
+
60
+ async function selectTools() {
61
+ const toolOptions = availableTools.map(tool => ({
62
+ value: tool.id,
63
+ label: tool.name,
64
+ hint: tool.description,
65
+ }));
66
+
67
+ const selectedTools = await multiselect({
68
+ message: chalk.cyan("Select tools to enable (Space to select, Enter to confirm):"),
69
+ options: toolOptions,
70
+ required: false,
71
+ });
72
+
73
+ if (isCancel(selectedTools)) {
74
+ cancel(chalk.yellow("Tool selection cancelled"));
75
+ process.exit(0);
76
+ }
77
+
78
+ // Enable selected tools
79
+ enableTools(selectedTools);
80
+
81
+ if (selectedTools.length === 0) {
82
+ console.log(chalk.yellow("\nāš ļø No tools selected. AI will work without tools.\n"));
83
+ } else {
84
+ const toolsBox = boxen(
85
+ chalk.green(`āœ… Enabled tools:\n${selectedTools.map(id => {
86
+ const tool = availableTools.find(t => t.id === id);
87
+ return ` • ${tool.name}`;
88
+ }).join('\n')}`),
89
+ {
90
+ padding: 1,
91
+ margin: { top: 1, bottom: 1 },
92
+ borderStyle: "round",
93
+ borderColor: "green",
94
+ title: "šŸ› ļø Active Tools",
95
+ titleAlignment: "center",
96
+ }
97
+ );
98
+ console.log(toolsBox);
99
+ }
100
+
101
+ return selectedTools.length > 0;
102
+ }
103
+
104
+ async function initConversation(token, userId, conversationId = null, mode = "tool") {
105
+ const spinner = yoctoSpinner({ text: "Loading conversation..." }).start();
106
+
107
+ const conversation = await apiClient.getOrCreateConversation(
108
+ token,
109
+ conversationId,
110
+ mode
111
+ );
112
+
113
+ spinner.success("Conversation loaded");
114
+
115
+ // Get enabled tool names for display
116
+ const enabledToolNames = getEnabledToolNames();
117
+ const toolsDisplay = enabledToolNames.length > 0
118
+ ? `\n${chalk.gray("Active Tools:")} ${enabledToolNames.join(", ")}`
119
+ : `\n${chalk.gray("No tools enabled")}`;
120
+
121
+ // Display conversation info in a box
122
+ const conversationInfo = boxen(
123
+ `${chalk.bold("Conversation")}: ${conversation.title}\n${chalk.gray("ID: " + conversation.id)}\n${chalk.gray("Mode: " + conversation.mode)}${toolsDisplay}`,
124
+ {
125
+ padding: 1,
126
+ margin: { top: 1, bottom: 1 },
127
+ borderStyle: "round",
128
+ borderColor: "cyan",
129
+ title: "šŸ’¬ Tool Calling Session",
130
+ titleAlignment: "center",
131
+ }
132
+ );
133
+
134
+ console.log(conversationInfo);
135
+
136
+ // Display existing messages if any
137
+ if (conversation.messages?.length > 0) {
138
+ console.log(chalk.yellow("šŸ“œ Previous messages:\n"));
139
+ displayMessages(conversation.messages);
140
+ }
141
+
142
+ return conversation;
143
+ }
144
+
145
+ function displayMessages(messages) {
146
+ messages.forEach((msg) => {
147
+ if (msg.role === "user") {
148
+ const userBox = boxen(chalk.white(msg.content), {
149
+ padding: 1,
150
+ margin: { left: 2, bottom: 1 },
151
+ borderStyle: "round",
152
+ borderColor: "blue",
153
+ title: "šŸ‘¤ You",
154
+ titleAlignment: "left",
155
+ });
156
+ console.log(userBox);
157
+ } else if (msg.role === "assistant") {
158
+ const renderedContent = marked.parse(msg.content);
159
+ const assistantBox = boxen(renderedContent.trim(), {
160
+ padding: 1,
161
+ margin: { left: 2, bottom: 1 },
162
+ borderStyle: "round",
163
+ borderColor: "green",
164
+ title: "šŸ¤– Assistant (with tools)",
165
+ titleAlignment: "left",
166
+ });
167
+ console.log(assistantBox);
168
+ }
169
+ });
170
+ }
171
+
172
+ async function saveMessage(token, conversationId, role, content) {
173
+ return await apiClient.addMessage(token, conversationId, role, content);
174
+ }
175
+
176
+ async function getAIResponse(token, conversationId) {
177
+ const spinner = yoctoSpinner({
178
+ text: "AI is thinking...",
179
+ color: "cyan"
180
+ }).start();
181
+
182
+ const dbMessages = await apiClient.getMessages(token, conversationId);
183
+ const aiMessages = dbMessages.map((msg) => ({
184
+ role: msg.role,
185
+ content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
186
+ }));
187
+
188
+ const tools = getEnabledTools();
189
+
190
+ let fullResponse = "";
191
+ let isFirstChunk = true;
192
+ const toolCallsDetected = [];
193
+
194
+ try {
195
+ // IMPORTANT: Pass tools in the streamText config
196
+ const result = await aiService.sendMessage(
197
+ aiMessages,
198
+ (chunk) => {
199
+ if (isFirstChunk) {
200
+ spinner.stop();
201
+ console.log("\n");
202
+ const header = chalk.green.bold("šŸ¤– Assistant:");
203
+ console.log(header);
204
+ console.log(chalk.gray("─".repeat(60)));
205
+ isFirstChunk = false;
206
+ }
207
+ fullResponse += chunk;
208
+ },
209
+ tools,
210
+ (toolCall) => {
211
+ toolCallsDetected.push(toolCall);
212
+ }
213
+ );
214
+
215
+ // Display tool calls if any
216
+ if (toolCallsDetected.length > 0) {
217
+ console.log("\n");
218
+ const toolCallBox = boxen(
219
+ toolCallsDetected.map(tc =>
220
+ `${chalk.cyan("šŸ”§ Tool:")} ${tc.toolName}\n${chalk.gray("Args:")} ${JSON.stringify(tc.args, null, 2)}`
221
+ ).join("\n\n"),
222
+ {
223
+ padding: 1,
224
+ margin: 1,
225
+ borderStyle: "round",
226
+ borderColor: "cyan",
227
+ title: "šŸ› ļø Tool Calls",
228
+ }
229
+ );
230
+ console.log(toolCallBox);
231
+ }
232
+
233
+ // Display tool results if any
234
+ if (result.toolResults && result.toolResults.length > 0) {
235
+ const toolResultBox = boxen(
236
+ result.toolResults.map(tr =>
237
+ `${chalk.green("āœ… Tool:")} ${tr.toolName}\n${chalk.gray("Result:")} ${JSON.stringify(tr.result, null, 2).slice(0, 200)}...`
238
+ ).join("\n\n"),
239
+ {
240
+ padding: 1,
241
+ margin: 1,
242
+ borderStyle: "round",
243
+ borderColor: "green",
244
+ title: "šŸ“Š Tool Results",
245
+ }
246
+ );
247
+ console.log(toolResultBox);
248
+ }
249
+
250
+ // Render markdown response
251
+ console.log("\n");
252
+ const renderedMarkdown = marked.parse(fullResponse);
253
+ console.log(renderedMarkdown);
254
+ console.log(chalk.gray("─".repeat(60)));
255
+ console.log("\n");
256
+
257
+ return result.content;
258
+ } catch (error) {
259
+ spinner.error("Failed to get AI response");
260
+ throw error;
261
+ }
262
+ }
263
+
264
+
265
+ async function updateConversationTitle(token, conversationId, userId, userInput, messageCount) {
266
+ if (messageCount === 1) {
267
+ const title = userInput.slice(0, 50) + (userInput.length > 50 ? "..." : "");
268
+ await apiClient.updateTitle(token, conversationId, title);
269
+ }
270
+ }
271
+
272
+ async function chatLoop(token, conversation) {
273
+ const enabledToolNames = getEnabledToolNames();
274
+ const helpBox = boxen(
275
+ `${chalk.gray('• Type your message and press Enter')}\n${chalk.gray('• AI has access to:')} ${enabledToolNames.length > 0 ? enabledToolNames.join(", ") : "No tools"}\n${chalk.gray('• Type "exit" to end conversation')}\n${chalk.gray('• Press Ctrl+C to quit anytime')}`,
276
+ {
277
+ padding: 1,
278
+ margin: { bottom: 1 },
279
+ borderStyle: "round",
280
+ borderColor: "gray",
281
+ dimBorder: true,
282
+ }
283
+ );
284
+
285
+ console.log(helpBox);
286
+
287
+ while (true) {
288
+ const userInput = await text({
289
+ message: chalk.blue("šŸ’¬ Your message"),
290
+ placeholder: "Type your message...",
291
+ validate(value) {
292
+ if (!value || value.trim().length === 0) {
293
+ return "Message cannot be empty";
294
+ }
295
+ },
296
+ });
297
+
298
+ if (isCancel(userInput)) {
299
+ const exitBox = boxen(chalk.yellow("Chat session ended. Goodbye! šŸ‘‹"), {
300
+ padding: 1,
301
+ margin: 1,
302
+ borderStyle: "round",
303
+ borderColor: "yellow",
304
+ });
305
+ console.log(exitBox);
306
+ process.exit(0);
307
+ }
308
+
309
+ if (userInput.toLowerCase() === "exit") {
310
+ const exitBox = boxen(chalk.yellow("Chat session ended. Goodbye! šŸ‘‹"), {
311
+ padding: 1,
312
+ margin: 1,
313
+ borderStyle: "round",
314
+ borderColor: "yellow",
315
+ });
316
+ console.log(exitBox);
317
+ break;
318
+ }
319
+
320
+ const userBox = boxen(chalk.white(userInput), {
321
+ padding: 1,
322
+ margin: { left: 2, top: 1, bottom: 1 },
323
+ borderStyle: "round",
324
+ borderColor: "blue",
325
+ title: "šŸ‘¤ You",
326
+ titleAlignment: "left",
327
+ });
328
+ console.log(userBox);
329
+
330
+ await saveMessage(token, conversation.id, "user", userInput);
331
+ const messages = await apiClient.getMessages(token, conversation.id);
332
+ const aiResponse = await getAIResponse(token, conversation.id);
333
+ await saveMessage(token, conversation.id, "assistant", aiResponse);
334
+ await updateConversationTitle(token, conversation.id, conversation.userId, userInput, messages.length);
335
+ }
336
+ }
337
+
338
+ export async function startToolChat(conversationId = null) {
339
+ try {
340
+ intro(
341
+ boxen(chalk.bold.cyan("šŸ› ļø Orbit AI - Tool Calling Mode"), {
342
+ padding: 1,
343
+ borderStyle: "double",
344
+ borderColor: "cyan",
345
+ })
346
+ );
347
+
348
+ const { user, token } = await getUserFromToken();
349
+
350
+ // Select tools
351
+ await selectTools();
352
+
353
+ const conversation = await initConversation(token.access_token, user.id, conversationId, "tool");
354
+ await chatLoop(token.access_token, conversation);
355
+
356
+ // Reset tools on exit
357
+ resetTools();
358
+
359
+ outro(chalk.green("✨ Thanks for using tools!"));
360
+ } catch (error) {
361
+ const errorBox = boxen(chalk.red(`āŒ Error: ${error.message}`), {
362
+ padding: 1,
363
+ margin: 1,
364
+ borderStyle: "round",
365
+ borderColor: "red",
366
+ });
367
+ console.log(errorBox);
368
+ resetTools();
369
+ process.exit(1);
370
+ }
371
+ }
@@ -0,0 +1,267 @@
1
+ import chalk from "chalk";
2
+ import boxen from "boxen";
3
+ import { text, isCancel, cancel, intro, outro } from "@clack/prompts";
4
+ import yoctoSpinner from "yocto-spinner";
5
+ import { marked } from "marked";
6
+ import { markedTerminal } from "marked-terminal";
7
+ import { AIService } from "../ai/google-service.js";
8
+ import { getStoredToken } from "../commands/auth/login.js";
9
+ import * as apiClient from "../api/api-client.js";
10
+
11
+ // Configure marked to use terminal renderer
12
+ marked.use(
13
+ markedTerminal({
14
+ // Styling options for terminal output
15
+ code: chalk.cyan,
16
+ blockquote: chalk.gray.italic,
17
+ heading: chalk.green.bold,
18
+ firstHeading: chalk.magenta.underline.bold,
19
+ hr: chalk.reset,
20
+ listitem: chalk.reset,
21
+ list: chalk.reset,
22
+ paragraph: chalk.reset,
23
+ strong: chalk.bold,
24
+ em: chalk.italic,
25
+ codespan: chalk.yellow.bgBlack,
26
+ del: chalk.dim.gray.strikethrough,
27
+ link: chalk.blue.underline,
28
+ href: chalk.blue.underline,
29
+ })
30
+ );
31
+
32
+ // Initialize service
33
+ const aiService = new AIService();
34
+
35
+ async function getUserFromToken() {
36
+ const token = await getStoredToken();
37
+
38
+ if (!token?.access_token) {
39
+ throw new Error("Not authenticated. Please run 'orbit login' first.");
40
+ }
41
+
42
+ const spinner = yoctoSpinner({ text: "Authenticating..." }).start();
43
+
44
+ const user = await apiClient.getUserFromApi(token.access_token);
45
+
46
+ if (!user) {
47
+ spinner.error("User not found");
48
+ throw new Error("User not found. Please login again.");
49
+ }
50
+
51
+ spinner.success(`Welcome back, ${user.name}!`);
52
+ return { user, token };
53
+ }
54
+
55
+ async function initConversation(token, userId, conversationId = null, mode = "chat") {
56
+ const spinner = yoctoSpinner({ text: "Loading conversation..." }).start();
57
+
58
+ const conversation = await apiClient.getOrCreateConversation(
59
+ token,
60
+ conversationId,
61
+ mode
62
+ );
63
+
64
+ spinner.success("Conversation loaded");
65
+
66
+ // Display conversation info in a box
67
+ const conversationInfo = boxen(
68
+ `${chalk.bold("Conversation")}: ${conversation.title}\n${chalk.gray("ID: " + conversation.id)}\n${chalk.gray("Mode: " + conversation.mode)}`,
69
+ {
70
+ padding: 1,
71
+ margin: { top: 1, bottom: 1 },
72
+ borderStyle: "round",
73
+ borderColor: "cyan",
74
+ title: "šŸ’¬ Chat Session",
75
+ titleAlignment: "center",
76
+ }
77
+ );
78
+
79
+ console.log(conversationInfo);
80
+
81
+ // Display existing messages if any
82
+ if (conversation.messages?.length > 0) {
83
+ console.log(chalk.yellow("šŸ“œ Previous messages:\n"));
84
+ displayMessages(conversation.messages);
85
+ }
86
+
87
+ return conversation;
88
+ }
89
+
90
+ function displayMessages(messages) {
91
+ messages.forEach((msg) => {
92
+ if (msg.role === "user") {
93
+ const userBox = boxen(chalk.white(msg.content), {
94
+ padding: 1,
95
+ margin: { left: 2, bottom: 1 },
96
+ borderStyle: "round",
97
+ borderColor: "blue",
98
+ title: "šŸ‘¤ You",
99
+ titleAlignment: "left",
100
+ });
101
+ console.log(userBox);
102
+ } else {
103
+ // Render markdown for assistant messages
104
+ const renderedContent = marked.parse(msg.content);
105
+ const assistantBox = boxen(renderedContent.trim(), {
106
+ padding: 1,
107
+ margin: { left: 2, bottom: 1 },
108
+ borderStyle: "round",
109
+ borderColor: "green",
110
+ title: "šŸ¤– Assistant",
111
+ titleAlignment: "left",
112
+ });
113
+ console.log(assistantBox);
114
+ }
115
+ });
116
+ }
117
+
118
+ async function saveMessage(token, conversationId, role, content) {
119
+ return await apiClient.addMessage(token, conversationId, role, content);
120
+ }
121
+
122
+ async function getAIResponse(token, conversationId) {
123
+ const spinner = yoctoSpinner({
124
+ text: "AI is thinking...",
125
+ color: "cyan"
126
+ }).start();
127
+
128
+ const dbMessages = await apiClient.getMessages(token, conversationId);
129
+ const aiMessages = dbMessages.map((msg) => ({
130
+ role: msg.role,
131
+ content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
132
+ }));
133
+
134
+ let fullResponse = "";
135
+ let isFirstChunk = true;
136
+
137
+ try {
138
+ const result = await aiService.sendMessage(aiMessages, (chunk) => {
139
+ // Stop spinner on first chunk and show header
140
+ if (isFirstChunk) {
141
+ spinner.stop();
142
+ console.log("\n");
143
+ const header = chalk.green.bold("šŸ¤– Assistant:");
144
+ console.log(header);
145
+ console.log(chalk.gray("─".repeat(60)));
146
+ isFirstChunk = false;
147
+ }
148
+ process.stdout.write(chunk);
149
+ fullResponse += chunk;
150
+ });
151
+
152
+ // Now render the complete markdown response
153
+ console.log("\n");
154
+ const renderedMarkdown = marked.parse(fullResponse);
155
+ console.log(renderedMarkdown);
156
+ console.log(chalk.gray("─".repeat(60)));
157
+ console.log("\n");
158
+
159
+ return result.content;
160
+ } catch (error) {
161
+ spinner.error("Failed to get AI response");
162
+ throw error;
163
+ }
164
+ }
165
+
166
+ async function updateConversationTitle(token, conversationId, userId, userInput, messageCount) {
167
+ if (messageCount === 1) {
168
+ const title = userInput.slice(0, 50) + (userInput.length > 50 ? "..." : "");
169
+ await apiClient.updateTitle(token, conversationId, title);
170
+ }
171
+ }
172
+
173
+ async function chatLoop(token, conversation) {
174
+ const helpBox = boxen(
175
+ `${chalk.gray('• Type your message and press Enter')}\n${chalk.gray('• Markdown formatting is supported in responses')}\n${chalk.gray('• Type "exit" to end conversation')}\n${chalk.gray('• Press Ctrl+C to quit anytime')}`,
176
+ {
177
+ padding: 1,
178
+ margin: { bottom: 1 },
179
+ borderStyle: "round",
180
+ borderColor: "gray",
181
+ dimBorder: true,
182
+ }
183
+ );
184
+
185
+ console.log(helpBox);
186
+
187
+ while (true) {
188
+ const userInput = await text({
189
+ message: chalk.blue("šŸ’¬ Your message"),
190
+ placeholder: "Type your message...",
191
+ validate(value) {
192
+ if (!value || value.trim().length === 0) {
193
+ return "Message cannot be empty";
194
+ }
195
+ },
196
+ });
197
+
198
+ // Handle cancellation (Ctrl+C)
199
+ if (isCancel(userInput)) {
200
+ const exitBox = boxen(chalk.yellow("Chat session ended. Goodbye! šŸ‘‹"), {
201
+ padding: 1,
202
+ margin: 1,
203
+ borderStyle: "round",
204
+ borderColor: "yellow",
205
+ });
206
+ console.log(exitBox);
207
+ process.exit(0);
208
+ }
209
+
210
+ // Handle exit command
211
+ if (userInput.toLowerCase() === "exit") {
212
+ const exitBox = boxen(chalk.yellow("Chat session ended. Goodbye! šŸ‘‹"), {
213
+ padding: 1,
214
+ margin: 1,
215
+ borderStyle: "round",
216
+ borderColor: "yellow",
217
+ });
218
+ console.log(exitBox);
219
+ break;
220
+ }
221
+
222
+ // Save user message
223
+ await saveMessage(token, conversation.id, "user", userInput);
224
+
225
+ // Get messages count before AI response
226
+ const messages = await apiClient.getMessages(token, conversation.id);
227
+
228
+ // Get AI response with streaming and markdown rendering
229
+ const aiResponse = await getAIResponse(token, conversation.id);
230
+
231
+ // Save AI response
232
+ await saveMessage(token, conversation.id, "assistant", aiResponse);
233
+
234
+ // Update title if first exchange
235
+ await updateConversationTitle(token, conversation.id, conversation.userId, userInput, messages.length);
236
+ }
237
+ }
238
+
239
+ // Main entry point
240
+ export async function startChat(mode = "chat", conversationId = null) {
241
+ try {
242
+ // Display intro banner
243
+ intro(
244
+ boxen(chalk.bold.cyan("šŸš€ Orbit AI Chat"), {
245
+ padding: 1,
246
+ borderStyle: "double",
247
+ borderColor: "cyan",
248
+ })
249
+ );
250
+
251
+ const { user, token } = await getUserFromToken();
252
+ const conversation = await initConversation(token.access_token, user.id, conversationId, mode);
253
+ await chatLoop(token.access_token, conversation);
254
+
255
+ // Display outro
256
+ outro(chalk.green("✨ Thanks for chatting!"));
257
+ } catch (error) {
258
+ const errorBox = boxen(chalk.red(`āŒ Error: ${error.message}`), {
259
+ padding: 1,
260
+ margin: 1,
261
+ borderStyle: "round",
262
+ borderColor: "red",
263
+ });
264
+ console.log(errorBox);
265
+ process.exit(1);
266
+ }
267
+ }
@@ -0,0 +1,61 @@
1
+ import chalk from "chalk";
2
+ import { Command } from "commander";
3
+ import { getStoredToken } from "../auth/login.js";
4
+ import { getUserFromApi } from "../../api/api-client.js";
5
+ import { select, isCancel } from "@clack/prompts";
6
+ import yoctoSpinner from "yocto-spinner";
7
+ import { startChat } from "../../chat/chat-with-ai.js";
8
+ import { startToolChat } from "../../chat/chat-with-ai-tool.js";
9
+ import { startAgentChat } from "../../chat/chat-with-ai-agent.js";
10
+
11
+ const wakeUpAction = async()=>{
12
+ const token=await getStoredToken();
13
+ if(!token?.access_token){
14
+ console.log(chalk.red("not authenticated please login"));
15
+ return;
16
+ }
17
+
18
+ const spinner=yoctoSpinner({text:"Fetching user Information....."}).start();
19
+ const user = await getUserFromApi(token.access_token);
20
+ spinner.stop();
21
+
22
+ if(!user){
23
+ console.log("User not found");
24
+ return;
25
+ }
26
+
27
+ while (true) {
28
+ const choice = await select({
29
+ message: chalk.cyan(`Welcome Back ${user.name}! How can I help you today?`),
30
+ options: [
31
+ { value: "chat", label: "AI Chat", hint: "Start a conversations with AI" },
32
+ { value: "tool", label: "Tool calling", hint: "Chat with tools enabled" },
33
+ { value: "agentic", label: "Agentic Mode", hint: "Build complete apps with AI" },
34
+ { value: "exit", label: "Exit", hint: "Exit the application" }
35
+ ]
36
+ });
37
+
38
+ if (isCancel(choice) || choice === "exit") {
39
+ console.log(chalk.green("\nGoodbye! See you next time. šŸ‘‹\n"));
40
+ break;
41
+ }
42
+
43
+ switch (choice) {
44
+ case "chat":
45
+ await startChat("chat");
46
+ break;
47
+ case "tool":
48
+ await startToolChat();
49
+ break;
50
+ case "agentic":
51
+ await startAgentChat();
52
+ break;
53
+ default:
54
+ console.log(chalk.red("Invalid option. Please try again."));
55
+ }
56
+ }
57
+ }
58
+
59
+ export const wakeup = new Command("wakeup")
60
+ .description("Wake up the AI agent")
61
+ .action(wakeUpAction);