@dubeyvishal/orbital-cli 1.0.4 → 1.0.5

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.
Files changed (52) hide show
  1. package/package.json +8 -10
  2. package/server/prisma/migrations/20260105143219_test_migration/migration.sql +7 -0
  3. package/server/prisma/migrations/20260105151026_authentication/migration.sql +78 -0
  4. package/server/prisma/migrations/20260114105919_add_devicecode_conversation_message/migration.sql +50 -0
  5. package/server/prisma/migrations/migration_lock.toml +3 -0
  6. package/server/prisma/schema.prisma +117 -0
  7. package/server/{ai → src/cli/ai}/googleService.js +4 -5
  8. package/server/{chat → src/cli/chat}/chat-with-ai-agent.js +43 -50
  9. package/server/{chat → src/cli/chat}/chat-with-ai-tools.js +70 -83
  10. package/server/{chat → src/cli/chat}/chat-with-ai.js +57 -69
  11. package/server/{commands → src/cli/commands}/General/openApp.js +13 -8
  12. package/server/{commands → src/cli/commands}/ai/wakeUp.js +18 -20
  13. package/server/{commands → src/cli/commands}/auth/aboutMe.js +3 -2
  14. package/server/{commands → src/cli/commands}/auth/login.js +35 -12
  15. package/server/{commands → src/cli/commands}/auth/logout.js +1 -1
  16. package/server/src/cli/commands/config/setkey.js +26 -0
  17. package/server/{main.js → src/cli/main.js} +1 -1
  18. package/server/src/cli/utils/apiClient.js +66 -0
  19. package/server/{config → src/config}/agentConfig.js +22 -17
  20. package/server/src/config/api.js +22 -0
  21. package/server/src/config/env.js +86 -0
  22. package/server/{config → src/config}/toolConfig.js +7 -0
  23. package/server/src/controllers/aiController.js +58 -0
  24. package/server/src/controllers/cliController.js +77 -0
  25. package/server/src/db/prisma.js +3 -0
  26. package/server/src/index.js +108 -0
  27. package/server/src/lib/auth.js +37 -0
  28. package/server/src/lib/credentialStore.js +47 -0
  29. package/server/src/lib/db.js +18 -0
  30. package/server/src/lib/dbHealth.js +106 -0
  31. package/server/src/lib/orbitalConfig.js +192 -0
  32. package/server/{utils → src/lib}/token.js +8 -14
  33. package/server/src/middleware/auth.js +39 -0
  34. package/server/src/middleware/errorHandler.js +11 -0
  35. package/server/src/prisma/migrations/20260107093841_device_flow/migration.sql +94 -0
  36. package/server/src/prisma/migrations/migration_lock.toml +3 -0
  37. package/server/src/prisma/schema.prisma +115 -0
  38. package/server/src/routes/authRoutes.js +14 -0
  39. package/server/src/routes/cliRoutes.js +18 -0
  40. package/server/src/service/chatService.js +156 -0
  41. package/server/src/services/aiService.js +10 -0
  42. package/server/src/services/chatService.js +1 -0
  43. package/server/src/types/express.d.ts +19 -0
  44. package/server/commands/config/setkey.js +0 -19
  45. package/server/config/env.js +0 -20
  46. package/server/utils/apiClient.js +0 -40
  47. package/server/utils/chatServiceClient.js +0 -73
  48. package/server/utils/orbitalConfig.js +0 -44
  49. /package/server/{commands → src/cli/commands}/General/playSong.js +0 -0
  50. /package/server/{commands → src/cli/commands}/General/searchYoutube.js +0 -0
  51. /package/server/{generalApp → src/cli/generalApp}/Apps.js +0 -0
  52. /package/server/{config → src/config}/googleConfig.js +0 -0
