aiwrapper
Version:
A Universal AI Wrapper for JavaScript & TypeScript
267 lines (266 loc) • 8.78 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import {
LangMessage
} from "../messages.js";
class OpenAIChatCompletionsStreamHandler {
constructor(messages, onResult) {
__publicField(this, "newMessage");
__publicField(this, "messages");
__publicField(this, "onResult");
__publicField(this, "toolCallItems", /* @__PURE__ */ new Map());
__publicField(this, "toolArgBuffers", /* @__PURE__ */ new Map());
__publicField(this, "reasoningSummaryIndex", /* @__PURE__ */ new Map());
__publicField(this, "toolCallIndexToId", /* @__PURE__ */ new Map());
this.messages = messages;
this.onResult = onResult;
}
setOnResult(onResult) {
this.onResult = onResult;
}
handleEvent(data) {
var _a, _b, _c;
if (data == null) {
return;
}
if (data.finished) {
this.finalizeToolArguments();
if (this.newMessage) {
(_a = this.onResult) == null ? void 0 : _a.call(this, this.newMessage);
}
return;
}
if (!Array.isArray(data.choices) || data.choices.length === 0) {
return;
}
const choice = data.choices[0];
const delta = (_b = choice == null ? void 0 : choice.delta) != null ? _b : {};
if (delta.role === "assistant" && !this.newMessage) {
this.handleNewMessage();
}
if (delta.content !== void 0) {
this.applyContentDelta(delta.content);
}
if (delta.reasoning !== void 0 || delta.reasoning_details !== void 0) {
this.applyReasoningDelta(delta.reasoning, delta.reasoning_details);
}
if (delta.reasoning_content !== void 0) {
this.applyReasoningContentDelta(delta.reasoning_content);
}
if (delta.tool_calls) {
this.applyToolCallsDelta(delta.tool_calls);
}
if (this.newMessage) {
(_c = this.onResult) == null ? void 0 : _c.call(this, this.newMessage);
}
}
handleNewMessage() {
this.newMessage = new LangMessage("assistant", []);
this.messages.push(this.newMessage);
}
getOrCreateTextItem() {
if (!this.newMessage) {
this.handleNewMessage();
}
const lastItem = this.newMessage.items[this.newMessage.items.length - 1];
if (lastItem && lastItem.type === "text") {
return lastItem;
}
const textItem = { type: "text", text: "" };
this.newMessage.items.push(textItem);
return textItem;
}
getOrCreateReasoningItem() {
if (!this.newMessage) {
this.handleNewMessage();
}
const lastItem = this.newMessage.items[this.newMessage.items.length - 1];
if (lastItem && lastItem.type === "reasoning") {
return lastItem;
}
const reasoningItem = { type: "reasoning", text: "" };
this.newMessage.items.push(reasoningItem);
return reasoningItem;
}
applyContentDelta(contentDelta) {
var _a;
if (typeof contentDelta === "string") {
this.applyTextDelta(contentDelta);
return;
}
if (!Array.isArray(contentDelta)) {
return;
}
for (const part of contentDelta) {
if (!part) continue;
if (part.type === "text" && typeof part.text === "string") {
this.applyTextDelta(part.text);
} else if (part.type === "reasoning" && typeof part.text === "string") {
this.applyReasoningTextDelta(part.text);
} else if (part.type === "image_url" && ((_a = part.image_url) == null ? void 0 : _a.url)) {
this.applyImageFromUrl(part.image_url.url);
} else if ((part.type === "output_image" || part.type === "inline_data") && (part.b64_json || part.data)) {
const base64 = part.b64_json || part.data;
const mimeType = part.mime_type || part.mimeType || "image/png";
this.applyImageFromBase64(base64, mimeType);
}
}
}
applyTextDelta(delta) {
if (typeof delta !== "string" || delta.length === 0) {
return;
}
const textItem = this.getOrCreateTextItem();
textItem.text += delta;
}
applyReasoningDelta(reasoningDelta, reasoningDetails) {
var _a;
let deltaToAppend = reasoningDelta;
if (Array.isArray(reasoningDetails) && reasoningDetails.length > 0) {
for (const detail of reasoningDetails) {
if (!detail) continue;
const summaryIndex = typeof detail.index === "number" ? detail.index : 0;
const previousIndex = (_a = this.reasoningSummaryIndex.get("reasoning")) != null ? _a : -1;
if (previousIndex !== -1 && summaryIndex > previousIndex) {
const reasoningItem = this.getOrCreateReasoningItem();
reasoningItem.text += "\n\n";
}
this.reasoningSummaryIndex.set("reasoning", summaryIndex);
if (!deltaToAppend && typeof detail.summary === "string" && detail.summary.length > 0) {
deltaToAppend = detail.summary;
}
}
}
if (typeof deltaToAppend === "string" && deltaToAppend.length > 0) {
this.applyReasoningTextDelta(deltaToAppend);
}
}
applyReasoningContentDelta(reasoningContentDelta) {
if (typeof reasoningContentDelta === "string") {
this.applyReasoningTextDelta(reasoningContentDelta);
return;
}
if (!Array.isArray(reasoningContentDelta)) {
return;
}
for (const part of reasoningContentDelta) {
if (!part) continue;
if (typeof part === "string") {
this.applyReasoningTextDelta(part);
} else if (typeof part.text === "string") {
this.applyReasoningTextDelta(part.text);
}
}
}
applyReasoningTextDelta(delta) {
if (typeof delta !== "string" || delta.length === 0) {
return;
}
const reasoningItem = this.getOrCreateReasoningItem();
reasoningItem.text += delta;
}
applyImageFromUrl(url) {
if (typeof url !== "string" || url.length === 0) {
return;
}
if (!this.newMessage) {
this.handleNewMessage();
}
const imageItem = { type: "image", url };
this.newMessage.items.push(imageItem);
}
applyImageFromBase64(base64, mimeType) {
if (typeof base64 !== "string" || base64.length === 0) {
return;
}
if (!this.newMessage) {
this.handleNewMessage();
}
const imageItem = {
type: "image",
base64,
mimeType: mimeType || "image/png"
};
this.newMessage.items.push(imageItem);
}
applyToolCallsDelta(toolCalls) {
var _a;
for (const tc of toolCalls) {
if (!tc) continue;
let id;
const index = typeof tc.index === "number" ? tc.index : void 0;
if (typeof tc.id === "string" && tc.id.length > 0) {
id = tc.id;
if (index !== void 0) {
this.toolCallIndexToId.set(index, id);
}
} else if (index !== void 0) {
id = this.toolCallIndexToId.get(index);
if (!id) {
id = `tool_call_${index}`;
this.toolCallIndexToId.set(index, id);
}
} else {
id = `tool_call_${this.toolCallItems.size}`;
}
const toolItem = this.getOrCreateToolItem(id);
const func = (_a = tc.function) != null ? _a : {};
if (typeof func.name === "string" && func.name.length > 0) {
toolItem.name = func.name;
}
if (typeof func.arguments === "string") {
this.applyToolArgsDelta(id, func.arguments);
}
}
}
applyToolArgsDelta(toolCallId, delta) {
var _a;
const existing = (_a = this.toolArgBuffers.get(toolCallId)) != null ? _a : "";
const updated = existing + delta;
this.toolArgBuffers.set(toolCallId, updated);
const toolItem = this.toolCallItems.get(toolCallId);
if (!toolItem) return;
try {
toolItem.arguments = JSON.parse(updated);
} catch (e) {
}
}
getOrCreateToolItem(id) {
let toolItem = this.toolCallItems.get(id);
if (!toolItem) {
if (!this.newMessage) {
this.handleNewMessage();
}
toolItem = {
type: "tool",
callId: id,
name: "",
arguments: {}
};
this.newMessage.items.push(toolItem);
this.toolCallItems.set(id, toolItem);
}
return toolItem;
}
finalizeToolArguments() {
for (const [id, buffer] of this.toolArgBuffers.entries()) {
const toolItem = this.toolCallItems.get(id);
if (!toolItem) continue;
if (!buffer) {
toolItem.arguments = {};
continue;
}
try {
toolItem.arguments = JSON.parse(buffer);
} catch (e) {
toolItem.arguments = {};
}
}
this.toolArgBuffers.clear();
}
}
export {
OpenAIChatCompletionsStreamHandler
};
//# sourceMappingURL=openai-chat-completions-stream-handler.js.map