flaio-cli 0.3.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 (271) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +461 -0
  3. package/dist/agents/agent-detector.d.ts +21 -0
  4. package/dist/agents/agent-detector.d.ts.map +1 -0
  5. package/dist/agents/agent-detector.js +109 -0
  6. package/dist/agents/agent-detector.js.map +1 -0
  7. package/dist/agents/agent-registry.d.ts +6 -0
  8. package/dist/agents/agent-registry.d.ts.map +1 -0
  9. package/dist/agents/agent-registry.js +25 -0
  10. package/dist/agents/agent-registry.js.map +1 -0
  11. package/dist/agents/agent-session.d.ts +60 -0
  12. package/dist/agents/agent-session.d.ts.map +1 -0
  13. package/dist/agents/agent-session.js +251 -0
  14. package/dist/agents/agent-session.js.map +1 -0
  15. package/dist/agents/drivers/base-driver.d.ts +37 -0
  16. package/dist/agents/drivers/base-driver.d.ts.map +1 -0
  17. package/dist/agents/drivers/base-driver.js +18 -0
  18. package/dist/agents/drivers/base-driver.js.map +1 -0
  19. package/dist/agents/drivers/claude-driver.d.ts +23 -0
  20. package/dist/agents/drivers/claude-driver.d.ts.map +1 -0
  21. package/dist/agents/drivers/claude-driver.js +61 -0
  22. package/dist/agents/drivers/claude-driver.js.map +1 -0
  23. package/dist/agents/drivers/gemini-driver.d.ts +23 -0
  24. package/dist/agents/drivers/gemini-driver.d.ts.map +1 -0
  25. package/dist/agents/drivers/gemini-driver.js +60 -0
  26. package/dist/agents/drivers/gemini-driver.js.map +1 -0
  27. package/dist/agents/session-metadata.d.ts +33 -0
  28. package/dist/agents/session-metadata.d.ts.map +1 -0
  29. package/dist/agents/session-metadata.js +34 -0
  30. package/dist/agents/session-metadata.js.map +1 -0
  31. package/dist/agents/sideband/hook-scripts.d.ts +29 -0
  32. package/dist/agents/sideband/hook-scripts.d.ts.map +1 -0
  33. package/dist/agents/sideband/hook-scripts.js +259 -0
  34. package/dist/agents/sideband/hook-scripts.js.map +1 -0
  35. package/dist/agents/sideband/sideband-receiver.d.ts +37 -0
  36. package/dist/agents/sideband/sideband-receiver.d.ts.map +1 -0
  37. package/dist/agents/sideband/sideband-receiver.js +203 -0
  38. package/dist/agents/sideband/sideband-receiver.js.map +1 -0
  39. package/dist/agents/sideband/status-resolver.d.ts +55 -0
  40. package/dist/agents/sideband/status-resolver.d.ts.map +1 -0
  41. package/dist/agents/sideband/status-resolver.js +194 -0
  42. package/dist/agents/sideband/status-resolver.js.map +1 -0
  43. package/dist/app.d.ts +3 -0
  44. package/dist/app.d.ts.map +1 -0
  45. package/dist/app.js +94 -0
  46. package/dist/app.js.map +1 -0
  47. package/dist/cli.d.ts +3 -0
  48. package/dist/cli.d.ts.map +1 -0
  49. package/dist/cli.js +188 -0
  50. package/dist/cli.js.map +1 -0
  51. package/dist/config/config.d.ts +341 -0
  52. package/dist/config/config.d.ts.map +1 -0
  53. package/dist/config/config.js +94 -0
  54. package/dist/config/config.js.map +1 -0
  55. package/dist/config/defaults.d.ts +33 -0
  56. package/dist/config/defaults.d.ts.map +1 -0
  57. package/dist/config/defaults.js +33 -0
  58. package/dist/config/defaults.js.map +1 -0
  59. package/dist/connectors/adapters/discord-adapter.d.ts +25 -0
  60. package/dist/connectors/adapters/discord-adapter.d.ts.map +1 -0
  61. package/dist/connectors/adapters/discord-adapter.js +154 -0
  62. package/dist/connectors/adapters/discord-adapter.js.map +1 -0
  63. package/dist/connectors/adapters/slack-adapter.d.ts +38 -0
  64. package/dist/connectors/adapters/slack-adapter.d.ts.map +1 -0
  65. package/dist/connectors/adapters/slack-adapter.js +502 -0
  66. package/dist/connectors/adapters/slack-adapter.js.map +1 -0
  67. package/dist/connectors/adapters/telegram-adapter.d.ts +25 -0
  68. package/dist/connectors/adapters/telegram-adapter.d.ts.map +1 -0
  69. package/dist/connectors/adapters/telegram-adapter.js +164 -0
  70. package/dist/connectors/adapters/telegram-adapter.js.map +1 -0
  71. package/dist/connectors/connector-interface.d.ts +41 -0
  72. package/dist/connectors/connector-interface.d.ts.map +1 -0
  73. package/dist/connectors/connector-interface.js +2 -0
  74. package/dist/connectors/connector-interface.js.map +1 -0
  75. package/dist/connectors/connector-manager.d.ts +24 -0
  76. package/dist/connectors/connector-manager.d.ts.map +1 -0
  77. package/dist/connectors/connector-manager.js +82 -0
  78. package/dist/connectors/connector-manager.js.map +1 -0
  79. package/dist/connectors/debug.d.ts +3 -0
  80. package/dist/connectors/debug.d.ts.map +1 -0
  81. package/dist/connectors/debug.js +16 -0
  82. package/dist/connectors/debug.js.map +1 -0
  83. package/dist/hooks/hook-server.d.ts +27 -0
  84. package/dist/hooks/hook-server.d.ts.map +1 -0
  85. package/dist/hooks/hook-server.js +149 -0
  86. package/dist/hooks/hook-server.js.map +1 -0
  87. package/dist/hooks/hook.d.ts +10 -0
  88. package/dist/hooks/hook.d.ts.map +1 -0
  89. package/dist/hooks/hook.js +58 -0
  90. package/dist/hooks/hook.js.map +1 -0
  91. package/dist/hooks/install.d.ts +8 -0
  92. package/dist/hooks/install.d.ts.map +1 -0
  93. package/dist/hooks/install.js +160 -0
  94. package/dist/hooks/install.js.map +1 -0
  95. package/dist/hooks/notification-hook.d.ts +9 -0
  96. package/dist/hooks/notification-hook.d.ts.map +1 -0
  97. package/dist/hooks/notification-hook.js +38 -0
  98. package/dist/hooks/notification-hook.js.map +1 -0
  99. package/dist/hooks/post-tool-hook.d.ts +9 -0
  100. package/dist/hooks/post-tool-hook.d.ts.map +1 -0
  101. package/dist/hooks/post-tool-hook.js +39 -0
  102. package/dist/hooks/post-tool-hook.js.map +1 -0
  103. package/dist/hooks/stop-hook.d.ts +9 -0
  104. package/dist/hooks/stop-hook.d.ts.map +1 -0
  105. package/dist/hooks/stop-hook.js +37 -0
  106. package/dist/hooks/stop-hook.js.map +1 -0
  107. package/dist/portal/ansi-renderer.d.ts +15 -0
  108. package/dist/portal/ansi-renderer.d.ts.map +1 -0
  109. package/dist/portal/ansi-renderer.js +75 -0
  110. package/dist/portal/ansi-renderer.js.map +1 -0
  111. package/dist/portal/portal-client.d.ts +18 -0
  112. package/dist/portal/portal-client.d.ts.map +1 -0
  113. package/dist/portal/portal-client.js +335 -0
  114. package/dist/portal/portal-client.js.map +1 -0
  115. package/dist/portal/portal-picker.d.ts +8 -0
  116. package/dist/portal/portal-picker.d.ts.map +1 -0
  117. package/dist/portal/portal-picker.js +145 -0
  118. package/dist/portal/portal-picker.js.map +1 -0
  119. package/dist/portal/portal-server.d.ts +24 -0
  120. package/dist/portal/portal-server.d.ts.map +1 -0
  121. package/dist/portal/portal-server.js +330 -0
  122. package/dist/portal/portal-server.js.map +1 -0
  123. package/dist/portal/shared.d.ts +79 -0
  124. package/dist/portal/shared.d.ts.map +1 -0
  125. package/dist/portal/shared.js +5 -0
  126. package/dist/portal/shared.js.map +1 -0
  127. package/dist/relay/rate-limiter.d.ts +16 -0
  128. package/dist/relay/rate-limiter.d.ts.map +1 -0
  129. package/dist/relay/rate-limiter.js +37 -0
  130. package/dist/relay/rate-limiter.js.map +1 -0
  131. package/dist/relay/relay-auth.d.ts +29 -0
  132. package/dist/relay/relay-auth.d.ts.map +1 -0
  133. package/dist/relay/relay-auth.js +129 -0
  134. package/dist/relay/relay-auth.js.map +1 -0
  135. package/dist/relay/relay-client.d.ts +52 -0
  136. package/dist/relay/relay-client.d.ts.map +1 -0
  137. package/dist/relay/relay-client.js +1102 -0
  138. package/dist/relay/relay-client.js.map +1 -0
  139. package/dist/relay/relay-crypto.d.ts +29 -0
  140. package/dist/relay/relay-crypto.d.ts.map +1 -0
  141. package/dist/relay/relay-crypto.js +100 -0
  142. package/dist/relay/relay-crypto.js.map +1 -0
  143. package/dist/relay/relay-message-schemas.d.ts +276 -0
  144. package/dist/relay/relay-message-schemas.d.ts.map +1 -0
  145. package/dist/relay/relay-message-schemas.js +137 -0
  146. package/dist/relay/relay-message-schemas.js.map +1 -0
  147. package/dist/relay/relay-protocol.d.ts +444 -0
  148. package/dist/relay/relay-protocol.d.ts.map +1 -0
  149. package/dist/relay/relay-protocol.js +15 -0
  150. package/dist/relay/relay-protocol.js.map +1 -0
  151. package/dist/relay/relay-store.d.ts +23 -0
  152. package/dist/relay/relay-store.d.ts.map +1 -0
  153. package/dist/relay/relay-store.js +54 -0
  154. package/dist/relay/relay-store.js.map +1 -0
  155. package/dist/relay/ticket-tracker.d.ts +18 -0
  156. package/dist/relay/ticket-tracker.d.ts.map +1 -0
  157. package/dist/relay/ticket-tracker.js +58 -0
  158. package/dist/relay/ticket-tracker.js.map +1 -0
  159. package/dist/store/app-store.d.ts +66 -0
  160. package/dist/store/app-store.d.ts.map +1 -0
  161. package/dist/store/app-store.js +227 -0
  162. package/dist/store/app-store.js.map +1 -0
  163. package/dist/store/connector-store.d.ts +21 -0
  164. package/dist/store/connector-store.d.ts.map +1 -0
  165. package/dist/store/connector-store.js +591 -0
  166. package/dist/store/connector-store.js.map +1 -0
  167. package/dist/store/portal-store.d.ts +5 -0
  168. package/dist/store/portal-store.d.ts.map +1 -0
  169. package/dist/store/portal-store.js +5 -0
  170. package/dist/store/portal-store.js.map +1 -0
  171. package/dist/store/settings-store.d.ts +13 -0
  172. package/dist/store/settings-store.d.ts.map +1 -0
  173. package/dist/store/settings-store.js +59 -0
  174. package/dist/store/settings-store.js.map +1 -0
  175. package/dist/terminal/pty-manager.d.ts +19 -0
  176. package/dist/terminal/pty-manager.d.ts.map +1 -0
  177. package/dist/terminal/pty-manager.js +58 -0
  178. package/dist/terminal/pty-manager.js.map +1 -0
  179. package/dist/terminal/screen-buffer.d.ts +36 -0
  180. package/dist/terminal/screen-buffer.d.ts.map +1 -0
  181. package/dist/terminal/screen-buffer.js +109 -0
  182. package/dist/terminal/screen-buffer.js.map +1 -0
  183. package/dist/terminal/xterm-bridge.d.ts +32 -0
  184. package/dist/terminal/xterm-bridge.d.ts.map +1 -0
  185. package/dist/terminal/xterm-bridge.js +168 -0
  186. package/dist/terminal/xterm-bridge.js.map +1 -0
  187. package/dist/ui/components/adopt-agent-dialog.d.ts +10 -0
  188. package/dist/ui/components/adopt-agent-dialog.d.ts.map +1 -0
  189. package/dist/ui/components/adopt-agent-dialog.js +31 -0
  190. package/dist/ui/components/adopt-agent-dialog.js.map +1 -0
  191. package/dist/ui/components/agent-tab.d.ts +17 -0
  192. package/dist/ui/components/agent-tab.d.ts.map +1 -0
  193. package/dist/ui/components/agent-tab.js +33 -0
  194. package/dist/ui/components/agent-tab.js.map +1 -0
  195. package/dist/ui/components/agents-settings-content.d.ts +7 -0
  196. package/dist/ui/components/agents-settings-content.d.ts.map +1 -0
  197. package/dist/ui/components/agents-settings-content.js +238 -0
  198. package/dist/ui/components/agents-settings-content.js.map +1 -0
  199. package/dist/ui/components/help-modal.d.ts +7 -0
  200. package/dist/ui/components/help-modal.d.ts.map +1 -0
  201. package/dist/ui/components/help-modal.js +29 -0
  202. package/dist/ui/components/help-modal.js.map +1 -0
  203. package/dist/ui/components/new-session-dialog.d.ts +8 -0
  204. package/dist/ui/components/new-session-dialog.d.ts.map +1 -0
  205. package/dist/ui/components/new-session-dialog.js +84 -0
  206. package/dist/ui/components/new-session-dialog.js.map +1 -0
  207. package/dist/ui/components/path-input.d.ts +8 -0
  208. package/dist/ui/components/path-input.d.ts.map +1 -0
  209. package/dist/ui/components/path-input.js +151 -0
  210. package/dist/ui/components/path-input.js.map +1 -0
  211. package/dist/ui/components/settings-panel.d.ts +7 -0
  212. package/dist/ui/components/settings-panel.d.ts.map +1 -0
  213. package/dist/ui/components/settings-panel.js +134 -0
  214. package/dist/ui/components/settings-panel.js.map +1 -0
  215. package/dist/ui/components/standalone-agents.d.ts +9 -0
  216. package/dist/ui/components/standalone-agents.d.ts.map +1 -0
  217. package/dist/ui/components/standalone-agents.js +28 -0
  218. package/dist/ui/components/standalone-agents.js.map +1 -0
  219. package/dist/ui/components/terminal-view.d.ts +12 -0
  220. package/dist/ui/components/terminal-view.d.ts.map +1 -0
  221. package/dist/ui/components/terminal-view.js +53 -0
  222. package/dist/ui/components/terminal-view.js.map +1 -0
  223. package/dist/ui/components/viewer-approval-dialog.d.ts +9 -0
  224. package/dist/ui/components/viewer-approval-dialog.d.ts.map +1 -0
  225. package/dist/ui/components/viewer-approval-dialog.js +38 -0
  226. package/dist/ui/components/viewer-approval-dialog.js.map +1 -0
  227. package/dist/ui/hooks/use-git-info.d.ts +8 -0
  228. package/dist/ui/hooks/use-git-info.d.ts.map +1 -0
  229. package/dist/ui/hooks/use-git-info.js +72 -0
  230. package/dist/ui/hooks/use-git-info.js.map +1 -0
  231. package/dist/ui/hooks/use-keybindings.d.ts +10 -0
  232. package/dist/ui/hooks/use-keybindings.d.ts.map +1 -0
  233. package/dist/ui/hooks/use-keybindings.js +91 -0
  234. package/dist/ui/hooks/use-keybindings.js.map +1 -0
  235. package/dist/ui/hooks/use-portal-connected.d.ts +2 -0
  236. package/dist/ui/hooks/use-portal-connected.d.ts.map +1 -0
  237. package/dist/ui/hooks/use-portal-connected.js +10 -0
  238. package/dist/ui/hooks/use-portal-connected.js.map +1 -0
  239. package/dist/ui/hooks/use-raw-input.d.ts +8 -0
  240. package/dist/ui/hooks/use-raw-input.d.ts.map +1 -0
  241. package/dist/ui/hooks/use-raw-input.js +106 -0
  242. package/dist/ui/hooks/use-raw-input.js.map +1 -0
  243. package/dist/ui/hooks/use-spinner.d.ts +2 -0
  244. package/dist/ui/hooks/use-spinner.d.ts.map +1 -0
  245. package/dist/ui/hooks/use-spinner.js +13 -0
  246. package/dist/ui/hooks/use-spinner.js.map +1 -0
  247. package/dist/ui/hooks/use-terminal-size.d.ts +5 -0
  248. package/dist/ui/hooks/use-terminal-size.d.ts.map +1 -0
  249. package/dist/ui/hooks/use-terminal-size.js +22 -0
  250. package/dist/ui/hooks/use-terminal-size.js.map +1 -0
  251. package/dist/ui/hooks/use-update-check.d.ts +6 -0
  252. package/dist/ui/hooks/use-update-check.d.ts.map +1 -0
  253. package/dist/ui/hooks/use-update-check.js +62 -0
  254. package/dist/ui/hooks/use-update-check.js.map +1 -0
  255. package/dist/ui/layout/main-pane.d.ts +13 -0
  256. package/dist/ui/layout/main-pane.d.ts.map +1 -0
  257. package/dist/ui/layout/main-pane.js +36 -0
  258. package/dist/ui/layout/main-pane.js.map +1 -0
  259. package/dist/ui/layout/shell.d.ts +17 -0
  260. package/dist/ui/layout/shell.d.ts.map +1 -0
  261. package/dist/ui/layout/shell.js +24 -0
  262. package/dist/ui/layout/shell.js.map +1 -0
  263. package/dist/ui/layout/sidebar.d.ts +12 -0
  264. package/dist/ui/layout/sidebar.d.ts.map +1 -0
  265. package/dist/ui/layout/sidebar.js +9 -0
  266. package/dist/ui/layout/sidebar.js.map +1 -0
  267. package/dist/ui/layout/status-bar.d.ts +9 -0
  268. package/dist/ui/layout/status-bar.d.ts.map +1 -0
  269. package/dist/ui/layout/status-bar.js +138 -0
  270. package/dist/ui/layout/status-bar.js.map +1 -0
  271. package/package.json +70 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 George Livas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,461 @@
