web-ai-service 1.0.1 → 1.0.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 (2) hide show
  1. package/README.md +199 -27
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -284,96 +284,268 @@ stages:
284
284
 
285
285
  ## Node Types
286
286
 
287
+ All nodes share these common properties:
288
+ - **type** (required) - The node type: `llm`, `code`, `reduce`, `split`, or `passthrough`
289
+ - **input** (required for most) - The input source: `$input`, `$input.field`, `stageName.nodeName`
290
+
287
291
  ### LLM Node
288
292
 
289
- Call an LLM provider:
293
+ Calls an LLM provider with a prompt.
290
294
 
295
+ **Required Properties:**
291
296
  ```yaml
292
297
  my_llm_node:
293
298
  type: llm
294
- input: $input.text # or reference: stageName.nodeName
295
- provider: gemini # gemini | openai | anthropic | grok
296
- model: gemini-2.0-flash-lite
297
- temperature: 0.7 # Optional (0.0-1.0)
298
- maxTokens: 1024 # Optional
299
- systemMessages:
300
- - file: prompt.txt
301
- cache: true # Cache for performance
299
+ input: $input # Input source
300
+ provider: gemini # Provider name: gemini | openai | anthropic | grok
301
+ model: gemini-2.0-flash-lite # Model identifier
302
+ ```
303
+
304
+ **Optional Properties:**
305
+ ```yaml
306
+ temperature: 0.7 # Default: 1.0. Controls randomness (0.0-1.0)
307
+ maxTokens: 1024 # Default: provider default. Max output tokens
308
+ systemMessages: # System prompts (optional)
309
+ - file: prompt.txt # Load from file
310
+ cache: true # Enable caching (default: false)
311
+ - text: "Direct prompt" # Or use inline text
312
+ config: # Provider-specific config (optional)
313
+ topP: 0.9
314
+ topK: 40
302
315
  ```
303
316
 
304
317
  **Supported Providers & Models:**
305
318
 
306
- | Provider | Example Models |
307
- |----------|----------------|
308
- | `gemini` | `gemini-2.0-flash-lite`, `gemini-2.0-flash`, `gemini-1.5-pro` |
309
- | `openai` | `gpt-4o`, `gpt-4o-mini`, `gpt-4-turbo` |
310
- | `anthropic` | `claude-3-5-sonnet-latest`, `claude-3-haiku-20240307` |
311
- | `grok` | `grok-2`, `grok-2-mini` |
319
+ | Provider | Example Models | Notes |
320
+ |----------|----------------|-------|
321
+ | `gemini` | `gemini-2.0-flash-lite`, `gemini-2.0-flash`, `gemini-1.5-pro` | Fast, cost-effective |
322
+ | `openai` | `gpt-4o`, `gpt-4o-mini`, `gpt-4-turbo` | High quality |
323
+ | `anthropic` | `claude-3-5-sonnet-latest`, `claude-3-haiku-20240307` | Long context |
324
+ | `grok` | `grok-2`, `grok-2-mini` | xAI models |
325
+
326
+ **Using LLM References (Alternative):**
327
+
328
+ Define reusable LLM configurations:
329
+
330
+ ```yaml
331
+ llm:
332
+ my-summarizer:
333
+ provider: gemini
334
+ model: gemini-2.0-flash-lite
335
+ temperature: 0.3
336
+
337
+ nodes:
338
+ summarize:
339
+ type: llm
340
+ input: $input
341
+ llmRef: my-summarizer # Reference the config
342
+ systemMessages:
343
+ - file: prompt.txt
344
+ ```
345
+
346
+ ---
312
347
 
313
348
  ### Code Node
314
349
 
315
- Execute custom TypeScript:
350
+ Executes a custom TypeScript function.
316
351
 
352
+ **Required Properties:**
317
353
  ```yaml
318
354
  my_code_node:
319
355
  type: code
320
356
  input: $input
321
- file: my-processor.ts
357
+ file: my-processor.ts # Relative to endpoint's codes/ folder
322
358
  ```
323
359
 
324
- The TypeScript file must export a default async function:
360
+ **TypeScript Function Signature:**
361
+
362
+ Your code file must export a default async function:
325
363
 
326
364
  ```typescript
327
365
  import type { NodeOutput } from '@workflow/types';
328
366
 
329
367
  export default async function(input: unknown): Promise<NodeOutput> {
330
368
  // Your logic here
369
+ const processed = /* ... */;
370
+
331
371
  return {
332
372
  type: 'json', // 'string' | 'json' | 'number' | 'boolean' | 'array'
333
- value: { processed: true }
373
+ value: processed
334
374
  };
335
375
  }
336
376
  ```
337
377
 
378
+ **Notes:**
379
+ - The `input` parameter is the **unwrapped value** from the previous node
380
+ - Must return a `NodeOutput` object with `type` and `value`
381
+ - Can import from `@code-plugins/*` for shared code
382
+ - Can use any npm packages (run `npm run scan-deps` to auto-install)
383
+
384
+ ---
385
+
338
386
  ### Reduce Node
339
387
 
340
- Combine multiple node outputs:
388
+ Combines multiple node outputs into a single JSON object.
341
389
 
