@tanstack/ai 0.23.0 → 0.24.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/README.md +1 -1
- package/dist/esm/activities/chat/index.d.ts +33 -9
- package/dist/esm/activities/chat/index.js +19 -9
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.js +2 -1
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/middleware/compose.d.ts +14 -14
- package/dist/esm/activities/chat/middleware/compose.js.map +1 -1
- package/dist/esm/activities/chat/middleware/types.d.ts +16 -16
- package/dist/esm/activities/chat/runtime-context-types.d.ts +43 -0
- package/dist/esm/activities/chat/stream/message-updaters.d.ts +2 -2
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +1 -0
- package/dist/esm/activities/chat/stream/processor.js +35 -12
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/tools/schema-converter.js +10 -3
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +15 -5
- package/dist/esm/activities/chat/tools/tool-calls.js +59 -19
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-definition.d.ts +12 -8
- package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -1
- package/dist/esm/activities/error-payload.d.ts +26 -0
- package/dist/esm/activities/error-payload.js +12 -1
- package/dist/esm/activities/error-payload.js.map +1 -1
- package/dist/esm/adapter-internals.d.ts +1 -1
- package/dist/esm/adapter-internals.js +3 -2
- package/dist/esm/client.d.ts +1 -1
- package/dist/esm/client.js +3 -1
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +7 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/tool-registry.d.ts +7 -7
- package/dist/esm/tool-registry.js +1 -1
- package/dist/esm/tool-registry.js.map +1 -1
- package/dist/esm/types.d.ts +40 -8
- package/dist/esm/utilities/ag-ui-wire.js +1 -1
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/chat-params.d.ts +8 -3
- package/dist/esm/utilities/chat-params.js +6 -2
- package/dist/esm/utilities/chat-params.js.map +1 -1
- package/dist/esm/utilities/tool-result.d.ts +21 -0
- package/dist/esm/utilities/tool-result.js +37 -0
- package/dist/esm/utilities/tool-result.js.map +1 -0
- package/package.json +3 -2
- package/src/activities/chat/index.ts +219 -47
- package/src/activities/chat/messages.ts +2 -1
- package/src/activities/chat/middleware/compose.ts +23 -17
- package/src/activities/chat/middleware/types.ts +16 -16
- package/src/activities/chat/runtime-context-types.ts +68 -0
- package/src/activities/chat/stream/message-updaters.ts +2 -1
- package/src/activities/chat/stream/processor.ts +48 -8
- package/src/activities/chat/tools/schema-converter.ts +32 -14
- package/src/activities/chat/tools/tool-calls.ts +138 -43
- package/src/activities/chat/tools/tool-definition.ts +25 -31
- package/src/activities/error-payload.ts +44 -0
- package/src/adapter-internals.ts +4 -1
- package/src/client.ts +5 -1
- package/src/index.ts +7 -0
- package/src/tool-registry.ts +16 -14
- package/src/types.ts +86 -29
- package/src/utilities/ag-ui-wire.ts +4 -1
- package/src/utilities/chat-params.ts +22 -7
- package/src/utilities/tool-result.ts +60 -0
|
@@ -34,7 +34,7 @@ export type ChatMiddlewarePhase =
|
|
|
34
34
|
* Stable context object passed to all middleware hooks.
|
|
35
35
|
* Created once per chat() invocation and shared across all hooks.
|
|
36
36
|
*/
|
|
37
|
-
export interface ChatMiddlewareContext {
|
|
37
|
+
export interface ChatMiddlewareContext<TContext = unknown> {
|
|
38
38
|
/** Unique identifier for this chat request */
|
|
39
39
|
requestId: string
|
|
40
40
|
/** Unique identifier for this stream */
|
|
@@ -64,8 +64,8 @@ export interface ChatMiddlewareContext {
|
|
|
64
64
|
signal?: AbortSignal
|
|
65
65
|
/** Abort the chat run with a reason */
|
|
66
66
|
abort: (reason?: string) => void
|
|
67
|
-
/**
|
|
68
|
-
context:
|
|
67
|
+
/** Runtime context provided by chat() options */
|
|
68
|
+
context: TContext
|
|
69
69
|
/**
|
|
70
70
|
* Defer a non-blocking side-effect promise.
|
|
71
71
|
* Deferred promises do not block streaming and are awaited
|
|
@@ -343,7 +343,7 @@ export interface ErrorInfo {
|
|
|
343
343
|
* }
|
|
344
344
|
* ```
|
|
345
345
|
*/
|
|
346
|
-
export interface ChatMiddleware {
|
|
346
|
+
export interface ChatMiddleware<TContext = unknown> {
|
|
347
347
|
/** Optional name for debugging and identification */
|
|
348
348
|
name?: string
|
|
349
349
|
|
|
@@ -355,7 +355,7 @@ export interface ChatMiddleware {
|
|
|
355
355
|
* Only the fields you return are overwritten — everything else is preserved.
|
|
356
356
|
*/
|
|
357
357
|
onConfig?: (
|
|
358
|
-
ctx: ChatMiddlewareContext
|
|
358
|
+
ctx: ChatMiddlewareContext<TContext>,
|
|
359
359
|
config: ChatMiddlewareConfig,
|
|
360
360
|
) =>
|
|
361
361
|
| void
|
|
@@ -379,7 +379,7 @@ export interface ChatMiddleware {
|
|
|
379
379
|
* outputSchema or apply structured-output-specific behavior.
|
|
380
380
|
*/
|
|
381
381
|
onStructuredOutputConfig?: (
|
|
382
|
-
ctx: ChatMiddlewareContext
|
|
382
|
+
ctx: ChatMiddlewareContext<TContext>,
|
|
383
383
|
config: StructuredOutputMiddlewareConfig,
|
|
384
384
|
) =>
|
|
385
385
|
| void
|
|
@@ -390,14 +390,14 @@ export interface ChatMiddleware {
|
|
|
390
390
|
/**
|
|
391
391
|
* Called when the chat run starts (after initial onConfig).
|
|
392
392
|
*/
|
|
393
|
-
onStart?: (ctx: ChatMiddlewareContext) => void | Promise<void>
|
|
393
|
+
onStart?: (ctx: ChatMiddlewareContext<TContext>) => void | Promise<void>
|
|
394
394
|
|
|
395
395
|
/**
|
|
396
396
|
* Called at the start of each agent loop iteration, after a new assistant message ID
|
|
397
397
|
* is created. Use this to observe iteration boundaries.
|
|
398
398
|
*/
|
|
399
399
|
onIteration?: (
|
|
400
|
-
ctx: ChatMiddlewareContext
|
|
400
|
+
ctx: ChatMiddlewareContext<TContext>,
|
|
401
401
|
info: IterationInfo,
|
|
402
402
|
) => void | Promise<void>
|
|
403
403
|
|
|
@@ -408,7 +408,7 @@ export interface ChatMiddleware {
|
|
|
408
408
|
* @returns void (pass through), chunk (replace), chunk[] (expand), null (drop)
|
|
409
409
|
*/
|
|
410
410
|
onChunk?: (
|
|
411
|
-
ctx: ChatMiddlewareContext
|
|
411
|
+
ctx: ChatMiddlewareContext<TContext>,
|
|
412
412
|
chunk: StreamChunk,
|
|
413
413
|
) =>
|
|
414
414
|
| void
|
|
@@ -422,7 +422,7 @@ export interface ChatMiddleware {
|
|
|
422
422
|
* Can observe, transform args, skip execution, or abort the run.
|
|
423
423
|
*/
|
|
424
424
|
onBeforeToolCall?: (
|
|
425
|
-
ctx: ChatMiddlewareContext
|
|
425
|
+
ctx: ChatMiddlewareContext<TContext>,
|
|
426
426
|
hookCtx: ToolCallHookContext,
|
|
427
427
|
) => BeforeToolCallDecision | Promise<BeforeToolCallDecision>
|
|
428
428
|
|
|
@@ -430,7 +430,7 @@ export interface ChatMiddleware {
|
|
|
430
430
|
* Called after a tool execution completes (success or failure).
|
|
431
431
|
*/
|
|
432
432
|
onAfterToolCall?: (
|
|
433
|
-
ctx: ChatMiddlewareContext
|
|
433
|
+
ctx: ChatMiddlewareContext<TContext>,
|
|
434
434
|
info: AfterToolCallInfo,
|
|
435
435
|
) => void | Promise<void>
|
|
436
436
|
|
|
@@ -439,7 +439,7 @@ export interface ChatMiddleware {
|
|
|
439
439
|
* Provides aggregate data about tool execution results, approvals, and client tools.
|
|
440
440
|
*/
|
|
441
441
|
onToolPhaseComplete?: (
|
|
442
|
-
ctx: ChatMiddlewareContext
|
|
442
|
+
ctx: ChatMiddlewareContext<TContext>,
|
|
443
443
|
info: ToolPhaseCompleteInfo,
|
|
444
444
|
) => void | Promise<void>
|
|
445
445
|
|
|
@@ -448,7 +448,7 @@ export interface ChatMiddleware {
|
|
|
448
448
|
* Called once per model iteration that reports usage.
|
|
449
449
|
*/
|
|
450
450
|
onUsage?: (
|
|
451
|
-
ctx: ChatMiddlewareContext
|
|
451
|
+
ctx: ChatMiddlewareContext<TContext>,
|
|
452
452
|
usage: UsageInfo,
|
|
453
453
|
) => void | Promise<void>
|
|
454
454
|
|
|
@@ -457,7 +457,7 @@ export interface ChatMiddleware {
|
|
|
457
457
|
* Exactly one of onFinish/onAbort/onError will be called per run.
|
|
458
458
|
*/
|
|
459
459
|
onFinish?: (
|
|
460
|
-
ctx: ChatMiddlewareContext
|
|
460
|
+
ctx: ChatMiddlewareContext<TContext>,
|
|
461
461
|
info: FinishInfo,
|
|
462
462
|
) => void | Promise<void>
|
|
463
463
|
|
|
@@ -466,7 +466,7 @@ export interface ChatMiddleware {
|
|
|
466
466
|
* Exactly one of onFinish/onAbort/onError will be called per run.
|
|
467
467
|
*/
|
|
468
468
|
onAbort?: (
|
|
469
|
-
ctx: ChatMiddlewareContext
|
|
469
|
+
ctx: ChatMiddlewareContext<TContext>,
|
|
470
470
|
info: AbortInfo,
|
|
471
471
|
) => void | Promise<void>
|
|
472
472
|
|
|
@@ -475,7 +475,7 @@ export interface ChatMiddleware {
|
|
|
475
475
|
* Exactly one of onFinish/onAbort/onError will be called per run.
|
|
476
476
|
*/
|
|
477
477
|
onError?: (
|
|
478
|
-
ctx: ChatMiddlewareContext
|
|
478
|
+
ctx: ChatMiddlewareContext<TContext>,
|
|
479
479
|
info: ErrorInfo,
|
|
480
480
|
) => void | Promise<void>
|
|
481
481
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ChatMiddleware } from './middleware/types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared type-level helpers for inferring the runtime `context` requirement
|
|
5
|
+
* from typed tools and middleware.
|
|
6
|
+
*
|
|
7
|
+
* These primitives are consumed by both the chat activity options
|
|
8
|
+
* (`./index.ts`, which merges tool + middleware requirements) and the tool
|
|
9
|
+
* execution layer (`./tools/tool-calls.ts`, which only sees tools). They live
|
|
10
|
+
* here so the two call sites share one definition instead of maintaining
|
|
11
|
+
* divergent copies.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** True only when `T` is exactly `unknown`. */
|
|
15
|
+
type IsUnknown<T> = unknown extends T
|
|
16
|
+
? [T] extends [unknown]
|
|
17
|
+
? true
|
|
18
|
+
: false
|
|
19
|
+
: false
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Drops an `unknown` context requirement to `never` so that untyped tools and
|
|
23
|
+
* middleware (which default `TContext` to `unknown`) contribute no requirement
|
|
24
|
+
* to the merged context.
|
|
25
|
+
*/
|
|
26
|
+
type KnownContext<T> = IsUnknown<T> extends true ? never : T
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Merge two inferred context requirements, treating `never` as "no
|
|
30
|
+
* requirement". Using this instead of a raw intersection keeps a `never`
|
|
31
|
+
* (untyped) contributor from collapsing the whole merge to `never`.
|
|
32
|
+
*/
|
|
33
|
+
export type MergeContext<TLeft, TRight> = [TLeft] extends [never]
|
|
34
|
+
? TRight
|
|
35
|
+
: [TRight] extends [never]
|
|
36
|
+
? TLeft
|
|
37
|
+
: TLeft & TRight
|
|
38
|
+
|
|
39
|
+
/** Collapse a union of context requirements into their intersection. */
|
|
40
|
+
export type UnionToIntersection<T> = [T] extends [never]
|
|
41
|
+
? never
|
|
42
|
+
: (T extends unknown ? (value: T) => void : never) extends (
|
|
43
|
+
value: infer TIntersection,
|
|
44
|
+
) => void
|
|
45
|
+
? TIntersection
|
|
46
|
+
: never
|
|
47
|
+
|
|
48
|
+
/** Strip `undefined` from a context requirement. */
|
|
49
|
+
export type DefinedContext<T> = Exclude<T, undefined>
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Extract the `context` requirement declared by a tool execute function's
|
|
53
|
+
* second argument, dropping `unknown` (untyped) contexts to `never`.
|
|
54
|
+
*/
|
|
55
|
+
type ContextFromExecute<T> = T extends (...args: any) => any
|
|
56
|
+
? NonNullable<Parameters<T>[1]> extends { context: infer TUserContext }
|
|
57
|
+
? KnownContext<TUserContext>
|
|
58
|
+
: never
|
|
59
|
+
: never
|
|
60
|
+
|
|
61
|
+
/** Extract the context requirement declared by a single tool. */
|
|
62
|
+
export type ContextFromTool<T> = T extends { execute?: infer TExecute }
|
|
63
|
+
? ContextFromExecute<TExecute>
|
|
64
|
+
: never
|
|
65
|
+
|
|
66
|
+
/** Extract the context requirement declared by a single middleware. */
|
|
67
|
+
export type ContextFromMiddleware<T> =
|
|
68
|
+
T extends ChatMiddleware<infer TContext> ? KnownContext<TContext> : never
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { parsePartialJSON } from './json-parser'
|
|
9
9
|
import type {
|
|
10
|
+
ContentPart,
|
|
10
11
|
StructuredOutputPart,
|
|
11
12
|
ThinkingPart,
|
|
12
13
|
ToolCallPart,
|
|
@@ -107,7 +108,7 @@ export function updateToolResultPart(
|
|
|
107
108
|
messages: Array<UIMessage>,
|
|
108
109
|
messageId: string,
|
|
109
110
|
toolCallId: string,
|
|
110
|
-
content: string
|
|
111
|
+
content: string | Array<ContentPart>,
|
|
111
112
|
state: ToolResultState,
|
|
112
113
|
error?: string,
|
|
113
114
|
): Array<UIMessage> {
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* adapter contract, single-shot flows, and expected UIMessage output.
|
|
19
19
|
*/
|
|
20
20
|
import { generateMessageId, uiMessageToModelMessages } from '../messages.js'
|
|
21
|
+
import { normalizeToolResult } from '../../../utilities/tool-result'
|
|
21
22
|
import { defaultJSONParser } from './json-parser'
|
|
22
23
|
import {
|
|
23
24
|
appendStructuredOutputDelta,
|
|
@@ -321,7 +322,7 @@ export class StreamProcessor {
|
|
|
321
322
|
)
|
|
322
323
|
|
|
323
324
|
// Step 2: Create a tool-result part (for LLM conversation history)
|
|
324
|
-
const content =
|
|
325
|
+
const content = normalizeToolResult(output)
|
|
325
326
|
const toolResultState: ToolResultState = error ? 'error' : 'complete'
|
|
326
327
|
|
|
327
328
|
updatedMessages = updateToolResultPart(
|
|
@@ -1170,30 +1171,51 @@ export class StreamProcessor {
|
|
|
1170
1171
|
// Step 1: Update the tool-call part's output field (for UI consistency
|
|
1171
1172
|
// with client tools — see GitHub issue #176)
|
|
1172
1173
|
let output: unknown
|
|
1173
|
-
|
|
1174
|
-
output = JSON.parse(chunk.result)
|
|
1175
|
-
} catch {
|
|
1174
|
+
if (Array.isArray(chunk.result)) {
|
|
1176
1175
|
output = chunk.result
|
|
1176
|
+
} else {
|
|
1177
|
+
try {
|
|
1178
|
+
output = JSON.parse(chunk.result)
|
|
1179
|
+
} catch {
|
|
1180
|
+
output = chunk.result
|
|
1181
|
+
}
|
|
1177
1182
|
}
|
|
1178
1183
|
this.messages = updateToolCallWithOutput(
|
|
1179
1184
|
this.messages,
|
|
1180
1185
|
chunk.toolCallId,
|
|
1181
1186
|
output,
|
|
1187
|
+
chunk.state === 'output-error' ? 'input-complete' : undefined,
|
|
1182
1188
|
)
|
|
1183
1189
|
|
|
1184
1190
|
// Step 2: Create/update the tool-result part (for LLM conversation history)
|
|
1185
|
-
const resultState: ToolResultState =
|
|
1191
|
+
const resultState: ToolResultState =
|
|
1192
|
+
chunk.state === 'output-error' ? 'error' : 'complete'
|
|
1186
1193
|
this.messages = updateToolResultPart(
|
|
1187
1194
|
this.messages,
|
|
1188
1195
|
messageId,
|
|
1189
1196
|
chunk.toolCallId,
|
|
1190
1197
|
chunk.result,
|
|
1191
1198
|
resultState,
|
|
1199
|
+
resultState === 'error'
|
|
1200
|
+
? this.extractToolResultError(output)
|
|
1201
|
+
: undefined,
|
|
1192
1202
|
)
|
|
1193
1203
|
this.emitMessagesChange()
|
|
1194
1204
|
}
|
|
1195
1205
|
}
|
|
1196
1206
|
|
|
1207
|
+
private extractToolResultError(output: unknown): string {
|
|
1208
|
+
if (
|
|
1209
|
+
output &&
|
|
1210
|
+
typeof output === 'object' &&
|
|
1211
|
+
'error' in output &&
|
|
1212
|
+
typeof output.error === 'string'
|
|
1213
|
+
) {
|
|
1214
|
+
return output.error
|
|
1215
|
+
}
|
|
1216
|
+
return typeof output === 'string' ? output : 'Tool execution failed'
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1197
1219
|
/**
|
|
1198
1220
|
* Handle TOOL_CALL_RESULT event (AG-UI spec).
|
|
1199
1221
|
*
|
|
@@ -1218,16 +1240,19 @@ export class StreamProcessor {
|
|
|
1218
1240
|
this.messages,
|
|
1219
1241
|
chunk.toolCallId,
|
|
1220
1242
|
output,
|
|
1243
|
+
chunk.state === 'output-error' ? 'input-complete' : undefined,
|
|
1221
1244
|
)
|
|
1222
1245
|
|
|
1223
1246
|
// Step 2: Create/update the tool-result part
|
|
1224
|
-
const resultState: ToolResultState =
|
|
1247
|
+
const resultState: ToolResultState =
|
|
1248
|
+
chunk.state === 'output-error' ? 'error' : 'complete'
|
|
1225
1249
|
this.messages = updateToolResultPart(
|
|
1226
1250
|
this.messages,
|
|
1227
1251
|
messageId,
|
|
1228
1252
|
chunk.toolCallId,
|
|
1229
1253
|
chunk.content,
|
|
1230
1254
|
resultState,
|
|
1255
|
+
resultState === 'error' ? this.extractToolResultError(output) : undefined,
|
|
1231
1256
|
)
|
|
1232
1257
|
this.emitMessagesChange()
|
|
1233
1258
|
}
|
|
@@ -1274,7 +1299,10 @@ export class StreamProcessor {
|
|
|
1274
1299
|
chunk: Extract<StreamChunk, { type: 'RUN_ERROR' }>,
|
|
1275
1300
|
): void {
|
|
1276
1301
|
this.hasError = true
|
|
1277
|
-
const runId =
|
|
1302
|
+
const runId =
|
|
1303
|
+
'runId' in chunk && typeof chunk.runId === 'string'
|
|
1304
|
+
? chunk.runId
|
|
1305
|
+
: undefined
|
|
1278
1306
|
if (runId) {
|
|
1279
1307
|
this.activeRuns.delete(runId)
|
|
1280
1308
|
} else {
|
|
@@ -1305,7 +1333,19 @@ export class StreamProcessor {
|
|
|
1305
1333
|
this.emitMessagesChange()
|
|
1306
1334
|
}
|
|
1307
1335
|
|
|
1308
|
-
|
|
1336
|
+
// Attach the provider's structured error body (`rawEvent`) and `code` to
|
|
1337
|
+
// the surfaced Error so consumers can recover the upstream detail that the
|
|
1338
|
+
// RUN_ERROR's `message` alone discards. Both are optional and added only
|
|
1339
|
+
// when present, keeping the Error backward compatible.
|
|
1340
|
+
const error = new Error(errorMessage)
|
|
1341
|
+
const code = chunk.code ?? chunk.error?.code
|
|
1342
|
+
if (code !== undefined) {
|
|
1343
|
+
Object.assign(error, { code })
|
|
1344
|
+
}
|
|
1345
|
+
if (chunk.rawEvent !== undefined) {
|
|
1346
|
+
Object.assign(error, { rawEvent: chunk.rawEvent })
|
|
1347
|
+
}
|
|
1348
|
+
this.events.onError?.(error)
|
|
1309
1349
|
}
|
|
1310
1350
|
|
|
1311
1351
|
/**
|
|
@@ -24,6 +24,20 @@ function toJsonSchema(obj: object): JSONSchema {
|
|
|
24
24
|
return result
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Whether a value can carry a `~standard` property. Most schema libraries
|
|
29
|
+
* (Zod, Valibot) return plain objects, but ArkType's `type()` returns a
|
|
30
|
+
* *callable function* with `~standard` attached — so `typeof` must accept
|
|
31
|
+
* both `'object'` and `'function'` or ArkType schemas are missed entirely
|
|
32
|
+
* (issue #276).
|
|
33
|
+
*/
|
|
34
|
+
function isPropertyCarrier(schema: unknown): schema is Record<string, unknown> {
|
|
35
|
+
return (
|
|
36
|
+
(typeof schema === 'object' || typeof schema === 'function') &&
|
|
37
|
+
schema !== null
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
27
41
|
/**
|
|
28
42
|
* Check if a value is a Standard JSON Schema compliant schema.
|
|
29
43
|
* Standard JSON Schema compliant libraries (Zod v4+, ArkType, Valibot with toStandardJsonSchema, etc.)
|
|
@@ -32,18 +46,23 @@ function toJsonSchema(obj: object): JSONSchema {
|
|
|
32
46
|
export function isStandardJSONSchema(
|
|
33
47
|
schema: unknown,
|
|
34
48
|
): schema is StandardJSONSchemaV1 {
|
|
35
|
-
return
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
typeof
|
|
40
|
-
|
|
41
|
-
(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
typeof
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
if (!isPropertyCarrier(schema) || !('~standard' in schema)) return false
|
|
50
|
+
|
|
51
|
+
const standard = schema['~standard']
|
|
52
|
+
if (
|
|
53
|
+
typeof standard !== 'object' ||
|
|
54
|
+
standard === null ||
|
|
55
|
+
!('version' in standard) ||
|
|
56
|
+
standard.version !== 1 ||
|
|
57
|
+
!('jsonSchema' in standard) ||
|
|
58
|
+
typeof standard.jsonSchema !== 'object' ||
|
|
59
|
+
standard.jsonSchema === null ||
|
|
60
|
+
!('input' in standard.jsonSchema)
|
|
61
|
+
) {
|
|
62
|
+
return false
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return typeof standard.jsonSchema.input === 'function'
|
|
47
66
|
}
|
|
48
67
|
|
|
49
68
|
/**
|
|
@@ -52,8 +71,7 @@ export function isStandardJSONSchema(
|
|
|
52
71
|
*/
|
|
53
72
|
export function isStandardSchema(schema: unknown): schema is StandardSchemaV1 {
|
|
54
73
|
return (
|
|
55
|
-
|
|
56
|
-
schema !== null &&
|
|
74
|
+
isPropertyCarrier(schema) &&
|
|
57
75
|
'~standard' in schema &&
|
|
58
76
|
typeof schema['~standard'] === 'object' &&
|
|
59
77
|
schema['~standard'] !== null &&
|