llm-messages 0.4.7 → 0.4.9
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 +15 -0
- package/README.md +4 -0
- package/docs/adoption-guide.md +93 -0
- package/examples/usage.mjs +26 -0
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ All notable changes to this project are documented here. The format is based on
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres
|
|
5
5
|
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.4.9] - 2026-06-04
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Added a public adoption guide for teams evaluating OpenAI-compatible provider
|
|
12
|
+
fallback, local validation, and production conversion checks.
|
|
13
|
+
- Included the examples directory in the published npm package.
|
|
14
|
+
|
|
15
|
+
## [0.4.8] - 2026-06-04
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Updated CI to run on Node 20 and 22, matching the secure Vitest development
|
|
20
|
+
tooling while keeping the package runtime build target at Node 18.
|
|
21
|
+
|
|
7
22
|
## [0.4.7] - 2026-06-04
|
|
8
23
|
|
|
9
24
|
### Changed
|
package/README.md
CHANGED
|
@@ -179,6 +179,10 @@ cases. The [conformance fixtures plan](./docs/conformance-fixtures.md) describes
|
|
|
179
179
|
how API credits should be used to refresh deterministic public fixtures without
|
|
180
180
|
putting secrets in CI.
|
|
181
181
|
|
|
182
|
+
For teams evaluating the package, the
|
|
183
|
+
[adoption guide](./docs/adoption-guide.md) covers the OpenAI-compatible boundary,
|
|
184
|
+
local validation and production checks.
|
|
185
|
+
|
|
182
186
|
## Provider portability suite
|
|
183
187
|
|
|
184
188
|
`llm-messages` is the conversation boundary in a small provider-portability
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# llm-messages adoption guide
|
|
2
|
+
|
|
3
|
+
`llm-messages` is meant for teams that use OpenAI Chat Completions as their
|
|
4
|
+
internal conversation shape but need to run the same agent loop against
|
|
5
|
+
Anthropic, Gemini, or a fallback provider.
|
|
6
|
+
|
|
7
|
+
Use it when you need:
|
|
8
|
+
|
|
9
|
+
- one canonical OpenAI-compatible message history in your app
|
|
10
|
+
- provider fallback without rewriting stored conversations
|
|
11
|
+
- tool-call and tool-result conversion across providers
|
|
12
|
+
- multimodal inputs that keep image, audio, and document parts explicit
|
|
13
|
+
- deterministic warnings instead of hidden conversion loss
|
|
14
|
+
|
|
15
|
+
## Five minute local check
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npm install llm-messages
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { convert, toAnthropic, toGemini } from 'llm-messages';
|
|
23
|
+
|
|
24
|
+
const openaiMessages = [
|
|
25
|
+
{ role: 'system', content: 'You are a concise support agent.' },
|
|
26
|
+
{ role: 'user', content: 'Summarize this ticket and call the right tool.' },
|
|
27
|
+
{
|
|
28
|
+
role: 'assistant',
|
|
29
|
+
content: null,
|
|
30
|
+
tool_calls: [
|
|
31
|
+
{
|
|
32
|
+
id: 'call_route',
|
|
33
|
+
type: 'function',
|
|
34
|
+
function: {
|
|
35
|
+
name: 'route_ticket',
|
|
36
|
+
arguments: '{"priority":"high","team":"billing"}',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
{ role: 'tool', tool_call_id: 'call_route', content: '{"ok":true}' },
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const anthropicBody = toAnthropic(openaiMessages);
|
|
45
|
+
const geminiBody = toGemini(openaiMessages);
|
|
46
|
+
const geminiFromAnthropic = convert(anthropicBody, {
|
|
47
|
+
from: 'anthropic',
|
|
48
|
+
to: 'gemini',
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
No API key is required for this check. The conversion runs locally and returns
|
|
53
|
+
plain request bodies you can inspect in tests.
|
|
54
|
+
|
|
55
|
+
## Integration pattern
|
|
56
|
+
|
|
57
|
+
1. Keep OpenAI Chat Completions messages as the canonical persisted shape.
|
|
58
|
+
2. Convert only at the provider boundary.
|
|
59
|
+
3. Log conversion warnings from `onWarning`.
|
|
60
|
+
4. Normalize provider responses before saving assistant messages.
|
|
61
|
+
5. Cover important agent loops with fixtures before enabling provider fallback.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { normalizeResponse, toAnthropic } from 'llm-messages';
|
|
65
|
+
|
|
66
|
+
const requestBody = toAnthropic(messages, {
|
|
67
|
+
onWarning: (warning) => logger.warn({ warning }, 'message conversion warning'),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const providerResponse = await anthropic.messages.create(requestBody);
|
|
71
|
+
const { message, finishReason, usage } = normalizeResponse(providerResponse, {
|
|
72
|
+
from: 'anthropic',
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## What to validate before production
|
|
77
|
+
|
|
78
|
+
- tool-call IDs stay stable across your retry and replay path
|
|
79
|
+
- provider-specific system prompt rules match your app assumptions
|
|
80
|
+
- unsupported modalities are surfaced through warnings
|
|
81
|
+
- saved fixtures cover tool calls, tool results, images, and fallback
|
|
82
|
+
- provider SDK versions are pinned or tested in CI
|
|
83
|
+
|
|
84
|
+
## Related public material
|
|
85
|
+
|
|
86
|
+
- [Conformance fixture plan](./conformance-fixtures.md)
|
|
87
|
+
- [Roadmap](../ROADMAP.md)
|
|
88
|
+
- [Offline portability demo](https://github.com/slegarraga/llm-portability-demo)
|
|
89
|
+
- [OpenAI-compatible agent portability note](https://github.com/slegarraga/llm-portability-demo/blob/main/docs/openai-compatible-agent-portability.md)
|
|
90
|
+
|
|
91
|
+
Questions, bug reports, and real-world fixture requests are welcome through
|
|
92
|
+
[GitHub Issues](https://github.com/slegarraga/llm-messages/issues) or
|
|
93
|
+
[sebastian@0a.cl](mailto:sebastian@0a.cl).
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Run from the repo root after `npm run build`:
|
|
2
|
+
// node examples/usage.mjs
|
|
3
|
+
import { toAnthropic, toGemini, convert } from '../dist/index.js';
|
|
4
|
+
|
|
5
|
+
const messages = [
|
|
6
|
+
{ role: 'system', content: 'You are a weather assistant.' },
|
|
7
|
+
{ role: 'user', content: "What's the weather in Paris?" },
|
|
8
|
+
{
|
|
9
|
+
role: 'assistant',
|
|
10
|
+
content: null,
|
|
11
|
+
tool_calls: [
|
|
12
|
+
{ id: 'call_abc', type: 'function', function: { name: 'get_weather', arguments: '{"location":"Paris"}' } },
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
{ role: 'tool', tool_call_id: 'call_abc', content: '15C partly cloudy' },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
console.log('--- OpenAI -> Anthropic ---');
|
|
19
|
+
console.log(JSON.stringify(toAnthropic(messages), null, 2));
|
|
20
|
+
|
|
21
|
+
console.log('\n--- OpenAI -> Gemini ---');
|
|
22
|
+
console.log(JSON.stringify(toGemini(messages), null, 2));
|
|
23
|
+
|
|
24
|
+
console.log('\n--- Anthropic -> Gemini (via convert) ---');
|
|
25
|
+
const anthropic = toAnthropic(messages);
|
|
26
|
+
console.log(JSON.stringify(convert(anthropic, { from: 'anthropic', to: 'gemini' }), null, 2));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llm-messages",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.9",
|
|
4
4
|
"description": "Convert chat conversations and responses between OpenAI, Anthropic and Gemini. Tool calls, images, audio, documents and roles handled. Zero dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openai",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"files": [
|
|
56
56
|
"dist",
|
|
57
57
|
"docs",
|
|
58
|
+
"examples",
|
|
58
59
|
"README.md",
|
|
59
60
|
"ROADMAP.md",
|
|
60
61
|
"LICENSE",
|