@love-moon/tui-driver 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +142 -0
  2. package/dist/driver/StateMachine.d.ts +28 -0
  3. package/dist/driver/StateMachine.d.ts.map +1 -0
  4. package/dist/driver/StateMachine.js +56 -0
  5. package/dist/driver/StateMachine.js.map +1 -0
  6. package/dist/driver/TuiDriver.d.ts +73 -0
  7. package/dist/driver/TuiDriver.d.ts.map +1 -0
  8. package/dist/driver/TuiDriver.js +506 -0
  9. package/dist/driver/TuiDriver.js.map +1 -0
  10. package/dist/driver/TuiProfile.d.ts +59 -0
  11. package/dist/driver/TuiProfile.d.ts.map +1 -0
  12. package/dist/driver/TuiProfile.js +13 -0
  13. package/dist/driver/TuiProfile.js.map +1 -0
  14. package/dist/driver/index.d.ts +5 -0
  15. package/dist/driver/index.d.ts.map +1 -0
  16. package/dist/driver/index.js +13 -0
  17. package/dist/driver/index.js.map +1 -0
  18. package/dist/driver/profiles/claudeCode.profile.d.ts +4 -0
  19. package/dist/driver/profiles/claudeCode.profile.d.ts.map +1 -0
  20. package/dist/driver/profiles/claudeCode.profile.js +91 -0
  21. package/dist/driver/profiles/claudeCode.profile.js.map +1 -0
  22. package/dist/driver/profiles/codex.profile.d.ts +4 -0
  23. package/dist/driver/profiles/codex.profile.d.ts.map +1 -0
  24. package/dist/driver/profiles/codex.profile.js +82 -0
  25. package/dist/driver/profiles/codex.profile.js.map +1 -0
  26. package/dist/driver/profiles/index.d.ts +3 -0
  27. package/dist/driver/profiles/index.d.ts.map +1 -0
  28. package/dist/driver/profiles/index.js +8 -0
  29. package/dist/driver/profiles/index.js.map +1 -0
  30. package/dist/example.d.ts +2 -0
  31. package/dist/example.d.ts.map +1 -0
  32. package/dist/example.js +43 -0
  33. package/dist/example.js.map +1 -0
  34. package/dist/expect/ExpectEngine.d.ts +34 -0
  35. package/dist/expect/ExpectEngine.d.ts.map +1 -0
  36. package/dist/expect/ExpectEngine.js +121 -0
  37. package/dist/expect/ExpectEngine.js.map +1 -0
  38. package/dist/expect/Matchers.d.ts +24 -0
  39. package/dist/expect/Matchers.d.ts.map +1 -0
  40. package/dist/expect/Matchers.js +71 -0
  41. package/dist/expect/Matchers.js.map +1 -0
  42. package/dist/expect/index.d.ts +3 -0
  43. package/dist/expect/index.d.ts.map +1 -0
  44. package/dist/expect/index.js +8 -0
  45. package/dist/expect/index.js.map +1 -0
  46. package/dist/extract/Diff.d.ts +10 -0
  47. package/dist/extract/Diff.d.ts.map +1 -0
  48. package/dist/extract/Diff.js +44 -0
  49. package/dist/extract/Diff.js.map +1 -0
  50. package/dist/extract/OutputExtractor.d.ts +16 -0
  51. package/dist/extract/OutputExtractor.d.ts.map +1 -0
  52. package/dist/extract/OutputExtractor.js +71 -0
  53. package/dist/extract/OutputExtractor.js.map +1 -0
  54. package/dist/extract/index.d.ts +3 -0
  55. package/dist/extract/index.d.ts.map +1 -0
  56. package/dist/extract/index.js +11 -0
  57. package/dist/extract/index.js.map +1 -0
  58. package/dist/index.d.ts +11 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +50 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/pty/PtySession.d.ts +38 -0
  63. package/dist/pty/PtySession.d.ts.map +1 -0
  64. package/dist/pty/PtySession.js +231 -0
  65. package/dist/pty/PtySession.js.map +1 -0
  66. package/dist/pty/index.d.ts +2 -0
  67. package/dist/pty/index.d.ts.map +1 -0
  68. package/dist/pty/index.js +6 -0
  69. package/dist/pty/index.js.map +1 -0
  70. package/dist/term/HeadlessScreen.d.ts +29 -0
  71. package/dist/term/HeadlessScreen.d.ts.map +1 -0
  72. package/dist/term/HeadlessScreen.js +126 -0
  73. package/dist/term/HeadlessScreen.js.map +1 -0
  74. package/dist/term/ScreenSnapshot.d.ts +37 -0
  75. package/dist/term/ScreenSnapshot.d.ts.map +1 -0
  76. package/dist/term/ScreenSnapshot.js +68 -0
  77. package/dist/term/ScreenSnapshot.js.map +1 -0
  78. package/dist/term/index.d.ts +3 -0
  79. package/dist/term/index.d.ts.map +1 -0
  80. package/dist/term/index.js +8 -0
  81. package/dist/term/index.js.map +1 -0
  82. package/docs/tui-driver_implementation_plan.md +307 -0
  83. package/package.json +33 -0
  84. package/pnpm-workspace.yaml +1 -0
  85. package/src/driver/StateMachine.ts +90 -0
  86. package/src/driver/TuiDriver.ts +624 -0
  87. package/src/driver/TuiProfile.ts +72 -0
  88. package/src/driver/index.ts +4 -0
  89. package/src/driver/profiles/claudeCode.profile.ts +96 -0
  90. package/src/driver/profiles/codex.profile.ts +87 -0
  91. package/src/driver/profiles/index.ts +2 -0
  92. package/src/example.ts +45 -0
  93. package/src/expect/ExpectEngine.ts +171 -0
  94. package/src/expect/Matchers.ts +92 -0
  95. package/src/expect/index.ts +2 -0
  96. package/src/extract/Diff.ts +51 -0
  97. package/src/extract/OutputExtractor.ts +88 -0
  98. package/src/extract/index.ts +2 -0
  99. package/src/index.ts +67 -0
  100. package/src/pty/PtySession.ts +234 -0
  101. package/src/pty/index.ts +1 -0
  102. package/src/term/HeadlessScreen.ts +151 -0
  103. package/src/term/ScreenSnapshot.ts +89 -0
  104. package/src/term/index.ts +2 -0
  105. package/test/claude-profile.test.ts +11 -0
  106. package/test/codex-profile.test.ts +108 -0
  107. package/test/debug-claude.ts +51 -0
  108. package/test/integration.ts +174 -0
  109. package/test/output-extractor.test.ts +49 -0
  110. package/test/state-diff.test.ts +120 -0
  111. package/test/unit.test.ts +136 -0
  112. package/tsconfig.json +20 -0
  113. package/vitest.config.ts +13 -0
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # TUI Driver
2
+
3
+ A headless TUI driver for interacting with interactive CLI tools like Claude Code and Codex.
4
+
5
+ ## Requirements
6
+
7
+ - Node.js >= 18.0.0 (recommended: Node.js 20.x LTS)
8
+ - node-pty requires native compilation (Python and build tools)
9
+
10
+ **Note**: node-pty may have compatibility issues with Node.js 23+. Use Node.js 20.x LTS for best compatibility.
11
+
12
+ ## Features
13
+
14
+ - **PTY Session Management**: Spawn and manage pseudo-terminal sessions
15
+ - **Headless Terminal Emulation**: Parse ANSI sequences and maintain screen buffer using @xterm/headless
16
+ - **Expect Engine**: Wait for screen conditions with stability checks and idle detection
17
+ - **State Machine**: Track interaction states (BOOT, READY, TYPING, STREAMING, etc.)
18
+ - **Output Extraction**: Extract model responses using diff-based algorithms
19
+ - **Profile System**: Configurable profiles for different TUI tools
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ pnpm install
25
+ pnpm build
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ### Basic Usage
31
+
32
+ ```typescript
33
+ import { createDriver } from "@love-moon/tui-driver";
34
+
35
+ const driver = createDriver("claude-code", { debug: true });
36
+
37
+ await driver.boot();
38
+ const result = await driver.ask("What is 2 + 2?");
39
+
40
+ if (result.success) {
41
+ console.log("Answer:", result.answer);
42
+ }
43
+
44
+ driver.kill();
45
+ ```
46
+
47
+ ### Advanced Usage
48
+
49
+ ```typescript
50
+ import { TuiDriver, claudeCodeProfile } from "@love-moon/tui-driver";
51
+
52
+ const driver = new TuiDriver({
53
+ profile: claudeCodeProfile,
54
+ debug: true,
55
+ onSnapshot: (snapshot, state) => {
56
+ console.log(`[${state}] Hash: ${snapshot.hash}`);
57
+ },
58
+ });
59
+
60
+ await driver.boot();
61
+
62
+ // Multiple questions in sequence
63
+ const q1 = await driver.ask("Hello!");
64
+ const q2 = await driver.ask("What can you do?");
65
+
66
+ driver.kill();
67
+ ```
68
+
69
+ ### Custom Profile
70
+
71
+ ```typescript
72
+ import { TuiDriver, createProfile } from "@love-moon/tui-driver";
73
+
74
+ const myProfile = createProfile({
75
+ name: "claude-code",
76
+ command: "my-cli",
77
+ args: ["--interactive"],
78
+ anchors: {
79
+ ready: [/>\s*$/m, /prompt:/i],
80
+ busy: [/thinking/i],
81
+ },
82
+ keys: {
83
+ submit: ["ENTER"],
84
+ cancel: ["CTRL_C"],
85
+ },
86
+ extraction: {
87
+ mode: "diff-scrollback",
88
+ stripPatterns: [/^>\s*/gm],
89
+ bottomUiLines: 2,
90
+ },
91
+ });
92
+
93
+ const driver = new TuiDriver({ profile: myProfile });
94
+ ```
95
+
96
+ ## Architecture
97
+
98
+ ```
99
+ src/
100
+ pty/
101
+ PtySession.ts # node-pty wrapper
102
+ term/
103
+ HeadlessScreen.ts # @xterm/headless wrapper
104
+ ScreenSnapshot.ts # Screen state snapshot
105
+ expect/
106
+ ExpectEngine.ts # Wait/expect engine
107
+ Matchers.ts # Pattern matchers
108
+ driver/
109
+ TuiProfile.ts # Profile type definitions
110
+ TuiDriver.ts # Main driver class
111
+ StateMachine.ts # State management
112
+ profiles/
113
+ claudeCode.profile.ts
114
+ codex.profile.ts
115
+ extract/
116
+ OutputExtractor.ts # Response extraction
117
+ Diff.ts # Text diff utilities
118
+ ```
119
+
120
+ ## API Reference
121
+
122
+ ### TuiDriver
123
+
124
+ - `boot()`: Initialize and wait for TUI to be ready
125
+ - `ask(prompt)`: Send a prompt and wait for response
126
+ - `ensureReady()`: Ensure TUI is in ready state
127
+ - `snapshot()`: Get current screen snapshot
128
+ - `sendKeys(keys)`: Send key sequences
129
+ - `kill()`: Terminate the PTY session
130
+
131
+ ### ExpectEngine
132
+
133
+ - `until(options)`: Wait for condition with stability
134
+ - `untilIdle(options)`: Wait for screen to stop changing
135
+ - `waitForChange(timeout)`: Wait for any screen change
136
+
137
+ ### ScreenSnapshot
138
+
139
+ - `viewportText`: Current visible screen content
140
+ - `scrollbackText`: Full scrollback buffer
141
+ - `cursor`: Current cursor position
142
+ - `hash`: Screen content hash for change detection
@@ -0,0 +1,28 @@
1
+ import { EventEmitter } from "events";
2
+ export type TuiState = "IDLE" | "BOOT" | "WAIT_READY" | "PREPARE_TURN" | "TYPE_PROMPT" | "SUBMIT" | "WAIT_STREAM_START" | "WAIT_STREAM_END" | "CAPTURE" | "DONE" | "ERROR" | "RECOVERY";
3
+ export interface StateTransition {
4
+ from: TuiState;
5
+ to: TuiState;
6
+ timestamp: number;
7
+ }
8
+ export interface StateMachineEvents {
9
+ stateChange: (transition: StateTransition) => void;
10
+ error: (error: Error, state: TuiState) => void;
11
+ }
12
+ export declare class StateMachine extends EventEmitter {
13
+ private _state;
14
+ private _history;
15
+ private _stateStartTime;
16
+ get state(): TuiState;
17
+ get history(): readonly StateTransition[];
18
+ get stateElapsedMs(): number;
19
+ transition(to: TuiState): void;
20
+ transitionTo(...states: TuiState[]): void;
21
+ isIn(...states: TuiState[]): boolean;
22
+ reset(): void;
23
+ error(err: Error): void;
24
+ recover(): void;
25
+ getLastTransition(): StateTransition | undefined;
26
+ getTransitionsSince(timestamp: number): StateTransition[];
27
+ }
28
+ //# sourceMappingURL=StateMachine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StateMachine.d.ts","sourceRoot":"","sources":["../../src/driver/StateMachine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,MAAM,QAAQ,GAChB,MAAM,GACN,MAAM,GACN,YAAY,GACZ,cAAc,GACd,aAAa,GACb,QAAQ,GACR,mBAAmB,GACnB,iBAAiB,GACjB,SAAS,GACT,MAAM,GACN,OAAO,GACP,UAAU,CAAC;AAEf,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,QAAQ,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,CAAC,UAAU,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;CAChD;AAED,qBAAa,YAAa,SAAQ,YAAY;IAC5C,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,eAAe,CAAsB;IAE7C,IAAI,KAAK,IAAI,QAAQ,CAEpB;IAED,IAAI,OAAO,IAAI,SAAS,eAAe,EAAE,CAExC;IAED,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,UAAU,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI;IAY9B,YAAY,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI;IAMzC,IAAI,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO;IAIpC,KAAK,IAAI,IAAI;IAMb,KAAK,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI;IAMvB,OAAO,IAAI,IAAI;IAIf,iBAAiB,IAAI,eAAe,GAAG,SAAS;IAIhD,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE;CAG1D"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StateMachine = void 0;
4
+ const events_1 = require("events");
5
+ class StateMachine extends events_1.EventEmitter {
6
+ _state = "IDLE";
7
+ _history = [];
8
+ _stateStartTime = Date.now();
9
+ get state() {
10
+ return this._state;
11
+ }
12
+ get history() {
13
+ return this._history;
14
+ }
15
+ get stateElapsedMs() {
16
+ return Date.now() - this._stateStartTime;
17
+ }
18
+ transition(to) {
19
+ const from = this._state;
20
+ const timestamp = Date.now();
21
+ const transition = { from, to, timestamp };
22
+ this._history.push(transition);
23
+ this._state = to;
24
+ this._stateStartTime = timestamp;
25
+ this.emit("stateChange", transition);
26
+ }
27
+ transitionTo(...states) {
28
+ for (const state of states) {
29
+ this.transition(state);
30
+ }
31
+ }
32
+ isIn(...states) {
33
+ return states.includes(this._state);
34
+ }
35
+ reset() {
36
+ this._state = "IDLE";
37
+ this._history = [];
38
+ this._stateStartTime = Date.now();
39
+ }
40
+ error(err) {
41
+ const previousState = this._state;
42
+ this.transition("ERROR");
43
+ this.emit("error", err, previousState);
44
+ }
45
+ recover() {
46
+ this.transition("RECOVERY");
47
+ }
48
+ getLastTransition() {
49
+ return this._history[this._history.length - 1];
50
+ }
51
+ getTransitionsSince(timestamp) {
52
+ return this._history.filter(t => t.timestamp >= timestamp);
53
+ }
54
+ }
55
+ exports.StateMachine = StateMachine;
56
+ //# sourceMappingURL=StateMachine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StateMachine.js","sourceRoot":"","sources":["../../src/driver/StateMachine.ts"],"names":[],"mappings":";;;AAAA,mCAAsC;AA2BtC,MAAa,YAAa,SAAQ,qBAAY;IACpC,MAAM,GAAa,MAAM,CAAC;IAC1B,QAAQ,GAAsB,EAAE,CAAC;IACjC,eAAe,GAAW,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7C,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC;IAC3C,CAAC;IAED,UAAU,CAAC,EAAY;QACrB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,MAAM,UAAU,GAAoB,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC;QAC5D,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QAEjC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;IACvC,CAAC;IAED,YAAY,CAAC,GAAG,MAAkB;QAChC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,GAAG,MAAkB;QACxB,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,GAAU;QACd,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC;IACzC,CAAC;IAED,OAAO;QACL,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,mBAAmB,CAAC,SAAiB;QACnC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,SAAS,CAAC,CAAC;IAC7D,CAAC;CACF;AA9DD,oCA8DC"}
@@ -0,0 +1,73 @@
1
+ import { EventEmitter } from "events";
2
+ import { ScreenSnapshot } from "../term/ScreenSnapshot.js";
3
+ import { TuiProfile } from "./TuiProfile.js";
4
+ import { TuiState } from "./StateMachine.js";
5
+ export interface TuiDriverOptions {
6
+ profile: TuiProfile;
7
+ debug?: boolean;
8
+ onSnapshot?: (snapshot: ScreenSnapshot, state: TuiState) => void;
9
+ onSignals?: (signals: TuiScreenSignals, snapshot: ScreenSnapshot, state: TuiState) => void;
10
+ }
11
+ export interface AskResult {
12
+ success: boolean;
13
+ answer: string;
14
+ beforeSnapshot: ScreenSnapshot;
15
+ afterSnapshot: ScreenSnapshot;
16
+ elapsedMs: number;
17
+ error?: Error;
18
+ signals?: TuiScreenSignals;
19
+ promptLine?: string;
20
+ replyText?: string;
21
+ replyBlocks?: string[];
22
+ replyInProgress?: boolean;
23
+ statusLine?: string;
24
+ statusDoneLine?: string;
25
+ }
26
+ export interface TuiScreenSignals {
27
+ hasPrompt: boolean;
28
+ promptLine?: string;
29
+ replyText?: string;
30
+ replyBlocks?: string[];
31
+ replyInProgress: boolean;
32
+ statusLine?: string;
33
+ statusDoneLine?: string;
34
+ }
35
+ export declare class TuiDriver extends EventEmitter {
36
+ private pty;
37
+ private screen;
38
+ private expect;
39
+ private stateMachine;
40
+ private profile;
41
+ private debug;
42
+ private onSnapshot?;
43
+ private onSignals?;
44
+ private isBooted;
45
+ constructor(options: TuiDriverOptions);
46
+ private setupEventHandlers;
47
+ private log;
48
+ get state(): TuiState;
49
+ get running(): boolean;
50
+ boot(): Promise<void>;
51
+ ensureReady(): Promise<void>;
52
+ ask(prompt: string): Promise<AskResult>;
53
+ private prepareTurn;
54
+ private typePrompt;
55
+ private submit;
56
+ private waitStreamStart;
57
+ private waitStreamEnd;
58
+ private extractAnswer;
59
+ private recovery;
60
+ private restart;
61
+ private captureSnapshot;
62
+ snapshot(): ScreenSnapshot;
63
+ getSignals(snapshot?: ScreenSnapshot): TuiScreenSignals;
64
+ sendKeys(keys: string[]): Promise<void>;
65
+ write(data: string): Promise<void>;
66
+ kill(): void;
67
+ private sleep;
68
+ private resolveTimeout;
69
+ private waitForScrollbackIdle;
70
+ private findLastMatch;
71
+ private extractReplyBlocks;
72
+ }
73
+ //# sourceMappingURL=TuiDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TuiDriver.d.ts","sourceRoot":"","sources":["../../src/driver/TuiDriver.ts"],"names":[],"mappings":"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"}