@convo-lang/convo-lang
Version:
The language of AI
248 lines • 7.83 kB
JavaScript
import { getErrorMessage, joinPaths, uiRouterService } from "@iyio/common";
import { Conversation } from "./Conversation";
import { convoTags, convoUsageTokensToString } from "./convo-lib";
export const maxConvoGraphConcurrentStepExe = 5;
export const convoTraverserStateStoreSuffix = '_suffix';
export const convoTraverserProxyVar = '_proxy';
export const defaultConvoGraphUserDataVarName = 'userData';
export const applyConvoTraverserControlPath = (tv) => {
if (tv.controlPath) {
const suffix = tv.state[convoTraverserStateStoreSuffix];
uiRouterService().replace(suffix ? joinPaths(tv.controlPath, suffix) : tv.controlPath);
}
};
export const getConvoTraverserForSaving = (tv) => {
const map = tv.state[convoTraverserProxyVar];
if (!map || (typeof map !== 'object')) {
return tv;
}
tv = { ...tv };
tv.state = { ...tv.state };
for (const e in map) {
delete tv.state[e];
}
return tv;
};
export const getConvoTraverserStoreId = (tv, ext) => {
const suffix = tv.state?.[convoTraverserStateStoreSuffix];
return getConvoTraverserStoreIdById(tv.id, suffix, ext);
};
export const getConvoTraverserStoreIdById = (id, storeSuffix, ext) => {
id = storeSuffix ? id + '-' + storeSuffix : id;
if (ext && !id.endsWith(ext)) {
id += ext;
}
return id;
};
export const getConvoNodeMetadataAsync = async (convo) => {
const outputTypes = [];
const metadata = { outputTypes };
const typeMap = {};
let sharedVars;
if (!convo) {
return { metadata, typeMap, sharedVars: {} };
}
try {
const flat = await convo.getLastAutoFlatAsync();
if (!flat) {
return { metadata, typeMap, sharedVars: {} };
}
const inputVar = flat.exe.getVarAsType('Input');
if (inputVar) {
metadata.inputType = { name: 'Input' };
typeMap['Input'] = inputVar;
}
for (const msg of flat.messages) {
if (msg.tags &&
(convoTags.output in msg.tags) &&
msg.fn?.returnType) {
const outputVar = flat.exe.getVarAsType(msg.fn.returnType);
if (outputVar) {
const output = {
name: msg.fn.returnType,
fnName: msg.fn.name,
};
outputTypes.push(output);
}
}
}
if (!outputTypes.length && inputVar) {
outputTypes.push({
name: 'Input'
});
}
sharedVars = flat.exe.getUserSharedVarsExcludeTypes();
}
catch (ex) {
console.warn('Creating ConvoMetadataAndTypeMap failed. This could be due to undefined vars in the last step of a node', ex);
}
return { metadata, typeMap, sharedVars: sharedVars ?? {} };
};
export const createConvoNodeExecCtxAsync = async (node, convoOptions) => {
const defaultVars = {
...convoOptions?.defaultVars
};
if (node.userData) {
const varName = node.userDataVarName === undefined ? defaultConvoGraphUserDataVarName : node.userDataVarName;
if (varName && defaultVars[varName] === undefined) {
defaultVars[varName] = { ...node.userData };
}
}
const metadataAndMap = await getConvoNodeMetadataAsync((node.sharedConvo || node.steps.length) ?
createConvoNodeExecCtxConvo(node, defaultVars, convoOptions, (node.steps[node.steps.length - 1]?.convo ?? '')) :
null);
return {
...metadataAndMap,
node,
defaultVars,
convo: createConvoNodeExecCtxConvo(node, defaultVars, convoOptions),
steps: node.steps.map((step) => ({
nodeStep: step,
}))
};
};
export const resetConvoNodeExecCtxConvo = (ctx) => {
ctx.convo = createConvoNodeExecCtxConvo(ctx.node, ctx.defaultVars, ctx.convoOptions);
};
export const createConvoNodeExecCtxConvo = (node, defaultVars, convoOptions, appendConvo = '') => {
return new Conversation({
...convoOptions,
defaultVars,
initConvo: ((convoOptions?.initConvo ? convoOptions?.initConvo + '\n\n' : '') +
(node.sharedConvo ? node.sharedConvo + '\n\n' : '') +
appendConvo)
});
};
export const hasConvoGraphDb = (obj) => {
return (obj &&
(typeof obj === 'object') &&
(Array.isArray(obj.db?.nodes)) &&
(Array.isArray(obj.db?.edges)) &&
(Array.isArray(obj.db?.traversers))) ? true : false;
};
export const fixConvoGraphDb = (db) => {
let changes = false;
if (!db.edges) {
db.edges = [];
changes = true;
}
if (!db.nodes) {
db.nodes = [];
changes = true;
}
if (!db.traversers) {
db.traversers = [];
changes = true;
}
if (!db.inputs) {
db.inputs = [];
changes = true;
}
if (!db.sourceNodes) {
db.sourceNodes = [];
changes = true;
}
return changes;
};
export const createEmptyConvoGraphDb = () => {
return {
nodes: [],
edges: [],
traversers: [],
inputs: [],
sourceNodes: [],
};
};
export const roundConvoGraphLayoutProps = (db) => {
roundLayoutItems(db.nodes);
roundLayoutItems(db.edges);
roundLayoutItems(db.inputs);
roundLayoutItems(db.sourceNodes);
roundLayoutItems(db.traversers);
};
const roundLayoutItems = (items) => {
if (!items) {
return;
}
for (const i of items) {
if (i.x !== undefined) {
i.x = Math.round(i.x);
}
if (i.y !== undefined) {
i.y = Math.round(i.y);
}
}
};
export const createConvoGraphEntity = (entities) => {
if (entities.node) {
return {
type: 'node',
id: entities.node.id,
entity: entities.node,
...entities
};
}
else if (entities.edge) {
return {
type: 'edge',
id: entities.edge.id,
entity: entities.edge,
...entities
};
}
else if (entities.input) {
return {
type: 'input',
id: entities.input.id,
entity: entities.input,
...entities
};
}
else if (entities.source) {
return {
type: 'source',
id: entities.source.id,
entity: entities.source,
...entities
};
}
else if (entities.traverser) {
return {
type: 'traverser',
id: entities.traverser.id,
entity: entities.traverser,
...entities
};
}
else {
return undefined;
}
};
export const compareConvoGraphSelections = (a, b) => {
if (a === b) {
return true;
}
if (!a || !b) {
return false;
}
if (a.id !== b.id || a.multi.length !== b.multi.length) {
return false;
}
for (let i = 0; i < a.multi.length; i++) {
const sa = a.multi[i];
const sb = b.multi[i];
if (sa?.id !== sb?.id) {
return false;
}
}
return true;
};
export const getConvoGraphEventString = (e, usage) => {
try {
return (`${e.type} / ${e.traverser?.exeState} - ${e.text} - \npayload:${JSON.stringify(e.traverser?.payload ?? null, null, 4)}\nstate:${JSON.stringify(e.traverser?.state ?? null, null, 4)}${e.node?.userData ? `\nuserData:${JSON.stringify(e.node.userData, null, 4)}` : ''}${usage ? `\nusage: ${convoUsageTokensToString(usage)}` : ''}`);
}
catch (ex) {
return (`${e.type} / ${e.traverser?.exeState} - ${e.text} - \njsonStringifyError:${getErrorMessage(ex)}${usage ? `\nusage: ${convoUsageTokensToString(usage)}` : ''}`);
}
};
//# sourceMappingURL=convo-graph-lib.js.map