content-agent 1.0.3 → 1.2.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/dist/_chunks-dts/sanity-agent-provider.d.ts +2 -793
- package/dist/_chunks-dts/sanity-agent-provider.d.ts.map +1 -1
- package/dist/_chunks-dts/types.d.ts +794 -0
- package/dist/_chunks-dts/types.d.ts.map +1 -0
- package/dist/_chunks-es/utils.js +310 -0
- package/dist/_chunks-es/utils.js.map +1 -0
- package/dist/chat-transport.d.ts +90 -0
- package/dist/chat-transport.d.ts.map +1 -0
- package/dist/chat-transport.js +91 -0
- package/dist/chat-transport.js.map +1 -0
- package/dist/content-agent.d.ts +2 -1
- package/dist/content-agent.d.ts.map +1 -1
- package/dist/index.d.ts +21 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -255
- package/dist/index.js.map +1 -1
- package/dist/messages.d.ts +106 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +79 -0
- package/dist/messages.js.map +1 -0
- package/dist/react.d.ts +110 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +84 -0
- package/dist/react.js.map +1 -0
- package/package.json +25 -2
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { b as OutputFormat } from "./_chunks-dts/types.js";
|
|
2
|
+
import { UIMessage } from "ai";
|
|
3
|
+
import { Application, Context } from "@sanity/agent-types";
|
|
4
|
+
/**
|
|
5
|
+
* Wire shape the Content Agent chat route expects: `{role, content}` where
|
|
6
|
+
* content is a flattened string for text-only turns, or the raw typed parts
|
|
7
|
+
* (tool calls / results) otherwise.
|
|
8
|
+
*
|
|
9
|
+
* @category Messages
|
|
10
|
+
*/
|
|
11
|
+
interface WireMessage {
|
|
12
|
+
id: string;
|
|
13
|
+
role: UIMessage['role'];
|
|
14
|
+
content: string | Array<Record<string, unknown>>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Convert an AI SDK `UIMessage` into the Content Agent wire shape. Text-only
|
|
18
|
+
* messages collapse to a single string; anything with tool parts passes the
|
|
19
|
+
* parts array through.
|
|
20
|
+
*
|
|
21
|
+
* @category Messages
|
|
22
|
+
*/
|
|
23
|
+
declare function toWireMessage(message: UIMessage): WireMessage;
|
|
24
|
+
/**
|
|
25
|
+
* Join a message's `text` parts into a single string. Separate text parts are
|
|
26
|
+
* delimited with a blank line so an inline directive followed by prose stays
|
|
27
|
+
* parseable.
|
|
28
|
+
*
|
|
29
|
+
* @category Messages
|
|
30
|
+
*/
|
|
31
|
+
declare function uiMessageToText(message: UIMessage): string;
|
|
32
|
+
/**
|
|
33
|
+
* Concatenate the agent's reasoning summary from `data-agent-status` stream
|
|
34
|
+
* parts. Returns `undefined` when the message carries no reasoning.
|
|
35
|
+
*
|
|
36
|
+
* @category Messages
|
|
37
|
+
*/
|
|
38
|
+
declare function getReasoningText(message: UIMessage): string | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* A persisted thread turn loaded from `GET /threads/:id`, ready to seed into
|
|
41
|
+
* `chat.messages`.
|
|
42
|
+
*
|
|
43
|
+
* @category Messages
|
|
44
|
+
*/
|
|
45
|
+
interface HistoryMessage {
|
|
46
|
+
id: string;
|
|
47
|
+
role: 'user' | 'assistant';
|
|
48
|
+
content: string;
|
|
49
|
+
metadata?: unknown;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Convert persisted thread history into `UIMessage`s for seeding. The directive
|
|
53
|
+
* text is kept as a single text part so {@link uiMessageToText} round-trips it.
|
|
54
|
+
*
|
|
55
|
+
* @category Messages
|
|
56
|
+
*/
|
|
57
|
+
declare function historyToUiMessages(messages: HistoryMessage[]): UIMessage[];
|
|
58
|
+
/**
|
|
59
|
+
* Merge persisted history (`seed`, ordered) with the live SDK messages.
|
|
60
|
+
*
|
|
61
|
+
* History and a resumed stream are complementary: after a reload mid-stream the
|
|
62
|
+
* resumed stream carries the assistant turn while only history has the user
|
|
63
|
+
* message. Merging by id keeps both. History order is preserved; for ids in
|
|
64
|
+
* both, the live object is kept (so the SDK keeps writing to the same message
|
|
65
|
+
* reference); live-only messages are appended.
|
|
66
|
+
*
|
|
67
|
+
* @category Messages
|
|
68
|
+
*/
|
|
69
|
+
declare function mergeMessagesById<UI_MESSAGE extends UIMessage>(seed: UI_MESSAGE[], live: UI_MESSAGE[]): UI_MESSAGE[];
|
|
70
|
+
/**
|
|
71
|
+
* Options for {@link buildSendBody}.
|
|
72
|
+
*
|
|
73
|
+
* @category Messages
|
|
74
|
+
*/
|
|
75
|
+
interface BuildSendBodyOptions {
|
|
76
|
+
/** The conversation messages from `useChat`; only the last is sent. */
|
|
77
|
+
messages: UIMessage[];
|
|
78
|
+
/** Base body the SDK already assembled (id, trigger, etc.) to spread. */
|
|
79
|
+
body?: Record<string, unknown>;
|
|
80
|
+
application?: Application;
|
|
81
|
+
context?: Context;
|
|
82
|
+
format?: OutputFormat;
|
|
83
|
+
clientId?: string;
|
|
84
|
+
/** Defaults to `true` — the route streams over SSE. */
|
|
85
|
+
stream?: boolean;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Build the Content Agent chat request body for `prepareSendMessagesRequest`.
|
|
89
|
+
*
|
|
90
|
+
* Sends only the last turn (the backend persists history and appends it),
|
|
91
|
+
* wire-shaped via {@link toWireMessage}, plus the routing fields the route
|
|
92
|
+
* understands. Empty `context` is omitted so it isn't sent as noise.
|
|
93
|
+
*
|
|
94
|
+
* @category Messages
|
|
95
|
+
*/
|
|
96
|
+
declare function buildSendBody({
|
|
97
|
+
messages,
|
|
98
|
+
body,
|
|
99
|
+
application,
|
|
100
|
+
context,
|
|
101
|
+
format,
|
|
102
|
+
clientId,
|
|
103
|
+
stream
|
|
104
|
+
}: BuildSendBodyOptions): Record<string, unknown>;
|
|
105
|
+
export { type BuildSendBodyOptions, type HistoryMessage, type WireMessage, buildSendBody, getReasoningText, historyToUiMessages, mergeMessagesById, toWireMessage, uiMessageToText };
|
|
106
|
+
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.d.ts","names":[],"sources":["../src/_internal/messages.ts"],"mappings":";;;;AAWA;;;;;;UAAiB,WAAA;EACf,EAAA;EACA,IAAA,EAAM,SAAA;EACN,OAAA,WAAkB,KAAA,CAAM,MAAA;AAAA;;;;;;AAU1B;;iBAAgB,aAAA,CAAc,OAAA,EAAS,SAAA,GAAY,WAAA;;;;;;;AA0BnD;iBAAgB,eAAA,CAAgB,OAAA,EAAS,SAAA;;;;AAkBzC;;;iBAAgB,gBAAA,CAAiB,OAAA,EAAS,SAAA;;AAiB1C;;;;;UAAiB,cAAA;EACf,EAAA;EACA,IAAA;EACA,OAAA;EACA,QAAA;AAAA;;;;;;;iBASc,mBAAA,CAAoB,QAAA,EAAU,cAAA,KAAmB,SAAA;;AAoBjE;;;;;;;;;;iBAAgB,iBAAA,oBAAqC,SAAA,CAAA,CACnD,IAAA,EAAM,UAAA,IACN,IAAA,EAAM,UAAA,KACL,UAAA;;;;;;UAsBc,oBAAA;EAtBJ;EAwBX,QAAA,EAAU,SAAA;EAFyB;EAInC,IAAA,GAAO,MAAA;EACP,WAAA,GAAc,WAAA;EACd,OAAA,GAAU,OAAA;EACV,MAAA,GAAS,YAAA;EACT,QAAA;EADS;EAGT,MAAA;AAAA;;;;;;;;;;iBAYc,aAAA,CAAA;EACd,QAAA;EACA,IAAA;EACA,WAAA;EACA,OAAA;EACA,MAAA;EACA,QAAA;EACA;AAAA,GACC,oBAAA,GAAuB,MAAA"}
|
package/dist/messages.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
function toWireMessage(message) {
|
|
2
|
+
const parts = message.parts ?? [];
|
|
3
|
+
if (!parts.some((p) => p.type !== "text")) {
|
|
4
|
+
const text = parts.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
5
|
+
return { id: message.id, role: message.role, content: text };
|
|
6
|
+
}
|
|
7
|
+
return {
|
|
8
|
+
id: message.id,
|
|
9
|
+
role: message.role,
|
|
10
|
+
content: parts
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function uiMessageToText(message) {
|
|
14
|
+
const parts = message.parts ?? [];
|
|
15
|
+
let out = "";
|
|
16
|
+
for (const part of parts)
|
|
17
|
+
part.type === "text" && typeof part.text == "string" && (out.length > 0 && !/\s$/.test(out) && !/^\s/.test(part.text) && (out += `
|
|
18
|
+
|
|
19
|
+
`), out += part.text);
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
function getReasoningText(message) {
|
|
23
|
+
const parts = message.parts ?? [];
|
|
24
|
+
let out = "";
|
|
25
|
+
for (const part of parts) {
|
|
26
|
+
if (part.type !== "data-agent-status") continue;
|
|
27
|
+
const text = part.data?.text;
|
|
28
|
+
typeof text == "string" && (out += text);
|
|
29
|
+
}
|
|
30
|
+
return out === "" ? void 0 : out;
|
|
31
|
+
}
|
|
32
|
+
function historyToUiMessages(messages) {
|
|
33
|
+
return messages.map((message) => ({
|
|
34
|
+
id: message.id,
|
|
35
|
+
role: message.role,
|
|
36
|
+
parts: message.content ? [{ type: "text", text: message.content }] : [],
|
|
37
|
+
...message.metadata !== void 0 && { metadata: message.metadata }
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
function mergeMessagesById(seed, live) {
|
|
41
|
+
if (live.length === 0) return seed;
|
|
42
|
+
const liveById = new Map(live.map((message) => [message.id, message])), seen = /* @__PURE__ */ new Set(), merged = [];
|
|
43
|
+
for (const message of seed)
|
|
44
|
+
merged.push(liveById.get(message.id) ?? message), seen.add(message.id);
|
|
45
|
+
for (const message of live)
|
|
46
|
+
seen.has(message.id) || merged.push(message);
|
|
47
|
+
return merged;
|
|
48
|
+
}
|
|
49
|
+
function buildSendBody({
|
|
50
|
+
messages,
|
|
51
|
+
body,
|
|
52
|
+
application,
|
|
53
|
+
context,
|
|
54
|
+
format,
|
|
55
|
+
clientId,
|
|
56
|
+
stream = !0
|
|
57
|
+
}) {
|
|
58
|
+
return {
|
|
59
|
+
...body,
|
|
60
|
+
messages: messages.slice(-1).map(toWireMessage),
|
|
61
|
+
...application && { application },
|
|
62
|
+
...context && hasContext(context) && { context },
|
|
63
|
+
...format && { format },
|
|
64
|
+
...clientId && { clientId },
|
|
65
|
+
stream
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function hasContext(context) {
|
|
69
|
+
return Object.values(context).some((value) => value != null);
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
buildSendBody,
|
|
73
|
+
getReasoningText,
|
|
74
|
+
historyToUiMessages,
|
|
75
|
+
mergeMessagesById,
|
|
76
|
+
toWireMessage,
|
|
77
|
+
uiMessageToText
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.js","sources":["../src/_internal/messages.ts"],"sourcesContent":["import type { Application, Context } from '@sanity/agent-types'\nimport type { UIMessage } from 'ai'\nimport type { OutputFormat } from '../types'\n\n/**\n * Wire shape the Content Agent chat route expects: `{role, content}` where\n * content is a flattened string for text-only turns, or the raw typed parts\n * (tool calls / results) otherwise.\n *\n * @category Messages\n */\nexport interface WireMessage {\n id: string\n role: UIMessage['role']\n content: string | Array<Record<string, unknown>>\n}\n\n/**\n * Convert an AI SDK `UIMessage` into the Content Agent wire shape. Text-only\n * messages collapse to a single string; anything with tool parts passes the\n * parts array through.\n *\n * @category Messages\n */\nexport function toWireMessage(message: UIMessage): WireMessage {\n const parts = message.parts ?? []\n const hasNonText = parts.some((p) => p.type !== 'text')\n\n if (!hasNonText) {\n const text = parts\n .filter((p): p is Extract<UIMessage['parts'][number], { type: 'text' }> => p.type === 'text')\n .map((p) => p.text)\n .join('')\n return { id: message.id, role: message.role, content: text }\n }\n\n return {\n id: message.id,\n role: message.role,\n content: parts as Array<Record<string, unknown>>,\n }\n}\n\n/**\n * Join a message's `text` parts into a single string. Separate text parts are\n * delimited with a blank line so an inline directive followed by prose stays\n * parseable.\n *\n * @category Messages\n */\nexport function uiMessageToText(message: UIMessage): string {\n const parts = message.parts ?? []\n let out = ''\n for (const part of parts) {\n if (part.type === 'text' && typeof part.text === 'string') {\n if (out.length > 0 && !/\\s$/.test(out) && !/^\\s/.test(part.text)) out += '\\n\\n'\n out += part.text\n }\n }\n return out\n}\n\n/**\n * Concatenate the agent's reasoning summary from `data-agent-status` stream\n * parts. Returns `undefined` when the message carries no reasoning.\n *\n * @category Messages\n */\nexport function getReasoningText(message: UIMessage): string | undefined {\n const parts = message.parts ?? []\n let out = ''\n for (const part of parts) {\n if (part.type !== 'data-agent-status') continue\n const text = (part as { data?: { text?: unknown } }).data?.text\n if (typeof text === 'string') out += text\n }\n return out === '' ? undefined : out\n}\n\n/**\n * A persisted thread turn loaded from `GET /threads/:id`, ready to seed into\n * `chat.messages`.\n *\n * @category Messages\n */\nexport interface HistoryMessage {\n id: string\n role: 'user' | 'assistant'\n content: string\n metadata?: unknown\n}\n\n/**\n * Convert persisted thread history into `UIMessage`s for seeding. The directive\n * text is kept as a single text part so {@link uiMessageToText} round-trips it.\n *\n * @category Messages\n */\nexport function historyToUiMessages(messages: HistoryMessage[]): UIMessage[] {\n return messages.map((message) => ({\n id: message.id,\n role: message.role,\n parts: message.content ? [{ type: 'text', text: message.content }] : [],\n ...(message.metadata !== undefined && { metadata: message.metadata }),\n }))\n}\n\n/**\n * Merge persisted history (`seed`, ordered) with the live SDK messages.\n *\n * History and a resumed stream are complementary: after a reload mid-stream the\n * resumed stream carries the assistant turn while only history has the user\n * message. Merging by id keeps both. History order is preserved; for ids in\n * both, the live object is kept (so the SDK keeps writing to the same message\n * reference); live-only messages are appended.\n *\n * @category Messages\n */\nexport function mergeMessagesById<UI_MESSAGE extends UIMessage>(\n seed: UI_MESSAGE[],\n live: UI_MESSAGE[],\n): UI_MESSAGE[] {\n if (live.length === 0) return seed\n\n const liveById = new Map(live.map((message) => [message.id, message]))\n const seen = new Set<string>()\n const merged: UI_MESSAGE[] = []\n\n for (const message of seed) {\n merged.push(liveById.get(message.id) ?? message)\n seen.add(message.id)\n }\n for (const message of live) {\n if (!seen.has(message.id)) merged.push(message)\n }\n return merged\n}\n\n/**\n * Options for {@link buildSendBody}.\n *\n * @category Messages\n */\nexport interface BuildSendBodyOptions {\n /** The conversation messages from `useChat`; only the last is sent. */\n messages: UIMessage[]\n /** Base body the SDK already assembled (id, trigger, etc.) to spread. */\n body?: Record<string, unknown>\n application?: Application\n context?: Context\n format?: OutputFormat\n clientId?: string\n /** Defaults to `true` — the route streams over SSE. */\n stream?: boolean\n}\n\n/**\n * Build the Content Agent chat request body for `prepareSendMessagesRequest`.\n *\n * Sends only the last turn (the backend persists history and appends it),\n * wire-shaped via {@link toWireMessage}, plus the routing fields the route\n * understands. Empty `context` is omitted so it isn't sent as noise.\n *\n * @category Messages\n */\nexport function buildSendBody({\n messages,\n body,\n application,\n context,\n format,\n clientId,\n stream = true,\n}: BuildSendBodyOptions): Record<string, unknown> {\n return {\n ...body,\n messages: messages.slice(-1).map(toWireMessage),\n ...(application && { application }),\n ...(context && hasContext(context) && { context }),\n ...(format && { format }),\n ...(clientId && { clientId }),\n stream,\n }\n}\n\nfunction hasContext(context: Context): boolean {\n return Object.values(context).some((value) => value !== undefined && value !== null)\n}\n"],"names":[],"mappings":"AAwBO,SAAS,cAAc,SAAiC;AAC7D,QAAM,QAAQ,QAAQ,SAAS,CAAA;AAG/B,MAAI,CAFe,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,GAErC;AACf,UAAM,OAAO,MACV,OAAO,CAAC,MAAkE,EAAE,SAAS,MAAM,EAC3F,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,EAAE;AACV,WAAO,EAAE,IAAI,QAAQ,IAAI,MAAM,QAAQ,MAAM,SAAS,KAAA;AAAA,EACxD;AAEA,SAAO;AAAA,IACL,IAAI,QAAQ;AAAA,IACZ,MAAM,QAAQ;AAAA,IACd,SAAS;AAAA,EAAA;AAEb;AASO,SAAS,gBAAgB,SAA4B;AAC1D,QAAM,QAAQ,QAAQ,SAAS,CAAA;AAC/B,MAAI,MAAM;AACV,aAAW,QAAQ;AACb,SAAK,SAAS,UAAU,OAAO,KAAK,QAAS,aAC3C,IAAI,SAAS,KAAK,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,KAAK,KAAK,IAAI,MAAG,OAAO;AAAA;AAAA,IACzE,OAAO,KAAK;AAGhB,SAAO;AACT;AAQO,SAAS,iBAAiB,SAAwC;AACvE,QAAM,QAAQ,QAAQ,SAAS,CAAA;AAC/B,MAAI,MAAM;AACV,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,SAAS,oBAAqB;AACvC,UAAM,OAAQ,KAAuC,MAAM;AACvD,WAAO,QAAS,aAAU,OAAO;AAAA,EACvC;AACA,SAAO,QAAQ,KAAK,SAAY;AAClC;AAqBO,SAAS,oBAAoB,UAAyC;AAC3E,SAAO,SAAS,IAAI,CAAC,aAAa;AAAA,IAChC,IAAI,QAAQ;AAAA,IACZ,MAAM,QAAQ;AAAA,IACd,OAAO,QAAQ,UAAU,CAAC,EAAE,MAAM,QAAQ,MAAM,QAAQ,QAAA,CAAS,IAAI,CAAA;AAAA,IACrE,GAAI,QAAQ,aAAa,UAAa,EAAE,UAAU,QAAQ,SAAA;AAAA,EAAS,EACnE;AACJ;AAaO,SAAS,kBACd,MACA,MACc;AACd,MAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,QAAM,WAAW,IAAI,IAAI,KAAK,IAAI,CAAC,YAAY,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC,GAC/D,2BAAW,IAAA,GACX,SAAuB,CAAA;AAE7B,aAAW,WAAW;AACpB,WAAO,KAAK,SAAS,IAAI,QAAQ,EAAE,KAAK,OAAO,GAC/C,KAAK,IAAI,QAAQ,EAAE;AAErB,aAAW,WAAW;AACf,SAAK,IAAI,QAAQ,EAAE,KAAG,OAAO,KAAK,OAAO;AAEhD,SAAO;AACT;AA6BO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AACX,GAAkD;AAChD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU,SAAS,MAAM,EAAE,EAAE,IAAI,aAAa;AAAA,IAC9C,GAAI,eAAe,EAAE,YAAA;AAAA,IACrB,GAAI,WAAW,WAAW,OAAO,KAAK,EAAE,QAAA;AAAA,IACxC,GAAI,UAAU,EAAE,OAAA;AAAA,IAChB,GAAI,YAAY,EAAE,SAAA;AAAA,IAClB;AAAA,EAAA;AAEJ;AAEA,SAAS,WAAW,SAA2B;AAC7C,SAAO,OAAO,OAAO,OAAO,EAAE,KAAK,CAAC,UAAiC,SAAU,IAAI;AACrF;"}
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { b as OutputFormat } from "./_chunks-dts/types.js";
|
|
2
|
+
import { UIMessage } from "ai";
|
|
3
|
+
import { Application, Context } from "@sanity/agent-types";
|
|
4
|
+
import { UseChatHelpers, UseChatOptions } from "@ai-sdk/react";
|
|
5
|
+
/** `useChat` options that {@link useContentAgentChat} owns; the rest pass through. */
|
|
6
|
+
type ManagedChatOptions = 'id' | 'transport' | 'resume' | 'messages' | 'onError' | 'onFinish' | 'onData';
|
|
7
|
+
/** A value, or a getter resolved at send time (avoids stale closures). */
|
|
8
|
+
type Resolvable<T> = T | (() => T | undefined);
|
|
9
|
+
/**
|
|
10
|
+
* Options for {@link useContentAgentChat}.
|
|
11
|
+
*
|
|
12
|
+
* @category React
|
|
13
|
+
*/
|
|
14
|
+
interface UseContentAgentChatOptions<UI_MESSAGE extends UIMessage = UIMessage> {
|
|
15
|
+
/** Sanity organization ID. When undefined, no transport is built. */
|
|
16
|
+
organizationId: string | undefined;
|
|
17
|
+
/** Stable thread id. When undefined, no transport is built. */
|
|
18
|
+
threadId: string | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Base URL for the Sanity API.
|
|
21
|
+
* @default 'https://api.sanity.io'
|
|
22
|
+
*/
|
|
23
|
+
baseURL?: string;
|
|
24
|
+
/** API version segment, e.g. `'v2026-01-12'`. */
|
|
25
|
+
apiVersion?: string;
|
|
26
|
+
/** Bearer token, or a getter read at request time. */
|
|
27
|
+
token?: string | (() => string | undefined);
|
|
28
|
+
/** Target application; pass a getter to read it fresh on each turn. */
|
|
29
|
+
application?: Resolvable<Application>;
|
|
30
|
+
/** Per-turn request context; pass a getter to read it fresh on each turn. */
|
|
31
|
+
context?: Resolvable<Context>;
|
|
32
|
+
/** Directive output format (`'directives'` for custom client rendering). */
|
|
33
|
+
format?: OutputFormat;
|
|
34
|
+
/** Identifies the creating client (e.g. `'dashboard'`). */
|
|
35
|
+
clientId?: string;
|
|
36
|
+
/**
|
|
37
|
+
* When true, reconnect to an in-flight stream once per thread (page reload
|
|
38
|
+
* or thread switch). The SDK's `resume: true` only fires on first mount, so
|
|
39
|
+
* this hook drives resume per (Chat x threadId) pair instead.
|
|
40
|
+
*/
|
|
41
|
+
autoResume?: boolean;
|
|
42
|
+
/** Initial messages (e.g. server-rendered history). */
|
|
43
|
+
messages?: UI_MESSAGE[];
|
|
44
|
+
onError?: (error: Error) => void;
|
|
45
|
+
onFinish?: () => void;
|
|
46
|
+
onData?: (dataPart: {
|
|
47
|
+
type: string;
|
|
48
|
+
data: unknown;
|
|
49
|
+
}) => void;
|
|
50
|
+
/**
|
|
51
|
+
* Any other `useChat` options to forward (e.g. `onToolCall`, `generateId`,
|
|
52
|
+
* `experimental_throttle`). The options this hook manages (transport, id,
|
|
53
|
+
* resume, messages, the callbacks above) take precedence.
|
|
54
|
+
*/
|
|
55
|
+
chatOptions?: Omit<UseChatOptions<UI_MESSAGE>, ManagedChatOptions>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Options for {@link useSanityChatResume}.
|
|
59
|
+
*
|
|
60
|
+
* @category React
|
|
61
|
+
*/
|
|
62
|
+
interface UseSanityChatResumeOptions {
|
|
63
|
+
/**
|
|
64
|
+
* When true, reconnect to an in-flight stream once per thread (page reload
|
|
65
|
+
* or thread switch). The SDK's `resume: true` only fires on first mount, so
|
|
66
|
+
* this drives resume per (Chat x threadId) pair instead.
|
|
67
|
+
*/
|
|
68
|
+
autoResume?: boolean;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Add Sanity resume semantics to a `useChat` instance you own: reconnect to an
|
|
72
|
+
* in-flight stream once per thread, and abort the previous Chat's stream when
|
|
73
|
+
* the thread changes. Use this when you need full control of the `useChat`
|
|
74
|
+
* call; {@link useContentAgentChat} composes it for the turnkey path.
|
|
75
|
+
*
|
|
76
|
+
* @category React
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```tsx
|
|
80
|
+
* const transport = useMemo(() => createSanityChatTransport({ ... }), [...])
|
|
81
|
+
* const chat = useChat({ id: threadId, transport, onToolCall })
|
|
82
|
+
* useSanityChatResume(chat, { autoResume: threadExistsOnBackend })
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
declare function useSanityChatResume<UI_MESSAGE extends UIMessage>(chat: Pick<UseChatHelpers<UI_MESSAGE>, 'id' | 'status' | 'stop' | 'resumeStream'>, options?: UseSanityChatResumeOptions): void;
|
|
86
|
+
/**
|
|
87
|
+
* `useChat` wired to the Sanity Content Agent: transport with bearer auth and
|
|
88
|
+
* transparent resume, per-turn body shaping (last message wire-shaped, plus
|
|
89
|
+
* application/context/format/clientId), `x-request-id` idempotency, resume on
|
|
90
|
+
* thread change, and stream cleanup when the thread changes.
|
|
91
|
+
*
|
|
92
|
+
* Returns the standard `useChat` helpers, so messages, status, sendMessage,
|
|
93
|
+
* stop, resumeStream, and setMessages all behave exactly as upstream.
|
|
94
|
+
*
|
|
95
|
+
* @category React
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```tsx
|
|
99
|
+
* const chat = useContentAgentChat({
|
|
100
|
+
* organizationId,
|
|
101
|
+
* threadId,
|
|
102
|
+
* token: () => client.config().token,
|
|
103
|
+
* application,
|
|
104
|
+
* autoResume: threadExistsOnBackend,
|
|
105
|
+
* })
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
declare function useContentAgentChat<UI_MESSAGE extends UIMessage = UIMessage>(options: UseContentAgentChatOptions<UI_MESSAGE>): UseChatHelpers<UI_MESSAGE>;
|
|
109
|
+
export { UseContentAgentChatOptions, UseSanityChatResumeOptions, useContentAgentChat, useSanityChatResume };
|
|
110
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","names":[],"sources":["../src/react.ts"],"mappings":";;;;;KASK,kBAAA;;KAUA,UAAA,MAAgB,CAAA,UAAW,CAAA;;;AAVT;;;UAiBN,0BAAA,oBAA8C,SAAA,GAAY,SAAA;EAP3D;EASd,cAAA;EAT8B;EAW9B,QAAA;EAX+B;AAOjC;;;EASE,OAAA;EATyE;EAWzE,UAAA;EAIc;EAFd,KAAA;EAIU;EAFV,WAAA,GAAc,UAAA,CAAW,WAAA;EAcd;EAZX,OAAA,GAAU,UAAA,CAAW,OAAA;EAqBa;EAnBlC,MAAA,GAAS,YAAA;EAmBsC;EAjB/C,QAAA;EAiBkB;;;;;EAXlB,UAAA;EAvBA;EAyBA,QAAA,GAAW,UAAA;EACX,OAAA,IAAW,KAAA,EAAO,KAAA;EAClB,QAAA;EACA,MAAA,IAAU,QAAA;IAAY,IAAA;IAAc,IAAA;EAAA;EAf1B;;;;;EAqBV,WAAA,GAAc,IAAA,CAAK,cAAA,CAAe,UAAA,GAAa,kBAAA;AAAA;;;;;;UAQhC,0BAAA;EAdO;;;;;EAoBtB,UAAA;AAAA;;;;AANF;;;;;AAwBA;;;;;;;iBAAgB,mBAAA,oBAAuC,SAAA,CAAA,CACrD,IAAA,EAAM,IAAA,CAAK,cAAA,CAAe,UAAA,+CAC1B,OAAA,GAAU,0BAAA;;;;;;;;;;;;;AA8CZ;;;;;;;;;;iBAAgB,mBAAA,oBAAuC,SAAA,GAAY,SAAA,CAAA,CACjE,OAAA,EAAS,0BAAA,CAA2B,UAAA,IACnC,cAAA,CAAe,UAAA"}
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { useChat } from "@ai-sdk/react";
|
|
2
|
+
import { useRef, useMemo, useEffect } from "react";
|
|
3
|
+
import { createSanityChatTransport } from "./chat-transport.js";
|
|
4
|
+
import { buildSendBody } from "./messages.js";
|
|
5
|
+
function useSanityChatResume(chat, options) {
|
|
6
|
+
const { autoResume = !1 } = options ?? {}, { id: threadId, status, stop, resumeStream } = chat;
|
|
7
|
+
useEffect(() => () => {
|
|
8
|
+
stop().catch(() => {
|
|
9
|
+
});
|
|
10
|
+
}, [stop]);
|
|
11
|
+
const resumeEvaluatedForRef = useRef(void 0);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
!autoResume || !threadId || status === "ready" && resumeEvaluatedForRef.current !== threadId && (resumeEvaluatedForRef.current = threadId, resumeStream());
|
|
14
|
+
}, [autoResume, threadId, status, resumeStream]);
|
|
15
|
+
}
|
|
16
|
+
function useContentAgentChat(options) {
|
|
17
|
+
const {
|
|
18
|
+
organizationId,
|
|
19
|
+
threadId,
|
|
20
|
+
baseURL,
|
|
21
|
+
apiVersion,
|
|
22
|
+
token,
|
|
23
|
+
application,
|
|
24
|
+
context,
|
|
25
|
+
format,
|
|
26
|
+
clientId,
|
|
27
|
+
autoResume = !1,
|
|
28
|
+
messages,
|
|
29
|
+
onError,
|
|
30
|
+
onFinish,
|
|
31
|
+
onData
|
|
32
|
+
} = options, latest = useRef({ token, application, context, format, clientId });
|
|
33
|
+
latest.current = { token, application, context, format, clientId };
|
|
34
|
+
const transport = useMemo(() => {
|
|
35
|
+
if (!(!organizationId || !threadId))
|
|
36
|
+
return createSanityChatTransport({
|
|
37
|
+
organizationId,
|
|
38
|
+
threadId,
|
|
39
|
+
baseURL,
|
|
40
|
+
apiVersion,
|
|
41
|
+
token: () => resolve(latest.current.token),
|
|
42
|
+
prepareSendMessagesRequest: ({ messages: turnMessages, body, headers }) => {
|
|
43
|
+
const current = latest.current;
|
|
44
|
+
return {
|
|
45
|
+
headers: withRequestId(headers, turnMessages),
|
|
46
|
+
body: buildSendBody({
|
|
47
|
+
messages: turnMessages,
|
|
48
|
+
body,
|
|
49
|
+
application: resolve(current.application),
|
|
50
|
+
context: resolve(current.context),
|
|
51
|
+
format: current.format,
|
|
52
|
+
clientId: current.clientId
|
|
53
|
+
})
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}, [organizationId, threadId, baseURL, apiVersion]), chat = useChat({
|
|
58
|
+
...options.chatOptions,
|
|
59
|
+
id: threadId,
|
|
60
|
+
transport,
|
|
61
|
+
resume: !1,
|
|
62
|
+
messages,
|
|
63
|
+
onError,
|
|
64
|
+
onFinish,
|
|
65
|
+
onData
|
|
66
|
+
});
|
|
67
|
+
return useSanityChatResume(chat, { autoResume }), chat;
|
|
68
|
+
}
|
|
69
|
+
function resolve(value) {
|
|
70
|
+
return typeof value == "function" ? value() : value;
|
|
71
|
+
}
|
|
72
|
+
function withRequestId(headers, messages) {
|
|
73
|
+
const merged = {};
|
|
74
|
+
new Headers(headers).forEach((value, key) => {
|
|
75
|
+
merged[key] = value;
|
|
76
|
+
});
|
|
77
|
+
const lastUser = [...messages].reverse().find((m) => m.role === "user");
|
|
78
|
+
return lastUser && (merged["x-request-id"] = lastUser.id), merged;
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
useContentAgentChat,
|
|
82
|
+
useSanityChatResume
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","sources":["../src/react.ts"],"sourcesContent":["import { type UseChatHelpers, type UseChatOptions, useChat } from '@ai-sdk/react'\nimport type { Application, Context } from '@sanity/agent-types'\nimport type { UIMessage } from 'ai'\nimport { useEffect, useMemo, useRef } from 'react'\nimport { createSanityChatTransport } from './_internal/chat-transport'\nimport { buildSendBody } from './_internal/messages'\nimport type { OutputFormat } from './types'\n\n/** `useChat` options that {@link useContentAgentChat} owns; the rest pass through. */\ntype ManagedChatOptions =\n | 'id'\n | 'transport'\n | 'resume'\n | 'messages'\n | 'onError'\n | 'onFinish'\n | 'onData'\n\n/** A value, or a getter resolved at send time (avoids stale closures). */\ntype Resolvable<T> = T | (() => T | undefined)\n\n/**\n * Options for {@link useContentAgentChat}.\n *\n * @category React\n */\nexport interface UseContentAgentChatOptions<UI_MESSAGE extends UIMessage = UIMessage> {\n /** Sanity organization ID. When undefined, no transport is built. */\n organizationId: string | undefined\n /** Stable thread id. When undefined, no transport is built. */\n threadId: string | undefined\n /**\n * Base URL for the Sanity API.\n * @default 'https://api.sanity.io'\n */\n baseURL?: string\n /** API version segment, e.g. `'v2026-01-12'`. */\n apiVersion?: string\n /** Bearer token, or a getter read at request time. */\n token?: string | (() => string | undefined)\n /** Target application; pass a getter to read it fresh on each turn. */\n application?: Resolvable<Application>\n /** Per-turn request context; pass a getter to read it fresh on each turn. */\n context?: Resolvable<Context>\n /** Directive output format (`'directives'` for custom client rendering). */\n format?: OutputFormat\n /** Identifies the creating client (e.g. `'dashboard'`). */\n clientId?: string\n /**\n * When true, reconnect to an in-flight stream once per thread (page reload\n * or thread switch). The SDK's `resume: true` only fires on first mount, so\n * this hook drives resume per (Chat x threadId) pair instead.\n */\n autoResume?: boolean\n /** Initial messages (e.g. server-rendered history). */\n messages?: UI_MESSAGE[]\n onError?: (error: Error) => void\n onFinish?: () => void\n onData?: (dataPart: { type: string; data: unknown }) => void\n /**\n * Any other `useChat` options to forward (e.g. `onToolCall`, `generateId`,\n * `experimental_throttle`). The options this hook manages (transport, id,\n * resume, messages, the callbacks above) take precedence.\n */\n chatOptions?: Omit<UseChatOptions<UI_MESSAGE>, ManagedChatOptions>\n}\n\n/**\n * Options for {@link useSanityChatResume}.\n *\n * @category React\n */\nexport interface UseSanityChatResumeOptions {\n /**\n * When true, reconnect to an in-flight stream once per thread (page reload\n * or thread switch). The SDK's `resume: true` only fires on first mount, so\n * this drives resume per (Chat x threadId) pair instead.\n */\n autoResume?: boolean\n}\n\n/**\n * Add Sanity resume semantics to a `useChat` instance you own: reconnect to an\n * in-flight stream once per thread, and abort the previous Chat's stream when\n * the thread changes. Use this when you need full control of the `useChat`\n * call; {@link useContentAgentChat} composes it for the turnkey path.\n *\n * @category React\n *\n * @example\n * ```tsx\n * const transport = useMemo(() => createSanityChatTransport({ ... }), [...])\n * const chat = useChat({ id: threadId, transport, onToolCall })\n * useSanityChatResume(chat, { autoResume: threadExistsOnBackend })\n * ```\n */\nexport function useSanityChatResume<UI_MESSAGE extends UIMessage>(\n chat: Pick<UseChatHelpers<UI_MESSAGE>, 'id' | 'status' | 'stop' | 'resumeStream'>,\n options?: UseSanityChatResumeOptions,\n): void {\n const { autoResume = false } = options ?? {}\n const { id: threadId, status, stop, resumeStream } = chat\n\n // Stop the previous Chat when the thread changes. The SDK recreates the Chat\n // on `id` change but leaves the old fetch running; the cleanup closure\n // captures the prior `stop`, so it aborts the OLD Chat.\n useEffect(() => {\n return () => void stop().catch(() => {})\n }, [stop])\n\n // Resume any in-flight stream once per (Chat x threadId). Skipped unless idle\n // so a concurrent send and resume don't collide.\n const resumeEvaluatedForRef = useRef<string | undefined>(undefined)\n useEffect(() => {\n if (!autoResume || !threadId) return\n if (status !== 'ready') return\n if (resumeEvaluatedForRef.current === threadId) return\n resumeEvaluatedForRef.current = threadId\n void resumeStream()\n }, [autoResume, threadId, status, resumeStream])\n}\n\n/**\n * `useChat` wired to the Sanity Content Agent: transport with bearer auth and\n * transparent resume, per-turn body shaping (last message wire-shaped, plus\n * application/context/format/clientId), `x-request-id` idempotency, resume on\n * thread change, and stream cleanup when the thread changes.\n *\n * Returns the standard `useChat` helpers, so messages, status, sendMessage,\n * stop, resumeStream, and setMessages all behave exactly as upstream.\n *\n * @category React\n *\n * @example\n * ```tsx\n * const chat = useContentAgentChat({\n * organizationId,\n * threadId,\n * token: () => client.config().token,\n * application,\n * autoResume: threadExistsOnBackend,\n * })\n * ```\n */\nexport function useContentAgentChat<UI_MESSAGE extends UIMessage = UIMessage>(\n options: UseContentAgentChatOptions<UI_MESSAGE>,\n): UseChatHelpers<UI_MESSAGE> {\n const {\n organizationId,\n threadId,\n baseURL,\n apiVersion,\n token,\n application,\n context,\n format,\n clientId,\n autoResume = false,\n messages,\n onError,\n onFinish,\n onData,\n } = options\n\n // Per-turn fields are read fresh on each send via a latest-ref so the\n // transport (and the Chat behind it) only rebuilds on URL identity, never\n // when the token refreshes or the user switches application/context.\n const latest = useRef({ token, application, context, format, clientId })\n latest.current = { token, application, context, format, clientId }\n\n const transport = useMemo(() => {\n if (!organizationId || !threadId) return undefined\n\n return createSanityChatTransport<UI_MESSAGE>({\n organizationId,\n threadId,\n baseURL,\n apiVersion,\n token: () => resolve(latest.current.token),\n prepareSendMessagesRequest: ({ messages: turnMessages, body, headers }) => {\n const current = latest.current\n return {\n headers: withRequestId(headers, turnMessages),\n body: buildSendBody({\n messages: turnMessages,\n body,\n application: resolve(current.application),\n context: resolve(current.context),\n format: current.format,\n clientId: current.clientId,\n }),\n }\n },\n })\n }, [organizationId, threadId, baseURL, apiVersion])\n\n const chat = useChat<UI_MESSAGE>({\n ...options.chatOptions,\n id: threadId,\n transport,\n resume: false,\n messages,\n onError,\n onFinish,\n onData,\n })\n\n useSanityChatResume(chat, { autoResume })\n\n return chat\n}\n\nfunction resolve<T>(value: Resolvable<T> | undefined): T | undefined {\n return typeof value === 'function' ? (value as () => T | undefined)() : value\n}\n\n/** Spread the SDK's base headers and stamp `x-request-id` from the last user\n * turn so the optimistic SDK message and the server share one id. */\nfunction withRequestId(headers: HeadersInit | undefined, messages: UIMessage[]): HeadersInit {\n const merged: Record<string, string> = {}\n new Headers(headers).forEach((value, key) => {\n merged[key] = value\n })\n const lastUser = [...messages].reverse().find((m) => m.role === 'user')\n if (lastUser) merged['x-request-id'] = lastUser.id\n return merged\n}\n"],"names":[],"mappings":";;;;AAgGO,SAAS,oBACd,MACA,SACM;AACN,QAAM,EAAE,aAAa,GAAA,IAAU,WAAW,CAAA,GACpC,EAAE,IAAI,UAAU,QAAQ,MAAM,iBAAiB;AAKrD,YAAU,MACD,MAAG;AAAQ,SAAA,EAAO,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EAAA,GACtC,CAAC,IAAI,CAAC;AAIT,QAAM,wBAAwB,OAA2B,MAAS;AAClE,YAAU,MAAM;AACV,KAAC,cAAc,CAAC,YAChB,WAAW,WACX,sBAAsB,YAAY,aACtC,sBAAsB,UAAU,UAC3B,aAAA;AAAA,EACP,GAAG,CAAC,YAAY,UAAU,QAAQ,YAAY,CAAC;AACjD;AAwBO,SAAS,oBACd,SAC4B;AAC5B,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACE,SAKE,SAAS,OAAO,EAAE,OAAO,aAAa,SAAS,QAAQ,UAAU;AACvE,SAAO,UAAU,EAAE,OAAO,aAAa,SAAS,QAAQ,SAAA;AAExD,QAAM,YAAY,QAAQ,MAAM;AAC9B,QAAI,EAAA,CAAC,kBAAkB,CAAC;AAExB,aAAO,0BAAsC;AAAA,QAC3C;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,MAAM,QAAQ,OAAO,QAAQ,KAAK;AAAA,QACzC,4BAA4B,CAAC,EAAE,UAAU,cAAc,MAAM,cAAc;AACzE,gBAAM,UAAU,OAAO;AACvB,iBAAO;AAAA,YACL,SAAS,cAAc,SAAS,YAAY;AAAA,YAC5C,MAAM,cAAc;AAAA,cAClB,UAAU;AAAA,cACV;AAAA,cACA,aAAa,QAAQ,QAAQ,WAAW;AAAA,cACxC,SAAS,QAAQ,QAAQ,OAAO;AAAA,cAChC,QAAQ,QAAQ;AAAA,cAChB,UAAU,QAAQ;AAAA,YAAA,CACnB;AAAA,UAAA;AAAA,QAEL;AAAA,MAAA,CACD;AAAA,EACH,GAAG,CAAC,gBAAgB,UAAU,SAAS,UAAU,CAAC,GAE5C,OAAO,QAAoB;AAAA,IAC/B,GAAG,QAAQ;AAAA,IACX,IAAI;AAAA,IACJ;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,CACD;AAED,SAAA,oBAAoB,MAAM,EAAE,WAAA,CAAY,GAEjC;AACT;AAEA,SAAS,QAAW,OAAiD;AACnE,SAAO,OAAO,SAAU,aAAc,MAAA,IAAkC;AAC1E;AAIA,SAAS,cAAc,SAAkC,UAAoC;AAC3F,QAAM,SAAiC,CAAA;AACvC,MAAI,QAAQ,OAAO,EAAE,QAAQ,CAAC,OAAO,QAAQ;AAC3C,WAAO,GAAG,IAAI;AAAA,EAChB,CAAC;AACD,QAAM,WAAW,CAAC,GAAG,QAAQ,EAAE,QAAA,EAAU,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AACtE,SAAI,aAAU,OAAO,cAAc,IAAI,SAAS,KACzC;AACT;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "content-agent",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Vercel AI SDK provider for Sanity Content Agent API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -23,6 +23,15 @@
|
|
|
23
23
|
"./agent": {
|
|
24
24
|
"default": "./dist/content-agent.js"
|
|
25
25
|
},
|
|
26
|
+
"./transport": {
|
|
27
|
+
"default": "./dist/chat-transport.js"
|
|
28
|
+
},
|
|
29
|
+
"./messages": {
|
|
30
|
+
"default": "./dist/messages.js"
|
|
31
|
+
},
|
|
32
|
+
"./react": {
|
|
33
|
+
"default": "./dist/react.js"
|
|
34
|
+
},
|
|
26
35
|
"./package.json": "./package.json"
|
|
27
36
|
},
|
|
28
37
|
"types": "./dist/index.d.ts",
|
|
@@ -37,10 +46,16 @@
|
|
|
37
46
|
"@sanity/agent-types": "0.1.4"
|
|
38
47
|
},
|
|
39
48
|
"devDependencies": {
|
|
49
|
+
"@ai-sdk/react": "^3.0.0",
|
|
40
50
|
"@sanity/pkg-utils": "^10.4.1",
|
|
51
|
+
"@testing-library/react": "^16.0.0",
|
|
41
52
|
"@types/node": "^22.19.7",
|
|
53
|
+
"@types/react": "^19.0.0",
|
|
42
54
|
"ai": "^6.0.168",
|
|
55
|
+
"jsdom": "^26.0.0",
|
|
43
56
|
"openapi-typescript": "^7.10.1",
|
|
57
|
+
"react": "^19.0.0",
|
|
58
|
+
"react-dom": "^19.0.0",
|
|
44
59
|
"typedoc": "^0.28.17",
|
|
45
60
|
"typescript": "^5.9.3",
|
|
46
61
|
"vitest": "^4.0.18",
|
|
@@ -48,11 +63,19 @@
|
|
|
48
63
|
"@repo/tsconfig": "0.0.0"
|
|
49
64
|
},
|
|
50
65
|
"peerDependencies": {
|
|
51
|
-
"ai": ">=
|
|
66
|
+
"@ai-sdk/react": ">=3.0.0",
|
|
67
|
+
"ai": ">=6.0.0",
|
|
68
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
52
69
|
},
|
|
53
70
|
"peerDependenciesMeta": {
|
|
71
|
+
"@ai-sdk/react": {
|
|
72
|
+
"optional": true
|
|
73
|
+
},
|
|
54
74
|
"ai": {
|
|
55
75
|
"optional": true
|
|
76
|
+
},
|
|
77
|
+
"react": {
|
|
78
|
+
"optional": true
|
|
56
79
|
}
|
|
57
80
|
},
|
|
58
81
|
"publishConfig": {
|