@nicomatt69/streamdown-tty 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +113 -0
- package/LICENSE +21 -0
- package/README.md +287 -0
- package/dist/adapters/index.d.ts +185 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/ai-sdk-adapter.d.ts +113 -0
- package/dist/ai-sdk-adapter.d.ts.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/core/index.d.ts +209 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/math-renderer.d.ts +40 -0
- package/dist/core/math-renderer.d.ts.map +1 -0
- package/dist/core/parser.d.ts +139 -0
- package/dist/core/parser.d.ts.map +1 -0
- package/dist/core/protocol.d.ts +319 -0
- package/dist/core/protocol.d.ts.map +1 -0
- package/dist/core/remend-tty.d.ts +68 -0
- package/dist/core/remend-tty.d.ts.map +1 -0
- package/dist/core/renderer.d.ts +286 -0
- package/dist/core/renderer.d.ts.map +1 -0
- package/dist/errors.d.ts +131 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/events.d.ts +185 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12921 -0
- package/dist/parser/streaming-parser.d.ts +81 -0
- package/dist/parser/streaming-parser.d.ts.map +1 -0
- package/dist/performance.d.ts +139 -0
- package/dist/performance.d.ts.map +1 -0
- package/dist/plugins/index.d.ts +6 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/plugin-system-inline.d.ts +116 -0
- package/dist/plugins/plugin-system-inline.d.ts.map +1 -0
- package/dist/plugins/plugin-system.d.ts +65 -0
- package/dist/plugins/plugin-system.d.ts.map +1 -0
- package/dist/plugins/rehype/harden.d.ts +15 -0
- package/dist/plugins/rehype/harden.d.ts.map +1 -0
- package/dist/plugins/rehype/index.d.ts +5 -0
- package/dist/plugins/rehype/index.d.ts.map +1 -0
- package/dist/plugins/remark/index.d.ts +6 -0
- package/dist/plugins/remark/index.d.ts.map +1 -0
- package/dist/plugins/remark/math.d.ts +7 -0
- package/dist/plugins/remark/math.d.ts.map +1 -0
- package/dist/plugins/remark/mermaid.d.ts +7 -0
- package/dist/plugins/remark/mermaid.d.ts.map +1 -0
- package/dist/plugins/types.d.ts +72 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/renderer/ansi-renderer.d.ts +76 -0
- package/dist/renderer/ansi-renderer.d.ts.map +1 -0
- package/dist/renderers/index.d.ts +7 -0
- package/dist/renderers/index.d.ts.map +1 -0
- package/dist/renderers/math-renderer.d.ts +49 -0
- package/dist/renderers/math-renderer.d.ts.map +1 -0
- package/dist/renderers/mermaid-ascii.d.ts +14 -0
- package/dist/renderers/mermaid-ascii.d.ts.map +1 -0
- package/dist/renderers/mermaid-renderer.d.ts +79 -0
- package/dist/renderers/mermaid-renderer.d.ts.map +1 -0
- package/dist/renderers/shiki-ansi.d.ts +48 -0
- package/dist/renderers/shiki-ansi.d.ts.map +1 -0
- package/dist/renderers/table-ascii.d.ts +30 -0
- package/dist/renderers/table-ascii.d.ts.map +1 -0
- package/dist/renderers/unicode-math.d.ts +29 -0
- package/dist/renderers/unicode-math.d.ts.map +1 -0
- package/dist/security/ansi-sanitizer.d.ts +71 -0
- package/dist/security/ansi-sanitizer.d.ts.map +1 -0
- package/dist/security/chunk-processor.d.ts +81 -0
- package/dist/security/chunk-processor.d.ts.map +1 -0
- package/dist/security/index.d.ts +6 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/input-validator.d.ts +55 -0
- package/dist/security/input-validator.d.ts.map +1 -0
- package/dist/stream-protocol.d.ts +61 -0
- package/dist/stream-protocol.d.ts.map +1 -0
- package/dist/streamdown-compat.d.ts +72 -0
- package/dist/streamdown-compat.d.ts.map +1 -0
- package/dist/streaming/stream-stats.d.ts +97 -0
- package/dist/streaming/stream-stats.d.ts.map +1 -0
- package/dist/streaming-integration.d.ts +71 -0
- package/dist/streaming-integration.d.ts.map +1 -0
- package/dist/themes/index.d.ts +59 -0
- package/dist/themes/index.d.ts.map +1 -0
- package/dist/types/index.d.ts +168 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/plugin-types.d.ts +5 -0
- package/dist/types/plugin-types.d.ts.map +1 -0
- package/dist/types/stream-events.d.ts +71 -0
- package/dist/types/stream-events.d.ts.map +1 -0
- package/dist/utils/blessed-syntax-highlighter.d.ts +124 -0
- package/dist/utils/blessed-syntax-highlighter.d.ts.map +1 -0
- package/dist/utils/enhanced-table-renderer.d.ts +77 -0
- package/dist/utils/enhanced-table-renderer.d.ts.map +1 -0
- package/dist/utils/formatting.d.ts +100 -0
- package/dist/utils/formatting.d.ts.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/math-unicode-renderer.d.ts +38 -0
- package/dist/utils/math-unicode-renderer.d.ts.map +1 -0
- package/dist/utils/mermaid-ascii-renderer.d.ts +20 -0
- package/dist/utils/mermaid-ascii-renderer.d.ts.map +1 -0
- package/dist/utils/mermaid-ascii.d.ts +53 -0
- package/dist/utils/mermaid-ascii.d.ts.map +1 -0
- package/dist/utils/shiki-ansi-renderer.d.ts +29 -0
- package/dist/utils/shiki-ansi-renderer.d.ts.map +1 -0
- package/dist/utils/syntax-highlighter.d.ts +87 -0
- package/dist/utils/syntax-highlighter.d.ts.map +1 -0
- package/dist/utils/table-formatter-inline.d.ts +37 -0
- package/dist/utils/table-formatter-inline.d.ts.map +1 -0
- package/dist/utils/table.d.ts +35 -0
- package/dist/utils/table.d.ts.map +1 -0
- package/dist/widgets/stream-indicator.d.ts +130 -0
- package/dist/widgets/stream-indicator.d.ts.map +1 -0
- package/package.json +129 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [2.0.0] - 2025-01-07
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Zero-dependency core** - Complete rewrite with no external dependencies
|
|
13
|
+
- `remend-tty` - Self-healing markdown (inspired by Vercel's remend)
|
|
14
|
+
- `StreamingParser` - Zero-dep streaming markdown parser
|
|
15
|
+
- `ANSIRenderer` - Pure ANSI terminal renderer
|
|
16
|
+
- `StreamProtocol` - Universal stream event protocol
|
|
17
|
+
|
|
18
|
+
- **AI SDK Adapters**
|
|
19
|
+
- `AnthropicAdapter` - Claude API streaming support
|
|
20
|
+
- `OpenAIAdapter` - GPT streaming support
|
|
21
|
+
- `VercelAIAdapter` - Vercel AI SDK support
|
|
22
|
+
- `GenericAdapter` - Generic async iterable adapter
|
|
23
|
+
|
|
24
|
+
- **Thinking block support** - Parse and render `<thinking>` blocks
|
|
25
|
+
|
|
26
|
+
- **Enterprise features**
|
|
27
|
+
- LRU caching for healing results
|
|
28
|
+
- Object pooling for tokens
|
|
29
|
+
- Debounced rendering
|
|
30
|
+
- Stream statistics and metrics
|
|
31
|
+
|
|
32
|
+
- **New exports**
|
|
33
|
+
- `@nicomatt69/streamdown-tty/core` - Zero-dep core only
|
|
34
|
+
- `@nicomatt69/streamdown-tty/adapters` - AI SDK adapters
|
|
35
|
+
- `@nicomatt69/streamdown-tty/remend` - Self-healing only
|
|
36
|
+
- `@nicomatt69/streamdown-tty/protocol` - Protocol only
|
|
37
|
+
|
|
38
|
+
- **Test suite** - Comprehensive Vitest tests with coverage
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- Renamed package to `@nicomatt69/streamdown-tty`
|
|
43
|
+
- Heavy dependencies (shiki, katex, marked) moved to optional
|
|
44
|
+
- Improved TypeScript types and exports
|
|
45
|
+
- Better theme customization API
|
|
46
|
+
|
|
47
|
+
### Deprecated
|
|
48
|
+
|
|
49
|
+
- Old `Streamtty` class (use `StreamdownTTY`)
|
|
50
|
+
- Legacy renderer imports (use new paths)
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
- Memory leaks in long-running streams
|
|
55
|
+
- ANSI injection vulnerabilities
|
|
56
|
+
- Performance issues with large code blocks
|
|
57
|
+
|
|
58
|
+
## [0.0.4] - Previous releases
|
|
59
|
+
|
|
60
|
+
See git history for changes before v2.0.0.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Migration from v0.x to v2.0
|
|
65
|
+
|
|
66
|
+
### Import Changes
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// Before (v0.x)
|
|
70
|
+
import Streamtty from '@nicomatt69/streamtty';
|
|
71
|
+
|
|
72
|
+
// After (v2.0)
|
|
73
|
+
import { StreamdownTTY } from '@nicomatt69/streamdown-tty';
|
|
74
|
+
// or for backward compatibility
|
|
75
|
+
import { Streamtty } from '@nicomatt69/streamdown-tty';
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### API Changes
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
// Before
|
|
82
|
+
const stream = new Streamtty(options);
|
|
83
|
+
stream.write(markdown);
|
|
84
|
+
|
|
85
|
+
// After
|
|
86
|
+
const tty = new StreamdownTTY(options);
|
|
87
|
+
tty.setContent(markdown);
|
|
88
|
+
// or for streaming
|
|
89
|
+
await tty.processStream(asyncIterable);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Zero-Dependency Core
|
|
93
|
+
|
|
94
|
+
If you only need the core functionality without legacy features:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import {
|
|
98
|
+
StreamingParser,
|
|
99
|
+
ANSIRenderer,
|
|
100
|
+
remendTTY,
|
|
101
|
+
} from '@nicomatt69/streamdown-tty/core';
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Using AI Adapters
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { createAdapter } from '@nicomatt69/streamdown-tty/adapters';
|
|
108
|
+
|
|
109
|
+
const adapter = createAdapter('anthropic');
|
|
110
|
+
for await (const text of adapter.process(stream)) {
|
|
111
|
+
console.log(text);
|
|
112
|
+
}
|
|
113
|
+
```
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Nicomatt69
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Streamdown-TTY
|
|
2
|
+
|
|
3
|
+
**Enterprise-grade markdown streaming for terminals.** A drop-in replacement inspired by [Vercel's Streamdown](https://streamdown.ai), optimized for TTY/ANSI output.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@nicomatt69/streamdown-tty)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- 🚀 **Zero-dependency core** - Parser and renderer with no external dependencies (~15KB)
|
|
11
|
+
- 🔄 **Self-healing markdown** - Auto-closes incomplete syntax during streaming (remend-tty)
|
|
12
|
+
- 🎨 **Beautiful ANSI rendering** - Dark/light themes with full customization
|
|
13
|
+
- 📊 **GFM support** - Tables, task lists, strikethrough
|
|
14
|
+
- 🔢 **Math rendering** - LaTeX to Unicode conversion
|
|
15
|
+
- 📈 **Mermaid diagrams** - ASCII diagram rendering
|
|
16
|
+
- 🛡️ **Security hardening** - ANSI injection protection
|
|
17
|
+
- ⚡ **Performance optimized** - Object pooling, memoization, LRU cache
|
|
18
|
+
- 🔌 **AI SDK adapters** - Anthropic, OpenAI, Vercel AI SDK support
|
|
19
|
+
- 🌐 **Cross-runtime** - Node.js, Bun, Deno compatible
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @nicomatt69/streamdown-tty
|
|
25
|
+
# or
|
|
26
|
+
yarn add @nicomatt69/streamdown-tty
|
|
27
|
+
# or
|
|
28
|
+
bun add @nicomatt69/streamdown-tty
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
### Static Rendering
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { render } from '@nicomatt69/streamdown-tty';
|
|
37
|
+
|
|
38
|
+
const markdown = `
|
|
39
|
+
# Hello World
|
|
40
|
+
|
|
41
|
+
This is **bold** and *italic* text.
|
|
42
|
+
|
|
43
|
+
\`\`\`typescript
|
|
44
|
+
console.log("Hello!");
|
|
45
|
+
\`\`\`
|
|
46
|
+
`;
|
|
47
|
+
|
|
48
|
+
console.log(render(markdown));
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Streaming from AI
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { StreamdownTTY } from '@nicomatt69/streamdown-tty';
|
|
55
|
+
|
|
56
|
+
const tty = new StreamdownTTY({
|
|
57
|
+
theme: 'dark',
|
|
58
|
+
maxWidth: 100,
|
|
59
|
+
lineNumbers: true,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Process any async iterable of strings
|
|
63
|
+
await tty.processStream(aiResponse);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Self-Healing Markdown
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { heal, healDetailed } from '@nicomatt69/streamdown-tty';
|
|
70
|
+
|
|
71
|
+
// Auto-close incomplete markdown
|
|
72
|
+
const incomplete = 'Hello **bold';
|
|
73
|
+
const fixed = heal(incomplete); // 'Hello **bold**'
|
|
74
|
+
|
|
75
|
+
// Get detailed diagnostics
|
|
76
|
+
const result = healDetailed('Check [link');
|
|
77
|
+
console.log(result.output); // 'Check [link](streamdown:incomplete-link)'
|
|
78
|
+
console.log(result.wasHealed); // true
|
|
79
|
+
console.log(result.fixes); // [{ type: 'link', ... }]
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### AI SDK Adapters
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { createAdapter } from '@nicomatt69/streamdown-tty';
|
|
86
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
87
|
+
|
|
88
|
+
const client = new Anthropic();
|
|
89
|
+
const adapter = createAdapter('anthropic');
|
|
90
|
+
|
|
91
|
+
const response = await client.messages.create({
|
|
92
|
+
model: 'claude-3-opus-20240229',
|
|
93
|
+
max_tokens: 1024,
|
|
94
|
+
messages: [{ role: 'user', content: 'Hello!' }],
|
|
95
|
+
stream: true,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
for await (const text of adapter.process(response)) {
|
|
99
|
+
process.stdout.write(text);
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Architecture
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
streamdown-tty/
|
|
107
|
+
├── src/
|
|
108
|
+
│ ├── core/ # Zero-dependency core
|
|
109
|
+
│ │ ├── remend-tty.ts # Self-healing markdown
|
|
110
|
+
│ │ ├── parser.ts # Streaming parser
|
|
111
|
+
│ │ ├── renderer.ts # ANSI renderer
|
|
112
|
+
│ │ ├── protocol.ts # Stream protocol
|
|
113
|
+
│ │ └── index.ts # Main entry
|
|
114
|
+
│ ├── adapters/ # AI SDK adapters
|
|
115
|
+
│ │ └── index.ts # Anthropic, OpenAI, Vercel AI
|
|
116
|
+
│ └── index.ts # Full exports
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## API Reference
|
|
120
|
+
|
|
121
|
+
### StreamdownTTY
|
|
122
|
+
|
|
123
|
+
Main class for markdown streaming.
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
interface StreamdownTTYOptions {
|
|
127
|
+
output?: NodeJS.WritableStream; // Default: process.stdout
|
|
128
|
+
theme?: 'dark' | 'light' | Theme; // Default: 'dark'
|
|
129
|
+
maxWidth?: number; // Default: terminal width
|
|
130
|
+
lineNumbers?: boolean; // Default: false
|
|
131
|
+
gfm?: boolean; // Default: true
|
|
132
|
+
math?: boolean; // Default: true
|
|
133
|
+
mermaid?: boolean; // Default: true
|
|
134
|
+
thinking?: boolean; // Default: true
|
|
135
|
+
autoHeal?: boolean; // Default: true
|
|
136
|
+
debounceMs?: number; // Default: 16
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Parser
|
|
141
|
+
|
|
142
|
+
Zero-dependency streaming markdown parser.
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { StreamingParser } from '@nicomatt69/streamdown-tty';
|
|
146
|
+
|
|
147
|
+
const parser = new StreamingParser({
|
|
148
|
+
gfm: true,
|
|
149
|
+
math: true,
|
|
150
|
+
mermaid: true,
|
|
151
|
+
autoHeal: true,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Stream chunks
|
|
155
|
+
parser.addChunk('# Hello ');
|
|
156
|
+
parser.addChunk('World');
|
|
157
|
+
|
|
158
|
+
// Get tokens
|
|
159
|
+
const tokens = parser.getTokens();
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Renderer
|
|
163
|
+
|
|
164
|
+
ANSI terminal renderer with themes.
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import { ANSIRenderer, darkTheme, ANSI } from '@nicomatt69/streamdown-tty';
|
|
168
|
+
|
|
169
|
+
const renderer = new ANSIRenderer({
|
|
170
|
+
theme: darkTheme,
|
|
171
|
+
maxWidth: 100,
|
|
172
|
+
lineNumbers: true,
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const output = renderer.render(tokens);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Protocol
|
|
179
|
+
|
|
180
|
+
Stream protocol for event handling.
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import { createStreamProtocol } from '@nicomatt69/streamdown-tty';
|
|
184
|
+
|
|
185
|
+
const protocol = createStreamProtocol({
|
|
186
|
+
onText: (event) => console.log('Text:', event.content),
|
|
187
|
+
onToolStart: (event) => console.log('Tool:', event.toolName),
|
|
188
|
+
onComplete: (event) => console.log('Done:', event.stats),
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
await protocol.start();
|
|
192
|
+
await protocol.text('Hello');
|
|
193
|
+
await protocol.complete();
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Adapters
|
|
197
|
+
|
|
198
|
+
AI SDK adapters for major providers.
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import {
|
|
202
|
+
createAdapter,
|
|
203
|
+
AnthropicAdapter,
|
|
204
|
+
OpenAIAdapter,
|
|
205
|
+
VercelAIAdapter,
|
|
206
|
+
GenericAdapter,
|
|
207
|
+
} from '@nicomatt69/streamdown-tty';
|
|
208
|
+
|
|
209
|
+
// Factory function
|
|
210
|
+
const adapter = createAdapter('anthropic', {
|
|
211
|
+
showThinking: true,
|
|
212
|
+
formatToolCalls: true,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Or direct instantiation
|
|
216
|
+
const anthropic = new AnthropicAdapter();
|
|
217
|
+
const openai = new OpenAIAdapter();
|
|
218
|
+
const vercel = new VercelAIAdapter();
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Themes
|
|
222
|
+
|
|
223
|
+
Built-in themes and full customization support.
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
import { darkTheme, lightTheme, type Theme } from '@nicomatt69/streamdown-tty';
|
|
227
|
+
|
|
228
|
+
// Custom theme
|
|
229
|
+
const customTheme: Theme = {
|
|
230
|
+
...darkTheme,
|
|
231
|
+
heading1: { fg: 'magenta', bold: true },
|
|
232
|
+
codeBlock: { bg: '#1a1a2e' },
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const tty = new StreamdownTTY({ theme: customTheme });
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Performance
|
|
239
|
+
|
|
240
|
+
Streamdown-TTY is optimized for high-throughput streaming:
|
|
241
|
+
|
|
242
|
+
- **Object pooling** - Token reuse to reduce GC pressure
|
|
243
|
+
- **LRU caching** - Memoized healing results
|
|
244
|
+
- **Efficient string ops** - No regex allocations in hot paths
|
|
245
|
+
- **Debounced rendering** - Configurable render batching
|
|
246
|
+
- **Tree-shakeable** - Import only what you need
|
|
247
|
+
|
|
248
|
+
## Comparison with Vercel Streamdown
|
|
249
|
+
|
|
250
|
+
| Feature | Streamdown (Vercel) | Streamdown-TTY |
|
|
251
|
+
|---------|---------------------|----------------|
|
|
252
|
+
| Target | React/Browser | TTY/Terminal |
|
|
253
|
+
| Output | HTML/React | ANSI |
|
|
254
|
+
| Dependencies | React, Shiki, KaTeX | Zero (core) |
|
|
255
|
+
| Self-healing | remend | remend-tty |
|
|
256
|
+
| AI Adapters | Via AI SDK | Built-in |
|
|
257
|
+
| Themes | Tailwind CSS | ANSI themes |
|
|
258
|
+
| Math | KaTeX | Unicode |
|
|
259
|
+
| Mermaid | SVG | ASCII |
|
|
260
|
+
|
|
261
|
+
## Contributing
|
|
262
|
+
|
|
263
|
+
Contributions are welcome! Please read our contributing guidelines.
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
# Clone
|
|
267
|
+
git clone https://github.com/nikomatt69/streamdown-tty
|
|
268
|
+
|
|
269
|
+
# Install
|
|
270
|
+
bun install
|
|
271
|
+
|
|
272
|
+
# Test
|
|
273
|
+
bun test
|
|
274
|
+
|
|
275
|
+
# Build
|
|
276
|
+
bun run build
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## License
|
|
280
|
+
|
|
281
|
+
MIT © [Nicomatt69](https://github.com/nikomatt69)
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
Built with ❤️ for CLI agents and terminal enthusiasts.
|
|
286
|
+
|
|
287
|
+
Inspired by [Vercel's Streamdown](https://streamdown.ai) - the best markdown streaming library for React.
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI SDK Adapters for Streamdown-TTY
|
|
3
|
+
*
|
|
4
|
+
* Universal adapters for major AI providers and SDKs.
|
|
5
|
+
* Converts provider-specific stream formats to StreamProtocol events.
|
|
6
|
+
*
|
|
7
|
+
* Supported:
|
|
8
|
+
* - Anthropic Claude API
|
|
9
|
+
* - OpenAI API
|
|
10
|
+
* - Vercel AI SDK
|
|
11
|
+
* - Generic async iterables
|
|
12
|
+
*
|
|
13
|
+
* @module adapters
|
|
14
|
+
*/
|
|
15
|
+
import { StreamProtocol, type AnyStreamEvent } from '../core/protocol.js';
|
|
16
|
+
/**
|
|
17
|
+
* Anthropic message event types
|
|
18
|
+
*/
|
|
19
|
+
export interface AnthropicMessageStreamEvent {
|
|
20
|
+
type: string;
|
|
21
|
+
index?: number;
|
|
22
|
+
content_block?: {
|
|
23
|
+
type: string;
|
|
24
|
+
text?: string;
|
|
25
|
+
id?: string;
|
|
26
|
+
name?: string;
|
|
27
|
+
input?: Record<string, unknown>;
|
|
28
|
+
};
|
|
29
|
+
delta?: {
|
|
30
|
+
type: string;
|
|
31
|
+
text?: string;
|
|
32
|
+
partial_json?: string;
|
|
33
|
+
thinking?: string;
|
|
34
|
+
};
|
|
35
|
+
message?: {
|
|
36
|
+
id: string;
|
|
37
|
+
model: string;
|
|
38
|
+
usage?: {
|
|
39
|
+
input_tokens: number;
|
|
40
|
+
output_tokens: number;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
usage?: {
|
|
44
|
+
input_tokens: number;
|
|
45
|
+
output_tokens: number;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* OpenAI stream chunk types
|
|
50
|
+
*/
|
|
51
|
+
export interface OpenAIStreamChunk {
|
|
52
|
+
id: string;
|
|
53
|
+
object: string;
|
|
54
|
+
created: number;
|
|
55
|
+
model: string;
|
|
56
|
+
choices: Array<{
|
|
57
|
+
index: number;
|
|
58
|
+
delta: {
|
|
59
|
+
content?: string;
|
|
60
|
+
role?: string;
|
|
61
|
+
tool_calls?: Array<{
|
|
62
|
+
index: number;
|
|
63
|
+
id?: string;
|
|
64
|
+
type?: string;
|
|
65
|
+
function?: {
|
|
66
|
+
name?: string;
|
|
67
|
+
arguments?: string;
|
|
68
|
+
};
|
|
69
|
+
}>;
|
|
70
|
+
};
|
|
71
|
+
finish_reason: string | null;
|
|
72
|
+
}>;
|
|
73
|
+
usage?: {
|
|
74
|
+
prompt_tokens: number;
|
|
75
|
+
completion_tokens: number;
|
|
76
|
+
total_tokens: number;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Vercel AI SDK stream part types
|
|
81
|
+
*/
|
|
82
|
+
export interface VercelAIStreamPart {
|
|
83
|
+
type: string;
|
|
84
|
+
value?: string | Record<string, unknown>;
|
|
85
|
+
toolCallId?: string;
|
|
86
|
+
toolName?: string;
|
|
87
|
+
args?: Record<string, unknown>;
|
|
88
|
+
result?: unknown;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Adapter options
|
|
92
|
+
*/
|
|
93
|
+
export interface AdapterOptions {
|
|
94
|
+
/** Protocol instance (created if not provided) */
|
|
95
|
+
protocol?: StreamProtocol;
|
|
96
|
+
/** Show thinking/reasoning blocks */
|
|
97
|
+
showThinking?: boolean;
|
|
98
|
+
/** Format tool calls as markdown */
|
|
99
|
+
formatToolCalls?: boolean;
|
|
100
|
+
/** Maximum tool result preview length */
|
|
101
|
+
maxToolResultLength?: number;
|
|
102
|
+
/** Custom event transformer */
|
|
103
|
+
transformer?: (event: unknown) => AnyStreamEvent | null;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Base adapter class
|
|
107
|
+
*/
|
|
108
|
+
export declare abstract class BaseAdapter {
|
|
109
|
+
protected protocol: StreamProtocol;
|
|
110
|
+
protected options: Required<AdapterOptions>;
|
|
111
|
+
protected currentToolId: string | null;
|
|
112
|
+
protected currentThinkingId: string | null;
|
|
113
|
+
constructor(options?: AdapterOptions);
|
|
114
|
+
/**
|
|
115
|
+
* Get the protocol instance
|
|
116
|
+
*/
|
|
117
|
+
getProtocol(): StreamProtocol;
|
|
118
|
+
/**
|
|
119
|
+
* Process a stream and yield text content
|
|
120
|
+
*/
|
|
121
|
+
abstract process(stream: AsyncIterable<unknown>): AsyncGenerator<string>;
|
|
122
|
+
/**
|
|
123
|
+
* Format tool call as markdown
|
|
124
|
+
*/
|
|
125
|
+
protected formatToolCall(name: string, input: unknown): string;
|
|
126
|
+
/**
|
|
127
|
+
* Format tool result as markdown
|
|
128
|
+
*/
|
|
129
|
+
protected formatToolResult(result: unknown): string;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Anthropic Claude API Adapter
|
|
133
|
+
*
|
|
134
|
+
* Handles:
|
|
135
|
+
* - message_start
|
|
136
|
+
* - content_block_start (text, tool_use, thinking)
|
|
137
|
+
* - content_block_delta
|
|
138
|
+
* - content_block_stop
|
|
139
|
+
* - message_delta
|
|
140
|
+
* - message_stop
|
|
141
|
+
*/
|
|
142
|
+
export declare class AnthropicAdapter extends BaseAdapter {
|
|
143
|
+
private toolInputBuffer;
|
|
144
|
+
process(stream: AsyncIterable<AnthropicMessageStreamEvent>): AsyncGenerator<string>;
|
|
145
|
+
private processEvent;
|
|
146
|
+
private handleContentBlockStart;
|
|
147
|
+
private handleContentBlockDelta;
|
|
148
|
+
private handleContentBlockStop;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* OpenAI API Adapter
|
|
152
|
+
*
|
|
153
|
+
* Handles chat completion streams
|
|
154
|
+
*/
|
|
155
|
+
export declare class OpenAIAdapter extends BaseAdapter {
|
|
156
|
+
private toolCallBuffers;
|
|
157
|
+
process(stream: AsyncIterable<OpenAIStreamChunk>): AsyncGenerator<string>;
|
|
158
|
+
private processChunk;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Vercel AI SDK Adapter
|
|
162
|
+
*
|
|
163
|
+
* Handles streamText and streamObject outputs
|
|
164
|
+
*/
|
|
165
|
+
export declare class VercelAIAdapter extends BaseAdapter {
|
|
166
|
+
process(stream: AsyncIterable<VercelAIStreamPart | string>): AsyncGenerator<string>;
|
|
167
|
+
private processPart;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Generic async iterable adapter
|
|
171
|
+
*
|
|
172
|
+
* For simple string streams
|
|
173
|
+
*/
|
|
174
|
+
export declare class GenericAdapter extends BaseAdapter {
|
|
175
|
+
process(stream: AsyncIterable<string>): AsyncGenerator<string>;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Create adapter for specific provider
|
|
179
|
+
*/
|
|
180
|
+
export declare function createAdapter(provider: 'anthropic' | 'openai' | 'vercel' | 'generic', options?: AdapterOptions): BaseAdapter;
|
|
181
|
+
/**
|
|
182
|
+
* Auto-detect and create adapter from stream
|
|
183
|
+
*/
|
|
184
|
+
export declare function autoAdapter(_stream: AsyncIterable<unknown>, options?: AdapterOptions): BaseAdapter;
|
|
185
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"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"}
|