package/package.json CHANGED
@@ -1,22 +1,17 @@
1
1
  {
2
2
  "name": "@dubeyvishal/orbital-cli",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
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",
7
7
  "private": false,
8
8
  "type": "module",
9
9
  "bin": {
10
- "orbital": "server/main.js"
10
+ "orbital": "server/src/cli/main.js"
11
11
  },
12
12
  "files": [
13
- "server/main.js",
14
- "server/commands",
15
- "server/chat",
16
- "server/ai",
17
- "server/config",
18
- "server/generalApp",
19
- "server/utils",
13
+ "server/src",
14
+ "server/prisma",
20
15
  "README.md"
21
16
  ],
22
17
  "publishConfig": {
@@ -36,6 +31,7 @@
36
31
  "commander": "^14.0.2",
37
32
  "dotenv": "^17.2.3",
38
33
  "figlet": "^1.9.4",
34
+ "keytar": "^7.9.0",
39
35
  "marked": "^15.0.12",
40
36
  "marked-terminal": "^7.3.0",
41
37
  "open": "^11.0.0",
@@ -44,6 +40,8 @@
44
40
  "zod": "^4.3.5"
45
41
  },
46
42
  "scripts": {
43
+ "postinstall": "cd server && npx prisma generate",
44
+ "install-all": "npm install --prefix client && npm install --prefix server",
47
45
  "start-client": "npm start --prefix client",
48
46
  "start-server": "npm start --prefix server",
49
47
  "dev": "npm run start-server && npm run start-client"
@@ -56,4 +54,4 @@
56
54
  "client-server",
57
55
  "javascript"
58
56
  ]
59
- }
57
+ }
@@ -0,0 +1,7 @@
1
+ -- CreateTable
2
+ CREATE TABLE "Test" (
3
+ "id" TEXT NOT NULL,
4
+ "name" TEXT NOT NULL,
5
+
6
+ CONSTRAINT "Test_pkey" PRIMARY KEY ("id")
7
+ );
@@ -0,0 +1,78 @@
1
+ -- CreateTable
2
+ CREATE TABLE "user" (
3
+ "id" TEXT NOT NULL,
4
+ "name" TEXT NOT NULL,
5
+ "email" TEXT NOT NULL,
6
+ "emailVerified" BOOLEAN NOT NULL DEFAULT false,
7
+ "image" TEXT,
8
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
9
+ "updatedAt" TIMESTAMP(3) NOT NULL,
10
+
11
+ CONSTRAINT "user_pkey" PRIMARY KEY ("id")
12
+ );
13
+
14
+ -- CreateTable
15
+ CREATE TABLE "session" (
16
+ "id" TEXT NOT NULL,
17
+ "expiresAt" TIMESTAMP(3) NOT NULL,
18
+ "token" TEXT NOT NULL,
19
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
20
+ "updatedAt" TIMESTAMP(3) NOT NULL,
21
+ "ipAddress" TEXT,
22
+ "userAgent" TEXT,
23
+ "userId" TEXT NOT NULL,
24
+
25
+ CONSTRAINT "session_pkey" PRIMARY KEY ("id")
26
+ );
27
+
28
+ -- CreateTable
29
+ CREATE TABLE "account" (
30
+ "id" TEXT NOT NULL,
31
+ "accountId" TEXT NOT NULL,
32
+ "providerId" TEXT NOT NULL,
33
+ "userId" TEXT NOT NULL,
34
+ "accessToken" TEXT,
35
+ "refreshToken" TEXT,
36
+ "idToken" TEXT,
37
+ "accessTokenExpiresAt" TIMESTAMP(3),
38
+ "refreshTokenExpiresAt" TIMESTAMP(3),
39
+ "scope" TEXT,
40
+ "password" TEXT,
41
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
42
+ "updatedAt" TIMESTAMP(3) NOT NULL,
43
+
44
+ CONSTRAINT "account_pkey" PRIMARY KEY ("id")
45
+ );
46
+
47
+ -- CreateTable
48
+ CREATE TABLE "verification" (
49
+ "id" TEXT NOT NULL,
50
+ "identifier" TEXT NOT NULL,
51
+ "value" TEXT NOT NULL,
52
+ "expiresAt" TIMESTAMP(3) NOT NULL,
53
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
54
+ "updatedAt" TIMESTAMP(3) NOT NULL,
55
+
56
+ CONSTRAINT "verification_pkey" PRIMARY KEY ("id")
57
+ );
58
+
59
+ -- CreateIndex
60
+ CREATE UNIQUE INDEX "user_email_key" ON "user"("email");
61
+
62
+ -- CreateIndex
63
+ CREATE INDEX "session_userId_idx" ON "session"("userId");
64
+
65
+ -- CreateIndex
66
+ CREATE UNIQUE INDEX "session_token_key" ON "session"("token");
67
+
68
+ -- CreateIndex
69
+ CREATE INDEX "account_userId_idx" ON "account"("userId");
70
+
71
+ -- CreateIndex
72
+ CREATE INDEX "verification_identifier_idx" ON "verification"("identifier");
73
+
74
+ -- AddForeignKey
75
+ ALTER TABLE "session" ADD CONSTRAINT "session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE;
76
+
77
+ -- AddForeignKey
78
+ ALTER TABLE "account" ADD CONSTRAINT "account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,50 @@
1
+ -- CreateTable
2
+ CREATE TABLE "deviceCode" (
3
+ "id" TEXT NOT NULL,
4
+ "deviceCode" TEXT NOT NULL,
5
+ "userCode" TEXT NOT NULL,
6
+ "userId" TEXT,
7
+ "expiresAt" TIMESTAMP(3) NOT NULL,
8
+ "status" TEXT NOT NULL,
9
+ "lastPolledAt" TIMESTAMP(3),
10
+ "pollingInterval" INTEGER,
11
+ "clientId" TEXT,
12
+ "scope" TEXT,
13
+
14
+ CONSTRAINT "deviceCode_pkey" PRIMARY KEY ("id")
15
+ );
16
+
17
+ -- CreateTable
18
+ CREATE TABLE "conversation" (
19
+ "id" TEXT NOT NULL,
20
+ "userId" TEXT NOT NULL,
21
+ "title" TEXT NOT NULL,
22
+ "mode" TEXT NOT NULL DEFAULT 'chat',
23
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
24
+ "updatedAt" TIMESTAMP(3) NOT NULL,
25
+
26
+ CONSTRAINT "conversation_pkey" PRIMARY KEY ("id")
27
+ );
28
+
29
+ -- CreateTable
30
+ CREATE TABLE "message" (
31
+ "id" TEXT NOT NULL,
32
+ "conversationId" TEXT NOT NULL,
33
+ "role" TEXT NOT NULL,
34
+ "content" TEXT NOT NULL,
35
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
36
+
37
+ CONSTRAINT "message_pkey" PRIMARY KEY ("id")
38
+ );
39
+
40
+ -- CreateIndex
41
+ CREATE INDEX "conversation_userId_idx" ON "conversation"("userId");
42
+
43
+ -- CreateIndex
44
+ CREATE INDEX "message_conversationId_idx" ON "message"("conversationId");
45
+
46
+ -- AddForeignKey
47
+ ALTER TABLE "conversation" ADD CONSTRAINT "conversation_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE;
48
+
49
+ -- AddForeignKey
50
+ ALTER TABLE "message" ADD CONSTRAINT "message_conversationId_fkey" FOREIGN KEY ("conversationId") REFERENCES "conversation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,3 @@
1
+ # Please do not edit this file manually
2
+ # It should be added in your version-control system (i.e. Git)
3
+ provider = "postgresql"
@@ -0,0 +1,117 @@
1
+ generator client {
2
+ provider = "prisma-client-js"
3
+ }
4
+
5
+ datasource db {
6
+ provider = "postgresql"
7
+ url = env("DATABASE_URL")
8
+ directUrl = env("DIRECT_DATABASE_URL")
9
+ }
10
+
11
+ model Test {
12
+ id String @id @default(cuid())
13
+ name String
14
+ }
15
+
16
+ model User {
17
+ id String @id @default(cuid())
18
+ name String
19
+ email String @unique
20
+ emailVerified Boolean @default(false)
21
+ image String?
22
+ createdAt DateTime @default(now())
23
+ updatedAt DateTime @updatedAt
24
+ accounts Account[]
25
+ conversations Conversation[]
26
+ sessions Session[]
27
+
28
+ @@map("user")
29
+ }
30
+
31
+ model Session {
32
+ id String @id @default(cuid())
33
+ expiresAt DateTime
34
+ token String @unique
35
+ createdAt DateTime @default(now())
36
+ updatedAt DateTime @updatedAt
37
+ ipAddress String?
38
+ userAgent String?
39
+ userId String
40
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
41
+
42
+ @@index([userId])
43
+ @@map("session")
44
+ }
45
+
46
+ model Account {
47
+ id String @id @default(cuid())
48
+ accountId String
49
+ providerId String
50
+ userId String
51
+ accessToken String?
52
+ refreshToken String?
53
+ idToken String?
54
+ accessTokenExpiresAt DateTime?
55
+ refreshTokenExpiresAt DateTime?
56
+ scope String?
57
+ password String?
58
+ createdAt DateTime @default(now())
59
+ updatedAt DateTime @updatedAt
60
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
61
+
62
+ @@index([userId])
63
+ @@map("account")
64
+ }
65
+
66
+ model Verification {
67
+ id String @id @default(cuid())
68
+ identifier String
69
+ value String
70
+ expiresAt DateTime
71
+ createdAt DateTime @default(now())
72
+ updatedAt DateTime @updatedAt
73
+
74
+ @@index([identifier])
75
+ @@map("verification")
76
+ }
77
+
78
+ model DeviceCode {
79
+ id String @id @default(cuid())
80
+ deviceCode String
81
+ userCode String
82
+ userId String?
83
+ expiresAt DateTime
84
+ status String
85
+ lastPolledAt DateTime?
86
+ pollingInterval Int?
87
+ clientId String?
88
+ scope String?
89
+
90
+ @@map("deviceCode")
91
+ }
92
+
93
+ model Conversation {
94
+ id String @id @default(cuid())
95
+ userId String
96
+ title String
97
+ mode String @default("chat")
98
+ createdAt DateTime @default(now())
99
+ updatedAt DateTime @updatedAt
100
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
101
+ messages Message[]
102
+
103
+ @@index([userId])
104
+ @@map("conversation")
105
+ }
106
+
107
+ model Message {
108
+ id String @id @default(cuid())
109
+ conversationId String
110
+ role String
111
+ content String
112
+ createdAt DateTime @default(now())
113
+ conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
114
+
115
+ @@index([conversationId])
116
+ @@map("message")
117
+ }
@@ -1,16 +1,15 @@
1
1
  import { google } from "@ai-sdk/google";
