mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-20 00:14:58 +00:00
Issue #1161. Sweeps 127 files to import from src/config/config-loader-facade.ts instead of unified-config-loader or utils/config-manager directly. WRITE callers (32 files): replaced raw saveUnifiedConfig / mutateUnifiedConfig / updateUnifiedConfig calls with the facade's cache-coherent wrappers saveConfig / mutateConfig / updateConfig. This fixes a latent stale-cache window where direct writes through the underlying loader bypassed the facade's memoization. READ callers (95 files): mechanical import-path migration only — function names unchanged because the facade re-exports them. No behavior change. Also updated: - tests/unit/utils/browser/browser-setup.test.ts (DI interface rename) - src/management/checks/image-analysis-check.ts (dynamic import rename) - src/web-server/health-service.ts (dynamic require rename) - src/ccs.ts (path prefix fix from sweep script) After sweep: zero raw write callers remain outside src/config/. Direct imports of config-manager remain only for symbols not in the facade (getConfigPath, getCcsDirSource, etc). Behavior unchanged; full suite passes 1824/1824. Out of scope: switching loadOrCreateUnifiedConfig() callers to getCachedConfig() — needs per-callsite cache-safety analysis. Tracked as follow-up. Refs #1161
165 lines
4.7 KiB
TypeScript
165 lines
4.7 KiB
TypeScript
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
import { getDefaultClaudeConfigDir } from '../utils/claude-config-path';
|
|
|
|
import InstanceManager from '../management/instance-manager';
|
|
import ProfileDetector from './profile-detector';
|
|
import { resolveConfiguredContinuitySourceAccount } from './profile-continuity-inheritance';
|
|
import type { ProfileType } from '../types/profile';
|
|
import { getCcsDir } from '../config/config-loader-facade';
|
|
|
|
export type ResumeLaneKind =
|
|
| 'native'
|
|
| 'account-default'
|
|
| 'account-inherited'
|
|
| 'profile-default'
|
|
| 'ambient';
|
|
|
|
export interface ResumeLaneSummary {
|
|
kind: ResumeLaneKind;
|
|
label: string;
|
|
configDir: string;
|
|
accountName?: string;
|
|
profileName?: string;
|
|
projectCount: number;
|
|
}
|
|
|
|
export interface ResumeFlagIntent {
|
|
implicit: boolean;
|
|
explicitSessionId?: string;
|
|
}
|
|
|
|
function countTopLevelProjectDirs(projectsDir: string): number {
|
|
try {
|
|
return fs
|
|
.readdirSync(projectsDir, { withFileTypes: true })
|
|
.filter((entry) => entry.isDirectory()).length;
|
|
} catch {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
function resolveNativeLaneSummary(
|
|
kind: ResumeLaneKind = 'native',
|
|
profileName?: string
|
|
): ResumeLaneSummary {
|
|
const configDir = getDefaultClaudeConfigDir();
|
|
const label =
|
|
kind === 'profile-default' && profileName
|
|
? `profile "${profileName}" via native Claude lane`
|
|
: 'native Claude lane';
|
|
|
|
return {
|
|
kind,
|
|
label,
|
|
configDir,
|
|
profileName,
|
|
projectCount: countTopLevelProjectDirs(path.join(configDir, 'projects')),
|
|
};
|
|
}
|
|
|
|
function resolveAccountLaneSummary(
|
|
kind: Extract<ResumeLaneKind, 'account-default' | 'account-inherited'>,
|
|
accountName: string
|
|
): ResumeLaneSummary {
|
|
const instanceMgr = new InstanceManager();
|
|
const configDir = instanceMgr.getInstancePath(accountName);
|
|
|
|
return {
|
|
kind,
|
|
label:
|
|
kind === 'account-inherited'
|
|
? `plain ccs inherits from account "${accountName}"`
|
|
: `plain ccs defaults to account "${accountName}"`,
|
|
configDir,
|
|
accountName,
|
|
projectCount: countTopLevelProjectDirs(path.join(configDir, 'projects')),
|
|
};
|
|
}
|
|
|
|
export async function resolveConfiguredPlainCcsResumeLane(): Promise<ResumeLaneSummary> {
|
|
const detector = new ProfileDetector();
|
|
const defaultProfile = detector.resolveDefaultProfileResult();
|
|
|
|
if (defaultProfile.type === 'account') {
|
|
return resolveAccountLaneSummary('account-default', defaultProfile.name);
|
|
}
|
|
|
|
const inheritedAccount = resolveConfiguredContinuitySourceAccount(
|
|
defaultProfile.name,
|
|
defaultProfile.type
|
|
);
|
|
if (inheritedAccount) {
|
|
return resolveAccountLaneSummary('account-inherited', inheritedAccount);
|
|
}
|
|
|
|
if (defaultProfile.type !== 'default') {
|
|
return resolveNativeLaneSummary('profile-default', defaultProfile.name);
|
|
}
|
|
|
|
return resolveNativeLaneSummary();
|
|
}
|
|
|
|
export async function resolveRuntimePlainCcsResumeLane(): Promise<ResumeLaneSummary> {
|
|
if (process.env.CLAUDE_CONFIG_DIR) {
|
|
const configDir = path.resolve(process.env.CLAUDE_CONFIG_DIR);
|
|
return {
|
|
kind: 'ambient',
|
|
label: 'current shell CLAUDE_CONFIG_DIR',
|
|
configDir,
|
|
projectCount: countTopLevelProjectDirs(path.join(configDir, 'projects')),
|
|
};
|
|
}
|
|
|
|
return resolveConfiguredPlainCcsResumeLane();
|
|
}
|
|
|
|
export function parseResumeFlagIntent(args: string[]): ResumeFlagIntent | null {
|
|
for (let index = 0; index < args.length; index += 1) {
|
|
const arg = args[index];
|
|
if (arg === '-r') {
|
|
return { implicit: true };
|
|
}
|
|
|
|
if (arg === '--resume') {
|
|
const next = args[index + 1];
|
|
if (next && !next.startsWith('-')) {
|
|
return { implicit: false, explicitSessionId: next };
|
|
}
|
|
return { implicit: true };
|
|
}
|
|
|
|
if (arg.startsWith('--resume=')) {
|
|
const sessionId = arg.slice('--resume='.length).trim();
|
|
return sessionId ? { implicit: false, explicitSessionId: sessionId } : { implicit: true };
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
export function getAuthBackupRoot(): string {
|
|
return path.join(getCcsDir(), 'backups', 'auth-continuity');
|
|
}
|
|
|
|
export function createTimestampStamp(date = new Date()): string {
|
|
const yyyy = date.getFullYear();
|
|
const mm = String(date.getMonth() + 1).padStart(2, '0');
|
|
const dd = String(date.getDate()).padStart(2, '0');
|
|
const hh = String(date.getHours()).padStart(2, '0');
|
|
const min = String(date.getMinutes()).padStart(2, '0');
|
|
const ss = String(date.getSeconds()).padStart(2, '0');
|
|
return `${yyyy}${mm}${dd}_${hh}${min}${ss}`;
|
|
}
|
|
|
|
export function getContinuityArtifactNames(profileType: ProfileType): string[] {
|
|
const sharedItems = ['projects'];
|
|
const deeperItems = ['session-env', 'file-history', 'shell-snapshots', 'todos'];
|
|
|
|
if (profileType === 'default' || profileType === 'account') {
|
|
return [...sharedItems, ...deeperItems];
|
|
}
|
|
|
|
return sharedItems;
|
|
}
|