@osdk/aip-core 0.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/CHANGELOG.md +20 -0
- package/README.md +211 -0
- package/ai-sdk.d.ts +17 -0
- package/build/browser/ai-sdk/convert-prompt.js +136 -0
- package/build/browser/ai-sdk/convert-prompt.js.map +1 -0
- package/build/browser/ai-sdk/foundry-chat-language-model.js +386 -0
- package/build/browser/ai-sdk/foundry-chat-language-model.js.map +1 -0
- package/build/browser/ai-sdk/map-finish-reason.js +42 -0
- package/build/browser/ai-sdk/map-finish-reason.js.map +1 -0
- package/build/browser/ai-sdk/provider.js +62 -0
- package/build/browser/ai-sdk/provider.js.map +1 -0
- package/build/browser/ai-sdk/types.js +2 -0
- package/build/browser/ai-sdk/types.js.map +1 -0
- package/build/browser/generateText.js +76 -0
- package/build/browser/generateText.js.map +1 -0
- package/build/browser/index.js +23 -0
- package/build/browser/index.js.map +1 -0
- package/build/browser/internal/__test__/mockPlatformClient.js +36 -0
- package/build/browser/internal/__test__/mockPlatformClient.js.map +1 -0
- package/build/browser/internal/ids.js +23 -0
- package/build/browser/internal/ids.js.map +1 -0
- package/build/browser/internal/openAi.js +293 -0
- package/build/browser/internal/openAi.js.map +1 -0
- package/build/browser/internal/options.js +58 -0
- package/build/browser/internal/options.js.map +1 -0
- package/build/browser/internal/runStep.js +107 -0
- package/build/browser/internal/runStep.js.map +1 -0
- package/build/browser/internal/streamStep.js +223 -0
- package/build/browser/internal/streamStep.js.map +1 -0
- package/build/browser/internal/uiMessageBridge.js +55 -0
- package/build/browser/internal/uiMessageBridge.js.map +1 -0
- package/build/browser/lmsChatTransport.js +185 -0
- package/build/browser/lmsChatTransport.js.map +1 -0
- package/build/browser/model.js +74 -0
- package/build/browser/model.js.map +1 -0
- package/build/browser/public/ai-sdk.js +18 -0
- package/build/browser/public/ai-sdk.js.map +1 -0
- package/build/browser/streamText.js +210 -0
- package/build/browser/streamText.js.map +1 -0
- package/build/browser/types.js +2 -0
- package/build/browser/types.js.map +1 -0
- package/build/browser/uiMessage.js +34 -0
- package/build/browser/uiMessage.js.map +1 -0
- package/build/cjs/index.cjs +1012 -0
- package/build/cjs/index.cjs.map +1 -0
- package/build/cjs/index.d.cts +467 -0
- package/build/cjs/model-B5uS56VB.d.cts +45 -0
- package/build/cjs/public/ai-sdk.cjs +534 -0
- package/build/cjs/public/ai-sdk.cjs.map +1 -0
- package/build/cjs/public/ai-sdk.d.cts +49 -0
- package/build/esm/ai-sdk/convert-prompt.js +136 -0
- package/build/esm/ai-sdk/convert-prompt.js.map +1 -0
- package/build/esm/ai-sdk/foundry-chat-language-model.js +386 -0
- package/build/esm/ai-sdk/foundry-chat-language-model.js.map +1 -0
- package/build/esm/ai-sdk/map-finish-reason.js +42 -0
- package/build/esm/ai-sdk/map-finish-reason.js.map +1 -0
- package/build/esm/ai-sdk/provider.js +62 -0
- package/build/esm/ai-sdk/provider.js.map +1 -0
- package/build/esm/ai-sdk/types.js +2 -0
- package/build/esm/ai-sdk/types.js.map +1 -0
- package/build/esm/generateText.js +76 -0
- package/build/esm/generateText.js.map +1 -0
- package/build/esm/index.js +23 -0
- package/build/esm/index.js.map +1 -0
- package/build/esm/internal/__test__/mockPlatformClient.js +36 -0
- package/build/esm/internal/__test__/mockPlatformClient.js.map +1 -0
- package/build/esm/internal/ids.js +23 -0
- package/build/esm/internal/ids.js.map +1 -0
- package/build/esm/internal/openAi.js +293 -0
- package/build/esm/internal/openAi.js.map +1 -0
- package/build/esm/internal/options.js +58 -0
- package/build/esm/internal/options.js.map +1 -0
- package/build/esm/internal/runStep.js +107 -0
- package/build/esm/internal/runStep.js.map +1 -0
- package/build/esm/internal/streamStep.js +223 -0
- package/build/esm/internal/streamStep.js.map +1 -0
- package/build/esm/internal/uiMessageBridge.js +55 -0
- package/build/esm/internal/uiMessageBridge.js.map +1 -0
- package/build/esm/lmsChatTransport.js +185 -0
- package/build/esm/lmsChatTransport.js.map +1 -0
- package/build/esm/model.js +74 -0
- package/build/esm/model.js.map +1 -0
- package/build/esm/public/ai-sdk.js +18 -0
- package/build/esm/public/ai-sdk.js.map +1 -0
- package/build/esm/streamText.js +210 -0
- package/build/esm/streamText.js.map +1 -0
- package/build/esm/types.js +2 -0
- package/build/esm/types.js.map +1 -0
- package/build/esm/uiMessage.js +34 -0
- package/build/esm/uiMessage.js.map +1 -0
- package/build/types/ai-sdk/convert-prompt.d.ts +19 -0
- package/build/types/ai-sdk/convert-prompt.d.ts.map +1 -0
- package/build/types/ai-sdk/foundry-chat-language-model.d.ts +20 -0
- package/build/types/ai-sdk/foundry-chat-language-model.d.ts.map +1 -0
- package/build/types/ai-sdk/map-finish-reason.d.ts +2 -0
- package/build/types/ai-sdk/map-finish-reason.d.ts.map +1 -0
- package/build/types/ai-sdk/provider.d.ts +46 -0
- package/build/types/ai-sdk/provider.d.ts.map +1 -0
- package/build/types/ai-sdk/types.d.ts +1 -0
- package/build/types/ai-sdk/types.d.ts.map +1 -0
- package/build/types/generateText.d.ts +56 -0
- package/build/types/generateText.d.ts.map +1 -0
- package/build/types/index.d.ts +12 -0
- package/build/types/index.d.ts.map +1 -0
- package/build/types/internal/__test__/mockPlatformClient.d.ts +13 -0
- package/build/types/internal/__test__/mockPlatformClient.d.ts.map +1 -0
- package/build/types/internal/ids.d.ts +1 -0
- package/build/types/internal/ids.d.ts.map +1 -0
- package/build/types/internal/openAi.d.ts +107 -0
- package/build/types/internal/openAi.d.ts.map +1 -0
- package/build/types/internal/options.d.ts +4 -0
- package/build/types/internal/options.d.ts.map +1 -0
- package/build/types/internal/runStep.d.ts +29 -0
- package/build/types/internal/runStep.d.ts.map +1 -0
- package/build/types/internal/streamStep.d.ts +52 -0
- package/build/types/internal/streamStep.d.ts.map +1 -0
- package/build/types/internal/uiMessageBridge.d.ts +15 -0
- package/build/types/internal/uiMessageBridge.d.ts.map +1 -0
- package/build/types/lmsChatTransport.d.ts +35 -0
- package/build/types/lmsChatTransport.d.ts.map +1 -0
- package/build/types/model.d.ts +42 -0
- package/build/types/model.d.ts.map +1 -0
- package/build/types/public/ai-sdk.d.ts +2 -0
- package/build/types/public/ai-sdk.d.ts.map +1 -0
- package/build/types/streamText.d.ts +82 -0
- package/build/types/streamText.d.ts.map +1 -0
- package/build/types/types.d.ts +189 -0
- package/build/types/types.d.ts.map +1 -0
- package/build/types/uiMessage.d.ts +85 -0
- package/build/types/uiMessage.d.ts.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,1012 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var languageModels = require('@osdk/language-models');
|
|
4
|
+
|
|
5
|
+
// src/internal/options.ts
|
|
6
|
+
function resolveMessages(callerLabel, system, prompt, messages) {
|
|
7
|
+
if (prompt != null && messages != null) {
|
|
8
|
+
throw new Error(`${callerLabel}: cannot specify both \`prompt\` and \`messages\`: choose one.`);
|
|
9
|
+
}
|
|
10
|
+
const sys = resolveSystem(system);
|
|
11
|
+
const body = resolveBody(prompt, messages);
|
|
12
|
+
if (sys.length === 0 && body.length === 0) {
|
|
13
|
+
throw new Error(`${callerLabel}: must provide at least one of \`system\`, \`prompt\`, or \`messages\`.`);
|
|
14
|
+
}
|
|
15
|
+
return [...sys, ...body];
|
|
16
|
+
}
|
|
17
|
+
function resolveSystem(system) {
|
|
18
|
+
if (system == null) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
if (typeof system === "string") {
|
|
22
|
+
return system === "" ? [] : [{
|
|
23
|
+
role: "system",
|
|
24
|
+
content: system
|
|
25
|
+
}];
|
|
26
|
+
}
|
|
27
|
+
if (Array.isArray(system)) {
|
|
28
|
+
return system;
|
|
29
|
+
}
|
|
30
|
+
return [system];
|
|
31
|
+
}
|
|
32
|
+
function resolveBody(prompt, messages) {
|
|
33
|
+
if (messages != null) {
|
|
34
|
+
return messages;
|
|
35
|
+
}
|
|
36
|
+
if (prompt == null) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
if (typeof prompt === "string") {
|
|
40
|
+
return [{
|
|
41
|
+
role: "user",
|
|
42
|
+
content: prompt
|
|
43
|
+
}];
|
|
44
|
+
}
|
|
45
|
+
return prompt;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/model.ts
|
|
49
|
+
var internals = /* @__PURE__ */ new WeakMap();
|
|
50
|
+
function foundryModel(options) {
|
|
51
|
+
const identifier = typeof options.model === "string" ? {
|
|
52
|
+
type: "lmsModel",
|
|
53
|
+
apiName: options.model
|
|
54
|
+
} : options.model;
|
|
55
|
+
const id = identifier.type === "lmsModel" ? identifier.apiName : identifier.registeredModelRid;
|
|
56
|
+
const handle = Object.freeze({
|
|
57
|
+
modelId: `foundry/${id}`,
|
|
58
|
+
provider: "foundry-lms"
|
|
59
|
+
});
|
|
60
|
+
internals.set(handle, {
|
|
61
|
+
client: options.client,
|
|
62
|
+
identifier
|
|
63
|
+
});
|
|
64
|
+
return handle;
|
|
65
|
+
}
|
|
66
|
+
function _getFoundryInternal(model) {
|
|
67
|
+
const handle = internals.get(model);
|
|
68
|
+
if (handle == null) {
|
|
69
|
+
throw new Error(`LanguageModel(modelId=${model.modelId}, provider=${model.provider}) was not constructed via foundryModel(). Only foundry-lms models are supported in v0.`);
|
|
70
|
+
}
|
|
71
|
+
return handle;
|
|
72
|
+
}
|
|
73
|
+
function getModelApiName(identifier) {
|
|
74
|
+
return identifier.type === "lmsModel" ? identifier.apiName : identifier.registeredModelRid;
|
|
75
|
+
}
|
|
76
|
+
function mapUsage(raw) {
|
|
77
|
+
return {
|
|
78
|
+
inputTokens: raw.prompt_tokens,
|
|
79
|
+
outputTokens: raw.completion_tokens,
|
|
80
|
+
totalTokens: raw.total_tokens,
|
|
81
|
+
reasoningTokens: raw.completion_tokens_details?.reasoning_tokens,
|
|
82
|
+
cachedInputTokens: raw.prompt_tokens_details?.cached_tokens
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
var EMPTY_USAGE = {
|
|
86
|
+
inputTokens: void 0,
|
|
87
|
+
outputTokens: void 0,
|
|
88
|
+
totalTokens: void 0
|
|
89
|
+
};
|
|
90
|
+
function mapFinishReason(reason) {
|
|
91
|
+
switch (reason) {
|
|
92
|
+
case "stop":
|
|
93
|
+
return "stop";
|
|
94
|
+
case "length":
|
|
95
|
+
return "length";
|
|
96
|
+
case "tool_calls":
|
|
97
|
+
case "function_call":
|
|
98
|
+
return "tool-calls";
|
|
99
|
+
case "content_filter":
|
|
100
|
+
return "content-filter";
|
|
101
|
+
default:
|
|
102
|
+
return "other";
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function convertMessage(m, warnings) {
|
|
106
|
+
switch (m.role) {
|
|
107
|
+
case "system":
|
|
108
|
+
return [{
|
|
109
|
+
role: "system",
|
|
110
|
+
content: m.content
|
|
111
|
+
}];
|
|
112
|
+
case "user": {
|
|
113
|
+
if (typeof m.content === "string") {
|
|
114
|
+
return [{
|
|
115
|
+
role: "user",
|
|
116
|
+
content: m.content
|
|
117
|
+
}];
|
|
118
|
+
}
|
|
119
|
+
const parts = [];
|
|
120
|
+
for (const p of m.content) {
|
|
121
|
+
if (p.type === "text") {
|
|
122
|
+
parts.push({
|
|
123
|
+
type: "text",
|
|
124
|
+
text: p.text
|
|
125
|
+
});
|
|
126
|
+
} else {
|
|
127
|
+
warnings.push({
|
|
128
|
+
type: "other",
|
|
129
|
+
message: `Unsupported user content part "${p.type}": ignored in v0`
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return [{
|
|
134
|
+
role: "user",
|
|
135
|
+
content: parts
|
|
136
|
+
}];
|
|
137
|
+
}
|
|
138
|
+
case "assistant": {
|
|
139
|
+
if (typeof m.content === "string") {
|
|
140
|
+
return [{
|
|
141
|
+
role: "assistant",
|
|
142
|
+
content: m.content
|
|
143
|
+
}];
|
|
144
|
+
}
|
|
145
|
+
let text = "";
|
|
146
|
+
const toolCalls = [];
|
|
147
|
+
for (const p of m.content) {
|
|
148
|
+
switch (p.type) {
|
|
149
|
+
case "text":
|
|
150
|
+
text += p.text;
|
|
151
|
+
break;
|
|
152
|
+
case "tool-call":
|
|
153
|
+
toolCalls.push({
|
|
154
|
+
id: p.toolCallId,
|
|
155
|
+
type: "function",
|
|
156
|
+
function: {
|
|
157
|
+
name: p.toolName,
|
|
158
|
+
arguments: JSON.stringify(p.input ?? {})
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
break;
|
|
162
|
+
case "reasoning":
|
|
163
|
+
case "file":
|
|
164
|
+
warnings.push({
|
|
165
|
+
type: "other",
|
|
166
|
+
message: `Unsupported assistant content part "${p.type}": ignored in v0`
|
|
167
|
+
});
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return [{
|
|
172
|
+
role: "assistant",
|
|
173
|
+
content: text.length > 0 ? text : null,
|
|
174
|
+
tool_calls: toolCalls.length > 0 ? toolCalls : void 0
|
|
175
|
+
}];
|
|
176
|
+
}
|
|
177
|
+
case "tool":
|
|
178
|
+
return m.content.map((part) => ({
|
|
179
|
+
role: "tool",
|
|
180
|
+
content: stringifyToolResult(part, warnings),
|
|
181
|
+
tool_call_id: part.toolCallId
|
|
182
|
+
}));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function stringifyToolResult(part, warnings) {
|
|
186
|
+
switch (part.output.type) {
|
|
187
|
+
case "text":
|
|
188
|
+
case "error-text":
|
|
189
|
+
return part.output.value;
|
|
190
|
+
case "json":
|
|
191
|
+
case "error-json":
|
|
192
|
+
return JSON.stringify(part.output.value);
|
|
193
|
+
case "content":
|
|
194
|
+
return part.output.value.map((c) => {
|
|
195
|
+
if (c.type === "text") {
|
|
196
|
+
return c.text;
|
|
197
|
+
}
|
|
198
|
+
warnings.push({
|
|
199
|
+
type: "other",
|
|
200
|
+
message: `Unsupported tool result media: ignored in v0`
|
|
201
|
+
});
|
|
202
|
+
return "";
|
|
203
|
+
}).filter((s) => s.length > 0).join("\n");
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function convertTools(tools, warnings) {
|
|
207
|
+
return Object.entries(tools).map(([name, tool]) => {
|
|
208
|
+
const parameters = isJsonSchemaLike(tool.inputSchema) ? tool.inputSchema : (warnings.push({
|
|
209
|
+
type: "unsupported-tool",
|
|
210
|
+
details: `Tool "${name}" inputSchema is not a JSON Schema; v0 only supports plain JSON Schema objects. Defaulting to {} parameters.`
|
|
211
|
+
}), {
|
|
212
|
+
type: "object",
|
|
213
|
+
properties: {}
|
|
214
|
+
});
|
|
215
|
+
return {
|
|
216
|
+
type: "function",
|
|
217
|
+
function: {
|
|
218
|
+
name,
|
|
219
|
+
description: tool.description,
|
|
220
|
+
parameters
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
function convertToolChoice(choice) {
|
|
226
|
+
if (choice == null) {
|
|
227
|
+
return void 0;
|
|
228
|
+
}
|
|
229
|
+
if (choice === "auto" || choice === "none" || choice === "required") {
|
|
230
|
+
return choice;
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
type: "function",
|
|
234
|
+
function: {
|
|
235
|
+
name: choice.toolName
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function isJsonSchemaLike(value) {
|
|
240
|
+
return typeof value === "object" && value != null && ("type" in value || "properties" in value || "$ref" in value || "oneOf" in value || "anyOf" in value || "allOf" in value);
|
|
241
|
+
}
|
|
242
|
+
function parseToolArguments(args, warnings) {
|
|
243
|
+
if (args === "") {
|
|
244
|
+
return {};
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
return JSON.parse(args);
|
|
248
|
+
} catch {
|
|
249
|
+
warnings.push({
|
|
250
|
+
type: "other",
|
|
251
|
+
message: `Tool call arguments were not valid JSON; passing through as a raw string`
|
|
252
|
+
});
|
|
253
|
+
return args;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function buildOpenAiRequestBody(args, streaming) {
|
|
257
|
+
const common = {
|
|
258
|
+
model: args.apiName,
|
|
259
|
+
messages: args.messages.map((m) => convertMessage(m, args.warnings)).flat(),
|
|
260
|
+
max_tokens: args.maxOutputTokens,
|
|
261
|
+
temperature: args.temperature,
|
|
262
|
+
top_p: args.topP,
|
|
263
|
+
stop: args.stopSequences,
|
|
264
|
+
seed: args.seed,
|
|
265
|
+
presence_penalty: args.presencePenalty,
|
|
266
|
+
frequency_penalty: args.frequencyPenalty,
|
|
267
|
+
tools: args.tools != null ? convertTools(args.tools, args.warnings) : void 0,
|
|
268
|
+
tool_choice: convertToolChoice(args.toolChoice)
|
|
269
|
+
};
|
|
270
|
+
if (streaming) {
|
|
271
|
+
return {
|
|
272
|
+
...common,
|
|
273
|
+
stream: true,
|
|
274
|
+
stream_options: {
|
|
275
|
+
include_usage: true
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
...common,
|
|
281
|
+
stream: false
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function buildAssistantContent(text, toolCalls) {
|
|
285
|
+
if (toolCalls.length === 0) {
|
|
286
|
+
return text;
|
|
287
|
+
}
|
|
288
|
+
const parts = [];
|
|
289
|
+
if (text.length > 0) {
|
|
290
|
+
parts.push({
|
|
291
|
+
type: "text",
|
|
292
|
+
text
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
for (const tc of toolCalls) {
|
|
296
|
+
parts.push({
|
|
297
|
+
type: "tool-call",
|
|
298
|
+
toolCallId: tc.toolCallId,
|
|
299
|
+
toolName: tc.toolName,
|
|
300
|
+
input: tc.input
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
return parts;
|
|
304
|
+
}
|
|
305
|
+
function filterHeaders(input) {
|
|
306
|
+
const out = {};
|
|
307
|
+
for (const [k, v] of Object.entries(input)) {
|
|
308
|
+
if (v != null) {
|
|
309
|
+
out[k] = v;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return out;
|
|
313
|
+
}
|
|
314
|
+
async function safeReadText(res) {
|
|
315
|
+
try {
|
|
316
|
+
return await res.text();
|
|
317
|
+
} catch {
|
|
318
|
+
return void 0;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
async function postChatCompletions(args) {
|
|
322
|
+
const handle = _getFoundryInternal(args.model);
|
|
323
|
+
const baseUrl = languageModels.getOpenAiBaseUrl(handle.client);
|
|
324
|
+
const url = new URL("chat/completions", `${baseUrl}/`).toString();
|
|
325
|
+
const res = await handle.client.fetch(url, {
|
|
326
|
+
method: "POST",
|
|
327
|
+
headers: filterHeaders({
|
|
328
|
+
"Content-Type": "application/json",
|
|
329
|
+
Accept: args.accept,
|
|
330
|
+
...args.headers ?? {}
|
|
331
|
+
}),
|
|
332
|
+
body: JSON.stringify(args.body),
|
|
333
|
+
signal: args.abortSignal
|
|
334
|
+
});
|
|
335
|
+
if (!res.ok) {
|
|
336
|
+
const errBody = await safeReadText(res);
|
|
337
|
+
throw new Error(`LMS chat/completions request failed: ${res.status} ${res.statusText}` + (errBody ? `: ${errBody}` : ""));
|
|
338
|
+
}
|
|
339
|
+
return res;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// src/internal/runStep.ts
|
|
343
|
+
async function runStep(input) {
|
|
344
|
+
const apiName = getModelApiName(_getFoundryInternal(input.model).identifier);
|
|
345
|
+
const body = buildOpenAiRequestBody({
|
|
346
|
+
apiName,
|
|
347
|
+
...input
|
|
348
|
+
}, false);
|
|
349
|
+
const res = await postChatCompletions({
|
|
350
|
+
model: input.model,
|
|
351
|
+
body,
|
|
352
|
+
accept: "application/json",
|
|
353
|
+
headers: input.headers,
|
|
354
|
+
abortSignal: input.abortSignal
|
|
355
|
+
});
|
|
356
|
+
const data = await res.json();
|
|
357
|
+
return parseResponse(data, body, input.warnings);
|
|
358
|
+
}
|
|
359
|
+
function parseResponse(res, request, warnings) {
|
|
360
|
+
const choice = res.choices[0];
|
|
361
|
+
if (choice == null) {
|
|
362
|
+
throw new Error("LMS chat/completions response did not include any choices");
|
|
363
|
+
}
|
|
364
|
+
const message = choice.message;
|
|
365
|
+
const text = message.content ?? "";
|
|
366
|
+
const reasoningText = message.reasoning ?? message.reasoning_content;
|
|
367
|
+
const toolCalls = (message.tool_calls ?? []).map((c) => ({
|
|
368
|
+
type: "tool-call",
|
|
369
|
+
toolCallId: c.id,
|
|
370
|
+
toolName: c.function.name,
|
|
371
|
+
input: parseToolArguments(c.function.arguments, warnings)
|
|
372
|
+
}));
|
|
373
|
+
const reasoning = reasoningText != null ? [{
|
|
374
|
+
type: "reasoning",
|
|
375
|
+
text: reasoningText
|
|
376
|
+
}] : [];
|
|
377
|
+
const content = [];
|
|
378
|
+
if (text.length > 0) {
|
|
379
|
+
content.push({
|
|
380
|
+
type: "text",
|
|
381
|
+
text
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
for (const r of reasoning) {
|
|
385
|
+
content.push({
|
|
386
|
+
type: "reasoning",
|
|
387
|
+
text: r.text
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
for (const tc of toolCalls) {
|
|
391
|
+
content.push({
|
|
392
|
+
...tc,
|
|
393
|
+
type: "tool-call"
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
const usage = res.usage != null ? mapUsage(res.usage) : EMPTY_USAGE;
|
|
397
|
+
const finishReason = mapFinishReason(choice.finish_reason);
|
|
398
|
+
const responseMessages = [{
|
|
399
|
+
role: "assistant",
|
|
400
|
+
content: buildAssistantContent(text, toolCalls)
|
|
401
|
+
}];
|
|
402
|
+
return {
|
|
403
|
+
content,
|
|
404
|
+
text,
|
|
405
|
+
reasoning,
|
|
406
|
+
reasoningText,
|
|
407
|
+
toolCalls,
|
|
408
|
+
toolResults: [],
|
|
409
|
+
finishReason,
|
|
410
|
+
rawFinishReason: choice.finish_reason,
|
|
411
|
+
usage,
|
|
412
|
+
warnings: warnings.length > 0 ? warnings : void 0,
|
|
413
|
+
request: {
|
|
414
|
+
body: request
|
|
415
|
+
},
|
|
416
|
+
response: {
|
|
417
|
+
id: res.id,
|
|
418
|
+
modelId: res.model,
|
|
419
|
+
timestamp: new Date(res.created * 1e3),
|
|
420
|
+
body: res,
|
|
421
|
+
messages: responseMessages
|
|
422
|
+
},
|
|
423
|
+
providerMetadata: void 0
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// src/generateText.ts
|
|
428
|
+
async function generateText(options) {
|
|
429
|
+
const messages = resolveMessages("generateText", options.system, options.prompt, options.messages);
|
|
430
|
+
const step = await runStep({
|
|
431
|
+
model: options.model,
|
|
432
|
+
messages,
|
|
433
|
+
tools: options.tools,
|
|
434
|
+
toolChoice: options.toolChoice,
|
|
435
|
+
maxOutputTokens: options.maxOutputTokens,
|
|
436
|
+
temperature: options.temperature,
|
|
437
|
+
topP: options.topP,
|
|
438
|
+
stopSequences: options.stopSequences,
|
|
439
|
+
seed: options.seed,
|
|
440
|
+
presencePenalty: options.presencePenalty,
|
|
441
|
+
frequencyPenalty: options.frequencyPenalty,
|
|
442
|
+
abortSignal: options.abortSignal,
|
|
443
|
+
headers: options.headers,
|
|
444
|
+
warnings: []
|
|
445
|
+
});
|
|
446
|
+
await options.onStepFinish?.(step);
|
|
447
|
+
const totalUsage = step.usage;
|
|
448
|
+
await options.onFinish?.({
|
|
449
|
+
...step,
|
|
450
|
+
steps: [step],
|
|
451
|
+
totalUsage
|
|
452
|
+
});
|
|
453
|
+
return {
|
|
454
|
+
...step,
|
|
455
|
+
totalUsage,
|
|
456
|
+
steps: [step]
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// src/internal/streamStep.ts
|
|
461
|
+
async function streamStep(input) {
|
|
462
|
+
const apiName = getModelApiName(_getFoundryInternal(input.model).identifier);
|
|
463
|
+
const body = buildOpenAiRequestBody({
|
|
464
|
+
apiName,
|
|
465
|
+
...input
|
|
466
|
+
}, true);
|
|
467
|
+
const res = await postChatCompletions({
|
|
468
|
+
model: input.model,
|
|
469
|
+
body,
|
|
470
|
+
accept: "text/event-stream",
|
|
471
|
+
headers: input.headers,
|
|
472
|
+
abortSignal: input.abortSignal
|
|
473
|
+
});
|
|
474
|
+
if (res.body == null) {
|
|
475
|
+
throw new Error("LMS chat/completions response had no streaming body");
|
|
476
|
+
}
|
|
477
|
+
return parseSseStream({
|
|
478
|
+
body: res.body,
|
|
479
|
+
onChunk: input.onChunk,
|
|
480
|
+
warnings: input.warnings,
|
|
481
|
+
request: {
|
|
482
|
+
body
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
var TEXT_PART_ID = "text-0";
|
|
487
|
+
var REASONING_PART_ID = "reasoning-0";
|
|
488
|
+
async function parseSseStream(args) {
|
|
489
|
+
const reader = args.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
490
|
+
let buffer = "";
|
|
491
|
+
let textBuf = "";
|
|
492
|
+
let reasoningStarted = false;
|
|
493
|
+
let reasoningBuf = "";
|
|
494
|
+
let finishReason = "other";
|
|
495
|
+
let rawFinishReason;
|
|
496
|
+
let usage;
|
|
497
|
+
const toolCallAcc = /* @__PURE__ */ new Map();
|
|
498
|
+
let responseInitialized = false;
|
|
499
|
+
let responseId;
|
|
500
|
+
let responseModel;
|
|
501
|
+
let responseCreated;
|
|
502
|
+
try {
|
|
503
|
+
while (true) {
|
|
504
|
+
const {
|
|
505
|
+
value,
|
|
506
|
+
done
|
|
507
|
+
} = await reader.read();
|
|
508
|
+
if (done) {
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
buffer += value.replace(/\r\n/g, "\n");
|
|
512
|
+
let frameEnd = buffer.indexOf("\n\n");
|
|
513
|
+
while (frameEnd !== -1) {
|
|
514
|
+
const frame = buffer.slice(0, frameEnd);
|
|
515
|
+
buffer = buffer.slice(frameEnd + 2);
|
|
516
|
+
for (const line of frame.split("\n")) {
|
|
517
|
+
if (!line.startsWith("data:")) {
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
const payload = line.slice(5).trim();
|
|
521
|
+
if (payload === "") {
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
if (payload === "[DONE]") {
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
let parsed;
|
|
528
|
+
try {
|
|
529
|
+
parsed = JSON.parse(payload);
|
|
530
|
+
} catch {
|
|
531
|
+
args.warnings.push({
|
|
532
|
+
type: "other",
|
|
533
|
+
message: `Skipped malformed SSE frame: ${payload.slice(0, 80)}`
|
|
534
|
+
});
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
if (isErrorFrame(parsed)) {
|
|
538
|
+
throw new Error(extractErrorMessage(parsed));
|
|
539
|
+
}
|
|
540
|
+
const chunk = parsed;
|
|
541
|
+
if (!responseInitialized) {
|
|
542
|
+
responseId = chunk.id;
|
|
543
|
+
responseModel = chunk.model;
|
|
544
|
+
responseCreated = chunk.created;
|
|
545
|
+
responseInitialized = true;
|
|
546
|
+
}
|
|
547
|
+
if (chunk.usage != null) {
|
|
548
|
+
usage = mapUsage(chunk.usage);
|
|
549
|
+
}
|
|
550
|
+
for (const choice of chunk.choices ?? []) {
|
|
551
|
+
const delta = choice.delta;
|
|
552
|
+
const contentDelta = delta.content;
|
|
553
|
+
if (typeof contentDelta === "string" && contentDelta.length > 0) {
|
|
554
|
+
textBuf += contentDelta;
|
|
555
|
+
await args.onChunk({
|
|
556
|
+
type: "text-delta",
|
|
557
|
+
id: TEXT_PART_ID,
|
|
558
|
+
delta: contentDelta
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
const reasoningDelta = delta.reasoning ?? delta.reasoning_content;
|
|
562
|
+
if (typeof reasoningDelta === "string" && reasoningDelta.length > 0) {
|
|
563
|
+
reasoningStarted = true;
|
|
564
|
+
reasoningBuf += reasoningDelta;
|
|
565
|
+
await args.onChunk({
|
|
566
|
+
type: "reasoning-delta",
|
|
567
|
+
id: REASONING_PART_ID,
|
|
568
|
+
delta: reasoningDelta
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
if (delta.tool_calls != null) {
|
|
572
|
+
for (const tc of delta.tool_calls) {
|
|
573
|
+
if (typeof tc.index !== "number") {
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
const acc = toolCallAcc.get(tc.index) ?? {
|
|
577
|
+
id: "",
|
|
578
|
+
name: "",
|
|
579
|
+
args: ""
|
|
580
|
+
};
|
|
581
|
+
if (tc.id != null) {
|
|
582
|
+
acc.id = tc.id;
|
|
583
|
+
}
|
|
584
|
+
if (tc.function?.name != null) {
|
|
585
|
+
acc.name = tc.function.name;
|
|
586
|
+
}
|
|
587
|
+
if (tc.function?.arguments != null) {
|
|
588
|
+
acc.args += tc.function.arguments;
|
|
589
|
+
}
|
|
590
|
+
toolCallAcc.set(tc.index, acc);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
if (choice.finish_reason != null) {
|
|
594
|
+
rawFinishReason = choice.finish_reason;
|
|
595
|
+
finishReason = mapFinishReason(choice.finish_reason);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
frameEnd = buffer.indexOf("\n\n");
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
} finally {
|
|
603
|
+
reader.releaseLock();
|
|
604
|
+
}
|
|
605
|
+
const finalUsage = usage ?? EMPTY_USAGE;
|
|
606
|
+
const toolCalls = Array.from(toolCallAcc.entries()).map(([index, acc]) => ({
|
|
607
|
+
type: "tool-call",
|
|
608
|
+
toolCallId: acc.id !== "" ? acc.id : `tool_call_${index}`,
|
|
609
|
+
toolName: acc.name,
|
|
610
|
+
input: parseToolArguments(acc.args, args.warnings)
|
|
611
|
+
}));
|
|
612
|
+
for (const tc of toolCalls) {
|
|
613
|
+
await args.onChunk({
|
|
614
|
+
type: "tool-call",
|
|
615
|
+
toolCallId: tc.toolCallId,
|
|
616
|
+
toolName: tc.toolName,
|
|
617
|
+
input: tc.input
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
await args.onChunk({
|
|
621
|
+
type: "finish",
|
|
622
|
+
finishReason,
|
|
623
|
+
rawFinishReason,
|
|
624
|
+
usage: finalUsage
|
|
625
|
+
});
|
|
626
|
+
const response = {
|
|
627
|
+
id: responseId,
|
|
628
|
+
modelId: responseModel,
|
|
629
|
+
timestamp: responseCreated != null ? new Date(responseCreated * 1e3) : void 0,
|
|
630
|
+
messages: [{
|
|
631
|
+
role: "assistant",
|
|
632
|
+
content: buildAssistantContent(textBuf, toolCalls)
|
|
633
|
+
}]
|
|
634
|
+
};
|
|
635
|
+
return {
|
|
636
|
+
text: textBuf,
|
|
637
|
+
reasoningText: reasoningStarted ? reasoningBuf : void 0,
|
|
638
|
+
toolCalls,
|
|
639
|
+
finishReason,
|
|
640
|
+
rawFinishReason,
|
|
641
|
+
usage: finalUsage,
|
|
642
|
+
request: args.request,
|
|
643
|
+
response
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
function isErrorFrame(payload) {
|
|
647
|
+
return typeof payload === "object" && payload != null && "error" in payload && payload.error != null;
|
|
648
|
+
}
|
|
649
|
+
function extractErrorMessage(payload) {
|
|
650
|
+
const err = payload.error;
|
|
651
|
+
if (typeof err === "string") {
|
|
652
|
+
return err;
|
|
653
|
+
}
|
|
654
|
+
if (typeof err === "object" && err != null) {
|
|
655
|
+
const message = err.message;
|
|
656
|
+
if (typeof message === "string") {
|
|
657
|
+
return message;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return "LMS chat/completions stream emitted an error frame";
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// src/streamText.ts
|
|
664
|
+
function streamText(options) {
|
|
665
|
+
const warnings = [];
|
|
666
|
+
const messages = resolveMessages("streamText", options.system, options.prompt, options.messages);
|
|
667
|
+
const final = createDeferred();
|
|
668
|
+
const internalAbort = new AbortController();
|
|
669
|
+
const abortHandler = () => internalAbort.abort();
|
|
670
|
+
if (options.abortSignal != null) {
|
|
671
|
+
if (options.abortSignal.aborted) {
|
|
672
|
+
internalAbort.abort();
|
|
673
|
+
} else {
|
|
674
|
+
options.abortSignal.addEventListener("abort", abortHandler);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
const detachAbortHandler = () => {
|
|
678
|
+
options.abortSignal?.removeEventListener("abort", abortHandler);
|
|
679
|
+
};
|
|
680
|
+
let streamController;
|
|
681
|
+
let streamClosed = false;
|
|
682
|
+
const run = async () => {
|
|
683
|
+
try {
|
|
684
|
+
const result = await streamStep({
|
|
685
|
+
model: options.model,
|
|
686
|
+
messages,
|
|
687
|
+
tools: options.tools,
|
|
688
|
+
toolChoice: options.toolChoice,
|
|
689
|
+
maxOutputTokens: options.maxOutputTokens,
|
|
690
|
+
temperature: options.temperature,
|
|
691
|
+
topP: options.topP,
|
|
692
|
+
stopSequences: options.stopSequences,
|
|
693
|
+
seed: options.seed,
|
|
694
|
+
presencePenalty: options.presencePenalty,
|
|
695
|
+
frequencyPenalty: options.frequencyPenalty,
|
|
696
|
+
abortSignal: internalAbort.signal,
|
|
697
|
+
headers: options.headers,
|
|
698
|
+
warnings,
|
|
699
|
+
onChunk: async (chunk) => {
|
|
700
|
+
if (!streamClosed) {
|
|
701
|
+
streamController?.enqueue(chunk);
|
|
702
|
+
}
|
|
703
|
+
if (options.onChunk != null) {
|
|
704
|
+
await options.onChunk(chunk);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
streamController?.close();
|
|
709
|
+
streamClosed = true;
|
|
710
|
+
const finalWarnings = warnings.length > 0 ? warnings : void 0;
|
|
711
|
+
final.resolve({
|
|
712
|
+
text: result.text,
|
|
713
|
+
reasoningText: result.reasoningText,
|
|
714
|
+
usage: result.usage,
|
|
715
|
+
finishReason: result.finishReason,
|
|
716
|
+
toolCalls: result.toolCalls,
|
|
717
|
+
warnings: finalWarnings,
|
|
718
|
+
response: result.response,
|
|
719
|
+
request: result.request
|
|
720
|
+
});
|
|
721
|
+
if (options.onFinish != null) {
|
|
722
|
+
await options.onFinish({
|
|
723
|
+
finishReason: result.finishReason,
|
|
724
|
+
text: result.text,
|
|
725
|
+
reasoningText: result.reasoningText,
|
|
726
|
+
toolCalls: result.toolCalls,
|
|
727
|
+
usage: result.usage,
|
|
728
|
+
totalUsage: result.usage,
|
|
729
|
+
warnings: finalWarnings,
|
|
730
|
+
response: result.response,
|
|
731
|
+
request: result.request
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
} catch (err) {
|
|
735
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
736
|
+
if (!streamClosed) {
|
|
737
|
+
streamController?.enqueue({
|
|
738
|
+
type: "error",
|
|
739
|
+
error
|
|
740
|
+
});
|
|
741
|
+
streamController?.error(error);
|
|
742
|
+
streamClosed = true;
|
|
743
|
+
}
|
|
744
|
+
final.reject(error);
|
|
745
|
+
if (options.onError != null) {
|
|
746
|
+
await options.onError(error);
|
|
747
|
+
}
|
|
748
|
+
} finally {
|
|
749
|
+
detachAbortHandler();
|
|
750
|
+
}
|
|
751
|
+
};
|
|
752
|
+
const sourceStream = new ReadableStream({
|
|
753
|
+
start(controller) {
|
|
754
|
+
streamController = controller;
|
|
755
|
+
void run();
|
|
756
|
+
},
|
|
757
|
+
cancel() {
|
|
758
|
+
internalAbort.abort();
|
|
759
|
+
detachAbortHandler();
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
const [fullStreamBranch, textStreamBranch] = sourceStream.tee();
|
|
763
|
+
const textStream = textStreamBranch.pipeThrough(new TransformStream({
|
|
764
|
+
transform(chunk, controller) {
|
|
765
|
+
if (chunk.type === "text-delta") {
|
|
766
|
+
controller.enqueue(chunk.delta);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}));
|
|
770
|
+
const warningsPromise = final.promise.then((s) => s.warnings, () => warnings.length > 0 ? warnings : void 0);
|
|
771
|
+
return {
|
|
772
|
+
fullStream: fullStreamBranch,
|
|
773
|
+
textStream,
|
|
774
|
+
text: silence(final.promise.then((s) => s.text)),
|
|
775
|
+
reasoningText: silence(final.promise.then((s) => s.reasoningText)),
|
|
776
|
+
usage: silence(final.promise.then((s) => s.usage)),
|
|
777
|
+
totalUsage: silence(final.promise.then((s) => s.usage)),
|
|
778
|
+
finishReason: silence(final.promise.then((s) => s.finishReason)),
|
|
779
|
+
toolCalls: silence(final.promise.then((s) => s.toolCalls)),
|
|
780
|
+
warnings: warningsPromise,
|
|
781
|
+
response: silence(final.promise.then((s) => s.response)),
|
|
782
|
+
request: silence(final.promise.then((s) => s.request))
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
function silence(p) {
|
|
786
|
+
p.catch(() => {
|
|
787
|
+
});
|
|
788
|
+
return p;
|
|
789
|
+
}
|
|
790
|
+
function createDeferred() {
|
|
791
|
+
let resolveFn = () => {
|
|
792
|
+
};
|
|
793
|
+
let rejectFn = () => {
|
|
794
|
+
};
|
|
795
|
+
const promise = new Promise((res, rej) => {
|
|
796
|
+
resolveFn = res;
|
|
797
|
+
rejectFn = rej;
|
|
798
|
+
});
|
|
799
|
+
promise.catch(() => {
|
|
800
|
+
});
|
|
801
|
+
return {
|
|
802
|
+
promise,
|
|
803
|
+
resolve: resolveFn,
|
|
804
|
+
reject: rejectFn
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// src/uiMessage.ts
|
|
809
|
+
function getUIMessageText(message) {
|
|
810
|
+
let buf = "";
|
|
811
|
+
for (const p of message.parts) {
|
|
812
|
+
if (p.type === "text") {
|
|
813
|
+
buf += p.text;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
return buf;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// src/internal/uiMessageBridge.ts
|
|
820
|
+
function uiMessagesToModelMessages(ui, system) {
|
|
821
|
+
const out = [];
|
|
822
|
+
const transportSystemSet = system != null && system.length > 0;
|
|
823
|
+
if (transportSystemSet) {
|
|
824
|
+
out.push({
|
|
825
|
+
role: "system",
|
|
826
|
+
content: system
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
for (const m of ui) {
|
|
830
|
+
const text = getUIMessageText(m);
|
|
831
|
+
if (text.length === 0) {
|
|
832
|
+
continue;
|
|
833
|
+
}
|
|
834
|
+
if (m.role === "system" && transportSystemSet) {
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
837
|
+
out.push({
|
|
838
|
+
role: m.role,
|
|
839
|
+
content: text
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
return out;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// src/lmsChatTransport.ts
|
|
846
|
+
var LmsChatTransport = class {
|
|
847
|
+
constructor(opts) {
|
|
848
|
+
this.opts = opts;
|
|
849
|
+
}
|
|
850
|
+
sendMessages = async (args) => {
|
|
851
|
+
const result = streamText({
|
|
852
|
+
model: this.opts.model,
|
|
853
|
+
// System prompt is folded into the model-message list by the bridge so
|
|
854
|
+
// it isn't double-prepended (transport.system + system messages from
|
|
855
|
+
// args.messages would both land otherwise).
|
|
856
|
+
messages: uiMessagesToModelMessages(args.messages, this.opts.system),
|
|
857
|
+
temperature: this.opts.temperature,
|
|
858
|
+
maxOutputTokens: this.opts.maxOutputTokens,
|
|
859
|
+
topP: this.opts.topP,
|
|
860
|
+
presencePenalty: this.opts.presencePenalty,
|
|
861
|
+
frequencyPenalty: this.opts.frequencyPenalty,
|
|
862
|
+
stopSequences: this.opts.stopSequences,
|
|
863
|
+
seed: this.opts.seed,
|
|
864
|
+
headers: mergeHeaders(this.opts.headers, args.headers),
|
|
865
|
+
abortSignal: args.abortSignal
|
|
866
|
+
});
|
|
867
|
+
const assistantId = args.messageId;
|
|
868
|
+
const textPartId = `${assistantId}-text-0`;
|
|
869
|
+
const reasoningPartId = `${assistantId}-reasoning-0`;
|
|
870
|
+
let textOpen = false;
|
|
871
|
+
let reasoningOpen = false;
|
|
872
|
+
let startEmitted = false;
|
|
873
|
+
return result.fullStream.pipeThrough(new TransformStream({
|
|
874
|
+
transform(chunk, controller) {
|
|
875
|
+
if (!startEmitted) {
|
|
876
|
+
startEmitted = true;
|
|
877
|
+
controller.enqueue({
|
|
878
|
+
type: "start",
|
|
879
|
+
messageId: assistantId
|
|
880
|
+
});
|
|
881
|
+
controller.enqueue({
|
|
882
|
+
type: "start-step"
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
const closeText = () => {
|
|
886
|
+
if (textOpen) {
|
|
887
|
+
textOpen = false;
|
|
888
|
+
controller.enqueue({
|
|
889
|
+
type: "text-end",
|
|
890
|
+
id: textPartId
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
const closeReasoning = () => {
|
|
895
|
+
if (reasoningOpen) {
|
|
896
|
+
reasoningOpen = false;
|
|
897
|
+
controller.enqueue({
|
|
898
|
+
type: "reasoning-end",
|
|
899
|
+
id: reasoningPartId
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
};
|
|
903
|
+
switch (chunk.type) {
|
|
904
|
+
case "text-delta": {
|
|
905
|
+
if (!textOpen) {
|
|
906
|
+
textOpen = true;
|
|
907
|
+
controller.enqueue({
|
|
908
|
+
type: "text-start",
|
|
909
|
+
id: textPartId
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
controller.enqueue({
|
|
913
|
+
type: "text-delta",
|
|
914
|
+
id: textPartId,
|
|
915
|
+
delta: chunk.delta
|
|
916
|
+
});
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
case "reasoning-delta": {
|
|
920
|
+
if (!reasoningOpen) {
|
|
921
|
+
reasoningOpen = true;
|
|
922
|
+
controller.enqueue({
|
|
923
|
+
type: "reasoning-start",
|
|
924
|
+
id: reasoningPartId
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
controller.enqueue({
|
|
928
|
+
type: "reasoning-delta",
|
|
929
|
+
id: reasoningPartId,
|
|
930
|
+
delta: chunk.delta
|
|
931
|
+
});
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
case "tool-call": {
|
|
935
|
+
controller.enqueue({
|
|
936
|
+
type: "tool-input-available",
|
|
937
|
+
toolCallId: chunk.toolCallId,
|
|
938
|
+
toolName: chunk.toolName,
|
|
939
|
+
input: chunk.input
|
|
940
|
+
});
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
case "finish": {
|
|
944
|
+
closeText();
|
|
945
|
+
closeReasoning();
|
|
946
|
+
controller.enqueue({
|
|
947
|
+
type: "finish-step"
|
|
948
|
+
});
|
|
949
|
+
controller.enqueue({
|
|
950
|
+
type: "finish",
|
|
951
|
+
messageMetadata: {
|
|
952
|
+
finishReason: chunk.finishReason,
|
|
953
|
+
usage: chunk.usage
|
|
954
|
+
}
|
|
955
|
+
});
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
case "error": {
|
|
959
|
+
closeText();
|
|
960
|
+
closeReasoning();
|
|
961
|
+
controller.enqueue({
|
|
962
|
+
type: "error",
|
|
963
|
+
errorText: chunk.error.message
|
|
964
|
+
});
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
default: {
|
|
968
|
+
const unhandled = chunk;
|
|
969
|
+
controller.enqueue({
|
|
970
|
+
type: "error",
|
|
971
|
+
errorText: `Unhandled chunk type "${unhandled.type}"`
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
}));
|
|
977
|
+
};
|
|
978
|
+
reconnectToStream = async (_args) => {
|
|
979
|
+
return null;
|
|
980
|
+
};
|
|
981
|
+
};
|
|
982
|
+
function mergeHeaders(base, override) {
|
|
983
|
+
if (base == null && override == null) {
|
|
984
|
+
return void 0;
|
|
985
|
+
}
|
|
986
|
+
const out = {
|
|
987
|
+
...base ?? {}
|
|
988
|
+
};
|
|
989
|
+
if (override != null) {
|
|
990
|
+
for (const [k, v] of Object.entries(override)) {
|
|
991
|
+
out[k] = v;
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
return out;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
// src/internal/ids.ts
|
|
998
|
+
function generateMessageId() {
|
|
999
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
1000
|
+
return crypto.randomUUID();
|
|
1001
|
+
}
|
|
1002
|
+
return `msg-${Math.random().toString(36).slice(2, 10)}-${Date.now()}`;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
exports.LmsChatTransport = LmsChatTransport;
|
|
1006
|
+
exports.foundryModel = foundryModel;
|
|
1007
|
+
exports.generateMessageId = generateMessageId;
|
|
1008
|
+
exports.generateText = generateText;
|
|
1009
|
+
exports.getUIMessageText = getUIMessageText;
|
|
1010
|
+
exports.streamText = streamText;
|
|
1011
|
+
//# sourceMappingURL=index.cjs.map
|
|
1012
|
+
//# sourceMappingURL=index.cjs.map
|