Archived
Inject Pi session service dependencies
This commit is contained in:
@@ -21,26 +21,49 @@ function noop(): void {
|
|||||||
// Intentionally empty default unsubscribe callback.
|
// Intentionally empty default unsubscribe callback.
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PiSessionService {
|
type SessionArchiveRepository = Pick<SessionArchiveStore, "list" | "archive" | "restore" | "isArchived">;
|
||||||
private readonly active = new Map<string, ActiveSession>();
|
type SessionManagerGateway = Pick<typeof SessionManager, "list" | "create" | "listAll" | "open">;
|
||||||
private readonly activities = new Map<string, { phase: "active" | "idle" | "error"; label: string; detail?: string; at: string }>();
|
|
||||||
private readonly heartbeat: NodeJS.Timeout;
|
function createDefaultRuntimeFactory(): CreateAgentSessionRuntimeFactory {
|
||||||
private readonly commandService: SessionCommandService;
|
const authStorage = AuthStorage.create();
|
||||||
private readonly archiveStore = new SessionArchiveStore();
|
const modelRegistry = ModelRegistry.create(authStorage);
|
||||||
private readonly agentDir = getAgentDir();
|
return async ({ cwd, agentDir, sessionManager, sessionStartEvent }) => {
|
||||||
private readonly authStorage = AuthStorage.create();
|
const services = await createAgentSessionServices({ cwd, agentDir, authStorage, modelRegistry });
|
||||||
private readonly modelRegistry = ModelRegistry.create(this.authStorage);
|
|
||||||
private readonly createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, agentDir, sessionManager, sessionStartEvent }) => {
|
|
||||||
const services = await createAgentSessionServices({ cwd, agentDir, authStorage: this.authStorage, modelRegistry: this.modelRegistry });
|
|
||||||
const options = sessionStartEvent === undefined
|
const options = sessionStartEvent === undefined
|
||||||
? { services, sessionManager }
|
? { services, sessionManager }
|
||||||
: { services, sessionManager, sessionStartEvent };
|
: { services, sessionManager, sessionStartEvent };
|
||||||
const result = await createAgentSessionFromServices(options);
|
const result = await createAgentSessionFromServices(options);
|
||||||
return { ...result, services, diagnostics: services.diagnostics };
|
return { ...result, services, diagnostics: services.diagnostics };
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
constructor(private readonly events: SessionEventHub) {
|
export interface PiSessionServiceDependencies {
|
||||||
this.heartbeat = setInterval(() => { this.publishHeartbeats(); }, 2000);
|
archiveStore?: SessionArchiveRepository;
|
||||||
|
agentDir?: string;
|
||||||
|
sessionManager?: SessionManagerGateway;
|
||||||
|
createRuntime?: CreateAgentSessionRuntimeFactory;
|
||||||
|
modelRegistry?: ReturnType<typeof ModelRegistry.create>;
|
||||||
|
heartbeatIntervalMs?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PiSessionService {
|
||||||
|
private readonly active = new Map<string, ActiveSession>();
|
||||||
|
private readonly activities = new Map<string, { phase: "active" | "idle" | "error"; label: string; detail?: string; at: string }>();
|
||||||
|
private readonly heartbeat: NodeJS.Timeout;
|
||||||
|
private readonly commandService: SessionCommandService;
|
||||||
|
private readonly archiveStore: SessionArchiveRepository;
|
||||||
|
private readonly agentDir: string;
|
||||||
|
private readonly sessionManager: SessionManagerGateway;
|
||||||
|
private readonly createRuntime: CreateAgentSessionRuntimeFactory;
|
||||||
|
private readonly modelRegistry: ReturnType<typeof ModelRegistry.create>;
|
||||||
|
|
||||||
|
constructor(private readonly events: SessionEventHub, deps: PiSessionServiceDependencies = {}) {
|
||||||
|
this.archiveStore = deps.archiveStore ?? new SessionArchiveStore();
|
||||||
|
this.agentDir = deps.agentDir ?? getAgentDir();
|
||||||
|
this.sessionManager = deps.sessionManager ?? SessionManager;
|
||||||
|
this.createRuntime = deps.createRuntime ?? createDefaultRuntimeFactory();
|
||||||
|
this.modelRegistry = deps.modelRegistry ?? ModelRegistry.create(AuthStorage.create());
|
||||||
|
this.heartbeat = setInterval(() => { this.publishHeartbeats(); }, deps.heartbeatIntervalMs ?? 2000);
|
||||||
this.commandService = new SessionCommandService(
|
this.commandService = new SessionCommandService(
|
||||||
(sessionId) => this.getActive(sessionId),
|
(sessionId) => this.getActive(sessionId),
|
||||||
(sessionId, text) => this.prompt(sessionId, text),
|
(sessionId, text) => this.prompt(sessionId, text),
|
||||||
@@ -65,7 +88,7 @@ export class PiSessionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async list(cwd: string): Promise<ClientSession[]> {
|
async list(cwd: string): Promise<ClientSession[]> {
|
||||||
const [sessions, archivedRecords] = await Promise.all([SessionManager.list(cwd), this.archiveStore.list()]);
|
const [sessions, archivedRecords] = await Promise.all([this.sessionManager.list(cwd), this.archiveStore.list()]);
|
||||||
const archivedById = new Map(archivedRecords.filter((record) => record.cwd === cwd).map((record) => [record.sessionId, record]));
|
const archivedById = new Map(archivedRecords.filter((record) => record.cwd === cwd).map((record) => [record.sessionId, record]));
|
||||||
return sessions.map((s) => {
|
return sessions.map((s) => {
|
||||||
const archived = archivedById.get(s.id);
|
const archived = archivedById.get(s.id);
|
||||||
@@ -84,7 +107,7 @@ export class PiSessionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async start(cwd: string): Promise<ClientSession> {
|
async start(cwd: string): Promise<ClientSession> {
|
||||||
const active = await this.create(SessionManager.create(cwd), cwd);
|
const active = await this.create(this.sessionManager.create(cwd), cwd);
|
||||||
const { session } = active.runtime;
|
const { session } = active.runtime;
|
||||||
return {
|
return {
|
||||||
id: session.sessionId,
|
id: session.sessionId,
|
||||||
@@ -225,9 +248,9 @@ export class PiSessionService {
|
|||||||
const active = this.active.get(sessionId);
|
const active = this.active.get(sessionId);
|
||||||
if (active) return active;
|
if (active) return active;
|
||||||
|
|
||||||
const match = (await SessionManager.listAll()).find((s) => s.id === sessionId || s.id.startsWith(sessionId));
|
const match = (await this.sessionManager.listAll()).find((s) => s.id === sessionId || s.id.startsWith(sessionId));
|
||||||
if (!match) throw new Error("Session not found");
|
if (!match) throw new Error("Session not found");
|
||||||
return this.create(SessionManager.open(match.path), match.cwd);
|
return this.create(this.sessionManager.open(match.path), match.cwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async create(sessionManager: SessionManager, cwd: string): Promise<ActiveSession> {
|
private async create(sessionManager: SessionManager, cwd: string): Promise<ActiveSession> {
|
||||||
|
|||||||
Reference in New Issue
Block a user