genaicode 2.0.0 → 2.3.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 +57 -0
- package/README.md +194 -26
- package/dist/core/client.d.ts +15 -3
- package/dist/core/client.js +87 -3
- package/dist/core/client.js.map +1 -1
- package/dist/core/errors.d.ts +38 -0
- package/dist/core/errors.js +118 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/middleware.d.ts +43 -0
- package/dist/core/middleware.js +175 -0
- package/dist/core/middleware.js.map +1 -0
- package/dist/core/plugins.d.ts +8 -1
- package/dist/core/plugins.js +25 -1
- package/dist/core/plugins.js.map +1 -1
- package/dist/core/result.d.ts +2 -2
- package/dist/core/result.js +5 -1
- package/dist/core/result.js.map +1 -1
- package/dist/core/stream.d.ts +11 -0
- package/dist/core/stream.js +93 -0
- package/dist/core/stream.js.map +1 -0
- package/dist/core/types.d.ts +101 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic-converter.js +32 -6
- package/dist/providers/anthropic-converter.js.map +1 -1
- package/dist/providers/anthropic.js +64 -0
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/fixtures/multimodal-tool-roundtrip.d.ts +4 -0
- package/dist/providers/fixtures/multimodal-tool-roundtrip.js +32 -0
- package/dist/providers/fixtures/multimodal-tool-roundtrip.js.map +1 -0
- package/dist/providers/google-converter.js +53 -2
- package/dist/providers/google-converter.js.map +1 -1
- package/dist/providers/google.js +65 -0
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/openai-converter.d.ts +20 -1
- package/dist/providers/openai-converter.js +98 -0
- package/dist/providers/openai-converter.js.map +1 -1
- package/dist/providers/openai.js +18 -1
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +1 -1
- package/dist/providers.js.map +1 -1
- package/docs/pivot.md +33 -14
- package/docs/provider-packages.md +60 -0
- package/docs/retry.md +62 -0
- package/docs/semver.md +56 -0
- package/package.json +5 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type OpenAI from 'openai';
|
|
2
|
-
import type { GenerationRequest, GenerationResult, PromptItem, ToolChoice, ToolDefinition } from '../core/types.js';
|
|
2
|
+
import type { GenerationRequest, GenerationResult, PromptItem, StreamEvent, ToolChoice, ToolDefinition } from '../core/types.js';
|
|
3
3
|
type OpenAIMessage = OpenAI.Chat.Completions.ChatCompletionMessageParam;
|
|
4
4
|
export declare function toOpenAIMessages(prompt: PromptItem[]): OpenAIMessage[];
|
|
5
5
|
export declare function toOpenAITools(tools: ToolDefinition[] | undefined): OpenAI.Chat.Completions.ChatCompletionTool[] | undefined;
|
|
@@ -12,5 +12,24 @@ export declare function toOpenAIRequest(request: GenerationRequest, defaultModel
|
|
|
12
12
|
max_completion_tokens: number | undefined;
|
|
13
13
|
tools: OpenAI.Chat.Completions.ChatCompletionTool[] | undefined;
|
|
14
14
|
tool_choice: OpenAI.Chat.Completions.ChatCompletionToolChoiceOption | undefined;
|
|
15
|
+
response_format: import("openai/resources/shared.mjs").ResponseFormatText | import("openai/resources/shared.mjs").ResponseFormatJSONSchema | import("openai/resources/shared.mjs").ResponseFormatJSONObject | undefined;
|
|
15
16
|
};
|
|
17
|
+
export declare function toOpenAIStreamRequest(request: GenerationRequest, defaultModel: string): {
|
|
18
|
+
stream: true;
|
|
19
|
+
stream_options: {
|
|
20
|
+
include_usage: true;
|
|
21
|
+
};
|
|
22
|
+
model: string;
|
|
23
|
+
messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[];
|
|
24
|
+
temperature: number | undefined;
|
|
25
|
+
max_completion_tokens: number | undefined;
|
|
26
|
+
tools: OpenAI.Chat.Completions.ChatCompletionTool[] | undefined;
|
|
27
|
+
tool_choice: OpenAI.Chat.Completions.ChatCompletionToolChoiceOption | undefined;
|
|
28
|
+
response_format: import("openai/resources/shared.mjs").ResponseFormatText | import("openai/resources/shared.mjs").ResponseFormatJSONSchema | import("openai/resources/shared.mjs").ResponseFormatJSONObject | undefined;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Accumulate OpenAI chat completion chunks into StreamEvents.
|
|
32
|
+
* Tool-call argument fragments are emitted as `tool-call-delta` and finalized on `done`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function fromOpenAIStream(chunks: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>): AsyncGenerator<StreamEvent>;
|
|
16
35
|
export {};
|
|
@@ -97,6 +97,21 @@ export function fromOpenAICompletion(completion) {
|
|
|
97
97
|
raw: completion,
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
|
+
function toOpenAIResponseFormat(format) {
|
|
101
|
+
if (!format || format.type === 'text')
|
|
102
|
+
return undefined;
|
|
103
|
+
if (format.type === 'json') {
|
|
104
|
+
return { type: 'json_object' };
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
type: 'json_schema',
|
|
108
|
+
json_schema: {
|
|
109
|
+
name: format.name,
|
|
110
|
+
schema: format.schema,
|
|
111
|
+
strict: format.strict,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
100
115
|
export function toOpenAIRequest(request, defaultModel) {
|
|
101
116
|
return {
|
|
102
117
|
model: request.model ?? defaultModel,
|
|
@@ -105,6 +120,89 @@ export function toOpenAIRequest(request, defaultModel) {
|
|
|
105
120
|
max_completion_tokens: request.maxOutputTokens,
|
|
106
121
|
tools: toOpenAITools(request.tools),
|
|
107
122
|
tool_choice: toOpenAIToolChoice(request.toolChoice),
|
|
123
|
+
response_format: toOpenAIResponseFormat(request.responseFormat),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
export function toOpenAIStreamRequest(request, defaultModel) {
|
|
127
|
+
return {
|
|
128
|
+
...toOpenAIRequest(request, defaultModel),
|
|
129
|
+
stream: true,
|
|
130
|
+
stream_options: { include_usage: true },
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Accumulate OpenAI chat completion chunks into StreamEvents.
|
|
135
|
+
* Tool-call argument fragments are emitted as `tool-call-delta` and finalized on `done`.
|
|
136
|
+
*/
|
|
137
|
+
export async function* fromOpenAIStream(chunks) {
|
|
138
|
+
let text = '';
|
|
139
|
+
const toolCalls = new Map();
|
|
140
|
+
let model;
|
|
141
|
+
let finishReason;
|
|
142
|
+
let usage;
|
|
143
|
+
let raw;
|
|
144
|
+
for await (const chunk of chunks) {
|
|
145
|
+
raw = chunk;
|
|
146
|
+
model = chunk.model ?? model;
|
|
147
|
+
if (chunk.usage) {
|
|
148
|
+
usage = {
|
|
149
|
+
inputTokens: chunk.usage.prompt_tokens,
|
|
150
|
+
outputTokens: chunk.usage.completion_tokens,
|
|
151
|
+
totalTokens: chunk.usage.total_tokens,
|
|
152
|
+
cachedInputTokens: chunk.usage.prompt_tokens_details?.cached_tokens,
|
|
153
|
+
};
|
|
154
|
+
yield { type: 'usage', usage };
|
|
155
|
+
}
|
|
156
|
+
const choice = chunk.choices[0];
|
|
157
|
+
if (!choice)
|
|
158
|
+
continue;
|
|
159
|
+
finishReason = choice.finish_reason ?? finishReason;
|
|
160
|
+
const delta = choice.delta;
|
|
161
|
+
if (delta.content) {
|
|
162
|
+
text += delta.content;
|
|
163
|
+
yield { type: 'text-delta', text: delta.content };
|
|
164
|
+
}
|
|
165
|
+
for (const call of delta.tool_calls ?? []) {
|
|
166
|
+
const current = toolCalls.get(call.index) ?? { arguments: '' };
|
|
167
|
+
if (call.id)
|
|
168
|
+
current.id = call.id;
|
|
169
|
+
if (call.function?.name)
|
|
170
|
+
current.name = call.function.name;
|
|
171
|
+
if (call.function?.arguments) {
|
|
172
|
+
current.arguments += call.function.arguments;
|
|
173
|
+
yield {
|
|
174
|
+
type: 'tool-call-delta',
|
|
175
|
+
id: current.id,
|
|
176
|
+
name: current.name,
|
|
177
|
+
argumentsDelta: call.function.arguments,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
toolCalls.set(call.index, current);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const parts = [];
|
|
184
|
+
if (text)
|
|
185
|
+
parts.push({ type: 'text', text });
|
|
186
|
+
for (const call of toolCalls.values()) {
|
|
187
|
+
if (!call.name)
|
|
188
|
+
continue;
|
|
189
|
+
const toolCall = {
|
|
190
|
+
id: call.id,
|
|
191
|
+
name: call.name,
|
|
192
|
+
arguments: parseArguments(call.arguments),
|
|
193
|
+
};
|
|
194
|
+
parts.push({ type: 'toolCall', toolCall });
|
|
195
|
+
yield { type: 'tool-call', toolCall };
|
|
196
|
+
}
|
|
197
|
+
yield {
|
|
198
|
+
type: 'done',
|
|
199
|
+
result: {
|
|
200
|
+
parts,
|
|
201
|
+
model,
|
|
202
|
+
finishReason: finishReason ?? undefined,
|
|
203
|
+
usage,
|
|
204
|
+
raw,
|
|
205
|
+
},
|
|
108
206
|
};
|
|
109
207
|
}
|
|
110
208
|
//# sourceMappingURL=openai-converter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-converter.js","sourceRoot":"","sources":["../../src/providers/openai-converter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"openai-converter.js","sourceRoot":"","sources":["../../src/providers/openai-converter.ts"],"names":[],"mappings":"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"}
|
package/dist/providers/openai.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import OpenAI from 'openai';
|
|
2
|
-
import { fromOpenAICompletion, toOpenAIRequest } from './openai-converter.js';
|
|
2
|
+
import { fromOpenAICompletion, fromOpenAIStream, toOpenAIRequest, toOpenAIStreamRequest } from './openai-converter.js';
|
|
3
3
|
export function openai(options = {}) {
|
|
4
4
|
const client = new OpenAI({
|
|
5
5
|
apiKey: options.apiKey ?? process.env.OPENAI_API_KEY,
|
|
@@ -10,6 +10,13 @@ export function openai(options = {}) {
|
|
|
10
10
|
const defaultModel = options.model ?? process.env.OPENAI_MODEL;
|
|
11
11
|
return {
|
|
12
12
|
name: 'openai',
|
|
13
|
+
capabilities: {
|
|
14
|
+
streaming: true,
|
|
15
|
+
tools: true,
|
|
16
|
+
images: 'input',
|
|
17
|
+
systemPrompt: true,
|
|
18
|
+
jsonResponse: true,
|
|
19
|
+
},
|
|
13
20
|
async generate(request) {
|
|
14
21
|
const model = request.model ?? defaultModel;
|
|
15
22
|
if (!model) {
|
|
@@ -20,6 +27,16 @@ export function openai(options = {}) {
|
|
|
20
27
|
});
|
|
21
28
|
return fromOpenAICompletion(completion);
|
|
22
29
|
},
|
|
30
|
+
async *stream(request) {
|
|
31
|
+
const model = request.model ?? defaultModel;
|
|
32
|
+
if (!model) {
|
|
33
|
+
throw new Error('No OpenAI model configured. Pass `model` to openai() or the request builder.');
|
|
34
|
+
}
|
|
35
|
+
const chunks = await client.chat.completions.create(toOpenAIStreamRequest(request, model), {
|
|
36
|
+
signal: request.signal,
|
|
37
|
+
});
|
|
38
|
+
yield* fromOpenAIStream(chunks);
|
|
39
|
+
},
|
|
23
40
|
};
|
|
24
41
|
}
|
|
25
42
|
export function openaiCompatible(options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAUvH,MAAM,UAAU,MAAM,CAAC,UAAiC,EAAE;IACxD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QACpD,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC,CAAC;IACH,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAE/D,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE;YACZ,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,OAAO;YACf,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,IAAI;SACnB;QACD,KAAK,CAAC,QAAQ,CAAC,OAAO;YACpB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,YAAY,CAAC;YAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,8EAA8E,CAAC,CAAC;YAClG,CAAC;YACD,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;gBACvF,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC,CAAC;YACH,OAAO,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAC1C,CAAC;QACD,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO;YACnB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,YAAY,CAAC;YAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,8EAA8E,CAAC,CAAC;YAClG,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,qBAAqB,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;gBACzF,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC,CAAC;YACH,KAAK,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;KACF,CAAC;AACJ,CAAC;AAMD,MAAM,UAAU,gBAAgB,CAAC,OAAwC;IACvE,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACjC,OAAO,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,mBAAmB,EAAE,CAAC;AACpE,CAAC"}
|
package/dist/providers.d.ts
CHANGED
|
@@ -8,4 +8,4 @@ export { fromGoogleResponse, toGoogleContents, toGoogleRequest, toGoogleSystemIn
|
|
|
8
8
|
export type { GoogleRequestDefaults } from './providers/google-converter.js';
|
|
9
9
|
export { openai, openaiCompatible } from './providers/openai.js';
|
|
10
10
|
export type { OpenAICompatibleProviderOptions, OpenAIProviderOptions } from './providers/openai.js';
|
|
11
|
-
export { fromOpenAICompletion, toOpenAIMessages, toOpenAIRequest, toOpenAIToolChoice, toOpenAITools, } from './providers/openai-converter.js';
|
|
11
|
+
export { fromOpenAICompletion, fromOpenAIStream, toOpenAIMessages, toOpenAIRequest, toOpenAIStreamRequest, toOpenAIToolChoice, toOpenAITools, } from './providers/openai-converter.js';
|
package/dist/providers.js
CHANGED
|
@@ -3,5 +3,5 @@ export { fromAnthropicMessage, toAnthropicMessages, toAnthropicRequest, toAnthro
|
|
|
3
3
|
export { gemini, vertexAI } from './providers/google.js';
|
|
4
4
|
export { fromGoogleResponse, toGoogleContents, toGoogleRequest, toGoogleSystemInstruction, } from './providers/google-converter.js';
|
|
5
5
|
export { openai, openaiCompatible } from './providers/openai.js';
|
|
6
|
-
export { fromOpenAICompletion, toOpenAIMessages, toOpenAIRequest, toOpenAIToolChoice, toOpenAITools, } from './providers/openai-converter.js';
|
|
6
|
+
export { fromOpenAICompletion, fromOpenAIStream, toOpenAIMessages, toOpenAIRequest, toOpenAIStreamRequest, toOpenAIToolChoice, toOpenAITools, } from './providers/openai-converter.js';
|
|
7
7
|
//# sourceMappingURL=providers.js.map
|
package/dist/providers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,yBAAyB,GAC1B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,aAAa,GACd,MAAM,iCAAiC,CAAC"}
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,yBAAyB,GAC1B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,aAAa,GACd,MAAM,iCAAiC,CAAC"}
|
package/docs/pivot.md
CHANGED
|
@@ -71,20 +71,39 @@ and in the 1.x npm line.
|
|
|
71
71
|
- Add converter contract tests with multimodal and tool-call fixtures.
|
|
72
72
|
- Keep provider SDKs isolated behind the `genaicode/providers` export.
|
|
73
73
|
|
|
74
|
-
### Phase 3: backend ergonomics
|
|
75
|
-
|
|
76
|
-
- Streaming with a provider-neutral event IR
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
-
|
|
86
|
-
|
|
87
|
-
|
|
74
|
+
### Phase 3: backend ergonomics — implemented
|
|
75
|
+
|
|
76
|
+
- Streaming with a provider-neutral event IR — implemented (`StreamEvent`,
|
|
77
|
+
`RequestBuilder.stream` / `streamText`, native provider streams with generate
|
|
78
|
+
fallback).
|
|
79
|
+
- Middleware for observability, rate limiting, caching, and fallback —
|
|
80
|
+
implemented (`timingPlugin`, `rateLimitPlugin`, `cachePlugin`, `fallbackPlugin`,
|
|
81
|
+
`fallbackProvider`).
|
|
82
|
+
- First-class schema adapters without requiring a specific validation library — implemented.
|
|
83
|
+
- Small framework examples for HTTP handlers, queues, and cron jobs — implemented
|
|
84
|
+
under `examples/`.
|
|
85
|
+
- Re-evaluate separate provider packages if dependency size becomes material —
|
|
86
|
+
evaluated; keep bundled for 2.x (see [provider-packages.md](./provider-packages.md)).
|
|
87
|
+
|
|
88
|
+
### Phase 4: hardening — implemented
|
|
89
|
+
|
|
90
|
+
- Provider capability metadata — implemented (`ProviderCapabilities` on
|
|
91
|
+
`ModelProvider`).
|
|
92
|
+
- Retry classification and idempotency guidance — implemented
|
|
93
|
+
(`classifyError` / `withRetry` + [retry.md](./retry.md)).
|
|
94
|
+
- Compatibility fixtures for multimodal and tool-call round trips — implemented
|
|
95
|
+
under `src/providers/fixtures/`.
|
|
96
|
+
- Stable extension contracts and a written semver policy — implemented
|
|
97
|
+
([semver.md](./semver.md)).
|
|
98
|
+
|
|
99
|
+
### Release status
|
|
100
|
+
|
|
101
|
+
- `2.0.0` on npm shipped the Phase 1–2 kernel and provider adapters.
|
|
102
|
+
- `2.1.0` publishes Phases 3–4 (streaming, middleware, capabilities, retry
|
|
103
|
+
helpers, fixtures, examples, and related docs).
|
|
104
|
+
- `2.2.0` adds portable `responseFormat` and `thinking` request fields (so apps
|
|
105
|
+
need fewer provider-specific `generationConfig` casts). See
|
|
106
|
+
[CHANGELOG.md](../CHANGELOG.md).
|
|
88
107
|
|
|
89
108
|
## Success measures
|
|
90
109
|
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Provider package split evaluation
|
|
2
|
+
|
|
3
|
+
Phase 3 asked whether OpenAI, Anthropic, and Google adapters should move into
|
|
4
|
+
separate packages to shrink the default install.
|
|
5
|
+
|
|
6
|
+
## Current shape
|
|
7
|
+
|
|
8
|
+
| Package surface | Role |
|
|
9
|
+
| ---------------------- | ----------------------------------------- |
|
|
10
|
+
| `genaicode` | Core client, IR, plugins, middleware |
|
|
11
|
+
| `genaicode/providers` | Adapters + public converters |
|
|
12
|
+
|
|
13
|
+
Hard dependencies today (approximate installed sizes in this repo's lockfile):
|
|
14
|
+
|
|
15
|
+
- `openai` ~12MB
|
|
16
|
+
- `@anthropic-ai/sdk` ~5MB
|
|
17
|
+
- `@google/genai` (+ tree) ~14MB
|
|
18
|
+
|
|
19
|
+
Together the provider SDKs dominate runtime dependency weight versus the small
|
|
20
|
+
core TypeScript sources.
|
|
21
|
+
|
|
22
|
+
## Options considered
|
|
23
|
+
|
|
24
|
+
1. **Keep bundled (status quo)**
|
|
25
|
+
One install, one version matrix, simplest DX. Cost: every consumer downloads
|
|
26
|
+
all three SDKs even if they only use one.
|
|
27
|
+
|
|
28
|
+
2. **Separate packages** (`genaicode-openai`, `genaicode-anthropic`, …)
|
|
29
|
+
Smallest installs. Cost: version skew between core and adapters, more release
|
|
30
|
+
surface, harder getting-started docs.
|
|
31
|
+
|
|
32
|
+
3. **Peer dependencies + optional installs**
|
|
33
|
+
Core stays free of SDKs; `genaicode/providers` re-exports adapters that import
|
|
34
|
+
peers. Cost: peer warnings and slightly worse first-run DX.
|
|
35
|
+
|
|
36
|
+
## Decision for 2.0
|
|
37
|
+
|
|
38
|
+
**Keep provider adapters bundled behind `genaicode/providers` for 2.x.**
|
|
39
|
+
|
|
40
|
+
Reasons:
|
|
41
|
+
|
|
42
|
+
- The product pitch is a tiny portable layer with batteries-included adapters.
|
|
43
|
+
- Converter functions are part of the public compatibility story and are tested
|
|
44
|
+
together against shared fixtures.
|
|
45
|
+
- Absolute weight (~30MB of SDKs) is material but still far smaller than GenAIcode
|
|
46
|
+
1.x; success measures emphasize “substantially smaller than 1.x,” not absolute
|
|
47
|
+
minimalism.
|
|
48
|
+
- Splitting before streaming, middleware, and capability metadata settled would
|
|
49
|
+
freeze the wrong package boundaries.
|
|
50
|
+
|
|
51
|
+
## Revisit triggers
|
|
52
|
+
|
|
53
|
+
Split (or move to optional peers) when any of these become true:
|
|
54
|
+
|
|
55
|
+
- Published install size or cold `npm install` time becomes a documented user pain.
|
|
56
|
+
- A provider SDK forces frequent breaking upgrades independent of core.
|
|
57
|
+
- Tree-shaking cannot eliminate unused SDKs for bundlers targeting edge runtimes.
|
|
58
|
+
|
|
59
|
+
Until then, application authors who need a zero-SDK core can implement
|
|
60
|
+
`ModelProvider` directly and ignore `genaicode/providers`.
|
package/docs/retry.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Retry classification and idempotency
|
|
2
|
+
|
|
3
|
+
GenAIcode does **not** retry provider calls automatically. Retries, backoff, and
|
|
4
|
+
failure budgets belong to application code so side effects stay explicit.
|
|
5
|
+
|
|
6
|
+
## Classify, then decide
|
|
7
|
+
|
|
8
|
+
```ts
|
|
9
|
+
import { classifyError, isRetryable, withRetry } from 'genaicode';
|
|
10
|
+
|
|
11
|
+
const classified = classifyError(error);
|
|
12
|
+
if (classified.retryable) {
|
|
13
|
+
// transient: 408/425/429/5xx, network resets, overload heuristics
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
await withRetry(() => ai('summarize this').text(), {
|
|
17
|
+
attempts: 3,
|
|
18
|
+
delayMs: 250,
|
|
19
|
+
shouldRetry: (error) => isRetryable(error),
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`classifyError` returns `{ class, retryable, reason, status?, code?, cause }`:
|
|
24
|
+
|
|
25
|
+
| Class | Typical causes | Retry? |
|
|
26
|
+
| ----------- | -------------------------------------- | ------ |
|
|
27
|
+
| `transient` | 429, 5xx, timeouts, connection resets | yes |
|
|
28
|
+
| `permanent` | 4xx (except above), auth, abort | no |
|
|
29
|
+
| `unknown` | Unrecognized shapes | no* |
|
|
30
|
+
|
|
31
|
+
\*Treat unknown as non-retryable by default; override with `shouldRetry` when you
|
|
32
|
+
know more about your gateway.
|
|
33
|
+
|
|
34
|
+
## Idempotency guidance
|
|
35
|
+
|
|
36
|
+
Safe to retry without extra coordination:
|
|
37
|
+
|
|
38
|
+
- Pure generation (`text`, `json`, `toolCalls` that only *propose* tool calls)
|
|
39
|
+
- Read-only prompts against immutable inputs
|
|
40
|
+
|
|
41
|
+
Not safe to retry blindly:
|
|
42
|
+
|
|
43
|
+
- Application code that executes tool calls with side effects (writes, charges, emails)
|
|
44
|
+
- Chains where a partial turn already mutated external state
|
|
45
|
+
|
|
46
|
+
Patterns that keep retries safe:
|
|
47
|
+
|
|
48
|
+
1. **Propose, then commit.** Let the model return a plan; apply side effects once
|
|
49
|
+
after validation.
|
|
50
|
+
2. **Idempotency keys.** If a tool must run inside a retry loop, key the effect
|
|
51
|
+
(e.g. `Idempotency-Key` on a payment API) so duplicates collapse.
|
|
52
|
+
3. **Outbox / queue.** Persist the intended effect before calling the provider, or
|
|
53
|
+
after a successful model response but before side effects, depending on your
|
|
54
|
+
failure mode.
|
|
55
|
+
4. **Do not put retries inside plugins by default.** A retry plugin hides policy
|
|
56
|
+
from callers; prefer `withRetry` at the call site or a named, intentional plugin.
|
|
57
|
+
|
|
58
|
+
## Streaming
|
|
59
|
+
|
|
60
|
+
If a stream fails mid-flight, do not assume the partial text was committed anywhere.
|
|
61
|
+
Re-run the full request (or resume with your own checkpointing). Conversation
|
|
62
|
+
chains only append history after a successful completed turn.
|
package/docs/semver.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Semver and extension contracts
|
|
2
|
+
|
|
3
|
+
GenAIcode 2.x follows semantic versioning for the published TypeScript API.
|
|
4
|
+
|
|
5
|
+
## Public contracts (semver-stable)
|
|
6
|
+
|
|
7
|
+
These are covered by minor/patch compatibility within 2.x:
|
|
8
|
+
|
|
9
|
+
- `genaicode()` client, immutable request builders, and conversation chains
|
|
10
|
+
- `PromptItem`, `GenerationRequest`, `GenerationResult`, `StreamEvent`
|
|
11
|
+
- `ResponseFormat`, `ThinkingConfig`, and related capability flags
|
|
12
|
+
- `ModelProvider` and `GenAIPlugin` interfaces
|
|
13
|
+
- Prompt helpers (`prompt`, `system`, `user`, `assistant`, `asPrompt`, …)
|
|
14
|
+
- Result helpers (`resultText`, `parseJsonResult`, …)
|
|
15
|
+
- Built-in middleware factories (`timingPlugin`, `rateLimitPlugin`, `cachePlugin`,
|
|
16
|
+
`fallbackPlugin`, `fallbackProvider`)
|
|
17
|
+
- Error helpers (`classifyError`, `isRetryable`, `withRetry`)
|
|
18
|
+
- Provider factories and converter functions exported from `genaicode/providers`
|
|
19
|
+
|
|
20
|
+
## Additive changes (minor)
|
|
21
|
+
|
|
22
|
+
Safe in a minor release:
|
|
23
|
+
|
|
24
|
+
- New optional fields on request/result/stream types
|
|
25
|
+
- New optional methods on `ModelProvider` / `GenAIPlugin` (callers must feature-detect)
|
|
26
|
+
- New exports and middleware helpers
|
|
27
|
+
- New provider adapters behind `genaicode/providers`
|
|
28
|
+
- New capability flags on `ProviderCapabilities`
|
|
29
|
+
|
|
30
|
+
## Breaking changes (major)
|
|
31
|
+
|
|
32
|
+
Require a new major version:
|
|
33
|
+
|
|
34
|
+
- Removing or renaming exports
|
|
35
|
+
- Changing the meaning of existing `PromptItem` fields
|
|
36
|
+
- Making previously optional callback/plugin behavior mandatory
|
|
37
|
+
- Changing default retry/side-effect policy (there is none today; introducing
|
|
38
|
+
hidden retries would be a major behavioral break)
|
|
39
|
+
- Moving provider SDKs in a way that removes the current `genaicode/providers`
|
|
40
|
+
entry without a compatibility window
|
|
41
|
+
|
|
42
|
+
## Non-guarantees
|
|
43
|
+
|
|
44
|
+
- Exact shapes of `raw` provider payloads
|
|
45
|
+
- Timing of stream events beyond the `StreamEvent` discriminant
|
|
46
|
+
- Dependency versions of underlying provider SDKs within a major (may bump in
|
|
47
|
+
minors when needed for security or API drift)
|
|
48
|
+
- Example apps under `examples/` (illustrative only)
|
|
49
|
+
|
|
50
|
+
## Plugin and provider authors
|
|
51
|
+
|
|
52
|
+
- Depend on TypeScript types from `genaicode`, not on private `dist/` paths.
|
|
53
|
+
- Prefer ordinary package exports over runtime loaders.
|
|
54
|
+
- Feature-detect `provider.stream` and `provider.capabilities`.
|
|
55
|
+
- Treat `metadata` on `GenerationRequest` as an open bag for your middleware;
|
|
56
|
+
do not require core to understand your keys.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genaicode",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "A small, provider-neutral TypeScript toolkit for calling LLMs from backend code.",
|
|
5
5
|
"author": "Grzegorz Tańczyk",
|
|
6
6
|
"repository": {
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"files": [
|
|
28
28
|
"dist",
|
|
29
29
|
"docs",
|
|
30
|
+
"CHANGELOG.md",
|
|
30
31
|
"README.md",
|
|
31
32
|
"LICENSE"
|
|
32
33
|
],
|
|
@@ -45,10 +46,12 @@
|
|
|
45
46
|
"build": "npm run clean && tsc -p tsconfig.build.json",
|
|
46
47
|
"lint": "eslint . --ext js,ts --report-unused-disable-directives --max-warnings 0",
|
|
47
48
|
"test": "vitest --config vitest.unit.config.ts --run",
|
|
49
|
+
"test:e2e": "vitest --config vitest.e2e.config.ts --run",
|
|
48
50
|
"test:watch": "vitest --config vitest.unit.config.ts",
|
|
49
51
|
"type-check": "tsc --noEmit",
|
|
50
52
|
"check": "npm run type-check && npm run lint && npm test && npm run build",
|
|
51
|
-
"prepublishOnly": "npm run check"
|
|
53
|
+
"prepublishOnly": "npm run check",
|
|
54
|
+
"prepare": "npm run build"
|
|
52
55
|
},
|
|
53
56
|
"dependencies": {
|
|
54
57
|
"@anthropic-ai/sdk": "^0.74.0",
|