@savantoai/ai-sdk 2.1.0 → 3.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.
- package/CHANGELOG.md +206 -0
- package/README.md +17 -2
- package/dist/index.cjs +194 -127
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1672 -117
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1672 -117
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +190 -128
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -9
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@savantoai/ai-sdk` will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and we follow [semantic versioning](https://semver.org/) — see _Versioning policy_
|
|
7
|
+
below for the one nuance that applies to a generated SDK.
|
|
8
|
+
|
|
9
|
+
## Versioning policy
|
|
10
|
+
|
|
11
|
+
This SDK is fully regenerated from `cloud/openapi.json` by
|
|
12
|
+
[`@hey-api/openapi-ts`](https://github.com/hey-api/openapi-ts). Generator and
|
|
13
|
+
schema changes can _both_ produce TypeScript-only breaking changes (e.g. a
|
|
14
|
+
field gains `| null`, a `body` shape narrows, a top-level helper type
|
|
15
|
+
widens) without changing any runtime behaviour. We treat those as breaking
|
|
16
|
+
under semver, meaning:
|
|
17
|
+
|
|
18
|
+
- A change that **narrows** a previously-accepted type (e.g. record →
|
|
19
|
+
concrete interface) is a major version bump.
|
|
20
|
+
- A change that **widens** a previously-non-nullable type to include `null`
|
|
21
|
+
is a major version bump.
|
|
22
|
+
- Generator-driven changes to top-level re-exports (`Client`, `Config`,
|
|
23
|
+
`Options`, `RequestResult`, `RequestOptions`) are major version bumps.
|
|
24
|
+
- Pure additions (new endpoints, new optional fields on requests,
|
|
25
|
+
newly-exported types) are minor.
|
|
26
|
+
- Internal regen with no public-surface diff is patch.
|
|
27
|
+
|
|
28
|
+
`@hey-api/openapi-ts` is pinned to `~0.97.x` (patch range only) in
|
|
29
|
+
`package.json` so generator-driven type narrowings can't slip in via a
|
|
30
|
+
caret update. Bumping that range is itself a major-version event for the
|
|
31
|
+
SDK.
|
|
32
|
+
|
|
33
|
+
## 3.1.0 — 2026-05-19
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- Search responses may include `query.truncated` and `query.originalLength` on
|
|
38
|
+
product and post search when the input text was shortened server-side.
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- **`POST /recommendations`** response type now uses the standard
|
|
43
|
+
`{ object, requestId, data }` envelope (`object: "recommendations"`).
|
|
44
|
+
Payload fields remain under `data`.
|
|
45
|
+
- **OpenAPI alignment** for non-streaming `POST /chat` and `POST /threads/search`
|
|
46
|
+
(documented envelopes; chat wire format unchanged if you already read `data`).
|
|
47
|
+
- **`POST /threads/search`** list field is `data.items` in generated types (matches
|
|
48
|
+
the handler; replaces any `results` naming in older spec snapshots).
|
|
49
|
+
|
|
50
|
+
### Breaking (TypeScript)
|
|
51
|
+
|
|
52
|
+
- **`Product.stockStatus` and `Product.type`** are strict enums. Values outside
|
|
53
|
+
`instock | outofstock | onbackorder` and `simple | grouped | external | variable`
|
|
54
|
+
are omitted at runtime and absent from the type.
|
|
55
|
+
- Any client code that assumed recommendations returned only `{ data: T }` at the
|
|
56
|
+
top level should use the generated `PostRecommendationsResponse` type (includes
|
|
57
|
+
`object` and `requestId`).
|
|
58
|
+
|
|
59
|
+
## Unreleased
|
|
60
|
+
|
|
61
|
+
### Breaking — streaming chat protocol
|
|
62
|
+
|
|
63
|
+
> The SDK's TypeScript surface is unchanged, but the **wire protocol** for
|
|
64
|
+
> the `/chat` streaming endpoint has been rewritten. Any client code that
|
|
65
|
+
> switches on `chunk.type` (including code generated against earlier
|
|
66
|
+
> versions of this README's example) must be migrated. The SDK is not
|
|
67
|
+
> under semver for the wire protocol — see _Versioning policy_ above —
|
|
68
|
+
> but we're flagging this prominently because real client switches will
|
|
69
|
+
> silently stop matching after this rollout.
|
|
70
|
+
|
|
71
|
+
The `/chat` streaming protocol has been rewritten to a block-based shape.
|
|
72
|
+
The legacy `text_delta`, `product`, `post`, `post_delta`, and `bubble_termination`
|
|
73
|
+
chunk types are gone; the new types are `block_start`, `block_delta`, `block_data`,
|
|
74
|
+
`item_delta`, and `block_end`, plus existing flow-control chunks (`progress`,
|
|
75
|
+
`prompts`, `metadata`, `complete`, `error`, `domain_offer`, `domain_offer_success`,
|
|
76
|
+
`agent_status`, `handoff_ended`, `analytics`, `usage`).
|
|
77
|
+
|
|
78
|
+
Migration cheat-sheet for code switching on `chunk.type`:
|
|
79
|
+
|
|
80
|
+
| Old chunk type | New chunk type |
|
|
81
|
+
| --------------------- | -------------------------------------------------------------- |
|
|
82
|
+
| `text_delta` | `block_delta` (read `chunk.data.content`) |
|
|
83
|
+
| `product` / `post` | `block_data` (full payload) + `block_start` (ordering) |
|
|
84
|
+
| `post_delta` | `item_delta` (read `chunk.data.field` + `chunk.data.delta`) |
|
|
85
|
+
| `bubble_termination` | (removed — single message bubble per turn now) |
|
|
86
|
+
|
|
87
|
+
The SDK's exported `ChatStreamChunk` type is intentionally unchanged
|
|
88
|
+
(`{ type: string; data?: unknown }`) — no SDK regen is required. See
|
|
89
|
+
the [Streaming Chat docs](https://savanto.ai/docs/developers/streaming)
|
|
90
|
+
for the full chunk reference and a worked React example.
|
|
91
|
+
|
|
92
|
+
The streaming `chat.message_sent` webhook payload has also picked up
|
|
93
|
+
`responseMessage.respondedBy` (which domain answered) and
|
|
94
|
+
`responseMessage.composedBlocks` (a tiny `{ type, ids }[]` describing
|
|
95
|
+
the structured blocks the composer wove together for multi-domain answers).
|
|
96
|
+
See the [Webhooks docs](https://savanto.ai/docs/developers/webhooks#chatmessage_sent).
|
|
97
|
+
|
|
98
|
+
## 3.0.0 — 2026-05-12
|
|
99
|
+
|
|
100
|
+
### Breaking (TypeScript)
|
|
101
|
+
|
|
102
|
+
- **`POST /threads/search` `sortBy` enum renamed.** Previously the SDK
|
|
103
|
+
emitted `'timestamp' | 'message_count' | 'token_count'`, but the
|
|
104
|
+
server-side handler routed those names through to OpenSearch
|
|
105
|
+
unchanged — and OpenSearch indexes those fields as `messageCount`
|
|
106
|
+
and `tokenCount`, so the snake_case values produced an invalid
|
|
107
|
+
sort clause that callers either silently ignored or got a 500 on.
|
|
108
|
+
The schema now matches the OpenSearch field names:
|
|
109
|
+
`'timestamp' | 'messageCount' | 'tokenCount'`.
|
|
110
|
+
**Migration**: switch `sortBy: 'message_count'` →
|
|
111
|
+
`sortBy: 'messageCount'`, `'token_count'` → `'tokenCount'`.
|
|
112
|
+
|
|
113
|
+
### Other
|
|
114
|
+
|
|
115
|
+
- `UpdateMcpConfigRequest` body has been reopened server-side to
|
|
116
|
+
accept arbitrary string-URL fields (`catchall(z.string().url())`),
|
|
117
|
+
so the generated SDK type now allows forward-compatible MCP URI
|
|
118
|
+
keys (e.g. a future `crmUri`) without an SDK regen. This restores
|
|
119
|
+
some of the pre-2.2.0 surface flagged in the 2.2.0 section below,
|
|
120
|
+
but with per-field URL/length validation instead of `passthrough()`.
|
|
121
|
+
|
|
122
|
+
## 2.2.0 — 2026-05-07
|
|
123
|
+
|
|
124
|
+
This release was published as a minor bump but **contains TypeScript-level
|
|
125
|
+
breaking changes** that, per the policy above, should have been a major
|
|
126
|
+
(`3.0.0`). It is documented here retroactively so consumers know to add
|
|
127
|
+
null-guards / update destructuring patterns when upgrading from `2.1.x`.
|
|
128
|
+
The next regeneration will be released as `3.0.0`.
|
|
129
|
+
|
|
130
|
+
### Breaking (TypeScript)
|
|
131
|
+
|
|
132
|
+
- **~30 fields gained `| null`.** The cloud OpenAPI emitter switched from
|
|
133
|
+
3.0 (`app.doc()`) to 3.1 (`app.doc31()`), so fields whose Zod schema
|
|
134
|
+
uses `.nullable()` now serialise as `type: [..., 'null']`, and the
|
|
135
|
+
generator faithfully reflects that with `T | null`. Affected fields
|
|
136
|
+
include:
|
|
137
|
+
- `ErrorResponse.error.param` (`string` → `string | null`)
|
|
138
|
+
- `Pagination.total` / `Pagination.cursor` (`number | null`,
|
|
139
|
+
`string | null`) — note that `total` lives on every paginated list
|
|
140
|
+
response in the SDK.
|
|
141
|
+
- `Product.price`, `Product.salePrice`, `Product.priceMin`,
|
|
142
|
+
`Product.priceMax`, `Product.weight`, `Product.dimensions`,
|
|
143
|
+
`Product.image`, `Product.attributes`, `Product.rating`, and their
|
|
144
|
+
`ProductInput.*` counterparts.
|
|
145
|
+
- `Post.publishedAt`, `Post.featuredImage`, `Post.attributes`.
|
|
146
|
+
- `TenantStatus.publishableKey`.
|
|
147
|
+
|
|
148
|
+
Consumer code like `product.price.toFixed(2)` or
|
|
149
|
+
`if (pagination.total > 0)` will fail TypeScript strict-mode typecheck.
|
|
150
|
+
**Migration**: add nullish guards or use `??` defaults:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
product.price?.toFixed(2);
|
|
154
|
+
if ((pagination.total ?? 0) > 0) { /* … */ }
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
- **Five admin/tenant request bodies narrowed from open-record to concrete
|
|
158
|
+
interface.** Cloud PR #138 replaced a `genericBody` Zod schema with six
|
|
159
|
+
typed request schemas. The regenerated SDK reflects this in:
|
|
160
|
+
- `UpdateWorkspaceData.body` → `UpdateWorkspaceRequest`
|
|
161
|
+
- `GetUploadUrlData.body` → `GetUploadUrlRequest`
|
|
162
|
+
- `UpdateMcpConfigData.body` → `UpdateMcpConfigRequest` _(reopened
|
|
163
|
+
server-side after audit #153 — see Unreleased)_
|
|
164
|
+
- `StoreCredentialsData.body` → `StoreLiveAgentCredentialsRequest`
|
|
165
|
+
- `UpdateLiveAgentScheduleData.body` →
|
|
166
|
+
`UpdateLiveAgentScheduleRequest`
|
|
167
|
+
|
|
168
|
+
Callers that were passing extra forward-compatible fields will fail
|
|
169
|
+
TypeScript typecheck. **Migration**: drop the extra fields — the cloud
|
|
170
|
+
was always ignoring them; the type just no longer admits them. (The
|
|
171
|
+
one exception, `updateMcpConfig`, has been reopened server-side; see
|
|
172
|
+
_Unreleased_.)
|
|
173
|
+
|
|
174
|
+
- **`RequestResult.request` / `response` made optional.** Generator bump
|
|
175
|
+
`@hey-api/openapi-ts` `0.94.x` → `0.97.x` changed the success branch of
|
|
176
|
+
`RequestResult` from `& { request: Request; response: Response }` to
|
|
177
|
+
`& { request?: Request; response?: Response }`. The change reflects
|
|
178
|
+
that `request` / `response` can be `undefined` if the failure happened
|
|
179
|
+
before the network call (DNS, request-building, etc.). Consumer code
|
|
180
|
+
like `const { data, response } = await chat(...); response.body` will
|
|
181
|
+
fail strict typecheck. **Migration** — either:
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
// Option A — guard with `if (response)`:
|
|
185
|
+
const { data, response } = await chat({ client, body: { … } });
|
|
186
|
+
if (response) { /* response.body, response.status, etc. */ }
|
|
187
|
+
|
|
188
|
+
// Option B — opt in to `throwOnError`, which keeps response non-optional:
|
|
189
|
+
const { data, response } = await chat({
|
|
190
|
+
client,
|
|
191
|
+
body: { … },
|
|
192
|
+
throwOnError: true,
|
|
193
|
+
});
|
|
194
|
+
response.body; // typed as `Response`, not `Response | undefined`
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Other notes
|
|
198
|
+
|
|
199
|
+
- `@hey-api/openapi-ts` was bumped from `^0.94.x` to `^0.97.1` as part of
|
|
200
|
+
this release. Subsequent versions pin to `~0.97.x` to avoid further
|
|
201
|
+
silent generator-driven type narrowings via caret updates.
|
|
202
|
+
|
|
203
|
+
## 2.1.0 and earlier
|
|
204
|
+
|
|
205
|
+
No formal changelog kept prior to 2.2.0. The git history (`sdks/javascript/`)
|
|
206
|
+
is the source of truth for older releases.
|
package/README.md
CHANGED
|
@@ -101,6 +101,9 @@ const { data: ids } = await listProductIds({ client });
|
|
|
101
101
|
```typescript
|
|
102
102
|
import { chat } from '@savantoai/ai-sdk';
|
|
103
103
|
|
|
104
|
+
// `throwOnError: true` makes `response` non-optional so `response.body` is
|
|
105
|
+
// safe to read directly. Without it (since 2.2.0) `response` is typed as
|
|
106
|
+
// `Response | undefined`. See CHANGELOG.md for details.
|
|
104
107
|
const { data, response } = await chat({
|
|
105
108
|
client,
|
|
106
109
|
body: {
|
|
@@ -108,9 +111,15 @@ const { data, response } = await chat({
|
|
|
108
111
|
threadId: 'thread-1',
|
|
109
112
|
stream: true,
|
|
110
113
|
},
|
|
114
|
+
throwOnError: true,
|
|
111
115
|
});
|
|
112
116
|
|
|
113
|
-
// For streaming (NDJSON), read the response body directly
|
|
117
|
+
// For streaming (NDJSON), read the response body directly. The protocol is
|
|
118
|
+
// block-based: text streams as `block_delta` chunks inside an active text
|
|
119
|
+
// block, structured items arrive as `block_data` keyed by item id, and
|
|
120
|
+
// per-field streaming (post summaries, product reasons, etc.) flows through
|
|
121
|
+
// `item_delta`. See https://savanto.ai/docs/developers/streaming for the
|
|
122
|
+
// full chunk-type reference.
|
|
114
123
|
const reader = response.body!.getReader();
|
|
115
124
|
const decoder = new TextDecoder();
|
|
116
125
|
|
|
@@ -120,7 +129,7 @@ while (true) {
|
|
|
120
129
|
const lines = decoder.decode(value).split('\n').filter(Boolean);
|
|
121
130
|
for (const line of lines) {
|
|
122
131
|
const chunk = JSON.parse(line);
|
|
123
|
-
if (chunk.type === '
|
|
132
|
+
if (chunk.type === 'block_delta') process.stdout.write(chunk.data.content);
|
|
124
133
|
}
|
|
125
134
|
}
|
|
126
135
|
```
|
|
@@ -266,6 +275,12 @@ Full endpoint documentation with request/response schemas:
|
|
|
266
275
|
|
|
267
276
|
**[savanto.ai/docs/api](https://savanto.ai/docs/api)**
|
|
268
277
|
|
|
278
|
+
## Versioning & changelog
|
|
279
|
+
|
|
280
|
+
See [CHANGELOG.md](./CHANGELOG.md) for per-version migration notes,
|
|
281
|
+
including the TypeScript-level breaking changes in `2.2.0`. Type
|
|
282
|
+
narrowings and generator-driven shape changes are treated as major.
|
|
283
|
+
|
|
269
284
|
## Regeneration
|
|
270
285
|
|
|
271
286
|
The SDK is auto-generated from the OpenAPI spec. To regenerate after API changes:
|