@gravity-ui/aikit 1.3.5 → 1.5.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/adapters/index.d.ts +1 -0
- package/dist/adapters/index.js +1 -0
- package/dist/adapters/openai/helpers/applyContentUpdate.d.ts +3 -0
- package/dist/adapters/openai/helpers/applyContentUpdate.js +113 -0
- package/dist/adapters/openai/helpers/buildFinalMessages.d.ts +11 -0
- package/dist/adapters/openai/helpers/buildFinalMessages.js +27 -0
- package/dist/adapters/openai/helpers/consumeOpenAIStream.d.ts +12 -0
- package/dist/adapters/openai/helpers/consumeOpenAIStream.js +101 -0
- package/dist/adapters/openai/helpers/contentPartsToMessageContent.d.ts +2 -0
- package/dist/adapters/openai/helpers/contentPartsToMessageContent.js +7 -0
- package/dist/adapters/openai/helpers/eventTypeUtils.d.ts +4 -0
- package/dist/adapters/openai/helpers/eventTypeUtils.js +17 -0
- package/dist/adapters/openai/helpers/fetchResponseToStreamEvents.d.ts +3 -0
- package/dist/adapters/openai/helpers/fetchResponseToStreamEvents.js +64 -0
- package/dist/adapters/openai/helpers/getStreamErrorMessage.d.ts +1 -0
- package/dist/adapters/openai/helpers/getStreamErrorMessage.js +12 -0
- package/dist/adapters/openai/helpers/getStreamEventContentUpdate.d.ts +41 -0
- package/dist/adapters/openai/helpers/getStreamEventContentUpdate.js +246 -0
- package/dist/adapters/openai/helpers/getTextDeltaFromStreamEvent.d.ts +3 -0
- package/dist/adapters/openai/helpers/getTextDeltaFromStreamEvent.js +34 -0
- package/dist/adapters/openai/helpers/isFetchResponse.d.ts +2 -0
- package/dist/adapters/openai/helpers/isFetchResponse.js +8 -0
- package/dist/adapters/openai/helpers/isMessageOutputItemDoneEvent.d.ts +3 -0
- package/dist/adapters/openai/helpers/isMessageOutputItemDoneEvent.js +18 -0
- package/dist/adapters/openai/helpers/isOutputItemDoneEvent.d.ts +2 -0
- package/dist/adapters/openai/helpers/isOutputItemDoneEvent.js +10 -0
- package/dist/adapters/openai/helpers/isOutputTextOrContentPartDone.d.ts +2 -0
- package/dist/adapters/openai/helpers/isOutputTextOrContentPartDone.js +10 -0
- package/dist/adapters/openai/helpers/isStreamEndOrErrorEvent.d.ts +2 -0
- package/dist/adapters/openai/helpers/isStreamEndOrErrorEvent.js +11 -0
- package/dist/adapters/openai/helpers/mapOutputToContent.d.ts +4 -0
- package/dist/adapters/openai/helpers/mapOutputToContent.js +73 -0
- package/dist/adapters/openai/helpers/openAIResponseToMessages.d.ts +4 -0
- package/dist/adapters/openai/helpers/openAIResponseToMessages.js +20 -0
- package/dist/adapters/openai/index.d.ts +10 -0
- package/dist/adapters/openai/index.js +7 -0
- package/dist/adapters/openai/types/index.d.ts +20 -0
- package/dist/adapters/openai/types/index.js +1 -0
- package/dist/adapters/openai/types/openAiTypes.d.ts +213 -0
- package/dist/adapters/openai/types/openAiTypes.js +1 -0
- package/dist/adapters/openai/useOpenAIResponsesAdapter.d.ts +12 -0
- package/dist/adapters/openai/useOpenAIResponsesAdapter.js +83 -0
- package/dist/components/organisms/MessageList/MessageList.js +2 -2
- package/dist/components/organisms/PromptInput/usePromptInput.js +2 -0
- package/dist/components/pages/ChatContainer/__stories__/ChatContainer.stories.js +12 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/types/chat.d.ts +1 -1
- package/package.json +4 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './openai';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './openai';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { TMessageContentUnion } from '../../../types';
|
|
2
|
+
import type { StreamEventContentUpdate } from './getStreamEventContentUpdate';
|
|
3
|
+
export declare function applyContentUpdate(parts: TMessageContentUnion[], update: StreamEventContentUpdate): TMessageContentUnion[] | null;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
function findContentPartIndex(parts, partType, id) {
|
|
2
|
+
return parts.findIndex((p) => p.type === partType && p.id === id);
|
|
3
|
+
}
|
|
4
|
+
export function applyContentUpdate(parts, update) {
|
|
5
|
+
switch (update.kind) {
|
|
6
|
+
case 'text_delta':
|
|
7
|
+
return applyTextDelta(parts, update);
|
|
8
|
+
case 'tool_add':
|
|
9
|
+
return applyToolAdd(parts, update);
|
|
10
|
+
case 'tool_update':
|
|
11
|
+
return applyToolUpdate(parts, update);
|
|
12
|
+
case 'thinking_add':
|
|
13
|
+
return applyThinkingAdd(parts, update);
|
|
14
|
+
case 'thinking_delta':
|
|
15
|
+
return applyThinkingDelta(parts, update);
|
|
16
|
+
case 'thinking_done':
|
|
17
|
+
return applyThinkingDone(parts, update);
|
|
18
|
+
default:
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function applyTextDelta(parts, update) {
|
|
23
|
+
const last = parts[parts.length - 1];
|
|
24
|
+
if ((last === null || last === void 0 ? void 0 : last.type) === 'text') {
|
|
25
|
+
return [
|
|
26
|
+
...parts.slice(0, -1),
|
|
27
|
+
{ type: 'text', data: { text: last.data.text + update.delta } },
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
return [...parts, { type: 'text', data: { text: update.delta } }];
|
|
31
|
+
}
|
|
32
|
+
function applyToolAdd(parts, update) {
|
|
33
|
+
var _a;
|
|
34
|
+
const status = (_a = update.status) !== null && _a !== void 0 ? _a : 'loading';
|
|
35
|
+
const data = {
|
|
36
|
+
toolName: update.toolName,
|
|
37
|
+
status,
|
|
38
|
+
};
|
|
39
|
+
if (update.headerContent !== undefined) {
|
|
40
|
+
data.headerContent = update.headerContent;
|
|
41
|
+
}
|
|
42
|
+
return [
|
|
43
|
+
...parts,
|
|
44
|
+
{
|
|
45
|
+
type: 'tool',
|
|
46
|
+
id: update.id,
|
|
47
|
+
data,
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
function applyToolUpdate(parts, update) {
|
|
52
|
+
var _a, _b;
|
|
53
|
+
let idx = findContentPartIndex(parts, 'tool', update.item_id);
|
|
54
|
+
let partsToUpdate = parts;
|
|
55
|
+
if (idx < 0) {
|
|
56
|
+
partsToUpdate = applyToolAdd(parts, {
|
|
57
|
+
kind: 'tool_add',
|
|
58
|
+
id: update.item_id,
|
|
59
|
+
toolName: (_a = update.toolName) !== null && _a !== void 0 ? _a : '',
|
|
60
|
+
status: update.status,
|
|
61
|
+
headerContent: (_b = update.output) !== null && _b !== void 0 ? _b : update.error,
|
|
62
|
+
});
|
|
63
|
+
idx = partsToUpdate.length - 1;
|
|
64
|
+
}
|
|
65
|
+
const prev = partsToUpdate[idx];
|
|
66
|
+
if (prev.type !== 'tool')
|
|
67
|
+
return partsToUpdate;
|
|
68
|
+
return partsToUpdate.map((p, i) => {
|
|
69
|
+
var _a, _b;
|
|
70
|
+
return i === idx
|
|
71
|
+
? Object.assign(Object.assign({}, prev), { data: Object.assign(Object.assign(Object.assign({}, prev.data), (update.toolName && { toolName: update.toolName })), { status: update.status, headerContent: (_b = (_a = update.output) !== null && _a !== void 0 ? _a : update.error) !== null && _b !== void 0 ? _b : prev.data.headerContent }) }) : p;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function applyThinkingAdd(parts, update) {
|
|
75
|
+
return [
|
|
76
|
+
...parts,
|
|
77
|
+
{
|
|
78
|
+
type: 'thinking',
|
|
79
|
+
id: update.item_id,
|
|
80
|
+
data: {
|
|
81
|
+
content: '',
|
|
82
|
+
status: 'thinking',
|
|
83
|
+
defaultExpanded: false,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
];
|
|
87
|
+
}
|
|
88
|
+
function applyThinkingDelta(parts, update) {
|
|
89
|
+
const idx = findContentPartIndex(parts, 'thinking', update.item_id);
|
|
90
|
+
if (idx < 0 || parts[idx].type !== 'thinking') {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const prev = parts[idx];
|
|
94
|
+
const prevContent = prev.data.content;
|
|
95
|
+
let prevText = '';
|
|
96
|
+
if (typeof prevContent === 'string') {
|
|
97
|
+
prevText = prevContent;
|
|
98
|
+
}
|
|
99
|
+
else if (Array.isArray(prevContent)) {
|
|
100
|
+
prevText = prevContent.join('');
|
|
101
|
+
}
|
|
102
|
+
const newContent = prevText + update.delta;
|
|
103
|
+
return parts.map((p, i) => i === idx ? Object.assign(Object.assign({}, prev), { data: Object.assign(Object.assign({}, prev.data), { content: newContent }) }) : p);
|
|
104
|
+
}
|
|
105
|
+
function applyThinkingDone(parts, update) {
|
|
106
|
+
const idx = findContentPartIndex(parts, 'thinking', update.item_id);
|
|
107
|
+
if (idx < 0 || parts[idx].type !== 'thinking') {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const prev = parts[idx];
|
|
111
|
+
return parts.map((p, i) => i === idx
|
|
112
|
+
? Object.assign(Object.assign({}, prev), { data: Object.assign(Object.assign({}, prev.data), { content: update.text, status: 'thought' }) }) : p);
|
|
113
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TAssistantMessage, TChatMessage, TMessageContentUnion } from '../../../types';
|
|
2
|
+
export type BuildFinalMessagesParams = {
|
|
3
|
+
baseMessages: TChatMessage[];
|
|
4
|
+
completedAssistantMessages: {
|
|
5
|
+
id: string;
|
|
6
|
+
content: TAssistantMessage['content'];
|
|
7
|
+
}[];
|
|
8
|
+
currentAssistantMessageId: string;
|
|
9
|
+
contentParts: TMessageContentUnion[];
|
|
10
|
+
};
|
|
11
|
+
export declare function buildFinalMessages(params: BuildFinalMessagesParams): TChatMessage[];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { contentPartsToMessageContent } from './contentPartsToMessageContent';
|
|
2
|
+
function isMessageContentEmpty(content) {
|
|
3
|
+
if (typeof content === 'string')
|
|
4
|
+
return content.trim() === '';
|
|
5
|
+
return Array.isArray(content) && content.length === 0;
|
|
6
|
+
}
|
|
7
|
+
export function buildFinalMessages(params) {
|
|
8
|
+
const { baseMessages, completedAssistantMessages, currentAssistantMessageId, contentParts } = params;
|
|
9
|
+
const currentContent = contentPartsToMessageContent(contentParts);
|
|
10
|
+
const completedWithContent = completedAssistantMessages.filter((m) => !isMessageContentEmpty(m.content));
|
|
11
|
+
const result = [...baseMessages];
|
|
12
|
+
for (const m of completedWithContent) {
|
|
13
|
+
result.push({
|
|
14
|
+
id: m.id,
|
|
15
|
+
role: 'assistant',
|
|
16
|
+
content: m.content,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
if (!isMessageContentEmpty(currentContent)) {
|
|
20
|
+
result.push({
|
|
21
|
+
id: currentAssistantMessageId,
|
|
22
|
+
role: 'assistant',
|
|
23
|
+
content: currentContent,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TAssistantMessage, TChatMessage } from '../../../types';
|
|
2
|
+
import type { OpenAIStreamEventLike } from '../types';
|
|
3
|
+
export type ConsumeStreamCallbacks = {
|
|
4
|
+
baseMessages: TChatMessage[];
|
|
5
|
+
getAssistantMessageId: (index: number) => string;
|
|
6
|
+
onContentUpdate: (messageId: string, content: TAssistantMessage['content']) => void;
|
|
7
|
+
onNewMessage: (messageId: string) => void;
|
|
8
|
+
onEnd: (finalMessages: TChatMessage[], status: 'done' | 'error', error?: Error) => void;
|
|
9
|
+
getIsCancelled: () => boolean;
|
|
10
|
+
};
|
|
11
|
+
/** Consumes stream, invokes callbacks. State/setters live in caller. */
|
|
12
|
+
export declare function consumeOpenAIStream(stream: AsyncIterable<OpenAIStreamEventLike>, callbacks: ConsumeStreamCallbacks): Promise<void>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { __asyncValues } from "tslib";
|
|
2
|
+
import { applyContentUpdate } from './applyContentUpdate';
|
|
3
|
+
import { buildFinalMessages } from './buildFinalMessages';
|
|
4
|
+
import { contentPartsToMessageContent } from './contentPartsToMessageContent';
|
|
5
|
+
import { getStreamErrorMessage } from './getStreamErrorMessage';
|
|
6
|
+
import { getStreamEventContentUpdate } from './getStreamEventContentUpdate';
|
|
7
|
+
import { isMessageOutputItemDoneEvent } from './isMessageOutputItemDoneEvent';
|
|
8
|
+
import { isStreamEndOrErrorEvent } from './isStreamEndOrErrorEvent';
|
|
9
|
+
/** Consumes stream, invokes callbacks. State/setters live in caller. */
|
|
10
|
+
export async function consumeOpenAIStream(stream, callbacks) {
|
|
11
|
+
var _a, e_1, _b, _c;
|
|
12
|
+
const { baseMessages, getAssistantMessageId, onContentUpdate, onNewMessage, onEnd, getIsCancelled, } = callbacks;
|
|
13
|
+
const completedAssistantMessages = [];
|
|
14
|
+
let messageIndex = 0;
|
|
15
|
+
let currentAssistantMessageId = getAssistantMessageId(0);
|
|
16
|
+
let contentParts = [];
|
|
17
|
+
const applyContentToCurrentMessage = (parts) => {
|
|
18
|
+
if (getIsCancelled())
|
|
19
|
+
return;
|
|
20
|
+
onContentUpdate(currentAssistantMessageId, contentPartsToMessageContent(parts));
|
|
21
|
+
};
|
|
22
|
+
try {
|
|
23
|
+
try {
|
|
24
|
+
for (var _d = true, stream_1 = __asyncValues(stream), stream_1_1; stream_1_1 = await stream_1.next(), _a = stream_1_1.done, !_a; _d = true) {
|
|
25
|
+
_c = stream_1_1.value;
|
|
26
|
+
_d = false;
|
|
27
|
+
const event = _c;
|
|
28
|
+
if (getIsCancelled())
|
|
29
|
+
return;
|
|
30
|
+
if (isStreamEndOrErrorEvent(event)) {
|
|
31
|
+
const e = event;
|
|
32
|
+
const finalMessages = buildFinalMessages({
|
|
33
|
+
baseMessages,
|
|
34
|
+
completedAssistantMessages,
|
|
35
|
+
currentAssistantMessageId,
|
|
36
|
+
contentParts,
|
|
37
|
+
});
|
|
38
|
+
if (e.type === 'error' || e.event === 'error' || e.error) {
|
|
39
|
+
if (getIsCancelled())
|
|
40
|
+
return;
|
|
41
|
+
onEnd(finalMessages, 'error', new Error(getStreamErrorMessage(e)));
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
if (getIsCancelled())
|
|
45
|
+
return;
|
|
46
|
+
onEnd(finalMessages, 'done');
|
|
47
|
+
}
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (isMessageOutputItemDoneEvent(event)) {
|
|
51
|
+
completedAssistantMessages.push({
|
|
52
|
+
id: currentAssistantMessageId,
|
|
53
|
+
content: contentPartsToMessageContent(contentParts),
|
|
54
|
+
});
|
|
55
|
+
messageIndex += 1;
|
|
56
|
+
currentAssistantMessageId = getAssistantMessageId(messageIndex);
|
|
57
|
+
contentParts = [];
|
|
58
|
+
if (getIsCancelled())
|
|
59
|
+
return;
|
|
60
|
+
onNewMessage(currentAssistantMessageId);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const update = getStreamEventContentUpdate(event);
|
|
64
|
+
if (!update)
|
|
65
|
+
continue;
|
|
66
|
+
const nextParts = applyContentUpdate(contentParts, update);
|
|
67
|
+
if (nextParts !== null) {
|
|
68
|
+
contentParts = nextParts;
|
|
69
|
+
applyContentToCurrentMessage(contentParts);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
74
|
+
finally {
|
|
75
|
+
try {
|
|
76
|
+
if (!_d && !_a && (_b = stream_1.return)) await _b.call(stream_1);
|
|
77
|
+
}
|
|
78
|
+
finally { if (e_1) throw e_1.error; }
|
|
79
|
+
}
|
|
80
|
+
if (!getIsCancelled()) {
|
|
81
|
+
const finalMessages = buildFinalMessages({
|
|
82
|
+
baseMessages,
|
|
83
|
+
completedAssistantMessages,
|
|
84
|
+
currentAssistantMessageId,
|
|
85
|
+
contentParts,
|
|
86
|
+
});
|
|
87
|
+
onEnd(finalMessages, 'done');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
if (!getIsCancelled()) {
|
|
92
|
+
const finalMessages = buildFinalMessages({
|
|
93
|
+
baseMessages,
|
|
94
|
+
completedAssistantMessages,
|
|
95
|
+
currentAssistantMessageId,
|
|
96
|
+
contentParts,
|
|
97
|
+
});
|
|
98
|
+
onEnd(finalMessages, 'error', err instanceof Error ? err : new Error(String(err)));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
type EventRecord = Record<string, unknown>;
|
|
2
|
+
export declare function isEventOneOf(e: EventRecord, data: EventRecord | undefined, types: string[]): boolean;
|
|
3
|
+
export declare function getDeltaForEventTypes(e: EventRecord, data: EventRecord | undefined, eventTypes: string[]): string | null;
|
|
4
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function isEventOneOf(e, data, types) {
|
|
2
|
+
const t = e.type;
|
|
3
|
+
const ev = e.event;
|
|
4
|
+
const dt = data === null || data === void 0 ? void 0 : data.type;
|
|
5
|
+
return types.some((type) => t === type || ev === type || dt === type);
|
|
6
|
+
}
|
|
7
|
+
export function getDeltaForEventTypes(e, data, eventTypes) {
|
|
8
|
+
var _a, _b;
|
|
9
|
+
if (eventTypes.includes((_a = e.type) !== null && _a !== void 0 ? _a : '') && typeof e.delta === 'string') {
|
|
10
|
+
return e.delta;
|
|
11
|
+
}
|
|
12
|
+
if (!isEventOneOf(e, data, eventTypes)) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const delta = ((_b = data === null || data === void 0 ? void 0 : data.delta) !== null && _b !== void 0 ? _b : e.delta);
|
|
16
|
+
return typeof delta === 'string' ? delta : null;
|
|
17
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { FetchResponseLike, OpenAIStreamEventLike } from '../types';
|
|
2
|
+
/** Fetch Response (text/event-stream) → AsyncIterable of stream events. Handles [DONE], errors; 4xx/5xx yield error. */
|
|
3
|
+
export declare function fetchResponseToStreamEvents(response: FetchResponseLike): AsyncIterable<OpenAIStreamEventLike>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { __asyncGenerator, __await } from "tslib";
|
|
2
|
+
const SSE_DATA_PREFIX = 'data: ';
|
|
3
|
+
function parseSSELine(line) {
|
|
4
|
+
try {
|
|
5
|
+
return JSON.parse(line.slice(SSE_DATA_PREFIX.length));
|
|
6
|
+
}
|
|
7
|
+
catch (_a) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** Fetch Response (text/event-stream) → AsyncIterable of stream events. Handles [DONE], errors; 4xx/5xx yield error. */
|
|
12
|
+
export function fetchResponseToStreamEvents(response) {
|
|
13
|
+
return __asyncGenerator(this, arguments, function* fetchResponseToStreamEvents_1() {
|
|
14
|
+
var _a, _b;
|
|
15
|
+
if (response.ok === false) {
|
|
16
|
+
const message = response.statusText || (response.status ? `HTTP ${response.status}` : 'HTTP error');
|
|
17
|
+
yield yield __await({ type: 'error', error: message });
|
|
18
|
+
return yield __await(void 0);
|
|
19
|
+
}
|
|
20
|
+
const reader = (_a = response.body) === null || _a === void 0 ? void 0 : _a.getReader();
|
|
21
|
+
if (!reader) {
|
|
22
|
+
return yield __await(void 0);
|
|
23
|
+
}
|
|
24
|
+
const decoder = new TextDecoder();
|
|
25
|
+
let buffer = '';
|
|
26
|
+
try {
|
|
27
|
+
while (true) {
|
|
28
|
+
const { done, value } = yield __await(reader.read());
|
|
29
|
+
if (done) {
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
buffer += decoder.decode(value, { stream: true });
|
|
33
|
+
const lines = buffer.split('\n');
|
|
34
|
+
buffer = (_b = lines.pop()) !== null && _b !== void 0 ? _b : '';
|
|
35
|
+
for (const line of lines) {
|
|
36
|
+
const trimmed = line.trim();
|
|
37
|
+
if (trimmed === `${SSE_DATA_PREFIX}[DONE]`) {
|
|
38
|
+
yield yield __await({ type: 'response.done' });
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (!trimmed.startsWith(SSE_DATA_PREFIX)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const parsed = parseSSELine(trimmed);
|
|
45
|
+
if (!parsed) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (parsed.error) {
|
|
49
|
+
yield yield __await({
|
|
50
|
+
type: 'error',
|
|
51
|
+
error: parsed.error,
|
|
52
|
+
});
|
|
53
|
+
return yield __await(void 0);
|
|
54
|
+
}
|
|
55
|
+
yield yield __await(parsed);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
yield yield __await({ type: 'response.done' });
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
reader.releaseLock();
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getStreamErrorMessage(event: Record<string, unknown>): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function getStreamErrorMessage(event) {
|
|
2
|
+
var _a, _b;
|
|
3
|
+
if (typeof event.error === 'string')
|
|
4
|
+
return event.error;
|
|
5
|
+
const dataError = (_a = event.data) === null || _a === void 0 ? void 0 : _a.error;
|
|
6
|
+
if (dataError)
|
|
7
|
+
return dataError;
|
|
8
|
+
const message = (_b = event.error) === null || _b === void 0 ? void 0 : _b.message;
|
|
9
|
+
if (message)
|
|
10
|
+
return message;
|
|
11
|
+
return 'Stream error';
|
|
12
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { TToolStatus } from '../../../types';
|
|
2
|
+
import { OpenAIStreamEventLike } from '../types/openAiTypes';
|
|
3
|
+
export type StreamEventTextDelta = {
|
|
4
|
+
kind: 'text_delta';
|
|
5
|
+
delta: string;
|
|
6
|
+
};
|
|
7
|
+
export type StreamEventToolAdd = {
|
|
8
|
+
kind: 'tool_add';
|
|
9
|
+
id: string;
|
|
10
|
+
toolName: string;
|
|
11
|
+
serverLabel?: string;
|
|
12
|
+
/** Initial status; use 'waitingConfirmation' for mcp_approval_request, 'waitingSubmission' if API defines such. Default 'loading'. */
|
|
13
|
+
status?: TToolStatus;
|
|
14
|
+
/** Optional payload to show in tool card (e.g. approval request arguments). */
|
|
15
|
+
headerContent?: string;
|
|
16
|
+
};
|
|
17
|
+
export type StreamEventToolUpdate = {
|
|
18
|
+
kind: 'tool_update';
|
|
19
|
+
item_id: string;
|
|
20
|
+
status: TToolStatus;
|
|
21
|
+
toolName?: string;
|
|
22
|
+
output?: string;
|
|
23
|
+
error?: string;
|
|
24
|
+
};
|
|
25
|
+
export type StreamEventThinkingAdd = {
|
|
26
|
+
kind: 'thinking_add';
|
|
27
|
+
item_id: string;
|
|
28
|
+
};
|
|
29
|
+
export type StreamEventThinkingDelta = {
|
|
30
|
+
kind: 'thinking_delta';
|
|
31
|
+
item_id: string;
|
|
32
|
+
delta: string;
|
|
33
|
+
};
|
|
34
|
+
export type StreamEventThinkingDone = {
|
|
35
|
+
kind: 'thinking_done';
|
|
36
|
+
item_id: string;
|
|
37
|
+
text: string;
|
|
38
|
+
};
|
|
39
|
+
export type StreamEventContentUpdate = StreamEventTextDelta | StreamEventToolAdd | StreamEventToolUpdate | StreamEventThinkingAdd | StreamEventThinkingDelta | StreamEventThinkingDone;
|
|
40
|
+
/** Stream event → content update (text delta, tool add/update, thinking add/delta/done) or null. */
|
|
41
|
+
export declare function getStreamEventContentUpdate(event: OpenAIStreamEventLike | null | undefined): StreamEventContentUpdate | null;
|