@hashbrownai/writer
Version:
Writer provider for Hashbrown AI
192 lines • 9.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.text = text;
const tslib_1 = require("tslib");
/* eslint-disable @typescript-eslint/no-explicit-any */
const writer_sdk_1 = require("writer-sdk");
const core_1 = require("@hashbrownai/core");
function text(options) {
return tslib_1.__asyncGenerator(this, arguments, function* text_1() {
var _a, e_1, _b, _c;
var _d, _e;
const { apiKey, request, transformRequestOptions, loadThread, saveThread } = options;
const writer = new writer_sdk_1.default({
apiKey,
});
const threadId = request.threadId;
let loadedThread = [];
let effectiveThreadId = threadId;
const shouldLoadThread = Boolean(request.threadId);
const shouldHydrateThreadOnTheClient = Boolean(request.operation === 'load-thread');
if (shouldLoadThread) {
yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'thread-load-start' }));
if (!loadThread) {
yield yield tslib_1.__await((0, core_1.encodeFrame)({
type: 'thread-load-failure',
error: 'Thread loading is not available for this transport.',
}));
return yield tslib_1.__await(void 0);
}
try {
loadedThread = yield tslib_1.__await(loadThread(request.threadId));
if (shouldHydrateThreadOnTheClient) {
yield yield tslib_1.__await((0, core_1.encodeFrame)({
type: 'thread-load-success',
thread: loadedThread,
}));
}
else {
yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'thread-load-success' }));
}
}
catch (error) {
yield yield tslib_1.__await((0, core_1.encodeFrame)({
type: 'thread-load-failure',
error: error instanceof Error ? error.message : String(error),
stacktrace: error instanceof Error ? error.stack : undefined,
}));
return yield tslib_1.__await(void 0);
}
}
if (request.operation === 'load-thread') {
return yield tslib_1.__await(void 0);
}
const mergedMessages = request.threadId && shouldLoadThread
? (0, core_1.mergeMessagesForThread)(loadedThread, (_d = request.messages) !== null && _d !== void 0 ? _d : [])
: ((_e = request.messages) !== null && _e !== void 0 ? _e : []);
let assistantMessage = null;
try {
const baseRequestOptions = {
stream: true,
model: request.model,
tool_choice: request.toolChoice
? { value: request.toolChoice }
: undefined,
response_format: request.responseFormat
? {
type: 'json_schema',
json_schema: {
strict: true,
name: 'schema',
description: '',
schema: request.responseFormat,
},
}
: undefined,
tools: request.tools && request.tools.length > 0
? request.tools.map((tool) => ({
type: 'function',
function: {
name: tool.name,
description: tool.description,
parameters: tool.parameters,
strict: true,
},
}))
: undefined,
messages: [
{
role: 'system',
content: request.system,
},
...mergedMessages.map((message) => {
switch (message.role) {
case 'user':
return {
role: 'user',
content: message.content,
};
case 'assistant':
return {
role: 'assistant',
content: message.content && typeof message.content !== 'string'
? JSON.stringify(message.content)
: message.content,
tool_calls: message.toolCalls && message.toolCalls.length > 0
? message.toolCalls.map((toolCall) => (Object.assign(Object.assign({}, toolCall), { type: 'function', function: Object.assign(Object.assign({}, toolCall.function), { arguments: JSON.stringify(toolCall.function.arguments) }) })))
: undefined,
};
case 'tool':
return {
role: 'tool',
content: JSON.stringify(message.content),
tool_call_id: message.toolCallId,
};
default:
throw new Error(`Unsupported message role: ${message.role}`);
}
}),
],
};
const requestOptions = transformRequestOptions
? yield tslib_1.__await(transformRequestOptions(baseRequestOptions))
: baseRequestOptions;
const stream = yield tslib_1.__await(writer.chat.chat(Object.assign(Object.assign({}, requestOptions), { stream: true })));
yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'generation-start' }));
try {
for (var _f = true, stream_1 = tslib_1.__asyncValues(stream), stream_1_1; stream_1_1 = yield tslib_1.__await(stream_1.next()), _a = stream_1_1.done, !_a; _f = true) {
_c = stream_1_1.value;
_f = false;
const chunk = _c;
const chunkMessage = {
choices: chunk.choices.map((choice) => {
var _a;
return ({
index: choice.index,
delta: Object.assign(Object.assign({}, choice.delta), { toolCalls: (_a = choice.delta.tool_calls) !== null && _a !== void 0 ? _a : undefined }),
finishReason: choice.finish_reason,
});
}),
};
yield yield tslib_1.__await((0, core_1.encodeFrame)({
type: 'generation-chunk',
chunk: chunkMessage,
}));
assistantMessage = (0, core_1.updateAssistantMessage)(assistantMessage, chunkMessage);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (!_f && !_a && (_b = stream_1.return)) yield tslib_1.__await(_b.call(stream_1));
}
finally { if (e_1) throw e_1.error; }
}
}
catch (error) {
yield yield tslib_1.__await((0, core_1.encodeFrame)({
type: 'generation-error',
error: error instanceof Error ? error.message : String(error),
}));
return yield tslib_1.__await(void 0);
}
yield yield tslib_1.__await((0, core_1.encodeFrame)({
type: 'generation-finish',
}));
if (saveThread) {
const threadToSave = (0, core_1.mergeMessagesForThread)(mergedMessages, [
...(assistantMessage ? [assistantMessage] : []),
]);
yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'thread-save-start' }));
try {
const savedThreadId = yield tslib_1.__await(saveThread(threadToSave, effectiveThreadId));
if (effectiveThreadId && savedThreadId !== effectiveThreadId) {
throw new Error('Save returned a different threadId than the existing thread');
}
effectiveThreadId = savedThreadId;
yield yield tslib_1.__await((0, core_1.encodeFrame)({
type: 'thread-save-success',
threadId: savedThreadId,
}));
}
catch (error) {
yield yield tslib_1.__await((0, core_1.encodeFrame)({
type: 'thread-save-failure',
error: error instanceof Error ? error.message : String(error),
stacktrace: error instanceof Error ? error.stack : undefined,
}));
}
}
});
}
//# sourceMappingURL=text.fn.js.map