llm-messages 0.5.3 → 0.5.5
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 +20 -0
- package/CODE_OF_CONDUCT.md +57 -0
- package/CONTRIBUTING.md +101 -0
- package/GOVERNANCE.md +72 -0
- package/README.md +150 -17
- package/ROADMAP.md +12 -5
- package/SUPPORT.md +41 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,26 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.5.5] - 2026-07-23
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Documented the boundary between completed Responses API normalization in
|
|
14
|
+
`llm-messages` and incremental Responses streaming in `llm-sse`.
|
|
15
|
+
- Added public governance, support channels, maintainer responsibilities, and a
|
|
16
|
+
contributor-to-maintainer path.
|
|
17
|
+
- Replaced the closed Responses coverage roadmap link with a scoped
|
|
18
|
+
cross-package conformance issue.
|
|
19
|
+
- Included governance and support documentation in the published package.
|
|
20
|
+
- Development tooling overrides `esbuild` to a patched release so a clean
|
|
21
|
+
install passes `npm audit` while the runtime remains dependency-free.
|
|
22
|
+
|
|
23
|
+
## [0.5.4] - 2026-06-29
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Documentation: add provider-SDK recipes (OpenAI, Anthropic, Vercel AI SDK), a "why not alternatives" section, complete cross-links to the sibling packages, and install / bundle-size badges. No code changes.
|
|
28
|
+
|
|
9
29
|
## [0.5.3] - 2026-06-29
|
|
10
30
|
|
|
11
31
|
### Fixed
|
|
@@ -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.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Contributing to llm-messages
|
|
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
|
+
The published package supports Node 18+ at runtime. The local development
|
|
10
|
+
toolchain currently needs Node 20.19+ or Node 22.13+ because the lint, test and
|
|
11
|
+
build dependencies follow those active Node release lines. CI keeps the runtime
|
|
12
|
+
floor honest by installing the packed tarball in a separate Node 18 consumer
|
|
13
|
+
smoke.
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
git clone https://github.com/slegarraga/llm-messages.git
|
|
17
|
+
cd llm-messages
|
|
18
|
+
npm install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Development workflow
|
|
22
|
+
|
|
23
|
+
Every change should keep the full check suite green:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
npm run check # full validation suite
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
That script runs the same checks individually listed here:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm run format:check # prettier --check
|
|
33
|
+
npm run typecheck # tsc --noEmit
|
|
34
|
+
npm run lint # eslint
|
|
35
|
+
npm test # vitest
|
|
36
|
+
npm run build # tsup (ESM + CJS + types)
|
|
37
|
+
npm run examples:check # smoke-test packaged ESM/CommonJS examples
|
|
38
|
+
npm run pack:check # npm pack --dry-run, with lifecycle output quieted
|
|
39
|
+
npm run pack:smoke # install the packed tarball and verify runtime/types usage
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Run `npm run test:watch` and `npm run format` while developing.
|
|
43
|
+
|
|
44
|
+
## Release and staging review
|
|
45
|
+
|
|
46
|
+
Before staging release, fixture, package metadata or published-file changes,
|
|
47
|
+
review the complete worktree, including untracked files:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
git status --short -uall
|
|
51
|
+
git diff --stat
|
|
52
|
+
npm run check
|
|
53
|
+
npm pack --dry-run --foreground-scripts=false
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Confirm that new fixtures, examples and scripts are intentional, and that no
|
|
57
|
+
private source, test, script, config or generated files are included in the
|
|
58
|
+
package dry-run output. Do not publish from a dirty tree whose untracked files
|
|
59
|
+
have not been reviewed.
|
|
60
|
+
|
|
61
|
+
## Pull requests
|
|
62
|
+
|
|
63
|
+
1. Fork the repo and create a branch from `main` (e.g. `fix/gemini-id-matching`).
|
|
64
|
+
2. Add or update tests. New behaviour without a test will not be merged.
|
|
65
|
+
3. When adding conformance fixtures, update `docs/conformance-fixtures.md`
|
|
66
|
+
in the same change so the fixture inventory stays reviewable and the
|
|
67
|
+
offline harness remains deterministic.
|
|
68
|
+
4. Make sure `format:check`, `typecheck`, `lint`, `test`, `build`,
|
|
69
|
+
`examples:check`, `pack:check` and `pack:smoke` all pass.
|
|
70
|
+
5. Keep the public API surface small and documented with JSDoc.
|
|
71
|
+
6. Open a pull request and fill in the template.
|
|
72
|
+
|
|
73
|
+
## Commit messages
|
|
74
|
+
|
|
75
|
+
This project uses [Conventional Commits](https://www.conventionalcommits.org/).
|
|
76
|
+
Examples:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
feat(gemini): support functionResponse arrays
|
|
80
|
+
fix(anthropic): merge consecutive tool-result turns
|
|
81
|
+
docs: clarify the canonical hub model
|
|
82
|
+
test: cover parallel tool calls
|
|
83
|
+
chore: bump dev dependencies
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The type drives the next version bump (`fix` -> patch, `feat` -> minor, a
|
|
87
|
+
`!` or `BREAKING CHANGE` footer -> major).
|
|
88
|
+
|
|
89
|
+
## Reporting bugs
|
|
90
|
+
|
|
91
|
+
Open an issue with a minimal reproduction: the input conversation, the target
|
|
92
|
+
provider, what you expected, and what you got. A failing test case is the most
|
|
93
|
+
useful form a bug report can take.
|
|
94
|
+
|
|
95
|
+
## Scope and philosophy
|
|
96
|
+
|
|
97
|
+
- Zero runtime dependencies. A dependency needs an exceptional justification.
|
|
98
|
+
- Conversions are total: they never throw on malformed input, they make a
|
|
99
|
+
deterministic choice and report it through `onWarning`.
|
|
100
|
+
- Provider behaviour is grounded in official documentation. When you add or
|
|
101
|
+
change a rule, link the source in the PR.
|
package/GOVERNANCE.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Governance
|
|
2
|
+
|
|
3
|
+
`llm-messages` is an independent open-source project and the conversation
|
|
4
|
+
boundary of the provider-portability suite. Governance favors correctness,
|
|
5
|
+
transparent tradeoffs, and a realistic path for contributors to take 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. Adding trusted reviewers and
|
|
13
|
+
maintainers is a project goal.
|
|
14
|
+
|
|
15
|
+
## Decision process
|
|
16
|
+
|
|
17
|
+
- Small fixes and backward-compatible improvements are decided through
|
|
18
|
+
pull-request review.
|
|
19
|
+
- New canonical message fields, provider targets, warning codes, or breaking
|
|
20
|
+
changes should start with a public issue or discussion.
|
|
21
|
+
- Provider mappings must be grounded in primary documentation and reproducible
|
|
22
|
+
fixtures.
|
|
23
|
+
- Lossy behavior must stay visible through stable warnings rather than being
|
|
24
|
+
hidden for convenience.
|
|
25
|
+
- When reasonable contributors disagree, the maintainer records the tradeoff
|
|
26
|
+
and decision publicly.
|
|
27
|
+
|
|
28
|
+
## Roles
|
|
29
|
+
|
|
30
|
+
### Contributor
|
|
31
|
+
|
|
32
|
+
Anyone who reports a reproducible problem, improves documentation, adds a
|
|
33
|
+
reviewed fixture, or lands a code change.
|
|
34
|
+
|
|
35
|
+
### Reviewer
|
|
36
|
+
|
|
37
|
+
A contributor with demonstrated understanding of one or more conversion
|
|
38
|
+
surfaces who regularly helps review changes or triage issues.
|
|
39
|
+
|
|
40
|
+
### Maintainer
|
|
41
|
+
|
|
42
|
+
A trusted reviewer with sustained, constructive involvement who can merge
|
|
43
|
+
changes, manage issues, and prepare releases. Maintainers are expected to:
|
|
44
|
+
|
|
45
|
+
- uphold the code of conduct and security policy;
|
|
46
|
+
- require tests and primary-source evidence for provider behavior;
|
|
47
|
+
- preserve deterministic, offline CI and the zero-dependency runtime;
|
|
48
|
+
- disclose conflicts of interest;
|
|
49
|
+
- avoid merging their own substantial changes without another review when a
|
|
50
|
+
second maintainer is available.
|
|
51
|
+
|
|
52
|
+
Maintainer access is based on judgment, reliability, project need, and mutual
|
|
53
|
+
agreement. It is never exchanged for sponsorship, stars, or a fixed number of
|
|
54
|
+
pull requests.
|
|
55
|
+
|
|
56
|
+
## Releases
|
|
57
|
+
|
|
58
|
+
Releases follow Semantic Versioning. The release workflow runs the full
|
|
59
|
+
validation suite, package dry run, installed ESM/CommonJS/type smoke tests, and
|
|
60
|
+
npm provenance publishing. Breaking changes require a migration note.
|
|
61
|
+
|
|
62
|
+
## Security and conduct
|
|
63
|
+
|
|
64
|
+
Security reports follow [SECURITY.md](./SECURITY.md). Community behavior follows
|
|
65
|
+
[CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md). A maintainer involved in a conduct
|
|
66
|
+
or security concern should recuse themselves when another trusted reviewer is
|
|
67
|
+
available.
|
|
68
|
+
|
|
69
|
+
## Governance changes
|
|
70
|
+
|
|
71
|
+
Governance changes use the normal public pull-request process and should explain
|
|
72
|
+
the problem they solve.
|
package/README.md
CHANGED
|
@@ -6,11 +6,10 @@
|
|
|
6
6
|
[](https://scorecard.dev/viewer/?uri=github.com/slegarraga/llm-messages)
|
|
7
7
|
[](./LICENSE)
|
|
8
8
|
[](./package.json)
|
|
9
|
+
[](https://packagephobia.com/result?p=llm-messages)
|
|
10
|
+
[](https://bundlephobia.com/package/llm-messages)
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
message formats, and normalize provider responses into the same
|
|
12
|
-
OpenAI-compatible assistant shape. Tool calls, system prompts, roles and
|
|
13
|
-
response metadata handled correctly. Zero dependencies.
|
|
12
|
+
One library to write a conversation once and send it to OpenAI, Anthropic, or Gemini: handles system prompts, tool calls, role names, consecutive-turn merging, and response normalization. Zero dependencies.
|
|
14
13
|
|
|
15
14
|
Switching an agent from one provider to another (or running fallback across providers) means rewriting the whole conversation, and the differences are subtle enough to break at runtime:
|
|
16
15
|
|
|
@@ -24,6 +23,17 @@ Switching an agent from one provider to another (or running fallback across prov
|
|
|
24
23
|
|
|
25
24
|
`llm-messages` handles all of it. Write the conversation once, send it to any provider.
|
|
26
25
|
|
|
26
|
+
## Project
|
|
27
|
+
|
|
28
|
+
- [Roadmap](./ROADMAP.md): conformance and portability priorities
|
|
29
|
+
- [Contributing](./CONTRIBUTING.md): development and fixture workflow
|
|
30
|
+
- [Governance](./GOVERNANCE.md): decisions and the path to reviewer or maintainer
|
|
31
|
+
- [Support](./SUPPORT.md): questions and reproducible bug reports
|
|
32
|
+
- [Security](./SECURITY.md): private vulnerability reporting
|
|
33
|
+
- [Conformance fixtures](./docs/conformance-fixtures.md): public compatibility contract
|
|
34
|
+
- [Changelog](./CHANGELOG.md): release history and migration notes
|
|
35
|
+
- [Code of Conduct](./CODE_OF_CONDUCT.md): community standards
|
|
36
|
+
|
|
27
37
|
## Install
|
|
28
38
|
|
|
29
39
|
```sh
|
|
@@ -57,6 +67,116 @@ const gemini = toGemini(messages);
|
|
|
57
67
|
// contents: [{ role: 'user', parts: [{ text: "What's the weather in Paris?" }] }] }
|
|
58
68
|
```
|
|
59
69
|
|
|
70
|
+
## Recipes
|
|
71
|
+
|
|
72
|
+
### Convert an OpenAI conversation to Anthropic and call the SDK
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
76
|
+
import { toAnthropic, responseFromAnthropic, type OpenAIMessage } from 'llm-messages';
|
|
77
|
+
|
|
78
|
+
const client = new Anthropic();
|
|
79
|
+
|
|
80
|
+
const conversation: OpenAIMessage[] = [
|
|
81
|
+
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
82
|
+
{ role: 'user', content: 'What is 2 + 2?' },
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
const { system, messages } = toAnthropic(conversation);
|
|
86
|
+
|
|
87
|
+
const raw = await client.messages.create({
|
|
88
|
+
model: 'claude-opus-4-8',
|
|
89
|
+
max_tokens: 256,
|
|
90
|
+
system,
|
|
91
|
+
messages,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Normalize the response back to the OpenAI-compatible shape:
|
|
95
|
+
const { message, finishReason, usage } = responseFromAnthropic(raw);
|
|
96
|
+
const text = raw.content.find((b) => b.type === 'text')?.text ?? '';
|
|
97
|
+
// message.role === 'assistant', finishReason === 'stop', usage.outputTokens > 0
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Provider-fallback loop: one conversation, two providers
|
|
101
|
+
|
|
102
|
+
When a provider is rate-limited or unavailable, retry against the next one without
|
|
103
|
+
rewriting the conversation or the response-parsing logic:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import OpenAI from 'openai';
|
|
107
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
108
|
+
import { toAnthropic, responseFromAnthropic, responseFromOpenAI, type OpenAIMessage } from 'llm-messages';
|
|
109
|
+
|
|
110
|
+
const conversation: OpenAIMessage[] = [
|
|
111
|
+
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
112
|
+
{ role: 'user', content: 'Summarize the water cycle in one sentence.' },
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
async function callWithFallback() {
|
|
116
|
+
// Try OpenAI first:
|
|
117
|
+
try {
|
|
118
|
+
const oai = new OpenAI();
|
|
119
|
+
const res = await oai.chat.completions.create({
|
|
120
|
+
model: 'gpt-4o-mini',
|
|
121
|
+
messages: conversation,
|
|
122
|
+
});
|
|
123
|
+
const raw = res.choices[0].message.content ?? '';
|
|
124
|
+
return responseFromOpenAI(res);
|
|
125
|
+
} catch {
|
|
126
|
+
// Fall back to Anthropic with the same conversation:
|
|
127
|
+
const ant = new Anthropic();
|
|
128
|
+
const { system, messages } = toAnthropic(conversation);
|
|
129
|
+
const res = await ant.messages.create({
|
|
130
|
+
model: 'claude-haiku-4-5-20251001',
|
|
131
|
+
max_tokens: 256,
|
|
132
|
+
system,
|
|
133
|
+
messages,
|
|
134
|
+
});
|
|
135
|
+
return responseFromAnthropic(res);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const { message, finishReason } = await callWithFallback();
|
|
140
|
+
// message.role === 'assistant' regardless of which provider answered
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Vercel AI SDK: keep your conversation portable
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { generateText } from 'ai';
|
|
147
|
+
import { openai } from '@ai-sdk/openai';
|
|
148
|
+
import { toAnthropic, type OpenAIMessage } from 'llm-messages';
|
|
149
|
+
|
|
150
|
+
const conversation: OpenAIMessage[] = [
|
|
151
|
+
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
152
|
+
{ role: 'user', content: 'Hello!' },
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
// Use directly with Vercel AI SDK (already OpenAI-compatible):
|
|
156
|
+
const { text } = await generateText({ model: openai('gpt-4o-mini'), messages: conversation });
|
|
157
|
+
|
|
158
|
+
// Or convert the same conversation to send via Anthropic SDK:
|
|
159
|
+
const { system, messages } = toAnthropic(conversation);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Why not X
|
|
163
|
+
|
|
164
|
+
**`ai` (Vercel AI SDK)** covers model routing and streaming well, but its
|
|
165
|
+
`CoreMessage` type differs from OpenAI's Chat Completions shape, and it does not
|
|
166
|
+
export converters to/from raw Anthropic or Gemini wire formats. `llm-messages` is
|
|
167
|
+
a complement: convert once so the conversation stays in one shape, then hand it to
|
|
168
|
+
whichever SDK or HTTP client you use.
|
|
169
|
+
|
|
170
|
+
**Writing the conversion yourself** is straightforward for text, but subtle for
|
|
171
|
+
tool calls: argument serialization differs per provider, consecutive same-role
|
|
172
|
+
turns are rejected by Anthropic and Gemini, Gemini matches results by name when
|
|
173
|
+
ids are absent, and Anthropic `tool_use_id` pairing has its own rules. The edge
|
|
174
|
+
cases accumulate. `llm-messages` has conformance fixtures that cover them.
|
|
175
|
+
|
|
176
|
+
**LangChain / LlamaIndex** solve orchestration. If you only need the message
|
|
177
|
+
conversion layer without the orchestration overhead, `llm-messages` is ~6 KB
|
|
178
|
+
min+gzip with zero runtime dependencies.
|
|
179
|
+
|
|
60
180
|
## API
|
|
61
181
|
|
|
62
182
|
### The canonical hub
|
|
@@ -168,6 +288,19 @@ for Gemini (which reports `STOP`) and Responses API bodies with `function_call`
|
|
|
168
288
|
items. OpenAI Chat Completions, OpenAI Responses, Anthropic and Gemini tool
|
|
169
289
|
calls without a non-empty string id get a deterministic one.
|
|
170
290
|
|
|
291
|
+
### Streaming Responses API output
|
|
292
|
+
|
|
293
|
+
`llm-messages` normalizes completed response bodies and conversations. For
|
|
294
|
+
incremental SSE events, use
|
|
295
|
+
[`llm-sse`](https://github.com/slegarraga/llm-sse)'s
|
|
296
|
+
`parseOpenAIResponsesStream`, then `collectStream` and `toAssistantMessage`
|
|
297
|
+
before converting the completed history here. Keeping the streaming and message
|
|
298
|
+
boundaries separate lets both packages stay small, deterministic, and
|
|
299
|
+
zero-dependency.
|
|
300
|
+
|
|
301
|
+
The cross-package conformance example is tracked in
|
|
302
|
+
[issue #29](https://github.com/slegarraga/llm-messages/issues/29).
|
|
303
|
+
|
|
171
304
|
### Format cheatsheet
|
|
172
305
|
|
|
173
306
|
| | OpenAI | Anthropic | Gemini |
|
|
@@ -246,21 +379,21 @@ local validation and production checks.
|
|
|
246
379
|
Security posture is tracked in [docs/security-posture.md](./docs/security-posture.md),
|
|
247
380
|
including CodeQL, OpenSSF Scorecard, Dependabot and branch rules.
|
|
248
381
|
|
|
249
|
-
|
|
382
|
+
Questions, reproducible bugs, and maintainer responsibilities are documented in
|
|
383
|
+
[SUPPORT.md](./SUPPORT.md) and [GOVERNANCE.md](./GOVERNANCE.md).
|
|
384
|
+
|
|
385
|
+
## Related
|
|
250
386
|
|
|
251
387
|
`llm-messages` is the conversation boundary in a small provider-portability
|
|
252
|
-
suite for OpenAI-compatible agent infrastructure:
|
|
253
|
-
|
|
254
|
-
- [`
|
|
255
|
-
|
|
256
|
-
- [`llm-sse`](https://
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
before it enters a tool or message pipeline.
|
|
262
|
-
- [`llm-portability-demo`](https://github.com/slegarraga/llm-portability-demo)
|
|
263
|
-
shows the whole flow offline, with no API key required.
|
|
388
|
+
suite for OpenAI-compatible agent infrastructure. The other packages in the suite:
|
|
389
|
+
|
|
390
|
+
- [`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
|
|
391
|
+
- [`tool-schema`](https://www.npmjs.com/package/tool-schema): convert a JSON Schema into a provider tool / function-calling schema for OpenAI, Anthropic, Gemini and MCP
|
|
392
|
+
- [`llm-sse`](https://www.npmjs.com/package/llm-sse): parse streaming SSE from LLM providers into typed, provider-agnostic events
|
|
393
|
+
- [`llm-errors`](https://www.npmjs.com/package/llm-errors): normalize provider errors (rate limits, retries, status) into one shape
|
|
394
|
+
|
|
395
|
+
The [`llm-portability-demo`](https://github.com/slegarraga/llm-portability-demo)
|
|
396
|
+
shows the whole flow offline, with no API key required.
|
|
264
397
|
|
|
265
398
|
Read the
|
|
266
399
|
[provider portability map](https://github.com/slegarraga/llm-portability-demo/blob/main/docs/provider-portability.md)
|
package/ROADMAP.md
CHANGED
|
@@ -7,13 +7,15 @@ fallback behavior matter.
|
|
|
7
7
|
|
|
8
8
|
## Current priorities
|
|
9
9
|
|
|
10
|
-
1. **OpenAI Responses API
|
|
10
|
+
1. **OpenAI Responses API boundary**
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
`function_call
|
|
14
|
-
hub shape.
|
|
12
|
+
Completed response normalization maps Responses API `output_text`,
|
|
13
|
+
`function_call`, refusal, and supported multimodal items into the current
|
|
14
|
+
OpenAI Chat Completions-compatible hub shape. Incremental SSE normalization
|
|
15
|
+
belongs in `llm-sse`. Next: prove the cross-package handoff from a streamed
|
|
16
|
+
function call into portable Anthropic and Gemini histories.
|
|
15
17
|
|
|
16
|
-
Public issue: https://github.com/slegarraga/llm-messages/issues/
|
|
18
|
+
Public issue: https://github.com/slegarraga/llm-messages/issues/29
|
|
17
19
|
|
|
18
20
|
2. **Provider-backed fixture refreshes**
|
|
19
21
|
|
|
@@ -33,6 +35,11 @@ fallback behavior matter.
|
|
|
33
35
|
Document the recommended flow for converting one conversation across
|
|
34
36
|
providers after rate limits or retryable provider failures.
|
|
35
37
|
|
|
38
|
+
5. **Reviewer and maintainer growth**
|
|
39
|
+
|
|
40
|
+
Make fixture ownership, review expectations, and the path to repository
|
|
41
|
+
responsibility explicit in [GOVERNANCE.md](./GOVERNANCE.md).
|
|
42
|
+
|
|
36
43
|
## API credit use
|
|
37
44
|
|
|
38
45
|
If API credits are available, they will be used for conformance checks against
|
package/SUPPORT.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Support
|
|
2
|
+
|
|
3
|
+
`llm-messages` is maintained in public on a best-effort basis.
|
|
4
|
+
|
|
5
|
+
## Questions and design discussions
|
|
6
|
+
|
|
7
|
+
Use
|
|
8
|
+
[GitHub Discussions](https://github.com/slegarraga/llm-messages/discussions)
|
|
9
|
+
for integration questions, proposed conversion behavior, and help choosing the
|
|
10
|
+
right API.
|
|
11
|
+
|
|
12
|
+
## Bugs
|
|
13
|
+
|
|
14
|
+
Open a
|
|
15
|
+
[bug report](https://github.com/slegarraga/llm-messages/issues/new?template=bug_report.yml)
|
|
16
|
+
with:
|
|
17
|
+
|
|
18
|
+
- the source and target provider/API surfaces;
|
|
19
|
+
- a minimal, sanitized message or response body;
|
|
20
|
+
- the canonical output, warning, or finish reason you expected;
|
|
21
|
+
- the package and Node.js versions;
|
|
22
|
+
- a reproduction or failing conformance fixture when possible.
|
|
23
|
+
|
|
24
|
+
Do not include API keys, private prompts, personal data, or proprietary model
|
|
25
|
+
output.
|
|
26
|
+
|
|
27
|
+
## Security
|
|
28
|
+
|
|
29
|
+
Do not open a public issue for a vulnerability. Follow
|
|
30
|
+
[SECURITY.md](./SECURITY.md) to use GitHub private vulnerability reporting or
|
|
31
|
+
the listed security email.
|
|
32
|
+
|
|
33
|
+
## Scope
|
|
34
|
+
|
|
35
|
+
The project can help with message and completed-response normalization.
|
|
36
|
+
Incremental SSE event parsing belongs in
|
|
37
|
+
[`llm-sse`](https://github.com/slegarraga/llm-sse). Provider account access,
|
|
38
|
+
billing, rate limits, and general SDK support belong with the provider.
|
|
39
|
+
|
|
40
|
+
No response-time guarantee is offered, but well-scoped reproductions and pull
|
|
41
|
+
requests are prioritized.
|