Skip to content

Commit c7bf155

Browse files
committed
feat(web): add terminal channel attach + replay client primitives
- Add TerminalChannelReplayEvent type with runtime_id, data, cols, rows - Add buildTerminalChannelAttach and sendTerminalChannelAttach helpers - Add subscribeTerminalChannelReplay for channel_replay event - Add WsTerminalChannelAttachEnvelope to ws protocol for type safety
1 parent 20ef7aa commit c7bf155

3 files changed

Lines changed: 51 additions & 2 deletions

File tree

apps/web/src/services/terminal-channel/client.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { TerminalChannelOutputEvent } from "../../types/app.ts";
1+
import type { TerminalChannelOutputEvent, TerminalChannelReplayEvent } from "../../types/app.ts";
22

33
const TERMINAL_CHANNEL_RESPONSE_PATTERNS = [
44
/^\u001b\[I$/,
@@ -148,3 +148,37 @@ export const subscribeTerminalChannelOutput = (
148148
});
149149
return () => unsubscribe();
150150
};
151+
152+
export const buildTerminalChannelAttach = (
153+
workspaceId: string,
154+
fencingToken: number,
155+
runtimeId: string,
156+
) => ({
157+
type: "terminal_channel_attach" as const,
158+
workspace_id: workspaceId,
159+
fencing_token: fencingToken,
160+
runtime_id: runtimeId,
161+
});
162+
163+
export const sendTerminalChannelAttach = (
164+
workspaceId: string,
165+
fencingToken: number,
166+
runtimeId: string,
167+
) => {
168+
void import("../../ws/client.ts").then(({ sendWsMessage }) => {
169+
sendWsMessage(buildTerminalChannelAttach(workspaceId, fencingToken, runtimeId));
170+
});
171+
};
172+
173+
export const subscribeTerminalChannelReplay = (
174+
handler: (payload: TerminalChannelReplayEvent) => void,
175+
) => {
176+
let unsubscribe = () => {};
177+
void import("../../ws/client.ts").then(({ subscribeWsEvent }) => {
178+
unsubscribe = subscribeWsEvent<TerminalChannelReplayEvent>(
179+
"terminal://channel_replay",
180+
handler,
181+
);
182+
});
183+
return () => unsubscribe();
184+
};

apps/web/src/types/app.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,13 @@ export type TerminalChannelOutputEvent = {
187187
data: string;
188188
};
189189

190+
export interface TerminalChannelReplayEvent {
191+
runtime_id: string;
192+
data: string;
193+
cols: number;
194+
rows: number;
195+
}
196+
190197
export type SessionRuntimeStartResult = {
191198
terminal_id: number;
192199
started: boolean;

apps/web/src/ws/protocol.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ export type WsTerminalChannelInputEnvelope = {
5151
input: string;
5252
};
5353

54+
export type WsTerminalChannelAttachEnvelope = {
55+
type: "terminal_channel_attach";
56+
workspace_id: string;
57+
fencing_token: number;
58+
runtime_id: string;
59+
};
60+
5461
export type WsPingEnvelope = {
5562
type: "ping";
5663
ts: number;
@@ -69,7 +76,8 @@ export type WsClientEnvelope =
6976
| WsTerminalWriteEnvelope
7077
| WsTerminalResizeEnvelope
7178
| WsWorkspaceControllerHeartbeatEnvelope
72-
| WsTerminalChannelInputEnvelope;
79+
| WsTerminalChannelInputEnvelope
80+
| WsTerminalChannelAttachEnvelope;
7381

7482
export const parseWsEnvelope = (message: string): WsEnvelope | null => {
7583
try {

0 commit comments

Comments
 (0)