@polyweave/middleware (1.0.8)
Installation
@polyweave:registry=https://hub.kl1.tenere.ai/api/packages/Polyweave/npm/npm install @polyweave/middleware@1.0.8"@polyweave/middleware": "1.0.8"About this package
@polyweave/middleware
Composable frame transformations for Polyweave push-streams — fork (tee), merge (join), re-ID (stamp), deduplicate, conversation slicing, system prompt marking, dialog meta injection, and meta-cognitive bumpers.
Synopsis
import { tee, join, stamp, deduplicate, createSlice } from '@polyweave/middleware';
const [branch1, branch2] = tee(source, 2);
const merged = join([branch1, branch2]);
const dedup = deduplicate();
const stamper = stamp();
const slicer = createSlice(0, 5);
source.pipe(stamper).pipe(dedup).pipe(mySink);
Install
npm install @polyweave/middleware
Why
Polyweave topologies (parallel sub-agents, cost predictors, budget gates, observability taps) create complex push-stream graphs. Without standardized combinators, every harness re-implements fork/join/dedup/stamp with subtle concurrency bugs. These eight middlewares provide the canonical push-stream combinators — each tested for backpressure compliance, topology-scan propagation, and ordered frame delivery.
API
This package re-exports from 8 submodules. Every export is available from the package root.
tee(source, count) — @polyweave/middleware/tee
Signature: tee(source: IFrameSource, count: number): IFrameSource[]
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
source |
IFrameSource |
Yes | — | The source to split. |
count |
number |
Yes | — | Number of destination branches. Must be >= 1. |
Returns: IFrameSource[] — Array of count independent sources. Each destination receives a copy of every frame from the original source, buffered independently. Backpressure: the original source pauses when any destination has buffered frames or is paused. TOPOLOGY_SCAN frames are forwarded to all branches with branch-index paths.
Throws: Error if source is falsy or count < 1.
join(sources) — @polyweave/middleware/join
Signature: join(sources: IFrameSource[]): IFrameSource
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
sources |
IFrameSource[] |
Yes | — | Non-empty array of sources to merge. |
Returns: IFrameSource — A single merged source that forwards all frames from all inputs. Ends when all input sources have ended and the buffer is empty. TOPOLOGY_SCAN frames from the first arriving branch are forwarded downstream with a join node path.
Throws: Error if sources is not a non-empty array.
stamp() — @polyweave/middleware/stamp
Signature: stamp(): IFrameTransform
Returns: IFrameTransform — A pass-through transform that replaces each frame's id with a fresh uuidv7(). All other frame fields are preserved via spread.
Throws: Does not throw.
deduplicate() — @polyweave/middleware/deduplicate
Signature: deduplicate(): IFrameTransform
Returns: IFrameTransform — A transform that tracks seen frame IDs in an internal Set. If a frame's id has already been seen, the transform returns null (drops the frame). Otherwise, the ID is added to the set and the frame passes through. The seen-ID set is not bounded; for very long-lived streams, consider wrapping with a reset mechanism.
Throws: Does not throw.
createSlice(start, end) — @polyweave/middleware/slice
Signature: createSlice(start: number, end: number): IFrameTransform
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
start |
number |
Yes | — | Turn index (inclusive). Negative values count from the end. |
end |
number |
Yes | — | Turn index (exclusive). Negative values count from the end. |
Returns: IFrameTransform — A transform that accumulates START/END-bounded conversation turns. When a turn contains at least one TEXT frame, it increments the turn counter. Once turns.length exceeds end, the range [start, end) of accumulated turns is yielded. start < 0 and end < 0 count from the end of the accumulated turn list. Non-TEXT turns may be yielded as-is before the slice range is reached.
Throws: Does not throw.
markSystemPrompt() — @polyweave/middleware/markSystemPrompt
Signature: markSystemPrompt(): IFrameTransform
Returns: IFrameTransform — A transform that buffers START/END-bounded turns. When a turn contains exactly one TEXT frame with metadata.role === 'system', the transform injects a META frame { type: FrameType.META, content: { key: 'type', value: 'system-prompt-update' } } between the START frame and the system TEXT frame. Non-system turns pass through unmodified.
Throws: Does not throw.
createReplaceDialogMeta(start, end, options) — @polyweave/middleware/replaceDialogMeta
Signature: createReplaceDialogMeta(start: number, end: number, options?: Object): IFrameTransform
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
start |
number |
Yes | — | Start index for the replace range. |
end |
number |
Yes | — | End index for the replace range. |
options |
Object |
No | {} |
Options object |
options.tags |
string[] |
No | [FrameType.TEXT] |
Frame types to include in the replace meta. |
options.roles |
string[] |
No | ['user', 'assistant'] |
Roles to include in the replace meta. |
Returns: IFrameTransform — A transform that buffers START/END-bounded turns and injects a META frame { type: FrameType.META, content: { replace: [start, end], tags, roles } } between the START frame and the turn's body.
Throws: Does not throw.
createBumper() — @polyweave/middleware/bumper
Signature: createBumper(): IFrameDuplex
Returns: IFrameDuplex — A duplex that buffers frames within a START/END scope. When END arrives, the bumper emits a new START frame, any accumulated PARAM frames, a meta-cognitive system prompt TEXT frame instructing the assistant to analyze the conversation and generate a concise system prompt, the user/assistant TEXT frames from the original turn, and a closing END frame. Frames outside START/END boundaries are ignored.
Frame protocol:
| Direction | Frame Type | Behavior |
|---|---|---|
| Input | START |
Enters buffering scope, resets buffer. |
| Input | TEXT, PARAM (inside scope) |
Buffered. PARAM frames re-emitted in new scope. |
| Input | END (inside scope) |
Triggers bumper injection sequence. |
| Output | START, TEXT, END |
Emitted bumper turn with meta-cognitive prompt. |
| Output | PARAM |
Original PARAM frames re-emitted. |
Throws: Does not throw.
Tests
npm test
Covers: tee backpressure across branches, join ordered merging with end propagation, stamp id replacement, deduplicate id-set tracking, slice positive/negative range extraction, markSystemPrompt system turn detection, replaceDialogMeta injection, and bumper turn injection.
Requirements
- Node.js 22+
- ESM only
- Peer:
@polyweave/core
Dependencies
Development Dependencies
| ID | Version |
|---|---|
| @rigor/core | * |
Peer Dependencies
| ID | Version |
|---|---|
| @polyweave/core | * |