voyageai-cli 1.30.0 → 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.
Files changed (82) hide show
  1. package/README.md +4 -4
  2. package/package.json +1 -1
  3. package/src/cli.js +8 -0
  4. package/src/commands/about.js +3 -3
  5. package/src/commands/chat.js +32 -11
  6. package/src/commands/code-search.js +751 -0
  7. package/src/commands/doctor.js +1 -1
  8. package/src/commands/export.js +124 -0
  9. package/src/commands/import.js +195 -0
  10. package/src/commands/index-workspace.js +243 -0
  11. package/src/commands/mcp-server.js +113 -3
  12. package/src/commands/playground.js +120 -4
  13. package/src/commands/quickstart.js +4 -4
  14. package/src/commands/workflow.js +132 -65
  15. package/src/lib/catalog.js +4 -2
  16. package/src/lib/code-search.js +315 -0
  17. package/src/lib/codegen.js +1 -1
  18. package/src/lib/explanations.js +3 -3
  19. package/src/lib/export/contexts/benchmark-export.js +27 -0
  20. package/src/lib/export/contexts/chat-export.js +41 -0
  21. package/src/lib/export/contexts/explore-export.js +22 -0
  22. package/src/lib/export/contexts/search-export.js +54 -0
  23. package/src/lib/export/contexts/workflow-export.js +80 -0
  24. package/src/lib/export/formats/clipboard-export.js +29 -0
  25. package/src/lib/export/formats/csv-export.js +45 -0
  26. package/src/lib/export/formats/json-export.js +50 -0
  27. package/src/lib/export/formats/markdown-export.js +189 -0
  28. package/src/lib/export/formats/mermaid-export.js +274 -0
  29. package/src/lib/export/formats/pdf-export.js +117 -0
  30. package/src/lib/export/formats/png-export.js +96 -0
  31. package/src/lib/export/formats/svg-export.js +116 -0
  32. package/src/lib/export/index.js +175 -0
  33. package/src/lib/github.js +226 -0
  34. package/src/lib/template-engine.js +154 -20
  35. package/src/lib/workflow-builder.js +753 -0
  36. package/src/lib/workflow-formatters.js +454 -0
  37. package/src/lib/workflow-input-cache.js +111 -0
  38. package/src/lib/workflow-scaffold.js +1 -1
  39. package/src/lib/workflow.js +297 -28
  40. package/src/mcp/install.js +280 -7
  41. package/src/mcp/schemas/index.js +170 -0
  42. package/src/mcp/server.js +19 -4
  43. package/src/mcp/tools/authoring.js +662 -0
  44. package/src/mcp/tools/code-search.js +620 -0
  45. package/src/mcp/tools/ingest.js +2 -5
  46. package/src/mcp/tools/retrieval.js +2 -15
  47. package/src/mcp/tools/workspace.js +452 -0
  48. package/src/mcp/utils.js +20 -0
  49. package/src/playground/announcements.md +52 -5
  50. package/src/playground/help/workflow-nodes.js +127 -2
  51. package/src/playground/index.html +17109 -12438
  52. package/src/playground/vendor/mermaid.min.js +2811 -0
  53. package/src/workflows/code-review.json +110 -0
  54. package/src/workflows/cost-analysis.json +5 -0
  55. package/src/workflows/rag-chat.json +165 -0
  56. package/src/workflows/tests/code-review.fresh-index.test.json +83 -0
  57. package/src/workflows/tests/code-review.happy-path.test.json +121 -0
  58. package/src/workflows/tests/code-review.no-question.test.json +70 -0
  59. package/src/workflows/tests/consistency-check.happy-path.test.json +28 -0
  60. package/src/workflows/tests/consistency-check.missing-source.test.json +26 -0
  61. package/src/workflows/tests/cost-analysis.happy-path.test.json +28 -0
  62. package/src/workflows/tests/enrich-and-ingest.happy-path.test.json +38 -0
  63. package/src/workflows/tests/enrich-and-ingest.notify-fails.test.json +38 -0
  64. package/src/workflows/tests/intelligent-ingest.all-filtered.test.json +26 -0
  65. package/src/workflows/tests/intelligent-ingest.happy-path.test.json +28 -0
  66. package/src/workflows/tests/kb-health-report.custom-queries.test.json +24 -0
  67. package/src/workflows/tests/kb-health-report.happy-path.test.json +26 -0
  68. package/src/workflows/tests/multi-collection-search.happy-path.test.json +40 -0
  69. package/src/workflows/tests/multi-collection-search.one-empty.test.json +28 -0
  70. package/src/workflows/tests/rag-chat.happy-path.test.json +26 -0
  71. package/src/workflows/tests/rag-chat.no-relevant-results.test.json +25 -0
  72. package/src/workflows/tests/research-and-summarize.happy-path.test.json +33 -0
  73. package/src/workflows/tests/research-and-summarize.no-results.test.json +29 -0
  74. package/src/workflows/tests/search-with-fallback.empty-both.test.json +24 -0
  75. package/src/workflows/tests/search-with-fallback.fallback-branch.test.json +24 -0
  76. package/src/workflows/tests/search-with-fallback.happy-path.test.json +27 -0
  77. package/src/workflows/tests/smart-ingest.duplicate-detected.test.json +34 -0
  78. package/src/workflows/tests/smart-ingest.happy-path.test.json +31 -0
  79. package/src/playground/assets/announcements/appstore.jpg +0 -0
  80. package/src/playground/assets/announcements/circuits.jpg +0 -0
  81. package/src/playground/assets/announcements/csvingest.jpg +0 -0
  82. package/src/playground/assets/announcements/green-wave.jpg +0 -0
