P2: découverte & reprise des sessions Claude
Arboretum découvre désormais toutes les sessions Claude de la machine (scan ~/.claude/projects + registre ~/.claude/sessions), distingue vivantes/mortes par pid+procStart, et permet de reprendre une morte (--resume dans son cwd d'origine) ou forker une vivante sans la corrompre. - shared: SessionSummary enrichi (source, claudeSessionId, pid, resumable, attachable, registryStatus) — additif, PROTOCOL_VERSION inchangé ; types REST resume/fork. - db: migration id:2 (claude_session_id, resumed_from). - core: jsonl-discovery (parseur tolérant, scan asynchrone non bloquant), session-registry (vivacité pid+procStart), discovery-service (cache + refresh périodique + diff/broadcast), pty-manager (resume/fork + capture du claudeSessionId via le registre). - routes: /sessions/:id/resume (garde-fou 409 anti-corruption sur session vivante) et /fork ; GET fusionné managées + découvertes ; relais WS. - web: badges managed/discovered + busy/idle/waiting, actions conditionnelles (Open/Observe/Kill vs Fork/View vs Resume/Fork), vue read-only des sessions externes, i18n EN/FR. - tests: jsonl-discovery, session-registry, discovery-service + resume/fork (130 verts) ; acceptation E2E acceptance-p2.mjs (sans quota) ALL GREEN. Conforme aux verdicts S1 (resume dans cwd d'origine, vivacité pid+procStart) et S4 (munge cwd, parseur tête+queue, priorité de titre).
This commit is contained in:
@@ -9,6 +9,7 @@ import type { Config } from './config.js';
|
||||
import type { Db } from './db/index.js';
|
||||
import { AuthService, LoginRateLimiter, type AuthContext } from './auth/service.js';
|
||||
import { PtyManager } from './core/pty-manager.js';
|
||||
import { DiscoveryService } from './core/discovery-service.js';
|
||||
import { registerAuthRoutes } from './routes/auth.js';
|
||||
import { registerSessionRoutes } from './routes/sessions.js';
|
||||
import { registerWsGateway } from './ws/gateway.js';
|
||||
@@ -26,13 +27,19 @@ export interface AppBundle {
|
||||
app: FastifyInstance;
|
||||
auth: AuthService;
|
||||
manager: PtyManager;
|
||||
discovery: DiscoveryService;
|
||||
}
|
||||
|
||||
export function buildApp(config: Config, db: Db, serverVersion: string): AppBundle {
|
||||
const app = Fastify({ logger: { level: process.env.ARBORETUM_LOG ?? 'info' } });
|
||||
const auth = new AuthService(db);
|
||||
const limiter = new LoginRateLimiter();
|
||||
const manager = new PtyManager(db);
|
||||
const manager = new PtyManager(db, config.claudeSessionsDir);
|
||||
const discovery = new DiscoveryService({
|
||||
ptyManager: manager,
|
||||
projectsDir: config.claudeProjectsDir,
|
||||
sessionsDir: config.claudeSessionsDir,
|
||||
});
|
||||
|
||||
void app.register(fastifyCookie);
|
||||
void app.register(fastifyWebsocket, {
|
||||
@@ -72,11 +79,11 @@ export function buildApp(config: Config, db: Db, serverVersion: string): AppBund
|
||||
});
|
||||
|
||||
registerAuthRoutes(app, auth, limiter, serverVersion);
|
||||
registerSessionRoutes(app, manager);
|
||||
registerSessionRoutes(app, manager, discovery);
|
||||
// La route websocket doit être déclarée APRÈS le chargement du plugin (contexte
|
||||
// encapsulé) — sinon le handler reçoit la signature REST (request, reply).
|
||||
void app.register(async (scoped) => {
|
||||
registerWsGateway(scoped, manager, serverVersion);
|
||||
registerWsGateway(scoped, manager, discovery, serverVersion);
|
||||
});
|
||||
|
||||
// SPA buildée embarquée dans le paquet npm (public/) — absente en dev (vite dev sert le front)
|
||||
@@ -91,5 +98,5 @@ export function buildApp(config: Config, db: Db, serverVersion: string): AppBund
|
||||
});
|
||||
}
|
||||
|
||||
return { app, auth, manager };
|
||||
return { app, auth, manager, discovery };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user