@gravity-ui/aikit 1.4.0 → 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/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/package.json +4 -1
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { getTextDeltaFromStreamEvent } from './getTextDeltaFromStreamEvent';
|
|
2
|
+
const TOOL_PROGRESS_EVENTS = [
|
|
3
|
+
['response.file_search_call.completed', 'success'],
|
|
4
|
+
['response.file_search_call.in_progress', 'loading'],
|
|
5
|
+
['response.file_search_call.searching', 'loading'],
|
|
6
|
+
['response.web_search_call.completed', 'success'],
|
|
7
|
+
['response.web_search_call.in_progress', 'loading'],
|
|
8
|
+
['response.web_search_call.searching', 'loading'],
|
|
9
|
+
['response.code_interpreter_call.completed', 'success'],
|
|
10
|
+
['response.code_interpreter_call.in_progress', 'loading'],
|
|
11
|
+
['response.code_interpreter_call.interpreting', 'loading'],
|
|
12
|
+
['response.image_generation_call.completed', 'success'],
|
|
13
|
+
['response.image_generation_call.in_progress', 'loading'],
|
|
14
|
+
['response.image_generation_call.generating', 'loading'],
|
|
15
|
+
['response.mcp_list_tools.completed', 'success'],
|
|
16
|
+
['response.mcp_list_tools.in_progress', 'loading'],
|
|
17
|
+
];
|
|
18
|
+
function getReasoningUpdate(e, data, type, itemId) {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
if (type === 'response.reasoning_text.delta' ||
|
|
21
|
+
type === 'response.reasoning_summary_text.delta') {
|
|
22
|
+
const d = ((_a = e.delta) !== null && _a !== void 0 ? _a : data === null || data === void 0 ? void 0 : data.delta);
|
|
23
|
+
return typeof d === 'string' ? { kind: 'thinking_delta', item_id: itemId, delta: d } : null;
|
|
24
|
+
}
|
|
25
|
+
if (type === 'response.reasoning_text.done' ||
|
|
26
|
+
type === 'response.reasoning_summary_text.done') {
|
|
27
|
+
const text = ((_b = e.text) !== null && _b !== void 0 ? _b : data === null || data === void 0 ? void 0 : data.text);
|
|
28
|
+
return typeof text === 'string' ? { kind: 'thinking_done', item_id: itemId, text } : null;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
function addUpdateForReasoning(id, itemId) {
|
|
33
|
+
const effectiveId = id || (itemId !== null && itemId !== void 0 ? itemId : '');
|
|
34
|
+
return effectiveId ? { kind: 'thinking_add', item_id: effectiveId } : null;
|
|
35
|
+
}
|
|
36
|
+
function addUpdateForMcpCall(item, id) {
|
|
37
|
+
var _a;
|
|
38
|
+
const name = typeof item.name === 'string' ? item.name : undefined;
|
|
39
|
+
const serverLabel = typeof item.server_label === 'string' ? item.server_label : undefined;
|
|
40
|
+
return {
|
|
41
|
+
kind: 'tool_add',
|
|
42
|
+
id,
|
|
43
|
+
toolName: (_a = name !== null && name !== void 0 ? name : serverLabel) !== null && _a !== void 0 ? _a : 'MCP',
|
|
44
|
+
serverLabel,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function addUpdateForFunctionCall(item) {
|
|
48
|
+
var _a;
|
|
49
|
+
const callId = typeof item.call_id === 'string' ? item.call_id : ((_a = item.id) !== null && _a !== void 0 ? _a : '');
|
|
50
|
+
const name = typeof item.name === 'string' ? item.name : 'Tool';
|
|
51
|
+
return { kind: 'tool_add', id: callId, toolName: name };
|
|
52
|
+
}
|
|
53
|
+
function addUpdateForMcpRequest(item, id, status) {
|
|
54
|
+
var _a;
|
|
55
|
+
const name = typeof item.name === 'string' ? item.name : undefined;
|
|
56
|
+
const serverLabel = typeof item.server_label === 'string' ? item.server_label : undefined;
|
|
57
|
+
const args = typeof item.arguments === 'string' ? item.arguments : undefined;
|
|
58
|
+
return {
|
|
59
|
+
kind: 'tool_add',
|
|
60
|
+
id,
|
|
61
|
+
toolName: (_a = name !== null && name !== void 0 ? name : serverLabel) !== null && _a !== void 0 ? _a : 'MCP',
|
|
62
|
+
serverLabel,
|
|
63
|
+
status,
|
|
64
|
+
headerContent: args,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function addUpdateForSimpleTool(id, toolName) {
|
|
68
|
+
return id ? { kind: 'tool_add', id, toolName } : null;
|
|
69
|
+
}
|
|
70
|
+
const OUTPUT_ITEM_TYPE_TO_TOOL_NAME = {
|
|
71
|
+
file_search_call: 'File Search',
|
|
72
|
+
web_search_call: 'Web Search',
|
|
73
|
+
code_interpreter_call: 'Code Interpreter',
|
|
74
|
+
image_generation_call: 'Image Generation',
|
|
75
|
+
mcp_list_tools: 'MCP List Tools',
|
|
76
|
+
};
|
|
77
|
+
function getUpdateFromOutputItemAdded(e, data, itemId) {
|
|
78
|
+
var _a;
|
|
79
|
+
const item = ((_a = e.item) !== null && _a !== void 0 ? _a : data === null || data === void 0 ? void 0 : data.item);
|
|
80
|
+
if (!item)
|
|
81
|
+
return null;
|
|
82
|
+
const id = typeof item.id === 'string' ? item.id : '';
|
|
83
|
+
if (item.type === 'reasoning')
|
|
84
|
+
return addUpdateForReasoning(id, itemId);
|
|
85
|
+
if (item.type === 'mcp_call')
|
|
86
|
+
return addUpdateForMcpCall(item, id);
|
|
87
|
+
if (item.type === 'function_call')
|
|
88
|
+
return addUpdateForFunctionCall(item);
|
|
89
|
+
if (item.type === 'mcp_approval_request')
|
|
90
|
+
return addUpdateForMcpRequest(item, id, 'waitingConfirmation');
|
|
91
|
+
if (item.type === 'mcp_submission_request')
|
|
92
|
+
return addUpdateForMcpRequest(item, id, 'waitingSubmission');
|
|
93
|
+
const toolName = item.type ? OUTPUT_ITEM_TYPE_TO_TOOL_NAME[item.type] : undefined;
|
|
94
|
+
if (toolName)
|
|
95
|
+
return addUpdateForSimpleTool(id, toolName);
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
function getReasoningDoneUpdate(item) {
|
|
99
|
+
var _a, _b, _c, _d, _e;
|
|
100
|
+
if (item.type !== 'reasoning' || typeof item.id !== 'string')
|
|
101
|
+
return null;
|
|
102
|
+
const reasoning = item;
|
|
103
|
+
const texts = (_d = (_b = (_a = reasoning.content) === null || _a === void 0 ? void 0 : _a.map((c) => c.text).filter((t) => typeof t === 'string')) !== null && _b !== void 0 ? _b : (_c = reasoning.summary) === null || _c === void 0 ? void 0 : _c.map((s) => s.text).filter((t) => typeof t === 'string')) !== null && _d !== void 0 ? _d : [];
|
|
104
|
+
const text = texts.length <= 1 ? ((_e = texts[0]) !== null && _e !== void 0 ? _e : '') : texts.join('\n\n');
|
|
105
|
+
return { kind: 'thinking_done', item_id: reasoning.id, text };
|
|
106
|
+
}
|
|
107
|
+
function getMcpCallDoneUpdate(item) {
|
|
108
|
+
if (item.type !== 'mcp_call' || typeof item.id !== 'string')
|
|
109
|
+
return null;
|
|
110
|
+
const mcp = item;
|
|
111
|
+
let status = 'loading';
|
|
112
|
+
if (mcp.status === 'completed')
|
|
113
|
+
status = 'success';
|
|
114
|
+
else if (mcp.status === 'failed')
|
|
115
|
+
status = 'error';
|
|
116
|
+
let toolName;
|
|
117
|
+
if (typeof mcp.name === 'string')
|
|
118
|
+
toolName = mcp.name;
|
|
119
|
+
else if (typeof mcp.server_label === 'string')
|
|
120
|
+
toolName = mcp.server_label;
|
|
121
|
+
else
|
|
122
|
+
toolName = undefined;
|
|
123
|
+
return {
|
|
124
|
+
kind: 'tool_update',
|
|
125
|
+
item_id: mcp.id,
|
|
126
|
+
status,
|
|
127
|
+
toolName,
|
|
128
|
+
output: typeof mcp.output === 'string' ? mcp.output : undefined,
|
|
129
|
+
error: typeof mcp.error === 'string' ? mcp.error : undefined,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function getFunctionCallDoneUpdate(item) {
|
|
133
|
+
if (item.type !== 'function_call')
|
|
134
|
+
return null;
|
|
135
|
+
const fn = item;
|
|
136
|
+
const fnCallId = fn.call_id ? fn.call_id : '';
|
|
137
|
+
if (!fnCallId)
|
|
138
|
+
return null;
|
|
139
|
+
let fnStatus = 'loading';
|
|
140
|
+
if (fn.status === 'completed') {
|
|
141
|
+
fnStatus = 'success';
|
|
142
|
+
}
|
|
143
|
+
else if (fn.status === 'failed') {
|
|
144
|
+
fnStatus = 'error';
|
|
145
|
+
}
|
|
146
|
+
let output;
|
|
147
|
+
if (typeof fn.output === 'string') {
|
|
148
|
+
output = fn.output;
|
|
149
|
+
}
|
|
150
|
+
else if (typeof fn.result === 'string') {
|
|
151
|
+
output = fn.result;
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
output = undefined;
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
kind: 'tool_update',
|
|
158
|
+
item_id: fnCallId,
|
|
159
|
+
status: fnStatus,
|
|
160
|
+
toolName: typeof fn.name === 'string' ? fn.name : undefined,
|
|
161
|
+
output,
|
|
162
|
+
error: typeof fn.error === 'string' ? fn.error : undefined,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function getToolCallDoneUpdate(item, toolName) {
|
|
166
|
+
if (typeof item.id !== 'string')
|
|
167
|
+
return null;
|
|
168
|
+
const t = item;
|
|
169
|
+
let status = 'loading';
|
|
170
|
+
if (t.status === 'completed')
|
|
171
|
+
status = 'success';
|
|
172
|
+
else if (t.status === 'failed' || t.status === 'incomplete')
|
|
173
|
+
status = 'error';
|
|
174
|
+
let output;
|
|
175
|
+
if (typeof t.output === 'string') {
|
|
176
|
+
output = t.output;
|
|
177
|
+
}
|
|
178
|
+
else if (typeof t.results === 'string') {
|
|
179
|
+
output = t.results;
|
|
180
|
+
}
|
|
181
|
+
else if (Array.isArray(t.results)) {
|
|
182
|
+
output = JSON.stringify(t.results);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
output = undefined;
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
kind: 'tool_update',
|
|
189
|
+
item_id: t.id,
|
|
190
|
+
status,
|
|
191
|
+
toolName,
|
|
192
|
+
output,
|
|
193
|
+
error: typeof t.error === 'string' ? t.error : undefined,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function getUpdateFromOutputItemDone(e, data) {
|
|
197
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
198
|
+
const item = ((_a = e.item) !== null && _a !== void 0 ? _a : data === null || data === void 0 ? void 0 : data.item);
|
|
199
|
+
if (!item)
|
|
200
|
+
return null;
|
|
201
|
+
return ((_h = (_g = (_f = (_e = (_d = (_c = (_b = getReasoningDoneUpdate(item)) !== null && _b !== void 0 ? _b : getMcpCallDoneUpdate(item)) !== null && _c !== void 0 ? _c : getFunctionCallDoneUpdate(item)) !== null && _d !== void 0 ? _d : (item.type === 'file_search_call' ? getToolCallDoneUpdate(item, 'File Search') : null)) !== null && _e !== void 0 ? _e : (item.type === 'web_search_call' ? getToolCallDoneUpdate(item, 'Web Search') : null)) !== null && _f !== void 0 ? _f : (item.type === 'code_interpreter_call'
|
|
202
|
+
? getToolCallDoneUpdate(item, 'Code Interpreter')
|
|
203
|
+
: null)) !== null && _g !== void 0 ? _g : (item.type === 'image_generation_call'
|
|
204
|
+
? getToolCallDoneUpdate(item, 'Image Generation')
|
|
205
|
+
: null)) !== null && _h !== void 0 ? _h : (item.type === 'mcp_list_tools' ? getToolCallDoneUpdate(item, 'MCP List Tools') : null));
|
|
206
|
+
}
|
|
207
|
+
/** Stream event → content update (text delta, tool add/update, thinking add/delta/done) or null. */
|
|
208
|
+
export function getStreamEventContentUpdate(event) {
|
|
209
|
+
var _a, _b, _c;
|
|
210
|
+
if (!event)
|
|
211
|
+
return null;
|
|
212
|
+
const e = event;
|
|
213
|
+
const type = (_c = (_a = e.type) !== null && _a !== void 0 ? _a : (_b = e.data) === null || _b === void 0 ? void 0 : _b.type) !== null && _c !== void 0 ? _c : e.event;
|
|
214
|
+
const data = e.data;
|
|
215
|
+
const itemId = typeof e.item_id === 'string' ? e.item_id : data === null || data === void 0 ? void 0 : data.item_id;
|
|
216
|
+
const delta = getTextDeltaFromStreamEvent(event);
|
|
217
|
+
if (delta)
|
|
218
|
+
return { kind: 'text_delta', delta };
|
|
219
|
+
if (itemId) {
|
|
220
|
+
const reasoningUpdate = getReasoningUpdate(e, data, type, itemId);
|
|
221
|
+
if (reasoningUpdate)
|
|
222
|
+
return reasoningUpdate;
|
|
223
|
+
}
|
|
224
|
+
if (type === 'response.output_item.added') {
|
|
225
|
+
return getUpdateFromOutputItemAdded(e, data, itemId);
|
|
226
|
+
}
|
|
227
|
+
if (type === 'response.mcp_call.completed' && itemId) {
|
|
228
|
+
return { kind: 'tool_update', item_id: itemId, status: 'success' };
|
|
229
|
+
}
|
|
230
|
+
if (type === 'response.mcp_call.failed' && itemId) {
|
|
231
|
+
const err = typeof e.error === 'string' ? e.error : undefined;
|
|
232
|
+
return { kind: 'tool_update', item_id: itemId, status: 'error', error: err };
|
|
233
|
+
}
|
|
234
|
+
const progressMatch = TOOL_PROGRESS_EVENTS.find(([t]) => t === type);
|
|
235
|
+
if (progressMatch && itemId) {
|
|
236
|
+
return { kind: 'tool_update', item_id: itemId, status: progressMatch[1] };
|
|
237
|
+
}
|
|
238
|
+
if (type === 'response.mcp_list_tools.failed' && itemId) {
|
|
239
|
+
const err = typeof e.error === 'string' ? e.error : undefined;
|
|
240
|
+
return { kind: 'tool_update', item_id: itemId, status: 'error', error: err };
|
|
241
|
+
}
|
|
242
|
+
if (type === 'response.output_item.done') {
|
|
243
|
+
return getUpdateFromOutputItemDone(e, data);
|
|
244
|
+
}
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { getDeltaForEventTypes } from './eventTypeUtils';
|
|
2
|
+
import { isOutputTextOrContentPartDone } from './isOutputTextOrContentPartDone';
|
|
3
|
+
/** Text delta from event; *.done ignored to avoid duplicate accumulation. */
|
|
4
|
+
export function getTextDeltaFromStreamEvent(event) {
|
|
5
|
+
var _a;
|
|
6
|
+
if (!event) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
const e = event;
|
|
10
|
+
const data = e.data;
|
|
11
|
+
if (isOutputTextOrContentPartDone(e, data)) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
const outputTextDelta = getDeltaForEventTypes(e, data, ['response.output_text.delta']);
|
|
15
|
+
if (outputTextDelta !== null)
|
|
16
|
+
return outputTextDelta;
|
|
17
|
+
const contentPartDelta = getDeltaForEventTypes(e, data, ['response.content_part.delta']);
|
|
18
|
+
if (contentPartDelta !== null)
|
|
19
|
+
return contentPartDelta;
|
|
20
|
+
const refusalDelta = getDeltaForEventTypes(e, data, ['response.refusal.delta']);
|
|
21
|
+
if (refusalDelta !== null)
|
|
22
|
+
return refusalDelta;
|
|
23
|
+
if (typeof (data === null || data === void 0 ? void 0 : data.text) === 'string') {
|
|
24
|
+
return data.text;
|
|
25
|
+
}
|
|
26
|
+
if (typeof e.text === 'string') {
|
|
27
|
+
return e.text;
|
|
28
|
+
}
|
|
29
|
+
// Legacy: event.event === 'content' && event.data.content
|
|
30
|
+
if (e.event === 'content' && ((_a = e.data) === null || _a === void 0 ? void 0 : _a.content)) {
|
|
31
|
+
return e.data.content;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { isOutputItemDoneEvent } from './isOutputItemDoneEvent';
|
|
2
|
+
/** output_item.done for item.type === 'message' only; other types (MCP, tool, reasoning) return false. */
|
|
3
|
+
export function isMessageOutputItemDoneEvent(event) {
|
|
4
|
+
var _a, _b, _c;
|
|
5
|
+
if (!isOutputItemDoneEvent(event)) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
const e = event;
|
|
9
|
+
const item = (_a = e.item) !== null && _a !== void 0 ? _a : (_b = e.data) === null || _b === void 0 ? void 0 : _b.item;
|
|
10
|
+
if (item === undefined) {
|
|
11
|
+
if (typeof process !== 'undefined' && ((_c = process.env) === null || _c === void 0 ? void 0 : _c.NODE_ENV) !== 'production') {
|
|
12
|
+
/* eslint-disable-next-line no-console */
|
|
13
|
+
console.warn('[useOpenAIStreamAdapter] output_item.done event has no item; treating as message done.', event);
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
return item.type === 'message';
|
|
18
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { isEventOneOf } from './eventTypeUtils';
|
|
2
|
+
const OUTPUT_TEXT_OR_CONTENT_PART_DONE_TYPES = [
|
|
3
|
+
'response.output_text.done',
|
|
4
|
+
'response.content_part.done',
|
|
5
|
+
'response.refusal.done',
|
|
6
|
+
];
|
|
7
|
+
/** *.done (full text) — don't return as delta to avoid duplicating accumulated text. */
|
|
8
|
+
export function isOutputTextOrContentPartDone(e, data) {
|
|
9
|
+
return isEventOneOf(e, data, OUTPUT_TEXT_OR_CONTENT_PART_DONE_TYPES);
|
|
10
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { isEventOneOf } from './eventTypeUtils';
|
|
2
|
+
const STREAM_END_TYPES = ['response.done', 'response.completed', 'response.failed'];
|
|
3
|
+
export function isStreamEndOrErrorEvent(event) {
|
|
4
|
+
if (!event) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
const e = event;
|
|
8
|
+
if (e.type === 'error')
|
|
9
|
+
return true;
|
|
10
|
+
return isEventOneOf(e, e.data, STREAM_END_TYPES);
|
|
11
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { TAssistantMessage } from '../../../types';
|
|
2
|
+
import { OpenAIResponseOutputItem } from '../types/openAiTypes';
|
|
3
|
+
/** OpenAI response output (flat array of message/reasoning/function_call) → TAssistantMessage content. */
|
|
4
|
+
export declare function mapOutputToContent(output: OpenAIResponseOutputItem[] | null | undefined): TAssistantMessage['content'];
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
function pushBlocksForMessage(msg, blocks) {
|
|
2
|
+
var _a;
|
|
3
|
+
for (const part of (_a = msg.content) !== null && _a !== void 0 ? _a : []) {
|
|
4
|
+
if (part.type === 'output_text') {
|
|
5
|
+
blocks.push({ type: 'text', data: { text: part.text } });
|
|
6
|
+
}
|
|
7
|
+
if (part.type === 'refusal') {
|
|
8
|
+
blocks.push({ type: 'text', data: { text: part.refusal } });
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function pushBlocksForReasoning(reasoning, blocks) {
|
|
13
|
+
var _a, _b, _c, _d, _e;
|
|
14
|
+
const content = (_d = (_b = (_a = reasoning.content) === null || _a === void 0 ? void 0 : _a.map((c) => c.text)) !== null && _b !== void 0 ? _b : (_c = reasoning.summary) === null || _c === void 0 ? void 0 : _c.map((s) => s.text)) !== null && _d !== void 0 ? _d : [];
|
|
15
|
+
blocks.push(Object.assign(Object.assign({}, (Boolean(reasoning.id) && { id: reasoning.id })), { type: 'thinking', data: {
|
|
16
|
+
content: content.length <= 1 ? ((_e = content[0]) !== null && _e !== void 0 ? _e : '') : content,
|
|
17
|
+
status: 'thought',
|
|
18
|
+
defaultExpanded: false,
|
|
19
|
+
} }));
|
|
20
|
+
}
|
|
21
|
+
function pushBlocksForFunctionCall(fn, blocks) {
|
|
22
|
+
blocks.push({
|
|
23
|
+
type: 'tool',
|
|
24
|
+
id: fn.call_id,
|
|
25
|
+
data: { toolName: fn.name, status: 'loading' },
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function pushBlocksForMcpCall(mcp, blocks) {
|
|
29
|
+
var _a, _b, _c, _d, _e;
|
|
30
|
+
const statusByMcpStatus = {
|
|
31
|
+
completed: 'success',
|
|
32
|
+
failed: 'error',
|
|
33
|
+
};
|
|
34
|
+
const status = (_b = statusByMcpStatus[(_a = mcp.status) !== null && _a !== void 0 ? _a : '']) !== null && _b !== void 0 ? _b : 'loading';
|
|
35
|
+
blocks.push({
|
|
36
|
+
type: 'tool',
|
|
37
|
+
id: mcp.id,
|
|
38
|
+
data: {
|
|
39
|
+
toolName: (_d = (_c = mcp.name) !== null && _c !== void 0 ? _c : mcp.server_label) !== null && _d !== void 0 ? _d : 'MCP',
|
|
40
|
+
status,
|
|
41
|
+
headerContent: (_e = mcp.output) !== null && _e !== void 0 ? _e : undefined,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function pushBlocksForItem(item, blocks) {
|
|
46
|
+
if (item.type === 'message' && 'role' in item && item.role === 'assistant') {
|
|
47
|
+
pushBlocksForMessage(item, blocks);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (item.type === 'reasoning') {
|
|
51
|
+
pushBlocksForReasoning(item, blocks);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (item.type === 'function_call') {
|
|
55
|
+
pushBlocksForFunctionCall(item, blocks);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (item.type === 'mcp_call') {
|
|
59
|
+
pushBlocksForMcpCall(item, blocks);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** OpenAI response output (flat array of message/reasoning/function_call) → TAssistantMessage content. */
|
|
63
|
+
export function mapOutputToContent(output) {
|
|
64
|
+
const blocks = [];
|
|
65
|
+
for (const item of output !== null && output !== void 0 ? output : []) {
|
|
66
|
+
pushBlocksForItem(item, blocks);
|
|
67
|
+
}
|
|
68
|
+
if (blocks.length === 0)
|
|
69
|
+
return '';
|
|
70
|
+
if (blocks.length === 1 && blocks[0].type === 'text')
|
|
71
|
+
return blocks[0].data.text;
|
|
72
|
+
return blocks;
|
|
73
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { TChatMessage } from '../../../types';
|
|
2
|
+
import { OpenAIResponseLike } from '../types/openAiTypes';
|
|
3
|
+
/** Single response → TChatMessage[] (one assistant message; output items merged into content). */
|
|
4
|
+
export declare function openAIResponseToMessages(response: OpenAIResponseLike | null): TChatMessage[];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { mapOutputToContent } from './mapOutputToContent';
|
|
2
|
+
function toMessageMetadata(value) {
|
|
3
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
4
|
+
return value;
|
|
5
|
+
}
|
|
6
|
+
return {};
|
|
7
|
+
}
|
|
8
|
+
/** Single response → TChatMessage[] (one assistant message; output items merged into content). */
|
|
9
|
+
export function openAIResponseToMessages(response) {
|
|
10
|
+
var _a, _b;
|
|
11
|
+
if (!((_a = response === null || response === void 0 ? void 0 : response.output) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
const baseMeta = toMessageMetadata(response.metadata);
|
|
15
|
+
const content = mapOutputToContent(response.output);
|
|
16
|
+
const firstMessage = response.output.find((item) => item.type === 'message' && 'role' in item && item.role === 'assistant');
|
|
17
|
+
const id = (_b = firstMessage === null || firstMessage === void 0 ? void 0 : firstMessage.id) !== null && _b !== void 0 ? _b : response.id;
|
|
18
|
+
const assistantMessage = Object.assign(Object.assign(Object.assign({}, (id && { id })), { role: 'assistant', content: content || '', metadata: baseMeta }), (response.error && { error: response.error }));
|
|
19
|
+
return [assistantMessage];
|
|
20
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { fetchResponseToStreamEvents } from './helpers/fetchResponseToStreamEvents';
|
|
2
|
+
export { getTextDeltaFromStreamEvent } from './helpers/getTextDeltaFromStreamEvent';
|
|
3
|
+
export { isFetchResponse } from './helpers/isFetchResponse';
|
|
4
|
+
export { isOutputItemDoneEvent } from './helpers/isOutputItemDoneEvent';
|
|
5
|
+
export { isStreamEndOrErrorEvent } from './helpers/isStreamEndOrErrorEvent';
|
|
6
|
+
export { openAIResponseToMessages } from './helpers/openAIResponseToMessages';
|
|
7
|
+
export { useOpenAIResponsesAdapter, useOpenAIStreamAdapter } from './useOpenAIResponsesAdapter';
|
|
8
|
+
export type { OpenAIStreamAdapterOptions, OpenAIStreamAdapterResult, OpenAIStreamSource, } from './types';
|
|
9
|
+
export type { FetchResponseLike, OpenAIStreamEventLike } from './types';
|
|
10
|
+
export type { OpenAIResponseLike } from './types/openAiTypes';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { fetchResponseToStreamEvents } from './helpers/fetchResponseToStreamEvents';
|
|
2
|
+
export { getTextDeltaFromStreamEvent } from './helpers/getTextDeltaFromStreamEvent';
|
|
3
|
+
export { isFetchResponse } from './helpers/isFetchResponse';
|
|
4
|
+
export { isOutputItemDoneEvent } from './helpers/isOutputItemDoneEvent';
|
|
5
|
+
export { isStreamEndOrErrorEvent } from './helpers/isStreamEndOrErrorEvent';
|
|
6
|
+
export { openAIResponseToMessages } from './helpers/openAIResponseToMessages';
|
|
7
|
+
export { useOpenAIResponsesAdapter, useOpenAIStreamAdapter } from './useOpenAIResponsesAdapter';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { TChatMessage } from '../../../types';
|
|
2
|
+
import type { OpenAIStreamEventLike } from './openAiTypes';
|
|
3
|
+
export type FetchResponseLike = {
|
|
4
|
+
body?: ReadableStream<Uint8Array> | null;
|
|
5
|
+
ok?: boolean;
|
|
6
|
+
status?: number;
|
|
7
|
+
statusText?: string;
|
|
8
|
+
};
|
|
9
|
+
export type { OpenAIStreamEventLike } from './openAiTypes';
|
|
10
|
+
export type OpenAIStreamAdapterOptions = {
|
|
11
|
+
initialMessages?: TChatMessage[];
|
|
12
|
+
assistantMessageId?: string;
|
|
13
|
+
onStreamEnd?: (messages: TChatMessage[]) => void;
|
|
14
|
+
};
|
|
15
|
+
export type OpenAIStreamAdapterResult = {
|
|
16
|
+
messages: TChatMessage[];
|
|
17
|
+
status: 'idle' | 'streaming' | 'done' | 'error';
|
|
18
|
+
error: Error | null;
|
|
19
|
+
};
|
|
20
|
+
export type OpenAIStreamSource = AsyncIterable<OpenAIStreamEventLike> | FetchResponseLike;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|