390
+ **Required Properties:**
342
391
  ```yaml
343
392
  merge_results:
344
393
  type: reduce
345
- inputs:
394
+ inputs: # Array of node references
346
395
  - stageName.node1
347
396
  - stageName.node2
348
- mapping:
397
+ mapping: # JSONPath mappings
349
398
  firstResult: $.0
350
399
  secondResult: $.1
400
+ nested:
401
+ data: $.0.someField
402
+ ```
403
+
404
+ **How it Works:**
405
+ - Takes outputs from multiple nodes specified in `inputs`
406
+ - Uses JSONPath expressions in `mapping` to extract values
407
+ - `$.0` refers to first input, `$.1` to second input, etc.
408
+ - Returns a single `{ type: 'json', value: {...} }` object
409
+
410
+ **Example:**
411
+
412
+ If `node1` outputs `{ value: { count: 10 } }` and `node2` outputs `{ value: { total: 100 } }`:
413
+
414
+ ```yaml
415
+ mapping:
416
+ count: $.0.count # Gets 10 from first input
417
+ total: $.1.total # Gets 100 from second input
418
+ # Result: { count: 10, total: 100 }
351
419
  ```
352
420
 
421
+ ---
422
+
353
423
  ### Split Node
354
424
 
355
- Divide output into named parts:
425
+ Divides a single output into multiple named outputs.
356
426
 
427
+ **Required Properties:**
357
428
  ```yaml
358
429
  split_data:
359
430
  type: split
360
431
  input: stageName.nodeName
361
- mapping:
362
- header: $.header
432
+ mapping: # JSONPath expressions for each output
433
+ header: $.metadata.header
363
434
  body: $.content
364
- footer: $.footer
435
+ footer: $.metadata.footer
436
+ ```
437
+
438
+ **How it Works:**
439
+ - Takes a single input (usually JSON)
440
+ - Extracts multiple values using JSONPath
441
+ - Creates named outputs accessible as `nodeId.outputName`
442
+
443
+ **Example:**
444
+
445
+ Input: `{ metadata: { header: 'Title' }, content: 'Body text' }`
446
+
447
+ ```yaml
448
+ split_data:
449
+ type: split
450
+ input: previous.node
451
+ mapping:
452
+ title: $.metadata.header # Accessible as split_data.title
453
+ text: $.content # Accessible as split_data.text
454
+ ```
455
+
456
+ Later nodes can reference:
457
+ ```yaml
458
+ another_node:
459
+ type: code
460
+ input: split_data.title # Gets 'Title'
365
461
  ```
366
462
 
463
+ ---
464
+
367
465
  ### Passthrough Node
368
466
 
369
- Pass input directly to output:
467
+ Passes input directly to output unchanged (useful for routing).
370
468
 
469
+ **Required Properties:**
371
470
  ```yaml
372
471
  forward:
373
472
  type: passthrough
374
473
  input: $input
375
474
  ```
376
475
 
476
+ **Notes:**
477
+ - No transformation applied
478
+ - Preserves the input type
479
+ - Useful for conditional routing or stage organization
480
+
481
+ ---
482
+
483
+ ## Input References
484
+
485
+ All nodes (except `reduce`) use the `input` property to specify data source:
486
+
487
+ | Reference Pattern | Description | Example |
488
+ |-------------------|-------------|---------|
489
+ | `$input` | Full request body | `input: $input` |
490
+ | `$input.field` | Specific field from request | `input: $input.text` |
491
+ | `$input.nested.field` | Nested field access | `input: $input.user.name` |
492
+ | `stageName.nodeName` | Output from another node | `input: extract.parser` |
493
+ | `nodeName.outputName` | Split node output | `input: splitter.header` |
494
+
495
+ ---
496
+
497
+ ## Workflow Structure
498
+
499
+ Every workflow must follow these rules:
500
+
501
+ **Single-Stage Workflows:**
502
+ ```yaml
503
+ version: "1.0"
504
+ stages:
505
+ - name: main # Must be named 'main'
506
+ nodes:
507
+ my_node: # Must have exactly 1 node
508
+ type: llm
509
+ input: $input # Must use $input
510
+ # ... node config ...
511
+ ```
512
+
513
+ **Multi-Stage Workflows:**
514
+ ```yaml
515
+ version: "1.0"
516
+ stages:
517
+ - name: preprocess # First stage: any name
518
+ nodes:
519
+ validator: # First node must use $input
520
+ type: code
521
+ input: $input
522
+ # ... config ...
523
+
524
+ - name: process # Middle stage(s): any name, multiple nodes OK
525
+ nodes:
526
+ analyze:
527
+ type: llm
528
+ input: preprocess.validator
529
+ # ... config ...
530
+ extract:
531
+ type: code
532
+ input: preprocess.validator
533
+ # ... config ...
534
+
535
+ - name: postprocess # Last stage: any name
536
+ nodes:
537
+ formatter: # Must have exactly 1 node (exit node)
538
+ type: code
539
+ input: process.analyze
540
+ # ... config ...
541
+ ```
542
+
543
+ **Rules:**
544
+ - **First stage's first node** must use `$input` or `$input.field` as input
545
+ - **Last stage** must have exactly 1 node (its output becomes the API response)
546
+ - Middle stages can have any number of nodes
547
+ - Stage names can be anything (no longer required to be "entry" and "exit")
548
+
377
549
  ---
378
550
 
379
551
  ## Using Plugins
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "web-ai-service",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "TypeScript-based Web AI Service that creates configurable AI-powered endpoints from YAML definitions",
5
5
  "main": "dist/engine/index.js",
6
6
  "bin": {
@@ -53,4 +53,4 @@
53
53
  "tsx": "^4.7.0",
54
54
  "typescript": "^5.3.3"
55
55
  }
56
- }
56
+ }