From 350b1bb246e72ada99e739610cff77efcce3600d Mon Sep 17 00:00:00 2001 From: Erik Jespersen <42016062+Mookse@users.noreply.github.com> Date: Tue, 9 Jul 2024 07:59:31 -0400 Subject: [PATCH] 248 version 0013 updates (#258) * 231 version 0010 updates (#239) (#240) * 20240604 @Mookse - teams() route - teams(teamId) returns a fully formed team from server with new bots (when instructions provided) * 20240604 @Mookse - fix bot-bar `setActiveBot` - cosmetic * 20240604 @Mookse - fix duplicate team members return * 20240604 @Mookse - botBar reordered * 20240605 @Mookse - teams must be active * 20240605 @Mookse - default mods * 20240605 @Mookse - create (non-custom) bot frontend - diary updates * 20240605 @Mookse - imagining `share memory` * 20240606 @Mookse - story updates * 20240606 @Mookse - minor cosmetics * 20240606 @Mookse - fetchShadows() - ignite shadow: member-version (wip) * 20240607 @Mookse - `shadow` initial endpoint * 20240607 @Mookse - add processingBotId to payload (so that frontend can determine if it should setActive) * 20240607 @Mookse - front-end receives message about updating from agent shadow * 20240607 @Mookse - shadow cosmetics * 20240607 @Mookse - biographer openai function definitions * 20240607 @Mookse - now _that's_ an error * 20240607 @Mookse - updateSummary() **note**: wip as thread got stopped * 20240608 @Mookse - updates summary * 20240608 @Mookse - remove dataset after shadow triggered - add `proxy` endpoint to shadow ideas * 20240608 @Mookse - `globals.getGPTJavascriptFunction`: `getSummary`, `updateSummary` - `updateBotInstructions` route - on setActiveBot checks versions and updates as needed * 20240609 @Mookse - cosmetic * 20240609 @Mookse stable wip kicking off memory is correct, need tuning of instructions or alternate scene-stepwise motion, no problem small error left in frontend for more testing but time to save * 20240618 @Mookse - cosmetic: file under "the right evocation can make all the difference" * 20240618 @Mookse - cosmetic in dribs and drabs * 20240618 @Mookse - frontend 'next' fix * version 0011 updates (#244) * 231 version 0010 updates (#239) * 20240604 @Mookse - teams() route - teams(teamId) returns a fully formed team from server with new bots (when instructions provided) * 20240604 @Mookse - fix bot-bar `setActiveBot` - cosmetic * 20240604 @Mookse - fix duplicate team members return * 20240604 @Mookse - botBar reordered * 20240605 @Mookse - teams must be active * 20240605 @Mookse - default mods * 20240605 @Mookse - create (non-custom) bot frontend - diary updates * 20240605 @Mookse - imagining `share memory` * 20240606 @Mookse - story updates * 20240606 @Mookse - minor cosmetics * 20240606 @Mookse - fetchShadows() - ignite shadow: member-version (wip) * 20240607 @Mookse - `shadow` initial endpoint * 20240607 @Mookse - add processingBotId to payload (so that frontend can determine if it should setActive) * 20240607 @Mookse - front-end receives message about updating from agent shadow * 20240607 @Mookse - shadow cosmetics * 20240607 @Mookse - biographer openai function definitions * 20240607 @Mookse - now _that's_ an error * 20240607 @Mookse - updateSummary() **note**: wip as thread got stopped * 20240608 @Mookse - updates summary * 20240608 @Mookse - remove dataset after shadow triggered - add `proxy` endpoint to shadow ideas * 20240608 @Mookse - `globals.getGPTJavascriptFunction`: `getSummary`, `updateSummary` - `updateBotInstructions` route - on setActiveBot checks versions and updates as needed * 20240609 @Mookse - cosmetic * 20240609 @Mookse stable wip kicking off memory is correct, need tuning of instructions or alternate scene-stepwise motion, no problem small error left in frontend for more testing but time to save * 20240618 @Mookse - cosmetic: file under "the right evocation can make all the difference" * 20240618 @Mookse - cosmetic in dribs and drabs * 20240618 @Mookse - frontend 'next' fix * 20240621 @Mookse - redirect logged in members to `/members` * 20240626 @Mookse - registration -> createAccount with Q * 20240626 @Mookse - hostedMembers fix * 20240626 @Mookse - avatar document name fix * 20240626 @Mookse - instruction change * 20240626 @Mookse - page-loader * 20240626 @Mookse - special pages fix --------- Signed-off-by: Erik Jespersen <42016062+Mookse@users.noreply.github.com> * Version 0.0.11 (#243) * 231 version 0010 updates (#239) * 20240604 @Mookse - teams() route - teams(teamId) returns a fully formed team from server with new bots (when instructions provided) * 20240604 @Mookse - fix bot-bar `setActiveBot` - cosmetic * 20240604 @Mookse - fix duplicate team members return * 20240604 @Mookse - botBar reordered * 20240605 @Mookse - teams must be active * 20240605 @Mookse - default mods * 20240605 @Mookse - create (non-custom) bot frontend - diary updates * 20240605 @Mookse - imagining `share memory` * 20240606 @Mookse - story updates * 20240606 @Mookse - minor cosmetics * 20240606 @Mookse - fetchShadows() - ignite shadow: member-version (wip) * 20240607 @Mookse - `shadow` initial endpoint * 20240607 @Mookse - add processingBotId to payload (so that frontend can determine if it should setActive) * 20240607 @Mookse - front-end receives message about updating from agent shadow * 20240607 @Mookse - shadow cosmetics * 20240607 @Mookse - biographer openai function definitions * 20240607 @Mookse - now _that's_ an error * 20240607 @Mookse - updateSummary() **note**: wip as thread got stopped * 20240608 @Mookse - updates summary * 20240608 @Mookse - remove dataset after shadow triggered - add `proxy` endpoint to shadow ideas * 20240608 @Mookse - `globals.getGPTJavascriptFunction`: `getSummary`, `updateSummary` - `updateBotInstructions` route - on setActiveBot checks versions and updates as needed * 20240609 @Mookse - cosmetic * 20240609 @Mookse stable wip kicking off memory is correct, need tuning of instructions or alternate scene-stepwise motion, no problem small error left in frontend for more testing but time to save * 20240618 @Mookse - cosmetic: file under "the right evocation can make all the difference" * 20240618 @Mookse - cosmetic in dribs and drabs * 20240618 @Mookse - frontend 'next' fix * 238 version 0011 updates (#242) * 231 version 0010 updates (#239) (#240) * 20240604 @Mookse - teams() route - teams(teamId) returns a fully formed team from server with new bots (when instructions provided) * 20240604 @Mookse - fix bot-bar `setActiveBot` - cosmetic * 20240604 @Mookse - fix duplicate team members return * 20240604 @Mookse - botBar reordered * 20240605 @Mookse - teams must be active * 20240605 @Mookse - default mods * 20240605 @Mookse - create (non-custom) bot frontend - diary updates * 20240605 @Mookse - imagining `share memory` * 20240606 @Mookse - story updates * 20240606 @Mookse - minor cosmetics * 20240606 @Mookse - fetchShadows() - ignite shadow: member-version (wip) * 20240607 @Mookse - `shadow` initial endpoint * 20240607 @Mookse - add processingBotId to payload (so that frontend can determine if it should setActive) * 20240607 @Mookse - front-end receives message about updating from agent shadow * 20240607 @Mookse - shadow cosmetics * 20240607 @Mookse - biographer openai function definitions * 20240607 @Mookse - now _that's_ an error * 20240607 @Mookse - updateSummary() **note**: wip as thread got stopped * 20240608 @Mookse - updates summary * 20240608 @Mookse - remove dataset after shadow triggered - add `proxy` endpoint to shadow ideas * 20240608 @Mookse - `globals.getGPTJavascriptFunction`: `getSummary`, `updateSummary` - `updateBotInstructions` route - on setActiveBot checks versions and updates as needed * 20240609 @Mookse - cosmetic * 20240609 @Mookse stable wip kicking off memory is correct, need tuning of instructions or alternate scene-stepwise motion, no problem small error left in frontend for more testing but time to save * 20240618 @Mookse - cosmetic: file under "the right evocation can make all the difference" * 20240618 @Mookse - cosmetic in dribs and drabs * 20240618 @Mookse - frontend 'next' fix * 20240621 @Mookse - redirect logged in members to `/members` * 20240626 @Mookse - registration -> createAccount with Q * 20240626 @Mookse - hostedMembers fix * 20240626 @Mookse - avatar document name fix * 20240626 @Mookse - instruction change * 20240626 @Mookse - page-loader * 20240626 @Mookse - special pages fix --------- Signed-off-by: Erik Jespersen <42016062+Mookse@users.noreply.github.com> --------- Signed-off-by: Erik Jespersen <42016062+Mookse@users.noreply.github.com> * 20240705 @Mookse - hotfix for experiences * 20240705 @Mookse - add server status to readme.md * 20240705 @Mookse - Add Favicon on site for easier identification in Browser #252 * 20240705 @Mookse - remove sources from message --------- Signed-off-by: Erik Jespersen <42016062+Mookse@users.noreply.github.com> --- README.md | 2 ++ inc/js/mylife-avatar.mjs | 15 ++++++++------- views/assets/png/favicon.png | Bin 0 -> 11557 bytes views/layout.html | 1 + 4 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 views/assets/png/favicon.png diff --git a/README.md b/README.md index 93deeb6..92551a5 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ ## Overview +[![Build and deploy Node.js app to Azure Web App - maht](https://github.com/MyLife-Services/mylife-maht/actions/workflows/azure-deploy-prod_maht.yml/badge.svg?branch=azure-deploy-prod)](https://github.com/MyLife-Services/mylife-maht/actions/workflows/azure-deploy-prod_maht.yml) + ### MyLife: Preserving Member Stories for Posterity MyLife is a groundbreaking initiative aimed at capturing and preserving the essence of human experiences for future generations. We believe in the power of personal stories, memories, and media to shape our understanding of the human condition. Our platform provides a unique, enduring, and internet-based solution for individuals to record and showcase their life stories. diff --git a/inc/js/mylife-avatar.mjs b/inc/js/mylife-avatar.mjs index 21570c8..96d1a16 100644 --- a/inc/js/mylife-avatar.mjs +++ b/inc/js/mylife-avatar.mjs @@ -321,10 +321,7 @@ class Avatar extends EventEmitter { /** * Returns all conversations of a specific-type stored in memory. * @param {string} type - Type of conversation: chat, experience, dialog, inter-system, etc.; defaults to `chat`. - * @returns {Conversation[]} - The array of conversation objects. - */ - getConversations(type='chat'){ - return this.#conversations + * @retu .replace(/\[.*?†.*?\]/gs, '') // This line removes OpenAI LLM "source" referencesLM "source" references.#conversations .filter(_=>_?.type===type) } /** @@ -1995,18 +1992,22 @@ function mPruneMessage(bot, message, type='chat', processStartTime=Date.now()){ /* parse message */ const { bot_id: activeBotAIId, id: activeBotId, } = bot let agent='server', + content='', purpose=type, response_time=Date.now()-processStartTime const { content: messageContent, thread_id, } = message - const content = Array.isArray(messageContent) + const rSource = /【.*?\】/gs + const rLines = /\n{2,}/g + content = Array.isArray(messageContent) ? messageContent.reduce((acc, item) => { - if (item?.type==='text' && item?.text?.value) { + if (item?.type==='text' && item?.text?.value){ acc += item.text.value + '\n' } return acc }, '') - .replace(/\n{2,}/g, '\n') : messageContent + content = content.replace(rLines, '\n') + .replace(rSource, '') // This line removes OpenAI LLM "source" references message = new Marked().parse(content) const messageResponse = { activeBotId, diff --git a/views/assets/png/favicon.png b/views/assets/png/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..15e3b1037941c6ae35f5f62f55b41ab9c478fd5d GIT binary patch literal 11557 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 +