UNPKG

@convo-lang/convo-lang

Version:
295 lines 10.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isLockedConvoObject = exports.isConvoObject = exports.convo = void 0; const common_1 = require("@iyio/common"); const Conversation_1 = require("./Conversation"); const convo_lib_1 = require("./convo-lib"); const convo_template_1 = require("./convo-template"); const convo_types_1 = require("./convo-types"); const jsonEndReg = /@json[ \t]*$/; let fnIndex = 0; /** * Converts a template literal string into a ConvoObject. The completion of the conversation * is not started until then, catch, finally, getValue or getCompletionAsync is called. After one * of the previously stated functions or getInput, getValueAsync or getCompletionAsync are called * the ConvoObject is considered finalized and non of the setter function will be allowed * to be called, if they are called an error will be thrown. */ const convo = (strings, valueOrZodType, ...values) => { const isLocked = valueOrZodType === lockFlag; if (isLocked) { valueOrZodType = values.shift(); } const cloneSrc = { valueOrZodType, values: [...values] }; let options; let conversation; const zodName = (0, common_1.getZodTypeName)(valueOrZodType); const dependencies = [ valueOrZodType, ...values, ...strings, ]; const isFinalized = () => (conversation || _input !== undefined) ? true : false; let _input; const getInput = () => { if (_input !== undefined) { return _input; } let prefix = ''; if (zodName && jsonEndReg.test(strings[0] ?? '')) { prefix = (0, convo_template_1.convoScript) `> define\nInlineJsonType=${valueOrZodType}\n\n`; values.splice(0, 0, ' InlineJsonType'); } else { values.splice(0, 0, valueOrZodType); } for (let i = 0; i < values.length; i++) { const fn = values[i]; if (typeof fn !== 'function') { continue; } const index = fnIndex++; const name = `_inline_extern_function_${index}_`; const next = strings[i + 1]; if (next?.startsWith('_')) { // call function values[i] = name.substring(0, name.length - 1); if (!internalExternFunctions) { internalExternFunctions = {}; } internalExternFunctions[name] = fn; } else { // define as function body values[i] = `(${name}(__args))`; if (!externScopeFunctions) { externScopeFunctions = {}; } const externFn = fn; externScopeFunctions[name] = (scope) => { const argsObj = scope.paramValues?.[0]; if (!argsObj || !(typeof argsObj === 'object')) { throw new Error(`__args object should be passed to ${name}`); } const scopeFn = scope[convo_types_1.convoScopeFnDefKey]; if (!scopeFn) { throw new Error(`convoScopeFnDefKey not defined in scope when calling ${name}`); } const args = []; for (const p of scopeFn.params) { if (p.label) { args.push(argsObj[p.label]); } } return externFn(...args); }; } } _input = prefix + (0, convo_template_1.convoScript)(strings, ...values); return _input; }; const getOutputOptions = () => { // must call get input since it can register extern functions getInput(); return { defaultVars: (options?.defaultVars || defaultVars) ? { ...options?.defaultVars, ...defaultVars } : undefined, externFunctions: (options?.externFunctions || externFunctions || internalExternFunctions) ? { ...options?.externFunctions, ...internalExternFunctions, ...externFunctions } : undefined, externScopeFunctions: (options?.externScopeFunctions || externScopeFunctions) ? { ...options?.externScopeFunctions, ...externScopeFunctions } : undefined, }; }; const getConversation = () => { if (conversation) { return conversation; } conversation = new Conversation_1.Conversation({ ...options, ...getOutputOptions(), }); return conversation; }; const assertUpdate = () => { if (isFinalized()) { throw new Error('Unable modify finalized convo object'); } if (isLocked) { throw new Error('Unable locked finalized convo object'); } }; const setConversation = (_conversation) => { dependencies.push(`instId:${_conversation.instanceId}`); conversation = _conversation; return _self; }; const setOptions = (_options) => { assertUpdate(); for (const e in _options) { const v = _options[e]; dependencies.push(e, v); } options = _options; return _self; }; const getValueAsync = async () => { return (await getCompletionAsync()).value; }; let valuePromise; const getCompletionAsync = () => { return valuePromise ?? (valuePromise = _getCompletionAsync()); }; const _getCompletionAsync = async () => { const cv = getConversation(); cv.append(getInput()); const completion = await cv.completeAsync({ returnOnCalled: true }); return { value: (0, convo_lib_1.getAssumedConvoCompletionValue)(completion), completion }; }; let defaultVars; const addVars = (vars) => { assertUpdate(); if (!defaultVars) { defaultVars = {}; } for (const e in vars) { const v = vars[e]; defaultVars[e] = v; dependencies.push(e, v); } return _self; }; let externScopeFunctions; let externFunctions; let internalExternFunctions; const setExternFunctions = (functions) => { assertUpdate(); if (!externFunctions) { externFunctions = {}; } for (const e in functions) { const fn = functions[e]; dependencies.push(e, fn); if (fn) { externFunctions[e] = fn; } } return _self; }; const clone = (lock) => { const clone = (lock ? (0, exports.convo)(strings, lockFlag, cloneSrc.valueOrZodType, ...cloneSrc.values) : (0, exports.convo)(strings, cloneSrc.valueOrZodType, ...cloneSrc.values)); if (defaultVars) { clone.addVars(defaultVars); } if (externFunctions) { clone.setExternFunctions(externFunctions); } if (options) { clone.setOptions(options); } return clone; }; const _self = { getInput, dependencies, zodType: zodName ? valueOrZodType : undefined, isFinalized, getConversation, setConversation, getValueAsync, getCompletionAsync, setOptions, addVars, setExternFunctions, getOutputOptions, debug: (verbose) => { const f = isFinalized(); console.log('ConvoObject', { isFinalized: f, input: f ? getInput() : null, vars: defaultVars, dependencies, options, externFunctions, externScopeFunctions, internalExternFunctions, conversation: verbose ? getConversation() : undefined, }); return _self; }, convertAsync: () => { const c = getConversation().clone(); c.append(getInput()); return c.toModelInputAsync(); }, flattenAsync: () => { const c = getConversation().clone(); c.append(getInput()); return c.flattenAsync(); }, clone: () => { return clone(false); }, then: (callback) => { getValueAsync().then(callback); return _self; }, catch: (callback) => { getValueAsync().catch(callback); return _self; }, finally: (callback) => { getValueAsync().finally(callback); return _self; }, proxyFunctions: (proxy) => { assertUpdate(); if (typeof valueOrZodType === 'function') { const proxied = proxy(0, valueOrZodType); if (proxied) { valueOrZodType = proxied; dependencies[0] = proxied; } } for (let i = 0; i < values.length; i++) { const fn = values[i]; if (typeof fn !== 'function') { continue; } const proxied = proxy(i + 1, fn); if (proxied) { values[i] = proxied; dependencies[i + 1] = proxied; } } }, lock: () => { const c = clone(true); return { dependencies: c.dependencies, zodType: c.zodType, clone: c.clone, debug: c.debug, isFinalized: c.isFinalized, getOutputOptions: c.getOutputOptions, }; } }; _self[isLocked ? lockedConvoObjectIdentifier : convoObjectIdentifier] = true; return _self; }; exports.convo = convo; const isConvoObject = (value) => { return value?.[convoObjectIdentifier] === true; }; exports.isConvoObject = isConvoObject; const isLockedConvoObject = (value) => { return value?.[lockedConvoObjectIdentifier] === true; }; exports.isLockedConvoObject = isLockedConvoObject; const convoObjectIdentifier = Symbol('ConvoObject'); const lockedConvoObjectIdentifier = Symbol('LockedConvoObject'); const lockFlag = Symbol(); //# sourceMappingURL=convoAsync.js.map