Merge remote-tracking branch 'origin/main' into pr-36-generic-agent-config

# Conflicts:
#	docs/config.html
#	docs/config.md
#	src/cli.test.ts
#	src/cli.ts
#	src/client/src/components/settings/SettingsSessiondPanel.ts
#	src/client/src/components/settings/settingsConfigDraft.test.ts
#	src/client/src/components/settings/settingsConfigDraft.ts
#	src/server/app.test.ts
#	src/server/app.ts
#	src/server/configRoutes.test.ts
#	src/server/configRoutes.ts
#	src/server/piWebPluginService.test.ts
#	src/server/piWebPluginService.ts
#	src/server/piWebStatus.test.ts
#	src/server/piWebStatus.ts
#	src/server/piWebStatusCache.ts
#	src/server/sessions/authService.test.ts
#	src/server/sessions/piSessionService.ts
#	src/server/sessions/sessionRoutes.test.ts
This commit is contained in:
Federico Jaramillo Martinez
2026-07-13 20:30:08 +02:00
289 changed files with 29164 additions and 6419 deletions
+37 -2
View File
@@ -1,5 +1,6 @@
import type { FastifyInstance } from "fastify";
import type { SessionCleanupRequest } from "../../shared/apiTypes.js";
import type { SessionBulkMutationRequest, SessionBulkMutationRef, SessionCleanupRequest } from "../../shared/apiTypes.js";
import { projectBrowserMessageResponse } from "../browserMessageProjection.js";
import { normalizeRequestCwd } from "../workingDirectory.js";
import type { SessionEventHub } from "../realtime/sessionEventHub.js";
import type { SessionRouteLookup, SessionRouteService } from "./sessionService.js";
@@ -64,10 +65,27 @@ export function registerSessionRoutes(app: FastifyInstance, sessions: SessionRou
}
});
app.post<{ Body: SessionBulkMutationRequest | undefined }>(`${prefix}/sessions/bulk/archive`, async (request, reply) => {
try {
return await sessions.archiveMany(bulkMutationRefsFromBody(request.body));
} catch (error) {
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
}
});
app.post<{ Body: SessionBulkMutationRequest | undefined }>(`${prefix}/sessions/bulk/delete-archived`, async (request, reply) => {
try {
return await sessions.deleteArchivedMany(bulkMutationRefsFromBody(request.body));
} catch (error) {
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
}
});
app.get<{ Params: { sessionId: string }; Querystring: MessageQuery }>(`${prefix}/sessions/:sessionId/messages`, async (request, reply) => {
try {
const page = { ...optionalField("before", optionalNumber(request.query.before)), ...optionalField("limit", optionalNumber(request.query.limit)) };
return await sessions.messages(sessionLookupFromQuery(request.params.sessionId, request.query), page);
const messages = await sessions.messages(sessionLookupFromQuery(request.params.sessionId, request.query), page);
return projectBrowserMessageResponse(messages);
} catch (error) {
return reply.code(404).send({ error: errorMessage(error) });
}
@@ -281,6 +299,23 @@ export function registerSessionRoutes(app: FastifyInstance, sessions: SessionRou
});
}
function bulkMutationRefsFromBody(body: SessionBulkMutationRequest | undefined): SessionBulkMutationRef[] {
const record = requireRecord(body);
const sessions = record["sessions"];
if (!Array.isArray(sessions)) throw new Error("sessions field must be an array");
return sessions.map(parseBulkMutationRef);
}
function parseBulkMutationRef(value: unknown): SessionBulkMutationRef {
const record = requireRecord(value);
const id = requireString(record, "id").trim();
if (id === "") throw new Error("id field must not be empty");
const cwd = record["cwd"];
if (cwd === undefined || cwd === "") return { id };
if (typeof cwd !== "string") throw new Error("cwd field must be a string");
return { id, cwd: normalizeRequestCwd(cwd) };
}
function sessionLookupFromQuery(id: string, query: SessionQuery): SessionLookup {
return sessionLookupFromCwd(id, query.cwd);
}