llm-messages 0.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.
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Type definitions for the three supported provider message formats plus the
3
+ * shared conversion plumbing.
4
+ *
5
+ * The OpenAI Chat Completions format is the canonical hub: every conversion goes
6
+ * `source -> OpenAI -> target`. The provider request shapes (Anthropic, Gemini)
7
+ * keep the system prompt outside the message list, so they are modelled as
8
+ * "conversation" objects rather than plain arrays.
9
+ */
10
+ /** A supported provider. */
11
+ type Provider = 'openai' | 'anthropic' | 'gemini';
12
+ /** A stable, machine readable code describing a non fatal conversion event. */
13
+ type WarningCode = 'generated-id' | 'unmapped-tool-result' | 'merged-role' | 'dropped-content' | 'invalid-json-arguments' | 'system-midstream';
14
+ /** A non fatal event raised during conversion. */
15
+ interface Warning {
16
+ code: WarningCode;
17
+ message: string;
18
+ }
19
+ /** Options accepted by every conversion function. */
20
+ interface ConvertOptions {
21
+ /** Called for each non fatal conversion event (generated id, merged turn, ...). */
22
+ onWarning?: (warning: Warning) => void;
23
+ }
24
+ interface OpenAITextPart {
25
+ type: 'text';
26
+ text: string;
27
+ }
28
+ /** A content part. Non text parts (images, audio) are preserved verbatim. */
29
+ type OpenAIContentPart = OpenAITextPart | {
30
+ type: string;
31
+ [key: string]: unknown;
32
+ };
33
+ interface OpenAIToolCall {
34
+ id: string;
35
+ type: 'function';
36
+ function: {
37
+ name: string;
38
+ /** Arguments as a JSON encoded string, per the OpenAI wire format. */
39
+ arguments: string;
40
+ };
41
+ }
42
+ interface OpenAISystemMessage {
43
+ /** `developer` is the o-series alias for `system`; both map to a system prompt. */
44
+ role: 'system' | 'developer';
45
+ content: string | OpenAITextPart[];
46
+ name?: string;
47
+ }
48
+ interface OpenAIUserMessage {
49
+ role: 'user';
50
+ content: string | OpenAIContentPart[];
51
+ name?: string;
52
+ }
53
+ interface OpenAIAssistantMessage {
54
+ role: 'assistant';
55
+ /** Text reply. `null` (or omitted) when the turn only contains tool calls. */
56
+ content?: string | OpenAIContentPart[] | null;
57
+ name?: string;
58
+ tool_calls?: OpenAIToolCall[];
59
+ }
60
+ interface OpenAIToolMessage {
61
+ role: 'tool';
62
+ tool_call_id: string;
63
+ content: string | OpenAITextPart[];
64
+ }
65
+ type OpenAIMessage = OpenAISystemMessage | OpenAIUserMessage | OpenAIAssistantMessage | OpenAIToolMessage;
66
+ interface AnthropicTextBlock {
67
+ type: 'text';
68
+ text: string;
69
+ }
70
+ interface AnthropicToolUseBlock {
71
+ type: 'tool_use';
72
+ id: string;
73
+ name: string;
74
+ /** Parsed arguments object (not a JSON string). */
75
+ input: Record<string, unknown>;
76
+ }
77
+ interface AnthropicToolResultBlock {
78
+ type: 'tool_result';
79
+ tool_use_id: string;
80
+ content: string | AnthropicTextBlock[];
81
+ is_error?: boolean;
82
+ }
83
+ type AnthropicContentBlock = AnthropicTextBlock | AnthropicToolUseBlock | AnthropicToolResultBlock | {
84
+ type: string;
85
+ [key: string]: unknown;
86
+ };
87
+ interface AnthropicMessage {
88
+ role: 'user' | 'assistant';
89
+ content: string | AnthropicContentBlock[];
90
+ }
91
+ /** An Anthropic request body fragment: the system prompt sits outside `messages`. */
92
+ interface AnthropicConversation {
93
+ system?: string;
94
+ messages: AnthropicMessage[];
95
+ }
96
+ interface GeminiTextPart {
97
+ text: string;
98
+ }
99
+ interface GeminiFunctionCallPart {
100
+ functionCall: {
101
+ id?: string;
102
+ name: string;
103
+ /** Parsed arguments object (not a JSON string). */
104
+ args: Record<string, unknown>;
105
+ };
106
+ }
107
+ interface GeminiFunctionResponsePart {
108
+ functionResponse: {
109
+ id?: string;
110
+ name: string;
111
+ /** Result as a JSON object. Gemini has no string shorthand. */
112
+ response: Record<string, unknown>;
113
+ };
114
+ }
115
+ type GeminiPart = GeminiTextPart | GeminiFunctionCallPart | GeminiFunctionResponsePart | Record<string, unknown>;
116
+ interface GeminiContent {
117
+ /** `model` is Gemini's name for the assistant role. */
118
+ role?: 'user' | 'model';
119
+ parts: GeminiPart[];
120
+ }
121
+ /** A Gemini request body fragment: `systemInstruction` sits outside `contents`. */
122
+ interface GeminiConversation {
123
+ systemInstruction?: GeminiContent;
124
+ contents: GeminiContent[];
125
+ }
126
+
127
+ /**
128
+ * Converts a canonical OpenAI conversation into an Anthropic request fragment
129
+ * (`{ system, messages }`). System messages move to the top-level `system`
130
+ * field, tool-call arguments are JSON parsed into `input` objects, tool results
131
+ * are folded into `tool_result` blocks inside a user turn, and consecutive
132
+ * same-role turns are merged to satisfy Anthropic's strict alternation.
133
+ */
134
+ declare function toAnthropic(messages: OpenAIMessage[], options?: ConvertOptions): AnthropicConversation;
135
+ /**
136
+ * Converts an Anthropic request fragment back into a canonical OpenAI message
137
+ * array. The top-level `system` becomes a leading system message, `tool_use`
138
+ * blocks become `tool_calls` (with `input` re-serialized to a JSON string), and
139
+ * `tool_result` blocks become standalone `role: 'tool'` messages.
140
+ */
141
+ declare function fromAnthropic(conversation: AnthropicConversation, options?: ConvertOptions): OpenAIMessage[];
142
+
143
+ /**
144
+ * Converts a canonical OpenAI conversation into a Gemini request fragment
145
+ * (`{ systemInstruction, contents }`). The assistant role becomes `model`,
146
+ * tool-call arguments are JSON parsed into `args` objects, tool results become
147
+ * `functionResponse` parts whose `name` is recovered from the matching call, and
148
+ * consecutive same-role turns are merged for Gemini's strict alternation.
149
+ *
150
+ * The OpenAI tool-call `id` is carried through as `functionCall.id` so that a
151
+ * round trip (OpenAI -> Gemini -> OpenAI) preserves ids exactly.
152
+ */
153
+ declare function toGemini(messages: OpenAIMessage[], options?: ConvertOptions): GeminiConversation;
154
+ /**
155
+ * Converts a Gemini request fragment back into a canonical OpenAI message array.
156
+ * Because Gemini matches tool calls and responses by function name (the `id`
157
+ * field is optional), this maintains a queue of pending calls and resolves each
158
+ * `functionResponse` by id when present, otherwise by name in call order,
159
+ * generating a deterministic id as a last resort.
160
+ */
161
+ declare function fromGemini(conversation: GeminiConversation, options?: ConvertOptions): OpenAIMessage[];
162
+
163
+ /** Maps a provider to the conversation shape it accepts and returns. */
164
+ type ConversationOf<P extends Provider> = P extends 'openai' ? OpenAIMessage[] : P extends 'anthropic' ? AnthropicConversation : P extends 'gemini' ? GeminiConversation : never;
165
+ /**
166
+ * Converts a conversation from one provider format to another. Every conversion
167
+ * routes through the canonical OpenAI representation, so any source/target pair
168
+ * is supported, including same-provider normalization.
169
+ *
170
+ * @example
171
+ * const gemini = convert(openaiMessages, { from: 'openai', to: 'gemini' });
172
+ * const openai = convert(anthropicBody, { from: 'anthropic', to: 'openai' });
173
+ */
174
+ declare function convert<From extends Provider, To extends Provider>(conversation: ConversationOf<From>, route: {
175
+ from: From;
176
+ to: To;
177
+ }, options?: ConvertOptions): ConversationOf<To>;
178
+
179
+ export { type AnthropicContentBlock, type AnthropicConversation, type AnthropicMessage, type AnthropicTextBlock, type AnthropicToolResultBlock, type AnthropicToolUseBlock, type ConversationOf, type ConvertOptions, type GeminiContent, type GeminiConversation, type GeminiFunctionCallPart, type GeminiFunctionResponsePart, type GeminiPart, type GeminiTextPart, type OpenAIAssistantMessage, type OpenAIContentPart, type OpenAIMessage, type OpenAISystemMessage, type OpenAITextPart, type OpenAIToolCall, type OpenAIToolMessage, type OpenAIUserMessage, type Provider, type Warning, type WarningCode, convert, fromAnthropic, fromGemini, toAnthropic, toGemini };
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Type definitions for the three supported provider message formats plus the
3
+ * shared conversion plumbing.
4
+ *
5
+ * The OpenAI Chat Completions format is the canonical hub: every conversion goes
6
+ * `source -> OpenAI -> target`. The provider request shapes (Anthropic, Gemini)
7
+ * keep the system prompt outside the message list, so they are modelled as
8
+ * "conversation" objects rather than plain arrays.
9
+ */
10
+ /** A supported provider. */
11
+ type Provider = 'openai' | 'anthropic' | 'gemini';
12
+ /** A stable, machine readable code describing a non fatal conversion event. */
13
+ type WarningCode = 'generated-id' | 'unmapped-tool-result' | 'merged-role' | 'dropped-content' | 'invalid-json-arguments' | 'system-midstream';
14
+ /** A non fatal event raised during conversion. */
15
+ interface Warning {
16
+ code: WarningCode;
17
+ message: string;
18
+ }
19
+ /** Options accepted by every conversion function. */
20
+ interface ConvertOptions {
21
+ /** Called for each non fatal conversion event (generated id, merged turn, ...). */
22
+ onWarning?: (warning: Warning) => void;
23
+ }
24
+ interface OpenAITextPart {
25
+ type: 'text';
26
+ text: string;
27
+ }
28
+ /** A content part. Non text parts (images, audio) are preserved verbatim. */
29
+ type OpenAIContentPart = OpenAITextPart | {
30
+ type: string;
31
+ [key: string]: unknown;
32
+ };
33
+ interface OpenAIToolCall {
34
+ id: string;
35
+ type: 'function';
36
+ function: {
37
+ name: string;
38
+ /** Arguments as a JSON encoded string, per the OpenAI wire format. */
39
+ arguments: string;
40
+ };
41
+ }
42
+ interface OpenAISystemMessage {
43
+ /** `developer` is the o-series alias for `system`; both map to a system prompt. */
44
+ role: 'system' | 'developer';
45
+ content: string | OpenAITextPart[];
46
+ name?: string;
47
+ }
48
+ interface OpenAIUserMessage {
49
+ role: 'user';
50
+ content: string | OpenAIContentPart[];
51
+ name?: string;
52
+ }
53
+ interface OpenAIAssistantMessage {
54
+ role: 'assistant';
55
+ /** Text reply. `null` (or omitted) when the turn only contains tool calls. */
56
+ content?: string | OpenAIContentPart[] | null;
57
+ name?: string;
58
+ tool_calls?: OpenAIToolCall[];
59
+ }
60
+ interface OpenAIToolMessage {
61
+ role: 'tool';
62
+ tool_call_id: string;
63
+ content: string | OpenAITextPart[];
64
+ }
65
+ type OpenAIMessage = OpenAISystemMessage | OpenAIUserMessage | OpenAIAssistantMessage | OpenAIToolMessage;
66
+ interface AnthropicTextBlock {
67
+ type: 'text';
68
+ text: string;
69
+ }
70
+ interface AnthropicToolUseBlock {
71
+ type: 'tool_use';
72
+ id: string;
73
+ name: string;
74
+ /** Parsed arguments object (not a JSON string). */
75
+ input: Record<string, unknown>;
76
+ }
77
+ interface AnthropicToolResultBlock {
78
+ type: 'tool_result';
79
+ tool_use_id: string;
80
+ content: string | AnthropicTextBlock[];
81
+ is_error?: boolean;
82
+ }
83
+ type AnthropicContentBlock = AnthropicTextBlock | AnthropicToolUseBlock | AnthropicToolResultBlock | {
84
+ type: string;
85
+ [key: string]: unknown;
86
+ };
87
+ interface AnthropicMessage {
88
+ role: 'user' | 'assistant';
89
+ content: string | AnthropicContentBlock[];
90
+ }
91
+ /** An Anthropic request body fragment: the system prompt sits outside `messages`. */
92
+ interface AnthropicConversation {
93
+ system?: string;
94
+ messages: AnthropicMessage[];
95
+ }
96
+ interface GeminiTextPart {
97
+ text: string;
98
+ }
99
+ interface GeminiFunctionCallPart {
100
+ functionCall: {
101
+ id?: string;
102
+ name: string;
103
+ /** Parsed arguments object (not a JSON string). */
104
+ args: Record<string, unknown>;
105
+ };
106
+ }
107
+ interface GeminiFunctionResponsePart {
108
+ functionResponse: {
109
+ id?: string;
110
+ name: string;
111
+ /** Result as a JSON object. Gemini has no string shorthand. */
112
+ response: Record<string, unknown>;
113
+ };
114
+ }
115
+ type GeminiPart = GeminiTextPart | GeminiFunctionCallPart | GeminiFunctionResponsePart | Record<string, unknown>;
116
+ interface GeminiContent {
117
+ /** `model` is Gemini's name for the assistant role. */
118
+ role?: 'user' | 'model';
119
+ parts: GeminiPart[];
120
+ }
121
+ /** A Gemini request body fragment: `systemInstruction` sits outside `contents`. */
122
+ interface GeminiConversation {
123
+ systemInstruction?: GeminiContent;
124
+ contents: GeminiContent[];
125
+ }
126
+
127
+ /**
128
+ * Converts a canonical OpenAI conversation into an Anthropic request fragment
129
+ * (`{ system, messages }`). System messages move to the top-level `system`
130
+ * field, tool-call arguments are JSON parsed into `input` objects, tool results
131
+ * are folded into `tool_result` blocks inside a user turn, and consecutive
132
+ * same-role turns are merged to satisfy Anthropic's strict alternation.
133
+ */
134
+ declare function toAnthropic(messages: OpenAIMessage[], options?: ConvertOptions): AnthropicConversation;
135
+ /**
136
+ * Converts an Anthropic request fragment back into a canonical OpenAI message
137
+ * array. The top-level `system` becomes a leading system message, `tool_use`
138
+ * blocks become `tool_calls` (with `input` re-serialized to a JSON string), and
139
+ * `tool_result` blocks become standalone `role: 'tool'` messages.
140
+ */
141
+ declare function fromAnthropic(conversation: AnthropicConversation, options?: ConvertOptions): OpenAIMessage[];
142
+
143
+ /**
144
+ * Converts a canonical OpenAI conversation into a Gemini request fragment
145
+ * (`{ systemInstruction, contents }`). The assistant role becomes `model`,
146
+ * tool-call arguments are JSON parsed into `args` objects, tool results become
147
+ * `functionResponse` parts whose `name` is recovered from the matching call, and
148
+ * consecutive same-role turns are merged for Gemini's strict alternation.
149
+ *
150
+ * The OpenAI tool-call `id` is carried through as `functionCall.id` so that a
151
+ * round trip (OpenAI -> Gemini -> OpenAI) preserves ids exactly.
152
+ */
153
+ declare function toGemini(messages: OpenAIMessage[], options?: ConvertOptions): GeminiConversation;
154
+ /**
155
+ * Converts a Gemini request fragment back into a canonical OpenAI message array.
156
+ * Because Gemini matches tool calls and responses by function name (the `id`
157
+ * field is optional), this maintains a queue of pending calls and resolves each
158
+ * `functionResponse` by id when present, otherwise by name in call order,
159
+ * generating a deterministic id as a last resort.
160
+ */
161
+ declare function fromGemini(conversation: GeminiConversation, options?: ConvertOptions): OpenAIMessage[];
162
+
163
+ /** Maps a provider to the conversation shape it accepts and returns. */
164
+ type ConversationOf<P extends Provider> = P extends 'openai' ? OpenAIMessage[] : P extends 'anthropic' ? AnthropicConversation : P extends 'gemini' ? GeminiConversation : never;
165
+ /**
166
+ * Converts a conversation from one provider format to another. Every conversion
167
+ * routes through the canonical OpenAI representation, so any source/target pair
168
+ * is supported, including same-provider normalization.
169
+ *
170
+ * @example
171
+ * const gemini = convert(openaiMessages, { from: 'openai', to: 'gemini' });
172
+ * const openai = convert(anthropicBody, { from: 'anthropic', to: 'openai' });
173
+ */
174
+ declare function convert<From extends Provider, To extends Provider>(conversation: ConversationOf<From>, route: {
175
+ from: From;
176
+ to: To;
177
+ }, options?: ConvertOptions): ConversationOf<To>;
178
+
179
+ export { type AnthropicContentBlock, type AnthropicConversation, type AnthropicMessage, type AnthropicTextBlock, type AnthropicToolResultBlock, type AnthropicToolUseBlock, type ConversationOf, type ConvertOptions, type GeminiContent, type GeminiConversation, type GeminiFunctionCallPart, type GeminiFunctionResponsePart, type GeminiPart, type GeminiTextPart, type OpenAIAssistantMessage, type OpenAIContentPart, type OpenAIMessage, type OpenAISystemMessage, type OpenAITextPart, type OpenAIToolCall, type OpenAIToolMessage, type OpenAIUserMessage, type Provider, type Warning, type WarningCode, convert, fromAnthropic, fromGemini, toAnthropic, toGemini };