Skip to content

Add Executor.stream() async generator and ModuleAnnotations.streaming #2

@tercel

Description

@tercel

Summary

Add optional stream() async generator to Executor and streaming: boolean to ModuleAnnotations, enabling modules to produce incremental output.

Changes

ModuleAnnotations

  • Added readonly streaming: boolean (default false)
  • Updated DEFAULT_ANNOTATIONS and ANNOTATION_FIELDS

Executor.stream()

  • New async *stream(moduleId, inputs?, context?): AsyncGenerator<Record<string, unknown>>
  • Steps 1-6 identical to call() (context, safety, lookup, ACL, validate, before-middleware)
  • If module has no stream(): falls back to call(), yields single chunk
  • If module has stream(): iterates it, yields each chunk, accumulates via shallow merge
  • Output validation runs on accumulated result
  • After-middleware runs on accumulated result
  • Error recovery via middleware onError

Extracted helper

  • _validateOutput() extracted from _executeWithMiddleware() for reuse

Tests (8 new)

  • Fallback single chunk, multiple chunks, ModuleNotFoundError
  • Before/after middleware ordering (streaming + fallback paths)
  • Error recovery, output schema validation
  • Disjoint-key shallow merge accumulation

Files Changed

  • src/module.tsstreaming field
  • src/executor.tsstream(), _streamWithMiddleware(), _validateOutput()
  • src/schema/annotations.tsANNOTATION_FIELDS updated
  • tests/test-executor-stream.test.ts — 8 new tests

Test Results

435 tests pass, 0 failures. tsc --noEmit clean.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions