MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / makeCliSurface

Function makeCliSurface

e2e/src/surfaces/cli.ts:78–125  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

76// acquireUseRelease so a vitest timeout (fiber interruption) still tears the
77// PTY down instead of leaking the child process.
78export const makeCliSurface = (): CliSurface => ({
79 session: (command, drive, options) =>
80 Effect.acquireUseRelease(
81 Effect.promise(async () => {
82 const tc = await TerminalControl.make();
83 const session: Session = await tc.launch({
84 command,
85 cwd: options?.cwd,
86 env: { ...options?.env, ...E2E_OUTBOUND_OPT_OUT },
87 record: options?.record ? true : undefined,
88 viewport: options?.viewport,
89 });
90 // Anchor the terminal recording on the run's focus timeline (symmetric
91 // with the browser surface), so a combined cli+browser scenario gets the
92 // synced SessionPlayer view (terminal/browser cuts + URL bar) for free.
93 const runDir = options?.record ? dirname(options.record) : null;
94 if (runDir) markRecordingStart(runDir, "terminal");
95 return { tc, session, runDir };
96 }),
97 ({ session, runDir }) =>
98 Effect.promise(async () => {
99 if (runDir) await enterFocus(runDir, "terminal");
100 const result = await drive(session);
101 // Hold the terminal's final frame (e.g. "connected") before the
102 // recording stops, so it isn't a single flash in the film. Filming
103 // only — fast runs return immediately.
104 await beat();
105 return result;
106 }),
107 ({ tc, session }) =>
108 Effect.promise(async () => {
109 if (options?.record) {
110 const recording = await session.recording().catch(() => undefined);
111 // Writing the cast is a best-effort film artifact (symmetric with the
112 // fetch above): a serialization or IO hiccup in teardown must never
113 // fail an otherwise-passing test.
114 // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: best-effort artifact write
115 try {
116 if (recording) writeFileSync(options.record, toAsciicast(recording));
117 } catch {
118 // drop the cast; the test result stands
119 }
120 }
121 await session.stop().catch(() => {});
122 await tc[Symbol.asyncDispose]();
123 }),
124 ),
125});

Callers 2

contextForFunction · 0.90

Calls 4

markRecordingStartFunction · 0.90
enterFocusFunction · 0.90
beatFunction · 0.90
toAsciicastFunction · 0.85

Tested by

no test coverage detected