llm-sse 0.4.8 → 0.5.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 CHANGED
@@ -6,6 +6,35 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.5.0] - 2026-07-23
10
+
11
+ ### Added
12
+
13
+ - `parseOpenAIResponsesStream(source)` and the `openai-responses` dispatcher
14
+ target for typed OpenAI Responses API streams.
15
+ - Normalization for Responses API text, reasoning summaries, function-call
16
+ arguments, refusal text, completion, incomplete responses, and errors.
17
+ - A public Responses API weather-tool fixture with normalized event and
18
+ collected-message expectations.
19
+ - Public roadmap, governance, support channels, and a documented path from
20
+ contributor to maintainer.
21
+
22
+ ### Changed
23
+
24
+ - Project documentation now links contribution, security, governance, support,
25
+ roadmap, and release resources from the README.
26
+ - The published tarball now includes those public project documents and is
27
+ installation-tested before release.
28
+ - Development tooling overrides `esbuild` to a patched release so a clean
29
+ install passes `npm audit` without changing the package's zero-dependency
30
+ runtime.
31
+
32
+ ## [0.4.9] - 2026-06-29
33
+
34
+ ### Changed
35
+
36
+ - Documentation: replace em dashes with standard punctuation for consistent house style.
37
+
9
38
  ## [0.4.8] - 2026-06-29
10
39
 
11
40
  ### Changed
@@ -111,6 +140,16 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
111
140
  and `Uint8Array` or string sources.
112
141
  - Zero runtime dependencies; ESM + CJS builds with type declarations.
113
142
 
143
+ [0.5.0]: https://github.com/slegarraga/llm-sse/releases/tag/v0.5.0
144
+ [0.4.9]: https://github.com/slegarraga/llm-sse/releases/tag/v0.4.9
145
+ [0.4.8]: https://github.com/slegarraga/llm-sse/releases/tag/v0.4.8
146
+ [0.4.7]: https://github.com/slegarraga/llm-sse/releases/tag/v0.4.7
147
+ [0.4.6]: https://github.com/slegarraga/llm-sse/releases/tag/v0.4.6
148
+ [0.4.5]: https://github.com/slegarraga/llm-sse/releases/tag/v0.4.5
149
+ [0.4.4]: https://github.com/slegarraga/llm-sse/releases/tag/v0.4.4
150
+ [0.4.3]: https://github.com/slegarraga/llm-sse/releases/tag/v0.4.3
151
+ [0.4.2]: https://github.com/slegarraga/llm-sse/releases/tag/v0.4.2
152
+ [0.4.1]: https://github.com/slegarraga/llm-sse/releases/tag/v0.4.1
114
153
  [0.4.0]: https://github.com/slegarraga/llm-sse/releases/tag/v0.4.0
115
154
  [0.3.0]: https://github.com/slegarraga/llm-sse/releases/tag/v0.3.0
116
155
  [0.2.0]: https://github.com/slegarraga/llm-sse/releases/tag/v0.2.0
