Archived
Disable forking active sessions
This commit is contained in:
@@ -114,4 +114,34 @@ describe("SessionCommandService", () => {
|
|||||||
expect(active.runtime.fork).toHaveBeenCalledWith("newest");
|
expect(active.runtime.fork).toHaveBeenCalledWith("newest");
|
||||||
await expect(service.respond("s1", result.requestId, "newest")).resolves.toEqual({ type: "unsupported", message: "Command request expired" });
|
await expect(service.respond("s1", result.requestId, "newest")).resolves.toEqual({ type: "unsupported", message: "Command request expired" });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("rejects fork and clone while the session has active work", async () => {
|
||||||
|
const active = activeSession({ isStreaming: true });
|
||||||
|
const service = new SessionCommandService(() => getActive(active), vi.fn(), { publish: vi.fn() } as never);
|
||||||
|
|
||||||
|
await expect(service.run("s1", "/fork")).resolves.toEqual({
|
||||||
|
type: "unsupported",
|
||||||
|
message: "Cannot fork while the session is active. Stop current activity before forking.",
|
||||||
|
});
|
||||||
|
await expect(service.run("s1", "/clone")).resolves.toEqual({
|
||||||
|
type: "unsupported",
|
||||||
|
message: "Cannot clone while the session is active. Stop current activity before cloning.",
|
||||||
|
});
|
||||||
|
expect(active.runtime.fork).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rejects fork responses if the session becomes active after choosing fork", async () => {
|
||||||
|
const active = activeSession();
|
||||||
|
const service = new SessionCommandService(() => getActive(active), vi.fn(), { publish: vi.fn() } as never);
|
||||||
|
|
||||||
|
const result = await service.run("s1", "/fork");
|
||||||
|
if (result.type !== "select") throw new Error("Expected select result");
|
||||||
|
(active.runtime.session as Record<string, unknown>)["isStreaming"] = true;
|
||||||
|
|
||||||
|
await expect(service.respond("s1", result.requestId, "m1")).resolves.toEqual({
|
||||||
|
type: "unsupported",
|
||||||
|
message: "Cannot fork while the session is active. Stop current activity before forking.",
|
||||||
|
});
|
||||||
|
expect(active.runtime.fork).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ export class SessionCommandService {
|
|||||||
this.pendingSelects.delete(requestId);
|
this.pendingSelects.delete(requestId);
|
||||||
|
|
||||||
const active = await this.getActive(sessionId);
|
const active = await this.getActive(sessionId);
|
||||||
|
if (sessionHasActiveWork(active.runtime.session)) return forkActiveUnsupported("fork");
|
||||||
const result = await active.runtime.fork(value);
|
const result = await active.runtime.fork(value);
|
||||||
if (result.cancelled) return { type: "done", message: "Fork cancelled" };
|
if (result.cancelled) return { type: "done", message: "Fork cancelled" };
|
||||||
return { type: "done", message: "Session forked", session: clientSessionFromRuntime(active.runtime) };
|
return { type: "done", message: "Session forked", session: clientSessionFromRuntime(active.runtime) };
|
||||||
@@ -84,6 +85,7 @@ export class SessionCommandService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async clone(active: ActiveSession): Promise<ClientCommandResult> {
|
private async clone(active: ActiveSession): Promise<ClientCommandResult> {
|
||||||
|
if (sessionHasActiveWork(active.runtime.session)) return forkActiveUnsupported("clone");
|
||||||
const leafId = active.runtime.session.sessionManager.getLeafId();
|
const leafId = active.runtime.session.sessionManager.getLeafId();
|
||||||
if (leafId === null || leafId === "") return { type: "unsupported", message: "Cannot clone: no current session entry" };
|
if (leafId === null || leafId === "") return { type: "unsupported", message: "Cannot clone: no current session entry" };
|
||||||
const result = await active.runtime.fork(leafId, { position: "at" });
|
const result = await active.runtime.fork(leafId, { position: "at" });
|
||||||
@@ -92,6 +94,7 @@ export class SessionCommandService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fork(active: ActiveSession): ClientCommandResult {
|
private fork(active: ActiveSession): ClientCommandResult {
|
||||||
|
if (sessionHasActiveWork(active.runtime.session)) return forkActiveUnsupported("fork");
|
||||||
const messages = active.runtime.session.getUserMessagesForForking();
|
const messages = active.runtime.session.getUserMessagesForForking();
|
||||||
if (!messages.length) return { type: "unsupported", message: "No user messages to fork from" };
|
if (!messages.length) return { type: "unsupported", message: "No user messages to fork from" };
|
||||||
const requestId = crypto.randomUUID();
|
const requestId = crypto.randomUUID();
|
||||||
@@ -127,6 +130,14 @@ function clientSessionFromRuntime(runtime: AgentSessionRuntime): ClientSession {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sessionHasActiveWork(session: AgentSession): boolean {
|
||||||
|
return session.isStreaming || session.isBashRunning || session.isCompacting || session.pendingMessageCount > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function forkActiveUnsupported(command: "fork" | "clone"): ClientCommandResult {
|
||||||
|
return { type: "unsupported", message: `Cannot ${command} while the session is active. Stop current activity before ${command === "fork" ? "forking" : "cloning"}.` };
|
||||||
|
}
|
||||||
|
|
||||||
function formatSessionStats(session: AgentSession): string {
|
function formatSessionStats(session: AgentSession): string {
|
||||||
const stats = session.getSessionStats();
|
const stats = session.getSessionStats();
|
||||||
return [
|
return [
|
||||||
|
|||||||
Reference in New Issue
Block a user