Skip to content

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:

  1. Install migration β€” replace one package install with a smaller package set.
  2. Import migration β€” change old subpath imports to current package imports.
  3. 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/vscodeBest-supported migration path today.
Thinking extraction@agentsy/core/thinkingDirect focused replacement.
XML/privacy scrubbing@agentsy/core/xml-filterDirect focused replacement.
Context block splitting and dedupe@agentsy/core/contextDirect focused replacement.
XML/native tool-call extraction@agentsy/core/tool-callsDirect focused replacement.
JSON parsing / validation / repair@agentsy/core/structuredDirect focused replacement.
Provider event normalization@agentsy/providers/normalizersPair with @agentsy/core/processor.
Stream orchestration / transforms@agentsy/core/processor / @agentsy/providers/pipelineProcessor primitives live in core; createPipeline lives in providers.
Generic integration adapters@agentsy/providers/adaptersHigh-level utilities including processRawStream, runStructuredDecisionFromRawStream, and applyDecisionAction.
Event-sourced UI state@agentsy/uiStore + reducer + processor bridge.
Agent loops@agentsy/orchestrator/agentEquivalent capability, now separated from parsing primitives.
Formatting / markdown helper utilities@agentsy/core/formattingappendToBlockquote moved here.

Install migration ​

Old monolith install ​

bash
npm install @selfagency/llm-stream-parser

New selective installs ​

VS Code extension authors ​

bash
npm install @agentsy/vscode vscode

Stream parsing pipeline users ​

bash
npm install @agentsy/providers @agentsy/core

Agent-loop users ​

bash
npm install @agentsy/orchestrator/agent @agentsy/core @agentsy/providers

UI-state consumers ​

bash
npm install @agentsy/ui @agentsy/core

Import mapping ​

The table below maps the main v0.3.1 subpaths to their modern homes.

Old importCurrent importMigration note
@selfagency/llm-stream-parser/processor@agentsy/core/processorLLMStreamProcessor and processor primitives consolidated in core.
@selfagency/llm-stream-parser/pipeline@agentsy/providers/pipeline / @agentsy/core/processorcreatePipeline now lives in providers; provider-agnostic transforms like createSmoothStream remain in core.
@selfagency/llm-stream-parser/thinking@agentsy/core/thinkingConsolidated in core stream processing layer.
@selfagency/llm-stream-parser/xml-filter@agentsy/core/xml-filterConsolidated in core stream processing layer.
@selfagency/llm-stream-parser/context@agentsy/core/contextConsolidated in core stream processing layer.
@selfagency/llm-stream-parser/tool-calls@agentsy/core/tool-callsConsolidated in core stream processing layer.
@selfagency/llm-stream-parser/structured@agentsy/core/structuredConsolidated in core stream processing layer.
@selfagency/llm-stream-parser/normalizers@agentsy/providers/normalizersProvider integration layer.
@selfagency/llm-stream-parser/adapters@agentsy/providers/adaptersProvider integration layer.
@selfagency/llm-stream-parser/agent@agentsy/orchestrator/agentAgent orchestration consolidated into orchestrator package.
@selfagency/llm-stream-parser/ui@agentsy/uiEvent-sourced conversation state now lives here.
@selfagency/llm-stream-parser/formatting@agentsy/core/formattingFormatting helpers consolidated in core.
@selfagency/llm-stream-parser/markdown@agentsy/core/formattingappendToBlockquote was consolidated into @agentsy/core/formatting.
@selfagency/llm-stream-parser/renderers/plain@agentsy/renderersUse createPlainTextRenderer from the renderers package root.
@selfagency/llm-stream-parser/renderers/vscode@agentsy/vscodeVS Code renderer APIs moved into the published VS Code package.
@selfagency/llm-stream-parser/renderers/cliNo stable one-to-one public replacement yetThe repo contains renderer work, but this old public subpath does not currently map to a documented stable export.
@selfagency/llm-stream-parser/renderers/streaming-mdNo stable one-to-one public replacement yetTreat as roadmap / internal until publicly documented and exported.
@selfagency/llm-stream-parser/renderers/inkNo stable one-to-one public replacement yetInk renderer work exists in-repo, but not as a documented stable public import path today.

Before-and-after examples ​

Stream processor ​

Before ​

ts
import { LLMStreamProcessor } from '@selfagency/llm-stream-parser/processor';

const processor = new LLMStreamProcessor({
  parseThinkTags: true,
  knownTools: new Set(['search', 'edit_file'])
});

After ​

ts
import { LLMStreamProcessor } from '@agentsy/core/processor';

const processor = new LLMStreamProcessor({
  parseThinkTags: true,
  knownTools: new Set(['search', 'edit_file'])
});

Pipeline transforms ​

Before ​

ts
import { createSmoothStream, createThinkingFilter } from '@selfagency/llm-stream-parser/pipeline';

After ​

ts
import { createSmoothStream, createThinkingFilter } from '@agentsy/core/processor';
import { createPipeline } from '@agentsy/providers/pipeline';

Tool calls plus structured output ​

Before ​

ts
import { extractXmlToolCalls } from '@selfagency/llm-stream-parser/tool-calls';
import { parseJson } from '@selfagency/llm-stream-parser/structured';

After ​

ts
import { extractXmlToolCalls } from '@agentsy/core/tool-calls';
import { parseJson } from '@agentsy/core/structured';

Generic adapter usage ​

Before ​

ts
import { createGenericAdapter } from '@selfagency/llm-stream-parser/adapters';

After ​

ts
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 ​

ts
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 ​

ts
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 ​

ts
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 ​

ts
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 ​

ts
import { createConversationStoreFromProcessor } from '@selfagency/llm-stream-parser/ui';

After ​

ts
import { createConversationStoreFromProcessor } from '@agentsy/ui';

VS Code renderer ​

Before ​

ts
import { createVSCodeChatRenderer } from '@selfagency/llm-stream-parser/renderers/vscode';

After ​

ts
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/renderers
  • renderers/vscode β†’ migrate now to @agentsy/vscode
  • renderers/cli, renderers/streaming-md, or renderers/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:

  1. VS Code extension / chat provider work β†’ move to @agentsy/vscode
  2. Parser-only use β†’ move to the focused parsing packages you actually use
  3. 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.

Open source under GPL-3.0-or-later License