@@ -0,0 +1,57 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment include:
18
+
19
+ - Demonstrating empathy and kindness toward other people
20
+ - Being respectful of differing opinions, viewpoints, and experiences
21
+ - Giving and gracefully accepting constructive feedback
22
+ - Accepting responsibility and apologizing to those affected by our mistakes
23
+ - Focusing on what is best for the overall community
24
+
25
+ Examples of unacceptable behavior include:
26
+
27
+ - The use of sexualized language or imagery, and sexual attention or advances
28
+ - Trolling, insulting or derogatory comments, and personal or political attacks
29
+ - Public or private harassment
30
+ - Publishing others' private information without their explicit permission
31
+ - Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Enforcement Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying and enforcing our standards of
37
+ acceptable behavior and will take appropriate and fair corrective action in
38
+ response to any behavior that they deem inappropriate, threatening, offensive, or
39
+ harmful.
40
+
41
+ ## Scope
42
+
43
+ This Code of Conduct applies within all community spaces, and also applies when
44
+ an individual is officially representing the community in public spaces.
45
+
46
+ ## Enforcement
47
+
48
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
49
+ reported to the maintainers at **sebastian@0a.cl**. All complaints will be
50
+ reviewed and investigated promptly and fairly. All maintainers are obligated to
51
+ respect the privacy and security of the reporter of any incident.
52
+
53
+ ## Attribution
54
+
55
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
56
+ version 2.1, available at
57
+ https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
@@ -0,0 +1,65 @@
1
+ # Contributing to llm-sse
2
+
3
+ Thanks for taking the time to contribute. This project aims to be a small,
4
+ dependable, zero-dependency building block, so the bar for changes is clarity
5
+ and correctness over breadth.
6
+
7
+ ## Getting started
8
+
9
+ ```sh
10
+ git clone https://github.com/slegarraga/llm-sse.git
11
+ cd llm-sse
12
+ npm install
13
+ ```
14
+
15
+ ## Development workflow
16
+
17
+ Every change should keep the full check suite green:
18
+
19
+ ```sh
20
+ npm run typecheck # tsc --noEmit
21
+ npm run lint # eslint
22
+ npm test # vitest
23
+ npm run build # tsup (ESM + CJS + types)
24
+ npm run format # prettier --write
25
+ ```
26
+
27
+ Run `npm run test:watch` while developing.
28
+
29
+ ## Pull requests
30
+
31
+ 1. Fork the repo and create a branch from `main` (e.g. `fix/gemini-tool-index`).
32
+ 2. Add or update tests. New behaviour without a test will not be merged.
33
+ 3. Make sure `typecheck`, `lint`, `test` and `build` all pass.
34
+ 4. Keep the public API surface small and documented with JSDoc.
35
+ 5. Open a pull request describing the provider stream shape you are handling.
36
+
37
+ ## Commit messages
38
+
39
+ This project uses [Conventional Commits](https://www.conventionalcommits.org/).
40
+ Examples:
41
+
42
+ ```
43
+ feat(anthropic): handle thinking_delta blocks
44
+ fix(sse): join multi-line data fields per spec
45
+ docs: clarify the tool-call delta model
46
+ test: cover chunk boundaries splitting an event
47
+ chore: bump dev dependencies
48
+ ```
49
+
50
+ The type drives the next version bump (`fix` -> patch, `feat` -> minor, a
51
+ `!` or `BREAKING CHANGE` footer -> major).
52
+
53
+ ## Reporting bugs
54
+
55
+ Open an issue with a minimal reproduction: the raw stream bytes (or the `data:`
56
+ lines) from the provider, which provider produced them, and the `StreamEvent`s
57
+ you expected. A failing test case is the most useful form a bug report can take.
58
+
59
+ ## Scope and philosophy
60
+
61
+ - Zero runtime dependencies. A dependency needs an exceptional justification.
62
+ - Parsing is total: malformed or non-JSON `data:` lines are skipped, never
63
+ thrown, so one bad keep-alive can't break a stream.
64
+ - Event mapping is grounded in official provider documentation. When you add or
65
+ change a rule, link the source in the PR.
package/GOVERNANCE.md ADDED
@@ -0,0 +1,71 @@
1
+ # Governance
2
+
3
+ `llm-sse` is an independent open-source project. Governance is designed to keep
4
+ the parser small and dependable while making it possible for trusted
5
+ contributors to take real ownership.
6
+
7
+ ## Current maintainer
8
+
9
+ - [Sebastian Legarraga](https://github.com/slegarraga) — project direction,
10
+ releases, security response, and repository administration.
11
+
12
+ The project currently has a single maintainer. Expanding the maintainer group is
13
+ an explicit goal, not a prerequisite contributors must wait for.
14
+
15
+ ## How decisions are made
16
+
17
+ - Bug fixes and small, backward-compatible improvements are decided through
18
+ pull-request review.
19
+ - New provider formats, normalized event variants, and breaking changes should
20
+ start with a public issue or discussion.
21
+ - Decisions prioritize primary provider documentation, reproducible fixtures,
22
+ interoperability, security, and maintenance cost.
23
+ - If reasonable contributors disagree, the maintainer records the tradeoff and
24
+ decision publicly rather than moving the discussion to a private channel.
25
+
26
+ ## Roles
27
+
28
+ ### Contributor
29
+
30
+ Anyone who reports a reproducible issue, improves documentation, supplies a
31
+ sanitized fixture, or lands a code change.
32
+
33
+ ### Reviewer
34
+
35
+ A contributor who understands an area of the project and regularly helps review
36
+ changes or triage issues. Reviewers may be listed in the repository and invited
37
+ to relevant reviews.
38
+
39
+ ### Maintainer
40
+
41
+ A trusted reviewer with sustained, constructive involvement who can merge
42
+ changes, manage issues, and help prepare releases. Maintainers are expected to:
43
+
44
+ - uphold the code of conduct and security policy;
45
+ - require tests and primary-source evidence for provider behavior changes;
46
+ - disclose conflicts of interest;
47
+ - avoid merging their own substantial changes without another review when a
48
+ second maintainer is available;
49
+ - preserve the project's zero-dependency and compatibility commitments.
50
+
51
+ Maintainer access is offered based on demonstrated judgment, reliability,
52
+ project need, and mutual agreement. It is never exchanged for sponsorship,
53
+ stars, or a fixed number of pull requests.
54
+
55
+ ## Releases
56
+
57
+ Releases follow Semantic Versioning. The release workflow reruns type checking,
58
+ linting, tests, and the build before publishing with npm provenance. Breaking
59
+ changes require a migration note.
60
+
61
+ ## Security and conduct
62
+
63
+ Security reports follow [SECURITY.md](./SECURITY.md). Community behavior follows
64
+ [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md). A maintainer involved in a conduct
65
+ or security concern should recuse themselves when another trusted reviewer is
66
+ available.
67
+
68
+ ## Changes to governance
69
+
70
+ Governance changes use the same public pull-request process as code changes and
71
+ should explain the problem they solve.
package/README.md CHANGED
@@ -9,16 +9,64 @@
9
9
  [![license](https://img.shields.io/npm/l/llm-sse.svg)](./LICENSE)
10
10
  [![zero dependencies](https://img.shields.io/badge/dependencies-0-brightgreen.svg)](./package.json)
11
11
 
12
- > Zero-dependency SSE parser that turns OpenAI, Anthropic, Gemini and any OpenAI-compatible stream into one unified event shape: text deltas, reasoning, tool-call fragments and finish reasons, handled the same way regardless of provider.
12
+ > Zero-dependency SSE parser that turns OpenAI Responses, OpenAI Chat Completions, Anthropic, Gemini and OpenAI-compatible streams into one unified event shape: text deltas, reasoning, tool-call fragments and finish reasons, handled the same way regardless of provider.
13
13
 
14
14
  Security posture is tracked in [docs/security-posture.md](https://github.com/slegarraga/llm-sse/blob/main/docs/security-posture.md),
15
15
  including CodeQL, OpenSSF Scorecard, Dependabot and branch rules.
16
16
 
17
- Each provider streams differently. OpenAI sends `choices[].delta` chunks, Anthropic sends typed `content_block_*` / `message_*` events, Gemini sends `candidates[].content.parts` — and the SSE framing, tool-call argument fragments and stop reasons are all shaped differently. `llm-sse` turns any of them into the same small set of events, so your streaming UI or agent loop stays provider-agnostic.
17
+ Each API streams differently. OpenAI Responses sends typed `response.*` events,
18
+ OpenAI Chat Completions sends `choices[].delta` chunks, Anthropic sends typed
19
+ `content_block_*` / `message_*` events, and Gemini sends
20
+ `candidates[].content.parts`. `llm-sse` turns all of them into the same small
21
+ set of events, so your streaming UI or agent loop stays provider-agnostic.
22
+
23
+ ## Project
24
+
25
+ - [Roadmap](./ROADMAP.md): compatibility, conformance, and sustainability priorities
26
+ - [Contributing](./CONTRIBUTING.md): local setup, tests, and pull-request expectations
27
+ - [Governance](./GOVERNANCE.md): decision process and the path to reviewer or maintainer
28
+ - [Support](./SUPPORT.md): where to ask questions or report reproducible bugs
29
+ - [Security](./SECURITY.md): private vulnerability reporting and supported versions
30
+ - [Changelog](./CHANGELOG.md): release history and migration notes
31
+ - [Code of Conduct](./CODE_OF_CONDUCT.md): community standards
18
32
 
19
33
  ## Quickstart
20
34
 
21
- ### OpenAI
35
+ ### OpenAI Responses API
36
+
37
+ ```ts
38
+ import { parseOpenAIResponsesStream } from 'llm-sse';
39
+
40
+ const res = await fetch('https://api.openai.com/v1/responses', {
41
+ method: 'POST',
42
+ headers: {
43
+ Authorization: `Bearer ${key}`,
44
+ 'content-type': 'application/json',
45
+ },
46
+ body: JSON.stringify({
47
+ model: process.env.OPENAI_MODEL,
48
+ input: 'What is the weather in Santiago?',
49
+ tools,
50
+ stream: true,
51
+ }),
52
+ });
53
+
54
+ for await (const event of parseOpenAIResponsesStream(res.body)) {
55
+ if (event.type === 'text') process.stdout.write(event.text);
56
+ if (event.type === 'tool_call_delta') {
57
+ process.stderr.write(event.argumentsDelta);
58
+ }
59
+ }
60
+ ```
61
+
62
+ The parser follows the official
63
+ [Responses streaming event reference](https://platform.openai.com/docs/api-reference/responses-streaming),
64
+ including output text, reasoning summaries, function-call arguments,
65
+ refusal text, completion, incomplete responses, and errors. Refusal deltas use
66
+ the normalized `text` channel so provider-agnostic UIs do not drop the model's
67
+ response.
68
+
69
+ ### OpenAI Chat Completions
22
70
 
23
71
  ```ts
24
72
  import { parseOpenAIStream } from 'llm-sse';
@@ -29,7 +77,11 @@ const res = await fetch('https://api.openai.com/v1/chat/completions', {
29
77
  Authorization: `Bearer ${key}`,
30
78
  'content-type': 'application/json',
31
79
  },
32
- body: JSON.stringify({ model: 'gpt-4o', messages, stream: true }),
80
+ body: JSON.stringify({
81
+ model: process.env.OPENAI_MODEL,
82
+ messages,
83
+ stream: true,
84
+ }),
33
85
  });
34
86
 
35
87
  for await (const event of parseOpenAIStream(res.body)) {
@@ -112,16 +164,29 @@ for await (const event of parseOpenAIStream(res.body)) {
112
164
 
113
165
  ## Why
114
166
 
115
- - **One event shape, three providers.** `text`, `tool_call_start`, `tool_call_delta`, `finish`, `error` — the same whether the bytes came from OpenAI, Anthropic or Gemini.
167
+ - **One event shape, four streaming formats.** `text`, `reasoning`, `tool_call_start`, `tool_call_delta`, `finish`, and `error`, whether the bytes came from OpenAI Responses, OpenAI Chat Completions, Anthropic, or Gemini.
116
168
  - **Tool calls just accumulate.** Streamed JSON argument fragments carry an `index`; concatenate by index (or let `collectStream` do it) to get the full call.
117
169
  - **Correct SSE framing.** Robust to chunk boundaries splitting a line or event mid-way, CRLF, multi-line `data:` fields, comments and keep-alives.
118
170
  - **Fixture-backed provider coverage.** Public OpenAI, Anthropic and Gemini `.sse` fixtures exercise text, reasoning, tool-call arguments and finish reasons.
119
- - **Bytes or strings.** Feed it a `fetch()` `ReadableStream<Uint8Array>`, a Node stream, or an async iterable of strings multibyte UTF-8 split across chunks is handled.
171
+ - **Bytes or strings.** Feed it a `fetch()` `ReadableStream<Uint8Array>`, a Node stream, or an async iterable of strings. Multibyte UTF-8 split across chunks is handled.
120
172
  - **Zero dependencies**, ESM + CJS, fully typed.
121
173
 
174
+ | Streaming source | Parser | Text | Reasoning | Function calls | Finish and errors |
175
+ | ------------------------------ | ---------------------------- | :--: | :---------------: | :------------: | :---------------: |
176
+ | OpenAI Responses API | `parseOpenAIResponsesStream` | ✓ | ✓ | ✓ | ✓ |
177
+ | OpenAI Chat Completions | `parseOpenAIStream` | ✓ | compatible fields | ✓ | ✓ |
178
+ | Anthropic Messages | `parseAnthropicStream` | ✓ | ✓ | ✓ | ✓ |
179
+ | Gemini `streamGenerateContent` | `parseGeminiStream` | ✓ | ✓ | ✓ | ✓ |
180
+
122
181
  ## Why not the provider SDK?
123
182
 
124
- The official SDKs (openai, @anthropic-ai/sdk, @google/generative-ai) each ship their own streaming abstraction, so combining two providers means learning two APIs and writing two adapter paths in your agent or UI. `llm-sse` is a thin, zero-dependency layer that normalizes the wire format only. You keep your own fetch/retry/auth logic, and every provider becomes the same three event types. If you are already using a provider SDK exclusively and do not plan to switch, the SDK's streaming helpers may be sufficient; this library is most useful when you need provider portability, a minimal footprint, or control over the HTTP layer.
183
+ The official SDKs each ship their own streaming abstraction, so combining APIs
184
+ means learning multiple event models and writing multiple adapter paths in your
185
+ agent or UI. `llm-sse` is a thin, zero-dependency layer that normalizes the wire
186
+ format only. You keep your own fetch, retry, and authentication logic. If you
187
+ use one provider exclusively, its SDK helpers may be sufficient; this library is
188
+ most useful when you need provider portability, a minimal footprint, or control
189
+ over the HTTP layer.
125
190
 
126
191
  ## Install
127
192
 
@@ -131,9 +196,16 @@ npm install llm-sse
131
196
 
132
197
  ## API
133
198
 
199
+ ### `parseOpenAIResponsesStream(source)`
200
+
201
+ Parses typed OpenAI Responses API SSE events. It maps
202
+ `response.output_text.delta`, reasoning deltas, function-call item and argument
203
+ events, and terminal response states into normalized events. The Responses
204
+ `output_index` is used as the normalized tool-call index.
205
+
134
206
  ### `parseOpenAIStream(source)` · `parseAnthropicStream(source)` · `parseGeminiStream(source)`
135
207
 
136
- Each takes a `source` (`AsyncIterable<Uint8Array | string>` `fetch().body` satisfies this) and returns an `AsyncGenerator<StreamEvent>`.
208
+ Each takes a `source` (`AsyncIterable<Uint8Array | string>`, `fetch().body` satisfies this) and returns an `AsyncGenerator<StreamEvent>`.
137
209
 
138
210
  > Gemini: use the SSE form of the streaming endpoint (`streamGenerateContent?alt=sse`).
139
211
 
@@ -141,7 +213,8 @@ Each takes a `source` (`AsyncIterable<Uint8Array | string>` — `fetch().body` s
141
213
 
142
214
  ### `parseStream(source, provider)`
143
215
 
144
- Same thing, dispatching on `provider` (`'openai' | 'anthropic' | 'gemini'`).
216
+ Same thing, dispatching on `provider`
217
+ (`'openai-responses' | 'openai' | 'anthropic' | 'gemini'`).
145
218
 
146
219
  ### `StreamEvent`
147
220
 
@@ -155,7 +228,9 @@ type StreamEvent =
155
228
  | { type: 'error'; error: unknown };
156
229
  ```
157
230
 
158
- > `reasoning` carries the model's thinking (Anthropic extended thinking `thinking_delta` and Gemini `thought` parts) separately from `text`, so you can render it in its own affordance or drop it.
231
+ > `reasoning` carries OpenAI reasoning text or summaries, Anthropic extended
232
+ > thinking, and Gemini thought parts separately from `text`, so you can render
233
+ > it in its own affordance or drop it.
159
234
 
160
235
  ### `collectStream(events)`
161
236
 
@@ -165,12 +240,12 @@ Drains an event stream into a single message:
165
240
  const { text, reasoning, toolCalls, finishReason } = await collectStream(
166
241
  parseAnthropicStream(res.body),
167
242
  );
168
- // toolCalls: { index, id?, name?, arguments }[] arguments is the joined JSON string
243
+ // toolCalls: { index, id?, name?, arguments }[], arguments is the joined JSON string
169
244
  ```
170
245
 
171
246
  ### `toAssistantMessage(collected)`
172
247
 
173
- Turn a collected stream into a standard OpenAI-shape assistant message the format `llm-messages` treats as canonical so a streamed response composes straight back into your history or into a different provider:
248
+ Turn a collected stream into a standard OpenAI-shape assistant message, the format `llm-messages` treats as canonical, so a streamed response composes straight back into your history or into a different provider:
174
249
 
175
250
  ```ts
176
251
  import { collectStream, toAssistantMessage } from 'llm-sse';
@@ -271,13 +346,19 @@ const result2 = await complete('openai', openaiResponse);
271
346
 
272
347
  ## Tool calls
273
348
 
274
- All three providers are normalized to the same pattern: a `tool_call_start` (with `index`, and `id` / `name` when available) followed by one or more `tool_call_delta`s whose `argumentsDelta` strings concatenate into the call's JSON arguments. OpenAI and Anthropic fragment the arguments; Gemini sends them whole in a single delta. `collectStream` joins them for you.
349
+ All supported APIs are normalized to the same pattern: a `tool_call_start`
350
+ (with `index`, and `id` / `name` when available) followed by one or more
351
+ `tool_call_delta`s whose `argumentsDelta` strings concatenate into the call's
352
+ JSON arguments. OpenAI Responses uses its stable `output_index`; Chat
353
+ Completions and Anthropic stream argument fragments; Gemini sends arguments
354
+ whole in a single delta. `collectStream` joins them for you.
275
355
 
276
356
  ## Fixture corpus
277
357
 
278
358
  The package includes a small public fixture corpus under [`fixtures/`](https://github.com/slegarraga/llm-sse/tree/main/fixtures):
279
359
 
280
360
  - `openai-weather-tool.sse`
361
+ - `openai-responses-weather-tool.sse`
281
362
  - `anthropic-weather-tool.sse`
282
363
  - `gemini-weather-tool.sse`
283
364
  - expected normalized events and collected messages under `fixtures/expected/`
@@ -287,6 +368,15 @@ Each fixture describes the same semantic turn: reasoning, visible text, a
287
368
  The tests parse the fixtures directly, including byte-split stream boundaries,
288
369
  so contributors can change parsers with a stable cross-provider contract.
289
370
 
371
+ ## Community
372
+
373
+ Contributions are welcome, especially sanitized provider fixtures, reproducible
374
+ edge cases, interoperability examples, and review help. Start with
375
+ [CONTRIBUTING.md](./CONTRIBUTING.md), use
376
+ [Discussions](https://github.com/slegarraga/llm-sse/discussions) for design
377
+ questions, and see [GOVERNANCE.md](./GOVERNANCE.md) for how sustained
378
+ contributors can become reviewers or maintainers.
379
+
290
380
  ## Related
291
381
 
292
382
  - [`json-from-llm`](https://www.npmjs.com/package/json-from-llm): extract valid JSON from an LLM response, even inside reasoning tags, fenced blocks or prose
package/ROADMAP.md ADDED
@@ -0,0 +1,64 @@
1
+ # Roadmap
2
+
3
+ `llm-sse` exists to make provider streaming predictable without requiring a
4
+ provider SDK or adding runtime dependencies. The roadmap prioritizes correctness,
5
+ interoperability, and evidence-backed support over adding providers by name.
6
+
7
+ ## Current priorities
8
+
9
+ ### 1. Streaming conformance
10
+
11
+ - Keep the public fixture corpus aligned with documented OpenAI Responses,
12
+ OpenAI Chat Completions, Anthropic Messages, and Gemini event shapes.
13
+ - Add regression fixtures for real provider edge cases after removing secrets
14
+ and user content.
15
+ - Preserve byte-boundary, line-ending, malformed-event, and multi-tool coverage.
16
+
17
+ ### 2. Provider portability
18
+
19
+ - Keep normalized text, reasoning, tool-call, finish, and error events stable.
20
+ - Document unavoidable information loss between provider formats.
21
+ - Improve composition with
22
+ [`llm-messages`](https://github.com/slegarraga/llm-messages),
23
+ [`tool-schema`](https://github.com/slegarraga/tool-schema), and
24
+ [`llm-errors`](https://github.com/slegarraga/llm-errors).
25
+
26
+ ### 3. Maintainer workflows
27
+
28
+ - Make provider-behavior changes reviewable through small fixtures and explicit
29
+ links to primary documentation.
30
+ - Automate compatibility reports, release notes, and routine issue triage while
31
+ keeping release decisions human-reviewed.
32
+ - Publish enough project context for contributors to reproduce and own an area
33
+ of the parser.
34
+
35
+ ### 4. Sustainable community
36
+
37
+ - Grow usage through real integrations and examples rather than synthetic stars
38
+ or low-value promotion.
39
+ - Welcome additional reviewers and maintainers through the path described in
40
+ [GOVERNANCE.md](./GOVERNANCE.md).
41
+ - Track breaking proposals in public issues before implementation.
42
+
43
+ ## API credit use
44
+
45
+ If the project receives sponsored API credits, they will be used for opt-in
46
+ conformance checks against official provider endpoints, fixture refreshes,
47
+ regression reproduction, and maintainer automation. Secrets and user prompts
48
+ will not be committed. Pull requests will continue to run deterministically
49
+ against sanitized offline fixtures.
50
+
51
+ ## Non-goals
52
+
53
+ - Replacing full provider SDKs.
54
+ - Managing authentication, retries, billing, or network requests.
55
+ - Claiming compatibility with an endpoint without a documented event format or
56
+ reproducible fixture.
57
+ - Adding runtime dependencies for convenience.
58
+
59
+ ## Propose an item
60
+
61
+ Open a [GitHub Discussion](https://github.com/slegarraga/llm-sse/discussions)
62
+ for design exploration or a
63
+ [feature request](https://github.com/slegarraga/llm-sse/issues/new?template=feature_request.yml)
64
+ for a scoped, testable change.
package/SECURITY.md ADDED
@@ -0,0 +1,24 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ The latest published `0.x` release receives security fixes.
6
+
7
+ ## Reporting a vulnerability
8
+
9
+ Please report security issues privately rather than opening a public issue.
10
+
11
+ - Use GitHub's [private vulnerability reporting](https://github.com/slegarraga/llm-sse/security/advisories/new), or
12
+ - Email **sebastian@0a.cl** with the details.
13
+
14
+ Include a description, a reproduction, and the impact. You can expect an initial
15
+ response within a few days. Once a fix is released, we are happy to credit you in
16
+ the advisory unless you prefer to remain anonymous.
17
+
18
+ ## Scope
19
+
20
+ `llm-sse` has zero runtime dependencies and performs only in-memory parsing
21
+ of streamed text: it does not make network requests, read or write files, or
22
+ execute code from its input. The most relevant risks are denial of service from
23
+ pathological input (for example, unbounded buffering on a stream with no event
24
+ delimiters). Reports along those lines are welcome.
package/SUPPORT.md ADDED
@@ -0,0 +1,38 @@
1
+ # Support
2
+
3
+ `llm-sse` is maintained in public on a best-effort basis.
4
+
5
+ ## Questions and design discussions
6
+
7
+ Use [GitHub Discussions](https://github.com/slegarraga/llm-sse/discussions) for
8
+ integration questions, design exploration, and help choosing the right parser.
9
+
10
+ ## Bugs
11
+
12
+ Open a
13
+ [bug report](https://github.com/slegarraga/llm-sse/issues/new?template=bug_report.yml)
14
+ with:
15
+
16
+ - the provider and API surface;
17
+ - a minimal, sanitized sequence of SSE `data:` payloads;
18
+ - the normalized events you expected and received;
19
+ - the `llm-sse`, Node.js, and runtime versions;
20
+ - a reproduction or failing test when possible.
21
+
22
+ Please do not include API keys, private prompts, personal data, or proprietary
23
+ model output.
24
+
25
+ ## Security
26
+
27
+ Do not open a public issue for a vulnerability. Follow
28
+ [SECURITY.md](./SECURITY.md) to use GitHub private vulnerability reporting or
29
+ the listed security email.
30
+
31
+ ## Scope
32
+
33
+ The project can help with parsing and normalization behavior. Provider account
34
+ access, billing, rate limits, model availability, and general SDK support belong
35
+ with the relevant provider.
36
+
37
+ No response-time guarantee is offered, but well-scoped reproductions and pull
38
+ requests are prioritized.