@vortex-ai/cli 0.1.50 → 0.1.55

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@vortex-ai/cli",
3
- "version": "0.1.50",
3
+ "version": "0.1.55",
4
4
  "description": "Vortex CLI - The main entry point",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {
@@ -12,9 +12,9 @@ cacheCommand
12
12
  const stats = await LLMCacheManager.getStats();
13
13
  console.log("\nLLM Cache Statistics\n");
14
14
  console.log(`Entries: ${stats.entries.toLocaleString()}`);
15
- console.log(`Hits: ${stats.hits.toLocaleString()}`);
15
+ console.log(`Saved API Calls: ${stats.hits.toLocaleString()}`);
16
16
  const storageMB = (stats.storage / 1024 / 1024).toFixed(2);
17
- console.log(`Storage: ${storageMB} MB\n`);
17
+ console.log(`Storage Used: ${storageMB} MB\n`);
18
18
  } catch (err) {
19
19
  console.error("Failed to retrieve cache stats:", err);
20
20
  }
@@ -80,11 +80,11 @@ export async function reviewCommand(options: any) {
80
80
 
81
81
  const allChunks: any[] = [];
82
82
  if (queries.length > 0) {
83
- spinner.text = `Hybrid searching for context...`;
84
- for (const query of queries) {
85
- const results = await indexer.hybridSearch(query, 3);
86
- allChunks.push(...results);
87
- }
83
+ spinner.text = `Hybrid searching for context (parallel)...`;
84
+ const allResults = await Promise.all(
85
+ queries.map(query => indexer.hybridSearch(query, 3))
86
+ );
87
+ allChunks.push(...allResults.flat());
88
88
  }
89
89
 
90
90
  const uniqueChunks = Array.from(
@@ -15,21 +15,33 @@ export async function searchCommand(options: any) {
15
15
  const indexer = new Indexer();
16
16
 
17
17
  try {
18
- spinner.text = "Running hybrid search (vector + BM25 + cross-encoder)...";
19
- const results = await indexer.hybridSearch(options.query, parseInt(options.limit, 10));
18
+ spinner.text = options.expandQuery ? "Expanding query and running parallel hybrid search..." : "Running hybrid search (vector + BM25 + cross-encoder)...";
20
19
 
21
- if (results.length === 0) {
20
+ let queriesToSearch = [options.query];
21
+ const agent = new IntelligenceAgent();
22
+
23
+ if (options.expandQuery) {
24
+ queriesToSearch = await agent.expandQuery(options.query);
25
+ }
26
+
27
+ const allResults = await Promise.all(
28
+ queriesToSearch.map(q => indexer.hybridSearch(q, parseInt(options.limit, 10)))
29
+ );
30
+
31
+ const flatResults = allResults.flat();
32
+ const uniqueResults = Array.from(new Map(flatResults.map((c) => [c.id, c])).values()).sort((a, b) => b.score - a.score).slice(0, parseInt(options.limit, 10));
33
+
34
+ if (uniqueResults.length === 0) {
22
35
  spinner.fail("No relevant code found.");
23
36
  return;
24
37
  }
25
38
 
26
- spinner.text = `Found ${results.length} relevant code chunks. Analyzing with AI engine...`;
39
+ spinner.text = `Found ${uniqueResults.length} relevant code chunks. Analyzing with AI engine...`;
27
40
 
28
41
  const memoryService = new MemoryService();
29
42
  const memories = await memoryService.recallRelevantMemories(options.query, 3);
30
43
 
31
- const agent = new IntelligenceAgent();
32
- const answer = await agent.answerQueryWithContext(options.query, results);
44
+ const answer = await agent.answerQueryWithContext(options.query, uniqueResults);
33
45
 
34
46
  spinner.succeed("Analysis complete!\n");
35
47
 
@@ -47,7 +59,7 @@ export async function searchCommand(options: any) {
47
59
  console.log(formatted);
48
60
 
49
61
  console.log(chalk.cyan.dim(" Reference Material (Hybrid Retrieval)"));
50
- results.forEach((res: any, i: number) => {
62
+ uniqueResults.forEach((res: any, i: number) => {
51
63
  const sources = res.sources ? res.sources.join("+") : "vector";
52
64
  const scoreStr = res.score ? (res.score * 100).toFixed(1) + '%' : 'N/A';
53
65
  console.log(chalk.gray(` │ [${i + 1}] ${res.file.replace(process.cwd(), '')} ➔ ${res.symbolPath || '(anonymous)'} (${scoreStr}) [${sources}]`));
@@ -59,7 +59,8 @@ Please fix this issue in the codebase.`;
59
59
  await solveCommand(prompt, {
60
60
  autoApprove: options.autoApprove,
61
61
  maxSteps: options.maxSteps,
62
- contextChunks: contextChunks
62
+ contextChunks: contextChunks,
63
+ verify: options.verify
63
64
  });
64
65
 
65
66
  } catch (err) {
@@ -22,7 +22,7 @@ import { initDatabase } from "@vortex/db";
22
22
  import { getGitRoot, isGitRepo } from "@vortex/git";
23
23
  import { VectorStore, LocalEmbedder, BM25Index, HybridRetriever } from "@vortex/retrieval";
24
24
 
25
- export async function solveCommand(prompt: string, options: { autoApprove?: boolean; maxSteps?: number; contextChunks?: AgentContextChunk[]; newProject?: string } = {}) {
25
+ export async function solveCommand(prompt: string, options: { autoApprove?: boolean; maxSteps?: number; contextChunks?: AgentContextChunk[]; newProject?: string; verify?: string | boolean } = {}) {
26
26
  let cwd = process.cwd();
27
27
 
28
28
  if (options.newProject) {
@@ -70,7 +70,7 @@ export async function solveCommand(prompt: string, options: { autoApprove?: bool
70
70
  if (!options.contextChunks || options.contextChunks.length === 0) {
71
71
  try {
72
72
  const indexer = new Indexer();
73
- const relevantContext = await indexer.hybridSearch(prompt, 5);
73
+ const relevantContext = await indexer.hybridSearch(prompt, 15);
74
74
  options.contextChunks = relevantContext.map((c: any) => ({
75
75
  file: c.file,
76
76
  symbolPath: c.symbolPath || "anonymous",
@@ -95,7 +95,10 @@ export async function solveCommand(prompt: string, options: { autoApprove?: bool
95
95
  const parsedPlan = JSON.parse(executionPlanStr);
96
96
  planSummary = parsedPlan.summary || planSummary;
97
97
  stepCount = parsedPlan.steps ? parsedPlan.steps.length : 0;
98
- executionPlan = parsedPlan.steps ? parsedPlan.steps.map((s: string, i: number) => `${i + 1}. ${s}`).join("\n") : executionPlanStr;
98
+ executionPlan = parsedPlan.steps ? parsedPlan.steps.map((s: any, i: number) => {
99
+ if (typeof s === 'string') return `${i + 1}. ${s}`;
100
+ return `${i + 1}. [${(s.action || 'MODIFY').toUpperCase()}] ${s.file || 'General'}\n ${s.description}`;
101
+ }).join("\n\n") : executionPlanStr;
99
102
  filesToRead = parsedPlan.filesToRead || [];
100
103
  } catch {
101
104
  executionPlan = executionPlanStr;
@@ -188,6 +191,7 @@ export async function solveCommand(prompt: string, options: { autoApprove?: bool
188
191
  },
189
192
  {
190
193
  initialState,
194
+ verifyCommand: options.verify,
191
195
  onToolCall: (toolName, args) => {
192
196
  if (toolName === "write_file") {
193
197
  spinner.text = `Writing ${args.path}...`;
package/src/index.ts CHANGED
@@ -89,6 +89,7 @@ program
89
89
  .description("Search the indexed codebase semantically and get an AI explanation")
90
90
  .requiredOption("-q, --query <text>", "Search query")
91
91
  .option("-l, --limit <number>", "Number of results to consider", "5")
92
+ .option("--expand-query", "Expand the search query using the LLM for better recall")
92
93
  .option("--no-cache", "Disable LLM response caching")
93
94
  .action(searchCommand);
94
95
 
@@ -121,6 +122,7 @@ program
121
122
  .option("--auto-approve", "Skip interactive prompts for file writes and shell commands")
122
123
  .option("--max-steps <number>", "Maximum number of agent loop iterations", Number, 30)
123
124
  .option("--new-project <folder>", "Create a new project folder and initialize git before solving")
125
+ .option("--verify [command]", "Run a verification command after completion (e.g., 'npm run check-types'). Agent will self-correct on failure.")
124
126
  .action((prompt, options) => solveCommand(prompt, options));
125
127
 
126
128
  program
@@ -129,6 +131,7 @@ program
129
131
  .requiredOption("--id <number>", "Issue number", Number)
130
132
  .option("--auto-approve", "Skip interactive prompts for file writes and shell commands")
131
133
  .option("--max-steps <number>", "Maximum number of agent loop iterations", Number, 30)
134
+ .option("--verify [command]", "Run a verification command after completion. Agent will self-correct on failure.")
132
135
  .action(solveIssueCommand);
133
136
 
134
137
  // ── AI-Powered Commands ──