session lock and workspace processing refinements

This commit is contained in:
Rob Colbert 2026-05-02 11:21:41 -04:00
parent 4075a63aea
commit b84e06fac8
4 changed files with 36 additions and 21 deletions

View File

@ -123,8 +123,6 @@ export class CodeSession extends SocketSession {
droneSession.socket.emit(
"processWorkOrder",
this.selectedDrone,
this.project,
this.chatSession,
turn,
(success: boolean, message?: string) => {
if (success) {

View File

@ -150,8 +150,6 @@ describe("CodeSession", () => {
expect(mockDroneSession.socket.emit).toHaveBeenCalledWith(
"processWorkOrder",
mockDrone,
mockProject,
mockChatSession,
mockTurn,
expect.any(Function),
);

View File

@ -33,6 +33,11 @@ interface UserCredentials {
password: string;
}
interface ISessionLock {
project: IProject;
session: IChatSession;
}
type ClientSocket = Socket<ServerToClientEvents, ClientToServerEvents>;
class GadgetDrone extends GadgetProcess {
@ -40,7 +45,7 @@ class GadgetDrone extends GadgetProcess {
private user: IUser | undefined;
private workspaceMode: WorkspaceMode = WorkspaceMode.Syncing;
private chatSession: IChatSession | undefined;
private sessionLock: ISessionLock | undefined;
private socket: ClientSocket | undefined;
private isShuttingDown: boolean = false;
@ -245,16 +250,22 @@ class GadgetDrone extends GadgetProcess {
* Check if the chat session lock is already held.
*/
if (this.chatSession) {
if (chatSession._id !== this.chatSession._id) {
if (this.sessionLock) {
if (chatSession._id !== this.sessionLock.session._id) {
this.log.warn("rejecting session lock request", {
chatSession: {
_id: this.chatSession._id,
name: this.chatSession.name,
sessionLock: {
project: {
_id: this.sessionLock.project._id,
name: this.sessionLock.project.name,
},
session: {
_id: this.sessionLock.session._id,
name: this.sessionLock.session.name,
},
},
workspaceMode: this.workspaceMode,
});
return cb(false, this.chatSession._id);
return cb(false, this.sessionLock.session._id);
}
// fall through to grant this lock request
this.log.info("chat session is re-connecting to session lock");
@ -269,7 +280,10 @@ class GadgetDrone extends GadgetProcess {
project: { _id: project._id, slug: project.slug },
chatSession: { _id: chatSession._id, name: chatSession.name },
});
this.chatSession = chatSession;
this.sessionLock = {
project,
session: chatSession,
};
this.workspaceMode = WorkspaceMode.Idle;
cb(true, chatSession._id);
@ -282,10 +296,10 @@ class GadgetDrone extends GadgetProcess {
mode: WorkspaceMode,
cb: RequestWorkspaceModeCallback,
) {
if (!this.chatSession) {
if (!this.sessionLock) {
return cb(false, this.workspaceMode);
}
if (chatSession._id !== this.chatSession._id) {
if (chatSession._id !== this.sessionLock.session._id) {
this.log.warn("rejecting workspace mode request", {
chatSession: { _id: chatSession._id, name: chatSession.name },
});
@ -306,17 +320,24 @@ class GadgetDrone extends GadgetProcess {
async onProcessWorkOrder(
registration: IDroneRegistration,
project: IProject,
chatSession: IChatSession,
turn: IChatTurn,
cb: ProcessWorkOrderCallback,
) {
if (!this.chatSession) {
const project = turn.project as IProject;
const session = turn.session as IChatSession;
if (!this.sessionLock) {
return cb(false, "this drone is not locked to a chat session");
}
if (this.chatSession._id !== chatSession._id) {
if (this.sessionLock.session._id !== session._id) {
return cb(false, "this drone is not locked to your chat session");
}
if (this.sessionLock.project._id !== project._id) {
return cb(
false,
`this drone is locked to a different project: ${this.sessionLock.project.name}`,
);
}
if (this.workspaceMode !== WorkspaceMode.Agent) {
return cb(false, "this drone's workspace is not in Agent mode");
}
@ -329,7 +350,7 @@ class GadgetDrone extends GadgetProcess {
this.log.info("processWorkOrder received", {
registration: { _id: registration._id },
project: { _id: project._id, name: project.name },
chatSession: { _id: chatSession._id, name: chatSession.name },
session: { _id: session._id, name: session.name },
turn: { _id: turn._id, mode: turn.mode, userPrompt: turn.prompts.user },
});

View File

@ -13,8 +13,6 @@ export type ProcessWorkOrderCallback = (
) => void;
export type ProcessWorkOrderMessage = (
registration: IDroneRegistration,
project: IProject,
chatSession: IChatSession,
turn: IChatTurn,
cb: ProcessWorkOrderCallback,
) => void;