UNPKG

@iyio/convo-lang

Version:

A conversational language.

846 lines 31.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isReservedConvoRole = exports.convoLabeledScopeParamsToObj = exports.getConvoMetadata = exports.createConvoMetadataForStatement = exports.mapToConvoTags = exports.convoTagsToMap = exports.getConvoTag = exports.containsConvoTag = exports.convoTagMapToCode = exports.setConvoScopeError = exports.createConvoScopeFunction = exports.makeAnyConvoType = exports.createConvoBaseTypeDef = exports.createConvoType = exports.createOptionalConvoValue = exports.allowedConvoDefinitionFunctions = exports.defaultConvoVisionResponse = exports.defaultConvoVisionSystemMessage = exports.getConvoDateString = exports.defaultConvoRenderTarget = exports.convoDateFormat = exports.convoTaskTriggers = exports.convoTags = exports.defaultConvoRagTol = exports.convoVars = exports.convoFunctions = exports.convoRoles = exports.defaultConvoTask = exports.convoCaptureMetadataTag = exports.convoMetadataKey = exports.convoEnumFnName = exports.convoGlobalRef = exports.convoCallFunctionModifier = exports.convoLocalFunctionModifier = exports.convoPipeFnName = exports.convoTestFnName = exports.convoDefaultFnName = exports.convoCaseFnName = exports.convoSwitchFnName = exports.convoJsonArrayFnName = exports.convoJsonMapFnName = exports.convoArrayFnName = exports.convoMapFnName = exports.convoNewFnName = exports.convoStructFnName = exports.convoDisableAutoCompleteName = exports.convoResultErrorName = exports.convoResultReturnName = exports.convoArgsName = exports.convoBodyFnName = void 0; exports.isConvoThreadFilterMatch = exports.getLastCompletionMessage = exports.convoMessageToString = exports.escapeConvoTagValue = exports.convoRagDocRefToMessage = exports.shouldDisableConvoAutoScroll = exports.getFlatConvoTag = exports.parseConvoBooleanTag = exports.getConvoStatementSource = exports.parseConvoMessageTemplate = exports.isConvoMessageIncludedInTask = exports.concatConvoCodeAndAppendEmptyUserMessage = exports.concatConvoCode = exports.removeDanglingConvoUserMessage = exports.parseConvoJsonMessage = exports.resetConvoUsageTokens = exports.createEmptyConvoTokenUsage = exports.addConvoUsageTokens = exports.parseConvoUsageTokens = exports.convoUsageTokensToString = exports.validateConvoTypeName = exports.validateConvoFunctionName = exports.validateConvoVarName = exports.isValidConvoTypeName = exports.isValidConvoFunctionName = exports.isValidConvoVarName = exports.convoStringToComment = exports.convoStringToCommentOut = exports.convoDescriptionToComment = exports.convoDescriptionToCommentOut = exports.collapseConvoPipes = exports.defaultConvoPrintFunction = exports.spreadConvoArgs = exports.escapeConvoMessageContent = exports.formatConvoMessage = exports.isValidConvoIdentifier = exports.isValidConvoRole = void 0; const common_1 = require("@iyio/common"); const json5_1 = require("@iyio/json5"); const date_fns_1 = require("date-fns"); const ConvoError_1 = require("./ConvoError"); const convo_types_1 = require("./convo-types"); exports.convoBodyFnName = '__body'; exports.convoArgsName = '__args'; exports.convoResultReturnName = '__return'; exports.convoResultErrorName = '__error'; exports.convoDisableAutoCompleteName = '__disableAutoComplete'; exports.convoStructFnName = 'struct'; exports.convoNewFnName = 'new'; exports.convoMapFnName = 'map'; exports.convoArrayFnName = 'array'; exports.convoJsonMapFnName = 'jsonMap'; exports.convoJsonArrayFnName = 'jsonArray'; exports.convoSwitchFnName = 'switch'; exports.convoCaseFnName = 'case'; exports.convoDefaultFnName = 'default'; exports.convoTestFnName = 'test'; exports.convoPipeFnName = 'pipe'; exports.convoLocalFunctionModifier = 'local'; exports.convoCallFunctionModifier = 'call'; exports.convoGlobalRef = 'convo'; exports.convoEnumFnName = 'enum'; exports.convoMetadataKey = Symbol('convoMetadataKey'); exports.convoCaptureMetadataTag = 'captureMetadata'; exports.defaultConvoTask = 'default'; exports.convoRoles = { user: 'user', assistant: 'assistant', rag: 'rag', /** * Used to define a prefix to add to rag messages */ ragPrefix: 'ragPrefix', /** * Used to define a suffix to add to rag messages */ ragSuffix: 'ragSuffix', }; exports.convoFunctions = { queryImage: 'queryImage', getState: 'getState', }; /** * reserved system variables */ exports.convoVars = { /** * In environments that have access to the filesystem __cwd defines the current working directory. */ __cwd: '__cwd', /** * When set to true debugging information will be added to conversations. */ __debug: '__debug', /** * Sets the default model */ __model: '__model', /** * Sets the default completion endpoint */ __endpoint: '__endpoint', /** * When set to true time tracking will be enabled. */ __trackTime: '__trackTime', /** * When set to true token usage tracking will be enabled. */ __trackTokenUsage: '__trackTokenUsage', /** * When set to true the model used as a completion provider will be tracked. */ __trackModel: '__trackModel', /** * When defined __visionSystemMessage will be injected into the system message of conversations * with vision capabilities. __visionSystemMessage will override the default vision * system message. */ __visionSystemMessage: '__visionSystemMessage', /** * The default system message used for completing vision requests. Vision requests are typically * completed in a separate conversation that supports vision messages. By default the system * message of the conversation that triggered the vision request will be used. */ __visionServiceSystemMessage: '__visionServiceSystemMessage', /** * Response used with the system is not able to generate a vision response. */ __defaultVisionResponse: '__defaultVisionResponse', /** * A reference to markdown vars. */ __md: '__md', /** * Enables retrieval augmented generation (RAG). The value of the __rag can either be true, * false or a number. The value indicates the number of rag results that should be sent to the * LLM by default all rag message will be sent to the LLM. When setting the number of rag * messages to a fixed number only the last N number of rag messages will be sent to the LLM. * Setting __rag to a fixed number can help to reduce prompt size. */ __rag: '__rag', /** * An object that will be passed to the rag callback of a conversation. If the value is not an * object it is ignored. */ __ragParams: '__ragParams', /** * The tolerance that determines if matched rag content should be included as contact. */ __ragTol: '__ragTol', /** * Sets the current thread filter. Can either be a string or a ConvoThreadFilter. If __threadFilter * is a string it will be converted into a filter that looks like `{includeThreads:[__threadId]}`. */ __threadFilter: '__threadFilter' }; exports.defaultConvoRagTol = 1.2; exports.convoTags = { /** * When applied to a function the return value of the function will not be used to generate a * new assistant message. */ disableAutoComplete: 'disableAutoComplete', /** * Used to indicate that a message should be evaluated at the edge of a conversation with the * latest state. @edge is most commonly used with system message to ensure that all injected values * are updated with the latest state of the conversation. */ edge: 'edge', /** * Used to track the time messages are created. */ time: 'time', /** * Used to track the number of tokens a message used */ tokenUsage: 'tokenUsage', /** * Used to track the model used to generate completions */ model: 'model', /** * Sets the requested model to complete a message with */ responseModel: 'responseModel', /** * Used to track the endpoint to generate completions */ endpoint: 'endpoint', /** * Sets the requested endpoint to complete a message with */ responseEndpoint: 'responseEndpoint', /** * Sets the format as message should be responded to with. */ responseFormat: 'responseFormat', /** * Causes the response of the tagged message to be assigned to a variable */ responseAssign: 'responseAssign', /** * When used with a message the json tag is short and for `@responseFormat json` */ json: 'json', /** * The format of a message */ format: 'format', /** * Used to assign the content or jsonValue of a message to a variable */ assign: 'assign', /** * Used to enable capabilities. Only the first and last message in the conversation are used * to determine current capabilities. Multiple capability tags can be * applied to a message and multiple capabilities can be specified by separating them with a * comma. */ capability: 'capability', /** * Shorthand for `@capability vision` */ enableVision: 'enableVision', /** * Sets the task a message is part of. By default messages are part of the "default" task */ task: 'task', /** * Sets the max number of non-system messages that should be included in a task completion */ maxTaskMessageCount: 'maxTaskMessageCount', /** * Defines what triggers a task */ taskTrigger: 'taskTrigger', /** * Defines a message as a template */ template: 'template', /** * used to track the name of templates used to generate messages */ sourceTemplate: 'sourceTemplate', /** * Used to mark a message as a component. The value of the tag is used as the component name. * If no value is provided then the component will be unnamed. */ component: 'component', /** * When applied to a message the message should be rendered but not sent to LLMs */ renderOnly: 'renderOnly', /** * Controls where a message is rendered. By default messages are rendered in the default chat * view, but applications can define different render targets. */ renderTarget: 'renderTarget', toolId: 'toolId', /** * When applied to the last content or component messages auto scrolling will be disabled */ disableAutoScroll: 'disableAutoScroll', /** * When applied to a message the content of the message will be parsed as markdown */ markdown: 'markdown', /** * When applied to a message the content of the message will be parsed as markdown and the * elements of the markdown will be auto assigned to vars */ markdownVars: 'markdownVars', /** * When applied to a message the message is conditionally added to the flattened view of a * conversation. When the condition is false the message will not be visible to the user * or the LLM. * * @note The example below uses (at) instead of the at symbol because of a limitation of jsdoc. * * The example below will only render and send the second system message to the LLM * @example * * ``` convo * > define * animal = 'dog' * * (at)condition animal frog * > system * You are a frog and you like to hop around. * * (at)condition animal dog * > system * You are a dog and you like to eat dirt. * ``` */ condition: 'condition', /** * A URL to the source of the message. Typically used with RAG. */ sourceUrl: 'sourceUrl', /** * The ID of the source content of the message. Typically used with RAG. */ sourceId: 'sourceId', /** * The name of the source content of the message. Typically used with RAG. */ sourceName: 'sourceName', /** * When applied to a message the message becomes a clickable suggestion that when clicked will * add a new user message with the content of the message. If the suggestion tag defines a value * that value will be displayed on the clickable button instead of the message content but the * message content will still be used as the user messaged added to the conversation when clicked. * Suggestion message are render only and not seen by LLMs. */ suggestion: 'suggestion', /** * Sets the threadId of the current message and all following messages. Using the `@thread` tag * without a value will clear the current thread id. */ thread: 'thread', /** * Used to mark a function as a node output. */ output: 'output', /** * Used to mark a function as an error callback */ errorCallback: 'errorCallback', /** * Used to import external convo script code */ import: 'import', /** * Causes a message to be concatenated with the previous message. Both the message the tag * is attached to and the previous message must be content messages or the tag is ignored. * When a message is concatenated to another message all other tags except the condition * tag are ignored. */ concat: 'concat', }; exports.convoTaskTriggers = { /** * Triggers a text message is received. Function calls will to trigger. */ onResponse: 'onResponse' }; exports.convoDateFormat = "yyyy-MM-dd'T'HH:mm:ssxxx"; exports.defaultConvoRenderTarget = 'default'; const getConvoDateString = (date = new Date()) => { return (0, date_fns_1.format)(date, exports.convoDateFormat); }; exports.getConvoDateString = getConvoDateString; exports.defaultConvoVisionSystemMessage = ('If the user references a markdown image without a ' + 'description or the description can not answer the user\'s question or ' + `complete the user\`s request call the ${exports.convoFunctions.queryImage} function. ` + 'Do not use the URL of the image to make any assumptions about the image.'); exports.defaultConvoVisionResponse = 'Unable to answer or respond to questions or requests for the given image or images'; exports.allowedConvoDefinitionFunctions = [ exports.convoNewFnName, exports.convoStructFnName, exports.convoMapFnName, exports.convoArrayFnName, exports.convoEnumFnName, exports.convoJsonMapFnName, exports.convoJsonArrayFnName, exports.convoFunctions.getState, ]; const createOptionalConvoValue = (value) => { return { [convo_types_1.convoObjFlag]: 'optional', value, }; }; exports.createOptionalConvoValue = createOptionalConvoValue; const createConvoType = (typeDef) => { typeDef[convo_types_1.convoObjFlag] = 'type'; return typeDef; }; exports.createConvoType = createConvoType; const createConvoBaseTypeDef = (type) => { return { [convo_types_1.convoObjFlag]: 'type', type, }; }; exports.createConvoBaseTypeDef = createConvoBaseTypeDef; const makeAnyConvoType = (type, value) => { if (!value) { return value; } value[convo_types_1.convoObjFlag] = 'type'; value['type'] = type; return value; }; exports.makeAnyConvoType = makeAnyConvoType; const createConvoScopeFunction = (fnOrCtrl, fn) => { if (typeof fnOrCtrl === 'function') { return fnOrCtrl; } if (!fn) { fn = (scope) => scope.paramValues ? scope.paramValues[scope.paramValues.length - 1] : undefined; } if (fnOrCtrl) { fn[convo_types_1.convoFlowControllerKey] = fnOrCtrl; } return fn; }; exports.createConvoScopeFunction = createConvoScopeFunction; const setConvoScopeError = (scope, error) => { if (typeof error === 'string') { error = { message: error, statement: scope?.s, }; } if (!scope) { throw error; } scope.error = error; if (scope.onError) { const oe = scope.onError; delete scope.onError; delete scope.onComplete; for (let i = 0; i < oe.length; i++) { oe[i]?.(error); } } }; exports.setConvoScopeError = setConvoScopeError; const notWord = /\W/g; const newline = /[\n\r]/g; const convoTagMapToCode = (tagsMap, append = '', tab = '') => { const out = []; for (const e in tagsMap) { const v = tagsMap[e]; out.push(`${tab}@${e.replace(notWord, '_')}${v ? ' ' + v.replace(newline, ' ') : ''}`); } return out.join('\n') + append; }; exports.convoTagMapToCode = convoTagMapToCode; const containsConvoTag = (tags, tagName) => { if (!tags) { return false; } for (let i = 0; i < tags.length; i++) { if (tags[i]?.name === tagName) { return true; } } return false; }; exports.containsConvoTag = containsConvoTag; const getConvoTag = (tags, tagName) => { if (!tags) { return undefined; } for (let i = 0; i < tags.length; i++) { const tag = tags[i]; if (tag?.name === tagName) { return tag; } } return undefined; }; exports.getConvoTag = getConvoTag; const convoTagsToMap = (tags) => { const map = {}; for (const t of tags) { map[t.name] = t.value; } return map; }; exports.convoTagsToMap = convoTagsToMap; const mapToConvoTags = (map) => { const tags = []; for (const e in map) { tags.push({ name: e, value: map[e] }); } return tags; }; exports.mapToConvoTags = mapToConvoTags; const createConvoMetadataForStatement = (statement) => { return { name: ((statement.set && !statement.setPath) ? statement.set : statement.label ? statement.label : undefined), comment: statement.comment, tags: statement.tags, }; }; exports.createConvoMetadataForStatement = createConvoMetadataForStatement; const getConvoMetadata = (value) => { return value?.[exports.convoMetadataKey]; }; exports.getConvoMetadata = getConvoMetadata; const convoLabeledScopeParamsToObj = (scope) => { const obj = {}; const labels = scope.labels; let metadata = undefined; if (scope.cm || (scope.s.tags && (0, exports.containsConvoTag)(scope.s.tags, exports.convoCaptureMetadataTag))) { metadata = (0, exports.createConvoMetadataForStatement)(scope.s); metadata.properties = {}; obj[exports.convoMetadataKey] = metadata; } if (labels) { for (const e in labels) { const label = labels[e]; if (label === undefined) { continue; } const isOptional = typeof label === 'object'; const index = isOptional ? label.value : label; if (index !== undefined) { const v = scope.paramValues?.[index]; obj[e] = isOptional ? (0, exports.createOptionalConvoValue)(v) : v; if (metadata?.properties && scope.s.params) { const propStatement = scope.s.params[index]; if (propStatement) { metadata.properties[e] = { name: e, comment: propStatement.comment, tags: propStatement.tags }; } } } } } return obj; }; exports.convoLabeledScopeParamsToObj = convoLabeledScopeParamsToObj; const isReservedConvoRole = (role) => { return convo_types_1.convoReservedRoles.includes(role); }; exports.isReservedConvoRole = isReservedConvoRole; const isValidConvoRole = (role) => { return /^\w+$/.test(role); }; exports.isValidConvoRole = isValidConvoRole; const isValidConvoIdentifier = (role) => { return /^[a-z]\w*$/.test(role); }; exports.isValidConvoIdentifier = isValidConvoIdentifier; const formatConvoMessage = (role, content, prefix = '') => { if (!(0, exports.isValidConvoRole)(role)) { throw new ConvoError_1.ConvoError('invalid-role', undefined, `(${role}) is not a valid role`); } if ((0, exports.isReservedConvoRole)(role)) { throw new ConvoError_1.ConvoError('use-of-reserved-role-not-allowed', undefined, `${role} is a reserved role`); } return `${prefix}> ${role}\n${(0, exports.escapeConvoMessageContent)(content)}`; }; exports.formatConvoMessage = formatConvoMessage; const escapeConvoMessageContent = (content, isStartOfMessage = true, options) => { // todo escape tags at end of message if (content.includes('{{')) { content = content.replace(/\{\{/g, '\\{{'); } if (content.includes('>')) { content = content.replace( // the non start of message reg should be the same except no start of input char should be included isStartOfMessage ? /((?:\n|\r|^)[ \t]*\\*)>/g : /((?:\n|\r)[ \t]*\\*)>/g, (_, space) => `${space}\\>`); } if (options?.removeNewLines) { content = content.replace(/[\n\r]/g, ''); } return content; }; exports.escapeConvoMessageContent = escapeConvoMessageContent; const spreadConvoArgs = (args, format) => { const json = JSON.stringify(args, null, format ? 4 : undefined); return json.substring(1, json.length - 1); }; exports.spreadConvoArgs = spreadConvoArgs; const defaultConvoPrintFunction = (...args) => { console.log(...args); return args[args.length - 1]; }; exports.defaultConvoPrintFunction = defaultConvoPrintFunction; const collapseConvoPipes = (statement) => { const params = statement.params; if (!params) { return 0; } delete statement._hasPipes; let count = 0; for (let i = 0; i < params.length; i++) { const s = params[i]; if (!s?._pipe) { continue; } count++; const dest = params[i - 1]; const src = params[i + 1]; if (i === 0 || i === params.length - 1 || !dest || !src) { // discard - pipes need a target and source params.splice(i, 1); i--; continue; } if (dest.fn === exports.convoPipeFnName) { if (!dest.params) { dest.params = []; } dest.params.unshift(src); params.splice(i, 2); } else { const pipeCall = { s: dest.s, e: dest.e, fn: exports.convoPipeFnName, params: [src, dest] }; params.splice(i - 1, 3, pipeCall); } i--; } return count; }; exports.collapseConvoPipes = collapseConvoPipes; const convoDescriptionToCommentOut = (description, tab = '', out) => { const lines = description.split('\n'); for (let i = 0; i < lines.length; i++) { const line = lines[i]; out.push(`${tab}# ${line}`); } }; exports.convoDescriptionToCommentOut = convoDescriptionToCommentOut; const convoDescriptionToComment = (description, tab = '') => { const out = []; (0, exports.convoDescriptionToCommentOut)(description, tab, out); return out.join('\n'); }; exports.convoDescriptionToComment = convoDescriptionToComment; const convoStringToCommentOut = (str, tab = '', out) => { const lines = str.split('\n'); for (let i = 0; i < lines.length; i++) { const line = lines[i]; out.push(`${tab}// ${line}`); } }; exports.convoStringToCommentOut = convoStringToCommentOut; const convoStringToComment = (str, tab = '') => { const out = []; (0, exports.convoStringToCommentOut)(str, tab, out); return out.join('\n'); }; exports.convoStringToComment = convoStringToComment; const nameReg = /^[a-z_]\w{,254}$/; const typeNameReg = /^[A-Z]\w{,254}$/; const isValidConvoVarName = (name) => { return nameReg.test(name); }; exports.isValidConvoVarName = isValidConvoVarName; const isValidConvoFunctionName = (name) => { return nameReg.test(name); }; exports.isValidConvoFunctionName = isValidConvoFunctionName; const isValidConvoTypeName = (typeName) => { return typeNameReg.test(typeName); }; exports.isValidConvoTypeName = isValidConvoTypeName; const validateConvoVarName = (name) => { if (nameReg.test(name)) { throw new ConvoError_1.ConvoError('invalid-variable-name', undefined, `${name} is an invalid Convo variable name. Variable names must start with a lower case letter followed by 0 to 254 more word characters`); } }; exports.validateConvoVarName = validateConvoVarName; const validateConvoFunctionName = (name) => { if (nameReg.test(name)) { throw new ConvoError_1.ConvoError('invalid-function-name', undefined, `${name} is an invalid Convo function name. Function names must start with a lower case letter followed by 0 to 254 more word characters`); } }; exports.validateConvoFunctionName = validateConvoFunctionName; const validateConvoTypeName = (name) => { if (nameReg.test(name)) { throw new ConvoError_1.ConvoError('invalid-type-name', undefined, `${name} is an invalid Convo type name. Type names must start with an upper case letter followed by 0 to 254 more word characters`); } }; exports.validateConvoTypeName = validateConvoTypeName; const convoUsageTokensToString = (usage) => { return `${usage.inputTokens ?? 0} / ${usage.outputTokens ?? 0}${usage.tokenPrice ? ' / $' + usage.tokenPrice : ''}`; }; exports.convoUsageTokensToString = convoUsageTokensToString; const parseConvoUsageTokens = (str) => { const parts = str.split('/'); return { inputTokens: Number(parts[0]) || 0, outputTokens: Number(parts[1]) || 0, tokenPrice: Number(parts[2]?.replace('$', '')) || 0, }; }; exports.parseConvoUsageTokens = parseConvoUsageTokens; const addConvoUsageTokens = (to, from) => { if (typeof from === 'string') { from = (0, exports.parseConvoUsageTokens)(from); } to.inputTokens += from.inputTokens; to.outputTokens += from.outputTokens; to.tokenPrice += from.tokenPrice; }; exports.addConvoUsageTokens = addConvoUsageTokens; const createEmptyConvoTokenUsage = () => ({ inputTokens: 0, outputTokens: 0, tokenPrice: 0, }); exports.createEmptyConvoTokenUsage = createEmptyConvoTokenUsage; const resetConvoUsageTokens = (usage) => { usage.inputTokens = 0; usage.outputTokens = 0; usage.tokenPrice = 0; }; exports.resetConvoUsageTokens = resetConvoUsageTokens; const parseConvoJsonMessage = (json) => { return (0, json5_1.parseJson5)(json .replace(/^\s*`+\s*\w*/, '') .replace(/`+\s*$/, '') .trim()); }; exports.parseConvoJsonMessage = parseConvoJsonMessage; const danglingReg = /[\r\n^](\s*>\s*user\s*)$/; const removeDanglingConvoUserMessage = (code) => { const dm = danglingReg.exec(code); if (!dm) { return code; } return code.substring(0, code.length - (dm[1] ?? '').length).trim(); }; exports.removeDanglingConvoUserMessage = removeDanglingConvoUserMessage; const concatConvoCode = (a, b) => { const dm = danglingReg.exec(a); if (!dm) { return a + b; } return a.substring(0, a.length - (dm[1] ?? '').length) + b; }; exports.concatConvoCode = concatConvoCode; const concatConvoCodeAndAppendEmptyUserMessage = (a, b) => { const code = (0, exports.concatConvoCode)(a, b); if (!danglingReg.test(code)) { return code + '\n\n> user\n'; } else { return code; } }; exports.concatConvoCodeAndAppendEmptyUserMessage = concatConvoCodeAndAppendEmptyUserMessage; const isConvoMessageIncludedInTask = (msg, task) => { const msgTask = (0, exports.getConvoTag)(msg.tags, exports.convoTags.task)?.value ?? exports.defaultConvoTask; return msgTask === task; }; exports.isConvoMessageIncludedInTask = isConvoMessageIncludedInTask; const parseConvoMessageTemplate = (msg, template) => { const match = /^(\w+)\s*([\w.]+)?\s*(.*)/.exec(template); return match ? { message: msg, name: match[1], watchPath: match[2], matchValue: match[3], } : { message: msg, }; }; exports.parseConvoMessageTemplate = parseConvoMessageTemplate; const getConvoStatementSource = (statement, code) => { return code.substring(statement.s, statement.e); }; exports.getConvoStatementSource = getConvoStatementSource; /** * If the value is empty, null or undefined true is returned, otherwise the Boolean * constructor is used to parse the value. */ const parseConvoBooleanTag = (value) => { if (!value) { return true; } return Boolean(value); }; exports.parseConvoBooleanTag = parseConvoBooleanTag; const getFlatConvoTag = (message, tagName) => { if (!message?.tags || !(tagName in message.tags)) { return false; } return (0, exports.parseConvoBooleanTag)(message.tags[tagName]); }; exports.getFlatConvoTag = getFlatConvoTag; const shouldDisableConvoAutoScroll = (messages) => { for (let i = messages.length - 1; i >= 0; i--) { const m = messages[i]; if (m && (m.content !== undefined || m.component !== undefined)) { return (0, exports.getFlatConvoTag)(m, exports.convoTags.disableAutoScroll); } } return false; }; exports.shouldDisableConvoAutoScroll = shouldDisableConvoAutoScroll; const convoRagDocRefToMessage = (doc, role) => { const msg = { role, content: doc.content, tags: [] }; if (doc.sourceId) { msg.sourceId = doc.sourceId; msg.tags?.push({ name: exports.convoTags.sourceId, value: doc.sourceId }); } if (doc.sourceName) { msg.sourceName = doc.sourceName; msg.tags?.push({ name: exports.convoTags.sourceName, value: doc.sourceName }); } if (doc.sourceUrl) { msg.sourceUrl = doc.sourceUrl; msg.tags?.push({ name: exports.convoTags.sourceUrl, value: doc.sourceUrl }); } if (!msg.tags?.length) { delete msg.tags; } return msg; }; exports.convoRagDocRefToMessage = convoRagDocRefToMessage; const escapeConvoTagValue = (value) => { return value.replace(/\s/g, ' '); }; exports.escapeConvoTagValue = escapeConvoTagValue; const convoMessageToString = (msg) => { if (msg.fn || msg.statement) { throw new common_1.UnsupportedError('convoMessageToString only supports text based messages without embedded statements'); } const out = []; if (msg.tags) { for (const tag of msg.tags) { out.push(`@${tag.name}${tag.value === undefined ? '' : ' ' + (0, exports.escapeConvoTagValue)(tag.value)}`); } } out.push(`> ${msg.role ?? 'user'}`); if (msg.content) { out.push((0, exports.escapeConvoMessageContent)(msg.content, true)); } return out.join('\n'); }; exports.convoMessageToString = convoMessageToString; const getLastCompletionMessage = (messages) => { for (let i = messages.length - 1; i >= 0; i--) { const msg = messages[i]; if (!msg || msg.role === 'function') { continue; } return msg; } return undefined; }; exports.getLastCompletionMessage = getLastCompletionMessage; const isConvoThreadFilterMatch = (filter, tid) => { if ((filter.excludeNonThreaded && !tid) || filter.excludeThreads?.includes(tid ?? '')) { return false; } if (filter.includeNonThreaded && !tid) { return true; } else if (filter.includeThreads) { return filter.includeThreads.includes(tid ?? ''); } else { return true; } }; exports.isConvoThreadFilterMatch = isConvoThreadFilterMatch; //# sourceMappingURL=convo-lib.js.map