Merge remote-tracking branch 'origin/main' into investigate/issue-12-session-dir

# Conflicts:
#	src/client/src/api.ts
#	src/client/src/api/clients.ts
#	src/client/src/api/federatedRouteContract.test.ts
#	src/server/sessions/piSessionService.ts
#	src/server/sessions/sessionRoutes.ts
This commit is contained in:
Federico Jaramillo Martinez
2026-06-10 20:43:10 +02:00
133 changed files with 4848 additions and 968 deletions
+58
View File
@@ -0,0 +1,58 @@
import Fastify, { type FastifyInstance } from "fastify";
import fastifyWebsocket from "@fastify/websocket";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { SessionEventHub } from "../realtime/sessionEventHub.js";
import { PiSessionService, type PiSessionManagerGateway } from "./piSessionService.js";
import { registerSessionRoutes } from "./sessionRoutes.js";
let app: FastifyInstance;
let service: PiSessionService;
let sessionManager: RejectingSessionManager;
beforeEach(async () => {
app = Fastify({ logger: false });
await app.register(fastifyWebsocket);
sessionManager = new RejectingSessionManager();
const eventHub = new SessionEventHub();
service = new PiSessionService(eventHub, { sessionManager, heartbeatIntervalMs: 60_000 });
registerSessionRoutes(app, service, eventHub);
});
afterEach(async () => {
await service.dispose();
await app.close();
});
describe("session routes", () => {
it("rejects prompt payloads that omit text without opening a session", async () => {
const response = await app.inject({ method: "POST", url: "/sessions/session-1/prompt", payload: { cwd: "/repo", body: "Build the thing" } });
expect(response.statusCode).toBe(400);
expect(response.json()).toEqual({ error: "Prompt text is required" });
expect(sessionManager.calls).toEqual({ create: 0, list: 0, listAll: 0, open: 0 });
});
});
class RejectingSessionManager implements PiSessionManagerGateway {
readonly calls = { create: 0, list: 0, listAll: 0, open: 0 };
list() {
this.calls.list += 1;
return Promise.resolve([]);
}
create(): never {
this.calls.create += 1;
throw new Error("Session manager should not create sessions for invalid prompt payloads");
}
listAll() {
this.calls.listAll += 1;
return Promise.resolve([]);
}
open(): never {
this.calls.open += 1;
throw new Error("Session manager should not open sessions for invalid prompt payloads");
}
}