@moejay/wrightty 0.0.0 → 0.1.1

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 (94) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.js +144 -0
  3. package/dist/client.d.ts +14 -0
  4. package/dist/client.js +83 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.js +8 -0
  7. package/dist/terminal.d.ts +48 -0
  8. package/dist/terminal.js +210 -0
  9. package/dist/types.d.ts +90 -0
  10. package/dist/types.js +3 -0
  11. package/package.json +38 -15
  12. package/.github/workflows/ci.yml +0 -90
  13. package/.github/workflows/release.yml +0 -177
  14. package/Cargo.lock +0 -2662
  15. package/Cargo.toml +0 -38
  16. package/PROTOCOL.md +0 -1351
  17. package/README.md +0 -386
  18. package/agents/ceo/AGENTS.md +0 -24
  19. package/agents/ceo/HEARTBEAT.md +0 -72
  20. package/agents/ceo/SOUL.md +0 -33
  21. package/agents/ceo/TOOLS.md +0 -3
  22. package/agents/founding-engineer/AGENTS.md +0 -44
  23. package/crates/wrightty/Cargo.toml +0 -43
  24. package/crates/wrightty/src/client_cmds.rs +0 -366
  25. package/crates/wrightty/src/discover.rs +0 -78
  26. package/crates/wrightty/src/main.rs +0 -100
  27. package/crates/wrightty/src/server.rs +0 -100
  28. package/crates/wrightty/src/term.rs +0 -338
  29. package/crates/wrightty-bridge-ghostty/Cargo.toml +0 -27
  30. package/crates/wrightty-bridge-ghostty/src/ghostty.rs +0 -422
  31. package/crates/wrightty-bridge-ghostty/src/lib.rs +0 -2
  32. package/crates/wrightty-bridge-ghostty/src/main.rs +0 -146
  33. package/crates/wrightty-bridge-ghostty/src/rpc.rs +0 -307
  34. package/crates/wrightty-bridge-kitty/Cargo.toml +0 -26
  35. package/crates/wrightty-bridge-kitty/src/kitty.rs +0 -269
  36. package/crates/wrightty-bridge-kitty/src/lib.rs +0 -2
  37. package/crates/wrightty-bridge-kitty/src/main.rs +0 -124
  38. package/crates/wrightty-bridge-kitty/src/rpc.rs +0 -304
  39. package/crates/wrightty-bridge-tmux/Cargo.toml +0 -26
  40. package/crates/wrightty-bridge-tmux/src/lib.rs +0 -2
  41. package/crates/wrightty-bridge-tmux/src/main.rs +0 -119
  42. package/crates/wrightty-bridge-tmux/src/rpc.rs +0 -291
  43. package/crates/wrightty-bridge-tmux/src/tmux.rs +0 -215
  44. package/crates/wrightty-bridge-wezterm/Cargo.toml +0 -26
  45. package/crates/wrightty-bridge-wezterm/src/lib.rs +0 -2
  46. package/crates/wrightty-bridge-wezterm/src/main.rs +0 -119
  47. package/crates/wrightty-bridge-wezterm/src/rpc.rs +0 -339
  48. package/crates/wrightty-bridge-wezterm/src/wezterm.rs +0 -190
  49. package/crates/wrightty-bridge-zellij/Cargo.toml +0 -27
  50. package/crates/wrightty-bridge-zellij/src/lib.rs +0 -2
  51. package/crates/wrightty-bridge-zellij/src/main.rs +0 -125
  52. package/crates/wrightty-bridge-zellij/src/rpc.rs +0 -328
  53. package/crates/wrightty-bridge-zellij/src/zellij.rs +0 -199
  54. package/crates/wrightty-client/Cargo.toml +0 -16
  55. package/crates/wrightty-client/src/client.rs +0 -254
  56. package/crates/wrightty-client/src/lib.rs +0 -2
  57. package/crates/wrightty-core/Cargo.toml +0 -21
  58. package/crates/wrightty-core/src/input.rs +0 -212
  59. package/crates/wrightty-core/src/lib.rs +0 -4
  60. package/crates/wrightty-core/src/screen.rs +0 -325
  61. package/crates/wrightty-core/src/session.rs +0 -249
  62. package/crates/wrightty-core/src/session_manager.rs +0 -77
  63. package/crates/wrightty-protocol/Cargo.toml +0 -13
  64. package/crates/wrightty-protocol/src/error.rs +0 -8
  65. package/crates/wrightty-protocol/src/events.rs +0 -138
  66. package/crates/wrightty-protocol/src/lib.rs +0 -4
  67. package/crates/wrightty-protocol/src/methods.rs +0 -321
  68. package/crates/wrightty-protocol/src/types.rs +0 -201
  69. package/crates/wrightty-server/Cargo.toml +0 -23
  70. package/crates/wrightty-server/src/lib.rs +0 -2
  71. package/crates/wrightty-server/src/main.rs +0 -65
  72. package/crates/wrightty-server/src/rpc.rs +0 -455
  73. package/crates/wrightty-server/src/state.rs +0 -39
  74. package/examples/basic_command.py +0 -53
  75. package/examples/interactive_tui.py +0 -86
  76. package/examples/record_session.py +0 -96
  77. package/install.sh +0 -81
  78. package/sdks/node/package-lock.json +0 -85
  79. package/sdks/node/package.json +0 -44
  80. package/sdks/node/src/client.ts +0 -94
  81. package/sdks/node/src/index.ts +0 -19
  82. package/sdks/node/src/terminal.ts +0 -258
  83. package/sdks/node/src/types.ts +0 -105
  84. package/sdks/node/tsconfig.json +0 -17
  85. package/sdks/python/README.md +0 -96
  86. package/sdks/python/pyproject.toml +0 -42
  87. package/sdks/python/wrightty/__init__.py +0 -6
  88. package/sdks/python/wrightty/cli.py +0 -210
  89. package/sdks/python/wrightty/client.py +0 -136
  90. package/sdks/python/wrightty/mcp_server.py +0 -434
  91. package/sdks/python/wrightty/terminal.py +0 -333
  92. package/skills/wrightty/SKILL.md +0 -261
  93. package/src/lib.rs +0 -1
  94. package/tests/integration_test.rs +0 -618
