@xsai/generate-text
Version:
extra-small AI SDK.
72 lines (69 loc) • 2.25 kB
JavaScript
import { trampoline, responseJSON } from '@xsai/shared';
import { chat, determineStepType, executeTool } from '@xsai/shared-chat';
const rawGenerateText = async (options) => chat({
...options,
maxSteps: void 0,
steps: void 0,
stream: false
}).then(responseJSON).then(async (res) => {
const { choices, usage } = res;
if (!choices?.length)
throw new Error(`No choices returned, response body: ${JSON.stringify(res)}`);
const messages = structuredClone(options.messages);
const steps = options.steps ? structuredClone(options.steps) : [];
const toolCalls = [];
const toolResults = [];
const { finish_reason: finishReason, message } = choices[0];
const msgToolCalls = message?.tool_calls ?? [];
const stepType = determineStepType({
finishReason,
maxSteps: options.maxSteps ?? 1,
stepsLength: steps.length,
toolCallsLength: msgToolCalls.length
});
messages.push(message);
if (finishReason !== "stop" && stepType !== "done") {
for (const toolCall of msgToolCalls) {
const { completionToolCall, completionToolResult, message: message2 } = await executeTool({
abortSignal: options.abortSignal,
messages,
toolCall,
tools: options.tools
});
toolCalls.push(completionToolCall);
toolResults.push(completionToolResult);
messages.push(message2);
}
}
const step = {
finishReason,
stepType,
text: Array.isArray(message.content) ? message.content.filter((m) => m.type === "text").map((m) => m.text).join("\n") : message.content,
toolCalls,
toolResults,
usage
};
steps.push(step);
if (options.onStepFinish)
await options.onStepFinish(step);
if (step.finishReason === "stop" || step.stepType === "done") {
return {
finishReason: step.finishReason,
messages,
reasoningText: message.reasoning ?? message.reasoning_content,
steps,
text: step.text,
toolCalls: step.toolCalls,
toolResults: step.toolResults,
usage: step.usage
};
} else {
return async () => rawGenerateText({
...options,
messages,
steps
});
}
});
const generateText = async (options) => trampoline(async () => rawGenerateText(options));
export { generateText };