cc-haha/src/utils/cachePaths.ts
程序员阿江(Relakkes) e8c045876e Stabilize portable mode PR before merge
The contributor PR adds useful Windows terminal and portable mode support, but it also reintroduced an older General settings zoom block and left the new native settings paths without enough regression coverage. This commit keeps the feature direction intact while removing the duplicate UI, making invalid bash paths fail at save time, and covering the portable cache and app-mode paths with focused tests.

Constraint: This commit lands directly on the contributor PR branch to avoid a long review-comment loop.
Rejected: Ask the contributor to rework the PR from scratch | the remaining issues are narrow and maintainable by us.
Confidence: high
Scope-risk: moderate
Directive: Keep future portable-mode changes covered at the native boundary and the desktop store boundary.
Tested: cd desktop && bun run test src/pages/TerminalSettings.test.tsx src/__tests__/generalSettings.test.tsx src/stores/settingsStore.test.ts
Tested: bun test src/utils/__tests__/cachePaths.test.ts
Tested: cd desktop/src-tauri && cargo test
Tested: cd desktop && bun run lint
Tested: cd desktop/src-tauri && cargo check
Tested: bun run check:server
Tested: bun run check:desktop
Not-tested: Manual Windows packaged-app portable-mode smoke; to be covered before a future release.
2026-05-17 00:50:59 +08:00

45 lines
1.8 KiB
TypeScript

import envPaths from 'env-paths'
import { join } from 'path'
import { getFsImplementation } from './fsOperations.js'
import { djb2Hash } from './hash.js'
// When CLAUDE_CONFIG_DIR is set (portable mode), place cache under it
// so the install is fully self-contained. Otherwise fall back to the
// system default (%LOCALAPPDATA%\claude-cli-nodejs\Cache on Windows).
function getCacheRoot() {
const claudeConfigDir = (process.env as Record<string, string | undefined>).CLAUDE_CONFIG_DIR
return claudeConfigDir ? join(claudeConfigDir, 'Cache') : envPaths('claude-cli').cache
}
// Local sanitizePath using djb2Hash — NOT the shared version from
// sessionStoragePortable.ts which uses Bun.hash (wyhash) when available.
// Cache directory names must remain stable across upgrades so existing cache
// data (error logs, MCP logs) is not orphaned.
const MAX_SANITIZED_LENGTH = 200
function sanitizePath(name: string): string {
const sanitized = name.replace(/[^a-zA-Z0-9]/g, '-')
if (sanitized.length <= MAX_SANITIZED_LENGTH) {
return sanitized
}
return `${sanitized.slice(0, MAX_SANITIZED_LENGTH)}-${Math.abs(djb2Hash(name)).toString(36)}`
}
function getProjectDir(cwd: string): string {
return sanitizePath(cwd)
}
export const CACHE_PATHS = {
baseLogs: () => join(getCacheRoot(), getProjectDir(getFsImplementation().cwd())),
errors: () =>
join(getCacheRoot(), getProjectDir(getFsImplementation().cwd()), 'errors'),
messages: () =>
join(getCacheRoot(), getProjectDir(getFsImplementation().cwd()), 'messages'),
mcpLogs: (serverName: string) =>
join(
getCacheRoot(),
getProjectDir(getFsImplementation().cwd()),
// Sanitize server name for Windows compatibility (colons are reserved for drive letters)
`mcp-logs-${sanitizePath(serverName)}`,
),
}