Fix project isolation: Make loadChatHistory respect active project sessions

- Modified loadChatHistory() to check for active project before fetching all sessions
- When active project exists, use project.sessions instead of fetching from API
- Added detailed console logging to debug session filtering
- This prevents ALL sessions from appearing in every project's sidebar

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
uroma
2026-01-22 14:43:05 +00:00
Unverified
parent b82837aa5f
commit 55aafbae9a
6463 changed files with 1115462 additions and 4486 deletions

92
cache-bust-middleware.js Normal file
View File

@@ -0,0 +1,92 @@
/**
* Cache-Busting Middleware for Obsidian Web Interface
*
* This module provides dynamic asset versioning to force browser cache invalidation
* on every server restart by intercepting HTML responses and injecting cache-busting
* query parameters into all JavaScript file references.
*
* Architecture Pattern: Cache-Busting via Query Parameters
* - Build timestamp is generated at server startup
* - All JS files get ?v=TIMESTAMP appended
* - Browser treats each timestamp as a unique resource
* - Cannot be cached across deployments
*/
const fs = require('fs');
const path = require('path');
/**
* Generate cache-busted HTML by adding timestamp to all <script src="..."> tags
*
* @param {string} htmlContent - Original HTML content
* @param {string} version - Version string to append (e.g., "v=1769008200000")
* @returns {string} HTML with cache-busted script tags
*/
function injectCacheBusting(htmlContent, version) {
// Match all <script src="..."> tags and append version parameter
// This matches both single and double quoted attributes
return htmlContent.replace(
/<script\s+src=(["'])(\/claude\/[^"']*\.(?:js|css))\1\s*>/g,
(match, quote, src) => {
// Check if the URL already has query parameters
const separator = src.includes('?') ? '&' : '?';
const cacheBustedSrc = `${src}${separator}${version}`;
return `<script src=${quote}${cacheBustedSrc}${quote}>`;
}
);
}
/**
* Middleware factory that creates a cache-busting middleware for HTML responses
* Uses res.on('finish') to intercept the response
*
* @param {string} version - Version string (e.g., "v=1769008200000")
* @returns {Function} Express middleware function
*/
function createCacheBustingMiddleware(version) {
return function cacheBustingMiddleware(req, res, next) {
// Override res.sendFile to transform HTML
const originalSendFile = res.sendFile.bind(res);
res.sendFile = function(filePath, options, callback) {
console.log(`[CACHE-BUSTING] sendFile called: ${filePath}`);
// Only process HTML files
if (!filePath || !filePath.match(/\.(html|htm)$/i)) {
console.log(`[CACHE-BUSTING] Skipping non-HTML file: ${filePath}`);
return originalSendFile(filePath, options, callback);
}
console.log(`[CACHE-BUSTING] Processing HTML file: ${path.basename(filePath)}`);
// Read file synchronously and transform
try {
const html = fs.readFileSync(filePath, 'utf8');
const transformed = injectCacheBusting(html, version);
// Set headers to prevent caching
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0');
res.setHeader('Pragma', 'no-cache');
res.setHeader('Expires', '0');
// Send transformed HTML
res.send(transformed);
if (callback) setImmediate(callback);
console.log(`[CACHE-BUSTING] ✓ Transformed: ${path.basename(filePath)}`);
} catch (err) {
console.error(`[CACHE-BUSTING] ✗ Error: ${err.message}`);
return originalSendFile(filePath, options, callback);
}
};
next();
};
}
module.exports = {
injectCacheBusting,
createCacheBustingMiddleware
};