feat(settings): réglages Claude CLI (binaire + ~/.claude) & notif « disponible »
- Réglages → Claude CLI : override du chemin du binaire `claude` (effet à la prochaine session, fallback `which claude`), diagnostic de détection, et override de la racine ~/.claude (effet au redémarrage). Validateurs stricts. - Push : notifie aussi sur le front busy→idle (session redevenue disponible). - Renomme l'état affiché idle → « disponible » / « available » (web EN/FR + VS Code) ; l'enum SessionActivity du protocole reste inchangé.
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
// Réglages liés au CLI Claude, persistés dans la table `settings` (clé/valeur), modifiables via
|
||||
// l'onglet Réglages. Frontière de sécurité identique à scan-settings : clés NON sensibles, écrites
|
||||
// uniquement via l'allow-list du PATCH /api/v1/settings et les validateurs ci-dessous.
|
||||
//
|
||||
// Motivation : un service systemd/launchd démarre avec un PATH minimal qui n'inclut pas ~/.local/bin
|
||||
// (où vit le binaire `claude`) → `which claude` échoue. Plutôt que de bricoler le PATH du service,
|
||||
// l'utilisateur peut pointer explicitement le binaire ici (effet : prochaine session, sans redémarrage).
|
||||
import { accessSync, constants, statSync } from 'node:fs';
|
||||
import { getSetting } from '../db/index.js';
|
||||
import type { Db } from '../db/index.js';
|
||||
import { isSafeAbsolutePath } from './git.js';
|
||||
|
||||
/** Chemin explicite du binaire `claude` (override de la résolution via PATH). */
|
||||
export const CLAUDE_BIN_PATH_KEY = 'claude_bin_path';
|
||||
/** Override de la racine ~/.claude (transcripts + registre des sessions). */
|
||||
export const CLAUDE_HOME_KEY = 'claude_home';
|
||||
|
||||
/** Chemin configuré du binaire `claude`, ou null si non défini (⇒ auto-détection via PATH). */
|
||||
export function readClaudeBinPath(db: Db): string | null {
|
||||
const raw = getSetting(db, CLAUDE_BIN_PATH_KEY)?.trim();
|
||||
return raw ? raw : null;
|
||||
}
|
||||
|
||||
/** Racine ~/.claude configurée, ou null si non défini (⇒ défaut/flag). */
|
||||
export function readClaudeHome(db: Db): string | null {
|
||||
const raw = getSetting(db, CLAUDE_HOME_KEY)?.trim();
|
||||
return raw ? raw : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide un chemin de binaire `claude`. Retourne `''` pour réinitialiser (auto-détection), le chemin
|
||||
* normalisé s'il est absolu ET pointe vers un fichier exécutable, ou `null` si invalide (⇒ 400).
|
||||
*/
|
||||
export function normalizeClaudeBinPath(raw: unknown): string | null {
|
||||
if (typeof raw !== 'string') return null;
|
||||
const p = raw.trim();
|
||||
if (p === '') return '';
|
||||
if (!isSafeAbsolutePath(p)) return null;
|
||||
try {
|
||||
if (!statSync(p).isFile()) return null;
|
||||
accessSync(p, constants.X_OK);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide une racine ~/.claude. Retourne `''` pour réinitialiser (défaut), le chemin normalisé s'il
|
||||
* est absolu ET pointe vers un répertoire existant, ou `null` si invalide (⇒ 400).
|
||||
*/
|
||||
export function normalizeClaudeHome(raw: unknown): string | null {
|
||||
if (typeof raw !== 'string') return null;
|
||||
const p = raw.trim();
|
||||
if (p === '') return '';
|
||||
if (!isSafeAbsolutePath(p)) return null;
|
||||
try {
|
||||
if (!statSync(p).isDirectory()) return null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
Reference in New Issue
Block a user