@@ -1,254 +0,0 @@
1
- use jsonrpsee::core::client::ClientT;
2
- use jsonrpsee::core::params::ObjectParams;
3
- use jsonrpsee::core::traits::ToRpcParams;
4
- use jsonrpsee::ws_client::{WsClient, WsClientBuilder};
5
- use serde::Serialize;
6
-
7
- use wrightty_protocol::methods::*;
8
- use wrightty_protocol::types::*;
9
-
10
- pub struct WrighttyClient {
11
- client: WsClient,
12
- }
13
-
14
- /// Wrapper to serialize a struct as named JSON-RPC params (object).
15
- struct NamedParams(serde_json::Value);
16
-
17
- impl ToRpcParams for NamedParams {
18
- fn to_rpc_params(
19
- self,
20
- ) -> Result<Option<Box<serde_json::value::RawValue>>, serde_json::Error> {
21
- let s = serde_json::to_string(&self.0)?;
22
- let raw = serde_json::value::RawValue::from_string(s)?;
23
- Ok(Some(raw))
24
- }
25
- }
26
-
27
- fn to_params<T: Serialize>(val: &T) -> Result<NamedParams, Box<dyn std::error::Error>> {
28
- Ok(NamedParams(serde_json::to_value(val)?))
29
- }
30
-
31
- impl WrighttyClient {
32
- pub async fn connect(url: &str) -> Result<Self, Box<dyn std::error::Error>> {
33
- let client = WsClientBuilder::default().build(url).await?;
34
- Ok(Self { client })
35
- }
36
-
37
- pub async fn get_info(&self) -> Result<ServerInfo, Box<dyn std::error::Error>> {
38
- let result: GetInfoResult = self
39
- .client
40
- .request("Wrightty.getInfo", ObjectParams::new())
41
- .await?;
42
- Ok(result.info)
43
- }
44
-
45
- pub async fn session_create(
46
- &self,
47
- params: SessionCreateParams,
48
- ) -> Result<String, Box<dyn std::error::Error>> {
49
- let result: SessionCreateResult = self
50
- .client
51
- .request("Session.create", to_params(&params)?)
52
- .await?;
53
- Ok(result.session_id)
54
- }
55
-
56
- pub async fn session_destroy(
57
- &self,
58
- session_id: &str,
59
- ) -> Result<(), Box<dyn std::error::Error>> {
60
- let params = SessionDestroyParams {
61
- session_id: session_id.to_string(),
62
- signal: None,
63
- };
64
- let _: SessionDestroyResult = self
65
- .client
66
- .request("Session.destroy", to_params(&params)?)
67
- .await?;
68
- Ok(())
69
- }
70
-
71
- pub async fn session_list(&self) -> Result<Vec<SessionInfo>, Box<dyn std::error::Error>> {
72
- let result: SessionListResult = self
73
- .client
74
- .request("Session.list", ObjectParams::new())
75
- .await?;
76
- Ok(result.sessions)
77
- }
78
-
79
- pub async fn send_keys(
80
- &self,
81
- session_id: &str,
82
- keys: Vec<KeyInput>,
83
- ) -> Result<(), Box<dyn std::error::Error>> {
84
- let params = InputSendKeysParams {
85
- session_id: session_id.to_string(),
86
- keys,
87
- };
88
- let _: serde_json::Value = self
89
- .client
90
- .request("Input.sendKeys", to_params(&params)?)
91
- .await?;
92
- Ok(())
93
- }
94
-
95
- pub async fn send_text(
96
- &self,
97
- session_id: &str,
98
- text: &str,
99
- ) -> Result<(), Box<dyn std::error::Error>> {
100
- let params = InputSendTextParams {
101
- session_id: session_id.to_string(),
102
- text: text.to_string(),
103
- };
104
- let _: serde_json::Value = self
105
- .client
106
- .request("Input.sendText", to_params(&params)?)
107
- .await?;
108
- Ok(())
109
- }
110
-
111
- pub async fn get_text(
112
- &self,
113
- session_id: &str,
114
- ) -> Result<String, Box<dyn std::error::Error>> {
115
- let params = ScreenGetTextParams {
116
- session_id: session_id.to_string(),
117
- region: None,
118
- trim_trailing_whitespace: true,
119
- };
120
- let result: ScreenGetTextResult = self
121
- .client
122
- .request("Screen.getText", to_params(&params)?)
123
- .await?;
124
- Ok(result.text)
125
- }
126
-
127
- pub async fn resize(
128
- &self,
129
- session_id: &str,
130
- cols: u16,
131
- rows: u16,
132
- ) -> Result<(), Box<dyn std::error::Error>> {
133
- let params = TerminalResizeParams {
134
- session_id: session_id.to_string(),
135
- cols,
136
- rows,
137
- };
138
- let _: serde_json::Value = self
139
- .client
140
- .request("Terminal.resize", to_params(&params)?)
141
- .await?;
142
- Ok(())
143
- }
144
-
145
- pub async fn get_contents(
146
- &self,
147
- session_id: &str,
148
- ) -> Result<ScreenGetContentsResult, Box<dyn std::error::Error>> {
149
- let params = ScreenGetContentsParams {
150
- session_id: session_id.to_string(),
151
- region: None,
152
- };
153
- let result: ScreenGetContentsResult = self
154
- .client
155
- .request("Screen.getContents", to_params(&params)?)
156
- .await?;
157
- Ok(result)
158
- }
159
-
160
- pub async fn get_scrollback(
161
- &self,
162
- session_id: &str,
163
- lines: u32,
164
- offset: u32,
165
- ) -> Result<ScreenGetScrollbackResult, Box<dyn std::error::Error>> {
166
- let params = ScreenGetScrollbackParams {
167
- session_id: session_id.to_string(),
168
- lines,
169
- offset,
170
- };
171
- let result: ScreenGetScrollbackResult = self
172
- .client
173
- .request("Screen.getScrollback", to_params(&params)?)
174
- .await?;
175
- Ok(result)
176
- }
177
-
178
- pub async fn screenshot(
179
- &self,
180
- session_id: &str,
181
- format: ScreenshotFormat,
182
- ) -> Result<ScreenScreenshotResult, Box<dyn std::error::Error>> {
183
- let params = ScreenScreenshotParams {
184
- session_id: session_id.to_string(),
185
- format,
186
- theme: None,
187
- font: None,
188
- };
189
- let result: ScreenScreenshotResult = self
190
- .client
191
- .request("Screen.screenshot", to_params(&params)?)
192
- .await?;
193
- Ok(result)
194
- }
195
-
196
- pub async fn wait_for_text(
197
- &self,
198
- session_id: &str,
199
- pattern: &str,
200
- is_regex: bool,
201
- timeout_ms: u64,
202
- ) -> Result<ScreenWaitForTextResult, Box<dyn std::error::Error>> {
203
- let params = ScreenWaitForTextParams {
204
- session_id: session_id.to_string(),
205
- pattern: pattern.to_string(),
206
- is_regex,
207
- region: None,
208
- timeout: timeout_ms,
209
- interval: 50,
210
- };
211
- let result: ScreenWaitForTextResult = self
212
- .client
213
- .request("Screen.waitForText", to_params(&params)?)
214
- .await?;
215
- Ok(result)
216
- }
217
-
218
- pub async fn send_mouse(
219
- &self,
220
- session_id: &str,
221
- event: &str,
222
- button: &str,
223
- row: u32,
224
- col: u32,
225
- ) -> Result<(), Box<dyn std::error::Error>> {
226
- let params = InputSendMouseParams {
227
- session_id: session_id.to_string(),
228
- event: event.to_string(),
229
- button: button.to_string(),
230
- row,
231
- col,
232
- modifiers: vec![],
233
- };
234
- let _: serde_json::Value = self
235
- .client
236
- .request("Input.sendMouse", to_params(&params)?)
237
- .await?;
238
- Ok(())
239
- }
240
-
241
- pub async fn get_size(
242
- &self,
243
- session_id: &str,
244
- ) -> Result<(u16, u16), Box<dyn std::error::Error>> {
245
- let params = TerminalGetSizeParams {
246
- session_id: session_id.to_string(),
247
- };
248
- let result: TerminalGetSizeResult = self
249
- .client
250
- .request("Terminal.getSize", to_params(&params)?)
251
- .await?;
252
- Ok((result.cols, result.rows))
253
- }
254
- }
@@ -1,2 +0,0 @@
1
- pub mod client;
2
- pub use client::WrighttyClient;
@@ -1,21 +0,0 @@
1
- [package]
2
- name = "wrightty-core"
3
- version.workspace = true
4
- edition.workspace = true
5
- license.workspace = true
6
- authors.workspace = true
7
- repository.workspace = true
8
- homepage.workspace = true
9
- description = "Core terminal engine for Wrightty"
10
-
11
- [dependencies]
12
- wrightty-protocol = { version = "0.1.0", path = "../wrightty-protocol" }
13
- alacritty_terminal = "0.25.1"
14
- vte = { version = "0.15", features = ["ansi"] }
15
- portable-pty = "0.9"
16
- tokio = { version = "1", features = ["full"] }
17
- uuid = { version = "1", features = ["v4"] }
18
- regex = "1"
19
- log = "0.4"
20
- thiserror = "2"
21
- base64 = "0.22"
@@ -1,212 +0,0 @@
1
- use wrightty_protocol::types::{KeyEvent, KeyInput, KeyType, Modifier};
2
-
3
- /// Encode a sequence of KeyInput values into bytes to write to a PTY.
4
- pub fn encode_keys(keys: &[KeyInput]) -> Vec<u8> {
5
- let mut out = Vec::new();
6
- for key in keys {
7
- match key {
8
- KeyInput::Shorthand(s) => encode_shorthand(s, &mut out),
9
- KeyInput::Structured(event) => encode_key_event(event, &mut out),
10
- }
11
- }
12
- out
13
- }
14
-
15
- fn encode_shorthand(s: &str, out: &mut Vec<u8>) {
16
- // Check for modifier combos like "Ctrl+c"
17
- if let Some((modifier_str, key_str)) = s.split_once('+') {
18
- let modifier = match modifier_str {
19
- "Ctrl" => Some(Modifier::Ctrl),
20
- "Alt" => Some(Modifier::Alt),
21
- "Shift" => Some(Modifier::Shift),
22
- "Meta" => Some(Modifier::Meta),
23
- _ => None,
24
- };
25
-
26
- if let Some(m) = modifier {
27
- // Try to parse the key part as a named key or single char
28
- if key_str.len() == 1 {
29
- let event = KeyEvent {
30
- key: KeyType::Char,
31
- char: Some(key_str.to_string()),
32
- n: None,
33
- modifiers: vec![m],
34
- };
35
- encode_key_event(&event, out);
36
- return;
37
- }
38
- // Named key with modifier
39
- if let Some(key_type) = parse_named_key(key_str) {
40
- let event = KeyEvent {
41
- key: key_type,
42
- char: None,
43
- n: None,
44
- modifiers: vec![m],
45
- };
46
- encode_key_event(&event, out);
47
- return;
48
- }
49
- }
50
- }
51
-
52
- // Check named keys
53
- if let Some(key_type) = parse_named_key(s) {
54
- let event = KeyEvent {
55
- key: key_type,
56
- char: None,
57
- n: None,
58
- modifiers: vec![],
59
- };
60
- encode_key_event(&event, out);
61
- return;
62
- }
63
-
64
- // Single character
65
- if s.len() == 1 {
66
- out.extend_from_slice(s.as_bytes());
67
- return;
68
- }
69
-
70
- // Function keys like "F5"
71
- if let Some(rest) = s.strip_prefix('F') && let Ok(n) = rest.parse::<u8>() {
72
- let event = KeyEvent {
73
- key: KeyType::F,
74
- char: None,
75
- n: Some(n),
76
- modifiers: vec![],
77
- };
78
- encode_key_event(&event, out);
79
- return;
80
- }
81
-
82
- // Fallback: send as raw text
83
- out.extend_from_slice(s.as_bytes());
84
- }
85
-
86
- fn parse_named_key(s: &str) -> Option<KeyType> {
87
- match s {
88
- "Enter" => Some(KeyType::Enter),
89
- "Tab" => Some(KeyType::Tab),
90
- "Backspace" => Some(KeyType::Backspace),
91
- "Delete" => Some(KeyType::Delete),
92
- "Escape" => Some(KeyType::Escape),
93
- "ArrowUp" => Some(KeyType::ArrowUp),
94
- "ArrowDown" => Some(KeyType::ArrowDown),
95
- "ArrowLeft" => Some(KeyType::ArrowLeft),
96
- "ArrowRight" => Some(KeyType::ArrowRight),
97
- "Home" => Some(KeyType::Home),
98
- "End" => Some(KeyType::End),
99
- "PageUp" => Some(KeyType::PageUp),
100
- "PageDown" => Some(KeyType::PageDown),
101
- "Insert" => Some(KeyType::Insert),
102
- _ => None,
103
- }
104
- }
105
-
106
- fn encode_key_event(event: &KeyEvent, out: &mut Vec<u8>) {
107
- let has_ctrl = event.modifiers.iter().any(|m| matches!(m, Modifier::Ctrl));
108
- let has_alt = event.modifiers.iter().any(|m| matches!(m, Modifier::Alt));
109
-
110
- match &event.key {
111
- KeyType::Char => {
112
- if let Some(ref ch) = event.char && let Some(c) = ch.chars().next() {
113
- if has_ctrl {
114
- // Ctrl+letter = letter & 0x1f
115
- let ctrl_byte = (c.to_ascii_lowercase() as u8) & 0x1f;
116
- if has_alt {
117
- out.push(0x1b);
118
- }
119
- out.push(ctrl_byte);
120
- } else if has_alt {
121
- out.push(0x1b);
122
- out.extend_from_slice(ch.as_bytes());
123
- } else {
124
- out.extend_from_slice(ch.as_bytes());
125
- }
126
- }
127
- }
128
- KeyType::Enter => {
129
- if has_alt {
130
- out.push(0x1b);
131
- }
132
- out.push(b'\r');
133
- }
134
- KeyType::Tab => {
135
- if has_alt {
136
- out.push(0x1b);
137
- }
138
- out.push(b'\t');
139
- }
140
- KeyType::Backspace => {
141
- if has_alt {
142
- out.push(0x1b);
143
- }
144
- out.push(0x7f);
145
- }
146
- KeyType::Escape => {
147
- out.push(0x1b);
148
- }
149
- KeyType::Delete => {
150
- if has_alt {
151
- out.push(0x1b);
152
- }
153
- out.extend_from_slice(b"\x1b[3~");
154
- }
155
- // Arrow keys — normal mode (not application mode for now)
156
- KeyType::ArrowUp => encode_csi_key(b'A', has_alt, out),
157
- KeyType::ArrowDown => encode_csi_key(b'B', has_alt, out),
158
- KeyType::ArrowRight => encode_csi_key(b'C', has_alt, out),
159
- KeyType::ArrowLeft => encode_csi_key(b'D', has_alt, out),
160
- KeyType::Home => encode_csi_key(b'H', has_alt, out),
161
- KeyType::End => encode_csi_key(b'F', has_alt, out),
162
- KeyType::PageUp => {
163
- if has_alt {
164
- out.push(0x1b);
165
- }
166
- out.extend_from_slice(b"\x1b[5~");
167
- }
168
- KeyType::PageDown => {
169
- if has_alt {
170
- out.push(0x1b);
171
- }
172
- out.extend_from_slice(b"\x1b[6~");
173
- }
174
- KeyType::Insert => {
175
- if has_alt {
176
- out.push(0x1b);
177
- }
178
- out.extend_from_slice(b"\x1b[2~");
179
- }
180
- KeyType::F => {
181
- let n = event.n.unwrap_or(1);
182
- let seq = match n {
183
- 1 => b"\x1bOP".as_slice(),
184
- 2 => b"\x1bOQ",
185
- 3 => b"\x1bOR",
186
- 4 => b"\x1bOS",
187
- 5 => b"\x1b[15~",
188
- 6 => b"\x1b[17~",
189
- 7 => b"\x1b[18~",
190
- 8 => b"\x1b[19~",
191
- 9 => b"\x1b[20~",
192
- 10 => b"\x1b[21~",
193
- 11 => b"\x1b[23~",
194
- 12 => b"\x1b[24~",
195
- _ => return,
196
- };
197
- if has_alt {
198
- out.push(0x1b);
199
- }
200
- out.extend_from_slice(seq);
201
- }
202
- }
203
- }
204
-
205
- fn encode_csi_key(code: u8, alt: bool, out: &mut Vec<u8>) {
206
- if alt {
207
- out.push(0x1b);
208
- }
209
- out.push(0x1b);
210
- out.push(b'[');
211
- out.push(code);
212
- }
@@ -1,4 +0,0 @@
1
- pub mod session;
2
- pub mod session_manager;
3
- pub mod screen;
4
- pub mod input;