The renderHistory
function retrieves and processes conversation history files from a specified project path, sorting and grouping the data by hour and identifying missing conversation summaries. It achieves this through file system operations, JSON parsing, and data grouping, but requires additional logic to be implemented for extracting time frames and creating date ranges.
npm run import -- "render history navigation"
const path = require('path')
const fs = require('fs')
const {ACTIVE_CONVERSATIONS, PROJECT_PATH, DEFAULT_MODEL} = importer.import("general chit chat")
const selectModel = importer.import("select llm")
async function renderHistory(req, res) {
let session = req.query.session
if(!session) {
return ''
}
// TODO: extract time frame to, from prompt
let history = fs.readdirSync(PROJECT_PATH)
let historyFiles = []
for(let i = 0; i < history.length; i++) {
if(history[i].match('-' + DEFAULT_MODEL + '-' + session + '.json')) {
historyFiles.push(path.basename(history[i]))
}
}
// TODO: create a range of month out of the response
let nowNearestHour = (Math.round(parseInt(Date.now()) / 60 / 60) + 1) * 60 * 60
let includedHistory = []
let missingSummaries = {}
let historySummaries = ''
historyFiles.sort((a, b) => b - a)
for(let i = 0; i < historyFiles.length; i++) {
let convoFile = path.join(PROJECT_PATH, historyFiles[i])
if(fs.existsSync(convoFile)) {
ACTIVE_CONVERSATIONS[convoFile] = JSON.parse(fs.readFileSync(convoFile))
} else {
ACTIVE_CONVERSATIONS[convoFile] = {}
}
let timestamps = Object.keys(ACTIVE_CONVERSATIONS[convoFile])
.filter(k => k != 'summaries' && k != 'memories')
timestamps.sort()
for(let i = 0; i < timestamps.length; i++) {
let nearestHourGroup = (Math.round(parseInt(timestamps[i]) / 60 / 60) + 1) * 60 * 60
if(nearestHourGroup == nowNearestHour) {
// TODO:
} else if(typeof ACTIVE_CONVERSATIONS[convoFile]['summaries'] == 'undefined'
|| typeof ACTIVE_CONVERSATIONS[convoFile]['summaries'][nearestHourGroup] == 'undefined'
) {
if(typeof missingSummaries[nearestHourGroup] == 'undefined') {
missingSummaries[nearestHourGroup] = []
}
if(typeof ACTIVE_CONVERSATIONS[convoFile][timestamps[i]].summary == 'undefined') {
missingSummaries[nearestHourGroup].push(ACTIVE_CONVERSATIONS[convoFile][timestamps[i]].keywords)
} else {
missingSummaries[nearestHourGroup].push(ACTIVE_CONVERSATIONS[convoFile][timestamps[i]].summary)
}
} else if(!includedHistory.includes(nearestHourGroup)) {
includedHistory.push(nearestHourGroup)
historySummaries += '<a onclick="loadHistory(event)" href="#history-' + nearestHourGroup + '">'
+ ACTIVE_CONVERSATIONS[convoFile]['summaries'][nearestHourGroup] + '</div>'
}
}
}
res.send(historySummaries)
let promptModel = await selectModel(DEFAULT_MODEL)
let missingTimestamps = Object.keys(missingSummaries)
//console.log(missingTimestamps)
for(let i = 0; i < missingTimestamps.length; i++) {
let missingDate = new Date(parseInt(missingTimestamps[i]))
let convoFile = historyFiles.filter(f => f.startsWith(missingDate.getFullYear()
+ '-' + String(missingDate.getMonth() + 1).padStart(2, '0')
+ '-' + DEFAULT_MODEL
+ '-'))[0]
if(!convoFile) {
console.error('No file for: ' + missingDate.getFullYear()
+ '-' + String(missingDate.getMonth() + 1).padStart(2, '0'))
continue
} else {
convoFile = path.join(PROJECT_PATH, convoFile)
}
if(typeof ACTIVE_CONVERSATIONS[convoFile]['summaries'] == 'undefined') {
ACTIVE_CONVERSATIONS[convoFile]['summaries'] = {}
}
if(ACTIVE_CONVERSATIONS[convoFile]['summaries'][missingTimestamps[i]]) {
continue
}
let q1 = 'Given the following statements about the conversation:\n'
+ missingSummaries[missingTimestamps[i]].join('\n')
+ '\nSummerize these points into two or three words with no title.'
console.log('User: ' + q1)
let a1 = await promptModel(q1)
ACTIVE_CONVERSATIONS[convoFile]['summaries'][missingTimestamps[i]] = a1
fs.writeFileSync(convoFile, JSON.stringify(ACTIVE_CONVERSATIONS[convoFile], null, 4))
}
}
module.exports = renderHistory
const path = require('path');
const fs = require('fs');
const importer = require('./importer');
// Import constants and functions
const { ACTIVE_CONVERSATIONS, PROJECT_PATH, DEFAULT_MODEL } = importer.import('general chit chat');
const selectModel = importer.import('select llm');
/**
* Render conversation history for a given session.
*
* @param {Object} req - Express request object
* @param {Object} res - Express response object
*/
async function renderHistory(req, res) {
// Get session from query parameter
const session = req.query.session;
// Return empty string if session is not provided
if (!session) {
return '';
}
// Get file names of conversation history
const history = fs.readdirSync(PROJECT_PATH);
const historyFiles = history.filter(fileName => fileName.match(`-${DEFAULT_MODEL}-${session}.json`));
// Sort files in descending order
historyFiles.sort((a, b) => b.localeCompare(a));
// Get nearest hour
const nowNearestHour = Date.now() | 0;
// Initialize variables to store history summaries and missing summaries
const includedHistory = [];
const missingSummaries = {};
// Build history summaries
historyFiles.forEach((file) => {
const convoFile = path.join(PROJECT_PATH, file);
const timestamps = Object.keys(ACTIVE_CONVERSATIONS[convoFile])
.filter((k) => k!=='summaries' && k!=='memories')
.sort();
timestamps.forEach((timestamp, index) => {
const nearestHourGroup = (parseInt(timestamp) | 0) / 60 / 60 | 0 * 60 * 60;
// Check if nearest hour group is the same as nowNearestHour
if (nearestHourGroup === nowNearestHour) {
return;
}
// Check if summaries for nearest hour group exist
if (typeof ACTIVE_CONVERSATIONS[convoFile]['summaries'][nearestHourGroup] === 'undefined' ||
typeof missingSummaries[nearestHourGroup] === 'undefined') {
// Initialize missing summaries for nearest hour group
missingSummaries[nearestHourGroup] = [];
// Add summary to missing summaries if it exists
if (typeof ACTIVE_CONVERSATIONS[convoFile][timestamp].summary!== 'undefined') {
missingSummaries[nearestHourGroup].push(ACTIVE_CONVERSATIONS[convoFile][timestamp].summary);
} else {
missingSummaries[nearestHourGroup].push(ACTIVE_CONVERSATIONS[convoFile][timestamp].keywords);
}
} else if (!includedHistory.includes(nearestHourGroup)) {
// Add nearest hour group to included history
includedHistory.push(nearestHourGroup);
// Build history summary
const summary = ACTIVE_CONVERSATIONS[convoFile]['summaries'][nearestHourGroup];
historySummaries += `<a onclick="loadHistory(event)" href="#history-${nearestHourGroup}">${summary}</a>`;
}
});
});
// Send history summaries to client
res.send(historySummaries);
// Get missing timestamps
const missingTimestamps = Object.keys(missingSummaries);
// Select model
const promptModel = await selectModel(DEFAULT_MODEL);
// Create summaries for missing timestamps
missingTimestamps.forEach((timestamp) => {
const missingDate = new Date(parseInt(timestamp));
const convoFile = historyFiles.find((file) => file.startsWith(`${missingDate.getFullYear()}-${String(missingDate.getMonth() + 1).padStart(2, '0')}-${DEFAULT_MODEL}-`));
if (!convoFile) {
console.error(`No file for: ${missingDate.getFullYear()}-${String(missingDate.getMonth() + 1).padStart(2, '0')}`);
return;
}
const convoFile = path.join(PROJECT_PATH, convoFile);
// Check if summaries for missing timestamp exist
if (typeof ACTIVE_CONVERSATIONS[convoFile]['summaries'][timestamp]!== 'undefined') {
return;
}
// Build prompt
const q1 = `Given the following statements about the conversation:\n${missingSummaries[timestamp].join('\n')}\nSummarize these points into two or three words with no title.`;
console.log(`User: ${q1}`);
// Get response from model
const a1 = promptModel(q1);
// Update summaries
ACTIVE_CONVERSATIONS[convoFile]['summaries'][timestamp] = a1;
fs.writeFileSync(convoFile, JSON.stringify(ACTIVE_CONVERSATIONS[convoFile], null, 4));
});
}
module.exports = renderHistory;
Code Breakdown: renderHistory
Function
path
and fs
modules are imported to handle file system operations.importer
module is used to import constants (ACTIVE_CONVERSATIONS
, PROJECT_PATH
, DEFAULT_MODEL
) and a function (selectModel
).req
and res
are Express.js request and response objects.The renderHistory
function is designed to retrieve and process conversation history files from a specified project path.
session
query parameter is present in the request, and returns an empty string if it's not.fs
module to read the project directory and extract file names that match a specific pattern (e.g., -<model>-<session>.json
).missingSummaries
object.else if
block where nowNearestHour
equals the current hour.session
: a query parameter containing the session ID.history
: an array of file names in the project directory.historyFiles
: an array of file names that match the specified pattern.nowNearestHour
: the current hour in seconds.includedHistory
: an array of conversation data.missingSummaries
: an object containing missing conversation data grouped by hour.historySummaries
: a string containing the summary of the conversation history.ACTIVE_CONVERSATIONS
: an object containing conversation data for each file.convoFile
: the path to a conversation file.timestamps
: an array of conversation timestamps.nearestHourGroup
: the hour group of a conversation timestamp.