@@ -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
+ }
@@ -69,5 +69,10 @@
69
69
  "docs": "{{ inputs.docs }}",
70
70
  "queriesPerMonth": "{{ inputs.queries }}",
71
71
  "months": "{{ inputs.months }}"
72
+ },
73
+ "formatters": {
74
+ "default": "table",
75
+ "title": "Cost Analysis",
76
+ "arrayField": "comparison"
72
77
  }
73
78
  }
@@ -0,0 +1,165 @@
1
+ {
2
+ "$schema": "https://vai.dev/schemas/workflow-v1.json",
3
+ "name": "RAG Chat",
4
+ "description": "Retrieval-Augmented Generation chat: searches your knowledge base, reranks for relevance, filters low-quality matches, and generates a grounded answer with source citations",
5
+ "version": "1.0.0",
6
+ "branding": {
7
+ "icon": "message-circle",
8
+ "color": "#7C3AED"
9
+ },
10
+ "inputs": {
11
+ "question": {
12
+ "type": "string",
13
+ "description": "The user's question or message",
14
+ "required": true
15
+ },
16
+ "collection": {
17
+ "type": "string",
18
+ "description": "Knowledge base collection to search",
19
+ "required": true
20
+ },
21
+ "collection2": {
22
+ "type": "string",
23
+ "description": "Optional second collection for broader search (leave empty to skip)",
24
+ "default": ""
25
+ },
26
+ "limit": {
27
+ "type": "number",
28
+ "description": "Maximum documents to retrieve per collection",
29
+ "default": 10
30
+ },
31
+ "min_score": {
32
+ "type": "number",
33
+ "description": "Minimum relevance score (0-1) to include a document",
34
+ "default": 0.3
35
+ },
36
+ "system_prompt": {
37
+ "type": "string",
38
+ "description": "Custom system prompt for the LLM",
39
+ "default": "You are a knowledgeable assistant. Answer questions accurately based on the provided context. Always cite your sources by referencing the document name or source field. If the context does not contain enough information to answer fully, say so clearly and explain what information is missing. Never fabricate information that is not in the provided context."
40
+ },
41
+ "chat_history": {
42
+ "type": "string",
43
+ "description": "Previous conversation turns (for multi-turn context)",
44
+ "default": ""
45
+ }
46
+ },
47
+ "defaults": {},
48
+ "steps": [
49
+ {
50
+ "id": "search_primary",
51
+ "name": "Search primary knowledge base",
52
+ "tool": "query",
53
+ "inputs": {
54
+ "query": "{{ inputs.question }}",
55
+ "collection": "{{ inputs.collection }}",
56
+ "limit": "{{ inputs.limit }}",
57
+ "rerank": false
58
+ }
59
+ },
60
+ {
61
+ "id": "check_multi",
62
+ "name": "Check if second collection is configured",
63
+ "tool": "conditional",
64
+ "inputs": {
65
+ "condition": "{{ inputs.collection2.length > 0 }}",
66
+ "then": ["search_secondary"],
67
+ "else": ["skip_merge"]
68
+ }
69
+ },
70
+ {
71
+ "id": "search_secondary",
72
+ "name": "Search secondary knowledge base",
73
+ "tool": "query",
74
+ "inputs": {
75
+ "query": "{{ inputs.question }}",
76
+ "collection": "{{ inputs.collection2 }}",
77
+ "limit": "{{ inputs.limit }}",
78
+ "rerank": false
79
+ }
80
+ },
81
+ {
82
+ "id": "skip_merge",
83
+ "name": "Pass primary results through",
84
+ "tool": "template",
85
+ "inputs": {
86
+ "text": "Using {{ search_primary.output.resultCount }} results from primary collection"
87
+ }
88
+ },
89
+ {
90
+ "id": "merge_results",
91
+ "name": "Merge results from all collections",
92
+ "tool": "merge",
93
+ "inputs": {
94
+ "arrays": [
95
+ "{{ search_primary.output.results }}",
96
+ "{{ search_secondary.output.results }}"
97
+ ],
98
+ "dedup": true,
99
+ "dedup_field": "source"
100
+ },
101
+ "condition": "{{ inputs.collection2.length > 0 }}"
102
+ },
103
+ {
104
+ "id": "rerank",
105
+ "name": "Rerank by relevance to question",
106
+ "tool": "rerank",
107
+ "inputs": {
108
+ "query": "{{ inputs.question }}",
109
+ "documents": "{{ merge_results.output.results || search_primary.output.results }}"
110
+ }
111
+ },
112
+ {
113
+ "id": "filter_relevant",
114
+ "name": "Filter out low-relevance documents",
115
+ "tool": "filter",
116
+ "inputs": {
117
+ "array": "{{ rerank.output.results }}",
118
+ "condition": "item.score >= {{ inputs.min_score }}"
119
+ }
120
+ },
121
+ {
122
+ "id": "check_context",
123
+ "name": "Check if any relevant context was found",
124
+ "tool": "conditional",
125
+ "inputs": {
126
+ "condition": "{{ filter_relevant.output.resultCount > 0 }}",
127
+ "then": ["build_prompt", "generate_answer"],
128
+ "else": ["no_context_response"]
129
+ }
130
+ },
131
+ {
132
+ "id": "build_prompt",
133
+ "name": "Assemble prompt with context and history",
134
+ "tool": "template",
135
+ "inputs": {
136
+ "text": "{{ inputs.chat_history ? 'Previous conversation:\\n' + inputs.chat_history + '\\n\\n' : '' }}Based on the following knowledge base documents, answer this question: {{ inputs.question }}"
137
+ }
138
+ },
139
+ {
140
+ "id": "generate_answer",
141
+ "name": "Generate grounded answer with LLM",
142
+ "tool": "generate",
143
+ "inputs": {
144
+ "prompt": "{{ build_prompt.output.text }}",
145
+ "context": "{{ filter_relevant.output.results }}",
146
+ "systemPrompt": "{{ inputs.system_prompt }}"
147
+ }
148
+ },
149
+ {
150
+ "id": "no_context_response",
151
+ "name": "Handle no relevant context found",
152
+ "tool": "template",
153
+ "inputs": {
154
+ "text": "I searched the knowledge base but didn't find documents relevant enough to answer your question confidently. The query '{{ inputs.question }}' returned {{ rerank.output.resultCount }} results, but none met the minimum relevance threshold of {{ inputs.min_score }}. Try rephrasing your question or lowering the min_score threshold."
155
+ }
156
+ }
157
+ ],
158
+ "output": {
159
+ "answer": "{{ generate_answer.output.text || no_context_response.output.text }}",
160
+ "sources": "{{ filter_relevant.output.results }}",
161
+ "sourceCount": "{{ filter_relevant.output.resultCount }}",
162
+ "model": "{{ generate_answer.output.model }}",
163
+ "question": "{{ inputs.question }}"
164
+ }
165
+ }
@@ -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
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "consistency-check: happy path (both sources have results)",
3
+ "inputs": {
4
+ "topic": "authentication best practices",
5
+ "collection1": "api_docs",
6
+ "collection2": "tutorials"
7
+ },
8
+ "mocks": {
9
+ "query": {
10
+ "results": [
11
+ { "text": "Use OAuth2 for API authentication", "score": 0.92, "source": "auth.md" }
12
+ ],
13
+ "resultCount": 1
14
+ },
15
+ "similarity": {
16
+ "similarity": 0.87,
17
+ "model": "voyage-4-large"
18
+ }
19
+ },
20
+ "expect": {
21
+ "steps": {
22
+ "search_source_a": { "status": "completed" },
23
+ "search_source_b": { "status": "completed" },
24
+ "compare": { "status": "completed" }
25
+ },
26
+ "noErrors": true
27
+ }
28
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "consistency-check: one source empty (comparison skipped)",
3
+ "inputs": {
4
+ "topic": "obscure topic",
5
+ "collection1": "api_docs",
6
+ "collection2": "tutorials"
7
+ },
8
+ "mocks": {
9
+ "query": {
10
+ "results": [],
11
+ "resultCount": 0
12
+ },
13
+ "similarity": {
14
+ "similarity": 0.0,
15
+ "model": "voyage-4-large"
16
+ }
17
+ },
18
+ "expect": {
19
+ "steps": {
20
+ "search_source_a": { "status": "completed" },
21
+ "search_source_b": { "status": "completed" },
22
+ "compare": { "status": "skipped" }
23
+ },
24
+ "noErrors": true
25
+ }
26
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "cost-analysis: happy path",
3
+ "inputs": {
4
+ "docs": 10000,
5
+ "queries": 5000,
6
+ "months": 12
7
+ },
8
+ "mocks": {
9
+ "estimate": {
10
+ "model": "voyage-4-large",
11
+ "embeddingCost": 12.50,
12
+ "queryCost": 8.25,
13
+ "totalCost": 20.75,
14
+ "currency": "USD"
15
+ }
16
+ },
17
+ "expect": {
18
+ "steps": {
19
+ "cost_large": { "status": "completed" },
20
+ "cost_balanced": { "status": "completed" },
21
+ "cost_lite": { "status": "completed" }
22
+ },
23
+ "output": {
24
+ "comparison": { "type": "array", "minLength": 3 }
25
+ },
26
+ "noErrors": true
27
+ }
28
+ }