ttyd-mux 0.4.0 → 0.4.2
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.
- package/README.md +347 -119
- package/dist/client/api-client.d.ts +9 -2
- package/dist/client/api-client.d.ts.map +1 -1
- package/dist/client/api-client.js +5 -4
- package/dist/client/api-client.js.map +1 -1
- package/dist/client/daemon-client.d.ts +10 -0
- package/dist/client/daemon-client.d.ts.map +1 -1
- package/dist/client/daemon-client.js +38 -2
- package/dist/client/daemon-client.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/commands/caddy.js +1 -1
- package/dist/commands/caddy.js.map +1 -1
- package/dist/commands/daemon.d.ts +2 -0
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +72 -3
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/down.d.ts +1 -0
- package/dist/commands/down.d.ts.map +1 -1
- package/dist/commands/down.js +14 -4
- package/dist/commands/down.js.map +1 -1
- package/dist/commands/list.d.ts +7 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +31 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/reload.js +3 -3
- package/dist/commands/reload.js.map +1 -1
- package/dist/commands/restart.d.ts +5 -0
- package/dist/commands/restart.d.ts.map +1 -0
- package/dist/commands/restart.js +19 -0
- package/dist/commands/restart.js.map +1 -0
- package/dist/commands/shutdown.d.ts +1 -0
- package/dist/commands/shutdown.d.ts.map +1 -1
- package/dist/commands/shutdown.js +8 -2
- package/dist/commands/shutdown.js.map +1 -1
- package/dist/commands/status.js +1 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/up.d.ts.map +1 -1
- package/dist/commands/up.js +0 -4
- package/dist/commands/up.js.map +1 -1
- package/dist/daemon/api-handler.d.ts.map +1 -1
- package/dist/daemon/api-handler.js +20 -7
- package/dist/daemon/api-handler.js.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +10 -6
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/session-manager.d.ts +6 -2
- package/dist/daemon/session-manager.d.ts.map +1 -1
- package/dist/daemon/session-manager.js +15 -6
- package/dist/daemon/session-manager.js.map +1 -1
- package/dist/index.js +47 -31
- package/dist/index.js.map +1 -1
- package/dist/utils/tmux-client.d.ts +4 -0
- package/dist/utils/tmux-client.d.ts.map +1 -1
- package/dist/utils/tmux-client.js +11 -1
- package/dist/utils/tmux-client.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/cuzic/ttyd-mux/actions/workflows/ci.yml)
|
|
4
4
|

