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.
- package/README.md +4 -4
- package/package.json +1 -1
- package/src/cli.js +8 -0
- package/src/commands/about.js +3 -3
- package/src/commands/chat.js +32 -11
- package/src/commands/code-search.js +751 -0
- package/src/commands/doctor.js +1 -1
- package/src/commands/export.js +124 -0
- package/src/commands/import.js +195 -0
- package/src/commands/index-workspace.js +243 -0
- package/src/commands/mcp-server.js +113 -3
- package/src/commands/playground.js +120 -4
- 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/export/contexts/benchmark-export.js +27 -0
- package/src/lib/export/contexts/chat-export.js +41 -0
- package/src/lib/export/contexts/explore-export.js +22 -0
- package/src/lib/export/contexts/search-export.js +54 -0
- package/src/lib/export/contexts/workflow-export.js +80 -0
- package/src/lib/export/formats/clipboard-export.js +29 -0
- package/src/lib/export/formats/csv-export.js +45 -0
- package/src/lib/export/formats/json-export.js +50 -0
- package/src/lib/export/formats/markdown-export.js +189 -0
- package/src/lib/export/formats/mermaid-export.js +274 -0
- package/src/lib/export/formats/pdf-export.js +117 -0
- package/src/lib/export/formats/png-export.js +96 -0
- package/src/lib/export/formats/svg-export.js +116 -0
- package/src/lib/export/index.js +175 -0
- 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 +297 -28
- package/src/mcp/install.js +280 -7
- package/src/mcp/schemas/index.js +170 -0
- package/src/mcp/server.js +19 -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 +452 -0
- package/src/mcp/utils.js +20 -0
- package/src/playground/announcements.md +52 -5
- package/src/playground/help/workflow-nodes.js +127 -2
- package/src/playground/index.html +17109 -12438
- package/src/playground/vendor/mermaid.min.js +2811 -0
- package/src/workflows/code-review.json +110 -0
- package/src/workflows/cost-analysis.json +5 -0
- package/src/workflows/rag-chat.json +165 -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/consistency-check.happy-path.test.json +28 -0
- package/src/workflows/tests/consistency-check.missing-source.test.json +26 -0
- package/src/workflows/tests/cost-analysis.happy-path.test.json +28 -0
- package/src/workflows/tests/enrich-and-ingest.happy-path.test.json +38 -0
- package/src/workflows/tests/enrich-and-ingest.notify-fails.test.json +38 -0
- package/src/workflows/tests/intelligent-ingest.all-filtered.test.json +26 -0
- package/src/workflows/tests/intelligent-ingest.happy-path.test.json +28 -0
- package/src/workflows/tests/kb-health-report.custom-queries.test.json +24 -0
- package/src/workflows/tests/kb-health-report.happy-path.test.json +26 -0
- package/src/workflows/tests/multi-collection-search.happy-path.test.json +40 -0
- package/src/workflows/tests/multi-collection-search.one-empty.test.json +28 -0
- package/src/workflows/tests/rag-chat.happy-path.test.json +26 -0
- package/src/workflows/tests/rag-chat.no-relevant-results.test.json +25 -0
- package/src/workflows/tests/research-and-summarize.happy-path.test.json +33 -0
- package/src/workflows/tests/research-and-summarize.no-results.test.json +29 -0
- package/src/workflows/tests/search-with-fallback.empty-both.test.json +24 -0
- package/src/workflows/tests/search-with-fallback.fallback-branch.test.json +24 -0
- package/src/workflows/tests/search-with-fallback.happy-path.test.json +27 -0
- package/src/workflows/tests/smart-ingest.duplicate-detected.test.json +34 -0
- package/src/workflows/tests/smart-ingest.happy-path.test.json +31 -0
- package/src/playground/assets/announcements/appstore.jpg +0 -0
- package/src/playground/assets/announcements/circuits.jpg +0 -0
- package/src/playground/assets/announcements/csvingest.jpg +0 -0
- package/src/playground/assets/announcements/green-wave.jpg +0 -0
|
@@ -92,6 +92,132 @@ function resolvePath(segments, context) {
|
|
|
92
92
|
return current;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Resolve a single expression fragment (a path, string literal, or number).
|
|
97
|
+
* Returns the resolved value or undefined.
|
|
98
|
+
*
|
|
99
|
+
* @param {string} fragment - e.g. "inputs.code", "'hello'", "42"
|
|
100
|
+
* @param {object} context
|
|
101
|
+
* @returns {*}
|
|
102
|
+
*/
|
|
103
|
+
function resolveFragment(fragment, context) {
|
|
104
|
+
const trimmed = fragment.trim();
|
|
105
|
+
if (!trimmed) return undefined;
|
|
106
|
+
|
|
107
|
+
// String literal (single or double quotes)
|
|
108
|
+
if ((trimmed.startsWith("'") && trimmed.endsWith("'")) ||
|
|
109
|
+
(trimmed.startsWith('"') && trimmed.endsWith('"'))) {
|
|
110
|
+
return trimmed.slice(1, -1);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Number literal
|
|
114
|
+
if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
|
|
115
|
+
return parseFloat(trimmed);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Boolean / null / undefined
|
|
119
|
+
if (trimmed === 'true') return true;
|
|
120
|
+
if (trimmed === 'false') return false;
|
|
121
|
+
if (trimmed === 'null') return null;
|
|
122
|
+
if (trimmed === 'undefined') return undefined;
|
|
123
|
+
|
|
124
|
+
// Path lookup
|
|
125
|
+
const segments = parseExpression(trimmed);
|
|
126
|
+
return resolvePath(segments, context);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Resolve an expression that may contain || (fallback) and + (concatenation).
|
|
131
|
+
*
|
|
132
|
+
* Supports:
|
|
133
|
+
* path.to.value simple path
|
|
134
|
+
* a.value || b.value fallback (first truthy)
|
|
135
|
+
* 'prefix: ' + path.to.value string concatenation
|
|
136
|
+
* a.value || 'default text' fallback with literal
|
|
137
|
+
* 'prefix' + a.value + ' suffix' multi-part concatenation
|
|
138
|
+
*
|
|
139
|
+
* Operator precedence: || is evaluated first (lowest), then +.
|
|
140
|
+
*
|
|
141
|
+
* @param {string} expr
|
|
142
|
+
* @param {object} context
|
|
143
|
+
* @returns {*}
|
|
144
|
+
*/
|
|
145
|
+
function resolveExpr(expr, context) {
|
|
146
|
+
const trimmed = expr.trim();
|
|
147
|
+
|
|
148
|
+
// Split on || (fallback operator) first
|
|
149
|
+
if (trimmed.includes('||')) {
|
|
150
|
+
const parts = splitOnOperator(trimmed, '||');
|
|
151
|
+
if (parts.length > 1) {
|
|
152
|
+
for (const part of parts) {
|
|
153
|
+
const val = resolveExpr(part.trim(), context);
|
|
154
|
+
if (val !== undefined && val !== null && val !== '' && val !== false) {
|
|
155
|
+
return val;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// All parts falsy: return the last one resolved
|
|
159
|
+
return resolveExpr(parts[parts.length - 1].trim(), context);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Split on + (concatenation)
|
|
164
|
+
if (trimmed.includes('+')) {
|
|
165
|
+
const parts = splitOnOperator(trimmed, '+');
|
|
166
|
+
if (parts.length > 1) {
|
|
167
|
+
let result = '';
|
|
168
|
+
for (const part of parts) {
|
|
169
|
+
const val = resolveFragment(part.trim(), context);
|
|
170
|
+
if (val === undefined || val === null) {
|
|
171
|
+
result += '';
|
|
172
|
+
} else if (typeof val === 'object') {
|
|
173
|
+
result += JSON.stringify(val);
|
|
174
|
+
} else {
|
|
175
|
+
result += String(val);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Simple fragment (path, literal, etc.)
|
|
183
|
+
return resolveFragment(trimmed, context);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Split a string on an operator, respecting string literals.
|
|
188
|
+
* Doesn't split inside quoted strings.
|
|
189
|
+
*
|
|
190
|
+
* @param {string} str
|
|
191
|
+
* @param {string} op - e.g. "||" or "+"
|
|
192
|
+
* @returns {string[]}
|
|
193
|
+
*/
|
|
194
|
+
function splitOnOperator(str, op) {
|
|
195
|
+
const parts = [];
|
|
196
|
+
let current = '';
|
|
197
|
+
let inSingle = false;
|
|
198
|
+
let inDouble = false;
|
|
199
|
+
|
|
200
|
+
for (let i = 0; i < str.length; i++) {
|
|
201
|
+
const ch = str[i];
|
|
202
|
+
|
|
203
|
+
if (ch === "'" && !inDouble) {
|
|
204
|
+
inSingle = !inSingle;
|
|
205
|
+
current += ch;
|
|
206
|
+
} else if (ch === '"' && !inSingle) {
|
|
207
|
+
inDouble = !inDouble;
|
|
208
|
+
current += ch;
|
|
209
|
+
} else if (!inSingle && !inDouble && str.slice(i, i + op.length) === op) {
|
|
210
|
+
parts.push(current);
|
|
211
|
+
current = '';
|
|
212
|
+
i += op.length - 1;
|
|
213
|
+
} else {
|
|
214
|
+
current += ch;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
parts.push(current);
|
|
218
|
+
return parts;
|
|
219
|
+
}
|
|
220
|
+
|
|
95
221
|
/**
|
|
96
222
|
* Resolve template expressions within a single string.
|
|
97
223
|
*
|
|
@@ -112,8 +238,7 @@ function resolveString(str, context) {
|
|
|
112
238
|
const soleMatch = str.match(SOLE_TEMPLATE_RE);
|
|
113
239
|
if (soleMatch) {
|
|
114
240
|
try {
|
|
115
|
-
|
|
116
|
-
return resolvePath(segments, context);
|
|
241
|
+
return resolveExpr(soleMatch[1], context);
|
|
117
242
|
} catch {
|
|
118
243
|
return undefined;
|
|
119
244
|
}
|
|
@@ -122,8 +247,7 @@ function resolveString(str, context) {
|
|
|
122
247
|
// Mixed text + templates: substitute all, coerce to string
|
|
123
248
|
return str.replace(TEMPLATE_RE, (_match, expr) => {
|
|
124
249
|
try {
|
|
125
|
-
const
|
|
126
|
-
const value = resolvePath(segments, context);
|
|
250
|
+
const value = resolveExpr(expr, context);
|
|
127
251
|
if (value === undefined) return '';
|
|
128
252
|
if (value === null) return 'null';
|
|
129
253
|
if (typeof value === 'object') return JSON.stringify(value);
|
|
@@ -192,23 +316,33 @@ function extractDependencies(obj) {
|
|
|
192
316
|
let match;
|
|
193
317
|
while ((match = re.exec(value)) !== null) {
|
|
194
318
|
const expr = match[1].trim();
|
|
195
|
-
// Extract
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
319
|
+
// Extract ALL root identifiers from the expression.
|
|
320
|
+
// Expressions can contain operators (&&, ||, !, ===, etc.)
|
|
321
|
+
// so we scan for all dotted-path identifiers.
|
|
322
|
+
const idRe = /(?:^|[^a-zA-Z0-9_.])([a-zA-Z_][a-zA-Z0-9_]*)(?:\.|$|\[| *[><=!&|)])/g;
|
|
323
|
+
let idMatch;
|
|
324
|
+
while ((idMatch = idRe.exec(expr)) !== null) {
|
|
325
|
+
const root = idMatch[1];
|
|
326
|
+
// Skip workflow-level references, literals, and keywords
|
|
327
|
+
if (root !== 'inputs' && root !== 'defaults' &&
|
|
328
|
+
root !== 'true' && root !== 'false' &&
|
|
329
|
+
root !== 'null' && root !== 'undefined' &&
|
|
330
|
+
root !== 'item' && root !== 'index') {
|
|
331
|
+
deps.add(root);
|
|
332
|
+
}
|
|
207
333
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
334
|
+
// Also handle simple single-identifier case (e.g. "{{ stepId }}")
|
|
335
|
+
if (!expr.includes('.') && !expr.includes('[') &&
|
|
336
|
+
!expr.includes('&') && !expr.includes('|') &&
|
|
337
|
+
!expr.includes('!') && !expr.includes('=') &&
|
|
338
|
+
!expr.includes('>') && !expr.includes('<')) {
|
|
339
|
+
const root = expr;
|
|
340
|
+
if (root !== 'inputs' && root !== 'defaults' &&
|
|
341
|
+
root !== 'true' && root !== 'false' &&
|
|
342
|
+
root !== 'null' && root !== 'undefined' &&
|
|
343
|
+
root !== 'item' && root !== 'index') {
|
|
344
|
+
deps.add(root);
|
|
345
|
+
}
|
|
212
346
|
}
|
|
213
347
|
}
|
|
214
348
|
return;
|