@vortex-ai/cli 0.1.4 → 0.1.45

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,17 +1,18 @@
1
1
  {
2
2
  "name": "@vortex-ai/cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.45",
4
4
  "description": "Vortex CLI - The main entry point",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {
7
7
  "vortex": "./dist/index.js"
8
8
  },
9
9
  "scripts": {
10
- "build": "tsup src/index.ts --format cjs,esm --external @xenova/transformers",
10
+ "build": "tsup src/index.ts --format cjs,esm --external @xenova/transformers && cp ../db/prisma/schema.prisma ./schema.prisma",
11
11
  "dev": "tsx src/index.ts",
12
12
  "watch": "tsup src/index.ts --format cjs,esm --watch",
13
13
  "lint": "eslint .",
14
- "check-types": "tsc --noEmit"
14
+ "check-types": "tsc --noEmit",
15
+ "postinstall": "node -e \"const fs=require('fs'); if(fs.existsSync('./schema.prisma')){require('child_process').execSync('npx prisma generate --schema=./schema.prisma', {stdio:'inherit'})}\""
15
16
  },
16
17
  "dependencies": {
17
18
  "@octokit/rest": "^22.0.1",
@@ -19,6 +20,7 @@
19
20
  "@google/genai": "^2.5.0",
20
21
  "groq-sdk": "^1.2.1",
21
22
  "@prisma/client": "^5.14.0",
23
+ "prisma": "^5.14.0",
22
24
  "ignore": "^7.0.5",
23
25
  "minisearch": "^7.2.0",
24
26
  "@xenova/transformers": "^2.17.2",
package/schema.prisma ADDED
@@ -0,0 +1,70 @@
1
+ datasource db {
2
+ provider = "sqlite"
3
+ url = "file:./vortex.db"
4
+ }
5
+
6
+ generator client {
7
+ provider = "prisma-client-js"
8
+ }
9
+
10
+ model Chunk {
11
+ id String @id
12
+ file String
13
+ language String
14
+ name String
15
+ symbolPath String
16
+ kind String
17
+ parent String?
18
+ isExported Boolean
19
+ isAsync Boolean
20
+ signature String?
21
+ dependencies String // Stringified JSON array
22
+ startLine Int
23
+ endLine Int
24
+ hash String
25
+ content String
26
+ embedding String? // Stringified JSON array of floats
27
+ createdAt DateTime @default(now())
28
+ updatedAt DateTime @updatedAt
29
+ }
30
+
31
+ /// Persistent memory entries for architectural decisions, known bugs,
32
+ /// and review summaries. Enables Vortex to recall past context.
33
+ model Memory {
34
+ id String @id @default(cuid())
35
+ type String // "review_summary" | "architectural_decision" | "known_bug"
36
+ content String // The actual memory text
37
+ source String // e.g., "PR #42", "issue #15", "manual"
38
+ tags String // JSON array of tags for search
39
+ embedding String? // Stringified JSON array for vector search over memories
40
+ createdAt DateTime @default(now())
41
+ updatedAt DateTime @updatedAt
42
+ }
43
+
44
+ /// Historical review records for tracking past PR reviews.
45
+ /// Enables "Have we seen this pattern before?" queries.
46
+ model ReviewHistory {
47
+ id String @id @default(cuid())
48
+ prNumber Int
49
+ owner String
50
+ repo String
51
+ verdict String // SAFE_TO_MERGE | REQUIRES_CHANGES | NEEDS_DISCUSSION
52
+ summary String // Short summary of the review
53
+ findings String // JSON - full structured findings
54
+ createdAt DateTime @default(now())
55
+ }
56
+
57
+ /// Cache for LLM responses to reduce latency and API cost
58
+ model LLMCache {
59
+ key String @id
60
+ model String
61
+ response String
62
+
63
+ promptHash String
64
+ contextHash String
65
+ commitHash String?
66
+
67
+ createdAt DateTime @default(now())
68
+ lastAccessedAt DateTime @default(now())
69
+ hitCount Int @default(0)
70
+ }
@@ -0,0 +1,73 @@
1
+ import * as fs from "fs";
2
+ import * as os from "os";
3
+ import * as path from "path";
4
+ import * as dotenv from "dotenv";
5
+
6
+ const envPath = path.resolve(os.homedir(), ".vortexenv");
7
+
8
+ function readEnv(): Record<string, string> {
9
+ if (!fs.existsSync(envPath)) return {};
10
+ const content = fs.readFileSync(envPath, "utf-8");
11
+ return dotenv.parse(content);
12
+ }
13
+
14
+ function writeEnv(env: Record<string, string>) {
15
+ const content = Object.entries(env)
16
+ .map(([k, v]) => `${k}="${v.replace(/"/g, '\\"')}"`)
17
+ .join("\n");
18
+ fs.writeFileSync(envPath, content + "\n", { mode: 0o600 });
19
+ }
20
+
21
+ export async function configSet(provider: string, value: string) {
22
+ const { default: chalk } = await import("chalk");
23
+
24
+ const providerUpper = provider.toUpperCase();
25
+ let envKey = "";
26
+
27
+ if (providerUpper === "GEMINI") {
28
+ envKey = "GEMINI_API_KEY";
29
+ } else if (providerUpper === "GROQ") {
30
+ envKey = "GROQ_API_KEY";
31
+ } else {
32
+ console.log(chalk.red(`Invalid option: ${chalk.bold(provider)}. Supported options are 'gemini' and 'groq'.`));
33
+ console.log(chalk.gray(`Usage: vortex config set gemini <your-key>`));
34
+ process.exit(1);
35
+ }
36
+
37
+ const env = readEnv();
38
+ env[envKey] = value;
39
+ writeEnv(env);
40
+ console.log(chalk.green(`✓ Successfully set ${chalk.bold(envKey)}`));
41
+ }
42
+
43
+ export async function configGet(key: string) {
44
+ const { default: chalk } = await import("chalk");
45
+ const env = readEnv();
46
+ if (env[key]) {
47
+ console.log(env[key]);
48
+ } else {
49
+ console.log(chalk.gray(`Key ${chalk.bold(key)} is not set.`));
50
+ }
51
+ }
52
+
53
+ export async function configList() {
54
+ const { default: chalk } = await import("chalk");
55
+ const env = readEnv();
56
+ const keys = Object.keys(env);
57
+ if (keys.length === 0) {
58
+ console.log(chalk.gray("No configuration values set in ~/.vortexenv"));
59
+ return;
60
+ }
61
+
62
+ console.log(chalk.blue.bold("\nVortex Global Configuration:\n"));
63
+ for (const [k, v] of Object.entries(env)) {
64
+ let masked = "***";
65
+ if (v.length > 10) {
66
+ masked = `${v.substring(0, 4)}...${v.substring(v.length - 4)}`;
67
+ } else if (v.length > 0) {
68
+ masked = v;
69
+ }
70
+ console.log(` ${chalk.cyan.bold(k)}: ${chalk.gray(masked)}`);
71
+ }
72
+ console.log(`\nLocation: ${chalk.gray(envPath)}\n`);
73
+ }
package/src/index.ts CHANGED
@@ -5,6 +5,9 @@ import * as path from "path";
5
5
  import * as dotenv from "dotenv";
6
6
  import * as os from "os";
7
7
 
8
+ // Suppress dotenv logging
9
+ process.env.DOTENV_CONFIG_QUIET = "true";
10
+
8
11
 
9
12
  const monorepoEnv = path.resolve(__dirname, "../../../.env");
10
13
  if (require("fs").existsSync(monorepoEnv)) {
@@ -39,13 +42,16 @@ import { analyzeCommand } from "./commands/analyze";
39
42
  import { solveCommand } from "./commands/solve";
40
43
  import { solveIssueCommand } from "./commands/solve-issue";
41
44
  import { cacheCommand } from "./commands/cache";
45
+ import { configSet, configGet, configList } from "./commands/config";
42
46
 
43
47
  const program = new Command();
44
48
 
49
+ const { version } = require("../package.json");
50
+
45
51
  program
46
52
  .name("vortex")
47
53
  .description("Developer Intelligence & PR Review Engine")
48
- .version("0.1.0");
54
+ .version(version);
49
55
 
50
56
  program.hook("preAction", (thisCommand, actionCommand) => {
51
57
  if (actionCommand.opts().cache === false) {
@@ -135,6 +141,25 @@ program
135
141
  .option("--no-cache", "Disable LLM response caching")
136
142
  .action(analyzeCommand);
137
143
 
144
+ const configCmd = program
145
+ .command("config")
146
+ .description("Manage global configuration and API keys");
147
+
148
+ configCmd
149
+ .command("set <provider> <key>")
150
+ .description("Set an API key for a specific provider (gemini or groq)")
151
+ .action(configSet);
152
+
153
+ configCmd
154
+ .command("get <key>")
155
+ .description("Get a global configuration value")
156
+ .action(configGet);
157
+
158
+ configCmd
159
+ .command("list")
160
+ .description("List all global configuration values")
161
+ .action(configList);
162
+
138
163
  program.addCommand(cacheCommand);
139
164
 
140
165
  program.parse();