2
2
  import { streamText, generateObject } from "ai";
3
- import { config } from "../config/googleConfig.js";
3
+ import { config } from "../../config/googleConfig.js";
4
4
  import chalk from "chalk";
5
+ import { requireGeminiApiKeySync } from "../../lib/orbitalConfig.js";
5
6
 
6
7
  export class AIService {
7
8
  constructor() {
8
- if (!config.googleApiKey) {
9
- throw new Error("GOOGLE_GENERATIVE_AI_API_KEY is not set in env");
10
- }
9
+ const apiKey = requireGeminiApiKeySync();
11
10
 
12
11
  this.model = google(config.model, {
13
- apiKey: config.googleApiKey,
12
+ apiKey,
14
13
  });
15
14
  }
16
15
 
@@ -4,17 +4,18 @@ import { text, isCancel, cancel, intro, outro, confirm } from "@clack/prompts";
4
4
  import yoctoSpinner from "yocto-spinner";
5
5
  import { marked } from "marked";
6
6
  import { markedTerminal } from "marked-terminal";
7
+ import { getStoredToken } from "../../lib/token.js";
8
+ import {
9
+ createApplicationFiles,
10
+ displayFileTree,
11
+ generateApplicationPlan,
12
+ } from "../../config/agentConfig.js";
13
+ import { apiRequestSafe } from "../utils/apiClient.js";
7
14
  import { AIService } from "../ai/googleService.js";
8
- import { ChatServiceClient as ChatService } from "../utils/chatServiceClient.js";
9
- import { getStoredToken } from "../utils/token.js";
10
-
11
- import { generateApplication } from "../config/agentConfig.js";
15
+ import { requireGeminiApiKey } from "../../lib/orbitalConfig.js";
12
16
 
13
17
  marked.use(markedTerminal());
14
18
 
15
- let aiService;
16
- const chatService = new ChatService();
17
-
18
19
  const getEnabledToolNames = () => {
19
20
  return [];
20
21
  };
@@ -27,39 +28,30 @@ const getUserFromToken = async () => {
27
28
  }
28
29
 
29
30
  const spinner = yoctoSpinner({ text: "Authenticating..." }).start();
30
-
31
- let user;
32
31
  try {
33
- const response = await fetch("https://smart-cli-based-agent.onrender.com/api/me", {
34
- headers: {
35
- Authorization: `Bearer ${token.access_token}`
36
- }
37
- });
32
+ const result = await apiRequestSafe("/api/cli/me");
33
+ const user = result?.user;
38
34
 
39
- if (!response.ok) {
40
- throw new Error("Failed to authenticate.");
35
+ if (!user) {
36
+ spinner.error("User not found");
37
+ throw new Error("User not found. Please login again");
41
38
  }
42
- const data = await response.json();
43
- user = data?.user;
44
39
 
45
- if (!user) throw new Error("User not found");
46
- } catch(err) {
47
- spinner.error("Authentication failed");
48
- throw new Error("User not found or connection failed. Please login again.");
40
+ spinner.success(`Welcome back, ${user.name}!`);
41
+ return user;
42
+ } finally {
43
+ spinner.stop();
49
44
  }
50
-
51
- spinner.success(`Welcome back, ${user.name}!`);
52
- return user;
53
45
  };
54
46
 
55
47
  const initConversation = async (userId, conversationId = null, mode = "tool") => {
56
48
  const spinner = yoctoSpinner({ text: "Loading conversation..." }).start();
57
49
 
58
- const conversation = await chatService.getOrCreateConversation(
59
- userId,
60
- conversationId,
61
- mode
62
- );
50
+ const result = await apiRequestSafe("/api/cli/conversations/init", {
51
+ method: "POST",
52
+ body: { conversationId, mode },
53
+ });
54
+ const conversation = result?.conversation;
63
55
 
64
56
  spinner.success("Conversation Loaded");
65
57
 
@@ -90,7 +82,10 @@ const initConversation = async (userId, conversationId = null, mode = "tool") =>
90
82
  };
91
83
 
92
84
  const saveMessage = async (conversationId, role, content) => {
93
- return await chatService.addMessage(conversationId, role, content);
85
+ return await apiRequestSafe("/api/cli/messages", {
86
+ method: "POST",
87
+ body: { conversationId, role, content },
88
+ });
94
89
  };
95
90
 
96
91
  const agentLoop = async (conversation) => {
@@ -154,21 +149,27 @@ const agentLoop = async (conversation) => {
154
149
  await saveMessage(conversation.id, "user", userInput);
155
150
 
156
151
  try {
157
- const result = await generateApplication(
158
- userInput,
159
- aiService,
160
- process.cwd()
161
- );
152
+ await requireGeminiApiKey();
153
+ const aiService = new AIService();
154
+ const application = await generateApplicationPlan(userInput, aiService);
162
155
 
163
- if (!result || !result.success) {
164
- throw new Error("Generation returned no result.");
156
+ if (!application || !Array.isArray(application.files) || application.files.length === 0) {
157
+ throw new Error("Generation returned no files.");
165
158
  }
166
159
 
160
+ displayFileTree(application.files, application.folderName);
161
+
162
+ const appDir = await createApplicationFiles(
163
+ process.cwd(),
164
+ application.folderName,
165
+ application.files
166
+ );
167
+
167
168
  const responseMessage =
168
- `Generated application: ${result.folderName}\n` +
169
- `Files created: ${result.files.length}\n` +
170
- `Location: ${result.appDir}\n\n` +
171
- `Setup commands:\n${result.commands.join("\n")}`;
169
+ `Generated application: ${application.folderName}\n` +
170
+ `Files created: ${application.files.length}\n` +
171
+ `Location: ${appDir}\n\n` +
172
+ `Setup commands:\n${(application.setupCommands || []).join("\n")}`;
172
173
 
173
174
  console.log(
174
175
  boxen(chalk.green(responseMessage), {
@@ -210,14 +211,6 @@ const agentLoop = async (conversation) => {
210
211
 
211
212
  export const startAgentChat = async (conversationId = null) => {
212
213
  try {
213
- if (!process.env.GOOGLE_GENERATIVE_AI_API_KEY) {
214
- throw new Error(
215
- "Gemini API key is not set. Run: orbital setkey <your-gemini-api-key>"
216
- );
217
- }
218
-
219
- aiService = new AIService();
220
-
221
214
  intro(
222
215
  boxen(
223
216
  chalk.bold.magenta("Orbital AI - Agent Mode\n\n") +