1/**
2 * PtyAdapter - Terminal PTY adapter service contract.
3 *
4 * Defines the process primitives required by terminal session management
5 * without binding to a specific PTY implementation.
6 *
7 * @module PtyAdapter
8 */
9import * as Context from "effect/Context";
10import * as Effect from "effect/Effect";
11import * as Schema from "effect/Schema";
12
13/**
14 * PtySpawnError - Error type for PTY spawn failures.
15 */
16export class PtySpawnError extends Schema.TaggedError<PtySpawnError>()("PtySpawnError", {
17 adapter: Schema.String,
18 shell: Schema.optional(Schema.String),
19 attemptedShells: Schema.optional(Schema.Array(Schema.String)),
20 cause: Schema.optional(Schema.Defect()),
21}) {
22 override get message(): string {
23 const shell = this.shell === undefined ? "" : ` '${this.shell}'`;
24 const attemptedShells =
25 this.attemptedShells === undefined || this.attemptedShells.length === 0
26 ? ""
27 : ` Tried shells: ${this.attemptedShells.join(", ")}.`;
28 return `Failed to spawn PTY process${shell} with ${this.adapter}.${attemptedShells}`;
29 }
30}
31
32export interface PtyExitEvent {
33 exitCode: number;
34 signal: number | null;
35}
36
37export interface PtyProcess {
38 readonly pid: number;
39 write(data: string): void;
40 resize(cols: number, rows: number): void;
41 kill(signal?: string): void;
42 onData(callback: (data: string) => void): () => void;
43 onExit(callback: (event: PtyExitEvent) => void): () => void;
44}
45
46export interface PtySpawnInput {
47 shell: string;
48 args?: string[];
49 cwd: string;
50 cols: number;
51 rows: number;
52 env: NodeJS.ProcessEnv;
53}
54
55/**
56 * PtyAdapter - Service tag for PTY process integration.
57 */
58export class PtyAdapter extends Context.Service<
59 PtyAdapter,
60 {
61 /**
62 * Spawn a PTY process for a terminal session.
63 */
64 readonly spawn: (input: PtySpawnInput) => Effect.Effect<PtyProcess, PtySpawnError>;
65 }
66>()("@t3tools/shared/PtyAdapter") {}