UNPKG

commandbase

Version:

The AI SDK for building declarative and composable AI-powered LLM products.

1,208 lines (1,199 loc) 37.4 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { Langbase: () => Langbase, Pipe: () => Pipe, fromReadableStream: () => fromReadableStream, getRunner: () => getRunner, getTextPart: () => getTextPart, getToolsFromRun: () => getToolsFromRun, getToolsFromRunStream: () => getToolsFromRunStream, getToolsFromStream: () => getToolsFromStream, handleResponseStream: () => handleResponseStream, printStreamToStdout: () => printStreamToStdout }); module.exports = __toCommonJS(index_exports); // src/lib/utils/doc-to-formdata.ts async function convertDocToFormData(options) { let formData = new FormData(); if (options.document instanceof Buffer) { const documentBlob = new Blob([options.document], { type: options.contentType }); formData.append("document", documentBlob, options.documentName); } else if (options.document instanceof File) { formData.append("document", options.document, options.documentName); } else if (options.document instanceof FormData) { formData = options.document; } else if (options.document instanceof ReadableStream) { const chunks = []; const reader = options.document.getReader(); while (true) { const { done, value } = await reader.read(); if (done) break; chunks.push(value); } const documentBlob = new Blob(chunks, { type: options.contentType }); formData.append("document", documentBlob, options.documentName); } formData.append("documentName", options.documentName); return formData; } // src/data/constants.ts var GENERATION_ENDPOINTS = [ "/v1/pipes/run", "/beta/chat", "/beta/generate" ]; // src/common/errors.ts var APIError = class _APIError extends Error { constructor(status, error, message, headers) { super(_APIError.makeMessage(status, error, message)); this.status = status; this.headers = headers; this.request_id = headers == null ? void 0 : headers["lb-request-id"]; const data = error; this.error = data; this.code = data == null ? void 0 : data["code"]; this.status = data == null ? void 0 : data["status"]; } static makeMessage(status, error, message) { const msg = (error == null ? void 0 : error.message) ? typeof error.message === "string" ? error.message : JSON.stringify(error.message) : error ? JSON.stringify(error) : message; if (status && msg) { return `${status} ${msg}`; } if (status) { return `${status} status code (no body)`; } if (msg) { return msg; } return "(no status code or body)"; } static generate(status, errorResponse, message, headers) { if (!status) { return new APIConnectionError({ cause: errorResponse instanceof Error ? errorResponse : void 0 }); } const error = errorResponse == null ? void 0 : errorResponse["error"]; switch (status) { case 400: return new BadRequestError(status, error, message, headers); case 401: return new AuthenticationError(status, error, message, headers); case 403: return new PermissionDeniedError( status, error, message, headers ); case 404: return new NotFoundError(status, error, message, headers); case 409: return new ConflictError(status, error, message, headers); case 422: return new UnprocessableEntityError( status, error, message, headers ); case 429: return new RateLimitError(status, error, message, headers); default: return status >= 500 ? new InternalServerError(status, error, message, headers) : new _APIError(status, error, message, headers); } } }; var APIConnectionError = class extends APIError { constructor({ message, cause }) { super(void 0, void 0, message || "Connection error.", void 0); this.status = void 0; if (cause) this.cause = cause; } }; var BadRequestError = class extends APIError { constructor() { super(...arguments); this.status = 400; } }; var AuthenticationError = class extends APIError { constructor() { super(...arguments); this.status = 401; } }; var PermissionDeniedError = class extends APIError { constructor() { super(...arguments); this.status = 403; } }; var NotFoundError = class extends APIError { constructor() { super(...arguments); this.status = 404; } }; var ConflictError = class extends APIError { constructor() { super(...arguments); this.status = 409; } }; var UnprocessableEntityError = class extends APIError { constructor() { super(...arguments); this.status = 422; } }; var RateLimitError = class extends APIError { constructor() { super(...arguments); this.status = 429; } }; var InternalServerError = class extends APIError { }; // src/common/stream.ts var Stream = class _Stream { constructor(iterator, controller) { this.iterator = iterator; this.controller = controller; } /** * Creates a stream of AsyncIterator from a Server-Sent Events (SSE) response. * * @template Item - The type of items in the stream. * @param {Response} response - The SSE response object. * @param {AbortController} controller - The abort controller used to cancel the ongoing request. * @returns {Stream<AsyncIterator<Item, any, undefined>>} - The stream created from the SSE response. * @throws {Error} - If the stream has already been consumed. */ static fromSSEResponse(response, controller) { let consumed = false; async function* iterator() { if (consumed) { throw new Error( "Cannot iterate over a consumed stream, use `.tee()` to split the stream." ); } consumed = true; let done = false; try { for await (const sse of _iterSSEMessages( response, controller )) { if (done) continue; if (sse.data.startsWith("[DONE]")) { done = true; continue; } if (sse.event === null) { let data; try { data = JSON.parse(sse.data); } catch (e) { console.error( `Could not parse message into JSON:`, sse.data ); console.error(`From chunk:`, sse.raw); throw e; } if (data && data.error) { throw new Error(data.error); } yield data; } else { let data; try { data = JSON.parse(sse.data); } catch (e) { console.error( `Could not parse message into JSON:`, sse.data ); console.error(`From chunk:`, sse.raw); throw e; } if (sse.event == "error") { throw new Error(data.message); } yield { event: sse.event, data }; } } done = true; } catch (e) { if (e instanceof Error && e.name === "AbortError") return; throw e; } finally { if (!done) controller.abort(); } } return new _Stream(iterator, controller); } /** * Generates a Stream from a newline-separated ReadableStream * where each item is a JSON value. * * @template Item - The type of items in the stream. * @param {ReadableStream} readableStream - The readable stream to create the stream from. * @param {AbortController} controller - The abort controller to control the stream. * @returns {Stream<Item>} - The created stream. */ static fromReadableStream(readableStream, controller) { let consumed = false; async function* iterLines() { const lineDecoder = new LineDecoder(); const iter = readableStreamAsyncIterable(readableStream); for await (const chunk of iter) { for (const line of lineDecoder.decode(chunk)) { yield line; } } for (const line of lineDecoder.flush()) { yield line; } } async function* iterator() { if (consumed) { throw new Error( "Cannot iterate over a consumed stream, use `.tee()` to split the stream." ); } consumed = true; let done = false; try { for await (const line of iterLines()) { if (done) continue; if (line) yield JSON.parse(line); } done = true; } catch (e) { if (e instanceof Error && e.name === "AbortError") return; throw e; } finally { if (!done) controller.abort(); } } return new _Stream(iterator, controller); } [Symbol.asyncIterator]() { return this.iterator(); } /** * Splits the stream into two streams which can be * independently read from at different speeds. */ tee() { const left = []; const right = []; const iterator = this.iterator(); const teeIterator = (queue) => { return { next: () => { if (queue.length === 0) { const result = iterator.next(); left.push(result); right.push(result); } return queue.shift(); } }; }; return [ new _Stream(() => teeIterator(left), this.controller), new _Stream(() => teeIterator(right), this.controller) ]; } /** * Converts this stream to a newline-separated ReadableStream of * JSON stringified values in the stream which can be turned back into a Stream with `Stream.fromReadableStream()`. */ toReadableStream() { const self = this; let iter; const encoder = new TextEncoder(); return new ReadableStream({ async start() { iter = self[Symbol.asyncIterator](); }, async pull(ctrl) { try { const { value, done } = await iter.next(); if (done) return ctrl.close(); const bytes = encoder.encode(JSON.stringify(value) + "\n"); ctrl.enqueue(bytes); } catch (err) { ctrl.error(err); } }, async cancel() { var _a; await ((_a = iter.return) == null ? void 0 : _a.call(iter)); } }); } }; async function* _iterSSEMessages(response, controller) { if (!response.body) { controller.abort(); throw new Error(`Attempted to iterate over a response with no body`); } const sseDecoder = new SSEDecoder(); const lineDecoder = new LineDecoder(); const iter = readableStreamAsyncIterable(response.body); for await (const sseChunk of iterSSEChunks(iter)) { for (const line of lineDecoder.decode(sseChunk)) { const sse = sseDecoder.decode(line); if (sse) yield sse; } } for (const line of lineDecoder.flush()) { const sse = sseDecoder.decode(line); if (sse) yield sse; } } async function* iterSSEChunks(iterator) { let data = new Uint8Array(); for await (const chunk of iterator) { if (chunk == null) { continue; } const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk) : typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk; let newData = new Uint8Array(data.length + binaryChunk.length); newData.set(data); newData.set(binaryChunk, data.length); data = newData; let patternIndex; while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) { yield data.slice(0, patternIndex); data = data.slice(patternIndex); } } if (data.length > 0) { yield data; } } function findDoubleNewlineIndex(buffer) { const newline = 10; const carriage = 13; for (let i = 0; i < buffer.length - 2; i++) { if (buffer[i] === newline && buffer[i + 1] === newline) { return i + 2; } if (buffer[i] === carriage && buffer[i + 1] === carriage) { return i + 2; } if (buffer[i] === carriage && buffer[i + 1] === newline && i + 3 < buffer.length && buffer[i + 2] === carriage && buffer[i + 3] === newline) { return i + 4; } } return -1; } var SSEDecoder = class { constructor() { this.event = null; this.data = []; this.chunks = []; } /** * Decodes a line of text and returns a ServerSentEvent object if a complete event is found. * @param line - The line of text to decode. * @returns A ServerSentEvent object if a complete event is found, otherwise null. */ decode(line) { if (line.endsWith("\r")) { line = line.substring(0, line.length - 1); } if (!line) { if (!this.event && !this.data.length) return null; const sse = { event: this.event, data: this.data.join("\n"), raw: this.chunks }; this.event = null; this.data = []; this.chunks = []; return sse; } this.chunks.push(line); if (line.startsWith(":")) { return null; } let [fieldname, _, value] = partition(line, ":"); if (value.startsWith(" ")) { value = value.substring(1); } if (fieldname === "event") { this.event = value; } else if (fieldname === "data") { this.data.push(value); } return null; } }; var _LineDecoder = class _LineDecoder { // TextDecoder found in browsers; not typed to avoid pulling in either "dom" or "node" types. constructor() { this.buffer = []; this.trailingCR = false; } decode(chunk) { let text = this.decodeText(chunk); if (this.trailingCR) { text = "\r" + text; this.trailingCR = false; } if (text.endsWith("\r")) { this.trailingCR = true; text = text.slice(0, -1); } if (!text) { return []; } const trailingNewline = _LineDecoder.NEWLINE_CHARS.has( text[text.length - 1] || "" ); let lines = text.split(_LineDecoder.NEWLINE_REGEXP); if (trailingNewline) { lines.pop(); } if (lines.length === 1 && !trailingNewline) { this.buffer.push(lines[0]); return []; } if (this.buffer.length > 0) { lines = [this.buffer.join("") + lines[0], ...lines.slice(1)]; this.buffer = []; } if (!trailingNewline) { this.buffer = [lines.pop() || ""]; } return lines; } decodeText(bytes) { var _a; if (bytes == null) return ""; if (typeof bytes === "string") return bytes; if (typeof Buffer !== "undefined") { if (bytes instanceof Buffer) { return bytes.toString(); } if (bytes instanceof Uint8Array) { return Buffer.from(bytes).toString(); } throw new Error( `Unexpected: received non-Uint8Array (${bytes.constructor.name}) stream chunk in an environment with a global "Buffer" defined, which this library assumes to be Node. Please report this error.` ); } if (typeof TextDecoder !== "undefined") { if (bytes instanceof Uint8Array || bytes instanceof ArrayBuffer) { (_a = this.textDecoder) != null ? _a : this.textDecoder = new TextDecoder("utf8"); return this.textDecoder.decode(bytes); } throw new Error( `Unexpected: received non-Uint8Array/ArrayBuffer (${bytes.constructor.name}) in a web platform. Please report this error.` ); } throw new Error( `Unexpected: neither Buffer nor TextDecoder are available as globals. Please report this error.` ); } flush() { if (!this.buffer.length && !this.trailingCR) { return []; } const lines = [this.buffer.join("")]; this.buffer = []; this.trailingCR = false; return lines; } }; // prettier-ignore _LineDecoder.NEWLINE_CHARS = /* @__PURE__ */ new Set(["\n", "\r"]); _LineDecoder.NEWLINE_REGEXP = /\r\n|[\n\r]/g; var LineDecoder = _LineDecoder; function partition(str, delimiter) { const index = str.indexOf(delimiter); if (index !== -1) { return [ str.substring(0, index), delimiter, str.substring(index + delimiter.length) ]; } return [str, "", ""]; } function readableStreamAsyncIterable(stream) { if (stream[Symbol.asyncIterator]) return stream; const reader = stream.getReader(); return { async next() { try { const result = await reader.read(); if (result == null ? void 0 : result.done) reader.releaseLock(); return result; } catch (e) { reader.releaseLock(); throw e; } }, async return() { const cancelPromise = reader.cancel(); reader.releaseLock(); await cancelPromise; return { done: true, value: void 0 }; }, [Symbol.asyncIterator]() { return this; } }; } // src/common/request.ts var Request = class { constructor(config) { this.config = config; } // Main send function async send({ endpoint, ...options }) { var _a, _b, _c, _d, _e; const url = this.buildUrl({ endpoint }); const headers = this.buildHeaders({ headers: options.headers }); let response; try { response = await this.makeRequest({ url, options, headers }); } catch (error) { throw new APIConnectionError({ cause: error instanceof Error ? error : void 0 }); } if (!response.ok) { await this.handleErrorResponse({ response }); } const isLllmGenerationEndpoint = GENERATION_ENDPOINTS.includes(endpoint); if (isLllmGenerationEndpoint) { const threadId = response.headers.get("lb-thread-id"); if (!options.body) { return this.handleRunResponse({ response, threadId: null, rawResponse: (_b = (_a = options.body) == null ? void 0 : _a.rawResponse) != null ? _b : false }); } if (((_c = options.body) == null ? void 0 : _c.stream) && url.includes("run")) { return this.handleRunResponseStream({ response, rawResponse: options.body.rawResponse }); } if (options.body.stream) { return this.handleStreamResponse({ response }); } return this.handleRunResponse({ response, threadId, rawResponse: (_e = (_d = options.body) == null ? void 0 : _d.rawResponse) != null ? _e : false }); } else { const res = response.json(); return res; } } buildUrl({ endpoint }) { return `${this.config.baseUrl}${endpoint}`; } buildHeaders({ headers }) { return { "Content-Type": "application/json", Authorization: `Bearer ${this.config.apiKey}`, ...headers }; } async makeRequest({ url, options, headers }) { return fetch(url, { method: options.method, headers, body: JSON.stringify(options.body) // signal: AbortSignal.timeout(this.config.timeout || 30000), }); } async handleErrorResponse({ response }) { let errorBody; try { errorBody = await response.json(); } catch (e) { errorBody = await response.text(); } throw APIError.generate( response.status, errorBody, response.statusText, response.headers ); } handleStreamResponse({ response }) { const controller = new AbortController(); const stream = Stream.fromSSEResponse(response, controller); return { stream, threadId: response.headers.get("lb-thread-id") }; } handleRunResponseStream({ response, rawResponse }) { const controller = new AbortController(); const streamSSE = Stream.fromSSEResponse(response, controller); const stream = streamSSE.toReadableStream(); const result = { stream, threadId: response.headers.get("lb-thread-id") }; if (rawResponse) { result.rawResponse = { headers: Object.fromEntries(response.headers.entries()) }; } return result; } async handleRunResponse({ response, threadId, rawResponse }) { const generateResponse = await response.json(); const buildResponse = generateResponse.raw ? { completion: generateResponse.completion, ...generateResponse.raw } : generateResponse; const result = { ...buildResponse }; if (threadId) { result.threadId = threadId; } if (rawResponse) { result.rawResponse = { headers: Object.fromEntries(response.headers.entries()) }; } return result; } async post(options) { return this.send({ ...options, method: "POST" }); } async get(options) { return this.send({ ...options, method: "GET" }); } async put(options) { return this.send({ ...options, method: "PUT" }); } async delete(options) { return this.send({ ...options, method: "DELETE" }); } }; // src/langbase/langbase.ts var Langbase = class { constructor(options) { var _a, _b; this.baseUrl = (_a = options == null ? void 0 : options.baseUrl) != null ? _a : "https://api.langbase.com"; this.apiKey = (_b = options == null ? void 0 : options.apiKey) != null ? _b : ""; this.request = new Request({ apiKey: this.apiKey, baseUrl: this.baseUrl }); this.pipe = { list: this.listPipe.bind(this), create: this.createPipe.bind(this), update: this.updatePipe.bind(this), run: this.runPipe.bind(this) }; this.memory = { create: this.createMemory.bind(this), delete: this.deleteMemory.bind(this), retrieve: this.retrieveMemory.bind(this), list: this.listMemory.bind(this), documents: { list: this.listDocs.bind(this), delete: this.deleteDoc.bind(this), upload: this.uploadDocs.bind(this), embedding: { retry: this.retryDocEmbed.bind(this) } } }; this.tool = { crawl: this.webCrawl.bind(this), webSearch: this.webSearch.bind(this) }; this.embed = this.generateEmbeddings.bind(this); this.chunk = this.chunkDocument.bind(this); this.parse = this.parseDocument.bind(this); this.thread = { messages: { add: this.addMessages.bind(this), list: this.listMessages.bind(this) }, delete: this.deleteThread.bind(this) }; } async runPipe(options) { var _a; if (!((_a = options.name) == null ? void 0 : _a.trim()) && !options.apiKey) { throw new Error( "Pipe name or Pipe API key is required to run the pipe." ); } if (typeof options.stream === "undefined") { delete options.stream; } if (options.apiKey) { this.request = new Request({ apiKey: options.apiKey, baseUrl: this.baseUrl }); } return this.request.post({ endpoint: "/v1/pipes/run", body: options, headers: { ...options.llmKey && { "LB-LLM-KEY": options.llmKey } } }); } /** * Creates a new pipe on Langbase. * * @param {PipeCreateOptions} options - The options for creating the pipe. * @returns {Promise<PipeCreateResponse>} A promise that resolves to the response of the pipe creation. */ async createPipe(options) { return this.request.post({ endpoint: "/v1/pipes", body: options }); } /** * Updates a pipe on Langbase. * * @param {PipeUpdateOptions} options - The options for updating the pipe. * @returns {Promise<PipeUpdateResponse>} A promise that resolves to the response of the update operation. */ async updatePipe(options) { return this.request.post({ endpoint: `/v1/pipes/${options.name}`, body: options }); } /** * Retrieves a list of pipes. * * @returns {Promise<PipeListResponse[]>} A promise that resolves to an array of PipeListResponse objects. */ async listPipe() { return this.request.get({ endpoint: "/v1/pipes" }); } /** * Creates a new memory on Langbase. * * @param {MemoryCreateOptions} options - The options to create the memory instance. * @param {string} options.name - The name of the memory. * @param {string} options.description - The description of the memory. * @returns {Promise<MemoryCreateResponse>} A promise that resolves to the response of the memory creation. */ async createMemory(options) { return this.request.post({ endpoint: "/v1/memory", body: options }); } /** * Retrieves a list of all memories on Langbase. * * @returns {Promise<MemoryListResponse[]>} A promise that resolves to an array of memory list responses. */ async listMemory() { return this.request.get({ endpoint: "/v1/memory" }); } /** * Deletes a memory on Langbase. * * @param {MemoryDeleteOptions} options - The options for deleting the memory resource. * @param {string} options.name - The name of the memory to delete. * @returns {Promise<MemoryDeleteResponse>} A promise that resolves to the response of the delete operation. */ async deleteMemory(options) { return this.request.delete({ endpoint: `/v1/memory/${options.name}` }); } /** * Retrieves similar text from the memory. * * @param {MemoryRetrieveOptions} options - The options to use for retrieving memory data. * @param {string} options.query - The query text to search for. * @param {object[]} options.memory - The memory to search in. * @param {number} [options.topK] - The number of similar texts to retrieve. * @returns A promise that resolves to an array of `MemoryRetrieveResponse` objects. */ async retrieveMemory(options) { return this.request.post({ endpoint: "/v1/memory/retrieve", body: options }); } /** * Retrieves a list of documents inside a memory. * * @param {MemoryListDocOptions} options - The options for listing documents, including the memory name. * @param {string} options.memoryName - The name of the memory to list documents from. * @returns A promise that resolves to an array of `MemoryListDocResponse` objects. */ async listDocs(options) { return this.request.get({ endpoint: `/v1/memory/${options.memoryName}/documents` }); } /** * Deletes a document from a memory. * * @param {MemoryDeleteDocOptions} options - The options for deleting the document. * @param {string} options.memoryName - The name of the memory to delete the document from. * @param {string} options.documentName - The name of the document to delete. * @returns A promise that resolves to a `MemoryDeleteDocResponse` indicating the result of the delete operation. */ async deleteDoc(options) { return this.request.delete({ endpoint: `/v1/memory/${options.memoryName}/documents/${options.documentName}` }); } /** * Uploads a document to the memory. * * @param {MemoryUploadDocOptions} options - The options for uploading the document. * @param {string} options.memoryName - The name of the memory to upload the document to. * @param {string} options.fileName - The name of the file being uploaded. * @param {object} [options.meta] - Optional metadata associated with the document. * @param {string} options.contentType - The MIME type of the file being uploaded. * @param {Blob | Buffer} options.file - The file content to be uploaded. * @returns {Promise<Response>} The response from the upload request. * @throws Will throw an error if the upload fails. */ async uploadDocs(options) { try { const response = await this.request.post({ endpoint: `/v1/memory/documents`, body: { memoryName: options.memoryName, fileName: options.documentName, meta: options.meta } }); const uploadUrl = response.signedUrl; return await fetch(uploadUrl, { method: "PUT", headers: { Authorization: `Bearer ${this.apiKey}`, "Content-Type": options.contentType }, body: options.document }); } catch (error) { throw error; } } /** * Retries the embedding process for a specific document in memory. * * @param options - The options required to retry the document embedding. * @param options.memoryName - The name of the memory containing the document. * @param options.documentName - The name of the document to retry embedding for. * @returns A promise that resolves to the response of the retry operation. */ async retryDocEmbed(options) { return this.request.get({ endpoint: `/v1/memory/${options.memoryName}/documents/${options.documentName}/embeddings/retry` }); } /** * Performs a web search using the Langbase API. * * @param options - Web search configuration options * @param options.apiKey - Optional API key for web search authentication * @returns Promise that resolves to an array of web search results */ async webSearch(options) { const apiKey = options.apiKey ? options.apiKey : null; apiKey && delete options.apiKey; return this.request.post({ endpoint: "/v1/tools/web-search", body: options, headers: { ...apiKey && { "LB-WEB-SEARCH-KEY": apiKey } } }); } /** * Performs a web crawls on target websites using the Langbase API. * * @param options - Crawl configuration options * @returns An array of responses containing data from the crawl operation. */ async webCrawl(options) { const apiKey = options.apiKey ? options.apiKey : null; apiKey && delete options.apiKey; return this.request.post({ endpoint: "/v1/tools/crawl", body: options, headers: { ...apiKey && { "LB-CRAWL-KEY": apiKey } } }); } /** * Generates embeddings for the given input using the LangBase API. * * @param options - Embed options * @returns Promise that resolves to the embedding response containing vector representations */ async generateEmbeddings(options) { return this.request.post({ endpoint: "/v1/embed", body: options }); } /** * Splits a given document into multiple chunks using the Langbase API. * * @param options - The chunking options. * @param options.document - The document to be chunked. * @param options.chunk_max_length - An optional maximum length for each chunk. * @param options.chunk_overlap - An optional number of overlapping characters between chunks. * @param options.separator - An optional separator used to split the document. * @returns A promise that resolves to the chunked document response. */ async chunkDocument(options) { const formData = await convertDocToFormData({ document: options.document, documentName: options.documentName, contentType: options.contentType }); if (options.chunkMaxLength) formData.append("chunkMaxLength", options.chunkMaxLength); if (options.chunkOverlap) formData.append("chunkOverlap", options.chunkOverlap); if (options.separator) formData.append("separator", options.separator); const response = await fetch(`${this.baseUrl}/v1/chunk`, { method: "POST", headers: { Authorization: `Bearer ${this.apiKey}` }, body: formData }); return response.json(); } /** * Parses a document using the Langbase API. * * @param options - The options for parsing the document * @param options.document - The document to be parsed * @param options.documentName - The name of the document * @param options.contentType - The content type of the document * * @returns A promise that resolves to the parse response from the API * * @throws {Error} If the API request fails */ async parseDocument(options) { const formData = await convertDocToFormData({ document: options.document, documentName: options.documentName, contentType: options.contentType }); const response = await fetch(`${this.baseUrl}/v1/parse`, { method: "POST", headers: { Authorization: `Bearer ${this.apiKey}` }, body: formData }); return response.json(); } /** * Adds multiple messages to a specified thread. * * @param options - The options for adding messages * @param options.threadId - The ID of the thread to add messages to * @param options.messages - The array of messages to be added * @returns A Promise that resolves to an array of Message objects * @throws May throw an error if the request fails */ async addMessages(options) { return this.request.post({ endpoint: `/v1/threads/${options.threadId}/messages`, body: options.messages }); } /** * Retrieves all messages from a specified thread. * * @param options - The options for listing messages * @param options.threadId - The unique identifier of the thread to list messages from * @returns Promise that resolves to an array of Message objects * @throws {Error} If the request fails or the thread ID is invalid */ async listMessages(options) { return this.request.get({ endpoint: `/v1/threads/${options.threadId}/messages` }); } /** * Deletes a thread using the provided thread ID. * @param options - The options for deleting a thread * @param options.threadId - The unique identifier of the thread to delete * @returns A promise that resolves to true if the thread was successfully deleted * @throws Will throw an error if the deletion fails or if the thread ID is invalid */ async deleteThread(options) { return this.request.delete({ endpoint: `/v1/threads/${options.threadId}` }); } }; // src/pipes/pipes.ts var Pipe = class { constructor(options) { const baseUrl = "https://api.langbase.com"; this.request = new Request({ apiKey: options.apiKey, baseUrl }); } /** * @deprecated This method is deprecated and will be removed in a future version. * * Please use `langbase.pipe.run()` instead * @see https://langbase.com/docs/sdk/pipe/run */ async generateText(options) { return this.request.post({ endpoint: options.chat ? "/beta/chat" : "/beta/generate", body: { ...options, stream: false } }); } /** * @deprecated This method is deprecated and will be removed in a future version. * * Please use `langbase.pipe.run()` instead * @see https://langbase.com/docs/sdk/pipe/run */ async streamText(options) { return this.request.post({ endpoint: options.chat ? "/beta/chat" : "/beta/generate", body: { ...options, stream: true } }); } }; var printStreamToStdout = async (stream) => { var _a, _b; for await (const chunk of stream) { const textPart = ((_b = (_a = chunk.choices[0]) == null ? void 0 : _a.delta) == null ? void 0 : _b.content) || ""; process.stdout.write(textPart); } }; // src/lib/helpers/index.ts var import_ChatCompletionStream = require("openai/lib/ChatCompletionStream"); var import_streaming = require("openai/streaming"); var fromReadableStream = (readableStream) => { return import_ChatCompletionStream.ChatCompletionStream.fromReadableStream(readableStream); }; var getRunner = (readableStream) => { return fromReadableStream(readableStream); }; var getTextPart = (chunk) => { var _a, _b; return ((_b = (_a = chunk.choices[0]) == null ? void 0 : _a.delta) == null ? void 0 : _b.content) || ""; }; function handleResponseStream({ response, rawResponse }) { const controller = new AbortController(); const streamSSE = import_streaming.Stream.fromSSEResponse(response, controller); const stream = streamSSE.toReadableStream(); const result = { stream, threadId: response.headers.get("lb-thread-id") }; if (rawResponse) { result.rawResponse = { headers: Object.fromEntries(response.headers.entries()) }; } return result; } async function getToolsFromStream(stream) { let run = getRunner(stream); const { choices } = await run.finalChatCompletion(); const tools = choices[0].message.tool_calls; return tools != null ? tools : []; } async function getToolsFromRunStream(stream) { return getToolsFromStream(stream); } async function getToolsFromRun(response) { const tools = response.choices[0].message.tool_calls; return tools != null ? tools : []; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Langbase, Pipe, fromReadableStream, getRunner, getTextPart, getToolsFromRun, getToolsFromRunStream, getToolsFromStream, handleResponseStream, printStreamToStdout }); //# sourceMappingURL=index.js.map