|
|
5
|
+
[](https://www.npmjs.com/package/ttyd-mux)
|
|
6
|
+
[](https://www.npmjs.com/package/ttyd-mux)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
8
|
|
|
6
9
|
A CLI tool for managing multiple ttyd+tmux web terminal sessions.
|
|
7
10
|
|
|
@@ -9,33 +12,149 @@ A CLI tool for managing multiple ttyd+tmux web terminal sessions.
|
|
|
9
12
|
|
|
10
13
|
---
|
|
11
14
|
|
|
12
|
-
##
|
|
15
|
+
## Table of Contents / 目次
|
|
16
|
+
|
|
17
|
+
- [Quick Start](#quick-start--クイックスタート)
|
|
18
|
+
- [Features](#features--機能)
|
|
19
|
+
- [Use Cases](#use-cases--ユースケース)
|
|
20
|
+
- [Installation](#installation--インストール)
|
|
21
|
+
- [Usage Patterns](#usage-patterns--使い方)
|
|
22
|
+
- [Commands](#commands--コマンド)
|
|
23
|
+
- [Configuration](#configuration--設定)
|
|
24
|
+
- [Architecture](#architecture--アーキテクチャ)
|
|
25
|
+
- [Toolbar Features](#toolbar-features--ツールバー機能)
|
|
26
|
+
- [PWA Support](#pwa-support--pwa-対応)
|
|
27
|
+
- [Caddy Integration](#caddy-integration--caddy-との連携)
|
|
28
|
+
- [Development](#development--開発)
|
|
13
29
|
|
|
14
|
-
|
|
15
|
-
This tool was developed to easily access terminal sessions running AI coding assistants like [Claude Code](https://docs.anthropic.com/en/docs/claude-code) from a web browser. When running long coding sessions with AI assistants on a remote server, you can monitor and interact with them from anywhere through your browser.
|
|
30
|
+
---
|
|
16
31
|
|
|
17
|
-
|
|
18
|
-
|
|
32
|
+
## Quick Start / クイックスタート
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Install / インストール
|
|
36
|
+
npm install -g ttyd-mux
|
|
37
|
+
|
|
38
|
+
# Start terminal in current directory / カレントディレクトリでターミナル起動
|
|
39
|
+
cd ~/my-project
|
|
40
|
+
ttyd-mux up
|
|
41
|
+
|
|
42
|
+
# Open in browser / ブラウザで開く
|
|
43
|
+
# → http://localhost:7680/ttyd-mux/my-project/
|
|
44
|
+
|
|
45
|
+
# Stop / 停止
|
|
46
|
+
ttyd-mux down
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
That's it! No configuration needed for basic usage.
|
|
50
|
+
|
|
51
|
+
基本的な利用には設定不要です。
|
|
19
52
|
|
|
20
53
|
---
|
|
21
54
|
|
|
22
|
-
##
|
|
55
|
+
## Features / 機能
|
|
23
56
|
|
|
24
|
-
|
|
25
|
-
|
|
57
|
+
### Core Features / コア機能
|
|
58
|
+
|
|
59
|
+
| Feature | Description |
|
|
60
|
+
|---------|-------------|
|
|
61
|
+
| **Zero Config** | Just run `ttyd-mux up` - no setup required / 設定不要で即起動 |
|
|
62
|
+
| **Multi-Session** | Manage multiple terminals from one portal / ポータルで複数ターミナルを一元管理 |
|
|
63
|
+
| **Auto Daemon** | Daemon starts automatically when needed / 必要時にデーモン自動起動 |
|
|
64
|
+
| **tmux Integration** | Sessions persist across restarts / tmux でセッション永続化 |
|
|
65
|
+
| **Reverse Proxy Ready** | Works with Caddy, nginx, etc. / リバースプロキシ対応 |
|
|
66
|
+
|
|
67
|
+
### Mobile Features / モバイル機能
|
|
68
|
+
|
|
69
|
+
| Feature | Description |
|
|
70
|
+
|---------|-------------|
|
|
71
|
+
| **PWA Support** | Add to home screen, fullscreen mode / ホーム画面追加、フルスクリーン |
|
|
72
|
+
| **IME Input** | Japanese/CJK input support / 日本語入力対応 |
|
|
73
|
+
| **Touch Zoom** | Pinch to resize font / ピンチでフォントサイズ変更 |
|
|
74
|
+
| **Double-tap Enter** | Quick command execution / ダブルタップで Enter |
|
|
75
|
+
| **Scroll Buttons** | Easy scrollback navigation / スクロール用ボタン |
|
|
76
|
+
|
|
77
|
+
### PC Features / PC 機能
|
|
78
|
+
|
|
79
|
+
| Feature | Description |
|
|
80
|
+
|---------|-------------|
|
|
81
|
+
| **Ctrl+Scroll Zoom** | Mouse wheel font resize / マウスホイールでサイズ変更 |
|
|
82
|
+
| **Trackpad Pinch** | Mac gesture support / Mac トラックパッド対応 |
|
|
83
|
+
| **Toolbar Toggle** | Ctrl+J to show/hide / Ctrl+J で表示切替 |
|
|
84
|
+
| **Auto Reload** | Reconnects on tab switch / タブ切替時に自動再接続 |
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Use Cases / ユースケース
|
|
89
|
+
|
|
90
|
+
### 1. AI Coding Assistant Monitoring / AI コーディングアシスタントの監視
|
|
91
|
+
|
|
92
|
+
Monitor long-running AI coding sessions (like Claude Code) from anywhere.
|
|
93
|
+
|
|
94
|
+
Claude Code などの AI コーディングセッションをどこからでも監視。
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# On your server / サーバー上で
|
|
98
|
+
cd ~/my-ai-project
|
|
99
|
+
ttyd-mux up
|
|
100
|
+
|
|
101
|
+
# Access from phone/tablet / スマホ・タブレットからアクセス
|
|
102
|
+
# https://your-server.com/ttyd-mux/my-ai-project/
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 2. Remote Development / リモート開発
|
|
26
106
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
107
|
+
Access your development environment from any device with a browser.
|
|
108
|
+
|
|
109
|
+
ブラウザさえあればどのデバイスからでも開発環境にアクセス。
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Start multiple project terminals / 複数プロジェクトを起動
|
|
113
|
+
cd ~/project-a && ttyd-mux up
|
|
114
|
+
cd ~/project-b && ttyd-mux up
|
|
115
|
+
|
|
116
|
+
# List all sessions / セッション一覧
|
|
117
|
+
ttyd-mux list --url
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 3. Server Administration / サーバー管理
|
|
121
|
+
|
|
122
|
+
Predefined sessions for server operations.
|
|
123
|
+
|
|
124
|
+
サーバー操作用の事前定義セッション。
|
|
125
|
+
|
|
126
|
+
```yaml
|
|
127
|
+
# ~/.config/ttyd-mux/config.yaml
|
|
128
|
+
sessions:
|
|
129
|
+
- name: logs
|
|
130
|
+
dir: /var/log
|
|
131
|
+
- name: docker
|
|
132
|
+
dir: /opt/docker
|
|
133
|
+
- name: admin
|
|
134
|
+
dir: /root
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
ttyd-mux daemon start --sessions
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 4. Pair Programming / ペアプログラミング
|
|
142
|
+
|
|
143
|
+
Share your terminal with team members via browser.
|
|
144
|
+
|
|
145
|
+
ブラウザ経由でチームメンバーとターミナルを共有。
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Motivation / 開発動機
|
|
150
|
+
|
|
151
|
+
**English:**
|
|
152
|
+
This tool was developed to easily access terminal sessions running AI coding assistants like [Claude Code](https://docs.anthropic.com/en/docs/claude-code) from a web browser. When running long coding sessions with AI assistants on a remote server, you can monitor and interact with them from anywhere through your browser.
|
|
31
153
|
|
|
32
154
|
**日本語:**
|
|
33
|
-
|
|
155
|
+
このツールは、[Claude Code](https://docs.anthropic.com/ja/docs/claude-code) などの AI コーディングアシスタントを実行しているターミナルセッションに、ブラウザから簡単にアクセスできるようにする目的で開発されました。リモートサーバーで AI アシスタントと長時間のコーディングセッションを実行する際、ブラウザからどこからでも監視・操作できます。
|
|
34
156
|
|
|
35
|
-
|
|
36
|
-
- 複数セッションを一元管理するポータルページを提供
|
|
37
|
-
- Caddy などのリバースプロキシと連携して外部公開
|
|
38
|
-
- Claude Code などの AI コーディングアシスタントをリモートから監視するのに最適
|
|
157
|
+
---
|
|
39
158
|
|
|
40
159
|
## Installation / インストール
|
|
41
160
|
|
|
@@ -61,13 +180,27 @@ sudo apt install ttyd tmux
|
|
|
61
180
|
|
|
62
181
|
# macOS (Homebrew)
|
|
63
182
|
brew install ttyd tmux
|
|
183
|
+
|
|
184
|
+
# Check installation / インストール確認
|
|
185
|
+
ttyd-mux doctor
|
|
64
186
|
```
|
|
65
187
|
|
|
66
|
-
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Usage Patterns / 使い方
|
|
191
|
+
|
|
192
|
+
ttyd-mux has two main usage patterns:
|
|
193
|
+
|
|
194
|
+
ttyd-mux には2つの利用パターンがあります:
|
|
195
|
+
|
|
196
|
+
### Dynamic Usage (Ad-hoc Sessions) / 動的利用
|
|
197
|
+
|
|
198
|
+
Start sessions on-demand in any directory. No configuration needed.
|
|
199
|
+
|
|
200
|
+
設定不要で、任意のディレクトリでその場でセッションを起動。
|
|
67
201
|
|
|
68
202
|
```bash
|
|
69
|
-
# Start in your project directory
|
|
70
|
-
# プロジェクトディレクトリで起動
|
|
203
|
+
# Start in your project directory / プロジェクトディレクトリで起動
|
|
71
204
|
cd ~/my-project
|
|
72
205
|
ttyd-mux up
|
|
73
206
|
|
|
@@ -77,65 +210,88 @@ ttyd-mux up
|
|
|
77
210
|
# Check status / 状態確認
|
|
78
211
|
ttyd-mux status
|
|
79
212
|
|
|
213
|
+
# List sessions with URLs / URLと一緒にセッション一覧
|
|
214
|
+
ttyd-mux list --url
|
|
215
|
+
|
|
80
216
|
# Stop / 停止
|
|
81
217
|
ttyd-mux down
|
|
82
218
|
```
|
|
83
219
|
|
|
84
|
-
|
|
220
|
+
### Static Usage (Predefined Sessions) / 静的利用
|
|
85
221
|
|
|
86
|
-
|
|
222
|
+
Define sessions in config.yaml and start them all at once. Ideal for servers.
|
|
87
223
|
|
|
88
|
-
|
|
89
|
-
ttyd-mux up [--name <name>] # Start session and attach / セッション起動 → 自動アタッチ
|
|
90
|
-
ttyd-mux up --detach # Start without attaching / セッション起動のみ(アタッチしない)
|
|
91
|
-
ttyd-mux down # Stop current directory session / カレントディレクトリのセッション停止
|
|
92
|
-
```
|
|
224
|
+
config.yaml にセッションを定義し、一括起動。サーバー運用に最適。
|
|
93
225
|
|
|
94
|
-
|
|
226
|
+
```yaml
|
|
227
|
+
# ~/.config/ttyd-mux/config.yaml
|
|
228
|
+
sessions:
|
|
229
|
+
- name: project-a
|
|
230
|
+
dir: /home/user/project-a
|
|
231
|
+
- name: project-b
|
|
232
|
+
dir: /home/user/project-b
|
|
233
|
+
```
|
|
95
234
|
|
|
96
235
|
```bash
|
|
97
|
-
|
|
98
|
-
ttyd-mux start --
|
|
99
|
-
ttyd-mux stop <name> # Stop session / セッション停止
|
|
100
|
-
ttyd-mux stop --all # Stop all sessions / 全セッション停止
|
|
101
|
-
ttyd-mux status # Show status / 状態表示
|
|
102
|
-
```
|
|
236
|
+
# Start daemon + all predefined sessions / デーモンと全セッションを起動
|
|
237
|
+
ttyd-mux daemon start --sessions
|
|
103
238
|
|
|
104
|
-
|
|
239
|
+
# Or select sessions interactively / またはインタラクティブに選択
|
|
240
|
+
ttyd-mux daemon start -s
|
|
105
241
|
|
|
106
|
-
|
|
107
|
-
ttyd-mux
|
|
242
|
+
# Stop daemon + all sessions / デーモンと全セッションを停止
|
|
243
|
+
ttyd-mux daemon stop --stop-sessions
|
|
108
244
|
```
|
|
109
245
|
|
|
110
|
-
|
|
246
|
+
---
|
|
111
247
|
|
|
112
|
-
|
|
113
|
-
ttyd-mux daemon # Start daemon / デーモン起動
|
|
114
|
-
ttyd-mux daemon -f # Start in foreground (debug) / フォアグラウンドで起動(デバッグ用)
|
|
115
|
-
ttyd-mux shutdown # Stop daemon / デーモン終了
|
|
116
|
-
```
|
|
248
|
+
## Commands / コマンド
|
|
117
249
|
|
|
118
|
-
###
|
|
250
|
+
### Session Commands / セッションコマンド
|
|
119
251
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
252
|
+
| Command | Description |
|
|
253
|
+
|---------|-------------|
|
|
254
|
+
| `ttyd-mux up` | Start session for current directory / セッション起動 |
|
|
255
|
+
| `ttyd-mux down` | Stop session for current directory / セッション停止 |
|
|
256
|
+
| `ttyd-mux down --kill-tmux` | Stop session and terminate tmux / tmux も終了 |
|
|
257
|
+
| `ttyd-mux status` | Show daemon and session status / 状態表示 |
|
|
258
|
+
| `ttyd-mux list` | List active sessions / セッション一覧 |
|
|
259
|
+
| `ttyd-mux list -l` | List with details (port, directory) / 詳細表示 |
|
|
260
|
+
| `ttyd-mux list --url` | List with access URLs / URL 表示 |
|
|
261
|
+
| `ttyd-mux attach [name]` | Attach to tmux session directly / tmux に直接接続 |
|
|
262
|
+
|
|
263
|
+
### Daemon Control / デーモン制御
|
|
123
264
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
-
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
-
|
|
131
|
-
|
|
132
|
-
`
|
|
133
|
-
|
|
134
|
-
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
265
|
+
| Command | Description |
|
|
266
|
+
|---------|-------------|
|
|
267
|
+
| `ttyd-mux daemon start` | Start daemon only / デーモンのみ起動 |
|
|
268
|
+
| `ttyd-mux daemon start --sessions` | Start daemon + all predefined sessions / 全セッションも起動 |
|
|
269
|
+
| `ttyd-mux daemon start -s` | Start daemon + select sessions / 選択して起動 |
|
|
270
|
+
| `ttyd-mux daemon start -f` | Start in foreground (debug) / フォアグラウンド起動 |
|
|
271
|
+
| `ttyd-mux daemon stop` | Stop daemon / デーモン停止 |
|
|
272
|
+
| `ttyd-mux daemon stop -s` | Stop all sessions + daemon / セッションも停止 |
|
|
273
|
+
| `ttyd-mux daemon stop -s --kill-tmux` | Stop all + terminate tmux / tmux も終了 |
|
|
274
|
+
| `ttyd-mux daemon reload` | Reload config (hot-reload) / 設定リロード |
|
|
275
|
+
| `ttyd-mux daemon restart` | Restart daemon / デーモン再起動 |
|
|
276
|
+
|
|
277
|
+
### Utilities / ユーティリティ
|
|
278
|
+
|
|
279
|
+
| Command | Description |
|
|
280
|
+
|---------|-------------|
|
|
281
|
+
| `ttyd-mux doctor` | Check dependencies and configuration / 診断 |
|
|
282
|
+
| `ttyd-mux deploy` | Generate static files (for static mode) / 静的ファイル生成 |
|
|
283
|
+
|
|
284
|
+
### Caddy Integration / Caddy 連携
|
|
285
|
+
|
|
286
|
+
| Command | Description |
|
|
287
|
+
|---------|-------------|
|
|
288
|
+
| `ttyd-mux caddy setup` | Add route via Caddy Admin API / ルート追加 |
|
|
289
|
+
| `ttyd-mux caddy remove` | Remove route / ルート削除 |
|
|
290
|
+
| `ttyd-mux caddy status` | Show routes in Caddy / ルート確認 |
|
|
291
|
+
| `ttyd-mux caddy sync` | Sync routes (static mode) / ルート同期 |
|
|
292
|
+
| `ttyd-mux caddy snippet` | Show Caddyfile snippet / スニペット表示 |
|
|
293
|
+
|
|
294
|
+
---
|
|
139
295
|
|
|
140
296
|
## Configuration / 設定
|
|
141
297
|
|
|
@@ -162,47 +318,35 @@ base_port: 7600
|
|
|
162
318
|
daemon_port: 7680
|
|
163
319
|
|
|
164
320
|
# Listen addresses (default: IPv4 + IPv6 localhost)
|
|
165
|
-
# リッスンアドレス(デフォルト: IPv4 + IPv6 localhost)
|
|
166
321
|
listen_addresses:
|
|
167
322
|
- "127.0.0.1"
|
|
168
323
|
- "::1"
|
|
169
|
-
# - "0.0.0.0" # Allow external access / 外部からのアクセスを許可する場合
|
|
170
|
-
|
|
171
|
-
# Unix socket listeners (optional, for reverse proxy integration)
|
|
172
|
-
# Unix ソケットリスナー(オプション、リバースプロキシ連携用)
|
|
173
|
-
listen_sockets:
|
|
174
|
-
# - /run/ttyd-mux.sock # Caddy: reverse_proxy unix//run/ttyd-mux.sock
|
|
175
|
-
|
|
176
|
-
# Auto-attach to tmux on session start (default: true)
|
|
177
|
-
# セッション起動時に自動でtmuxにアタッチ(デフォルト: true)
|
|
178
|
-
auto_attach: true
|
|
179
324
|
|
|
180
325
|
# Proxy mode: "proxy" (default) or "static"
|
|
181
|
-
#
|
|
182
|
-
# -
|
|
183
|
-
# - static: Sessions are accessed directly via Caddy (lower latency)
|
|
326
|
+
# - proxy: All traffic goes through daemon (supports toolbar)
|
|
327
|
+
# - static: Sessions accessed directly via Caddy (lower latency)
|
|
184
328
|
proxy_mode: proxy
|
|
185
329
|
|
|
186
|
-
# Hostname for Caddy integration
|
|
187
|
-
# Caddy連携用のホスト名(caddy/deployコマンドで使用)
|
|
330
|
+
# Hostname for Caddy integration
|
|
188
331
|
hostname: example.com
|
|
189
332
|
|
|
190
|
-
#
|
|
191
|
-
|
|
333
|
+
# Toolbar settings (proxy mode only)
|
|
334
|
+
toolbar:
|
|
335
|
+
font_size_default_mobile: 32
|
|
336
|
+
font_size_default_pc: 14
|
|
337
|
+
font_size_min: 10
|
|
338
|
+
font_size_max: 48
|
|
192
339
|
|
|
193
|
-
# Predefined sessions
|
|
340
|
+
# Predefined sessions for static usage / 静的利用のためのセッション定義
|
|
194
341
|
sessions:
|
|
195
342
|
- name: project-a
|
|
196
343
|
dir: /home/user/project-a
|
|
197
|
-
path: /project-a
|
|
198
|
-
port_offset: 1
|
|
199
|
-
|
|
200
344
|
- name: project-b
|
|
201
345
|
dir: /home/user/project-b
|
|
202
|
-
path: /project-b
|
|
203
|
-
port_offset: 2
|
|
204
346
|
```
|
|
205
347
|
|
|
348
|
+
---
|
|
349
|
+
|
|
206
350
|
## Architecture / アーキテクチャ
|
|
207
351
|
|
|
208
352
|
### Proxy Mode (default) / プロキシモード(デフォルト)
|
|
@@ -218,12 +362,13 @@ sessions:
|
|
|
218
362
|
└─────────┘ │ │ │ project-b) │
|
|
219
363
|
│ - Portal │ └─────────────────┘
|
|
220
364
|
│ - Proxy │
|
|
365
|
+
│ - Toolbar │
|
|
221
366
|
│ - API │
|
|
222
367
|
└──────────────┘
|
|
223
368
|
```
|
|
224
369
|
|
|
225
370
|
- **Caddy**: Forwards external requests to ttyd-mux / 外部からのリクエストを ttyd-mux に転送
|
|
226
|
-
- **ttyd-mux daemon**: Portal + reverse proxy
|
|
371
|
+
- **ttyd-mux daemon**: Portal + reverse proxy + toolbar injection / ポータル + プロキシ + ツールバー注入
|
|
227
372
|
- **ttyd**: Web terminal for each session (runs tmux) / 各セッションの Web ターミナル(tmux を起動)
|
|
228
373
|
|
|
229
374
|
### Static Mode / スタティックモード
|
|
@@ -240,7 +385,44 @@ sessions:
|
|
|
240
385
|
|
|
241
386
|
- Lower latency (no intermediate proxy) / 低レイテンシ(中間プロキシなし)
|
|
242
387
|
- Static portal (no daemon needed at runtime) / 静的ポータル(実行時デーモン不要)
|
|
243
|
-
- No
|
|
388
|
+
- No toolbar support / ツールバー非対応
|
|
389
|
+
|
|
390
|
+
### Session Lifecycle / セッションのライフサイクル
|
|
391
|
+
|
|
392
|
+
Each session consists of three independent processes:
|
|
393
|
+
|
|
394
|
+
各セッションは3つの独立したプロセスで構成されています:
|
|
395
|
+
|
|
396
|
+
```
|
|
397
|
+
ttyd-mux daemon (manages sessions)
|
|
398
|
+
│
|
|
399
|
+
└── ttyd (web terminal server)
|
|
400
|
+
│
|
|
401
|
+
└── tmux session (terminal multiplexer)
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
**What happens when stopping:**
|
|
405
|
+
|
|
406
|
+
**停止時の挙動:**
|
|
407
|
+
|
|
408
|
+
| Command | daemon | ttyd | tmux |
|
|
409
|
+
|---------|--------|------|------|
|
|
410
|
+
| `daemon stop` | Stops | Keeps running | Keeps running |
|
|
411
|
+
| `daemon stop -s` | Stops | Stops | **Keeps running** |
|
|
412
|
+
| `daemon stop -s --kill-tmux` | Stops | Stops | Stops |
|
|
413
|
+
| `down` | - | Stops | **Keeps running** |
|
|
414
|
+
| `down --kill-tmux` | - | Stops | Stops |
|
|
415
|
+
| `exit` in terminal | - | Stops | Stops |
|
|
416
|
+
|
|
417
|
+
- By default, tmux sessions persist even when ttyd or daemon is stopped
|
|
418
|
+
- Restarting with `ttyd-mux up` reconnects to existing tmux session
|
|
419
|
+
- Use `--kill-tmux` flag to fully terminate tmux sessions
|
|
420
|
+
|
|
421
|
+
- デフォルトでは tmux セッションは ttyd やデーモンを停止しても残ります
|
|
422
|
+
- `ttyd-mux up` で再起動すると既存の tmux セッションに再接続します
|
|
423
|
+
- `--kill-tmux` フラグで tmux セッションも完全に終了できます
|
|
424
|
+
|
|
425
|
+
---
|
|
244
426
|
|
|
245
427
|
## Toolbar Features / ツールバー機能
|
|
246
428
|
|
|
@@ -248,20 +430,45 @@ In proxy mode, ttyd-mux injects a toolbar for improved input experience:
|
|
|
248
430
|
|
|
249
431
|
プロキシモードでは、入力体験向上のためツールバーが注入されます:
|
|
250
432
|
|
|
251
|
-
### Mobile
|
|
433
|
+
### Mobile / モバイル
|
|
434
|
+
|
|
435
|
+
- **IME Input**: Text field with virtual keyboard support / 日本語 IME 対応テキスト入力
|
|
436
|
+
- **Touch Pinch Zoom**: Two-finger pinch to resize font / 2本指ピンチでフォントサイズ変更
|
|
437
|
+
- **Double-tap Enter**: Double-tap to send Enter key / ダブルタップで Enter 送信
|
|
438
|
+
- **Scroll Buttons**: PgUp/PgDn for scrollback / スクロールバック用ボタン
|
|
439
|
+
- **Minimize Mode**: Collapse toolbar for more terminal space / ツールバー最小化
|
|
440
|
+
|
|
441
|
+
### PC Browser / PC ブラウザ
|
|
442
|
+
|
|
443
|
+
- **Ctrl+Scroll Zoom**: Mouse wheel with Ctrl key / Ctrl+マウスホイールでサイズ変更
|
|
444
|
+
- **Trackpad Pinch Zoom** (Mac): Two-finger pinch gesture / トラックパッドピンチ
|
|
445
|
+
- **Ctrl+J Toggle**: Show/hide toolbar / ツールバー表示切替
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
## PWA Support / PWA 対応
|
|
252
450
|
|
|
253
|
-
-
|
|
254
|
-
- **Touch Pinch Zoom**: Two-finger pinch to resize terminal font (requires Ctrl/Shift button) / 2本指ピンチでフォントサイズ変更(Ctrl/Shift ボタン押下時)
|
|
255
|
-
- **Double-tap Enter**: Double-tap to send Enter key / ダブルタップで Enter キー送信
|
|
256
|
-
- **Minimize Mode**: Compact toolbar showing only input field / コンパクト表示(入力フィールドのみ)
|
|
257
|
-
- **Onboarding Tips**: First-time usage hints / 初回利用時のヒント表示
|
|
451
|
+
ttyd-mux supports Progressive Web App (PWA) for a native app-like experience:
|
|
258
452
|
|
|
259
|
-
|
|
453
|
+
ttyd-mux はネイティブアプリのような体験のため PWA に対応しています:
|
|
260
454
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
- **
|
|
264
|
-
- **
|
|
455
|
+
### Features / 機能
|
|
456
|
+
|
|
457
|
+
- **Fullscreen Mode**: No browser address bar / アドレスバーなしのフルスクリーン
|
|
458
|
+
- **Home Screen Icon**: Add to home screen on iOS/Android / ホーム画面にアイコン追加
|
|
459
|
+
- **Auto Reconnect**: Automatically reloads when returning from background / バックグラウンドから復帰時に自動再接続
|
|
460
|
+
|
|
461
|
+
### How to Install / インストール方法
|
|
462
|
+
|
|
463
|
+
**Android (Chrome):**
|
|
464
|
+
1. Open portal page / ポータルページを開く
|
|
465
|
+
2. Menu → "Add to Home screen" / メニュー → 「ホーム画面に追加」
|
|
466
|
+
|
|
467
|
+
**iOS (Safari):**
|
|
468
|
+
1. Open portal page / ポータルページを開く
|
|
469
|
+
2. Share → "Add to Home Screen" / 共有 → 「ホーム画面に追加」
|
|
470
|
+
|
|
471
|
+
---
|
|
265
472
|
|
|
266
473
|
## Caddy Integration / Caddy との連携
|
|
267
474
|
|
|
@@ -291,29 +498,28 @@ handle /ttyd-mux/* {
|
|
|
291
498
|
}
|
|
292
499
|
```
|
|
293
500
|
|
|
294
|
-
###
|
|
501
|
+
### Authentication / 認証
|
|
295
502
|
|
|
296
|
-
For
|
|
503
|
+
For external access, configure authentication in Caddy:
|
|
297
504
|
|
|
298
|
-
|
|
505
|
+
外部公開時は Caddy で認証を設定:
|
|
299
506
|
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
507
|
+
```caddyfile
|
|
508
|
+
example.com {
|
|
509
|
+
# Basic authentication
|
|
510
|
+
basicauth /ttyd-mux/* {
|
|
511
|
+
user $2a$14$... # bcrypt hash
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
handle /ttyd-mux/* {
|
|
515
|
+
reverse_proxy 127.0.0.1:7680
|
|
516
|
+
}
|
|
517
|
+
}
|
|
304
518
|
```
|
|
305
519
|
|
|
306
|
-
|
|
307
|
-
# Generate static portal and Caddyfile snippet
|
|
308
|
-
# 静的ポータルと Caddyfile スニペットを生成
|
|
309
|
-
ttyd-mux deploy
|
|
310
|
-
|
|
311
|
-
# Sync routes after starting/stopping sessions
|
|
312
|
-
# セッション開始/停止後にルートを同期
|
|
313
|
-
ttyd-mux caddy sync
|
|
314
|
-
```
|
|
520
|
+
See [docs/caddy-setup.md](docs/caddy-setup.md) for details, including OAuth setup.
|
|
315
521
|
|
|
316
|
-
|
|
522
|
+
---
|
|
317
523
|
|
|
318
524
|
## File Structure / ファイル構成
|
|
319
525
|
|
|
@@ -326,14 +532,24 @@ See [docs/caddy-setup.md](docs/caddy-setup.md) for details, including authentica
|
|
|
326
532
|
ttyd-mux.sock # Daemon communication socket / デーモン通信用ソケット
|
|
327
533
|
```
|
|
328
534
|
|
|
535
|
+
---
|
|
536
|
+
|
|
329
537
|
## Development / 開発
|
|
330
538
|
|
|
331
539
|
```bash
|
|
540
|
+
# Clone repository
|
|
541
|
+
git clone https://github.com/cuzic/ttyd-mux.git
|
|
542
|
+
cd ttyd-mux
|
|
543
|
+
|
|
544
|
+
# Install dependencies
|
|
545
|
+
bun install
|
|
546
|
+
|
|
332
547
|
# Run in development / 開発実行
|
|
333
548
|
bun run src/index.ts <command>
|
|
334
549
|
|
|
335
550
|
# Test / テスト
|
|
336
|
-
bun test
|
|
551
|
+
bun test # Unit tests
|
|
552
|
+
bun run test:e2e # E2E tests (Playwright)
|
|
337
553
|
|
|
338
554
|
# Type check / 型チェック
|
|
339
555
|
bun run typecheck
|
|
@@ -341,10 +557,22 @@ bun run typecheck
|
|
|
341
557
|
# Lint / リント
|
|
342
558
|
bun run check
|
|
343
559
|
|
|
344
|
-
# Build
|
|
345
|
-
bun build
|
|
560
|
+
# Build / ビルド
|
|
561
|
+
bun run build
|
|
346
562
|
```
|
|
347
563
|
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
## Contributing / 貢献
|
|
567
|
+
|
|
568
|
+
Issues and Pull Requests are welcome!
|
|
569
|
+
|
|
570
|
+
Issue や Pull Request を歓迎します!
|
|
571
|
+
|
|
572
|
+
See [CLAUDE.md](CLAUDE.md) for development guidelines.
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
348
576
|
## License / ライセンス
|
|
349
577
|
|
|
350
578
|
MIT
|
|
@@ -15,12 +15,19 @@ export declare function getSessions(config: Config): Promise<SessionResponse[]>;
|
|
|
15
15
|
* Start a new session
|
|
16
16
|
*/
|
|
17
17
|
export declare function startSession(config: Config, request: StartSessionRequest): Promise<SessionResponse>;
|
|
18
|
+
export interface StopSessionOptions {
|
|
19
|
+
killTmux?: boolean;
|
|
20
|
+
}
|
|
18
21
|
/**
|
|
19
22
|
* Stop a session
|
|
20
23
|
*/
|
|
21
|
-
export declare function stopSession(config: Config, name: string): Promise<void>;
|
|
24
|
+
export declare function stopSession(config: Config, name: string, options?: StopSessionOptions): Promise<void>;
|
|
25
|
+
export interface ShutdownOptions {
|
|
26
|
+
stopSessions?: boolean;
|
|
27
|
+
killTmux?: boolean;
|
|
28
|
+
}
|
|
22
29
|
/**
|
|
23
30
|
* Request daemon shutdown
|
|
24
31
|
*/
|
|
25
|
-
export declare function requestShutdown(config: Config): Promise<void>;
|
|
32
|
+
export declare function requestShutdown(config: Config, options?: ShutdownOptions): Promise<void>;
|
|
26
33
|
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/client/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EACN,eAAe,EACf,mBAAmB,EACnB,cAAc,EACf,MAAM,mBAAmB,CAAC;AAa3B;;GAEG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAChC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,CAAC,CAAC,CAgBZ;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAEjE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAEtE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,eAAe,CAAC,CAE1B;AAED;;GAEG;AACH,wBAAsB,WAAW,
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/client/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EACN,eAAe,EACf,mBAAmB,EACnB,cAAc,EACf,MAAM,mBAAmB,CAAC;AAa3B;;GAEG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAChC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,CAAC,CAAC,CAgBZ;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAEjE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAEtE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,eAAe,CAAC,CAE1B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9F"}
|
|
@@ -45,15 +45,16 @@ export function startSession(config, request) {
|
|
|
45
45
|
/**
|
|
46
46
|
* Stop a session
|
|
47
47
|
*/
|
|
48
|
-
export async function stopSession(config, name) {
|
|
49
|
-
|
|
48
|
+
export async function stopSession(config, name, options) {
|
|
49
|
+
const query = options?.killTmux ? '?killTmux=true' : '';
|
|
50
|
+
await apiRequest(config, 'DELETE', `/api/sessions/${encodeURIComponent(name)}${query}`);
|
|
50
51
|
}
|
|
51
52
|
/**
|
|
52
53
|
* Request daemon shutdown
|
|
53
54
|
*/
|
|
54
|
-
export async function requestShutdown(config) {
|
|
55
|
+
export async function requestShutdown(config, options) {
|
|
55
56
|
try {
|
|
56
|
-
await apiRequest(config, 'POST', '/api/shutdown');
|
|
57
|
+
await apiRequest(config, 'POST', '/api/shutdown', options);
|
|
57
58
|
}
|
|
58
59
|
catch {
|
|
59
60
|
// Server will shut down, so connection may be lost
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/client/api-client.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;GAEG;AACH,SAAS,YAAY,CAAC,MAAc;IAClC,MAAM,IAAI,GAAG,mBAAmB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC;IAChD,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,MAAM,CAAC,WAAW,CAAC;IAChD,OAAO,oBAAoB,IAAI,EAAE,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAc,EACd,MAAc,EACd,IAAY,EACZ,IAAc;IAEd,MAAM,GAAG,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,SAAS,GAAG,IAAI,EAAE,CAAC;IAEhE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM;QACN,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,SAAS;QAClE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KAC9C,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAEnC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAE,IAA2B,CAAC,KAAK,IAAI,gBAAgB,CAAC,CAAC;IAC1E,CAAC;IAED,OAAO,IAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,OAAO,UAAU,CAAiB,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;AAClE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,UAAU,CAAoB,MAAM,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;AACvE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,OAA4B;IAE5B,OAAO,UAAU,CAAkB,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;AAC/E,CAAC;
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/client/api-client.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;GAEG;AACH,SAAS,YAAY,CAAC,MAAc;IAClC,MAAM,IAAI,GAAG,mBAAmB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC;IAChD,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,MAAM,CAAC,WAAW,CAAC;IAChD,OAAO,oBAAoB,IAAI,EAAE,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAc,EACd,MAAc,EACd,IAAY,EACZ,IAAc;IAEd,MAAM,GAAG,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,SAAS,GAAG,IAAI,EAAE,CAAC;IAEhE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM;QACN,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,SAAS;QAClE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KAC9C,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAEnC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAE,IAA2B,CAAC,KAAK,IAAI,gBAAgB,CAAC,CAAC;IAC1E,CAAC;IAED,OAAO,IAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,OAAO,UAAU,CAAiB,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;AAClE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,UAAU,CAAoB,MAAM,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;AACvE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,OAA4B;IAE5B,OAAO,UAAU,CAAkB,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;AAC/E,CAAC;AAMD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAc,EACd,IAAY,EACZ,OAA4B;IAE5B,MAAM,KAAK,GAAG,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,MAAM,UAAU,CACd,MAAM,EACN,QAAQ,EACR,iBAAiB,kBAAkB,CAAC,IAAI,CAAC,GAAG,KAAK,EAAE,CACpD,CAAC;AACJ,CAAC;AAOD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAc,EAAE,OAAyB;IAC7E,IAAI,CAAC;QACH,MAAM,UAAU,CAAuB,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;IACnF,CAAC;IAAC,MAAM,CAAC;QACP,mDAAmD;IACrD,CAAC;AACH,CAAC"}
|