@tanstack/ai 0.51.0 → 0.52.1
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/README.md +2 -6
- package/dist/esm/activities/chat/index.js +94 -23
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/middleware/compose.js +4 -2
- package/dist/esm/activities/chat/middleware/compose.js.map +1 -1
- package/dist/esm/activities/chat/middleware/index.d.ts +2 -0
- package/dist/esm/activities/chat/middleware/metadata.d.ts +16 -0
- package/dist/esm/activities/chat/middleware/metadata.js +8 -0
- package/dist/esm/activities/chat/middleware/metadata.js.map +1 -0
- package/dist/esm/activities/chat/middleware/types.d.ts +9 -0
- package/dist/esm/activities/chat/middleware/types.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.js +1 -0
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/tools/schema-converter.js +21 -10
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +2 -1
- package/package.json +2 -2
- package/skills/ai-core/media-generation/SKILL.md +8 -5
- package/src/activities/chat/index.ts +139 -44
- package/src/activities/chat/middleware/compose.ts +14 -2
- package/src/activities/chat/middleware/index.ts +3 -0
- package/src/activities/chat/middleware/metadata.ts +20 -0
- package/src/activities/chat/middleware/types.ts +9 -0
- package/src/activities/chat/stream/processor.ts +6 -0
- package/src/activities/chat/tools/schema-converter.ts +30 -17
- package/src/index.ts +4 -0
|
@@ -67,6 +67,9 @@ export {
|
|
|
67
67
|
} from './locks'
|
|
68
68
|
export type { LockStore } from './locks'
|
|
69
69
|
|
|
70
|
+
export { MetadataCapability, getMetadata, provideMetadata } from './metadata'
|
|
71
|
+
export type { MetadataStore } from './metadata'
|
|
72
|
+
|
|
70
73
|
export {
|
|
71
74
|
isRunStatus,
|
|
72
75
|
isTerminalRunStatus,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createCapability } from './capabilities'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Namespaced key/value store for app and middleware metadata.
|
|
5
|
+
*
|
|
6
|
+
* `(namespace, key)` is the composite identity. Keep both values separate;
|
|
7
|
+
* joining them with a delimiter can create collisions.
|
|
8
|
+
*/
|
|
9
|
+
export interface MetadataStore {
|
|
10
|
+
/** Return the value for `(namespace, key)`, or `null` when it is absent. */
|
|
11
|
+
get: (namespace: string, key: string) => Promise<unknown | null>
|
|
12
|
+
/** Insert or replace the value for `(namespace, key)`. */
|
|
13
|
+
set: (namespace: string, key: string, value: unknown) => Promise<void>
|
|
14
|
+
/** Delete `(namespace, key)`. Do nothing when it is absent. */
|
|
15
|
+
delete: (namespace: string, key: string) => Promise<void>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const MetadataCapability = createCapability<MetadataStore>()('metadata')
|
|
19
|
+
|
|
20
|
+
export const [getMetadata, provideMetadata] = MetadataCapability
|
|
@@ -213,6 +213,12 @@ export interface ChatMiddlewareContext<TContext = unknown> {
|
|
|
213
213
|
signal?: AbortSignal
|
|
214
214
|
/** Abort the chat run with a reason */
|
|
215
215
|
abort: (reason?: string) => void
|
|
216
|
+
/**
|
|
217
|
+
* Push a `CUSTOM` chunk onto the chat stream immediately.
|
|
218
|
+
* The engine yields it as soon as it can (including while `onConfig`
|
|
219
|
+
* is still awaiting work such as a summarize call).
|
|
220
|
+
*/
|
|
221
|
+
emitCustomEvent: (name: string, value: Record<string, any>) => void
|
|
216
222
|
/** Runtime context provided by chat() options */
|
|
217
223
|
context: TContext
|
|
218
224
|
/**
|
|
@@ -305,7 +311,10 @@ export interface ChatMiddlewareContext<TContext = unknown> {
|
|
|
305
311
|
* that middleware is allowed to modify.
|
|
306
312
|
*/
|
|
307
313
|
export interface ChatMiddlewareConfig {
|
|
314
|
+
/** Canonical conversation history. Middleware and persistence read this. */
|
|
308
315
|
messages: Array<ModelMessage>
|
|
316
|
+
/** Provider-only context. Defaults to `messages` when it is not set. */
|
|
317
|
+
providerMessages?: Array<ModelMessage> | undefined
|
|
309
318
|
systemPrompts: Array<SystemPrompt>
|
|
310
319
|
tools: Array<Tool>
|
|
311
320
|
resume?: Array<RunAgentResumeItem> | undefined
|
|
@@ -1357,6 +1357,12 @@ export class StreamProcessor {
|
|
|
1357
1357
|
state.hasToolCallsSinceTextStart = false
|
|
1358
1358
|
}
|
|
1359
1359
|
|
|
1360
|
+
// A segment begins at its first delta, not its second. Left set, the flag
|
|
1361
|
+
// makes the second delta look like a further segment: the accumulation
|
|
1362
|
+
// resets and updateTextPart writes over the part the first delta created.
|
|
1363
|
+
// A later tool call sets it again in handleToolCallStartEvent.
|
|
1364
|
+
state.hasToolCallsSinceTextStart = false
|
|
1365
|
+
|
|
1360
1366
|
const currentText = state.currentSegmentText
|
|
1361
1367
|
const delta = chunk.delta || ''
|
|
1362
1368
|
const nextText = delta !== '' ? currentText + delta : currentText
|
|
@@ -99,6 +99,26 @@ function pruneMap(map: NullWideningMap): NullWideningMap | undefined {
|
|
|
99
99
|
return Object.keys(map).length > 0 ? map : undefined
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
function coerceArrayItems(items: JSONSchema | Array<JSONSchema>): {
|
|
103
|
+
schema: JSONSchema | Array<JSONSchema>
|
|
104
|
+
itemMap: NullWideningMap | Array<NullWideningMap> | undefined
|
|
105
|
+
} {
|
|
106
|
+
if (Array.isArray(items)) {
|
|
107
|
+
const nested = items.map((item) =>
|
|
108
|
+
makeStructuredOutputCompatible(item, item.required || []),
|
|
109
|
+
)
|
|
110
|
+
const itemMaps = nested.map((entry) => entry.nullWidening ?? {})
|
|
111
|
+
return {
|
|
112
|
+
schema: nested.map((entry) => entry.schema),
|
|
113
|
+
itemMap: itemMaps.some((entry) => Object.keys(entry).length > 0)
|
|
114
|
+
? itemMaps
|
|
115
|
+
: undefined,
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const nested = makeStructuredOutputCompatible(items, items.required || [])
|
|
119
|
+
return { schema: nested.schema, itemMap: nested.nullWidening }
|
|
120
|
+
}
|
|
121
|
+
|
|
102
122
|
/**
|
|
103
123
|
* Transform a JSON schema to be compatible with OpenAI's structured output requirements.
|
|
104
124
|
* OpenAI requires:
|
|
@@ -146,18 +166,15 @@ function makeStructuredOutputCompatible(
|
|
|
146
166
|
widenedHere = wasOptional
|
|
147
167
|
childMap = nested.nullWidening
|
|
148
168
|
} else if (prop.type === 'array' && prop.items) {
|
|
149
|
-
const
|
|
150
|
-
const nestedItems = items
|
|
151
|
-
? makeStructuredOutputCompatible(items, items.required || [])
|
|
152
|
-
: undefined
|
|
169
|
+
const nestedItems = coerceArrayItems(prop.items)
|
|
153
170
|
properties[propName] = {
|
|
154
171
|
...prop,
|
|
155
|
-
items: nestedItems
|
|
172
|
+
items: nestedItems.schema,
|
|
156
173
|
...(wasOptional ? { type: ['array', 'null'] } : {}),
|
|
157
174
|
}
|
|
158
175
|
widenedHere = wasOptional
|
|
159
|
-
childMap = nestedItems
|
|
160
|
-
? { items: nestedItems.
|
|
176
|
+
childMap = nestedItems.itemMap
|
|
177
|
+
? { items: nestedItems.itemMap }
|
|
161
178
|
: undefined
|
|
162
179
|
} else if (wasOptional) {
|
|
163
180
|
// Make optional fields nullable by adding null to the type. Mark
|
|
@@ -188,17 +205,13 @@ function makeStructuredOutputCompatible(
|
|
|
188
205
|
if (Object.keys(propertyMaps).length > 0) map.properties = propertyMaps
|
|
189
206
|
}
|
|
190
207
|
|
|
191
|
-
// Handle array
|
|
208
|
+
// Handle array item schemas. A tuple (`items: [a, b, …]`) keeps every
|
|
209
|
+
// position. A homogeneous schema stays a single items map so
|
|
210
|
+
// `undoNullWidening` applies it to every element.
|
|
192
211
|
if (result.type === 'array' && result.items) {
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
items,
|
|
197
|
-
items.required || [],
|
|
198
|
-
)
|
|
199
|
-
result.items = nestedItems.schema
|
|
200
|
-
if (nestedItems.nullWidening) map.items = nestedItems.nullWidening
|
|
201
|
-
}
|
|
212
|
+
const nestedItems = coerceArrayItems(result.items)
|
|
213
|
+
result.items = nestedItems.schema
|
|
214
|
+
if (nestedItems.itemMap) map.items = nestedItems.itemMap
|
|
202
215
|
}
|
|
203
216
|
|
|
204
217
|
return { schema: result, nullWidening: pruneMap(map) }
|
package/src/index.ts
CHANGED
|
@@ -283,6 +283,9 @@ export {
|
|
|
283
283
|
createCapability,
|
|
284
284
|
defineChatMiddleware,
|
|
285
285
|
createChatMiddleware,
|
|
286
|
+
MetadataCapability,
|
|
287
|
+
getMetadata,
|
|
288
|
+
provideMetadata,
|
|
286
289
|
} from './activities/chat/middleware/index'
|
|
287
290
|
export type {
|
|
288
291
|
Capability,
|
|
@@ -292,6 +295,7 @@ export type {
|
|
|
292
295
|
CapabilityProvider,
|
|
293
296
|
DefinedChatMiddleware,
|
|
294
297
|
AnyChatMiddleware,
|
|
298
|
+
MetadataStore,
|
|
295
299
|
} from './activities/chat/middleware/index'
|
|
296
300
|
// Locks are a distributed-mutex primitive — coordination, not chat state — and
|
|
297
301
|
// live behind their own subpath: `@tanstack/ai/locks` (see ./locks.ts).
|