@obayd/agentic
Version:
A powerful agent framework for LLMs.
155 lines (136 loc) • 5.35 kB
JavaScript
// src/lib/utils.js
export async function* fetchResponseToStream(response) {
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`API Error (${response.status}): ${errorBody}`);
}
if (!response.body) throw new Error("Response body is null.");
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.startsWith('data:')) {
const data = line.substring(5).trim();
if (data === '[DONE]') break;
try {
const parsed = JSON.parse(data);
const textChunk = parsed.choices?.[0]?.delta?.content;
if (textChunk) yield textChunk;
} catch (error) {
yield data;
}
}
}
}
}
export function makeid(length) {
let result = "";
const characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const charactersLength = characters.length;
let counter = 0;
while (counter < length) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
counter += 1;
}
return result;
}
export function parseAttributes(attrString) {
if (!attrString || !attrString.trim()) {
return {};
}
const attributes = {};
const regex = /(\w+)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+))/g;
let match;
while ((match = regex.exec(attrString)) !== null) {
const key = match[1];
const value = match[2] ?? match[3] ?? match[4];
if (value === undefined || value === null) continue;
try {
attributes[key] = JSON.parse(value);
} catch (e) {
if (!isNaN(value) && value.trim() !== '') {
attributes[key] = Number(value);
} else if (value === 'true') {
attributes[key] = true;
} else if (value === 'false') {
attributes[key] = false;
} else {
attributes[key] = value;
}
}
}
return attributes;
}
export function normalizeToolResult(result) {
let content = [];
let otherData = {};
let error = null;
if (result === null || result === undefined) {
content = [{ type: "text", text: "Tool returned empty result." }];
} else if (typeof result === 'string') {
content = [{ type: "text", text: result }];
} else if (Array.isArray(result)) {
content = result.map(part =>
typeof part === 'string' ? { type: 'text', text: part } : part
).filter(part => typeof part === 'object' && part?.type);
} else if (typeof result === 'object') {
if (result.error) {
error = result.error;
content = [{ type: "text", text: typeof error === 'string' ? error : JSON.stringify(error) }];
Object.keys(result).forEach(key => {
if (key !== 'error') {
otherData[key] = result[key];
}
});
}
else if (Array.isArray(result.content)) {
content = result.content.filter(part => typeof part === 'object' && part?.type);
Object.keys(result).forEach(key => {
if (key !== 'content') {
otherData[key] = result[key];
}
});
} else if (typeof result.content === 'string') {
content = [{ type: "text", text: result.content }];
Object.keys(result).forEach(key => {
if (key !== 'content') {
otherData[key] = result[key];
}
});
} else {
try {
content = [{ type: "text", text: JSON.stringify(result) }];
} catch {
content = [{ type: "text", text: "[Unserializable Tool Result]" }];
error = "Result object could not be serialized.";
}
otherData = result;
}
} else {
content = [{ type: "text", text: String(result) }];
}
if (!Array.isArray(content)) {
console.warn("Tool result normalization failed to produce an array, check tool return value:", result);
content = [{ type: "text", text: "[Invalid Tool Result Format]" }];
if (!error) error = "Tool returned an invalid result format.";
}
content = content.filter(part =>
part &&
(part.type !== 'text' || (part.text !== null && part.text !== undefined && String(part.text).trim() !== ""))
);
if (content.length === 0 && !error) {
content = [{ type: "text", text: "Tool returned no displayable content." }];
}
const normalized = { content, ...otherData };
if (error) {
normalized.error = error;
}
return normalized;
}