voyageai-cli 1.29.0 → 1.30.0
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 +82 -8
- package/package.json +1 -1
- package/src/commands/benchmark.js +22 -8
- package/src/commands/chat.js +18 -0
- package/src/commands/chunk.js +10 -0
- package/src/commands/demo.js +4 -0
- package/src/commands/embed.js +13 -0
- package/src/commands/estimate.js +3 -0
- package/src/commands/eval.js +6 -0
- package/src/commands/explain.js +2 -0
- package/src/commands/generate.js +2 -0
- package/src/commands/ingest.js +4 -0
- package/src/commands/init.js +2 -0
- package/src/commands/mcp-server.js +2 -0
- package/src/commands/models.js +2 -0
- package/src/commands/ping.js +7 -0
- package/src/commands/pipeline.js +15 -0
- package/src/commands/playground.js +52 -6
- package/src/commands/query.js +16 -0
- package/src/commands/rerank.js +12 -0
- package/src/commands/scaffold.js +2 -0
- package/src/commands/search.js +11 -0
- package/src/commands/similarity.js +9 -0
- package/src/commands/store.js +4 -0
- package/src/commands/workflow.js +286 -0
- package/src/lib/capability-report.js +134 -0
- package/src/lib/chat.js +32 -1
- package/src/lib/config.js +2 -0
- package/src/lib/cost-display.js +107 -0
- package/src/lib/explanations.js +6 -0
- package/src/lib/llm.js +125 -18
- package/src/lib/quality-audit.js +71 -0
- package/src/lib/security/blocked-domains.json +17 -0
- package/src/lib/security-audit.js +198 -0
- package/src/lib/telemetry.js +23 -1
- package/src/lib/workflow-scaffold.js +61 -0
- package/src/lib/workflow-test-runner.js +208 -0
- package/src/lib/workflow.js +128 -2
- package/src/playground/announcements.md +9 -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
- package/src/playground/help/workflow-nodes.js +472 -0
- package/src/playground/index.html +1482 -184
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* In-app help content for all workflow node types.
|
|
5
|
+
*
|
|
6
|
+
* Each entry is keyed by the node's tool name (matching WF_NODE_META)
|
|
7
|
+
* and provides structured documentation: description, how it works,
|
|
8
|
+
* inputs table, outputs, and usage tips.
|
|
9
|
+
*/
|
|
10
|
+
module.exports = {
|
|
11
|
+
// ── Retrieval ──
|
|
12
|
+
|
|
13
|
+
query: {
|
|
14
|
+
description:
|
|
15
|
+
'Performs a full RAG query: embeds your question with Voyage AI, runs vector search against MongoDB Atlas, and reranks the results for maximum relevance.',
|
|
16
|
+
howItWorks:
|
|
17
|
+
'Takes your natural language query, converts it to a vector embedding using a Voyage AI model, then performs an approximate nearest neighbor search against the specified MongoDB Atlas collection. The initial candidates are reranked using a neural reranker to surface the most relevant documents.',
|
|
18
|
+
inputs: [
|
|
19
|
+
{ key: 'query', type: 'string', required: true, desc: 'The natural language question or search text.' },
|
|
20
|
+
{ key: 'collection', type: 'string', required: false, desc: 'MongoDB collection name. Falls back to project default if omitted.' },
|
|
21
|
+
{ key: 'db', type: 'string', required: false, desc: 'MongoDB database name. Falls back to project default if omitted.' },
|
|
22
|
+
{ key: 'limit', type: 'number', required: false, desc: 'Maximum number of results to return (default: 5).' },
|
|
23
|
+
{ key: 'filter', type: 'object', required: false, desc: 'MongoDB pre-filter applied during vector search to narrow candidates (e.g., { "metadata.type": "api-doc" }).' },
|
|
24
|
+
],
|
|
25
|
+
outputs: [
|
|
26
|
+
{ key: 'results', type: 'array', desc: 'Array of matched documents, each with text, source, relevanceScore, and metadata.' },
|
|
27
|
+
{ key: 'query', type: 'string', desc: 'The original query string.' },
|
|
28
|
+
{ key: 'model', type: 'string', desc: 'The embedding model used.' },
|
|
29
|
+
],
|
|
30
|
+
tips: [
|
|
31
|
+
'Use the filter parameter to narrow results by metadata fields before vector search runs, improving both relevance and speed.',
|
|
32
|
+
'Increase the limit if you plan to post-process or re-filter results in a downstream step.',
|
|
33
|
+
'Pair with a Generate node to build a complete RAG pipeline: Query retrieves context, Generate produces the answer.',
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
search: {
|
|
38
|
+
description:
|
|
39
|
+
'Raw vector similarity search without reranking. Faster than RAG Query but results are ordered by vector distance only.',
|
|
40
|
+
howItWorks:
|
|
41
|
+
'Embeds your query text using a Voyage AI model, then performs an approximate nearest neighbor search against the specified MongoDB Atlas vector index. Returns results ordered by cosine similarity score, without applying a neural reranker.',
|
|
42
|
+
inputs: [
|
|
43
|
+
{ key: 'query', type: 'string', required: true, desc: 'The search query text.' },
|
|
44
|
+
{ key: 'collection', type: 'string', required: false, desc: 'MongoDB collection name.' },
|
|
45
|
+
{ key: 'db', type: 'string', required: false, desc: 'MongoDB database name.' },
|
|
46
|
+
{ key: 'limit', type: 'number', required: false, desc: 'Maximum results to return (default: 10).' },
|
|
47
|
+
{ key: 'filter', type: 'object', required: false, desc: 'MongoDB pre-filter for vector search.' },
|
|
48
|
+
],
|
|
49
|
+
outputs: [
|
|
50
|
+
{ key: 'results', type: 'array', desc: 'Array of matched documents with text, source, and similarity score.' },
|
|
51
|
+
{ key: 'query', type: 'string', desc: 'The original query string.' },
|
|
52
|
+
],
|
|
53
|
+
tips: [
|
|
54
|
+
'Use Search instead of Query when speed matters more than precision, or when you plan to rerank separately.',
|
|
55
|
+
'Good for exploratory searches where you want to see a broader set of candidates.',
|
|
56
|
+
'Combine with a Rerank node downstream for a two-stage retrieval pipeline with more control.',
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
rerank: {
|
|
61
|
+
description:
|
|
62
|
+
'Reorders a list of documents by relevance to a query using a Voyage AI neural reranker.',
|
|
63
|
+
howItWorks:
|
|
64
|
+
'Takes a query and an array of document texts, then uses a Voyage AI reranking model to score each document against the query. Returns the documents sorted by relevance score, with the most relevant first.',
|
|
65
|
+
inputs: [
|
|
66
|
+
{ key: 'query', type: 'string', required: true, desc: 'The query to rank documents against.' },
|
|
67
|
+
{ key: 'documents', type: 'array', required: true, desc: 'Array of document text strings to rerank.' },
|
|
68
|
+
{ key: 'model', type: 'string', required: false, desc: 'Reranking model (default: rerank-2.5). Use rerank-2.5-lite for faster results.' },
|
|
69
|
+
],
|
|
70
|
+
outputs: [
|
|
71
|
+
{ key: 'results', type: 'array', desc: 'Reranked documents with index and relevance_score fields.' },
|
|
72
|
+
{ key: 'model', type: 'string', desc: 'The reranking model used.' },
|
|
73
|
+
],
|
|
74
|
+
tips: [
|
|
75
|
+
'Feed the output of a Search node into Rerank for a two-stage retrieval pipeline.',
|
|
76
|
+
'Use rerank-2.5 for highest accuracy, rerank-2.5-lite for lower latency.',
|
|
77
|
+
'Reranking works best when you have 10-50 candidate documents to reorder.',
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
ingest: {
|
|
82
|
+
description:
|
|
83
|
+
'Chunks text, embeds each chunk with Voyage AI, and stores the vectors in MongoDB Atlas.',
|
|
84
|
+
howItWorks:
|
|
85
|
+
'Takes raw text content and a source identifier, splits the text into chunks using the specified strategy, generates vector embeddings for each chunk via the Voyage AI API, and inserts the embedded chunks into the target MongoDB Atlas collection.',
|
|
86
|
+
inputs: [
|
|
87
|
+
{ key: 'text', type: 'string', required: true, desc: 'The text content to ingest.' },
|
|
88
|
+
{ key: 'collection', type: 'string', required: false, desc: 'Target MongoDB collection.' },
|
|
89
|
+
{ key: 'db', type: 'string', required: false, desc: 'Target MongoDB database.' },
|
|
90
|
+
{ key: 'source', type: 'string', required: false, desc: 'Source identifier attached to each chunk for citation tracking.' },
|
|
91
|
+
{ key: 'chunkSize', type: 'number', required: false, desc: 'Target chunk size in characters (default: 512).' },
|
|
92
|
+
{ key: 'chunkStrategy', type: 'string', required: false, desc: 'Chunking strategy: fixed, sentence, paragraph, recursive, or markdown.' },
|
|
93
|
+
],
|
|
94
|
+
outputs: [
|
|
95
|
+
{ key: 'chunksCreated', type: 'number', desc: 'Number of chunks created and stored.' },
|
|
96
|
+
{ key: 'source', type: 'string', desc: 'The source identifier used.' },
|
|
97
|
+
],
|
|
98
|
+
tips: [
|
|
99
|
+
'Use the "markdown" strategy for structured documents with headings to preserve section boundaries.',
|
|
100
|
+
'If you need to inspect or filter chunks before embedding, use the Chunk node first, then Ingest.',
|
|
101
|
+
'Attach a meaningful source identifier so you can trace search results back to their origin.',
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
// ── Embedding ──
|
|
106
|
+
|
|
107
|
+
embed: {
|
|
108
|
+
description:
|
|
109
|
+
'Generates a vector embedding for a piece of text using a Voyage AI embedding model.',
|
|
110
|
+
howItWorks:
|
|
111
|
+
'Sends the input text to the Voyage AI embeddings API, which returns a high-dimensional vector representation. The vector captures the semantic meaning of the text and can be used for similarity comparisons, clustering, or storage.',
|
|
112
|
+
inputs: [
|
|
113
|
+
{ key: 'text', type: 'string', required: true, desc: 'The text to embed.' },
|
|
114
|
+
{ key: 'model', type: 'string', required: false, desc: 'Voyage AI embedding model (default: voyage-3-large).' },
|
|
115
|
+
{ key: 'inputType', type: 'string', required: false, desc: 'Whether this text is a "document" or a "query". Affects embedding optimization.' },
|
|
116
|
+
],
|
|
117
|
+
outputs: [
|
|
118
|
+
{ key: 'embedding', type: 'array', desc: 'The vector embedding as an array of floating-point numbers.' },
|
|
119
|
+
{ key: 'model', type: 'string', desc: 'The model used for embedding.' },
|
|
120
|
+
{ key: 'dimensions', type: 'number', desc: 'Number of dimensions in the embedding vector.' },
|
|
121
|
+
],
|
|
122
|
+
tips: [
|
|
123
|
+
'Set inputType to "query" for search queries and "document" for content being indexed. This optimizes the embedding for its intended use.',
|
|
124
|
+
'Use voyage-3-large for highest quality, voyage-3-lite for lower latency and cost.',
|
|
125
|
+
'Embeddings from different models are not comparable. Always use the same model for queries and documents.',
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
similarity: {
|
|
130
|
+
description:
|
|
131
|
+
'Compares two texts semantically by embedding both and computing cosine similarity.',
|
|
132
|
+
howItWorks:
|
|
133
|
+
'Embeds both input texts using the same Voyage AI model, then computes the cosine similarity between the two vectors. Returns a score from -1 (opposite meaning) to 1 (identical meaning).',
|
|
134
|
+
inputs: [
|
|
135
|
+
{ key: 'text1', type: 'string', required: true, desc: 'The first text to compare.' },
|
|
136
|
+
{ key: 'text2', type: 'string', required: true, desc: 'The second text to compare.' },
|
|
137
|
+
{ key: 'model', type: 'string', required: false, desc: 'Voyage AI embedding model to use for both texts.' },
|
|
138
|
+
],
|
|
139
|
+
outputs: [
|
|
140
|
+
{ key: 'similarity', type: 'number', desc: 'Cosine similarity score between -1 and 1.' },
|
|
141
|
+
{ key: 'model', type: 'string', desc: 'The embedding model used.' },
|
|
142
|
+
],
|
|
143
|
+
tips: [
|
|
144
|
+
'Scores above 0.8 generally indicate high semantic similarity.',
|
|
145
|
+
'Use for duplicate detection, content matching, or quality checks in workflows.',
|
|
146
|
+
'Combine with a Conditional node to branch based on similarity thresholds.',
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
// ── Management ──
|
|
151
|
+
|
|
152
|
+
collections: {
|
|
153
|
+
description:
|
|
154
|
+
'Lists MongoDB collections in a database, showing document counts and vector index information.',
|
|
155
|
+
howItWorks:
|
|
156
|
+
'Connects to the specified MongoDB database and enumerates all collections, including their document counts and any vector search indexes configured.',
|
|
157
|
+
inputs: [
|
|
158
|
+
{ key: 'db', type: 'string', required: false, desc: 'MongoDB database name. Uses project default if omitted.' },
|
|
159
|
+
],
|
|
160
|
+
outputs: [
|
|
161
|
+
{ key: 'collections', type: 'array', desc: 'Array of collection objects with name, documentCount, and indexes.' },
|
|
162
|
+
],
|
|
163
|
+
tips: [
|
|
164
|
+
'Use at the start of a workflow to discover what data is available before running queries.',
|
|
165
|
+
'Helpful for building dynamic workflows that adapt to the available collections.',
|
|
166
|
+
],
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
models: {
|
|
170
|
+
description:
|
|
171
|
+
'Lists available Voyage AI models with their capabilities, benchmarks, and pricing.',
|
|
172
|
+
howItWorks:
|
|
173
|
+
'Retrieves the catalog of Voyage AI models, filtered by category. Returns model details including supported dimensions, context length, and per-token pricing.',
|
|
174
|
+
inputs: [
|
|
175
|
+
{ key: 'category', type: 'string', required: false, desc: 'Filter by category: "embedding", "rerank", or "all" (default).' },
|
|
176
|
+
],
|
|
177
|
+
outputs: [
|
|
178
|
+
{ key: 'models', type: 'array', desc: 'Array of model objects with name, type, dimensions, maxTokens, and pricing.' },
|
|
179
|
+
],
|
|
180
|
+
tips: [
|
|
181
|
+
'Use to programmatically select the best model based on your requirements.',
|
|
182
|
+
'Filter by "rerank" to see only reranking models, or "embedding" for embedding models.',
|
|
183
|
+
],
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
// ── Utility ──
|
|
187
|
+
|
|
188
|
+
estimate: {
|
|
189
|
+
description:
|
|
190
|
+
'Estimates costs for Voyage AI embedding and query operations at various scales.',
|
|
191
|
+
howItWorks:
|
|
192
|
+
'Calculates projected costs based on the number of documents to embed, queries per month, and time horizon. Uses current Voyage AI pricing to provide detailed cost breakdowns.',
|
|
193
|
+
inputs: [
|
|
194
|
+
{ key: 'docs', type: 'number', required: true, desc: 'Number of documents to embed.' },
|
|
195
|
+
{ key: 'queries', type: 'number', required: false, desc: 'Number of queries per month (default: 0).' },
|
|
196
|
+
{ key: 'months', type: 'number', required: false, desc: 'Time horizon in months (default: 12).' },
|
|
197
|
+
],
|
|
198
|
+
outputs: [
|
|
199
|
+
{ key: 'embedding', type: 'object', desc: 'Embedding cost breakdown with per-document and total costs.' },
|
|
200
|
+
{ key: 'querying', type: 'object', desc: 'Query cost breakdown with per-query and monthly costs.' },
|
|
201
|
+
{ key: 'total', type: 'object', desc: 'Total projected cost over the time horizon.' },
|
|
202
|
+
],
|
|
203
|
+
tips: [
|
|
204
|
+
'Use before large ingestion jobs to understand the cost impact.',
|
|
205
|
+
'Factor in both embedding (one-time) and querying (ongoing) costs for realistic projections.',
|
|
206
|
+
],
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
explain: {
|
|
210
|
+
description:
|
|
211
|
+
'Provides a detailed explanation of a Voyage AI or vector search concept.',
|
|
212
|
+
howItWorks:
|
|
213
|
+
'Looks up the specified topic in the built-in knowledge base and returns a structured explanation with key points, examples, and related resources.',
|
|
214
|
+
inputs: [
|
|
215
|
+
{ key: 'topic', type: 'string', required: true, desc: 'The concept or topic to explain (e.g., "embeddings", "reranking", "cosine-similarity").' },
|
|
216
|
+
],
|
|
217
|
+
outputs: [
|
|
218
|
+
{ key: 'title', type: 'string', desc: 'The topic title.' },
|
|
219
|
+
{ key: 'content', type: 'string', desc: 'Detailed explanation text.' },
|
|
220
|
+
{ key: 'keyPoints', type: 'array', desc: 'Key takeaways as bullet points.' },
|
|
221
|
+
],
|
|
222
|
+
tips: [
|
|
223
|
+
'Use the Topics node first to discover available topics, then Explain to get the full details.',
|
|
224
|
+
'Great for building educational or onboarding workflows.',
|
|
225
|
+
],
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
topics: {
|
|
229
|
+
description:
|
|
230
|
+
'Lists available educational topics that can be explored with the Explain node.',
|
|
231
|
+
howItWorks:
|
|
232
|
+
'Returns the catalog of available topics with summaries. Optionally filters by a search term to find relevant topics.',
|
|
233
|
+
inputs: [
|
|
234
|
+
{ key: 'search', type: 'string', required: false, desc: 'Optional search term to filter topics by name or description.' },
|
|
235
|
+
],
|
|
236
|
+
outputs: [
|
|
237
|
+
{ key: 'topics', type: 'array', desc: 'Array of topic objects with id, title, and summary.' },
|
|
238
|
+
],
|
|
239
|
+
tips: [
|
|
240
|
+
'Omit the search parameter to list all available topics.',
|
|
241
|
+
'Combine with a Loop node to generate explanations for multiple topics in sequence.',
|
|
242
|
+
],
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
// ── Control Flow ──
|
|
246
|
+
|
|
247
|
+
merge: {
|
|
248
|
+
description:
|
|
249
|
+
'Combines outputs from multiple workflow steps into a single array.',
|
|
250
|
+
howItWorks:
|
|
251
|
+
'Takes references to outputs from previous steps and merges them into one consolidated array. Supports concatenation (append all), interleaving (alternate items), and unique (deduplicate) strategies.',
|
|
252
|
+
inputs: [
|
|
253
|
+
{ key: 'sources', type: 'array', required: true, desc: 'Array of step output references to merge (e.g., ["step1.output", "step2.output"]).' },
|
|
254
|
+
{ key: 'strategy', type: 'string', required: false, desc: 'Merge strategy: "concat" (default), "interleave", or "unique".' },
|
|
255
|
+
],
|
|
256
|
+
outputs: [
|
|
257
|
+
{ key: 'merged', type: 'array', desc: 'The combined array of items from all sources.' },
|
|
258
|
+
{ key: 'count', type: 'number', desc: 'Total number of items in the merged result.' },
|
|
259
|
+
],
|
|
260
|
+
tips: [
|
|
261
|
+
'Use "unique" strategy to deduplicate results from multiple search queries.',
|
|
262
|
+
'Merge results from different collections before passing to a Generate node for a comprehensive answer.',
|
|
263
|
+
'The "interleave" strategy alternates items from each source, useful for balanced sampling.',
|
|
264
|
+
],
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
filter: {
|
|
268
|
+
description:
|
|
269
|
+
'Filters an array of items based on a condition expression, keeping only items that match.',
|
|
270
|
+
howItWorks:
|
|
271
|
+
'Iterates over an input array and evaluates the condition expression for each item. Items where the condition evaluates to true are kept; others are discarded. The expression has access to each item via the "item" variable.',
|
|
272
|
+
inputs: [
|
|
273
|
+
{ key: 'input', type: 'string', required: true, desc: 'Reference to an array from a previous step (e.g., "{{ step.output.results }}").' },
|
|
274
|
+
{ key: 'condition', type: 'string', required: true, desc: 'JavaScript-like expression evaluated per item. Use "item" to reference the current element (e.g., "item.score > 0.5").' },
|
|
275
|
+
],
|
|
276
|
+
outputs: [
|
|
277
|
+
{ key: 'items', type: 'array', desc: 'Array of items that passed the filter condition.' },
|
|
278
|
+
{ key: 'count', type: 'number', desc: 'Number of items that passed.' },
|
|
279
|
+
{ key: 'removed', type: 'number', desc: 'Number of items that were filtered out.' },
|
|
280
|
+
],
|
|
281
|
+
tips: [
|
|
282
|
+
'Filter search results by relevance score before passing to an LLM: "item.score > 0.7".',
|
|
283
|
+
'Use after a Chunk node to remove boilerplate: "item.charCount > 100".',
|
|
284
|
+
'Combine numeric and string conditions: "item.metadata.type === \'api-doc\' && item.score > 0.5".',
|
|
285
|
+
],
|
|
286
|
+
},
|
|
287
|
+
|
|
288
|
+
transform: {
|
|
289
|
+
description:
|
|
290
|
+
'Maps each item in an array through a transformation expression, producing a new array.',
|
|
291
|
+
howItWorks:
|
|
292
|
+
'Iterates over an input array and evaluates the expression for each item, collecting the results into a new array. The expression has access to each item via the "item" variable and can extract fields, compute values, or reshape data.',
|
|
293
|
+
inputs: [
|
|
294
|
+
{ key: 'input', type: 'string', required: true, desc: 'Reference to an array from a previous step.' },
|
|
295
|
+
{ key: 'expression', type: 'string', required: true, desc: 'Expression evaluated per item. Use "item" to reference the current element (e.g., "item.text" or "{ title: item.metadata.title, score: item.score }").' },
|
|
296
|
+
],
|
|
297
|
+
outputs: [
|
|
298
|
+
{ key: 'items', type: 'array', desc: 'Array of transformed items.' },
|
|
299
|
+
{ key: 'count', type: 'number', desc: 'Number of items in the result.' },
|
|
300
|
+
],
|
|
301
|
+
tips: [
|
|
302
|
+
'Extract just the text fields from search results: "item.text".',
|
|
303
|
+
'Reshape objects to keep only relevant fields: "{ text: item.text, source: item.source }".',
|
|
304
|
+
'Use before a Rerank node to prepare document strings from complex objects.',
|
|
305
|
+
],
|
|
306
|
+
},
|
|
307
|
+
|
|
308
|
+
conditional: {
|
|
309
|
+
description:
|
|
310
|
+
'Branches workflow execution based on a condition. Routes to different paths depending on whether the condition is true or false.',
|
|
311
|
+
howItWorks:
|
|
312
|
+
'Evaluates a condition expression against the workflow context. If true, enables the steps listed in the "then" branch. If false, enables the steps in the "else" branch (if provided). Steps in the non-taken branch are skipped. Renders as a diamond shape on the canvas to indicate a decision point.',
|
|
313
|
+
inputs: [
|
|
314
|
+
{ key: 'condition', type: 'string', required: true, desc: 'Template expression that resolves to a boolean (e.g., "{{ search.output.results.length > 0 }}").' },
|
|
315
|
+
{ key: 'then', type: 'array', required: true, desc: 'Array of step IDs to enable when condition is true.' },
|
|
316
|
+
{ key: 'else', type: 'array', required: false, desc: 'Array of step IDs to enable when condition is false. If omitted, no action is taken on false.' },
|
|
317
|
+
],
|
|
318
|
+
outputs: [
|
|
319
|
+
{ key: 'conditionResult', type: 'boolean', desc: 'The evaluated condition result.' },
|
|
320
|
+
{ key: 'branchTaken', type: 'string', desc: '"then" or "else", indicating which branch was activated.' },
|
|
321
|
+
{ key: 'enabledSteps', type: 'array', desc: 'List of step IDs that were enabled.' },
|
|
322
|
+
],
|
|
323
|
+
tips: [
|
|
324
|
+
'Use to implement fallback patterns: if primary search finds nothing, try a different collection.',
|
|
325
|
+
'Steps referenced in then/else must exist in the workflow. The conditional does not define steps inline.',
|
|
326
|
+
'Combine with Similarity to branch based on score thresholds for deduplication workflows.',
|
|
327
|
+
],
|
|
328
|
+
},
|
|
329
|
+
|
|
330
|
+
loop: {
|
|
331
|
+
description:
|
|
332
|
+
'Iterates over an array, executing a sub-step for each item. Collects all results into an output array.',
|
|
333
|
+
howItWorks:
|
|
334
|
+
'Resolves the items expression to an array, then sequentially executes the inline sub-step for each element. Each iteration has access to the current item via the variable name specified in "as". Results accumulate into an output array. A safety limit prevents runaway loops.',
|
|
335
|
+
inputs: [
|
|
336
|
+
{ key: 'items', type: 'string', required: true, desc: 'Template reference resolving to an array (e.g., "{{ search.output.results }}").' },
|
|
337
|
+
{ key: 'as', type: 'string', required: true, desc: 'Variable name for the current item, accessible in the sub-step (e.g., "doc").' },
|
|
338
|
+
{ key: 'step', type: 'object', required: true, desc: 'Inline step definition executed per item. Same schema as a regular step, minus the id.' },
|
|
339
|
+
{ key: 'maxIterations', type: 'number', required: false, desc: 'Safety limit to prevent runaway loops (default: 100).' },
|
|
340
|
+
],
|
|
341
|
+
outputs: [
|
|
342
|
+
{ key: 'iterations', type: 'number', desc: 'Number of iterations completed.' },
|
|
343
|
+
{ key: 'results', type: 'array', desc: 'Array of sub-step outputs, one per iteration.' },
|
|
344
|
+
{ key: 'errors', type: 'array', desc: 'Errors from failed iterations (if continueOnError is true).' },
|
|
345
|
+
],
|
|
346
|
+
tips: [
|
|
347
|
+
'Iterations run sequentially, not in parallel, to avoid API rate limits.',
|
|
348
|
+
'Use for per-item processing: embed each chunk, check similarity for each result, or enrich each document via HTTP.',
|
|
349
|
+
'Set maxIterations to a reasonable limit for your use case to prevent unexpected costs.',
|
|
350
|
+
],
|
|
351
|
+
},
|
|
352
|
+
|
|
353
|
+
template: {
|
|
354
|
+
description:
|
|
355
|
+
'Composes a text string from multiple step outputs using template interpolation.',
|
|
356
|
+
howItWorks:
|
|
357
|
+
'Resolves all {{ }} template references in the text against the workflow context (previous step outputs, workflow inputs). Produces a single composed text output. Useful for assembling complex prompts before a Generate step.',
|
|
358
|
+
inputs: [
|
|
359
|
+
{ key: 'text', type: 'string', required: true, desc: 'Template string with {{ }} references to step outputs and workflow inputs.' },
|
|
360
|
+
],
|
|
361
|
+
outputs: [
|
|
362
|
+
{ key: 'text', type: 'string', desc: 'The resolved text with all template references replaced.' },
|
|
363
|
+
{ key: 'charCount', type: 'number', desc: 'Character count of the resolved text.' },
|
|
364
|
+
{ key: 'referencedSteps', type: 'array', desc: 'List of step IDs referenced in the template.' },
|
|
365
|
+
],
|
|
366
|
+
tips: [
|
|
367
|
+
'Use before a Generate node to assemble context from multiple sources into a single prompt.',
|
|
368
|
+
'Combine search results, aggregation stats, and user inputs into a coherent context string.',
|
|
369
|
+
'Template references use the syntax: {{ stepId.output.field }}.',
|
|
370
|
+
],
|
|
371
|
+
},
|
|
372
|
+
|
|
373
|
+
// ── Generation ──
|
|
374
|
+
|
|
375
|
+
generate: {
|
|
376
|
+
description:
|
|
377
|
+
'Generates text using an LLM (Large Language Model), optionally with retrieved context for grounded responses.',
|
|
378
|
+
howItWorks:
|
|
379
|
+
'Sends a prompt to the configured LLM provider (OpenAI, Anthropic, or Ollama) along with optional context text. The LLM generates a response based on the prompt and context. This is the generation step in a RAG pipeline.',
|
|
380
|
+
inputs: [
|
|
381
|
+
{ key: 'prompt', type: 'string', required: true, desc: 'The instruction or question for the LLM.' },
|
|
382
|
+
{ key: 'context', type: 'string', required: false, desc: 'Additional context text (e.g., from a search or template step) injected into the LLM prompt.' },
|
|
383
|
+
],
|
|
384
|
+
outputs: [
|
|
385
|
+
{ key: 'text', type: 'string', desc: 'The generated response text.' },
|
|
386
|
+
{ key: 'model', type: 'string', desc: 'The LLM model used.' },
|
|
387
|
+
{ key: 'provider', type: 'string', desc: 'The LLM provider (openai, anthropic, ollama).' },
|
|
388
|
+
],
|
|
389
|
+
tips: [
|
|
390
|
+
'Pair with a Query or Search node to build a complete RAG pipeline: retrieve context, then generate an answer.',
|
|
391
|
+
'Use a Template node to assemble context from multiple steps before passing to Generate.',
|
|
392
|
+
'The LLM provider and model are configured in your project settings, not per-node.',
|
|
393
|
+
],
|
|
394
|
+
},
|
|
395
|
+
|
|
396
|
+
// ── Processing ──
|
|
397
|
+
|
|
398
|
+
chunk: {
|
|
399
|
+
description:
|
|
400
|
+
'Splits text into smaller chunks using configurable strategies, without embedding. Useful for inspecting or filtering chunks before storage.',
|
|
401
|
+
howItWorks:
|
|
402
|
+
'Takes raw text and splits it into chunks using one of five strategies: fixed (character count), sentence, paragraph, recursive (smart splitting), or markdown (heading-aware). Returns the chunks with metadata but does not embed or store them.',
|
|
403
|
+
inputs: [
|
|
404
|
+
{ key: 'text', type: 'string', required: true, desc: 'The text content to split into chunks.' },
|
|
405
|
+
{ key: 'strategy', type: 'string', required: false, desc: 'Chunking strategy: "fixed", "sentence", "paragraph", "recursive" (default), or "markdown".' },
|
|
406
|
+
{ key: 'size', type: 'number', required: false, desc: 'Target chunk size in characters (default: 512).' },
|
|
407
|
+
{ key: 'overlap', type: 'number', required: false, desc: 'Overlap between adjacent chunks in characters (default: 50).' },
|
|
408
|
+
{ key: 'source', type: 'string', required: false, desc: 'Source identifier attached to each chunk for tracking.' },
|
|
409
|
+
],
|
|
410
|
+
outputs: [
|
|
411
|
+
{ key: 'chunks', type: 'array', desc: 'Array of chunk objects, each with index, content, charCount, and metadata.' },
|
|
412
|
+
{ key: 'totalChunks', type: 'number', desc: 'Total number of chunks produced.' },
|
|
413
|
+
{ key: 'strategy', type: 'string', desc: 'The chunking strategy used.' },
|
|
414
|
+
{ key: 'avgChunkSize', type: 'number', desc: 'Average character count per chunk.' },
|
|
415
|
+
],
|
|
416
|
+
tips: [
|
|
417
|
+
'Use "markdown" for documents with headings to preserve section boundaries.',
|
|
418
|
+
'Combine with a Filter node to remove boilerplate or short chunks before embedding.',
|
|
419
|
+
'Separating chunking from embedding (vs. using Ingest) gives you more control over the pipeline.',
|
|
420
|
+
],
|
|
421
|
+
},
|
|
422
|
+
|
|
423
|
+
aggregate: {
|
|
424
|
+
description:
|
|
425
|
+
'Runs a MongoDB aggregation pipeline for analytics, grouping, counting, and structured data queries.',
|
|
426
|
+
howItWorks:
|
|
427
|
+
'Executes a MongoDB aggregation pipeline against the specified collection. Supports all standard aggregation stages ($match, $group, $sort, $project, $limit, etc.) for flexible data analysis beyond vector search.',
|
|
428
|
+
inputs: [
|
|
429
|
+
{ key: 'pipeline', type: 'array', required: true, desc: 'MongoDB aggregation pipeline stages as a JSON array (e.g., [{"$group": {"_id": "$field", "count": {"$sum": 1}}}]).' },
|
|
430
|
+
{ key: 'collection', type: 'string', required: false, desc: 'MongoDB collection to aggregate.' },
|
|
431
|
+
{ key: 'db', type: 'string', required: false, desc: 'MongoDB database name.' },
|
|
432
|
+
],
|
|
433
|
+
outputs: [
|
|
434
|
+
{ key: 'results', type: 'array', desc: 'Array of aggregation result documents.' },
|
|
435
|
+
{ key: 'count', type: 'number', desc: 'Number of result documents.' },
|
|
436
|
+
{ key: 'durationMs', type: 'number', desc: 'Execution time in milliseconds.' },
|
|
437
|
+
],
|
|
438
|
+
tips: [
|
|
439
|
+
'Use for analytics that vector search cannot express: document counts by source, date-range filtering, metadata grouping.',
|
|
440
|
+
'The pipeline is read-only by default. Write operations ($out, $merge) are restricted.',
|
|
441
|
+
'Combine with a Generate node to produce human-readable reports from aggregation data.',
|
|
442
|
+
],
|
|
443
|
+
},
|
|
444
|
+
|
|
445
|
+
// ── Integration ──
|
|
446
|
+
|
|
447
|
+
http: {
|
|
448
|
+
description:
|
|
449
|
+
'Makes an outbound HTTP request to an external API. The extensibility escape hatch for integrating with any HTTP-accessible service.',
|
|
450
|
+
howItWorks:
|
|
451
|
+
'Sends an HTTP request to the specified URL with configurable method, headers, body, and timeout. Returns the response status, headers, and body. Supports JSON and text response types. Does not follow redirects by default for security.',
|
|
452
|
+
inputs: [
|
|
453
|
+
{ key: 'url', type: 'string', required: true, desc: 'The request URL. Supports template resolution for dynamic URLs.' },
|
|
454
|
+
{ key: 'method', type: 'string', required: false, desc: 'HTTP method: GET (default), POST, PUT, PATCH, or DELETE.' },
|
|
455
|
+
{ key: 'headers', type: 'object', required: false, desc: 'Request headers as key-value pairs (e.g., {"Authorization": "Bearer ..."}).' },
|
|
456
|
+
{ key: 'body', type: 'object', required: false, desc: 'Request body. Objects are JSON-serialized automatically.' },
|
|
457
|
+
{ key: 'timeout', type: 'number', required: false, desc: 'Request timeout in milliseconds (default: 30000).' },
|
|
458
|
+
],
|
|
459
|
+
outputs: [
|
|
460
|
+
{ key: 'status', type: 'number', desc: 'HTTP response status code (e.g., 200, 404).' },
|
|
461
|
+
{ key: 'statusText', type: 'string', desc: 'HTTP status text (e.g., "OK", "Not Found").' },
|
|
462
|
+
{ key: 'headers', type: 'object', desc: 'Response headers as key-value pairs.' },
|
|
463
|
+
{ key: 'body', type: 'object', desc: 'Parsed response body (JSON or text depending on responseType).' },
|
|
464
|
+
{ key: 'durationMs', type: 'number', desc: 'Request duration in milliseconds.' },
|
|
465
|
+
],
|
|
466
|
+
tips: [
|
|
467
|
+
'Use for Slack notifications, webhook triggers, CMS content fetching, or external API enrichment.',
|
|
468
|
+
'Set continueOnError: true if the HTTP call is optional and should not block the workflow.',
|
|
469
|
+
'Response size is limited to 5MB. For large payloads, use streaming or pagination on the external API.',
|
|
470
|
+
],
|
|
471
|
+
},
|
|
472
|
+
};
|