Skip to content

Commit 05e40b7

Browse files
authored
Merge pull request #441 from MyLife-Services/version-0.0.28-updates
Version 0.0.28 updates push to PROD
2 parents 8f51c46 + c2e9533 commit 05e40b7

23 files changed

+1138
-304
lines changed

inc/js/agents/system/bot-agent.mjs

+21-6
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,15 @@ class BotAgent {
391391
const Conversation = await mConversationStart(type, form, bot_id, null, llm_id, this.#llm, this.#factory, prompt)
392392
return Conversation
393393
}
394+
/**
395+
* Given an itemId, evaluates aspects of item summary. Evaluate content is a vanilla function for MyLife, so does not require intervening intelligence and relies on the factory's modular LLM.
396+
* @param {Guid} itemId - The item id
397+
* @returns {Object} - The Response object { instruction, responses, success, }
398+
*/
399+
async evaluate(itemId){
400+
const response = await this.#factory.evaluate(itemId, this.avatar.llm_id)
401+
return response
402+
}
394403
/**
395404
* Gets the correct bot for the item type and form.
396405
* @todo - deprecate
@@ -405,6 +414,7 @@ class BotAgent {
405414
return itemForm.toLowerCase()==='diary'
406415
? 'diary'
407416
: 'journaler'
417+
return 'avatar'
408418
}
409419
/**
410420
* Get a static or dynamic greeting from active bot.
@@ -432,9 +442,9 @@ class BotAgent {
432442
const messages = []
433443
messages.push({
434444
content: `## MEMORY SUMMARY Reference for id: ${ item.id }\n### FOR REFERENCE ONLY\n${ item.summary }\n`,
435-
role: 'assistant',
445+
role: 'user',
436446
})
437-
memberInput = `${ message }Let's begin to LIVE MEMORY, id: ${ item.id }, MEMORY SUMMARY in previous message`
447+
memberInput = `${ message }Let's begin to LIVE MEMORY, id: ${ item.id }, MEMORY SUMMARY starts this conversation`
438448
const Conversation = await mConversationStart('memory', type, bot_id, null, llm_id, this.#llm, this.#factory, memberInput, messages)
439449
Conversation.action = 'living'
440450
livingMemory.Conversation = Conversation
@@ -580,8 +590,7 @@ class BotAgent {
580590
}
581591
await Bot.update(_bot, botOptions)
582592
if(migrateThread)
583-
if(!await Bot.migrateChat())
584-
console.log(`thread migration failed for bot: ${ bot_id }`)
593+
await Bot.migrateChat()
585594
}
586595
return Bot
587596
}
@@ -1005,9 +1014,9 @@ async function mCallLLM(Conversation, allowSave=true, llm, factory, avatar){
10051014
if(!prompt?.length)
10061015
throw new Error('No `prompt` found in Conversation for `mCallLLM`.')
10071016
const botResponses = await llm.getLLMResponse(thread_id, llm_id, prompt, factory, avatar)
1008-
const run_id = botResponses?.[0]?.run_id
1009-
if(!run_id?.length)
1017+
if(!botResponses?.length)
10101018
return
1019+
const { run_id, } = botResponses[0]
10111020
Conversation.addRun(run_id)
10121021
botResponses
10131022
.filter(botResponse=>botResponse?.run_id===Conversation.run_id)
@@ -1095,12 +1104,17 @@ function mGetAIFunctions(type, globals, vectorstoreId){
10951104
case 'avatar':
10961105
case 'personal-assistant':
10971106
case 'personal-avatar':
1107+
tools.push(
1108+
globals.getGPTJavascriptFunction('changeTitle'),
1109+
globals.getGPTJavascriptFunction('getSummary'),
1110+
)
10981111
includeSearch = true
10991112
break
11001113
case 'biographer':
11011114
case 'personal-biographer':
11021115
tools.push(
11031116
globals.getGPTJavascriptFunction('changeTitle'),
1117+
globals.getGPTJavascriptFunction('endReliving'),
11041118
globals.getGPTJavascriptFunction('getSummary'),
11051119
globals.getGPTJavascriptFunction('itemSummary'),
11061120
globals.getGPTJavascriptFunction('updateSummary'),
@@ -1297,6 +1311,7 @@ async function mMigrateChat(Bot, llm, saveConversation=false){
12971311
conversation.save() // no `await`
12981312
}
12991313
await Bot.setThread(newThread.id) // autosaves `thread_id`, no `await`
1314+
console.log(`chat migrated::from ${ thread_id } to ${ newThread.id }`, botType )
13001315
}
13011316
/**
13021317
* Gets or creates a new thread in LLM provider.

inc/js/functions.mjs

+23-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ async function about(ctx){
2020
await ctx.render('about')
2121
} else {
2222
const { avatar: Avatar, } = ctx.state
23-
const aboutFilePath = path.resolve(__dirname, '../..', 'views/about.html')
23+
const aboutFilePath = path.resolve(__dirname, '../..', 'views/assets/html/_about.html')
2424
const html = await fs.readFile(aboutFilePath, 'utf-8')
2525
const response = await Avatar.renderContent(html)
2626
ctx.body = response
@@ -151,6 +151,16 @@ async function createBot(ctx){
151151
bot.teams.push(teamId)
152152
ctx.body = await avatar.createBot(bot)
153153
}
154+
/**
155+
* Given an itemId, evaluates aspects of contents of the data record.
156+
* @param {Koa} ctx - Koa Context object
157+
* @returns {object} - The evaluation ersponse
158+
*/
159+
async function evaluate(ctx){
160+
const { iid, } = ctx.params
161+
const { avatar: Avatar, } = ctx.state
162+
ctx.body = await Avatar.evaluate(iid)
163+
}
154164
/**
155165
* Save feedback from the member.
156166
* @param {Koa} ctx - Koa Context object
@@ -232,7 +242,7 @@ async function item(ctx){
232242
if(!item?.id && id?.length)
233243
item.id = id
234244
const response = await avatar.item(item, method)
235-
delete avatar.frontendInstruction // already embedded in response
245+
delete avatar.frontendInstruction
236246
ctx.body = response
237247
}
238248
async function logout(ctx){
@@ -292,9 +302,16 @@ async function passphraseReset(ctx){
292302
* @param {Koa} ctx - Koa Context object
293303
*/
294304
async function privacyPolicy(ctx){
295-
ctx.state.title = `MyLife Privacy Policy`
296-
ctx.state.subtitle = `Effective Date: 2024-01-01`
297-
await ctx.render('privacy-policy') // privacy-policy
305+
if(ctx.state.locked){
306+
ctx.state.title = `MyLife Privacy Policy`
307+
await ctx.render('privacy-policy')
308+
} else {
309+
const { avatar: Avatar, } = ctx.state
310+
const aboutFilePath = path.resolve(__dirname, '../..', 'views/assets/html/_privacy-policy.html')
311+
const html = await fs.readFile(aboutFilePath, 'utf-8')
312+
const response = await Avatar.renderContent(html)
313+
ctx.body = response
314+
}
298315
}
299316
/**
300317
* Direct request from member to retire a bot.
@@ -431,6 +448,7 @@ export {
431448
chat,
432449
collections,
433450
createBot,
451+
evaluate,
434452
feedback,
435453
greetings,
436454
help,

inc/js/globals.mjs

+30-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Guid } from 'js-guid'
88
const mAiJsFunctions = await mParseFunctions()
99
const mEmailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
1010
const mForbiddenCosmosFields = ['$', '_', ' ', '@', '#',]
11+
const mForbiddenValues = [undefined, null, NaN]
1112
const mGuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i // regex for GUID validation
1213
const mOpenAIBotModel = process.env.OPENAI_MODEL_CORE_BOT
1314
?? 'gpt-4o'
@@ -113,20 +114,42 @@ class Globals extends EventEmitter {
113114
const regex = /^\d+\.\d+\.\d+$/
114115
return typeof version === 'string' && regex.test(version)
115116
}
117+
/**
118+
* Populate an object with data, alters in place the incoming class instance.
119+
* @param {object} obj - Object to populate
120+
* @param {object} data - Data to populate object with
121+
* @param {Array} immutableFields - Fields that should not be altered, and are removed from update
122+
* @returns {void}
123+
*/
124+
populateObject(obj, data, immutableFields){
125+
if(!obj || typeof obj!=='object')
126+
throw new Error('Parameter requires an object')
127+
if(!data || typeof data!=='object')
128+
throw new Error('Parameter requires an object')
129+
data = this.sanitize(data, immutableFields)
130+
Object.keys(data)
131+
.forEach(key=>{
132+
const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(obj), key)
133+
if(descriptor && (typeof descriptor.get==='function' || typeof obj[key]==='function'))
134+
return // Skip functions and getters
135+
obj[key]=data[key]
136+
})
137+
}
116138
/**
117139
* Sanitize an object by removing forbidden Cosmos fields and undefined/null values.
118-
* @param {object} object - Cosmos document to sanitize
140+
* @param {object} obj - Cosmos document to sanitize
141+
* @param {Array} immutableFields - Fields that should not be altered, and are removed from update
119142
* @returns {object} - Sanitized data object
120143
*/
121-
sanitize(object){
122-
if(!object || typeof object !== 'object')
123-
throw new Error('Parameter requires an object')
144+
sanitize(obj, immutableFields=[]){
145+
if(!obj || typeof obj!=='object')
146+
return {}
124147
const sanitizedData = Object.fromEntries(
125-
Object.entries(object)
148+
Object.entries(obj)
126149
.filter(([key, value])=>
127150
!mForbiddenCosmosFields.some(char => key.startsWith(char)) &&
128-
value !== null &&
129-
value !== undefined
151+
!immutableFields.includes(key) &&
152+
!mForbiddenValues.includes(value)
130153
)
131154
)
132155
return sanitizedData

inc/js/memory-functions.mjs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
/* imports */
22
import {
33
activateBot,
4-
interfaceMode, // @stub - deprecate?
54
upload,
65
} from './functions.mjs'
76
/* module export functions */

0 commit comments

Comments
 (0)