voyageai-cli 1.30.1 → 1.30.2
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/README.md +4 -4
- package/package.json +1 -1
- package/src/cli.js +2 -0
- package/src/commands/about.js +3 -3
- package/src/commands/code-search.js +751 -0
- package/src/commands/doctor.js +1 -1
- package/src/commands/index-workspace.js +9 -5
- package/src/commands/playground.js +9 -1
- package/src/commands/quickstart.js +4 -4
- package/src/commands/workflow.js +132 -65
- package/src/lib/catalog.js +4 -2
- package/src/lib/code-search.js +315 -0
- package/src/lib/codegen.js +1 -1
- package/src/lib/explanations.js +3 -3
- package/src/lib/github.js +226 -0
- package/src/lib/template-engine.js +154 -20
- package/src/lib/workflow-builder.js +753 -0
- package/src/lib/workflow-formatters.js +454 -0
- package/src/lib/workflow-input-cache.js +111 -0
- package/src/lib/workflow-scaffold.js +1 -1
- package/src/lib/workflow.js +91 -1
- package/src/mcp/schemas/index.js +130 -0
- package/src/mcp/server.js +17 -4
- package/src/mcp/tools/authoring.js +662 -0
- package/src/mcp/tools/code-search.js +620 -0
- package/src/mcp/tools/ingest.js +2 -5
- package/src/mcp/tools/retrieval.js +2 -15
- package/src/mcp/tools/workspace.js +1 -12
- package/src/mcp/utils.js +20 -0
- package/src/playground/help/workflow-nodes.js +127 -2
- package/src/playground/index.html +1366 -24
- package/src/workflows/code-review.json +110 -0
- package/src/workflows/cost-analysis.json +5 -0
- package/src/workflows/tests/code-review.fresh-index.test.json +83 -0
- package/src/workflows/tests/code-review.happy-path.test.json +121 -0
- package/src/workflows/tests/code-review.no-question.test.json +70 -0
- package/src/workflows/tests/smart-ingest.duplicate-detected.test.json +2 -2
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://vai.dev/schemas/workflow-v1.json",
|
|
3
|
+
"name": "Code Review Assistant",
|
|
4
|
+
"description": "Index a codebase, find similar patterns, and surface related code for review. Paste a code snippet and get context from across the project — similar implementations, related functions, and architectural patterns.",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"branding": {
|
|
7
|
+
"icon": "code",
|
|
8
|
+
"color": "#06B6D4"
|
|
9
|
+
},
|
|
10
|
+
"inputs": {
|
|
11
|
+
"source": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "Local directory path or GitHub repo URL to analyze",
|
|
14
|
+
"required": true
|
|
15
|
+
},
|
|
16
|
+
"code": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "Code snippet to review — finds similar patterns and related implementations",
|
|
19
|
+
"required": true
|
|
20
|
+
},
|
|
21
|
+
"question": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "Optional question about the code (e.g., 'are there any other retry implementations?')",
|
|
24
|
+
"default": ""
|
|
25
|
+
},
|
|
26
|
+
"language": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "Filter results to a specific language (e.g., 'js', 'py', 'go')"
|
|
29
|
+
},
|
|
30
|
+
"limit": {
|
|
31
|
+
"type": "number",
|
|
32
|
+
"description": "Maximum results per search step",
|
|
33
|
+
"default": 5
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"defaults": {
|
|
37
|
+
"db": "vai_code_search"
|
|
38
|
+
},
|
|
39
|
+
"steps": [
|
|
40
|
+
{
|
|
41
|
+
"id": "check_index",
|
|
42
|
+
"name": "Check if codebase is already indexed",
|
|
43
|
+
"tool": "code_status",
|
|
44
|
+
"inputs": {
|
|
45
|
+
"db": "{{ defaults.db }}"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "index_codebase",
|
|
50
|
+
"name": "Index codebase (skip if already indexed and fresh)",
|
|
51
|
+
"tool": "code_index",
|
|
52
|
+
"inputs": {
|
|
53
|
+
"source": "{{ inputs.source }}",
|
|
54
|
+
"db": "{{ defaults.db }}",
|
|
55
|
+
"refresh": true
|
|
56
|
+
},
|
|
57
|
+
"condition": "{{ !check_index.output || check_index.output.totalChunks === 0 }}"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"id": "find_similar",
|
|
61
|
+
"name": "Find similar code patterns across the codebase",
|
|
62
|
+
"tool": "code_find_similar",
|
|
63
|
+
"inputs": {
|
|
64
|
+
"code": "{{ inputs.code }}",
|
|
65
|
+
"db": "{{ defaults.db }}",
|
|
66
|
+
"collection": "{{ index_codebase.output.collection || check_index.output.collection }}",
|
|
67
|
+
"limit": "{{ inputs.limit }}",
|
|
68
|
+
"language": "{{ inputs.language }}",
|
|
69
|
+
"threshold": 0.4
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"id": "contextual_search",
|
|
74
|
+
"name": "Search for related architectural context",
|
|
75
|
+
"tool": "code_search",
|
|
76
|
+
"inputs": {
|
|
77
|
+
"query": "{{ inputs.question || 'functions and modules related to: ' + inputs.code }}",
|
|
78
|
+
"db": "{{ defaults.db }}",
|
|
79
|
+
"collection": "{{ index_codebase.output.collection || check_index.output.collection }}",
|
|
80
|
+
"limit": "{{ inputs.limit }}",
|
|
81
|
+
"language": "{{ inputs.language }}",
|
|
82
|
+
"rerank": true
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"id": "deep_query",
|
|
87
|
+
"name": "Answer specific question about the code",
|
|
88
|
+
"tool": "code_query",
|
|
89
|
+
"inputs": {
|
|
90
|
+
"query": "{{ inputs.question }}",
|
|
91
|
+
"db": "{{ defaults.db }}",
|
|
92
|
+
"collection": "{{ index_codebase.output.collection || check_index.output.collection }}",
|
|
93
|
+
"limit": 3,
|
|
94
|
+
"language": "{{ inputs.language }}"
|
|
95
|
+
},
|
|
96
|
+
"condition": "{{ inputs.question && inputs.question.length > 0 }}"
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
"output": {
|
|
100
|
+
"similarPatterns": "{{ find_similar.output.results }}",
|
|
101
|
+
"similarCount": "{{ find_similar.output.metadata.resultCount }}",
|
|
102
|
+
"relatedCode": "{{ contextual_search.output.results }}",
|
|
103
|
+
"relatedCount": "{{ contextual_search.output.metadata.resultCount }}",
|
|
104
|
+
"answer": "{{ deep_query.output.results }}",
|
|
105
|
+
"indexStatus": {
|
|
106
|
+
"totalFiles": "{{ check_index.output.uniqueFiles || index_codebase.output.filesIndexed }}",
|
|
107
|
+
"totalChunks": "{{ check_index.output.totalChunks || index_codebase.output.chunksCreated }}"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "code-review: fresh index required (no existing index)",
|
|
3
|
+
"inputs": {
|
|
4
|
+
"source": "https://github.com/mrlynn/voyageai-cli",
|
|
5
|
+
"code": "function generateEmbeddings(texts, model) { ... }",
|
|
6
|
+
"limit": 5
|
|
7
|
+
},
|
|
8
|
+
"mocks": {
|
|
9
|
+
"code_status": {
|
|
10
|
+
"totalChunks": 0,
|
|
11
|
+
"uniqueFiles": 0,
|
|
12
|
+
"languages": {},
|
|
13
|
+
"lastIndexed": null,
|
|
14
|
+
"indexes": []
|
|
15
|
+
},
|
|
16
|
+
"code_index": {
|
|
17
|
+
"source": "https://github.com/mrlynn/voyageai-cli",
|
|
18
|
+
"sourceType": "github",
|
|
19
|
+
"db": "vai_code_search",
|
|
20
|
+
"collection": "voyageai_cli_code",
|
|
21
|
+
"model": "voyage-code-3",
|
|
22
|
+
"filesFound": 89,
|
|
23
|
+
"filesIndexed": 89,
|
|
24
|
+
"chunksCreated": 642,
|
|
25
|
+
"totalTokens": 185000,
|
|
26
|
+
"errors": [],
|
|
27
|
+
"timeMs": 8400,
|
|
28
|
+
"refresh": true,
|
|
29
|
+
"indexName": "code_search_index"
|
|
30
|
+
},
|
|
31
|
+
"code_find_similar": {
|
|
32
|
+
"results": [
|
|
33
|
+
{
|
|
34
|
+
"source": "src/lib/api.js",
|
|
35
|
+
"language": "js",
|
|
36
|
+
"startLine": 45,
|
|
37
|
+
"endLine": 78,
|
|
38
|
+
"symbols": ["generateEmbeddings", "batchEmbed"],
|
|
39
|
+
"content": "async function generateEmbeddings(texts, model, opts) { ... }",
|
|
40
|
+
"score": 0.962,
|
|
41
|
+
"chunkType": "boundary"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"metadata": {
|
|
45
|
+
"collection": "voyageai_cli_code",
|
|
46
|
+
"model": "voyage-code-3",
|
|
47
|
+
"resultCount": 1,
|
|
48
|
+
"timeMs": 145
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"code_search": {
|
|
52
|
+
"results": [
|
|
53
|
+
{
|
|
54
|
+
"source": "src/lib/api.js",
|
|
55
|
+
"language": "js",
|
|
56
|
+
"startLine": 1,
|
|
57
|
+
"endLine": 30,
|
|
58
|
+
"symbols": ["apiRequest", "BASE_URL"],
|
|
59
|
+
"content": "const BASE_URL = process.env.VOYAGE_API_URL || 'https://ai.mongodb.com/v1/'; ...",
|
|
60
|
+
"score": 0.834
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
"metadata": {
|
|
64
|
+
"collection": "voyageai_cli_code",
|
|
65
|
+
"model": "voyage-code-3",
|
|
66
|
+
"reranked": true,
|
|
67
|
+
"resultCount": 1,
|
|
68
|
+
"timeMs": 210
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"code_query": null
|
|
72
|
+
},
|
|
73
|
+
"expect": {
|
|
74
|
+
"steps": {
|
|
75
|
+
"check_index": { "status": "completed" },
|
|
76
|
+
"index_codebase": { "status": "completed" },
|
|
77
|
+
"find_similar": { "status": "completed" },
|
|
78
|
+
"contextual_search": { "status": "completed" },
|
|
79
|
+
"deep_query": { "status": "skipped" }
|
|
80
|
+
},
|
|
81
|
+
"noErrors": true
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "code-review: find similar patterns with contextual search",
|
|
3
|
+
"inputs": {
|
|
4
|
+
"source": "/Users/dev/myapp",
|
|
5
|
+
"code": "async function retryWithBackoff(fn, maxRetries = 3) {\n for (let i = 0; i < maxRetries; i++) {\n try { return await fn(); }\n catch (e) { if (i === maxRetries - 1) throw e; await sleep(Math.pow(2, i) * 1000); }\n }\n}",
|
|
6
|
+
"question": "are there other retry or backoff implementations?",
|
|
7
|
+
"language": "js",
|
|
8
|
+
"limit": 5
|
|
9
|
+
},
|
|
10
|
+
"mocks": {
|
|
11
|
+
"code_status": {
|
|
12
|
+
"totalChunks": 1823,
|
|
13
|
+
"uniqueFiles": 247,
|
|
14
|
+
"collection": "myapp_code",
|
|
15
|
+
"languages": { "js": 180, "ts": 45, "json": 22 },
|
|
16
|
+
"lastIndexed": "2026-02-16T12:00:00.000Z",
|
|
17
|
+
"indexes": [{ "name": "code_search_index", "status": "READY" }]
|
|
18
|
+
},
|
|
19
|
+
"code_index": null,
|
|
20
|
+
"code_find_similar": {
|
|
21
|
+
"results": [
|
|
22
|
+
{
|
|
23
|
+
"source": "src/lib/http-client.js",
|
|
24
|
+
"language": "js",
|
|
25
|
+
"startLine": 88,
|
|
26
|
+
"endLine": 112,
|
|
27
|
+
"symbols": ["retryRequest", "exponentialDelay"],
|
|
28
|
+
"content": "async function retryRequest(url, opts, retries = 5) {\n const exponentialDelay = (attempt) => Math.pow(2, attempt) * 500;\n for (let attempt = 0; attempt < retries; attempt++) { ... }",
|
|
29
|
+
"score": 0.921,
|
|
30
|
+
"chunkType": "boundary"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"source": "src/lib/queue.js",
|
|
34
|
+
"language": "js",
|
|
35
|
+
"startLine": 34,
|
|
36
|
+
"endLine": 58,
|
|
37
|
+
"symbols": ["processWithRetry"],
|
|
38
|
+
"content": "async function processWithRetry(task, { maxAttempts = 3, backoff = 'exponential' }) { ... }",
|
|
39
|
+
"score": 0.867,
|
|
40
|
+
"chunkType": "boundary"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"source": "src/utils/resilience.js",
|
|
44
|
+
"language": "js",
|
|
45
|
+
"startLine": 1,
|
|
46
|
+
"endLine": 30,
|
|
47
|
+
"symbols": ["circuitBreaker", "withTimeout"],
|
|
48
|
+
"content": "function circuitBreaker(fn, { threshold = 5, resetMs = 30000 }) { ... }",
|
|
49
|
+
"score": 0.743,
|
|
50
|
+
"chunkType": "boundary"
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"metadata": {
|
|
54
|
+
"collection": "myapp_code",
|
|
55
|
+
"model": "voyage-code-3",
|
|
56
|
+
"resultCount": 3,
|
|
57
|
+
"timeMs": 187
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"code_search": {
|
|
61
|
+
"results": [
|
|
62
|
+
{
|
|
63
|
+
"source": "src/lib/http-client.js",
|
|
64
|
+
"language": "js",
|
|
65
|
+
"startLine": 1,
|
|
66
|
+
"endLine": 25,
|
|
67
|
+
"symbols": ["createClient", "DEFAULT_TIMEOUT"],
|
|
68
|
+
"content": "const DEFAULT_TIMEOUT = 30000;\nfunction createClient(baseUrl, opts) { ... }",
|
|
69
|
+
"score": 0.856
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"source": "docs/resilience.md",
|
|
73
|
+
"language": "md",
|
|
74
|
+
"startLine": 1,
|
|
75
|
+
"endLine": 40,
|
|
76
|
+
"symbols": [],
|
|
77
|
+
"content": "# Resilience Patterns\n\nThis project uses exponential backoff with jitter for all HTTP retries...",
|
|
78
|
+
"score": 0.812
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"metadata": {
|
|
82
|
+
"collection": "myapp_code",
|
|
83
|
+
"model": "voyage-code-3",
|
|
84
|
+
"rerankModel": "rerank-2.5",
|
|
85
|
+
"reranked": true,
|
|
86
|
+
"resultCount": 2,
|
|
87
|
+
"timeMs": 234
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"code_query": {
|
|
91
|
+
"results": [
|
|
92
|
+
{
|
|
93
|
+
"source": "src/lib/http-client.js",
|
|
94
|
+
"language": "js",
|
|
95
|
+
"startLine": 88,
|
|
96
|
+
"endLine": 112,
|
|
97
|
+
"symbols": ["retryRequest", "exponentialDelay"],
|
|
98
|
+
"content": "async function retryRequest(url, opts, retries = 5) { ... }",
|
|
99
|
+
"score": 0.943
|
|
100
|
+
}
|
|
101
|
+
],
|
|
102
|
+
"metadata": {
|
|
103
|
+
"collection": "myapp_code",
|
|
104
|
+
"model": "voyage-code-3",
|
|
105
|
+
"reranked": true,
|
|
106
|
+
"resultCount": 1,
|
|
107
|
+
"timeMs": 198
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"expect": {
|
|
112
|
+
"steps": {
|
|
113
|
+
"check_index": { "status": "completed" },
|
|
114
|
+
"index_codebase": { "status": "skipped" },
|
|
115
|
+
"find_similar": { "status": "completed" },
|
|
116
|
+
"contextual_search": { "status": "completed" },
|
|
117
|
+
"deep_query": { "status": "completed" }
|
|
118
|
+
},
|
|
119
|
+
"noErrors": true
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "code-review: no question — skip deep_query, auto-generate search from snippet",
|
|
3
|
+
"inputs": {
|
|
4
|
+
"source": "/Users/dev/myapp",
|
|
5
|
+
"code": "class DatabasePool {\n constructor(uri, { maxSize = 10, idleTimeoutMs = 30000 }) {\n this.pool = [];\n this.maxSize = maxSize;\n }\n async acquire() { ... }\n release(conn) { ... }\n}",
|
|
6
|
+
"limit": 3
|
|
7
|
+
},
|
|
8
|
+
"mocks": {
|
|
9
|
+
"code_status": {
|
|
10
|
+
"totalChunks": 500,
|
|
11
|
+
"uniqueFiles": 80,
|
|
12
|
+
"collection": "myapp_code",
|
|
13
|
+
"languages": { "js": 60, "ts": 20 },
|
|
14
|
+
"lastIndexed": "2026-02-16T10:00:00.000Z",
|
|
15
|
+
"indexes": [{ "name": "code_search_index", "status": "READY" }]
|
|
16
|
+
},
|
|
17
|
+
"code_index": null,
|
|
18
|
+
"code_find_similar": {
|
|
19
|
+
"results": [
|
|
20
|
+
{
|
|
21
|
+
"source": "src/lib/redis-pool.js",
|
|
22
|
+
"language": "js",
|
|
23
|
+
"startLine": 5,
|
|
24
|
+
"endLine": 45,
|
|
25
|
+
"symbols": ["RedisPool", "acquire", "release"],
|
|
26
|
+
"content": "class RedisPool { constructor(opts) { ... } async acquire() { ... } }",
|
|
27
|
+
"score": 0.889,
|
|
28
|
+
"chunkType": "boundary"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"metadata": {
|
|
32
|
+
"collection": "myapp_code",
|
|
33
|
+
"model": "voyage-code-3",
|
|
34
|
+
"resultCount": 1,
|
|
35
|
+
"timeMs": 156
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"code_search": {
|
|
39
|
+
"results": [
|
|
40
|
+
{
|
|
41
|
+
"source": "src/lib/mongo.js",
|
|
42
|
+
"language": "js",
|
|
43
|
+
"startLine": 12,
|
|
44
|
+
"endLine": 50,
|
|
45
|
+
"symbols": ["getMongoCollection", "closeClient"],
|
|
46
|
+
"content": "async function getMongoCollection(db, collection) { ... }",
|
|
47
|
+
"score": 0.801
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"metadata": {
|
|
51
|
+
"collection": "myapp_code",
|
|
52
|
+
"model": "voyage-code-3",
|
|
53
|
+
"reranked": true,
|
|
54
|
+
"resultCount": 1,
|
|
55
|
+
"timeMs": 189
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"code_query": null
|
|
59
|
+
},
|
|
60
|
+
"expect": {
|
|
61
|
+
"steps": {
|
|
62
|
+
"check_index": { "status": "completed" },
|
|
63
|
+
"index_codebase": { "status": "skipped" },
|
|
64
|
+
"find_similar": { "status": "completed" },
|
|
65
|
+
"contextual_search": { "status": "completed" },
|
|
66
|
+
"deep_query": { "status": "skipped" }
|
|
67
|
+
},
|
|
68
|
+
"noErrors": true
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smart-ingest: duplicate detected (high similarity)",
|
|
3
|
-
"description": "
|
|
3
|
+
"description": "When a near-duplicate is found (similarity above 0.85), the ingest_doc step is correctly skipped to avoid ingesting duplicate content.",
|
|
4
4
|
"inputs": {
|
|
5
5
|
"text": "A document that already exists in the knowledge base",
|
|
6
6
|
"source": "existing-doc.md",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"steps": {
|
|
28
28
|
"check_existing": { "status": "completed" },
|
|
29
29
|
"similarity_check": { "status": "completed" },
|
|
30
|
-
"ingest_doc": { "status": "
|
|
30
|
+
"ingest_doc": { "status": "skipped" }
|
|
31
31
|
},
|
|
32
32
|
"noErrors": true
|
|
33
33
|
}
|