Add end-to-end abort support: AbortSignal in @gadget/ai providers, abortWorkOrder socket message, drone AbortController handling, Cancel button and double-Esc in frontend, and aborted turn status display.
144 lines
3.9 KiB
TypeScript
144 lines
3.9 KiB
TypeScript
// src/messages/socket.ts
|
|
// Copyright (C) 2026 Rob Colbert <rob.colbert@openplatform.us>
|
|
// Licensed under the Apache License, Version 2.0
|
|
|
|
import {
|
|
StatusMessage,
|
|
ProcessWorkOrderMessage,
|
|
ResponseMessage,
|
|
ThinkingMessage,
|
|
ToolCallMessage,
|
|
WorkOrderCompleteMessage,
|
|
RequestCrashRecoveryMessage,
|
|
CrashRecoveryResponseMessage,
|
|
RequestTerminationMessage,
|
|
WorkspaceModeChangedMessage,
|
|
LogMessage,
|
|
} from "./drone.ts";
|
|
import { SessionUpdatedMessage } from "./web.ts";
|
|
import {
|
|
AbortWorkOrderMessage,
|
|
ReleaseSessionLockMessage,
|
|
RequestSessionLockMessage,
|
|
RequestWorkspaceModeMessage,
|
|
SessionHeartbeatMessage,
|
|
SubmitPromptMessage,
|
|
} from "./ide.ts";
|
|
|
|
/*
|
|
There are two different kinds of clients that connect to the gadget-code:web
|
|
Socket.IO server:
|
|
|
|
1. The gadget-code:ide (ReactJS front-end)
|
|
2. The gadget-drone work order runner (NodeJS headless process)
|
|
|
|
gadget-code:ide sends Socket.IO messages to gadget-code:web, which then routes
|
|
them to the appropriate gadget-drone socket.
|
|
|
|
gadget-drone sends messages to gadget-code:web intending for them to be routed
|
|
to the appropriate gadget-code:ide socket.
|
|
|
|
This architecture lets the IDE run under User control in any browser anywhere,
|
|
and serve as a remote control surface for one or more gadget-drone processes
|
|
running work orders on projects in chat sessions.
|
|
*/
|
|
|
|
export interface ClientToServerEvents {
|
|
/*
|
|
* gadget-code:ide => gadget-code:web
|
|
*/
|
|
|
|
requestSessionLock: RequestSessionLockMessage;
|
|
requestWorkspaceMode: RequestWorkspaceModeMessage;
|
|
submitPrompt: SubmitPromptMessage;
|
|
abortWorkOrder: AbortWorkOrderMessage;
|
|
releaseSessionLock: ReleaseSessionLockMessage;
|
|
sessionHeartbeat: SessionHeartbeatMessage;
|
|
|
|
/*
|
|
* gadget-drone => gadget-code:web
|
|
*/
|
|
|
|
log: LogMessage;
|
|
status: StatusMessage;
|
|
thinking: ThinkingMessage;
|
|
response: ResponseMessage;
|
|
toolCall: ToolCallMessage;
|
|
workOrderComplete: WorkOrderCompleteMessage;
|
|
requestCrashRecovery: RequestCrashRecoveryMessage;
|
|
requestTermination: RequestTerminationMessage;
|
|
workspaceModeChanged: WorkspaceModeChangedMessage;
|
|
"agent:thinking": AgentThinkingMessage;
|
|
"agent:response": AgentResponseMessage;
|
|
"agent:tool-call": AgentToolCallMessage;
|
|
"agent:tool-result": AgentToolResultMessage;
|
|
"agent:complete": AgentCompleteMessage;
|
|
}
|
|
|
|
export type AgentThinkingMessage = (data: {
|
|
agentId: string;
|
|
thinking: string;
|
|
}) => void;
|
|
|
|
export type AgentResponseMessage = (data: {
|
|
agentId: string;
|
|
chunk: string;
|
|
}) => void;
|
|
|
|
export type AgentToolCallMessage = (data: {
|
|
agentId: string;
|
|
tool: string;
|
|
args: unknown;
|
|
}) => void;
|
|
|
|
export type AgentToolResultMessage = (data: {
|
|
agentId: string;
|
|
tool: string;
|
|
result: unknown;
|
|
}) => void;
|
|
|
|
export type AgentCompleteMessage = (data: {
|
|
agentId: string;
|
|
response?: string;
|
|
subagent?: Record<string, unknown>;
|
|
stats?: Record<string, unknown>;
|
|
}) => void;
|
|
|
|
export interface ServerToClientEvents {
|
|
/*
|
|
* gadget-code:web => gadget-drone
|
|
*/
|
|
|
|
requestSessionLock: RequestSessionLockMessage;
|
|
requestWorkspaceMode: RequestWorkspaceModeMessage;
|
|
releaseSessionLock: ReleaseSessionLockMessage;
|
|
sessionHeartbeat: SessionHeartbeatMessage;
|
|
abortWorkOrder: AbortWorkOrderMessage;
|
|
processWorkOrder: ProcessWorkOrderMessage;
|
|
crashRecoveryResponse: CrashRecoveryResponseMessage;
|
|
requestTermination: RequestTerminationMessage;
|
|
|
|
/*
|
|
* gadget-code:web => gadget-code:ide
|
|
*/
|
|
|
|
log: LogMessage;
|
|
status: StatusMessage;
|
|
thinking: ThinkingMessage;
|
|
response: ResponseMessage;
|
|
toolCall: ToolCallMessage;
|
|
workOrderComplete: WorkOrderCompleteMessage;
|
|
workspaceModeChanged: WorkspaceModeChangedMessage;
|
|
sessionUpdated: SessionUpdatedMessage;
|
|
tabLockDenied: (data: { message: string }) => void;
|
|
"agent:thinking": AgentThinkingMessage;
|
|
"agent:response": AgentResponseMessage;
|
|
"agent:tool-call": AgentToolCallMessage;
|
|
"agent:tool-result": AgentToolResultMessage;
|
|
"agent:complete": AgentCompleteMessage;
|
|
}
|
|
|
|
export interface SocketData {
|
|
/* no data defined */
|
|
}
|