@polyweave/conversation (1.0.7)
Installation
@polyweave:registry=https://hub.kl1.tenere.ai/api/packages/Polyweave/npm/npm install @polyweave/conversation@1.0.7"@polyweave/conversation": "1.0.7"About this package
@polyweave/conversation
Conversation control wrappers for Polyweave frame duplexes. Provides system prompt injection, turn-taking enforcement, and interrupt handling as bidirectional wrappers that compose with any adapter.
Synopsis
import { createSystemPromptWrapper, createTurnTakingWrapper, createInterruptHandler } from '@polyweave/conversation';
import { createOpenAIAdapter } from '@polyweave/openai';
const adapter = createOpenAIAdapter({ apiKey: process.env.OPENAI_API_KEY });
const withSystem = createSystemPromptWrapper(adapter, {
systemPrompt: 'You are a helpful assistant. Be concise.'
});
const withTurns = createTurnTakingWrapper(withSystem, {
maxTurns: 10,
onTurn: (turn) => console.log('Turn', turn)
});
const managed = createInterruptHandler(withTurns, {
onInterrupt: (reason) => console.log('Interrupted:', reason)
});
managed.sink.write({ type: 'TEXT', content: { text: 'Hello' } });
Install
npm install @polyweave/conversation
Why
Raw LLM adapters have no conversation state — they treat every frame as a fresh interaction. These wrappers add conversational control: system prompts persist across turns, turn counts are enforced with configurable termination, and interrupts allow graceful shutdown mid-conversation. All wrappers are bidirectional — they intercept both inbound and outbound frames, making them composable with any adapter and with each other.
API
createSystemPromptWrapper(innerDuplex, options)
Returns a wrapped duplex. Injects a system prompt into every conversation turn. The system prompt is sent as the first frame of each request stream.
| Parameter | Type | Default | Description |
|---|---|---|---|
innerDuplex |
IFrameDuplex |
Yes | The adapter to wrap |
systemPrompt |
string |
'' |
System prompt text |
preserveSystem |
boolean |
true |
Re-inject system prompt on each new START frame |
How it works: When START is received on the sink, the wrapper emits START, then TEXT with the system prompt, then forwards all subsequent frames. On END, the wrapper forwards END to the inner duplex.
createTurnTakingWrapper(innerDuplex, options)
Returns a wrapped duplex. Enforces a maximum number of conversation turns. After maxTurns, the wrapper emits END automatically.
| Parameter | Type | Default | Description |
|---|---|---|---|
innerDuplex |
IFrameDuplex |
Yes | The adapter to wrap |
maxTurns |
number |
20 |
Maximum conversation turns |
onTurn(turnNumber) |
function |
null |
Callback fired at the start of each turn |
endOnMax |
boolean |
true |
Automatically end the conversation when maxTurns is reached |
Turn definition: A turn is counted each time a TEXT frame is written to the sink. Responses (frames emitted by the adapter) do not count toward the turn limit.
createInterruptHandler(innerDuplex, options)
Returns a wrapped duplex. Provides structured interrupt handling — cancels in-flight requests and emits an interrupt frame on the source.
| Parameter | Type | Default | Description |
|---|---|---|---|
innerDuplex |
IFrameDuplex |
Yes | The adapter to wrap |
onInterrupt(reason) |
function |
null |
Callback when interrupt is triggered |
interruptSignal |
AbortSignal |
null |
External AbortSignal for programmatic interruption |
gracePeriodMs |
number |
0 |
Wait before force-closing after interrupt |
How it works: Writing CANCEL or ABORT to the sink triggers interruption. The wrapper sends CANCEL to the inner duplex, emits an INTERRUPTED frame on the source, and calls onInterrupt. If gracePeriodMs > 0, the wrapper waits before force-ending.
Frame Protocol
All three wrappers are transparent bidirectional wrappers — they pass through all frames they don't specifically handle.
| Wrapper | Adds to sink | Adds to source |
|---|---|---|
| System prompt | (none) | Injects system prompt TEXT after START |
| Turn taking | Counts TEXT frames; auto-ends on maxTurns | Emits END when limit reached |
| Interrupt handler | Handles CANCEL/ABORT | Emits INTERRUPTED on interrupt |
Errors
- No specific error codes. Errors from the inner duplex pass through unchanged.
- On interrupt, the wrappers emit
INTERRUPTEDrather than throwing.
Tests
npm test
5 tests covering system prompt injection, turn counting and enforcement, interrupt handling, and wrapper durability (500 js-rigor property cases).
Requirements
Node.js 22 or later. ESM only.
Peer dependency: @polyweave/core.
Dependencies
Development Dependencies
| ID | Version |
|---|---|
| @rigor/core | * |
Peer Dependencies
| ID | Version |
|---|---|
| @polyweave/core | * |