replace ptyc with forkpty() via Dart FFI
test / unit + widget + golden + a11y (push) Failing after 3m13s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped

NativePty calls forkpty() directly — no helper binary, no socketpair,
no SCM_RIGHTS. The master fd stays in-process. Reader isolate uses
poll() for clean shutdown.

Based on the pty-spike proof-of-concept. Platform-aware: macOS uses
libSystem (DynamicLibrary.process), Linux needs libutil.so.1.
TIOCSWINSZ platform-detected.

PaneRegistry updated to use NativePty. registerPaneCommands no longer
needs a Toolchain parameter. All ptyc references removed from the
daemon layer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jeroen Schweitzer
2026-04-30 20:30:15 +02:00
co-authored by Claude Opus 4.6
parent cf2ae48201
commit 5aa0eb46e4
12 changed files with 708 additions and 336 deletions
+23 -9
View File
@@ -8,10 +8,11 @@ library;
import 'dart:async';
import 'dart:convert';
import 'dart:io' show Platform;
import 'dart:typed_data';
import '../ipc/envelope.dart';
import '../pty/session.dart';
import '../pty/native_pty.dart';
import 'event_sink.dart';
import 'pane.dart';
@@ -20,7 +21,7 @@ class PaneRegistry {
final DaemonEventSink events;
final Map<String, Pane> _panes = {};
final Map<String, PtySession> _sessions = {};
final Map<String, NativePty> _sessions = {};
final Map<String, StreamSubscription<Uint8List>> _subs = {};
int _nextId = 1;
@@ -42,16 +43,29 @@ class PaneRegistry {
int cols = 80,
int rows = 24,
String? title,
String ptycPath = 'ptyc',
}) async {
final id = 'p_${_nextId++}';
final session = await PtySession.spawn(
argv: argv,
cwd: cwd,
env: env,
cols: cols,
final executable = argv.first;
final arguments = argv.length > 1 ? argv.sublist(1) : const <String>[];
// Merge the caller's env on top of the process environment +
// terminal defaults, matching the old ptyc contract.
final fullEnv = <String, String>{
...Platform.environment,
'TERM': 'xterm-256color',
'COLORTERM': 'truecolor',
'LANG': 'en_US.UTF-8',
'LC_ALL': 'en_US.UTF-8',
if (env != null) ...env,
};
final session = NativePty.start(
executable: executable,
arguments: arguments,
columns: cols,
rows: rows,
ptycPath: ptycPath,
workingDirectory: cwd,
environment: fullEnv,
);
final pane = Pane(
id: id,