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
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 2.2.0 — 2026-07-26
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Portable `responseFormat` on `GenerationRequest` / request builders
|
|
8
|
+
(`text` | `json` | `json_schema`), mapped by OpenAI and Google adapters
|
|
9
|
+
- Portable `thinking` controls (`false` | `{ budgetTokens?, level? }`), mapped by
|
|
10
|
+
Anthropic (budget / disable) and Google (budget or level)
|
|
11
|
+
- `.json()` sets `responseFormat: { type: 'json' }` when no format was already chosen
|
|
12
|
+
- Capability flags: `jsonResponse`, `thinking`
|
|
13
|
+
|
|
14
|
+
### Notes
|
|
15
|
+
|
|
16
|
+
- Additive only; provider `generationConfig` / Anthropic `thinking` factory options still
|
|
17
|
+
work as escape hatches for vendor-only knobs.
|
|
18
|
+
- On Google, `thinking: false` and `budgetTokens: 0` map to `thinkingLevel: MINIMAL`
|
|
19
|
+
(Gemini 3 rejects `thinkingBudget: 0`). JSON `responseFormat` also defaults Google
|
|
20
|
+
thinking to `MINIMAL` when unset, so small token budgets are not spent only on thoughts.
|
|
21
|
+
- Provider E2E covers JSON response format and thinking knobs when credentials are set.
|
|
22
|
+
|
|
23
|
+
## 2.1.0 — 2026-07-25
|
|
24
|
+
|
|
25
|
+
Publishes the Phase 3–4 work already on `master`. npm `2.0.0` shipped the 2.0
|
|
26
|
+
kernel and provider adapters only; this minor adds the remaining public surface
|
|
27
|
+
documented in the README and [semver policy](docs/semver.md).
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- Provider-neutral streaming (`StreamEvent`, `.stream()` / `.streamText()`,
|
|
32
|
+
native streams for OpenAI / Anthropic / Google with generate→stream fallback)
|
|
33
|
+
- Built-in middleware: `timingPlugin`, `rateLimitPlugin`, `cachePlugin`,
|
|
34
|
+
`fallbackPlugin`, `fallbackProvider`
|
|
35
|
+
- Retry helpers: `classifyError`, `isRetryable`, `withRetry` (+ [docs/retry.md](docs/retry.md))
|
|
36
|
+
- `ProviderCapabilities` on `ModelProvider`
|
|
37
|
+
- Compatibility fixtures for multimodal and tool-call round trips
|
|
38
|
+
- Framework examples under `examples/` (HTTP handler, queue worker, cron job)
|
|
39
|
+
- Written guidance: [docs/semver.md](docs/semver.md),
|
|
40
|
+
[docs/provider-packages.md](docs/provider-packages.md)
|
|
41
|
+
|
|
42
|
+
### Notes
|
|
43
|
+
|
|
44
|
+
- Additive API only; no breaking changes from `2.0.0`.
|
|
45
|
+
- Retries remain opt-in application policy (no hidden retries in core).
|
|
46
|
+
- Provider SDKs stay bundled behind `genaicode/providers` for 2.x.
|
|
47
|
+
|
|
48
|
+
## 2.0.0 — 2026-07-24
|
|
49
|
+
|
|
50
|
+
Major pivot from coding agent to backend LLM toolkit.
|
|
51
|
+
|
|
52
|
+
- `genaicode()` client, immutable request builders, conversation chains
|
|
53
|
+
- `PromptItem` IR and prompt/result helpers
|
|
54
|
+
- OpenAI, OpenAI-compatible, Anthropic, Gemini, and Vertex adapters
|
|
55
|
+
- `GenAIPlugin` middleware contract
|
|
56
|
+
- Coding-agent CLI/UI/tools removed; `npx genaicode` prints migration guidance
|
|
57
|
+
(1.x remains on the `1.x` branch / `genaicode@1`)
|
package/README.md
CHANGED
|
@@ -14,36 +14,39 @@ It sits between raw provider SDKs and full agent frameworks: one prompt represen
|
|
|
14
14
|
thin provider adapters, a convenient request API, and lightweight conversation chains.
|
|
15
15
|
It does not inspect repositories, execute shell commands, edit files, or run an agent UI.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
**Like jQuery**, the common case starts with one small function and becomes more specific
|
|
18
|
+
through chaining—configure a request, follow up across multiple prompts, and keep history
|
|
19
|
+
portable without adopting a full agent framework.
|
|
18
20
|
|
|
19
|
-
GenAIcode 1.x was a coding agent
|
|
20
|
-
|
|
21
|
-
conversation chains, and plugins.
|
|
21
|
+
GenAIcode 1.x was a coding agent; see [Migration from 1.x](#migration-from-1x) if you need
|
|
22
|
+
the old product or the 2.0 scope decisions.
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
orchestration are not deprecated compatibility features; they have been removed from
|
|
25
|
-
2.0. The GenAIcode name, `PromptItem` model, provider converters, and extensibility
|
|
26
|
-
continue here in a smaller and more focused form.
|
|
27
|
-
|
|
28
|
-
The original coding agent remains available from the preserved
|
|
29
|
-
[`1.x` branch](https://github.com/gtanczyk/genaicode/tree/1.x) and the 1.x npm releases:
|
|
24
|
+
## Install
|
|
30
25
|
|
|
31
26
|
```bash
|
|
32
|
-
|
|
27
|
+
npm install genaicode
|
|
33
28
|
```
|
|
34
29
|
|
|
35
|
-
|
|
36
|
-
starting the old agent.
|
|
30
|
+
Node.js 20 or newer is required.
|
|
37
31
|
|
|
38
|
-
|
|
32
|
+
## Why this vs a raw SDK
|
|
39
33
|
|
|
40
|
-
|
|
34
|
+
Provider SDKs are the right tool when you call one vendor and own every request shape
|
|
35
|
+
yourself. The cost shows up when the same backend needs a second provider, a test double,
|
|
36
|
+
or shared policy (timeouts, JSON parsing, rate limits, fallback) without copying glue.
|
|
41
37
|
|
|
42
|
-
|
|
43
|
-
npm install genaicode
|
|
44
|
-
```
|
|
38
|
+
GenAIcode is that thin shared layer:
|
|
45
39
|
|
|
46
|
-
|
|
40
|
+
- One portable prompt/tool IR (`PromptItem`) instead of OpenAI messages vs Anthropic
|
|
41
|
+
blocks vs Gemini contents.
|
|
42
|
+
- One request API (`.text()`, `.json()`, `.stream()`, chains) over those adapters.
|
|
43
|
+
- A tiny `ModelProvider` seam so tests and custom gateways do not mock vendor HTTP.
|
|
44
|
+
- Opt-in middleware and retry helpers—no hidden tool runners, no silent retries, no
|
|
45
|
+
agent loop.
|
|
46
|
+
|
|
47
|
+
If you are happy importing one SDK and never swapping models or providers, stay on the
|
|
48
|
+
SDK. If you want the call site to look the same while the edge stays replaceable, use
|
|
49
|
+
GenAIcode.
|
|
47
50
|
|
|
48
51
|
## A prompt in three lines
|
|
49
52
|
|
|
@@ -55,8 +58,9 @@ const ai = genaicode(openai({ model: 'your-model-name' }));
|
|
|
55
58
|
const answer = await ai('Explain why the sky is blue in two sentences.').text();
|
|
56
59
|
```
|
|
57
60
|
|
|
58
|
-
The client is callable on purpose.
|
|
59
|
-
|
|
61
|
+
The client is callable on purpose. Configuration is ordinary method chaining—system
|
|
62
|
+
instructions, temperature, token limits, and more—without a separate options object or
|
|
63
|
+
framework setup:
|
|
60
64
|
|
|
61
65
|
```ts
|
|
62
66
|
const result = await ai('Create a release note from these commits')
|
|
@@ -66,12 +70,21 @@ const result = await ai('Create a release note from these commits')
|
|
|
66
70
|
.text();
|
|
67
71
|
```
|
|
68
72
|
|
|
69
|
-
Builders are immutable, so a configured base request can be safely reused
|
|
73
|
+
Builders are immutable, so a configured base request can be safely reused:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
const releaseNote = ai('Create a release note from these commits')
|
|
77
|
+
.system('You are a concise technical writer.')
|
|
78
|
+
.temperature(0.2);
|
|
79
|
+
|
|
80
|
+
const short = await releaseNote.maxOutputTokens(200).text();
|
|
81
|
+
const long = await releaseNote.maxOutputTokens(800).text();
|
|
82
|
+
```
|
|
70
83
|
|
|
71
84
|
## Chaining prompts
|
|
72
85
|
|
|
73
86
|
A chain remembers successful user and assistant turns. Each new prompt sees the complete
|
|
74
|
-
history:
|
|
87
|
+
history, so multi-step work stays in ordinary application code:
|
|
75
88
|
|
|
76
89
|
```ts
|
|
77
90
|
import { system } from 'genaicode';
|
|
@@ -129,6 +142,51 @@ for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
|
129
142
|
|
|
130
143
|
The application owns validation, attempt limits, and failure policy.
|
|
131
144
|
|
|
145
|
+
## Schema adapters
|
|
146
|
+
|
|
147
|
+
`json(...)` and `parseJsonResult(...)` accept either a parser function or a schema adapter
|
|
148
|
+
with a `parse(value)` method. This keeps schema validation library-agnostic:
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
const value = await ai('Return {"count": 3}.').json({
|
|
152
|
+
parse(input) {
|
|
153
|
+
if (typeof input !== 'object' || input === null || typeof input.count !== 'number') {
|
|
154
|
+
throw new Error('Invalid shape');
|
|
155
|
+
}
|
|
156
|
+
return input;
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Calling `.json()` also sets `responseFormat: { type: 'json' }` on the request when you have
|
|
162
|
+
not already chosen a format, so providers that support JSON mode (OpenAI, Gemini/Vertex)
|
|
163
|
+
are asked for JSON rather than free text.
|
|
164
|
+
|
|
165
|
+
## Response format and thinking
|
|
166
|
+
|
|
167
|
+
Portable request fields cover the two knobs backends usually poke through provider-specific
|
|
168
|
+
config:
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
const verdict = await ai(promptText)
|
|
172
|
+
.responseFormat({ type: 'json' })
|
|
173
|
+
.thinking({ level: 'minimal' }) // or { budgetTokens: 0 } / false to disable
|
|
174
|
+
.temperature(0)
|
|
175
|
+
.json((value) => VerdictSchema.parse(value));
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
- `responseFormat`: `{ type: 'text' | 'json' }` or
|
|
179
|
+
`{ type: 'json_schema', name, schema, strict? }`.
|
|
180
|
+
- `thinking`: `false` to disable, or `{ budgetTokens?, level? }` (`minimal` |
|
|
181
|
+
`low` | `medium` | `high`). Prefer one of budget or level — some providers reject both.
|
|
182
|
+
On Google/Gemini, `false` and `budgetTokens: 0` map to `thinkingLevel: MINIMAL`
|
|
183
|
+
because Gemini 3 rejects `thinkingBudget: 0`. JSON `responseFormat` without an
|
|
184
|
+
explicit `thinking` setting also defaults Google to `MINIMAL`.
|
|
185
|
+
|
|
186
|
+
Providers map what they support and ignore the rest. `ProviderCapabilities.jsonResponse`
|
|
187
|
+
and `ProviderCapabilities.thinking` advertise support. Vendor-specific escapes such as
|
|
188
|
+
Vertex `generationConfig` remain available for anything not covered here.
|
|
189
|
+
|
|
132
190
|
## PromptItem: the portable prompt IR
|
|
133
191
|
|
|
134
192
|
`PromptItem` is GenAIcode's provider-neutral intermediate representation:
|
|
@@ -184,6 +242,68 @@ const calls = await ai('What is the weather in Warsaw?')
|
|
|
184
242
|
GenAIcode normalizes tool calls but deliberately does not execute them. The application
|
|
185
243
|
owns permissions, retries, and side effects.
|
|
186
244
|
|
|
245
|
+
## Streaming
|
|
246
|
+
|
|
247
|
+
Providers that support native streaming expose a provider-neutral `StreamEvent` IR.
|
|
248
|
+
Request builders and chains offer `.stream()` and `.streamText()`. If a provider has no
|
|
249
|
+
`stream` method, GenAIcode synthesizes a short stream from `generate`.
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
for await (const event of ai('Write a haiku about queues.').stream()) {
|
|
253
|
+
if (event.type === 'text-delta') process.stdout.write(event.text);
|
|
254
|
+
if (event.type === 'done') console.log('\n', event.result.usage);
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Built-in adapters declare capability metadata:
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
ai.provider.capabilities;
|
|
262
|
+
// { streaming: true, tools: true, images: 'input', systemPrompt: true }
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Middleware
|
|
266
|
+
|
|
267
|
+
Hook-style plugins remain the extension point. Built-in helpers cover common backend
|
|
268
|
+
needs without restoring a global registry:
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
import {
|
|
272
|
+
cachePlugin,
|
|
273
|
+
fallbackPlugin,
|
|
274
|
+
genaicode,
|
|
275
|
+
rateLimitPlugin,
|
|
276
|
+
timingPlugin,
|
|
277
|
+
} from 'genaicode';
|
|
278
|
+
import { anthropic, openai } from 'genaicode/providers';
|
|
279
|
+
|
|
280
|
+
const ai = genaicode(openai({ model: 'your-model-name' }), {
|
|
281
|
+
plugins: [
|
|
282
|
+
timingPlugin(),
|
|
283
|
+
rateLimitPlugin({ concurrency: 2, minIntervalMs: 50 }),
|
|
284
|
+
cachePlugin({ maxEntries: 64 }),
|
|
285
|
+
fallbackPlugin({ providers: [anthropic({ model: 'your-claude-model' })] }),
|
|
286
|
+
],
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Retries
|
|
291
|
+
|
|
292
|
+
Retries stay in application code. Use `classifyError`, `isRetryable`, and `withRetry`
|
|
293
|
+
when you want shared classification without hidden policy:
|
|
294
|
+
|
|
295
|
+
```ts
|
|
296
|
+
import { withRetry } from 'genaicode';
|
|
297
|
+
|
|
298
|
+
const text = await withRetry(() => ai('Summarize the deploy notes.').text(), {
|
|
299
|
+
attempts: 3,
|
|
300
|
+
delayMs: 250,
|
|
301
|
+
});
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
See [retry guidance](docs/retry.md), [semver policy](docs/semver.md), and the
|
|
305
|
+
[provider package evaluation](docs/provider-packages.md).
|
|
306
|
+
|
|
187
307
|
## Providers
|
|
188
308
|
|
|
189
309
|
Models are provided in the adapter, through `.model(...)`, or with environment variables:
|
|
@@ -248,6 +368,27 @@ const provider: ModelProvider = {
|
|
|
248
368
|
All Anthropic, Google, and OpenAI conversion functions are public from
|
|
249
369
|
`genaicode/providers`, so gateways and tests can reuse them without instantiating clients.
|
|
250
370
|
|
|
371
|
+
## Provider E2E tests
|
|
372
|
+
|
|
373
|
+
Run real-provider E2E tests locally with:
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
npm run test:e2e
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
These tests are credential-gated and run only when provider-specific environment variables
|
|
380
|
+
are set:
|
|
381
|
+
|
|
382
|
+
- OpenAI: `OPENAI_API_KEY`, `OPENAI_MODEL`
|
|
383
|
+
- Anthropic: `ANTHROPIC_API_KEY`, `ANTHROPIC_MODEL`
|
|
384
|
+
- Gemini: `GEMINI_API_KEY`, `GEMINI_MODEL`
|
|
385
|
+
|
|
386
|
+
Beyond the smoke call, E2E also covers portable `responseFormat: { type: 'json' }`
|
|
387
|
+
(OpenAI, Gemini) and `thinking` (Anthropic disable; Gemini disable / `level: 'minimal'`).
|
|
388
|
+
|
|
389
|
+
CI/CD is configured in `.github/workflows/provider-e2e.yaml`. Each provider runs in its own
|
|
390
|
+
job and only starts when both required secrets are configured in GitHub Actions.
|
|
391
|
+
|
|
251
392
|
## Plugins and hooks
|
|
252
393
|
|
|
253
394
|
A provider plugin no longer needs registration in global configuration. It exports the
|
|
@@ -259,6 +400,7 @@ import type { ModelProvider } from 'genaicode';
|
|
|
259
400
|
|
|
260
401
|
export const bedrock = (options: BedrockOptions): ModelProvider => ({
|
|
261
402
|
name: 'bedrock',
|
|
403
|
+
capabilities: { streaming: false, tools: true, systemPrompt: true },
|
|
262
404
|
async generate(request) {
|
|
263
405
|
// Convert PromptItem[], call Bedrock, and return GenerationResult.
|
|
264
406
|
return { parts: [{ type: 'text', text: 'response' }] };
|
|
@@ -267,7 +409,8 @@ export const bedrock = (options: BedrockOptions): ModelProvider => ({
|
|
|
267
409
|
```
|
|
268
410
|
|
|
269
411
|
Hook-style plugins use middleware. They can observe or rewrite requests and results,
|
|
270
|
-
handle errors, implement caches or fallbacks, and intentionally short-circuit a call
|
|
412
|
+
handle errors, implement caches or fallbacks, and intentionally short-circuit a call.
|
|
413
|
+
Optional `stream` middleware follows the same registration order.
|
|
271
414
|
|
|
272
415
|
```ts
|
|
273
416
|
import { definePlugin, genaicode } from 'genaicode';
|
|
@@ -294,6 +437,9 @@ Plugins run in registration order, and each plugin may call `next()` once. This
|
|
|
294
437
|
extension mechanism compatible with npm packages and ordinary imports without restoring
|
|
295
438
|
the 1.x runtime TypeScript loader or process-global plugin registry.
|
|
296
439
|
|
|
440
|
+
Framework-shaped examples live under `examples/` (`http-handler`, `queue-worker`,
|
|
441
|
+
`cron-job`).
|
|
442
|
+
|
|
297
443
|
## Design boundaries
|
|
298
444
|
|
|
299
445
|
- Backend library, not a coding agent.
|
|
@@ -305,4 +451,26 @@ the 1.x runtime TypeScript loader or process-global plugin registry.
|
|
|
305
451
|
- Third-party providers and middleware use stable TypeScript contracts.
|
|
306
452
|
- Provider SDKs stay behind the `genaicode/providers` subpath.
|
|
307
453
|
|
|
308
|
-
|
|
454
|
+
## Migration from 1.x
|
|
455
|
+
|
|
456
|
+
GenAIcode 1.x was a coding agent. Version 2.0 deliberately replaces that product with a
|
|
457
|
+
small backend LLM toolkit: a jQuery-like layer for portable prompts, provider adapters,
|
|
458
|
+
conversation chains, and plugins.
|
|
459
|
+
|
|
460
|
+
The coding-agent CLI, browser UI, repository tools, shell execution, and agent
|
|
461
|
+
orchestration are not deprecated compatibility features; they have been removed from
|
|
462
|
+
2.0. The GenAIcode name, `PromptItem` model, provider converters, and extensibility
|
|
463
|
+
continue here in a smaller and more focused form.
|
|
464
|
+
|
|
465
|
+
The original coding agent remains available from the preserved
|
|
466
|
+
[`1.x` branch](https://github.com/gtanczyk/genaicode/tree/1.x) and the 1.x npm releases:
|
|
467
|
+
|
|
468
|
+
```bash
|
|
469
|
+
npx genaicode@1
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
Running `npx genaicode` with version 2.x prints this migration guidance instead of
|
|
473
|
+
starting the old agent.
|
|
474
|
+
|
|
475
|
+
See [the pivot plan](docs/pivot.md) for the full scope, migration decisions, and the
|
|
476
|
+
roadmap.
|
package/dist/core/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type GenAIPlugin } from './plugins.js';
|
|
2
|
-
import type { GenerationDefaults, GenerationRequest, GenerationResult, ModelProvider, PromptInput, PromptItem, ToolCall, ToolChoice, ToolDefinition } from './types.js';
|
|
2
|
+
import type { GenerationDefaults, GenerationRequest, GenerationResult, JsonResultParser, ModelProvider, PromptInput, PromptItem, ResponseFormat, StreamEvent, ThinkingConfig, ToolCall, ToolChoice, ToolDefinition } from './types.js';
|
|
3
3
|
export interface RequestBuilder {
|
|
4
4
|
system(text: string): RequestBuilder;
|
|
5
5
|
user(input: PromptInput): RequestBuilder;
|
|
@@ -8,19 +8,31 @@ export interface RequestBuilder {
|
|
|
8
8
|
temperature(temperature: number): RequestBuilder;
|
|
9
9
|
maxOutputTokens(maxOutputTokens: number): RequestBuilder;
|
|
10
10
|
tools(tools: ToolDefinition[], choice?: ToolChoice): RequestBuilder;
|
|
11
|
+
/** Ask the provider for JSON (or a JSON schema) when supported. */
|
|
12
|
+
responseFormat(format: ResponseFormat): RequestBuilder;
|
|
13
|
+
/** Portable thinking / reasoning controls when the provider supports them. */
|
|
14
|
+
thinking(thinking: ThinkingConfig): RequestBuilder;
|
|
15
|
+
/** Ground the answer in the provider's own built-in web search, where supported. */
|
|
16
|
+
search(enabled?: boolean): RequestBuilder;
|
|
11
17
|
signal(signal: AbortSignal): RequestBuilder;
|
|
12
18
|
run(): Promise<GenerationResult>;
|
|
13
19
|
text(): Promise<string>;
|
|
14
|
-
json<T = unknown>(parse?:
|
|
20
|
+
json<T = unknown>(parse?: JsonResultParser<T>): Promise<T>;
|
|
15
21
|
toolCalls(): Promise<ToolCall[]>;
|
|
22
|
+
/** Provider-neutral streaming events (native when available, synthesized otherwise). */
|
|
23
|
+
stream(): AsyncIterable<StreamEvent>;
|
|
24
|
+
/** Convenience: yield only text deltas. */
|
|
25
|
+
streamText(): AsyncIterable<string>;
|
|
16
26
|
inspect(): GenerationRequest;
|
|
17
27
|
}
|
|
18
28
|
export type ConfigureRequest = (request: RequestBuilder) => RequestBuilder;
|
|
19
29
|
export interface Conversation {
|
|
20
30
|
ask(input: PromptInput, configure?: ConfigureRequest): Promise<GenerationResult>;
|
|
21
31
|
text(input: PromptInput, configure?: ConfigureRequest): Promise<string>;
|
|
22
|
-
json<T = unknown>(input: PromptInput, parse?:
|
|
32
|
+
json<T = unknown>(input: PromptInput, parse?: JsonResultParser<T>, configure?: ConfigureRequest): Promise<T>;
|
|
23
33
|
toolCalls(input: PromptInput, configure?: ConfigureRequest): Promise<ToolCall[]>;
|
|
34
|
+
stream(input: PromptInput, configure?: ConfigureRequest): AsyncIterable<StreamEvent>;
|
|
35
|
+
streamText(input: PromptInput, configure?: ConfigureRequest): AsyncIterable<string>;
|
|
24
36
|
history(): PromptItem[];
|
|
25
37
|
reset(...initial: PromptInput[]): void;
|
|
26
38
|
}
|
package/dist/core/client.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { assistant, prompt, system, toPromptItems } from './prompt.js';
|
|
2
2
|
import { withPlugins } from './plugins.js';
|
|
3
3
|
import { parseJsonResult, resultText, resultToPromptItem, resultToolCalls } from './result.js';
|
|
4
|
+
import { providerStream, streamTextDeltas } from './stream.js';
|
|
4
5
|
class RequestBuilderImpl {
|
|
5
6
|
provider;
|
|
6
7
|
state;
|
|
@@ -39,6 +40,15 @@ class RequestBuilderImpl {
|
|
|
39
40
|
tools(tools, toolChoice = 'auto') {
|
|
40
41
|
return this.copy({ tools, toolChoice });
|
|
41
42
|
}
|
|
43
|
+
responseFormat(responseFormat) {
|
|
44
|
+
return this.copy({ responseFormat });
|
|
45
|
+
}
|
|
46
|
+
thinking(thinking) {
|
|
47
|
+
return this.copy({ thinking });
|
|
48
|
+
}
|
|
49
|
+
search(enabled = true) {
|
|
50
|
+
return this.copy({ search: enabled });
|
|
51
|
+
}
|
|
42
52
|
signal(signal) {
|
|
43
53
|
return this.copy({ signal });
|
|
44
54
|
}
|
|
@@ -50,6 +60,9 @@ class RequestBuilderImpl {
|
|
|
50
60
|
maxOutputTokens: this.state.maxOutputTokens,
|
|
51
61
|
tools: this.state.tools,
|
|
52
62
|
toolChoice: this.state.toolChoice,
|
|
63
|
+
responseFormat: this.state.responseFormat,
|
|
64
|
+
thinking: this.state.thinking,
|
|
65
|
+
search: this.state.search,
|
|
53
66
|
signal: this.state.signal,
|
|
54
67
|
metadata: this.state.metadata,
|
|
55
68
|
};
|
|
@@ -61,12 +74,18 @@ class RequestBuilderImpl {
|
|
|
61
74
|
return resultText(await this.run());
|
|
62
75
|
}
|
|
63
76
|
async json(parse) {
|
|
64
|
-
const
|
|
65
|
-
return parseJsonResult(
|
|
77
|
+
const builder = this.state.responseFormat ? this : this.copy({ responseFormat: { type: 'json' } });
|
|
78
|
+
return parseJsonResult(await builder.run(), parse);
|
|
66
79
|
}
|
|
67
80
|
async toolCalls() {
|
|
68
81
|
return resultToolCalls(await this.run());
|
|
69
82
|
}
|
|
83
|
+
stream() {
|
|
84
|
+
return providerStream(this.provider, this.inspect());
|
|
85
|
+
}
|
|
86
|
+
streamText() {
|
|
87
|
+
return streamTextDeltas(this.stream());
|
|
88
|
+
}
|
|
70
89
|
}
|
|
71
90
|
class ConversationImpl {
|
|
72
91
|
createRequest;
|
|
@@ -95,11 +114,76 @@ class ConversationImpl {
|
|
|
95
114
|
return resultText(await this.ask(input, configure));
|
|
96
115
|
}
|
|
97
116
|
async json(input, parse, configure) {
|
|
98
|
-
return parseJsonResult(await this.ask(input,
|
|
117
|
+
return parseJsonResult(await this.ask(input, (request) => {
|
|
118
|
+
const withJson = request.inspect().responseFormat ? request : request.responseFormat({ type: 'json' });
|
|
119
|
+
return (configure ?? ((value) => value))(withJson);
|
|
120
|
+
}), parse);
|
|
99
121
|
}
|
|
100
122
|
async toolCalls(input, configure) {
|
|
101
123
|
return resultToolCalls(await this.ask(input, configure));
|
|
102
124
|
}
|
|
125
|
+
stream(input, configure = (request) => request) {
|
|
126
|
+
return this.iterateStream(input, configure);
|
|
127
|
+
}
|
|
128
|
+
async *iterateStream(input, configure) {
|
|
129
|
+
let release = () => undefined;
|
|
130
|
+
const gate = new Promise((resolve) => {
|
|
131
|
+
release = resolve;
|
|
132
|
+
});
|
|
133
|
+
const previous = this.queue;
|
|
134
|
+
this.queue = previous.then(() => gate);
|
|
135
|
+
await previous;
|
|
136
|
+
try {
|
|
137
|
+
const additions = toPromptItems(input);
|
|
138
|
+
const generation = this.generation;
|
|
139
|
+
const events = configure(this.createRequest(this.items, additions)).stream();
|
|
140
|
+
let text = '';
|
|
141
|
+
const toolCalls = [];
|
|
142
|
+
const images = [];
|
|
143
|
+
let usage;
|
|
144
|
+
let doneResult;
|
|
145
|
+
for await (const event of events) {
|
|
146
|
+
yield event;
|
|
147
|
+
switch (event.type) {
|
|
148
|
+
case 'text-delta':
|
|
149
|
+
text += event.text;
|
|
150
|
+
break;
|
|
151
|
+
case 'tool-call':
|
|
152
|
+
toolCalls.push(event.toolCall);
|
|
153
|
+
break;
|
|
154
|
+
case 'image':
|
|
155
|
+
images.push({ type: 'image', image: event.image });
|
|
156
|
+
break;
|
|
157
|
+
case 'usage':
|
|
158
|
+
usage = event.usage;
|
|
159
|
+
break;
|
|
160
|
+
case 'done':
|
|
161
|
+
doneResult = event.result;
|
|
162
|
+
break;
|
|
163
|
+
default:
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const result = doneResult ??
|
|
168
|
+
{
|
|
169
|
+
parts: [
|
|
170
|
+
...(text ? [{ type: 'text', text }] : []),
|
|
171
|
+
...toolCalls.map((toolCall) => ({ type: 'toolCall', toolCall })),
|
|
172
|
+
...images,
|
|
173
|
+
],
|
|
174
|
+
usage,
|
|
175
|
+
};
|
|
176
|
+
if (generation === this.generation) {
|
|
177
|
+
this.items = [...this.items, ...additions, resultToPromptItem(result)];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
release();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
streamText(input, configure) {
|
|
185
|
+
return streamTextDeltas(this.stream(input, configure));
|
|
186
|
+
}
|
|
103
187
|
history() {
|
|
104
188
|
return this.items.map((item) => ({ ...item }));
|
|
105
189
|
}
|
package/dist/core/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,WAAW,EAAoB,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type ErrorClass = 'transient' | 'permanent' | 'unknown';
|
|
2
|
+
export interface ClassifiedError {
|
|
3
|
+
class: ErrorClass;
|
|
4
|
+
retryable: boolean;
|
|
5
|
+
reason: string;
|
|
6
|
+
status?: number;
|
|
7
|
+
code?: string;
|
|
8
|
+
cause: unknown;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Classify a provider/SDK error for application-owned retry loops.
|
|
12
|
+
*
|
|
13
|
+
* GenAIcode does not retry automatically. Use this helper (or your own policy)
|
|
14
|
+
* inside ordinary application control flow. See docs/retry.md.
|
|
15
|
+
*/
|
|
16
|
+
export declare function classifyError(error: unknown): ClassifiedError;
|
|
17
|
+
export declare function isRetryable(error: unknown): boolean;
|
|
18
|
+
export interface RetryOptions {
|
|
19
|
+
attempts?: number;
|
|
20
|
+
/** Base delay in ms; doubles each attempt. Defaults to 250. */
|
|
21
|
+
delayMs?: number;
|
|
22
|
+
/** Max delay cap in ms. Defaults to 5000. */
|
|
23
|
+
maxDelayMs?: number;
|
|
24
|
+
shouldRetry?: (error: unknown, attempt: number) => boolean;
|
|
25
|
+
onRetry?: (info: {
|
|
26
|
+
attempt: number;
|
|
27
|
+
error: unknown;
|
|
28
|
+
delayMs: number;
|
|
29
|
+
}) => void;
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Explicit retry helper for application code. Not wired into the client by default.
|
|
34
|
+
*
|
|
35
|
+
* Idempotency: only wrap operations that are safe to repeat (most pure generation
|
|
36
|
+
* calls are; tool side effects are not unless the application makes them idempotent).
|
|
37
|
+
*/
|
|
38
|
+
export declare function withRetry<T>(operation: () => Promise<T>, options?: RetryOptions): Promise<T>;
|