1
+ # Flaio
2
+
3
+ A terminal UI application for managing multiple AI CLI agents in tabbed sessions. Run Claude Code and Gemini CLI side by side, get permission requests forwarded to Slack, Discord, or Telegram, and adopt standalone agents already running on your system — all from a single interface.
4
+
5
+ Built with [Ink](https://github.com/vadimdemedes/ink) (React for CLIs), [node-pty](https://github.com/microsoft/node-pty), and [xterm-headless](https://github.com/xtermjs/xterm.js).
6
+
7
+ ![Version](https://img.shields.io/badge/version-0.1.0-blue)
8
+ ![License](https://img.shields.io/badge/license-MIT-green)
9
+ ![Node](https://img.shields.io/badge/node-%3E%3D18-brightgreen)
10
+
11
+ ## Features
12
+
13
+ ### Multi-Agent Sessions
14
+ - **Tabbed interface** — Run multiple AI agents simultaneously, each in its own tab with a full PTY-backed terminal
15
+ - **Supported agents** — Claude Code and Gemini CLI out of the box, with a driver abstraction for adding more
16
+ - **Session lifecycle** — Create new sessions, resume previous ones, or continue where you left off
17
+ - **Intelligent status detection** — Automatically detects when an agent is idle, running, or waiting for input
18
+
19
+ ### Standalone Agent Adoption
20
+ - **Auto-detection** — Continuously scans for Claude Code and Gemini CLI processes running outside the manager
21
+ - **One-key adoption** — Press `Alt+A` to bring a standalone agent into a managed tab, seamlessly continuing its session
22
+
23
+ ### Messaging Connectors
24
+ Forward permission requests, tool results, and session notifications to your preferred messaging platform:
25
+
26
+ | Platform | Permission Requests | Tool Results | Notifications | Threading |
27
+ |----------|-------------------|--------------|---------------|-----------|
28
+ | **Slack** | Text replies (allow/deny) | Per-session threads | Session start/stop | Per-session threads |
29
+ | **Discord** | Thread replies | Formatted output | Status messages | Auto-created threads |
30
+ | **Telegram** | Inline keyboard buttons | Formatted output | Status messages | — |
31
+
32
+ All connector dependencies are optional — only install what you need.
33
+
34
+ ### Portal — Remote Session Access
35
+ Connect to running sessions from another terminal window without disrupting the main UI:
36
+
37
+ - **Interactive picker** — Run `flaio portal` to browse and select sessions
38
+ - **Create sessions remotely** — Start new agent sessions directly from the portal
39
+ - **Full terminal mirroring** — See the exact same output as the main app in real-time
40
+ - **Input forwarding** — Type commands and interact with the agent as if you were in the main app
41
+ - **Scroll support** — Mouse wheel, `Ctrl+U`/`Ctrl+D`, and `PageUp`/`PageDown` all work
42
+ - **Connection indicator** — The main app shows a `⇄` icon in the header when a portal client is connected
43
+
44
+ ### Hooks System
45
+ An IPC-based hooks system bridges Claude Code's lifecycle events to the manager:
46
+
47
+ - **PermissionRequest** — Tool execution approval routed through connectors
48
+ - **PostToolUse** — Tool results forwarded to messaging platforms
49
+ - **Notification** — Agent responses and status changes relayed to connectors
50
+
51
+ Hooks communicate via Unix socket IPC (`/tmp/flaio/hooks.sock`) with newline-delimited JSON.
52
+
53
+ ### Terminal Emulation
54
+ - Full ANSI color support (16, 256, and truecolor RGB)
55
+ - Text attributes: bold, italic, underline, dim, inverse, strikethrough
56
+ - Mouse wheel scrolling and keyboard scroll (`Ctrl+U`/`Ctrl+D`)
57
+ - 1000-line scrollback buffer
58
+ - FPS-limited screen rendering (default 30 FPS)
59
+
60
+ ### Responsive Layout
61
+ - **Wide terminals (100+ cols):** Sidebar with session list on the left, terminal on the right
62
+ - **Narrow terminals (< 100 cols):** Compact tab bar at the top, full-width terminal below
63
+
64
+ ## Installation
65
+
66
+ ### Prerequisites
67
+ - Node.js >= 18
68
+ - At least one supported AI CLI agent installed:
69
+ - [Claude Code](https://docs.anthropic.com/en/docs/claude-code) — `npm install -g @anthropic-ai/claude-code`
70
+ - [Gemini CLI](https://github.com/google-gemini/gemini-cli) — `npm install -g @google/gemini-cli`
71
+
72
+ ### Install from npm
73
+
74
+ ```bash
75
+ npm install -g flaio-cli
76
+ ```
77
+
78
+ Then run it:
79
+
80
+ ```bash
81
+ flaio
82
+ ```
83
+
84
+ ### Install from Source
85
+
86
+ ```bash
87
+ git clone https://github.com/flaio-ai/flaio.git
88
+ cd flaio
89
+ npm install
90
+ npm run build
91
+ npm start
92
+ ```
93
+
94
+ ### Development
95
+
96
+ ```bash
97
+ # Run with live reload
98
+ npm run dev
99
+ ```
100
+
101
+ ### Hook Installation
102
+
103
+ To enable messaging connector integration with Claude Code, install the hooks:
104
+
105
+ ```bash
106
+ npm run install-hooks
107
+ ```
108
+
109
+ This registers three hooks in `~/.claude/settings.json` that route Claude Code events through the manager's IPC server. To remove them:
110
+
111
+ ```bash
112
+ npm run uninstall-hooks
113
+ ```
114
+
115
+ ## Usage
116
+
117
+ ### Starting the Manager
118
+
119
+ ```bash
120
+ # Development
121
+ npm run dev
122
+
123
+ # Production
124
+ npm start
125
+ ```
126
+
127
+ ### Creating a Session
128
+
129
+ 1. Press `Ctrl+T` to open the new session dialog
130
+ 2. Select an agent (Claude Code or Gemini CLI)
131
+ 3. Enter the working directory (supports tab completion)
132
+ 4. The agent spawns in a new tab with a full terminal
133
+
134
+ ### Adopting a Standalone Agent
135
+
136
+ If you have a Claude Code or Gemini CLI process running in another terminal:
137
+
138
+ 1. Press `Alt+A` to open the adopt dialog
139
+ 2. Select the detected agent from the list
140
+ 3. The external process is terminated and its session continues in a new managed tab
141
+
142
+ ### Using Portals
143
+
144
+ Portals let you access running sessions from a separate terminal — useful for monitoring agents on a remote machine, pairing, or just keeping the main UI on one screen while interacting from another.
145
+
146
+ ```bash
147
+ # Interactive picker — browse sessions, create new ones
148
+ flaio portal
149
+
150
+ # Connect directly to a known session
151
+ flaio portal <session-id>
152
+
153
+ # Static table of running sessions
154
+ flaio portal --list
155
+ ```
156
+
157
+ In the interactive picker:
158
+ - Use **arrow keys** to navigate, **Enter** to select
159
+ - Choose **"+ New Session"** to start a fresh agent from the portal
160
+ - Press **Esc** to exit
161
+
162
+ Once connected, the portal mirrors the session in real-time. Press **Ctrl+C** to disconnect and return to your shell.
163
+
164
+ ### Configuring Connectors
165
+
166
+ Press `Ctrl+S` to open the settings panel, then configure your preferred messaging connectors.
167
+
168
+ #### Slack
169
+
170
+ Slack integration gives you per-session threads, permission approval via text replies, and agent response forwarding — so you can monitor and interact with agents from your phone or desktop.
171
+
172
+ **1. Create a Slack App**
173
+
174
+ Go to [api.slack.com/apps](https://api.slack.com/apps) and create a new app "From scratch."
175
+
176
+ **2. Configure Bot Scopes**
177
+
178
+ Under **OAuth & Permissions**, add these Bot Token Scopes:
179
+
180
+ | Scope | Purpose |
181
+ |-------|---------|
182
+ | `chat:write` | Post messages and thread replies |
183
+ | `channels:history` | Read replies in public channels (for permission responses and prompts) |
184
+ | `channels:read` | Resolve channel info |
185
+
186
+ If you're using a **private channel**, also add `groups:history` and `groups:read`.
187
+
188
+ **3. Install to Workspace**
189
+
190
+ Click **Install to Workspace** and authorize. Copy the **Bot User OAuth Token** (`xoxb-...`).
191
+
192
+ **4. Invite the Bot to a Channel**
193
+
194
+ In Slack, go to your channel and type `/invite @YourBotName`.
195
+
196
+ **5. Get the Channel ID**
197
+
198
+ Right-click the channel name > **View channel details** > copy the **Channel ID** at the bottom.
199
+
200
+ **6. (Optional) Enable Socket Mode for Real-Time Events**
201
+
202
+ By default, the manager polls Slack threads every 3 seconds. For faster message delivery:
203
+
204
+ 1. Go to **Socket Mode** in your app settings and enable it
205
+ 2. Generate an **App-Level Token** with `connections:write` scope
206
+ 3. Copy the token (`xapp-...`)
207
+
208
+ **7. Configure in Flaio**
209
+
210
+ Press `Ctrl+S` in the manager, enable Slack, and enter:
211
+
212
+ | Field | Value |
213
+ |-------|-------|
214
+ | **Bot Token** | `xoxb-...` from step 3 |
215
+ | **Channel ID** | From step 5 |
216
+ | **App Token** (optional) | `xapp-...` from step 6 |
217
+
218
+ Or edit `~/.config/flaio/settings.json` directly:
219
+
220
+ ```json
221
+ {
222
+ "connectors": {
223
+ "slack": {
224
+ "enabled": true,
225
+ "botToken": "xoxb-your-token",
226
+ "appToken": "xapp-your-token",
227
+ "channelId": "C0123456789",
228
+ "pollInterval": 3000,
229
+ "timeout": 300000
230
+ }
231
+ }
232
+ }
233
+ ```
234
+
235
+ **8. Install Hooks**
236
+
237
+ ```bash
238
+ npm run install-hooks
239
+ ```
240
+
241
+ This registers lifecycle hooks in `~/.claude/settings.json` so Claude Code events (permission requests, agent responses, notifications) are forwarded to Slack.
242
+
243
+ **How It Works**
244
+
245
+ When a session starts, the bot creates a thread in your Slack channel:
246
+
247
+ ```
248
+ Session started
249
+ Project: my-project
250
+ CWD: ~/projects/my-project
251
+ Session: abc123
252
+ ```
253
+
254
+ All agent interactions happen in that thread:
255
+ - **Agent responses** are posted automatically
256
+ - **Permission requests** appear with the tool name and input — reply `allow` or `deny`
257
+ - **You can send prompts** by replying in the thread — they're forwarded directly to the agent's input
258
+
259
+ Messages from Slack are delivered via Socket Mode (instant) or thread polling (every 3s), with built-in deduplication to prevent double delivery.
260
+
261
+ #### Discord
262
+
263
+ 1. Create a Discord bot at the [Developer Portal](https://discord.com/developers/applications)
264
+ 2. Enable the bot and grant `Send Messages` + `Read Message History` permissions
265
+ 3. In settings, enable Discord and enter:
266
+ - **Bot Token**
267
+ - **Channel ID**
268
+
269
+ #### Telegram
270
+
271
+ 1. Create a bot via [@BotFather](https://t.me/botfather)
272
+ 2. In settings, enable Telegram and enter:
273
+ - **Bot Token** (from BotFather)
274
+ - **Chat ID** (your personal or group chat ID)
275
+
276
+ ### Managing Agents
277
+
278
+ Press `Ctrl+S` and navigate to the **Agents** tab to:
279
+ - Check installed agent versions
280
+ - Switch install method (npm or Homebrew)
281
+ - Install or update agents directly from the UI
282
+
283
+ ## Keyboard Shortcuts
284
+
285
+ ### Navigation
286
+
287
+ | Key | Action |
288
+ |-----|--------|
289
+ | `Ctrl+T` | New session |
290
+ | `Ctrl+W` | Close active session |
291
+ | `Ctrl+N` / `Ctrl+Down` | Next session |
292
+ | `Ctrl+P` / `Ctrl+Up` | Previous session |
293
+ | `Alt+1` — `Alt+9` | Jump to session by number |
294
+
295
+ ### Scrolling
296
+
297
+ | Key | Action |
298
+ |-----|--------|
299
+ | `Ctrl+U` | Scroll up |
300
+ | `Ctrl+D` | Scroll down |
301
+ | `Mouse Wheel` | Scroll up/down |
302
+
303
+ ### Panels & Modals
304
+
305
+ | Key | Action |
306
+ |-----|--------|
307
+ | `Ctrl+S` | Toggle settings panel |
308
+ | `Ctrl+B` | Toggle sidebar |
309
+ | `Ctrl+G` | Toggle help modal |
310
+ | `Alt+A` | Adopt standalone agent |
311
+ | `Esc` | Close modal / cancel dialog |
312
+
313
+ ### Application
314
+
315
+ | Key | Action |
316
+ |-----|--------|
317
+ | `Ctrl+Q` | Quit |
318
+
319
+ > **Note:** On macOS, `Alt` shortcuts use the `Option` key or the `Esc` prefix (press `Esc` then the key).
320
+
321
+ ## Architecture
322
+
323
+ ```
324
+ src/
325
+ ├── cli.tsx # Entry point (Commander + Ink)
326
+ ├── app.tsx # Root component
327
+ ├── agents/
328
+ │ ├── agent-session.ts # Session lifecycle & events
329
+ │ ├── agent-registry.ts # Driver registry
330
+ │ ├── agent-detector.ts # Standalone process scanner
331
+ │ └── drivers/
332
+ │ ├── base-driver.ts # Abstract driver interface
333
+ │ ├── claude-driver.ts # Claude Code driver
334
+ │ └── gemini-driver.ts # Gemini CLI driver
335
+ ├── connectors/
336
+ │ ├── connector-interface.ts # Connector contract
337
+ │ ├── connector-manager.ts # Routes events to connectors
338
+ │ └── adapters/
339
+ │ ├── slack-adapter.ts # Slack (Web API + Socket Mode)
340
+ │ ├── discord-adapter.ts # Discord (discord.js)
341
+ │ └── telegram-adapter.ts # Telegram (Telegraf)
342
+ ├── terminal/
343
+ │ ├── pty-manager.ts # node-pty wrapper
344
+ │ ├── xterm-bridge.ts # xterm-headless rendering
345
+ │ └── screen-buffer.ts # FPS-limited display buffer
346
+ ├── hooks/
347
+ │ ├── hook-server.ts # Unix socket IPC server
348
+ │ ├── hook.ts # PermissionRequest handler
349
+ │ ├── post-tool-hook.ts # PostToolUse handler
350
+ │ ├── notification-hook.ts # Notification handler
351
+ │ ├── stop-hook.ts # Stop event handler
352
+ │ └── install.ts # Hook installer/uninstaller
353
+ ├── portal/
354
+ │ ├── shared.ts # Protocol types (client ↔ server)
355
+ │ ├── portal-server.ts # Unix socket server (main app)
356
+ │ ├── portal-client.ts # IPC client functions
357
+ │ ├── portal-picker.tsx # Interactive session picker
358
+ │ └── ansi-renderer.ts # ScreenContent → ANSI converter
359
+ ├── store/
360
+ │ ├── app-store.ts # Session state (Zustand)
361
+ │ ├── settings-store.ts # Persisted config (Zustand)
362
+ │ ├── connector-store.ts # Connector lifecycle & bridges
363
+ │ └── portal-store.ts # Portal connection tracking
364
+ ├── config/
365
+ │ ├── config.ts # Zod schema & load/save
366
+ │ └── defaults.ts # Default configuration
367
+ └── ui/
368
+ ├── layout/
369
+ │ ├── shell.tsx # Main layout container
370
+ │ ├── sidebar.tsx # Session list panel
371
+ │ ├── main-pane.tsx # Terminal + header
372
+ │ └── status-bar.tsx # Bottom status indicators
373
+ ├── components/
374
+ │ ├── terminal-view.tsx # xterm grid renderer
375
+ │ ├── agent-tab.tsx # Session tab
376
+ │ ├── new-session-dialog.tsx # Create session dialog
377
+ │ ├── adopt-agent-dialog.tsx # Adopt agent dialog
378
+ │ ├── standalone-agents.tsx # Detected agents list
379
+ │ ├── settings-panel.tsx # Settings UI
380
+ │ ├── agents-settings-content.tsx # Agent install/update UI
381
+ │ ├── help-modal.tsx # Keybindings reference
382
+ │ └── path-input.tsx # Directory autocomplete
383
+ └── hooks/
384
+ ├── use-keybindings.ts # Keyboard shortcut handler
385
+ ├── use-raw-input.ts # Raw stdin forwarding
386
+ ├── use-terminal-size.ts # Terminal dimensions
387
+ ├── use-spinner.ts # Cycling animation hook
388
+ ├── use-git-info.ts # Git branch/status polling
389
+ └── use-portal-connected.ts # Portal connection state
390
+ ```
391
+
392
+ ### How It Works
393
+
394
+ 1. **CLI entry** (`cli.tsx`) sets up the alternate screen buffer, mouse tracking, and renders the Ink app. The `portal` subcommand launches the interactive picker or connects to a session directly.
395
+ 2. **App** (`app.tsx`) initializes stores, starts connectors and the portal server, and renders the shell layout
396
+ 3. **Sessions** are managed by `AppStore` — each session owns a `PtyManager` (node-pty), `XtermBridge` (headless terminal emulation), and `ScreenBuffer` (FPS-limited rendering)
397
+ 4. **Keyboard input** is captured by `useRawInput` and forwarded to the active session's PTY, except when intercepted by `useKeybindings` for shortcuts
398
+ 5. **Portal server** (`portal-server.ts`) listens on a Unix socket (`/tmp/flaio/portal.sock`). Portal clients subscribe to sessions, receive throttled screen frames, and forward keystrokes — providing full remote access without disrupting the main UI
399
+ 6. **Hooks** are installed as Claude Code lifecycle hooks that send events to the manager's IPC server, which routes them through `ConnectorManager` to the configured messaging adapters
400
+ 7. **State** flows through Zustand stores with selector-based subscriptions for efficient re-renders
401
+
402
+ ## Configuration
403
+
404
+ Settings are persisted to `~/.config/flaio/settings.json` and validated with Zod on load.
405
+
406
+ ```jsonc
407
+ {
408
+ "ui": {
409
+ "sidebarWidth": 24, // Sidebar character width
410
+ "narrowBreakpoint": 100, // Column threshold for responsive layout
411
+ "targetFps": 30 // Screen buffer refresh rate
412
+ },
413
+ "connectors": {
414
+ "slack": {
415
+ "enabled": false,
416
+ "botToken": "", // xoxb-... token
417
+ "appToken": "", // xapp-... token (optional, for Socket Mode)
418
+ "channelId": "",
419
+ "pollInterval": 2000, // Thread polling interval (ms)
420
+ "timeout": 300000 // Permission request timeout (ms)
421
+ },
422
+ "discord": {
423
+ "enabled": false,
424
+ "botToken": "",
425
+ "channelId": "",
426
+ "timeout": 300000
427
+ },
428
+ "telegram": {
429
+ "enabled": false,
430
+ "botToken": "",
431
+ "chatId": "",
432
+ "timeout": 300000
433
+ }
434
+ },
435
+ "agents": {
436
+ "statusCheckInterval": 1000, // Agent status polling (ms)
437
+ "detectorInterval": 5000 // Standalone agent scan interval (ms)
438
+ }
439
+ }
440
+ ```
441
+
442
+ ## Contributing
443
+
444
+ Contributions are welcome! Please feel free to submit issues and pull requests.
445
+
446
+ ### Adding a New Agent Driver
447
+
448
+ 1. Create a new driver in `src/agents/drivers/` extending `BaseDriver`
449
+ 2. Implement the required methods: `spawn()`, `resume()`, `continue()`, `detectStatus()`
450
+ 3. Register it in `src/agents/agent-registry.ts`
451
+
452
+ ### Adding a New Connector
453
+
454
+ 1. Create a new adapter in `src/connectors/adapters/` implementing `ConnectorInterface`
455
+ 2. Implement: `connect()`, `disconnect()`, `requestPermission()`, `postToolResult()`, `postNotification()`
456
+ 3. Add config schema in `src/config/config.ts`
457
+ 4. Wire it up in `src/connectors/connector-manager.ts`
458
+
459
+ ## License
460
+
461
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,21 @@
1
+ import { EventEmitter } from "node:events";
2
+ export interface DetectedAgent {
3
+ pid: number;
4
+ driverName: string;
5
+ displayName: string;
6
+ command: string;
7
+ cwd: string | null;
8
+ }
9
+ export declare class AgentDetector extends EventEmitter {
10
+ private timer;
11
+ private _detected;
12
+ private ignoredPids;
13
+ get detected(): DetectedAgent[];
14
+ /** Mark a PID as managed by us (so we stop reporting it) */
15
+ ignorePid(pid: number): void;
16
+ start(intervalMs?: number): void;
17
+ stop(): void;
18
+ private scan;
19
+ private getCwd;
20
+ }
21
+ //# sourceMappingURL=agent-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-detector.d.ts","sourceRoot":"","sources":["../../src/agents/agent-detector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,WAAW,CAA0B;IAE7C,IAAI,QAAQ,IAAI,aAAa,EAAE,CAE9B;IAED,4DAA4D;IAC5D,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI5B,KAAK,CAAC,UAAU,GAAE,MAAa,GAAG,IAAI;IAKtC,IAAI,IAAI,IAAI;IAOZ,OAAO,CAAC,IAAI;IAqEZ,OAAO,CAAC,MAAM;CAqBf"}
@@ -0,0 +1,109 @@
1
+ import { execSync } from "node:child_process";
2
+ import { EventEmitter } from "node:events";
3
+ import { getAllDrivers } from "./agent-registry.js";
4
+ export class AgentDetector extends EventEmitter {
5
+ timer = null;
6
+ _detected = [];
7
+ ignoredPids = new Set();
8
+ get detected() {
9
+ return this._detected;
10
+ }
11
+ /** Mark a PID as managed by us (so we stop reporting it) */
12
+ ignorePid(pid) {
13
+ this.ignoredPids.add(pid);
14
+ }
15
+ start(intervalMs = 5000) {
16
+ this.scan();
17
+ this.timer = setInterval(() => this.scan(), intervalMs);
18
+ }
19
+ stop() {
20
+ if (this.timer) {
21
+ clearInterval(this.timer);
22
+ this.timer = null;
23
+ }
24
+ }
25
+ scan() {
26
+ try {
27
+ const drivers = getAllDrivers();
28
+ const commandNames = drivers.map((d) => d.command);
29
+ // Use ps to find processes matching known agent commands
30
+ let psOutput;
31
+ try {
32
+ psOutput = execSync("ps aux", {
33
+ encoding: "utf-8",
34
+ timeout: 5000,
35
+ });
36
+ }
37
+ catch {
38
+ return;
39
+ }
40
+ const detected = [];
41
+ const lines = psOutput.split("\n");
42
+ for (const line of lines) {
43
+ for (const driver of drivers) {
44
+ // Match the command in the ps output
45
+ // e.g., "user 12345 ... claude -p ..."
46
+ const regex = new RegExp(`\\b${driver.command}\\b`);
47
+ if (!regex.test(line))
48
+ continue;
49
+ const parts = line.trim().split(/\s+/);
50
+ const pid = parseInt(parts[1] ?? "0");
51
+ if (!pid || isNaN(pid) || pid === process.pid)
52
+ continue;
53
+ if (this.ignoredPids.has(pid))
54
+ continue;
55
+ // Try to get cwd via lsof
56
+ const cwd = this.getCwd(pid);
57
+ detected.push({
58
+ pid,
59
+ driverName: driver.name,
60
+ displayName: driver.displayName,
61
+ command: driver.command,
62
+ cwd,
63
+ });
64
+ }
65
+ }
66
+ // Deduplicate by PID
67
+ const seen = new Set();
68
+ const unique = detected.filter((a) => {
69
+ if (seen.has(a.pid))
70
+ return false;
71
+ seen.add(a.pid);
72
+ return true;
73
+ });
74
+ const changed = unique.length !== this._detected.length ||
75
+ unique.some((a, i) => a.pid !== this._detected[i]?.pid ||
76
+ a.driverName !== this._detected[i]?.driverName);
77
+ if (changed) {
78
+ this._detected = unique;
79
+ this.emit("change", unique);
80
+ }
81
+ }
82
+ catch {
83
+ // Non-critical — just skip this scan
84
+ }
85
+ }
86
+ getCwd(pid) {
87
+ try {
88
+ // lsof -Fn outputs "fcwd" on one line, then "n/path" on the next
89
+ const output = execSync(`lsof -p ${pid} -Fn 2>/dev/null`, {
90
+ encoding: "utf-8",
91
+ timeout: 3000,
92
+ });
93
+ const lines = output.split("\n");
94
+ for (let i = 0; i < lines.length; i++) {
95
+ if (lines[i] === "fcwd") {
96
+ const next = lines[i + 1];
97
+ if (next?.startsWith("n")) {
98
+ return next.slice(1);
99
+ }
100
+ }
101
+ }
102
+ return null;
103
+ }
104
+ catch {
105
+ return null;
106
+ }
107
+ }
108
+ }
109
+ //# sourceMappingURL=agent-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-detector.js","sourceRoot":"","sources":["../../src/agents/agent-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { BaseDriver } from "./drivers/base-driver.js";
2
+ export declare function registerDriver(driver: BaseDriver): void;
3
+ export declare function getDriver(name: string): BaseDriver | undefined;
4
+ export declare function getAllDrivers(): BaseDriver[];
5
+ export declare function getInstalledDrivers(): Promise<BaseDriver[]>;
6
+ //# sourceMappingURL=agent-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-registry.d.ts","sourceRoot":"","sources":["../../src/agents/agent-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAM3D,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAEvD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAE9D;AAED,wBAAgB,aAAa,IAAI,UAAU,EAAE,CAE5C;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAQjE"}
@@ -0,0 +1,25 @@
1
+ import { ClaudeDriver } from "./drivers/claude-driver.js";
2
+ import { GeminiDriver } from "./drivers/gemini-driver.js";
3
+ const drivers = new Map();
4
+ export function registerDriver(driver) {
5
+ drivers.set(driver.name, driver);
6
+ }
7
+ export function getDriver(name) {
8
+ return drivers.get(name);
9
+ }
10
+ export function getAllDrivers() {
11
+ return Array.from(drivers.values());
12
+ }
13
+ export async function getInstalledDrivers() {
14
+ const results = [];
15
+ for (const driver of drivers.values()) {
16
+ if (await driver.checkInstalled()) {
17
+ results.push(driver);
18
+ }
19
+ }
20
+ return results;
21
+ }
22
+ // Register built-in drivers
23
+ registerDriver(new ClaudeDriver());
24
+ registerDriver(new GeminiDriver());
25
+ //# sourceMappingURL=agent-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-registry.js","sourceRoot":"","sources":["../../src/agents/agent-registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,MAAM,OAAO,GAA4B,IAAI,GAAG,EAAE,CAAC;AAEnD,MAAM,UAAU,cAAc,CAAC,MAAkB;IAC/C,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACtC,IAAI,MAAM,MAAM,CAAC,cAAc,EAAE,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,4BAA4B;AAC5B,cAAc,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC;AACnC,cAAc,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC"}