From 13735a693679b7eee39534b1fdd39dc03a33e1d2 Mon Sep 17 00:00:00 2001
From: Erik Jespersen <42016062+Mookse@users.noreply.github.com>
Date: Mon, 23 Sep 2024 23:39:47 -0400
Subject: [PATCH 1/2] 365 version 0022 updates (#371)
* 20240917 @Mookse
- version change
* 20240917 @Mookse
- Reliving Memory is not showing copy of entered text in Scrapbook Chat Window #331
- backend
* 20240919 @Mookse
- minor intel mods
* 20240919 @Mookse
- Reliving Memory is not showing copy of entered text in Scrapbook Chat Window #331
- frontend
* 20240923 @Mookse
- frontend fix when no .instruction
* 20240923 @Mookse
- tracking for callbacks
* 20240923 @Mookse
- small publicity updates
* 20240923 @Mookse
- add tutorial to member avatar menu
* 20240923 @Mookse
- stub for retires
---------
Signed-off-by: Erik Jespersen <42016062+Mookse@users.noreply.github.com>
---
inc/js/mylife-llm-services.mjs | 16 ++++--
.../biographer-intelligence-1.4.json | 3 +-
server.js | 2 +-
views/assets/css/bots.css | 21 ++++----
views/assets/html/_bots.html | 10 +++-
views/assets/js/bots.mjs | 49 ++++++++++++++++++-
views/assets/js/experience.mjs | 11 ++---
views/assets/js/members.mjs | 39 ++++++++++-----
8 files changed, 111 insertions(+), 40 deletions(-)
diff --git a/inc/js/mylife-llm-services.mjs b/inc/js/mylife-llm-services.mjs
index a52646c..4119d92 100644
--- a/inc/js/mylife-llm-services.mjs
+++ b/inc/js/mylife-llm-services.mjs
@@ -410,11 +410,12 @@ async function mRunFunctions(openai, run, factory, avatar){ // add avatar ref
action = `journal entry failed to save, notify member and continue on for now`
}
confirmation.output = JSON.stringify({ action, success, })
+ console.log('mRunFunctions()::entrySummary', toolArguments, confirmation.output)
return confirmation
case 'getsummary':
case 'get_summary':
case 'get summary':
- let { summary, } = item ?? {}
+ let { summary, title: _getSummaryTitle, } = item ?? {}
if(!summary?.length){
action = `error getting summary for itemId: ${ itemId ?? 'missing itemId' } - halt any further processing and instead ask user to paste summary into chat and you will continue from there to incorporate their message.`
summary = 'no summary found for itemId'
@@ -423,16 +424,16 @@ async function mRunFunctions(openai, run, factory, avatar){ // add avatar ref
success = true
}
confirmation.output = JSON.stringify({ action, itemId, success, summary, })
- console.log('mRunFunctions()::getSummary::confirmation', itemId)
+ console.log('mRunFunctions()::getsummary', itemId, _getSummaryTitle)
return confirmation
case 'hijackattempt':
case 'hijack_attempt':
case 'hijack-attempt':
case 'hijack attempt':
- console.log('mRunFunctions()::hijack_attempt', toolArguments)
action = 'attempt noted in system and user ejected; greet per normal as first time new user'
success = true
confirmation.output = JSON.stringify({ action, success, })
+ console.log('mRunFunctions()::hijack_attempt', toolArguments)
return confirmation
case 'registercandidate':
case 'register_candidate':
@@ -454,6 +455,7 @@ async function mRunFunctions(openai, run, factory, avatar){ // add avatar ref
case 'story-summary':
case 'story_summary':
case 'story summary':
+ console.log('mRunFunctions()::storySummary', toolArguments)
const story = await factory.story(toolArguments)
if(story){
const { keywords, phaseOfLife, } = story
@@ -465,11 +467,9 @@ async function mRunFunctions(openai, run, factory, avatar){ // add avatar ref
switch(true){
case phaseOfLife?.length:
action = `ask about another encounter during member's ${ phaseOfLife }`
- console.log('mRunFunctions()::story-summary::phaseOfLife', phaseOfLife)
break
case interests?.length:
action = `ask about a different interest from: ${ interests }`
- console.log('mRunFunctions()::story-summary::interests', interests)
break
default:
action = 'ask about another event in member\'s life'
@@ -478,6 +478,7 @@ async function mRunFunctions(openai, run, factory, avatar){ // add avatar ref
success = true
} // error cascades
confirmation.output = JSON.stringify({ action, success, })
+ console.log('mRunFunctions()::storySummary()::end', story.id)
return confirmation
case 'updatesummary':
case 'update_summary':
@@ -486,6 +487,11 @@ async function mRunFunctions(openai, run, factory, avatar){ // add avatar ref
const { summary: updatedSummary, } = toolArguments
// remove await once confirmed updates are connected
await factory.updateItem({ id: itemId, summary: updatedSummary, })
+ avatar.frontendInstruction = {
+ command: 'updateItemSummary',
+ itemId,
+ summary: updatedSummary,
+ }
action=`confirm success and present updated summary to member`
success = true
confirmation.output = JSON.stringify({ action, success, })
diff --git a/inc/json-schemas/intelligences/biographer-intelligence-1.4.json b/inc/json-schemas/intelligences/biographer-intelligence-1.4.json
index f41b107..9832af3 100644
--- a/inc/json-schemas/intelligences/biographer-intelligence-1.4.json
+++ b/inc/json-schemas/intelligences/biographer-intelligence-1.4.json
@@ -13,7 +13,7 @@
"purpose": "My goal is to specialize in creating, updating, and presenting accurate biographical content for MyLife member <-mFN-> based on our interactions.\n",
"references": [
{
- "default": "as yet unknown, please evince at start of process",
+ "default": "ERROR loading preferences, gather interests directly from member",
"description": "interests are h2 (##) in prefix so that they do not get lost in context window shortening",
"insert": "## interests",
"method": "append-hard",
@@ -46,5 +46,6 @@
"name": "instructions-personal-biographer-bot",
"purpose": "To be a biographer bot for requesting member",
"type": "personal-biographer",
+ "$comments": "20240919 updated error return without version update",
"version": 1.4
}
\ No newline at end of file
diff --git a/server.js b/server.js
index c768276..eaacc82 100644
--- a/server.js
+++ b/server.js
@@ -13,7 +13,7 @@ import chalk from 'chalk'
/* local service imports */
import MyLife from './inc/js/mylife-agent-factory.mjs'
/** variables **/
-const version = '0.0.21'
+const version = '0.0.22'
const app = new Koa()
const port = process.env.PORT ?? '3000'
const __filename = fileURLToPath(import.meta.url)
diff --git a/views/assets/css/bots.css b/views/assets/css/bots.css
index cb60b96..c03dd89 100644
--- a/views/assets/css/bots.css
+++ b/views/assets/css/bots.css
@@ -150,24 +150,20 @@
overflow-x: hidden;
overflow-y: auto; /* Enable vertical scrolling */
}
-/* Styles the scrollbar itself */
.bot-options::-webkit-scrollbar,
.checkbox-group::-webkit-scrollbar {
width: 6px; /* Adjust the width of the scrollbar */
}
-/* Styles the track of the scrollbar */
.bot-options::-webkit-scrollbar-track,
.checkbox-group::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.1); /* Color of the track */
border-radius: 10px; /* Optional: adds rounded corners to the track */
}
-/* Styles the handle (thumb) of the scrollbar */
.bot-options::-webkit-scrollbar-thumb,
.checkbox-group::-webkit-scrollbar-thumb {
background: rgba(232, 226, 183, .5); /* Color of the thumb */
border-radius: 10px; /* Optional: adds rounded corners to the thumb */
}
-/* Changes the color of the thumb when hovered over or clicked */
.bot-options::-webkit-scrollbar-thumb:hover,
.checkbox-group::-webkit-scrollbar-thumb:hover {
background: rgba(214, 198, 75, 0.5); /* Darker shade on hover */
@@ -238,6 +234,15 @@
margin-right: 0.8rem;
max-width: 50%;
}
+.mylife-widget.bots {
+ flex-direction: column;
+ justify-content: flex-start;
+ max-width: 100%;
+}
+.publicity-toggle-view-icon {
+ cursor: default;
+ font-size: 1.25rem;
+}
.ticker {
background: radial-gradient(at top left, darkgray, black); /* Radial gradient background */
border: thin solid rgba(255, 255, 255, 0.5); /* Thin white border with 50% opacity */
@@ -261,11 +266,6 @@
animation: none;
padding: 0;
}
-.mylife-widget.bots {
- flex-direction: column;
- justify-content: flex-start;
- max-width: 100%;
-}
/* bot-collections */
.collection {
background-color: royalblue;
@@ -440,7 +440,8 @@
justify-content: space-between;
width: 100%;
}
-.passphrase-reset {
+.passphrase-reset,
+.tutorial-button {
width: 100%;
}
/* publicity sliders */
diff --git a/views/assets/html/_bots.html b/views/assets/html/_bots.html
index 7c1c232..72c4882 100644
--- a/views/assets/html/_bots.html
+++ b/views/assets/html/_bots.html
@@ -28,8 +28,9 @@
-
+
+
+
+
+ Retire this:
+ CHAT
+ BOT-->
+
diff --git a/views/assets/js/bots.mjs b/views/assets/js/bots.mjs
index cfd8286..e31dbca 100644
--- a/views/assets/js/bots.mjs
+++ b/views/assets/js/bots.mjs
@@ -5,6 +5,7 @@ import {
addMessage,
addMessages,
decorateActiveBot,
+ experiences,
expunge,
fetchSummary,
getActiveItemId,
@@ -13,6 +14,7 @@ import {
setActiveItem,
setActiveItemTitle,
show,
+ startExperience,
submit,
toggleMemberInput,
toggleVisibility,
@@ -123,7 +125,8 @@ function getBot(type='personal-avatar', id){
* @returns {object} - The collection item object.
*/
function getItem(id){
- /* return collection item by id */
+ /* return collection elements by id */
+
}
/**
* Refresh designated collection from server. **note**: external calls denied option to identify collectionList parameter, ergo must always be of same type.
@@ -205,6 +208,19 @@ function togglePopup(id, bForceState=null){
throw new Error(`No popup found for id: ${ id }`)
toggleVisibility(popup, bForceState)
}
+/**
+ * Update collection item title.
+ * @todo - Only update local memory and data(sets), not full local refresh
+ * @param {object} item - The collection item fields to update, requires `{ itemId, }`
+ * @returns {void}
+ */
+function updateItem(item){
+ if(!item?.itemId)
+ throw new Error(`No item provided to update.`)
+ /* update collection elements indicated as object keys with this itemId */
+ // @stub - force-refresh memories; could be more savvy
+ refreshCollection('story')
+}
/**
* Proxy to update bot-bar, bot-containers, and bot-greeting, if desired. Requirements should come from including module, here `members.mjs`.
* @public
@@ -317,7 +333,7 @@ function mBotIcon(type){
*/
function mCreateCollectionItem(collectionItem){
/* collection item container */
- const { assistantType, filename, form, id, keywords, library_id, name, summary, title, type, } = collectionItem
+ const { assistantType, filename, form, id, keywords, name, summary, title, type, } = collectionItem
const item = document.createElement('div')
item.id = `collection-item_${ id }`
item.name = `collection-item-${ type }`
@@ -1698,6 +1714,7 @@ function mToggleSwitchPrivacy(event){
let { id, } = this
id = id.replace('-toggle', '') // remove toggle
const type = mGlobals.HTMLIdToType(id)
+ console.log('mToggleSwitchPrivacy', type)
const publicityCheckbox = document.getElementById(`${ type }-publicity-input`)
const viewIcon = document.getElementById(`${ type }-publicity-toggle-view-icon`)
const { checked=false, } = publicityCheckbox
@@ -1851,6 +1868,21 @@ function mUpdateBotContainerAddenda(botContainer){
}
})
}
+ /* publicity */
+ const publicityToggle = document.getElementById(`${ type }-publicity-toggle`)
+ if(publicityToggle){
+ publicityToggle.addEventListener('click', mToggleSwitchPrivacy)
+ const publicityToggleView = document.getElementById(`${ type }-publicity-toggle-view-icon`)
+ if(publicityToggleView){
+ const { checked=false, } = document.getElementById(`${ type }-publicity-input`) ?? {}
+ mToggleClass(publicityToggleView, !checked ? ['fa-eye-slash'] : ['fa-eye'], checked ? ['fa-eye'] : ['fa-eye-slash'])
+ publicityToggleView.addEventListener('click', event=>{
+ // @note - shouldn't be required, but container masters the switch
+ event.stopImmediatePropagation()
+ event.stopPropagation()
+ })
+ }
+ }
switch(type){
case 'diary':
case 'journaler':
@@ -1860,6 +1892,18 @@ function mUpdateBotContainerAddenda(botContainer){
/* attach avatar listeners */
/* set additional data attributes */
mTogglePassphrase(false) /* passphrase */
+ const tutorialButton = document.getElementById('personal-avatar-tutorial')
+ if(tutorialButton){
+ if(experiences().length){
+ show(tutorialButton)
+ tutorialButton.addEventListener('click', async event=>{
+ hide(tutorialButton)
+ const tutorialId = 'aae28fe4-30f9-4c29-9174-a0616569e762'
+ startExperience(tutorialId) // no await
+ }, { once: true })
+ } else
+ hide(tutorialButton)
+ }
break
default:
break
@@ -2123,5 +2167,6 @@ export {
refreshCollection,
setActiveBot,
togglePopup,
+ updateItem,
updatePageBots,
}
\ No newline at end of file
diff --git a/views/assets/js/experience.mjs b/views/assets/js/experience.mjs
index a686106..0b5ff3c 100644
--- a/views/assets/js/experience.mjs
+++ b/views/assets/js/experience.mjs
@@ -170,12 +170,9 @@ async function experiencePlay(memberInput){
* Retrieve full or scoped list of experiences from server.
* @todo - more robust logic underpinning selection of experiences, currently only system-controlled exist.
* @requires mExperiences
- * @param {string} scope - The scope of the experiences to retrieve.
- * @returns {Promise
} - The return is an array of Experience objects.
+ * @returns {Experience[]} - The return is an array of Experience objects.
*/
-async function experiences(scope){
- if(!mExperiences.length)
- mExperiences.push(...await mGetExperiences(scope))
+function experiences(scope){
return mExperiences
}
/**
@@ -196,8 +193,8 @@ function experienceSkip(sceneId){
/**
* Start experience onscreen, displaying welcome ande loading remaining data.
* @public
- * @param {Guid} experienceId - The Experience object.
- * @returns {Promise} - The return is its own success.
+ * @param {Guid} experienceId - The Experience id
+ * @returns {Promise}
*/
async function experienceStart(experienceId){
if(!globals.isGuid(experienceId))
diff --git a/views/assets/js/members.mjs b/views/assets/js/members.mjs
index 635fd71..2f6e517 100644
--- a/views/assets/js/members.mjs
+++ b/views/assets/js/members.mjs
@@ -2,7 +2,7 @@
import {
experienceEnd,
experiencePlay,
- experiences,
+ experiences as _experiences,
experienceSkip,
experienceStart,
submitInput,
@@ -13,6 +13,7 @@ import {
refreshCollection,
setActiveBot as _setActiveBot,
togglePopup,
+ updateItem,
} from './bots.mjs'
import Globals from './globals.mjs'
/* variables */
@@ -129,6 +130,9 @@ function decorateActiveBot(activeBot=activeBot()){
function escapeHtml(text) {
return mGlobals.escapeHtml(text)
}
+function experiences(){
+ return _experiences()
+}
/**
* Deletes an element from the DOM via Avatar functionality.
* @param {HTMLElement} element - The element to expunge.
@@ -354,6 +358,15 @@ function stageTransition(experienceId){
else
mStageTransitionMember()
}
+/**
+ * Start experience onscreen, displaying welcome ande loading remaining data. Passthrough to `experience.mjs::experienceStart()`.
+ * @public
+ * @param {Guid} experienceId - The Experience id
+ * @returns {void}
+ */
+async function startExperience(experienceId){
+ await experienceStart(experienceId)
+}
/**
* Toggle visibility functionality.
* @returns {void}
@@ -419,15 +432,21 @@ async function mAddMemberMessage(event){
})
/* server request */
const response = await submit(memberMessage)
- let { instruction, responses, success, } = response
+ let { instruction={}, responses=[], success=false, } = response
+ if(!success)
+ mAddMessage('I\'m sorry, I didn\'t understand that, something went wrong on the server. Please try again.')
/* process instructions */
+ const { itemId, summary, title, } = instruction
if(instruction?.command?.length){
switch(instruction.command){
+ case 'updateItemSummary':
+ if(itemId?.length && summary?.length)
+ updateItem({ itemId, summary, })
+ break
case 'updateItemTitle':
- const { title, itemId, } = instruction
if(title?.length && itemId?.length){
setActiveItemTitle(title, itemId)
- refreshCollection('story') // force-refresh memories; could be more savvy
+ updateItem({ itemId, title, })
}
break
case 'experience':
@@ -439,7 +458,8 @@ async function mAddMemberMessage(event){
}
/* process response */
responses
- .forEach(message => {
+ .forEach(message=>{
+ console.log('mAddMemberMessage::responses', message)
mAddMessage(message.message ?? message.content, {
bubbleClass: 'agent-bubble',
role: 'agent',
@@ -512,13 +532,6 @@ async function mAddMessage(message, options={}){
mScrollBottom()
}
}
-async function mFetchExperiences(){
- let response = await fetch('/members/experiences/')
- if(!response.ok)
- throw new Error(`HTTP error! Status: ${ response.status }`)
- response = await response.json()
- return response
-}
/**
* Fetches the summary via PA for a specified file.
* @private
@@ -808,6 +821,7 @@ export {
clearSystemChat,
decorateActiveBot,
escapeHtml,
+ experiences,
expunge,
fetchSummary,
getActiveItemId,
@@ -827,6 +841,7 @@ export {
showMemberChat,
showSidebar,
stageTransition,
+ startExperience,
submit,
toggleMemberInput,
toggleInputTextarea,
From 84c5f4cff8cccfa02cae3820167f5b653a495097 Mon Sep 17 00:00:00 2001
From: Erik Jespersen <42016062+Mookse@users.noreply.github.com>
Date: Tue, 1 Oct 2024 01:16:37 -0400
Subject: [PATCH 2/2] version 0023 updates => Production (#383)
---
inc/js/api-functions.mjs | 17 +-
inc/js/core.mjs | 22 ++-
inc/js/functions.mjs | 21 ++-
inc/js/globals.mjs | 19 ++-
inc/js/memory-functions.mjs | 4 +-
inc/js/mylife-agent-factory.mjs | 147 ++++++++++++++----
inc/js/mylife-avatar.mjs | 60 ++++++-
inc/js/mylife-data-service.js | 12 +-
inc/js/mylife-datamanager.mjs | 13 +-
inc/js/mylife-llm-services.mjs | 36 ++++-
inc/js/routes.mjs | 8 +-
inc/js/session.mjs | 24 +--
.../intelligences/diary-intelligence-1.0.json | 65 ++++++++
inc/yaml/mylife_diary-bot_openai.yaml | 69 +++++++-
server.js | 2 +-
views/assets/html/_bots.html | 4 +-
views/assets/js/experience.mjs | 2 -
views/layout.html | 2 +
18 files changed, 443 insertions(+), 84 deletions(-)
create mode 100644 inc/json-schemas/intelligences/diary-intelligence-1.0.json
diff --git a/inc/js/api-functions.mjs b/inc/js/api-functions.mjs
index 4ce8d94..64a5b6b 100644
--- a/inc/js/api-functions.mjs
+++ b/inc/js/api-functions.mjs
@@ -246,7 +246,20 @@ async function memory(ctx){
}
}
/**
- * Validates api token
+ * Given an itemId, obscures aspects of contents of the data record.
+ * @param {Koa} ctx - Koa Context object
+ * @returns {Promise
+
+
+ -->
diff --git a/views/assets/js/experience.mjs b/views/assets/js/experience.mjs
index 0b5ff3c..0c80be7 100644
--- a/views/assets/js/experience.mjs
+++ b/views/assets/js/experience.mjs
@@ -90,7 +90,6 @@ async function experienceEnd(){
mExperience = null
/* remove listeners */
closeButton.removeEventListener('click', experienceEnd)
- skip.removeEventListener('click', experienceSkip)
startButton.removeEventListener('click', experiencePlay)
/* end experience onscreen */
sceneStage.innerHTML = '' // clear full-screen character-lanes
@@ -843,7 +842,6 @@ function mImageSource(icon, type){
function mInitListeners(skippable=true){
if(skippable)
closeButton.addEventListener('click', experienceEnd)
- skip.addEventListener('click', experienceSkip)
}
/**
* Whether the character is the personal-avatar.
diff --git a/views/layout.html b/views/layout.html
index e7e46d9..6fbae06 100644
--- a/views/layout.html
+++ b/views/layout.html
@@ -27,9 +27,11 @@
+
<% include assets/html/_experience %>