Migrating from @selfagency/llm-stream-parser β
This guide documents the migration path from the old single-package library, @selfagency/llm-stream-parser, to the current @agentsy/* package family.
The baseline for this guide is the published v0.3.1 release of @selfagency/llm-stream-parser, corresponding to commit f6b71cc.
What changed β
@selfagency/llm-stream-parser bundled stream parsing, agent loops, renderers, UI state, and VS Code integration into one package.
@agentsy decomposes that monolith into focused packages so consumers can install only what they need.
That means migration usually happens on three levels:
- Install migration β replace one package install with a smaller package set.
- Import migration β change old subpath imports to current package imports.
- Conceptual migration β move from a monolith mental model to a layered ecosystem:
normalizersβprocessorβagent/adapters/renderers/ui.
Before you migrate β
- Published today: the current
@agentsy/*package family in this repository - Private:
@agentsy/testing
If you only used the old VS Code chat renderer or provider utilities, migration is straightforward and production-oriented today.
If you depended on deeper monolith surfaces like agent loops, UI state, pipeline transforms, or multiple renderer variants, the equivalents now exist as focused published packages in this repository. The main caveat is not package availability; it is whether a historical monolith subpath still has a direct modern public export path.
Choose the smallest modern package set β
If you used @selfagency/llm-stream-parser for⦠| Start with⦠| Notes |
|---|---|---|
| VS Code chat providers and renderers | @agentsy/vscode | Best-supported migration path today. |
| Thinking extraction | @agentsy/core/thinking | Direct focused replacement. |
| XML/privacy scrubbing | @agentsy/core/xml-filter | Direct focused replacement. |
| Context block splitting and dedupe | @agentsy/core/context | Direct focused replacement. |
| XML/native tool-call extraction | @agentsy/core/tool-calls | Direct focused replacement. |
| JSON parsing / validation / repair | @agentsy/core/structured | Direct focused replacement. |
| Provider event normalization | @agentsy/providers/normalizers | Pair with @agentsy/core/processor. |
| Stream orchestration / transforms | @agentsy/core/processor / @agentsy/providers/pipeline | Processor primitives live in core; createPipeline lives in providers. |
| Generic integration adapters | @agentsy/providers/adapters | High-level utilities including processRawStream, runStructuredDecisionFromRawStream, and applyDecisionAction. |
| Event-sourced UI state | @agentsy/ui | Store + reducer + processor bridge. |
| Agent loops | @agentsy/orchestrator/agent | Equivalent capability, now separated from parsing primitives. |
| Formatting / markdown helper utilities | @agentsy/core/formatting | appendToBlockquote moved here. |
Install migration β
Old monolith install β
npm install @selfagency/llm-stream-parserNew selective installs β
VS Code extension authors β
npm install @agentsy/vscode vscodeStream parsing pipeline users β
npm install @agentsy/providers @agentsy/coreAgent-loop users β
npm install @agentsy/orchestrator/agent @agentsy/core @agentsy/providersUI-state consumers β
npm install @agentsy/ui @agentsy/coreImport mapping β
The table below maps the main v0.3.1 subpaths to their modern homes.
| Old import | Current import | Migration note |
|---|---|---|
@selfagency/llm-stream-parser/processor | @agentsy/core/processor | LLMStreamProcessor and processor primitives consolidated in core. |
@selfagency/llm-stream-parser/pipeline | @agentsy/providers/pipeline / @agentsy/core/processor | createPipeline now lives in providers; provider-agnostic transforms like createSmoothStream remain in core. |
@selfagency/llm-stream-parser/thinking | @agentsy/core/thinking | Consolidated in core stream processing layer. |
@selfagency/llm-stream-parser/xml-filter | @agentsy/core/xml-filter | Consolidated in core stream processing layer. |
@selfagency/llm-stream-parser/context | @agentsy/core/context | Consolidated in core stream processing layer. |
@selfagency/llm-stream-parser/tool-calls | @agentsy/core/tool-calls | Consolidated in core stream processing layer. |
@selfagency/llm-stream-parser/structured | @agentsy/core/structured | Consolidated in core stream processing layer. |
@selfagency/llm-stream-parser/normalizers | @agentsy/providers/normalizers | Provider integration layer. |
@selfagency/llm-stream-parser/adapters | @agentsy/providers/adapters | Provider integration layer. |
@selfagency/llm-stream-parser/agent | @agentsy/orchestrator/agent | Agent orchestration consolidated into orchestrator package. |
@selfagency/llm-stream-parser/ui | @agentsy/ui | Event-sourced conversation state now lives here. |
@selfagency/llm-stream-parser/formatting | @agentsy/core/formatting | Formatting helpers consolidated in core. |
@selfagency/llm-stream-parser/markdown | @agentsy/core/formatting | appendToBlockquote was consolidated into @agentsy/core/formatting. |
@selfagency/llm-stream-parser/renderers/plain | @agentsy/renderers | Use createPlainTextRenderer from the renderers package root. |
@selfagency/llm-stream-parser/renderers/vscode | @agentsy/vscode | VS Code renderer APIs moved into the published VS Code package. |
@selfagency/llm-stream-parser/renderers/cli | No stable one-to-one public replacement yet | The repo contains renderer work, but this old public subpath does not currently map to a documented stable export. |
@selfagency/llm-stream-parser/renderers/streaming-md | No stable one-to-one public replacement yet | Treat as roadmap / internal until publicly documented and exported. |
@selfagency/llm-stream-parser/renderers/ink | No stable one-to-one public replacement yet | Ink renderer work exists in-repo, but not as a documented stable public import path today. |
Before-and-after examples β
Stream processor β
Before β
import { LLMStreamProcessor } from '@selfagency/llm-stream-parser/processor';
const processor = new LLMStreamProcessor({
parseThinkTags: true,
knownTools: new Set(['search', 'edit_file'])
});After β
import { LLMStreamProcessor } from '@agentsy/core/processor';
const processor = new LLMStreamProcessor({
parseThinkTags: true,
knownTools: new Set(['search', 'edit_file'])
});Pipeline transforms β
Before β
import { createSmoothStream, createThinkingFilter } from '@selfagency/llm-stream-parser/pipeline';After β
import { createSmoothStream, createThinkingFilter } from '@agentsy/core/processor';
import { createPipeline } from '@agentsy/providers/pipeline';Tool calls plus structured output β
Before β
import { extractXmlToolCalls } from '@selfagency/llm-stream-parser/tool-calls';
import { parseJson } from '@selfagency/llm-stream-parser/structured';After β
import { extractXmlToolCalls } from '@agentsy/core/tool-calls';
import { parseJson } from '@agentsy/core/structured';Generic adapter usage β
Before β
import { createGenericAdapter } from '@selfagency/llm-stream-parser/adapters';After β
import { createGenericAdapter } from '@agentsy/providers/adapters';Manual normalize + process loop β processRawStream β
If your old monolith usage had custom loops that manually normalized chunks and fed a processor, prefer processRawStream in the new stack.
Before β
for await (const rawChunk of providerStream) {
const normalized = normalizeOpenAIChatChunk(rawChunk);
if (!normalized) continue;
const output = processor.process(normalized.chunk);
render(output);
}
render(processor.flush());After β
import { processRawStream } from '@agentsy/providers/adapters';
import { normalizeOpenAIChatChunk } from '@agentsy/providers/normalizers';
for await (const output of processRawStream(providerStream, normalizeOpenAIChatChunk, { parseThinkTags: true })) {
render(output);
}Manual parse + validate + conditional action β runStructuredDecisionFromRawStream + applyDecisionAction β
If your monolith migration path still has repetitive "extract final content β validate schema β conditionally run side effect" code, move that orchestration to @agentsy/providers/adapters helpers.
Before β
for await (const rawChunk of providerStream) {
const normalized = normalizeOpenAIChatChunk(rawChunk);
if (!normalized) continue;
processor.process(normalized.chunk);
}
const content = processor.accumulatedMessage.content;
const validated = validateJsonSchema(content, schema);
if (!validated.success) throw new Error(validated.errors.join('; '));
if (validated.data.shouldBlock) {
await updateRemoteDns(validated.data);
}After β
import { applyDecisionAction, runStructuredDecisionFromRawStream } from '@agentsy/providers/adapters';
import { normalizeOpenAIChatChunk } from '@agentsy/providers/normalizers';
const decision = await runStructuredDecisionFromRawStream<unknown, { shouldBlock: boolean }>({
source: providerStream,
normalize: normalizeOpenAIChatChunk,
schema
});
if (!decision.success) {
throw new Error(decision.errors.join('; '));
}
await applyDecisionAction(decision.decision, {
shouldAct: value => value.shouldBlock,
action: async value => updateRemoteDns(value)
});UI state β
Before β
import { createConversationStoreFromProcessor } from '@selfagency/llm-stream-parser/ui';After β
import { createConversationStoreFromProcessor } from '@agentsy/ui';VS Code renderer β
Before β
import { createVSCodeChatRenderer } from '@selfagency/llm-stream-parser/renderers/vscode';After β
import { createVSCodeChatRenderer } from '@agentsy/vscode';Conceptual migration notes β
The old monolith became a layered package family β
In v0.3.1, one package carried most of the framework surface.
Today the same capabilities are split across focused layers:
- Parsing primitives:
@agentsy/core/thinking,@agentsy/core/xml-filter,@agentsy/core/context,@agentsy/core/tool-calls,@agentsy/core/structured - Provider normalization:
@agentsy/providers/normalizers - Stream orchestration:
@agentsy/core/processor,@agentsy/providers/pipeline - High-level orchestration:
@agentsy/orchestrator/agent,@agentsy/providers/adapters,@agentsy/ui - Targeted integration layer:
@agentsy/vscode
Not every old public subpath has a modern stable twin yet β
The old package exposed several renderer-specific subpaths directly. In the current repo, renderer work is more modular, but the publicly documented, exported surface is narrower.
If you depended on:
renderers/plainβ migrate now to@agentsy/renderersrenderers/vscodeβ migrate now to@agentsy/vscoderenderers/cli,renderers/streaming-md, orrenderers/inkβ evaluate current repo state carefully before migrating; these should be treated as non-drop-in until they are fully documented and exported as stable public entry points
The safest migration path today β
If you are migrating production code today, the safest path is usually one of these:
- VS Code extension / chat provider work β move to
@agentsy/vscode - Parser-only use β move to the focused parsing packages you actually use
- Broader framework usage β migrate incrementally, feature by feature, rather than swapping the entire monolith for every package in one heroic and probably unnecessary move
Suggested migration checklist β
- Replace the old package install with the smallest modern package set you need.
- Rewrite imports using the mapping table above.
- Check whether you relied on old renderer subpaths that do not yet have stable public replacements.
- Update examples and internal docs to point to
@agentsy/*packages. - If your codebase still mentions
@selfagency/llm-stream-parser, link teammates to this guide.