1import type { TerminalSessionState } from "@t3tools/client-runtime/state/terminal";
2import {
3 AuthTerminalOperateScope,
4 type EnvironmentId,
5 type TerminalResizeInput,
6 type ThreadId,
7} from "@t3tools/contracts";
8import { useEffect } from "react";
9
10import type { TerminalGridSize } from "./terminalUiState";
11import { readEnvironmentScope } from "../../state/session";
12
13/** Replay the measured grid when a writable attachment becomes ready or reconnects. */
14export function useTerminalGridSync({
15 environmentId,
16 threadId,
17 terminalId,
18 canOperate,
19 terminal,
20 size,
21 resize,
22}: {
23 readonly environmentId: EnvironmentId | null;
24 readonly threadId: ThreadId | null;
25 readonly terminalId: string;
26 readonly canOperate: boolean;
27 readonly terminal: Pick<TerminalSessionState, "output" | "status" | "version">;
28 readonly size: TerminalGridSize;
29 readonly resize: (target: {
30 readonly environmentId: EnvironmentId;
31 readonly input: TerminalResizeInput;
32 }) => void;
33}): void {
34 const generation =
35 canOperate && terminal.version > 0 && terminal.status === "running"
36 ? terminal.output.generation
37 : null;
38
39 useEffect(() => {
40 if (
41 generation === null ||
42 environmentId === null ||
43 threadId === null ||
44 !readEnvironmentScope(environmentId, AuthTerminalOperateScope)
45 )
46 return;
47 resize({
48 environmentId,
49 input: { threadId, terminalId, cols: size.cols, rows: size.rows },
50 });
51 }, [environmentId, generation, resize, size.cols, size.rows, terminalId, threadId]);
52}