Skip to content

Commit 12ab178

Browse files
authored
Merge pull request #468 from MyLife-Services/version-0031-updates
Version 0031 updates
2 parents 32b0104 + c2fa0f4 commit 12ab178

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+3220
-1342
lines changed

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

+16-8
Original file line numberDiff line numberDiff line change
@@ -394,9 +394,11 @@ class BotAgent {
394394
* @param {String} type - The type of conversation, defaults to `chat`
395395
* @param {String} form - The form of conversation, defaults to `system-avatar`
396396
* @param {String} prompt - The prompt for the conversation (optional)
397+
* @param {Guid} scriptAdvisorLlmId - The script advisor llm id (optional)
398+
* @param {String} mbr_id - The member id to use for conversation (optional)
397399
* @returns {Promise<Conversation>} - The Conversation instance
398400
*/
399-
async conversationStart(type='chat', form='system-avatar', prompt, scriptAdvisorLlmId){
401+
async conversationStart(type='chat', form='system-avatar', prompt, scriptAdvisorLlmId, mbr_id){
400402
let { id, llm_id, } = this.avatar
401403
if(type==='experience'){
402404
id = this.#factory.actor.id
@@ -405,7 +407,7 @@ class BotAgent {
405407
// use member avatar?
406408
llm_id = scriptAdvisorLlmId
407409
}
408-
const Conversation = await mConversationStart(type, form, id, null, llm_id, this.#llm, this.#factory, prompt)
410+
const Conversation = await mConversationStart(type, form, id, undefined, llm_id, this.#llm, this.#factory, prompt, undefined, mbr_id)
409411
return Conversation
410412
}
411413
/**
@@ -462,7 +464,7 @@ class BotAgent {
462464
role: 'user',
463465
})
464466
memberInput = `${ message }Let's begin to LIVE MEMORY, id: ${ item.id }, MEMORY SUMMARY starts this conversation`
465-
const Conversation = await mConversationStart('memory', type, bot_id, null, llm_id, this.#llm, this.#factory, memberInput, messages)
467+
const Conversation = await mConversationStart('memory', type, bot_id, undefined, llm_id, this.#llm, this.#factory, memberInput, messages)
466468
Conversation.action = 'living'
467469
livingMemory.Conversation = Conversation
468470
livingMemory.id = this.#factory.newGuid
@@ -1084,11 +1086,17 @@ async function mConversationDelete(Conversation, factory, llm){
10841086
* @param {AgentFactory} factory - Agent Factory object
10851087
* @param {string} prompt - The prompt for the conversation (optional)
10861088
* @param {Message[]} messages - The array of messages to seed the conversation
1089+
* @param {String} mbr_id_Override - The member id to use for conversation (optional)
10871090
* @returns {Conversation} - The conversation object
10881091
*/
1089-
async function mConversationStart(type='chat', form='system', bot_id, thread_id, llm_id, llm, factory, prompt, messages){
1090-
const { mbr_id, newGuid: id, } = factory
1091-
const metadata = { bot_id, conversation_id: id, mbr_id, },
1092+
async function mConversationStart(type='chat', form='system', bot_id, thread_id, llm_id, llm, factory, prompt, messages, mbr_id_Override){
1093+
const { mbr_id: mbr_id_innate, newGuid: id, } = factory
1094+
const mbr_id = mbr_id_Override
1095+
?? mbr_id_innate
1096+
const metadata = {
1097+
bot_id,
1098+
conversation_id: id,
1099+
},
10921100
processStartTime = Date.now(),
10931101
thread = await mThread(llm, thread_id, messages, metadata)
10941102
const Conversation = new (factory.conversation)(
@@ -1212,7 +1220,7 @@ function mGetGPTResources(globals, toolName, vectorstoreId){
12121220
async function mInit(BotAgent, bots, Avatar, factory, llm){
12131221
const { vectorstoreId, } = BotAgent
12141222
bots.push(...await mInitBots(vectorstoreId, Avatar, factory, llm))
1215-
BotAgent.setActiveBot(null, false)
1223+
BotAgent.setActiveBot(undefined, false)
12161224
}
12171225
/**
12181226
* Initializes active bots based upon criteria.
@@ -1345,7 +1353,7 @@ async function mMigrateChat(Bot, llm, saveConversation=false){
13451353
if(!summaryMessages.length)
13461354
return
13471355
/* add messages to new thread */
1348-
const newThread = await mThread(llm, null, summaryMessages.reverse(), metadata)
1356+
const newThread = await mThread(llm, undefined, summaryMessages.reverse(), metadata)
13491357
if(!!conversation){
13501358
conversation.setThread(newThread)
13511359
if(saveConversation)

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

+204-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import LLMServices from "../../mylife-llm-services.mjs"
21
import BotAgent from "./bot-agent.mjs"
2+
import { Share, } from '../../mylife-models.mjs'
33
import { Marked } from 'marked'
44
/* module constants */
55
const mAvailableEventActionMap = {
@@ -272,7 +272,6 @@ class ExperienceAgent {
272272
Experience = mExperience(experienceData, this.#botAgent, this.#llm, this.#factory, this.#variables)
273273
this.#experiences.push(Experience)
274274
}
275-
console.log()
276275
await Experience.run(memberInput)
277276
return Experience
278277
}
@@ -376,6 +375,203 @@ class ExperienceEvent {
376375
this.#portrayed = !!portrayed
377376
}
378377
}
378+
/* ShareAgent class */
379+
/**
380+
* @class ShareAgent
381+
* Handles the `sharing` process for Mylife currently only via System Avatar.
382+
*/
383+
class ShareAgent {
384+
/* private properties */
385+
#avatar
386+
#botAgent // @todo - unclear if necessary
387+
#factory
388+
#llm
389+
#shares=[] // current-list of active shares
390+
constructor(obj={}, avatar, factory, llm){
391+
this.#avatar = avatar
392+
this.#factory = factory
393+
this.#llm = llm
394+
obj = this.#factory.globals.sanitize(obj)
395+
Object.assign(this, obj)
396+
}
397+
/* public functions */
398+
/**
399+
* Accepts the warnings for a share.
400+
* @param {Guid} instanceId - The Share instance id
401+
* @returns {Boolean} - The Share acceptance status
402+
*/
403+
acceptWarnings(instanceId){
404+
const Share = this.share(instanceId)
405+
if(!!Share)
406+
return Share.acceptWarnings()
407+
else
408+
throw new Error('Share not found')
409+
}
410+
/**
411+
* Create share with new data.
412+
* @param {object} shareData - The share data object
413+
* @returns {Promise<object>} - The updated Share object
414+
*/
415+
async create(shareData){
416+
const share = await this.#factory.createShare(shareData)
417+
this.#shares.push(share.id)
418+
return share
419+
}
420+
/**
421+
* Deletes a share from MyLife `shares` container and associated object (get itemId from `share` itself).
422+
* @param {Guid} sid - The Share id
423+
* @returns {Promise<Boolean>} - Success or failure of the operation
424+
*/
425+
async delete(shareId){
426+
const { itemId, } = await this.getShare(shareId)
427+
this.#factory.deleteShare(shareId, itemId)
428+
this.#shares = this.#shares.filter(share=>share!==shareId)
429+
return true
430+
}
431+
/**
432+
* Get a share data by id.
433+
* @param {Guid} sid - The share id
434+
* @returns {Promise<object>} - The MemberShare document
435+
*/
436+
async getShare(shareId){
437+
let response = await this.#factory.getShare(shareId, this.#factory.mbr_id)
438+
response = this.#factory.globals.sanitize(response)
439+
return response
440+
}
441+
/**
442+
* Gets all owned relevant shares from MyLife `shares` container, either by item or member.
443+
* @param {Guid} itemId - The item id (optional)
444+
* @returns {Promise<object[]>} - The MemberShare array
445+
*/
446+
async getShares(itemId){
447+
let response = await this.#factory.getShares(itemId)
448+
if(Array.isArray(response))
449+
response = response.map(share=>this.#factory.globals.sanitize(share))
450+
return response
451+
}
452+
/**
453+
* Get a memory `Header`.
454+
* @param {guid} instanceId - Share instanceId
455+
* @returns {Promise<object>} - shareHeader object
456+
*/
457+
async header(instanceId){
458+
const Share = this.share(instanceId)
459+
if(Share && !Share.header){
460+
let MemberAvatar = await this.#factory.avatarProxy(Share.mbr_id)
461+
const shareData = await MemberAvatar.cleanShare(Share) // operates directly upon Shared Memory Share
462+
Share.header = shareData
463+
}
464+
return Share?.header
465+
}
466+
/**
467+
* Plays a public share.
468+
* @param {Guid} instanceId - The instance id
469+
* @param {object} input - The recipient input
470+
* @returns {object} - The next message(s) in the share experience
471+
*/
472+
async play(instanceId, input){
473+
const Share = this.share(instanceId)
474+
if(!Share)
475+
throw new Error('Share not found')
476+
else if(!Share.header || !Share.warningsAccepted)
477+
return await this.shareHeader(instanceId)
478+
else if(!Share.initialized)
479+
await this.shareInit(Share)
480+
const shareContent = await Share.play(input)
481+
shareContent.scene = new Marked().parse(shareContent.scene)
482+
return shareContent
483+
}
484+
share(instanceId, shareId){
485+
let Share
486+
if(this.#factory.globals.isValidGuid(instanceId))
487+
Share = this.#shares.find(share=>share.instanceId===instanceId)
488+
else if(this.#factory.globals.isValidGuid(shareId))
489+
Share = this.#shares.find(share=>share.id===shareId)
490+
return Share
491+
}
492+
/**
493+
* Initializes a share experience.
494+
* @param {Share} Share - The Share instance
495+
* @returns {object} - The first message(s) in the share experience
496+
*/
497+
async shareInit(Share){
498+
if(!Share.header) // set header if not already set
499+
await this.shareHeader(Share.instanceId)
500+
/* scene creation */
501+
let prompt = `# Scenes\n`
502+
const shareData = {}
503+
if(Share.conclusion?.length)
504+
prompt += `- conclusion: ${ Share.conclusion }\n`
505+
if(Share.voice?.length)
506+
prompt += `- voice: ${ Share.voice }\n`
507+
prompt += `- summary: ${ Share.summary }`
508+
const messages = await this.#llm.getLLMResponse(undefined, mDefaultScriptAdvisorLLMId, prompt)
509+
if(messages?.[0]){
510+
const { content, thread_id, } = messages[0]
511+
const message = content
512+
.filter(_content=>_content.type==='text')
513+
?.[0]
514+
?.text
515+
?.value
516+
if(message?.length){
517+
const scenes = JSON.parse(message).scenes
518+
if(scenes.length===1)
519+
scenes = scenes.first()
520+
.split(/(?=(scene\s*\d+:?\n?))/i)
521+
.filter(item =>item.trim()!=='')
522+
const lastItem = scenes[scenes.length - 1].trim()
523+
shareData.scenes = scenes
524+
}
525+
if(thread_id?.length)
526+
this.#llm.deleteThread(thread_id) // no await
527+
}
528+
/* set Conversation */
529+
shareData.Conversation = await this.#avatar.conversationStart('share', 'share-agent', Share.mbr_id)
530+
Share.init(shareData)
531+
setTimeout(_=>{ // @todo - incorporate lock
532+
if(this.share(Share.instanceId))
533+
this.#shares = this.#shares.filter(share=>share.instanceId!==Share.instanceId)
534+
Share.stop()
535+
}, 10 * 60 * 1000)
536+
}
537+
/**
538+
* Stops a share experience.
539+
* @param {Guid} instanceId - The Share instance id
540+
* @returns {Promise<object>} - The share stop object
541+
*/
542+
async stop(instanceId){
543+
const Share = this.share(instanceId)
544+
if(Share){
545+
this.#shares = this.#shares.filter(share=>share.instanceId!==Share.instanceId)
546+
return {
547+
responses: Share.stop(),
548+
success: true
549+
}
550+
}
551+
}
552+
/**
553+
* Update a share with provided data.
554+
* @param {object} shareData - The share data object
555+
* @returns {Promise<object>} - The updated Share object
556+
*/
557+
async update(shareData){
558+
return await this.#factory.updateShare(shareData)
559+
}
560+
async validateShare(shareId){
561+
if(!this.share(shareId)){ // protect in case instanceId sent
562+
const share = await this.#factory.getShare(shareId)
563+
if(!share)
564+
throw new Error(`Share not found: ${ shareId }`)
565+
share.instanceId = this.#factory.newGuid
566+
const _Share = new Share(share)
567+
if(!_Share.mbr_id)
568+
throw new Error('Invalid Share, no Member associated with content')
569+
shareId = _Share.instanceId
570+
this.#shares.push(_Share)
571+
}
572+
return shareId
573+
}
574+
}
379575
/* module functions */
380576
/**
381577
* Creates cast and returns associated `cast` object.
@@ -403,7 +599,7 @@ function mCast(cast, botAgent, Factory){
403599
case 'member':
404600
case 'member-bot':
405601
default:
406-
Bot = botAgent.bot(null, form)
602+
Bot = botAgent.bot(undefined, form)
407603
break
408604
}
409605
const Actor = new CastMember(castMember, Bot, Factory)
@@ -922,7 +1118,7 @@ function mLocation(Experience, eid){
9221118
eid = eid
9231119
?? scriptEvents[0].id
9241120
const iteration = 0
925-
const sid = Experience.scene(null, eid).id
1121+
const sid = Experience.scene(undefined, eid).id
9261122
return { xid, eid, iteration, sid, }
9271123
}
9281124
/**
@@ -969,4 +1165,7 @@ function mReplaceVariables(prompt, variableList, variableValues){
9691165
return prompt
9701166
}
9711167
/* exports */
972-
export default ExperienceAgent
1168+
export {
1169+
ExperienceAgent,
1170+
ShareAgent,
1171+
}

inc/js/api-functions.mjs

+4-4
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ async function entry(ctx){
4444
async function experienceBuilder(ctx){
4545
await mAPIKeyValidation(ctx)
4646
const { assistantType, mbr_id } = ctx.state
47-
const { eid, sid } = ctx.params
47+
const { eid, } = ctx.params
4848
const { experience } = ctx.request.body?.experience
4949
if(!experience)
5050
ctx.throw(400, 'No experience provided for builder. Use `experience` field.')
@@ -314,9 +314,9 @@ async function upload(ctx){
314314
* @returns {Promise<void>}
315315
*/
316316
async function mAPIKeyValidation(ctx){ // transforms ctx.state
317-
if(ctx.params.mid === ':mid')
318-
ctx.params.mid = undefined
319-
const memberId = ctx.params?.mid
317+
if(ctx.query.mid === ':mid')
318+
ctx.query.mid = undefined
319+
const memberId = ctx.query?.mid
320320
?? ctx.request.body?.mbr_id
321321
?? ctx.request.body?.memberKey
322322
?? ctx.session?.APIMemberKey

inc/js/core.mjs

+2
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,9 @@ class Organization extends Member { // form=organization
236236
}
237237
class MyLife extends Organization { // form=server
238238
#avatar // MyLife's private class avatar, _same_ object reference as Member Class's `#avatar`
239+
#currentShares = [] // array of current shares
239240
#factory
241+
#shareAgent
240242
#version = '0.0.0' // indicates error
241243
constructor(Factory){ // no session presumed to exist
242244
super(Factory)

inc/js/factory-class-extenders/class-conversation-functions.mjs

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ async function mSaveConversation(Conversation, factory){
1212
form,
1313
id,
1414
isSaved=false,
15+
mbr_id,
1516
name,
1617
thread,
1718
type,
@@ -26,6 +27,7 @@ async function mSaveConversation(Conversation, factory){
2627
form,
2728
id,
2829
messages,
30+
mbr_id,
2931
name,
3032
thread,
3133
type,
@@ -35,7 +37,7 @@ async function mSaveConversation(Conversation, factory){
3537
}
3638
const updatedConversation = await factory.dataservices.patch(
3739
id,
38-
{ messages, }
40+
{ mbr_id, messages, }
3941
)
4042
return !!updatedConversation
4143
}

0 commit comments

Comments
 (0)