UNPKG

json-object-editor

Version:

JOE the Json Object Editor | Platform Edition

173 lines (156 loc) 7.4 kB
var schema = { title: "Ai Conversation | ${name}", display:'Ai Convo', summary:{ description:'Metadata record for an AI conversation between a user, optional external members, and one or more assistants.', purpose:'Use ai_conversation to track which user and assistant are involved in a chat, the OpenAI thread_id, high-level status, tags, and a summary. Full message history is fetched from OpenAI at runtime rather than stored in Joe.', labelField:'name', defaultSort:{ field:'created', dir:'desc' }, searchableFields:['name','info','summary','thread_id','tags','_id'], allowedSorts:['created','joeUpdated','name'], relationships:{ outbound:[ { field:'user', targetSchema:'user', cardinality:'one' }, { field:'assistant', targetSchema:'ai_assistant', cardinality:'one' }, { field:'members', targetSchema:'members', cardinality:'many' }, { field:'status', targetSchema:'status', cardinality:'one' }, { field:'tags', targetSchema:'tag', cardinality:'many' } ], inbound:{ graphRef:'server/relationships.graph.json' } }, joeManagedFields:['created','joeUpdated'], fields:[ { name:'_id', type:'string', required:true }, { name:'itemtype', type:'string', required:true, const:'ai_conversation' }, { name:'name', type:'string', required:true }, { name:'info', type:'string' }, { name:'user', type:'string', isReference:true, targetSchema:'user' }, { name:'assistant', type:'string', isReference:true, targetSchema:'ai_assistant' }, { name:'members', type:'string', isArray:true, isReference:true, targetSchema:'members' }, { name:'thread_id', type:'string' }, { name:'summary', type:'string' }, { name:'status', type:'string', isReference:true, targetSchema:'status' }, { name:'tags', type:'string', isArray:true, isReference:true, targetSchema:'tag' }, { name:'joeUpdated', type:'string', format:'date-time' }, { name:'created', type:'string', format:'date-time' } ] }, info: "Tracks AI conversations across users, assistants, and external members, storing only summaries for performance.", methods:{ chatSpawner:async function(object_id){ await _joe.Ai.spawnContextualChat(object_id); }, listConversations:function(bus,oneline){ let html =''; let conversations = _joe.Data.ai_conversation.filter(co=>{ if(co?.context_objects?.includes(bus._id)) return true; }) $c.sortBy(conversations,'!created'); let temp = oneline?null:'<joe-subtext>${RUN[_joe.Utils.prettyPrintDTS;${created}]}</joe-subtext><joe-subtitle>${name}</joe-subtitle>'; conversations.map(tct=>{ html+=_joe.renderFieldListItem(tct,temp,'ai_conversation'); }) return html; }, }, listView:{ title: function(chat){ return ` <joe-subtext >${_joe.Utils.prettyPrintDTS(chat.created)}</joe-subtext> <joe-title>${chat.name}</joe-title> <joe-title>${_joe.SERVER.User.Render.cubes(chat.user,'fleft')}</joe-title> <div>${(chat.context_objects||[]).map(function(ref){ var obj = $J.get(ref); if(obj){ return `<joe-subtext>${obj.itemtype}:<b>${obj.name}</b> - ${obj._id}</joe-subtext>`; }else{ return `<joe-subtext>${ref}</joe-subtext>`; } }).join('')}</div> `; }, listWindowTitle: 'Ai Conversations' }, fields: function() { return [ "name", "info", { section_start: "participants", display: "Participants", collapsed: false }, { name: "user", type: "select", values: "user", display: "JOE User", comment: "Select the JOE user who initiated this conversation.",width:'50%'}, {name:'assistant',type:"select",values:'ai_assistant',display:'AI Assistant',width:'50%', comment:'Select the AI assistant to use for this conversation.',default:function(){ try{ var defAi = Ai.getDefaultAssistant(); return defAi._id; }catch(e){ console.log('Error getting default assistant',e); } }, }, { name: "members", type: "objectReference", values: "members", display: "External Members"}, // { name: "assistants", type: "group", cssClass:"ai-options", template:function(ass,curObj){ // return `${ass.name} || ${curObj.name}`; // }, values: function() { return _joe.getDataset('ai_assistant'); }, display: "Assistants", cols:2 }, { section_end: "participants" }, { section_start: "thread", display: "Thread", collapsed: true }, { name: "thread_id", type: "text", display: "OpenAI Thread ID", locked: true }, { section_end: "thread" }, { section_start: "summary", display: "Summary", collapsed: false }, { name: "summary", type: "wysiwyg", display: "Conversation Summary", height: "300px", comment: "Auto-generated after key points or closing." }, { section_end: "summary" }, { section_start: "system", collapsed: true }, "_id", "created", "joeUpdated", "itemtype", { section_end: "system" }, { sidebar_start: "right", collapsed: false }, 'status', "tags", { name: "openChat", type: "button", display: "Continue Conversation", icon:"ai_assistant", onclick2:function(object){ if (!object || !object._id) return ''; return `_joe.Ai.spawnChat('${object._id}');`; }, onclick:function(object){ if (!object || !object._id) return ''; return `_joe.schemas.ai_conversation.methods.chatSpawner('${object._id}');`; }, }, {name:'context_objects',type:"objectReference", display:'Context Objects', comment:'Objects included in this conversation for Ai context.', locked:true,values:function(obj,prop){ return JOE.getData(); }}, { sidebar_end: "right" }, ]; }, idprop: "_id", sorter: ["!created"], }; module.exports = schema; /** * AI Conversation Schema * * Purpose: * - Tracks live AI conversations linked to users, assistants, and external members. * - Stores only metadata and final conversation summaries (not full chat messages). * - Supports dynamic pulling of live thread content from OpenAI at runtime. * * Key Concepts: * - user: Internal staff or admin account who initiated the conversation. * - members: External participants (clients, business users), optional and multiple. * - assistants: One or more AI assistants participating in the conversation. * - thread_id: The OpenAI thread ID for live runtime message retrieval. * - summary: Final AI-generated overview of the conversation (saved on close). * * Best Practices: * - Messages are *not* stored permanently in Joe for performance and privacy. * - Summaries provide lightweight snapshots for audits and reviews. * - Chat UIs should always fetch full threads from OpenAI at runtime. */