@osdk/react 2.40.0 → 2.41.0-main-d24cc61b1e7fde7722d8229ed2b6821f5ce1bf8a
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 +16 -0
- package/build/browser/aip/chatStore.js +67 -0
- package/build/browser/aip/chatStore.js.map +1 -0
- package/build/browser/aip/chatStream.js +155 -0
- package/build/browser/aip/chatStream.js.map +1 -0
- package/build/browser/aip/useChat.js +243 -0
- package/build/browser/aip/useChat.js.map +1 -0
- package/build/browser/public/experimental/aip.js +18 -0
- package/build/browser/public/experimental/aip.js.map +1 -0
- package/build/browser/util/UserAgent.js +1 -1
- package/build/browser/util/UserAgent.js.map +1 -1
- package/build/cjs/{chunk-L33DWZUR.cjs → chunk-QNNQV2NH.cjs} +3 -3
- package/build/cjs/chunk-QNNQV2NH.cjs.map +1 -0
- package/build/cjs/index.cjs +15 -15
- package/build/cjs/public/experimental/aip.cjs +389 -0
- package/build/cjs/public/experimental/aip.cjs.map +1 -0
- package/build/cjs/public/experimental/aip.d.cts +83 -0
- package/build/cjs/public/experimental.cjs +16 -16
- package/build/esm/aip/chatStore.js +67 -0
- package/build/esm/aip/chatStore.js.map +1 -0
- package/build/esm/aip/chatStream.js +155 -0
- package/build/esm/aip/chatStream.js.map +1 -0
- package/build/esm/aip/useChat.js +243 -0
- package/build/esm/aip/useChat.js.map +1 -0
- package/build/esm/public/experimental/aip.js +18 -0
- package/build/esm/public/experimental/aip.js.map +1 -0
- package/build/esm/util/UserAgent.js +1 -1
- package/build/esm/util/UserAgent.js.map +1 -1
- package/build/types/aip/chatStore.d.ts +31 -0
- package/build/types/aip/chatStore.d.ts.map +1 -0
- package/build/types/aip/chatStream.d.ts +20 -0
- package/build/types/aip/chatStream.d.ts.map +1 -0
- package/build/types/aip/useChat.d.ts +79 -0
- package/build/types/aip/useChat.d.ts.map +1 -0
- package/build/types/public/experimental/aip.d.ts +4 -0
- package/build/types/public/experimental/aip.d.ts.map +1 -0
- package/experimental/aip.d.ts +17 -0
- package/package.json +22 -8
- package/build/cjs/chunk-L33DWZUR.cjs.map +0 -1
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var aipCore = require('@osdk/aip-core');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
|
|
6
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
+
|
|
8
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
9
|
+
|
|
10
|
+
// src/aip/useChat.ts
|
|
11
|
+
|
|
12
|
+
// src/aip/chatStore.ts
|
|
13
|
+
function createChatStore(options) {
|
|
14
|
+
let state = {
|
|
15
|
+
messages: options.initialMessages ?? [],
|
|
16
|
+
status: "ready",
|
|
17
|
+
error: void 0
|
|
18
|
+
};
|
|
19
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
20
|
+
const throttleMs = options.throttleMs ?? 0;
|
|
21
|
+
let pendingNotify;
|
|
22
|
+
const notifyNow = () => {
|
|
23
|
+
if (pendingNotify != null) {
|
|
24
|
+
clearTimeout(pendingNotify);
|
|
25
|
+
pendingNotify = void 0;
|
|
26
|
+
}
|
|
27
|
+
for (const s of subscribers) {
|
|
28
|
+
s();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const notifyThrottled = () => {
|
|
32
|
+
if (throttleMs <= 0) {
|
|
33
|
+
notifyNow();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (pendingNotify != null) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
pendingNotify = setTimeout(notifyNow, throttleMs);
|
|
40
|
+
};
|
|
41
|
+
return {
|
|
42
|
+
getSnapshot: () => state,
|
|
43
|
+
subscribe: (notify) => {
|
|
44
|
+
subscribers.add(notify);
|
|
45
|
+
return () => {
|
|
46
|
+
subscribers.delete(notify);
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
setState: (next) => {
|
|
50
|
+
state = typeof next === "function" ? next(state) : next;
|
|
51
|
+
notifyNow();
|
|
52
|
+
},
|
|
53
|
+
setStateThrottled: (next) => {
|
|
54
|
+
state = typeof next === "function" ? next(state) : next;
|
|
55
|
+
notifyThrottled();
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
async function runChatStream(ctx, transport, chatId, seed, trigger) {
|
|
60
|
+
ctx.abortRef.current?.abort();
|
|
61
|
+
const ctrl = new AbortController();
|
|
62
|
+
ctx.abortRef.current = ctrl;
|
|
63
|
+
ctx.stoppedRef.current = false;
|
|
64
|
+
const assistantId = aipCore.generateMessageId();
|
|
65
|
+
try {
|
|
66
|
+
const stream = await transport.sendMessages({
|
|
67
|
+
trigger,
|
|
68
|
+
chatId,
|
|
69
|
+
messageId: assistantId,
|
|
70
|
+
messages: seed.slice(),
|
|
71
|
+
abortSignal: ctrl.signal
|
|
72
|
+
});
|
|
73
|
+
await drainStream(ctx, stream, assistantId, ctrl);
|
|
74
|
+
} catch (err) {
|
|
75
|
+
handleStreamError(ctx, err, ctrl);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async function drainStream(ctx, stream, assistantMessageId, capturedCtrl) {
|
|
79
|
+
const {
|
|
80
|
+
store
|
|
81
|
+
} = ctx;
|
|
82
|
+
const reader = stream.getReader();
|
|
83
|
+
let textBuf = "";
|
|
84
|
+
const isStale = () => ctx.abortRef.current != null && ctx.abortRef.current !== capturedCtrl;
|
|
85
|
+
const isOrphaned = () => {
|
|
86
|
+
const messages = store.getSnapshot().messages;
|
|
87
|
+
return textBuf.length > 0 && !messages.some((m) => m.id === assistantMessageId);
|
|
88
|
+
};
|
|
89
|
+
try {
|
|
90
|
+
while (true) {
|
|
91
|
+
const {
|
|
92
|
+
done,
|
|
93
|
+
value
|
|
94
|
+
} = await reader.read();
|
|
95
|
+
if (done) {
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
if (isStale()) {
|
|
99
|
+
await reader.cancel();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (isOrphaned()) {
|
|
103
|
+
await reader.cancel();
|
|
104
|
+
store.setState((prev) => ({
|
|
105
|
+
...prev,
|
|
106
|
+
status: "ready"
|
|
107
|
+
}));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (value.type === "text-delta") {
|
|
111
|
+
textBuf += value.delta;
|
|
112
|
+
upsertAssistantText(store, assistantMessageId, textBuf);
|
|
113
|
+
} else if (value.type === "error") {
|
|
114
|
+
if (ctx.stoppedRef.current || capturedCtrl.signal.aborted) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
await reader.cancel();
|
|
118
|
+
throw new Error(value.errorText);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (isStale()) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
store.setState((prev) => ({
|
|
125
|
+
...prev,
|
|
126
|
+
status: "ready"
|
|
127
|
+
}));
|
|
128
|
+
const finalSnap = store.getSnapshot();
|
|
129
|
+
const finalMessage = finalSnap.messages.find((m) => m.id === assistantMessageId);
|
|
130
|
+
if (finalMessage != null && ctx.onFinish != null) {
|
|
131
|
+
ctx.onFinish({
|
|
132
|
+
message: finalMessage,
|
|
133
|
+
messages: finalSnap.messages
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
} catch (err) {
|
|
137
|
+
handleStreamError(ctx, err, capturedCtrl);
|
|
138
|
+
} finally {
|
|
139
|
+
reader.releaseLock();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function upsertAssistantText(store, assistantMessageId, text) {
|
|
143
|
+
store.setStateThrottled((prev) => {
|
|
144
|
+
const exists = prev.messages.some((m) => m.id === assistantMessageId);
|
|
145
|
+
const messages = exists ? prev.messages.map((m) => m.id === assistantMessageId ? {
|
|
146
|
+
...m,
|
|
147
|
+
parts: [{
|
|
148
|
+
type: "text",
|
|
149
|
+
text
|
|
150
|
+
}]
|
|
151
|
+
} : m) : [...prev.messages, {
|
|
152
|
+
id: assistantMessageId,
|
|
153
|
+
role: "assistant",
|
|
154
|
+
parts: [{
|
|
155
|
+
type: "text",
|
|
156
|
+
text
|
|
157
|
+
}]
|
|
158
|
+
}];
|
|
159
|
+
return {
|
|
160
|
+
...prev,
|
|
161
|
+
status: "streaming",
|
|
162
|
+
messages
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
function handleStreamError(ctx, err, capturedCtrl) {
|
|
167
|
+
if (ctx.abortRef.current != null && ctx.abortRef.current !== capturedCtrl) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
171
|
+
if (ctx.stoppedRef.current || error.name === "AbortError" || capturedCtrl.signal.aborted) {
|
|
172
|
+
ctx.store.setState((prev) => ({
|
|
173
|
+
...prev,
|
|
174
|
+
status: "ready",
|
|
175
|
+
error: void 0
|
|
176
|
+
}));
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
ctx.store.setState((prev) => ({
|
|
180
|
+
...prev,
|
|
181
|
+
status: "error",
|
|
182
|
+
error
|
|
183
|
+
}));
|
|
184
|
+
ctx.onError?.(error);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/aip/useChat.ts
|
|
188
|
+
function useChat(options) {
|
|
189
|
+
const {
|
|
190
|
+
onFinish,
|
|
191
|
+
onError
|
|
192
|
+
} = options;
|
|
193
|
+
const id = React__default.default.useMemo(() => options.id ?? aipCore.generateMessageId(), [options.id]);
|
|
194
|
+
const headersKey = JSON.stringify(options.headers ?? null);
|
|
195
|
+
const stopSequencesKey = JSON.stringify(options.stopSequences ?? null);
|
|
196
|
+
const transport = React__default.default.useMemo(
|
|
197
|
+
() => {
|
|
198
|
+
if (options.transport != null) {
|
|
199
|
+
return options.transport;
|
|
200
|
+
}
|
|
201
|
+
if (options.model == null) {
|
|
202
|
+
throw new Error("useChat: `model` is required when no `transport` is provided.");
|
|
203
|
+
}
|
|
204
|
+
const built = {
|
|
205
|
+
model: options.model,
|
|
206
|
+
system: options.system,
|
|
207
|
+
temperature: options.temperature,
|
|
208
|
+
maxOutputTokens: options.maxOutputTokens,
|
|
209
|
+
topP: options.topP,
|
|
210
|
+
presencePenalty: options.presencePenalty,
|
|
211
|
+
frequencyPenalty: options.frequencyPenalty,
|
|
212
|
+
stopSequences: options.stopSequences,
|
|
213
|
+
seed: options.seed,
|
|
214
|
+
headers: options.headers
|
|
215
|
+
};
|
|
216
|
+
return new aipCore.LmsChatTransport(built);
|
|
217
|
+
},
|
|
218
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
219
|
+
[options.transport, options.model, options.system, options.temperature, options.maxOutputTokens, options.topP, options.presencePenalty, options.frequencyPenalty, options.seed, headersKey, stopSequencesKey]
|
|
220
|
+
);
|
|
221
|
+
const store = React__default.default.useMemo(
|
|
222
|
+
() => createChatStore({
|
|
223
|
+
initialMessages: options.messages,
|
|
224
|
+
throttleMs: options.experimentalThrottle ?? 50
|
|
225
|
+
}),
|
|
226
|
+
// Recreating the store mid-session would drop chat state, so it's keyed
|
|
227
|
+
// only by `id`. Use `setMessages` to mutate messages at runtime.
|
|
228
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
229
|
+
[id]
|
|
230
|
+
);
|
|
231
|
+
const state = React__default.default.useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
232
|
+
const abortRef = React__default.default.useRef(void 0);
|
|
233
|
+
const stoppedRef = React__default.default.useRef(false);
|
|
234
|
+
const ctxRef = React__default.default.useRef({
|
|
235
|
+
store,
|
|
236
|
+
abortRef,
|
|
237
|
+
stoppedRef,
|
|
238
|
+
onFinish,
|
|
239
|
+
onError
|
|
240
|
+
});
|
|
241
|
+
ctxRef.current = {
|
|
242
|
+
store,
|
|
243
|
+
abortRef,
|
|
244
|
+
stoppedRef,
|
|
245
|
+
onFinish,
|
|
246
|
+
onError
|
|
247
|
+
};
|
|
248
|
+
const runStream = React__default.default.useCallback((seed, trigger) => runChatStream(ctxRef.current, transport, id, seed, trigger), [transport, id]);
|
|
249
|
+
const sendMessage = React__default.default.useCallback(async (input) => {
|
|
250
|
+
const userMsg = normalizeUserMessage(input);
|
|
251
|
+
const seeded = [...store.getSnapshot().messages, userMsg];
|
|
252
|
+
store.setState({
|
|
253
|
+
messages: seeded,
|
|
254
|
+
status: "submitted",
|
|
255
|
+
error: void 0
|
|
256
|
+
});
|
|
257
|
+
await runStream(seeded, "submit-message");
|
|
258
|
+
}, [store, runStream]);
|
|
259
|
+
const regenerate = React__default.default.useCallback(async (regenerateOpts) => {
|
|
260
|
+
const messages = store.getSnapshot().messages;
|
|
261
|
+
const cutoff = resolveRegenerateCutoff(messages, regenerateOpts?.messageId);
|
|
262
|
+
if (cutoff.kind === "noop") {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (cutoff.kind === "error") {
|
|
266
|
+
store.setState((prev) => ({
|
|
267
|
+
...prev,
|
|
268
|
+
status: "error",
|
|
269
|
+
error: cutoff.error
|
|
270
|
+
}));
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
const truncated = messages.slice(0, cutoff.index);
|
|
274
|
+
store.setState({
|
|
275
|
+
messages: truncated,
|
|
276
|
+
status: "submitted",
|
|
277
|
+
error: void 0
|
|
278
|
+
});
|
|
279
|
+
await runStream(truncated, "regenerate-message");
|
|
280
|
+
}, [store, runStream]);
|
|
281
|
+
const stop = React__default.default.useCallback(() => {
|
|
282
|
+
stoppedRef.current = true;
|
|
283
|
+
abortRef.current?.abort();
|
|
284
|
+
abortRef.current = void 0;
|
|
285
|
+
}, []);
|
|
286
|
+
const resumeStream = React__default.default.useCallback(async () => {
|
|
287
|
+
const stream = await transport.reconnectToStream({
|
|
288
|
+
chatId: id
|
|
289
|
+
});
|
|
290
|
+
if (stream == null) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
abortRef.current?.abort();
|
|
294
|
+
const ctrl = new AbortController();
|
|
295
|
+
abortRef.current = ctrl;
|
|
296
|
+
const assistantId = aipCore.generateMessageId();
|
|
297
|
+
await drainStream(ctxRef.current, stream, assistantId, ctrl);
|
|
298
|
+
}, [transport, id]);
|
|
299
|
+
const clearError = React__default.default.useCallback(() => {
|
|
300
|
+
store.setState((prev) => prev.status === "error" ? {
|
|
301
|
+
...prev,
|
|
302
|
+
status: "ready",
|
|
303
|
+
error: void 0
|
|
304
|
+
} : prev);
|
|
305
|
+
}, [store]);
|
|
306
|
+
const setMessages = React__default.default.useCallback((next) => {
|
|
307
|
+
store.setState((prev) => {
|
|
308
|
+
if (prev.status === "streaming" || prev.status === "submitted") {
|
|
309
|
+
return prev;
|
|
310
|
+
}
|
|
311
|
+
return {
|
|
312
|
+
...prev,
|
|
313
|
+
messages: typeof next === "function" ? next(prev.messages) : next
|
|
314
|
+
};
|
|
315
|
+
});
|
|
316
|
+
}, [store]);
|
|
317
|
+
return React__default.default.useMemo(() => ({
|
|
318
|
+
id,
|
|
319
|
+
messages: state.messages,
|
|
320
|
+
setMessages,
|
|
321
|
+
status: state.status,
|
|
322
|
+
error: state.error,
|
|
323
|
+
sendMessage,
|
|
324
|
+
regenerate,
|
|
325
|
+
stop,
|
|
326
|
+
resumeStream,
|
|
327
|
+
clearError
|
|
328
|
+
}), [id, state.messages, state.status, state.error, setMessages, sendMessage, regenerate, stop, resumeStream, clearError]);
|
|
329
|
+
}
|
|
330
|
+
function resolveRegenerateCutoff(messages, messageId) {
|
|
331
|
+
if (messageId != null) {
|
|
332
|
+
const index = messages.findIndex((m) => m.id === messageId);
|
|
333
|
+
if (index < 0) {
|
|
334
|
+
return {
|
|
335
|
+
kind: "noop"
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
const target = messages[index];
|
|
339
|
+
if (target == null || target.role !== "assistant") {
|
|
340
|
+
return {
|
|
341
|
+
kind: "error",
|
|
342
|
+
error: new Error(`useChat.regenerate: messageId "${messageId}" is not an assistant message; only assistant messages can be regenerated.`)
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
return {
|
|
346
|
+
kind: "ok",
|
|
347
|
+
index
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
const lastAssistant = findLastAssistantIndex(messages);
|
|
351
|
+
if (lastAssistant < 0) {
|
|
352
|
+
return {
|
|
353
|
+
kind: "noop"
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
kind: "ok",
|
|
358
|
+
index: lastAssistant
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
function normalizeUserMessage(input) {
|
|
362
|
+
if ("text" in input) {
|
|
363
|
+
return {
|
|
364
|
+
id: aipCore.generateMessageId(),
|
|
365
|
+
role: "user",
|
|
366
|
+
parts: [{
|
|
367
|
+
type: "text",
|
|
368
|
+
text: input.text
|
|
369
|
+
}]
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
id: aipCore.generateMessageId(),
|
|
374
|
+
role: input.role,
|
|
375
|
+
parts: input.parts
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
function findLastAssistantIndex(arr) {
|
|
379
|
+
for (let i = arr.length - 1; i >= 0; i--) {
|
|
380
|
+
if (arr[i]?.role === "assistant") {
|
|
381
|
+
return i;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return -1;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
exports.useChat = useChat;
|
|
388
|
+
//# sourceMappingURL=aip.cjs.map
|
|
389
|
+
//# sourceMappingURL=aip.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/aip/chatStore.ts","../../../../src/aip/chatStream.ts","../../../../src/aip/useChat.ts"],"names":["generateMessageId","React","LmsChatTransport"],"mappings":"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","file":"aip.cjs","sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Tiny pub-sub store backing `useChat`. Throttles subscriber notifications so\n * fast token-delta streams don't trigger one render per token.\n */\nexport function createChatStore(options) {\n let state = {\n messages: options.initialMessages ?? [],\n status: \"ready\",\n error: undefined\n };\n const subscribers = new Set();\n const throttleMs = options.throttleMs ?? 0;\n let pendingNotify;\n const notifyNow = () => {\n if (pendingNotify != null) {\n clearTimeout(pendingNotify);\n pendingNotify = undefined;\n }\n for (const s of subscribers) {\n s();\n }\n };\n const notifyThrottled = () => {\n if (throttleMs <= 0) {\n notifyNow();\n return;\n }\n if (pendingNotify != null) {\n return;\n }\n pendingNotify = setTimeout(notifyNow, throttleMs);\n };\n return {\n getSnapshot: () => state,\n subscribe: notify => {\n subscribers.add(notify);\n return () => {\n subscribers.delete(notify);\n };\n },\n setState: next => {\n state = typeof next === \"function\" ? next(state) : next;\n notifyNow();\n },\n setStateThrottled: next => {\n state = typeof next === \"function\" ? next(state) : next;\n notifyThrottled();\n }\n };\n}","/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { generateMessageId } from \"@osdk/aip-core\";\n\n/**\n * Mutable orchestration handle threaded through the streaming functions.\n * Holds everything they need to read snapshots, mutate state, and check\n * whether their stream is still the active one.\n */\n\nexport async function runChatStream(ctx, transport, chatId, seed, trigger) {\n ctx.abortRef.current?.abort();\n const ctrl = new AbortController();\n ctx.abortRef.current = ctrl;\n ctx.stoppedRef.current = false;\n const assistantId = generateMessageId();\n try {\n const stream = await transport.sendMessages({\n trigger,\n chatId,\n messageId: assistantId,\n messages: seed.slice(),\n abortSignal: ctrl.signal\n });\n await drainStream(ctx, stream, assistantId, ctrl);\n } catch (err) {\n handleStreamError(ctx, err, ctrl);\n }\n}\nexport async function drainStream(ctx, stream, assistantMessageId, capturedCtrl) {\n const {\n store\n } = ctx;\n const reader = stream.getReader();\n let textBuf = \"\";\n const isStale = () => ctx.abortRef.current != null && ctx.abortRef.current !== capturedCtrl;\n\n // Caller dropped our assistant message via `setMessages` mid-stream.\n // Treat as \"the consumer no longer wants this stream\" — quietly stop.\n const isOrphaned = () => {\n const messages = store.getSnapshot().messages;\n return textBuf.length > 0 && !messages.some(m => m.id === assistantMessageId);\n };\n try {\n while (true) {\n const {\n done,\n value\n } = await reader.read();\n if (done) {\n break;\n }\n if (isStale()) {\n await reader.cancel();\n return;\n }\n if (isOrphaned()) {\n await reader.cancel();\n store.setState(prev => ({\n ...prev,\n status: \"ready\"\n }));\n return;\n }\n if (value.type === \"text-delta\") {\n textBuf += value.delta;\n upsertAssistantText(store, assistantMessageId, textBuf);\n } else if (value.type === \"error\") {\n if (ctx.stoppedRef.current || capturedCtrl.signal.aborted) {\n return;\n }\n await reader.cancel();\n throw new Error(value.errorText);\n }\n }\n if (isStale()) {\n return;\n }\n store.setState(prev => ({\n ...prev,\n status: \"ready\"\n }));\n const finalSnap = store.getSnapshot();\n const finalMessage = finalSnap.messages.find(m => m.id === assistantMessageId);\n if (finalMessage != null && ctx.onFinish != null) {\n ctx.onFinish({\n message: finalMessage,\n messages: finalSnap.messages\n });\n }\n } catch (err) {\n handleStreamError(ctx, err, capturedCtrl);\n } finally {\n reader.releaseLock();\n }\n}\nfunction upsertAssistantText(store, assistantMessageId, text) {\n store.setStateThrottled(prev => {\n const exists = prev.messages.some(m => m.id === assistantMessageId);\n const messages = exists ? prev.messages.map(m => m.id === assistantMessageId ? {\n ...m,\n parts: [{\n type: \"text\",\n text\n }]\n } : m) : [...prev.messages, {\n id: assistantMessageId,\n role: \"assistant\",\n parts: [{\n type: \"text\",\n text\n }]\n }];\n return {\n ...prev,\n status: \"streaming\",\n messages\n };\n });\n}\nfunction handleStreamError(ctx, err, capturedCtrl) {\n if (ctx.abortRef.current != null && ctx.abortRef.current !== capturedCtrl) {\n return;\n }\n const error = err instanceof Error ? err : new Error(String(err));\n if (ctx.stoppedRef.current || error.name === \"AbortError\" || capturedCtrl.signal.aborted) {\n ctx.store.setState(prev => ({\n ...prev,\n status: \"ready\",\n error: undefined\n }));\n return;\n }\n ctx.store.setState(prev => ({\n ...prev,\n status: \"error\",\n error\n }));\n ctx.onError?.(error);\n}","/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { generateMessageId, LmsChatTransport } from \"@osdk/aip-core\";\nimport React from \"react\";\nimport { createChatStore } from \"./chatStore.js\";\nimport { drainStream, runChatStream } from \"./chatStream.js\";\n\n/**\n * Options for {@link useChat}.\n *\n * v0 covers text-only chat. Tools, multi-step agent loops, and stream\n * resume are not supported.\n */\n\n/** Return value of {@link useChat}. */\n\n/** Input shape accepted by `sendMessage`. */\n\n/**\n * React hook for streaming chat completions through `@osdk/aip-core`'s\n * `streamText`.\n *\n * @example\n * ```tsx\n * const { messages, status, sendMessage, stop, error } = useChat({\n * model: foundryModel({ client, model: \"gpt-4o\" }),\n * system: \"You are a concise assistant.\",\n * });\n * ```\n */\nexport function useChat(options) {\n const {\n onFinish,\n onError\n } = options;\n const id = React.useMemo(() => options.id ?? generateMessageId(), [options.id]);\n\n // JSON-stringify keys keep the memo stable when callers pass inline objects.\n const headersKey = JSON.stringify(options.headers ?? null);\n const stopSequencesKey = JSON.stringify(options.stopSequences ?? null);\n const transport = React.useMemo(() => {\n if (options.transport != null) {\n return options.transport;\n }\n if (options.model == null) {\n throw new Error(\"useChat: `model` is required when no `transport` is provided.\");\n }\n const built = {\n model: options.model,\n system: options.system,\n temperature: options.temperature,\n maxOutputTokens: options.maxOutputTokens,\n topP: options.topP,\n presencePenalty: options.presencePenalty,\n frequencyPenalty: options.frequencyPenalty,\n stopSequences: options.stopSequences,\n seed: options.seed,\n headers: options.headers\n };\n return new LmsChatTransport(built);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [options.transport, options.model, options.system, options.temperature, options.maxOutputTokens, options.topP, options.presencePenalty, options.frequencyPenalty, options.seed, headersKey, stopSequencesKey]);\n const store = React.useMemo(() => createChatStore({\n initialMessages: options.messages,\n throttleMs: options.experimentalThrottle ?? 50\n }),\n // Recreating the store mid-session would drop chat state, so it's keyed\n // only by `id`. Use `setMessages` to mutate messages at runtime.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [id]);\n const state = React.useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n const abortRef = React.useRef(undefined);\n const stoppedRef = React.useRef(false);\n const ctxRef = React.useRef({\n store,\n abortRef,\n stoppedRef,\n onFinish,\n onError\n });\n ctxRef.current = {\n store,\n abortRef,\n stoppedRef,\n onFinish,\n onError\n };\n const runStream = React.useCallback((seed, trigger) => runChatStream(ctxRef.current, transport, id, seed, trigger), [transport, id]);\n const sendMessage = React.useCallback(async input => {\n const userMsg = normalizeUserMessage(input);\n const seeded = [...store.getSnapshot().messages, userMsg];\n store.setState({\n messages: seeded,\n status: \"submitted\",\n error: undefined\n });\n await runStream(seeded, \"submit-message\");\n }, [store, runStream]);\n const regenerate = React.useCallback(async regenerateOpts => {\n const messages = store.getSnapshot().messages;\n const cutoff = resolveRegenerateCutoff(messages, regenerateOpts?.messageId);\n if (cutoff.kind === \"noop\") {\n return;\n }\n if (cutoff.kind === \"error\") {\n store.setState(prev => ({\n ...prev,\n status: \"error\",\n error: cutoff.error\n }));\n return;\n }\n const truncated = messages.slice(0, cutoff.index);\n store.setState({\n messages: truncated,\n status: \"submitted\",\n error: undefined\n });\n await runStream(truncated, \"regenerate-message\");\n }, [store, runStream]);\n const stop = React.useCallback(() => {\n stoppedRef.current = true;\n abortRef.current?.abort();\n abortRef.current = undefined;\n }, []);\n const resumeStream = React.useCallback(async () => {\n const stream = await transport.reconnectToStream({\n chatId: id\n });\n if (stream == null) {\n return;\n }\n abortRef.current?.abort();\n const ctrl = new AbortController();\n abortRef.current = ctrl;\n const assistantId = generateMessageId();\n await drainStream(ctxRef.current, stream, assistantId, ctrl);\n }, [transport, id]);\n const clearError = React.useCallback(() => {\n // Resetting from streaming/submitted would race the in-flight stream, so\n // only reset when status === \"error\".\n store.setState(prev => prev.status === \"error\" ? {\n ...prev,\n status: \"ready\",\n error: undefined\n } : prev);\n }, [store]);\n const setMessages = React.useCallback(next => {\n store.setState(prev => {\n if (prev.status === \"streaming\" || prev.status === \"submitted\") {\n return prev;\n }\n return {\n ...prev,\n messages: typeof next === \"function\" ? next(prev.messages) : next\n };\n });\n }, [store]);\n return React.useMemo(() => ({\n id,\n messages: state.messages,\n setMessages,\n status: state.status,\n error: state.error,\n sendMessage,\n regenerate,\n stop,\n resumeStream,\n clearError\n }), [id, state.messages, state.status, state.error, setMessages, sendMessage, regenerate, stop, resumeStream, clearError]);\n}\nfunction resolveRegenerateCutoff(messages, messageId) {\n if (messageId != null) {\n const index = messages.findIndex(m => m.id === messageId);\n if (index < 0) {\n return {\n kind: \"noop\"\n };\n }\n const target = messages[index];\n if (target == null || target.role !== \"assistant\") {\n return {\n kind: \"error\",\n error: new Error(`useChat.regenerate: messageId \"${messageId}\" is ` + `not an assistant message; only assistant messages can be regenerated.`)\n };\n }\n return {\n kind: \"ok\",\n index\n };\n }\n const lastAssistant = findLastAssistantIndex(messages);\n if (lastAssistant < 0) {\n return {\n kind: \"noop\"\n };\n }\n return {\n kind: \"ok\",\n index: lastAssistant\n };\n}\nfunction normalizeUserMessage(input) {\n if (\"text\" in input) {\n return {\n id: generateMessageId(),\n role: \"user\",\n parts: [{\n type: \"text\",\n text: input.text\n }]\n };\n }\n return {\n id: generateMessageId(),\n role: input.role,\n parts: input.parts\n };\n}\nfunction findLastAssistantIndex(arr) {\n for (let i = arr.length - 1; i >= 0; i--) {\n if (arr[i]?.role === \"assistant\") {\n return i;\n }\n }\n return -1;\n}"]}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { UIMessage, LanguageModel, ChatTransport } from '@osdk/aip-core';
|
|
2
|
+
export { UIMessage, UIMessageChunk } from '@osdk/aip-core';
|
|
3
|
+
|
|
4
|
+
type ChatStatus = "ready" | "submitted" | "streaming" | "error";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Options for {@link useChat}.
|
|
8
|
+
*
|
|
9
|
+
* v0 covers text-only chat. Tools, multi-step agent loops, and stream
|
|
10
|
+
* resume are not supported.
|
|
11
|
+
*/
|
|
12
|
+
interface UseChatOptions {
|
|
13
|
+
/** Required when no `transport` is provided: the LMS-backed model. */
|
|
14
|
+
model?: LanguageModel;
|
|
15
|
+
/** System prompt prepended to every request. Forwarded to the default transport. */
|
|
16
|
+
system?: string;
|
|
17
|
+
/** Sampling controls. Forwarded to the default transport. */
|
|
18
|
+
temperature?: number;
|
|
19
|
+
maxOutputTokens?: number;
|
|
20
|
+
topP?: number;
|
|
21
|
+
presencePenalty?: number;
|
|
22
|
+
frequencyPenalty?: number;
|
|
23
|
+
stopSequences?: Array<string>;
|
|
24
|
+
seed?: number;
|
|
25
|
+
headers?: Record<string, string | undefined>;
|
|
26
|
+
/** Stable chat id. A stable id is generated if not provided. */
|
|
27
|
+
id?: string;
|
|
28
|
+
/** Initial messages — used as the seed snapshot. */
|
|
29
|
+
messages?: ReadonlyArray<UIMessage>;
|
|
30
|
+
/** Override the transport. Defaults to a new `LmsChatTransport(options)`. */
|
|
31
|
+
transport?: ChatTransport<UIMessage>;
|
|
32
|
+
/**
|
|
33
|
+
* Throttle subscriber notifications during streaming (ms). Default 50ms,
|
|
34
|
+
* which keeps token-by-token rendering smooth without rerendering per token.
|
|
35
|
+
*/
|
|
36
|
+
experimentalThrottle?: number;
|
|
37
|
+
/** Fires when an in-flight stream errors out. */
|
|
38
|
+
onError?: (error: Error) => void;
|
|
39
|
+
/** Fires once after a stream completes successfully. */
|
|
40
|
+
onFinish?: (event: {
|
|
41
|
+
message: UIMessage;
|
|
42
|
+
messages: ReadonlyArray<UIMessage>;
|
|
43
|
+
}) => void;
|
|
44
|
+
}
|
|
45
|
+
/** Return value of {@link useChat}. */
|
|
46
|
+
interface UseChatReturn {
|
|
47
|
+
id: string;
|
|
48
|
+
messages: ReadonlyArray<UIMessage>;
|
|
49
|
+
/** No-op while a stream is in flight (`status === "streaming" | "submitted"`). Call `stop()` first to mutate during a stream. */
|
|
50
|
+
setMessages: (messages: ReadonlyArray<UIMessage> | ((prev: ReadonlyArray<UIMessage>) => ReadonlyArray<UIMessage>)) => void;
|
|
51
|
+
status: ChatStatus;
|
|
52
|
+
error: Error | undefined;
|
|
53
|
+
sendMessage: (message: SendMessageInput) => Promise<void>;
|
|
54
|
+
regenerate: (options?: {
|
|
55
|
+
messageId?: string;
|
|
56
|
+
}) => Promise<void>;
|
|
57
|
+
stop: () => void;
|
|
58
|
+
/** Calls `transport.reconnectToStream`. v0: LMS returns null, so this is a no-op. */
|
|
59
|
+
resumeStream: () => Promise<void>;
|
|
60
|
+
clearError: () => void;
|
|
61
|
+
}
|
|
62
|
+
/** Input shape accepted by `sendMessage`. */
|
|
63
|
+
type SendMessageInput = {
|
|
64
|
+
text: string;
|
|
65
|
+
} | {
|
|
66
|
+
role: "user";
|
|
67
|
+
parts: UIMessage["parts"];
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* React hook for streaming chat completions through `@osdk/aip-core`'s
|
|
71
|
+
* `streamText`.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```tsx
|
|
75
|
+
* const { messages, status, sendMessage, stop, error } = useChat({
|
|
76
|
+
* model: foundryModel({ client, model: "gpt-4o" }),
|
|
77
|
+
* system: "You are a concise assistant.",
|
|
78
|
+
* });
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
declare function useChat(options: UseChatOptions): UseChatReturn;
|
|
82
|
+
|
|
83
|
+
export { type ChatStatus, type SendMessageInput, type UseChatOptions, type UseChatReturn, useChat };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkQNNQV2NH_cjs = require('../chunk-QNNQV2NH.cjs');
|
|
4
4
|
var chunkOGP2DK2V_cjs = require('../chunk-OGP2DK2V.cjs');
|
|
5
5
|
require('../chunk-UKQGMTMG.cjs');
|
|
6
6
|
require('../chunk-DO3NFBKN.cjs');
|
|
@@ -9,63 +9,63 @@ require('../chunk-DO3NFBKN.cjs');
|
|
|
9
9
|
|
|
10
10
|
Object.defineProperty(exports, "OsdkProvider2", {
|
|
11
11
|
enumerable: true,
|
|
12
|
-
get: function () { return
|
|
12
|
+
get: function () { return chunkQNNQV2NH_cjs.OsdkProvider; }
|
|
13
13
|
});
|
|
14
14
|
Object.defineProperty(exports, "useDebouncedCallback", {
|
|
15
15
|
enumerable: true,
|
|
16
|
-
get: function () { return
|
|
16
|
+
get: function () { return chunkQNNQV2NH_cjs.useDebouncedCallback; }
|
|
17
17
|
});
|
|
18
18
|
Object.defineProperty(exports, "useLinks", {
|
|
19
19
|
enumerable: true,
|
|
20
|
-
get: function () { return
|
|
20
|
+
get: function () { return chunkQNNQV2NH_cjs.useLinks; }
|
|
21
21
|
});
|
|
22
22
|
Object.defineProperty(exports, "useObjectSet", {
|
|
23
23
|
enumerable: true,
|
|
24
|
-
get: function () { return
|
|
24
|
+
get: function () { return chunkQNNQV2NH_cjs.useObjectSet; }
|
|
25
25
|
});
|
|
26
26
|
Object.defineProperty(exports, "useOsdkAction", {
|
|
27
27
|
enumerable: true,
|
|
28
|
-
get: function () { return
|
|
28
|
+
get: function () { return chunkQNNQV2NH_cjs.useOsdkAction; }
|
|
29
29
|
});
|
|
30
30
|
Object.defineProperty(exports, "useOsdkAggregation", {
|
|
31
31
|
enumerable: true,
|
|
32
|
-
get: function () { return
|
|
32
|
+
get: function () { return chunkQNNQV2NH_cjs.useOsdkAggregation; }
|
|
33
33
|
});
|
|
34
34
|
Object.defineProperty(exports, "useOsdkClient", {
|
|
35
35
|
enumerable: true,
|
|
36
|
-
get: function () { return
|
|
36
|
+
get: function () { return chunkQNNQV2NH_cjs.useOsdkClient; }
|
|
37
37
|
});
|
|
38
38
|
Object.defineProperty(exports, "useOsdkClient2", {
|
|
39
39
|
enumerable: true,
|
|
40
|
-
get: function () { return
|
|
40
|
+
get: function () { return chunkQNNQV2NH_cjs.useOsdkClient; }
|
|
41
41
|
});
|
|
42
42
|
Object.defineProperty(exports, "useOsdkFunction", {
|
|
43
43
|
enumerable: true,
|
|
44
|
-
get: function () { return
|
|
44
|
+
get: function () { return chunkQNNQV2NH_cjs.useOsdkFunction; }
|
|
45
45
|
});
|
|
46
46
|
Object.defineProperty(exports, "useOsdkFunctions", {
|
|
47
47
|
enumerable: true,
|
|
48
|
-
get: function () { return
|
|
48
|
+
get: function () { return chunkQNNQV2NH_cjs.useOsdkFunctions; }
|
|
49
49
|
});
|
|
50
50
|
Object.defineProperty(exports, "useOsdkMetadata", {
|
|
51
51
|
enumerable: true,
|
|
52
|
-
get: function () { return
|
|
52
|
+
get: function () { return chunkQNNQV2NH_cjs.useOsdkMetadata; }
|
|
53
53
|
});
|
|
54
54
|
Object.defineProperty(exports, "useOsdkObject", {
|
|
55
55
|
enumerable: true,
|
|
56
|
-
get: function () { return
|
|
56
|
+
get: function () { return chunkQNNQV2NH_cjs.useOsdkObject; }
|
|
57
57
|
});
|
|
58
58
|
Object.defineProperty(exports, "useOsdkObjects", {
|
|
59
59
|
enumerable: true,
|
|
60
|
-
get: function () { return
|
|
60
|
+
get: function () { return chunkQNNQV2NH_cjs.useOsdkObjects; }
|
|
61
61
|
});
|
|
62
62
|
Object.defineProperty(exports, "useRegisterUserAgent", {
|
|
63
63
|
enumerable: true,
|
|
64
|
-
get: function () { return
|
|
64
|
+
get: function () { return chunkQNNQV2NH_cjs.useRegisterUserAgent; }
|
|
65
65
|
});
|
|
66
66
|
Object.defineProperty(exports, "useStableObjectSet", {
|
|
67
67
|
enumerable: true,
|
|
68
|
-
get: function () { return
|
|
68
|
+
get: function () { return chunkQNNQV2NH_cjs.useStableObjectSet; }
|
|
69
69
|
});
|
|
70
70
|
Object.defineProperty(exports, "getRegisteredDevTools", {
|
|
71
71
|
enumerable: true,
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 Palantir Technologies, Inc. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Tiny pub-sub store backing `useChat`. Throttles subscriber notifications so
|
|
19
|
+
* fast token-delta streams don't trigger one render per token.
|
|
20
|
+
*/
|
|
21
|
+
export function createChatStore(options) {
|
|
22
|
+
let state = {
|
|
23
|
+
messages: options.initialMessages ?? [],
|
|
24
|
+
status: "ready",
|
|
25
|
+
error: undefined
|
|
26
|
+
};
|
|
27
|
+
const subscribers = new Set();
|
|
28
|
+
const throttleMs = options.throttleMs ?? 0;
|
|
29
|
+
let pendingNotify;
|
|
30
|
+
const notifyNow = () => {
|
|
31
|
+
if (pendingNotify != null) {
|
|
32
|
+
clearTimeout(pendingNotify);
|
|
33
|
+
pendingNotify = undefined;
|
|
34
|
+
}
|
|
35
|
+
for (const s of subscribers) {
|
|
36
|
+
s();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const notifyThrottled = () => {
|
|
40
|
+
if (throttleMs <= 0) {
|
|
41
|
+
notifyNow();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (pendingNotify != null) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
pendingNotify = setTimeout(notifyNow, throttleMs);
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
getSnapshot: () => state,
|
|
51
|
+
subscribe: notify => {
|
|
52
|
+
subscribers.add(notify);
|
|
53
|
+
return () => {
|
|
54
|
+
subscribers.delete(notify);
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
setState: next => {
|
|
58
|
+
state = typeof next === "function" ? next(state) : next;
|
|
59
|
+
notifyNow();
|
|
60
|
+
},
|
|
61
|
+
setStateThrottled: next => {
|
|
62
|
+
state = typeof next === "function" ? next(state) : next;
|
|
63
|
+
notifyThrottled();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=chatStore.js.map
|