fix(remote-control): resync clients on session switch
This commit is contained in:
parent
f16a5fed83
commit
33403bd030
|
|
@ -74,6 +74,11 @@ export default function remoteControl(pi: ExtensionAPI) {
|
||||||
updateStatus(ctx);
|
updateStatus(ctx);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pi.on("session_switch", async (_event, ctx) => {
|
||||||
|
server?.sync(ctx);
|
||||||
|
updateStatus(ctx);
|
||||||
|
});
|
||||||
|
|
||||||
pi.on("session_shutdown", async () => {
|
pi.on("session_shutdown", async () => {
|
||||||
if (server) {
|
if (server) {
|
||||||
await server.stop();
|
await server.stop();
|
||||||
|
|
|
||||||
|
|
@ -79,3 +79,25 @@ export function getBranchMessages(ctx: ExtensionContext): RenderMsg[] {
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildSyncMessage(ctx: ExtensionContext): {
|
||||||
|
type: "sync";
|
||||||
|
messages: RenderMsg[];
|
||||||
|
state: {
|
||||||
|
isStreaming: boolean;
|
||||||
|
model: string | undefined;
|
||||||
|
cwd: string;
|
||||||
|
sessionName: string | undefined;
|
||||||
|
};
|
||||||
|
} {
|
||||||
|
return {
|
||||||
|
type: "sync",
|
||||||
|
messages: getBranchMessages(ctx),
|
||||||
|
state: {
|
||||||
|
isStreaming: !ctx.isIdle(),
|
||||||
|
model: ctx.model?.id,
|
||||||
|
cwd: ctx.cwd,
|
||||||
|
sessionName: ctx.sessionManager.getSessionName(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import {
|
||||||
generateSessionId,
|
generateSessionId,
|
||||||
parseCookies,
|
parseCookies,
|
||||||
} from "./auth.js";
|
} from "./auth.js";
|
||||||
import { getBranchMessages } from "./messages.js";
|
import { buildSyncMessage } from "./messages.js";
|
||||||
import { buildHTML } from "./html.js";
|
import { buildHTML } from "./html.js";
|
||||||
|
|
||||||
// Load ws (bundled with pi) without needing @types/ws installed locally
|
// Load ws (bundled with pi) without needing @types/ws installed locally
|
||||||
|
|
@ -29,6 +29,7 @@ const { WebSocketServer, OPEN } = wsModule;
|
||||||
|
|
||||||
export interface RemoteServer {
|
export interface RemoteServer {
|
||||||
broadcast: (msg: object) => void;
|
broadcast: (msg: object) => void;
|
||||||
|
sync: (ctx: ExtensionContext) => void;
|
||||||
stop: () => Promise<void>;
|
stop: () => Promise<void>;
|
||||||
clientCount: () => number;
|
clientCount: () => number;
|
||||||
onClientChange: (cb: () => void) => void;
|
onClientChange: (cb: () => void) => void;
|
||||||
|
|
@ -79,6 +80,10 @@ export function startServer(pi: ExtensionAPI, ctx: ExtensionContext): Promise<Re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sync(currentCtx: ExtensionContext): void {
|
||||||
|
broadcast(buildSyncMessage(currentCtx));
|
||||||
|
}
|
||||||
|
|
||||||
const httpServer = createServer((req, res) => {
|
const httpServer = createServer((req, res) => {
|
||||||
const url = new URL(req.url ?? "/", "http://localhost");
|
const url = new URL(req.url ?? "/", "http://localhost");
|
||||||
const pathname = url.pathname;
|
const pathname = url.pathname;
|
||||||
|
|
@ -160,18 +165,7 @@ export function startServer(pi: ExtensionAPI, ctx: ExtensionContext): Promise<Re
|
||||||
|
|
||||||
// Send full state snapshot to the new client
|
// Send full state snapshot to the new client
|
||||||
try {
|
try {
|
||||||
ws.send(
|
ws.send(JSON.stringify(buildSyncMessage(ctx)));
|
||||||
JSON.stringify({
|
|
||||||
type: "sync",
|
|
||||||
messages: getBranchMessages(ctx),
|
|
||||||
state: {
|
|
||||||
isStreaming: !ctx.isIdle(),
|
|
||||||
model: ctx.model?.id,
|
|
||||||
cwd: ctx.cwd,
|
|
||||||
sessionName: ctx.sessionManager.getSessionName(),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
} catch {
|
} catch {
|
||||||
/* client disconnected before first send */
|
/* client disconnected before first send */
|
||||||
}
|
}
|
||||||
|
|
@ -225,6 +219,7 @@ export function startServer(pi: ExtensionAPI, ctx: ExtensionContext): Promise<Re
|
||||||
httpServer.listen(0, "127.0.0.1", () => {
|
httpServer.listen(0, "127.0.0.1", () => {
|
||||||
resolve({
|
resolve({
|
||||||
broadcast,
|
broadcast,
|
||||||
|
sync,
|
||||||
stop: () =>
|
stop: () =>
|
||||||
new Promise<void>((res) => {
|
new Promise<void>((res) => {
|
||||||
// Forcefully kill all WebSocket clients — terminate() sends no
|
// Forcefully kill all WebSocket clients — terminate() sends no
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue