nterminal 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +12 -0
- package/LICENSE +674 -0
- package/README.md +181 -0
- package/assets/brand/app-icon-1024.png +0 -0
- package/assets/brand/app-icon-384.png +0 -0
- package/assets/brand/apple-touch-icon-360.png +0 -0
- package/assets/brand/favicon-32.png +0 -0
- package/assets/brand/favicon-64.png +0 -0
- package/assets/brand/favicon-96.png +0 -0
- package/assets/brand/favicon.svg +4 -0
- package/assets/brand/nterminal-mark-64.png +0 -0
- package/assets/brand/nterminal-mark.svg +4 -0
- package/assets/brand/nterminal-wordmark-486x68.png +0 -0
- package/assets/brand/nterminal-wordmark.svg +3 -0
- package/assets/screenshot/scr.png +0 -0
- package/bin/nterminal.js +114 -0
- package/dist/client/apple-touch-icon.png +0 -0
- package/dist/client/assets/MarkdownPreview-BeDi-V7k.js +29 -0
- package/dist/client/assets/MesloLGS-NF-Bold-Italic-DwFsXcwX.ttf +0 -0
- package/dist/client/assets/MesloLGS-NF-Bold-kN-HYz-g.ttf +0 -0
- package/dist/client/assets/MesloLGS-NF-Italic-CMg1T6-G.ttf +0 -0
- package/dist/client/assets/MesloLGS-NF-Regular-Cxr8pvCI.ttf +0 -0
- package/dist/client/assets/index-BQkKYjXb.js +33 -0
- package/dist/client/assets/index-WqeS39wU.css +1 -0
- package/dist/client/assets/notifications/character-2258.mp4 +0 -0
- package/dist/client/assets/notifications/character-2260.mp4 +0 -0
- package/dist/client/assets/notifications/character-2272.mp4 +0 -0
- package/dist/client/brand/nterminal-mark-64.png +0 -0
- package/dist/client/brand/nterminal-mark.svg +4 -0
- package/dist/client/brand/nterminal-wordmark-486x68.png +0 -0
- package/dist/client/brand/nterminal-wordmark.svg +3 -0
- package/dist/client/icons/app-icon-1024.png +0 -0
- package/dist/client/icons/app-icon-384.png +0 -0
- package/dist/client/icons/favicon-32.png +0 -0
- package/dist/client/icons/favicon-64.png +0 -0
- package/dist/client/icons/favicon-96.png +0 -0
- package/dist/client/icons/favicon.svg +4 -0
- package/dist/client/index.html +21 -0
- package/dist/client/manifest.webmanifest +24 -0
- package/dist/scripts/generate-secrets.js +3 -0
- package/dist/scripts/generate-secrets.js.map +1 -0
- package/dist/scripts/onboarding.js +814 -0
- package/dist/scripts/onboarding.js.map +1 -0
- package/dist/scripts/proxySetup.js +1007 -0
- package/dist/scripts/proxySetup.js.map +1 -0
- package/dist/server/agent/agentAuth.d.ts +6 -0
- package/dist/server/agent/agentAuth.js +35 -0
- package/dist/server/agent/agentAuth.js.map +1 -0
- package/dist/server/agent/agentProxy.d.ts +5 -0
- package/dist/server/agent/agentProxy.js +63 -0
- package/dist/server/agent/agentProxy.js.map +1 -0
- package/dist/server/agent/agentRoutes.d.ts +9 -0
- package/dist/server/agent/agentRoutes.js +327 -0
- package/dist/server/agent/agentRoutes.js.map +1 -0
- package/dist/server/agent/agentWebSocketProxy.d.ts +3 -0
- package/dist/server/agent/agentWebSocketProxy.js +65 -0
- package/dist/server/agent/agentWebSocketProxy.js.map +1 -0
- package/dist/server/auth/authService.d.ts +100 -0
- package/dist/server/auth/authService.js +415 -0
- package/dist/server/auth/authService.js.map +1 -0
- package/dist/server/auth/cookies.d.ts +11 -0
- package/dist/server/auth/cookies.js +39 -0
- package/dist/server/auth/cookies.js.map +1 -0
- package/dist/server/auth/ipMatch.d.ts +14 -0
- package/dist/server/auth/ipMatch.js +103 -0
- package/dist/server/auth/ipMatch.js.map +1 -0
- package/dist/server/auth/rateLimit.d.ts +17 -0
- package/dist/server/auth/rateLimit.js +25 -0
- package/dist/server/auth/rateLimit.js.map +1 -0
- package/dist/server/auth/totpService.d.ts +10 -0
- package/dist/server/auth/totpService.js +37 -0
- package/dist/server/auth/totpService.js.map +1 -0
- package/dist/server/config.d.ts +27 -0
- package/dist/server/config.js +138 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/files/fileExplorerService.d.ts +38 -0
- package/dist/server/files/fileExplorerService.js +551 -0
- package/dist/server/files/fileExplorerService.js.map +1 -0
- package/dist/server/files/rootToken.d.ts +51 -0
- package/dist/server/files/rootToken.js +139 -0
- package/dist/server/files/rootToken.js.map +1 -0
- package/dist/server/http.d.ts +13 -0
- package/dist/server/http.js +69 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +45 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/routes/agentManagementRoutes.d.ts +9 -0
- package/dist/server/routes/agentManagementRoutes.js +304 -0
- package/dist/server/routes/agentManagementRoutes.js.map +1 -0
- package/dist/server/routes/authRoutes.d.ts +10 -0
- package/dist/server/routes/authRoutes.js +95 -0
- package/dist/server/routes/authRoutes.js.map +1 -0
- package/dist/server/routes/fileRoutes.d.ts +11 -0
- package/dist/server/routes/fileRoutes.js +185 -0
- package/dist/server/routes/fileRoutes.js.map +1 -0
- package/dist/server/routes/notificationAssetRoutes.d.ts +9 -0
- package/dist/server/routes/notificationAssetRoutes.js +280 -0
- package/dist/server/routes/notificationAssetRoutes.js.map +1 -0
- package/dist/server/routes/securityRoutes.d.ts +7 -0
- package/dist/server/routes/securityRoutes.js +53 -0
- package/dist/server/routes/securityRoutes.js.map +1 -0
- package/dist/server/routes/socketBackpressure.d.ts +26 -0
- package/dist/server/routes/socketBackpressure.js +63 -0
- package/dist/server/routes/socketBackpressure.js.map +1 -0
- package/dist/server/routes/terminalLayoutRoutes.d.ts +9 -0
- package/dist/server/routes/terminalLayoutRoutes.js +108 -0
- package/dist/server/routes/terminalLayoutRoutes.js.map +1 -0
- package/dist/server/routes/terminalRoutes.d.ts +14 -0
- package/dist/server/routes/terminalRoutes.js +177 -0
- package/dist/server/routes/terminalRoutes.js.map +1 -0
- package/dist/server/routes/terminalWebSocket.d.ts +9 -0
- package/dist/server/routes/terminalWebSocket.js +129 -0
- package/dist/server/routes/terminalWebSocket.js.map +1 -0
- package/dist/server/routes/totpRoutes.d.ts +7 -0
- package/dist/server/routes/totpRoutes.js +46 -0
- package/dist/server/routes/totpRoutes.js.map +1 -0
- package/dist/server/routes/updateRoutes.d.ts +7 -0
- package/dist/server/routes/updateRoutes.js +24 -0
- package/dist/server/routes/updateRoutes.js.map +1 -0
- package/dist/server/routes/uploadRoutes.d.ts +9 -0
- package/dist/server/routes/uploadRoutes.js +95 -0
- package/dist/server/routes/uploadRoutes.js.map +1 -0
- package/dist/server/storage/fileStore.d.ts +90 -0
- package/dist/server/storage/fileStore.js +275 -0
- package/dist/server/storage/fileStore.js.map +1 -0
- package/dist/server/system/stats.d.ts +2 -0
- package/dist/server/system/stats.js +37 -0
- package/dist/server/system/stats.js.map +1 -0
- package/dist/server/terminal/NodePtyAdapter.d.ts +4 -0
- package/dist/server/terminal/NodePtyAdapter.js +14 -0
- package/dist/server/terminal/NodePtyAdapter.js.map +1 -0
- package/dist/server/terminal/PtyAdapter.d.ts +57 -0
- package/dist/server/terminal/PtyAdapter.js +2 -0
- package/dist/server/terminal/PtyAdapter.js.map +1 -0
- package/dist/server/terminal/TerminalManager.d.ts +74 -0
- package/dist/server/terminal/TerminalManager.js +561 -0
- package/dist/server/terminal/TerminalManager.js.map +1 -0
- package/dist/server/terminal/TmuxPtyAdapter.d.ts +25 -0
- package/dist/server/terminal/TmuxPtyAdapter.js +543 -0
- package/dist/server/terminal/TmuxPtyAdapter.js.map +1 -0
- package/dist/server/terminal/codexTranscriptSource.d.ts +9 -0
- package/dist/server/terminal/codexTranscriptSource.js +144 -0
- package/dist/server/terminal/codexTranscriptSource.js.map +1 -0
- package/dist/server/terminal/cwdResolver.d.ts +8 -0
- package/dist/server/terminal/cwdResolver.js +37 -0
- package/dist/server/terminal/cwdResolver.js.map +1 -0
- package/dist/server/terminal/outputBuffer.d.ts +7 -0
- package/dist/server/terminal/outputBuffer.js +17 -0
- package/dist/server/terminal/outputBuffer.js.map +1 -0
- package/dist/server/terminal/transcriptHistory.d.ts +7 -0
- package/dist/server/terminal/transcriptHistory.js +315 -0
- package/dist/server/terminal/transcriptHistory.js.map +1 -0
- package/dist/server/update/gitUpdate.d.ts +27 -0
- package/dist/server/update/gitUpdate.js +241 -0
- package/dist/server/update/gitUpdate.js.map +1 -0
- package/dist/server/uploads/uploadPaths.d.ts +18 -0
- package/dist/server/uploads/uploadPaths.js +116 -0
- package/dist/server/uploads/uploadPaths.js.map +1 -0
- package/dist/server/uploads/uploadService.d.ts +21 -0
- package/dist/server/uploads/uploadService.js +230 -0
- package/dist/server/uploads/uploadService.js.map +1 -0
- package/dist/shared/layoutState.d.ts +6 -0
- package/dist/shared/layoutState.js +115 -0
- package/dist/shared/layoutState.js.map +1 -0
- package/dist/shared/notificationAssets.d.ts +9 -0
- package/dist/shared/notificationAssets.js +27 -0
- package/dist/shared/notificationAssets.js.map +1 -0
- package/dist/shared/protocol.d.ts +308 -0
- package/dist/shared/protocol.js +29 -0
- package/dist/shared/protocol.js.map +1 -0
- package/dist/shared/types.d.ts +56 -0
- package/dist/shared/types.js +2 -0
- package/dist/shared/types.js.map +1 -0
- package/docs/assets/nterminal-workspace.png +0 -0
- package/docs/configuration.md +97 -0
- package/docs/features.md +126 -0
- package/docs/onboarding.md +122 -0
- package/docs/operations.md +112 -0
- package/docs/terminal-history.md +54 -0
- package/package.json +85 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/assets/notifications/character-2258.mp4 +0 -0
- package/public/assets/notifications/character-2260.mp4 +0 -0
- package/public/assets/notifications/character-2272.mp4 +0 -0
- package/public/brand/nterminal-mark-64.png +0 -0
- package/public/brand/nterminal-mark.svg +4 -0
- package/public/brand/nterminal-wordmark-486x68.png +0 -0
- package/public/brand/nterminal-wordmark.svg +3 -0
- package/public/icons/app-icon-1024.png +0 -0
- package/public/icons/app-icon-384.png +0 -0
- package/public/icons/favicon-32.png +0 -0
- package/public/icons/favicon-64.png +0 -0
- package/public/icons/favicon-96.png +0 -0
- package/public/icons/favicon.svg +4 -0
- package/public/manifest.webmanifest +24 -0
- package/scripts/nterminalctl +588 -0
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { resolveProcessCwd } from './cwdResolver.js';
|
|
4
|
+
import { OutputBuffer } from './outputBuffer.js';
|
|
5
|
+
import { readTranscriptHistoryPage } from './transcriptHistory.js';
|
|
6
|
+
// Window for the output-rate component of busy detection. Slightly larger
|
|
7
|
+
// than the poll interval so a tab that just stopped emitting output
|
|
8
|
+
// transitions to idle on the very next poll (rather than lagging a tick),
|
|
9
|
+
// and small enough that "command finished" notifications fire within ~3s
|
|
10
|
+
// of the prompt returning.
|
|
11
|
+
const BUSY_OUTPUT_WINDOW_MS = 2_500;
|
|
12
|
+
// Interval between activity polls. Each tick spawns one `tmux list-panes`
|
|
13
|
+
// subprocess (~5-10ms) so even on a busy host with many terminals the
|
|
14
|
+
// overhead stays well under 1% CPU. 2000ms also caps the worst-case latency
|
|
15
|
+
// before a "command completed" notification reaches the operator at 2s,
|
|
16
|
+
// which is fast enough to feel responsive without spamming polls.
|
|
17
|
+
const STATUS_POLL_INTERVAL_MS = 2_000;
|
|
18
|
+
const HISTORY_PAGE_LINES = 1000;
|
|
19
|
+
const HISTORY_PAGE_MAX_LINES = 5000;
|
|
20
|
+
const HISTORY_CURSOR_PROBE_LINES = 1;
|
|
21
|
+
export class TerminalManager {
|
|
22
|
+
config;
|
|
23
|
+
ptyAdapter;
|
|
24
|
+
terminals = new Map();
|
|
25
|
+
resolveCwd;
|
|
26
|
+
now;
|
|
27
|
+
// Captured at construction so every spawn can compare a poll's
|
|
28
|
+
// pane_current_command against the configured shell to decide "is this
|
|
29
|
+
// terminal idle at a prompt or busy running something else?".
|
|
30
|
+
shellBasename;
|
|
31
|
+
statusPollTimer = null;
|
|
32
|
+
statusPollInflight = false;
|
|
33
|
+
constructor(config, ptyAdapter, options = {}) {
|
|
34
|
+
this.config = config;
|
|
35
|
+
this.ptyAdapter = ptyAdapter;
|
|
36
|
+
this.resolveCwd = options.resolveCwd ?? resolveProcessCwd;
|
|
37
|
+
this.now = options.now ?? (() => new Date());
|
|
38
|
+
this.shellBasename = path.basename(this.config.shell);
|
|
39
|
+
if (typeof this.ptyAdapter.pollSessions === 'function') {
|
|
40
|
+
this.startStatusPoller();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
startStatusPoller() {
|
|
44
|
+
if (this.statusPollTimer)
|
|
45
|
+
return;
|
|
46
|
+
this.statusPollTimer = setInterval(() => {
|
|
47
|
+
if (this.statusPollInflight)
|
|
48
|
+
return;
|
|
49
|
+
this.statusPollInflight = true;
|
|
50
|
+
void this.pollOnce().finally(() => {
|
|
51
|
+
this.statusPollInflight = false;
|
|
52
|
+
});
|
|
53
|
+
}, STATUS_POLL_INTERVAL_MS);
|
|
54
|
+
// Unref so the interval doesn't keep the Node event loop alive on its
|
|
55
|
+
// own — the HTTP server is what should be holding the process up.
|
|
56
|
+
this.statusPollTimer.unref?.();
|
|
57
|
+
}
|
|
58
|
+
async pollOnce() {
|
|
59
|
+
const poll = this.ptyAdapter.pollSessions;
|
|
60
|
+
if (!poll)
|
|
61
|
+
return;
|
|
62
|
+
let result;
|
|
63
|
+
try {
|
|
64
|
+
result = await poll.call(this.ptyAdapter);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const now = Date.now();
|
|
70
|
+
for (const [terminalId, { currentCommand, busy }] of result) {
|
|
71
|
+
const record = this.terminals.get(terminalId);
|
|
72
|
+
if (!record || record.summary.status !== 'running')
|
|
73
|
+
continue;
|
|
74
|
+
// Two complementary signals for "is this tab working":
|
|
75
|
+
// - kernel run state: catches CPU-bound work like npm install,
|
|
76
|
+
// vim :%s, codex executing a tool call locally
|
|
77
|
+
// - PTY output rate: catches I/O-bound work like codex streaming
|
|
78
|
+
// tokens or claude printing a response — those processes spend
|
|
79
|
+
// most of their time sleeping in epoll_wait (state S) but
|
|
80
|
+
// output is steadily flowing, which is what the operator
|
|
81
|
+
// actually means by "it's working"
|
|
82
|
+
// OR them together so either signal alone is enough.
|
|
83
|
+
const recentOutput = now - record.lastOutputAt < BUSY_OUTPUT_WINDOW_MS;
|
|
84
|
+
const nextActivity = busy || recentOutput ? 'busy' : 'idle';
|
|
85
|
+
const nextCommand = currentCommand === this.shellBasename ? null : currentCommand;
|
|
86
|
+
if (record.summary.activity === nextActivity &&
|
|
87
|
+
record.summary.currentCommand === nextCommand) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
record.summary.activity = nextActivity;
|
|
91
|
+
record.summary.currentCommand = nextCommand;
|
|
92
|
+
record.summary.updatedAt = this.timestamp();
|
|
93
|
+
this.publish(record, { type: 'terminal_updated', terminal: cloneSummary(record.summary) });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Allow the process to shut down cleanly without leaking the polling
|
|
97
|
+
// interval — called by the server's graceful-shutdown path.
|
|
98
|
+
dispose() {
|
|
99
|
+
if (this.statusPollTimer) {
|
|
100
|
+
clearInterval(this.statusPollTimer);
|
|
101
|
+
this.statusPollTimer = null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async createTerminal(options = {}) {
|
|
105
|
+
const cwd = await this.resolveInitialCwd(options);
|
|
106
|
+
const cols = normalizeDimension(options.cols, 80);
|
|
107
|
+
const rows = normalizeDimension(options.rows, 24);
|
|
108
|
+
const id = randomUUID();
|
|
109
|
+
const timestamp = this.timestamp();
|
|
110
|
+
const initialTitle = this.createTitle(cwd);
|
|
111
|
+
const pty = this.ptyAdapter.spawn({
|
|
112
|
+
sessionId: id,
|
|
113
|
+
shell: this.config.shell,
|
|
114
|
+
cwd,
|
|
115
|
+
cols,
|
|
116
|
+
rows,
|
|
117
|
+
env: terminalEnv(),
|
|
118
|
+
// Pass the initial title in so persistent adapters (tmux) name the
|
|
119
|
+
// session with it from the start — otherwise an immediate restart
|
|
120
|
+
// before the operator interacted would show a placeholder pill.
|
|
121
|
+
title: initialTitle
|
|
122
|
+
});
|
|
123
|
+
const record = {
|
|
124
|
+
summary: {
|
|
125
|
+
id,
|
|
126
|
+
title: initialTitle,
|
|
127
|
+
cwd,
|
|
128
|
+
pid: pty.pid,
|
|
129
|
+
cols,
|
|
130
|
+
rows,
|
|
131
|
+
createdAt: timestamp,
|
|
132
|
+
updatedAt: timestamp,
|
|
133
|
+
status: 'running',
|
|
134
|
+
exitCode: null
|
|
135
|
+
},
|
|
136
|
+
pty,
|
|
137
|
+
output: new OutputBuffer(),
|
|
138
|
+
subscribers: new Set(),
|
|
139
|
+
dataDisposable: { dispose: () => undefined },
|
|
140
|
+
exitDisposable: { dispose: () => undefined },
|
|
141
|
+
pauseCount: 0,
|
|
142
|
+
lastOutputAt: 0,
|
|
143
|
+
history: null
|
|
144
|
+
};
|
|
145
|
+
this.wireUpPty(record, pty);
|
|
146
|
+
this.terminals.set(id, record);
|
|
147
|
+
return cloneSummary(record.summary);
|
|
148
|
+
}
|
|
149
|
+
// Repopulate the in-memory record map with any persistent sessions the
|
|
150
|
+
// adapter is already holding for us — used at process start so that after
|
|
151
|
+
// `nterminalctl restart` or a NTerminal version update the operator's panes
|
|
152
|
+
// reattach to their live shells instead of being silently replaced by
|
|
153
|
+
// fresh ones. A no-op for adapters without persistence (NodePtyAdapter).
|
|
154
|
+
async restoreSessions() {
|
|
155
|
+
const existing = this.ptyAdapter.listExisting?.() ?? [];
|
|
156
|
+
const now = this.timestamp();
|
|
157
|
+
for (const session of existing) {
|
|
158
|
+
const sessionId = session.sessionId;
|
|
159
|
+
if (this.terminals.has(sessionId))
|
|
160
|
+
continue;
|
|
161
|
+
// Use the adapter-provided title (tmux's window name) when the
|
|
162
|
+
// operator had renamed the tab in a previous run — that's how a
|
|
163
|
+
// human-readable label survives NTerminal restarts. Fall back to a
|
|
164
|
+
// distinguishable placeholder when no name was set.
|
|
165
|
+
const restoredTitle = session.title?.trim() || `Terminal ${sessionId.slice(0, 6)}`;
|
|
166
|
+
this.terminals.set(sessionId, {
|
|
167
|
+
summary: {
|
|
168
|
+
id: sessionId,
|
|
169
|
+
// We don't know the original cwd/cols/rows after a restart — the
|
|
170
|
+
// adapter (tmux) holds the real shell state. Use sensible
|
|
171
|
+
// defaults; the browser will resize on connect and any cwd-aware
|
|
172
|
+
// feature (file explorer, refresh_cwd) repulls live values.
|
|
173
|
+
title: restoredTitle,
|
|
174
|
+
cwd: this.config.workspaceRoot,
|
|
175
|
+
pid: null,
|
|
176
|
+
cols: 80,
|
|
177
|
+
rows: 24,
|
|
178
|
+
createdAt: now,
|
|
179
|
+
updatedAt: now,
|
|
180
|
+
status: 'running',
|
|
181
|
+
exitCode: null
|
|
182
|
+
},
|
|
183
|
+
pty: null, // null = persisted but no local client attached yet
|
|
184
|
+
output: new OutputBuffer(),
|
|
185
|
+
subscribers: new Set(),
|
|
186
|
+
dataDisposable: { dispose: () => undefined },
|
|
187
|
+
exitDisposable: { dispose: () => undefined },
|
|
188
|
+
pauseCount: 0,
|
|
189
|
+
lastOutputAt: 0,
|
|
190
|
+
history: null
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
wireUpPty(record, pty) {
|
|
195
|
+
const id = record.summary.id;
|
|
196
|
+
record.pty = pty;
|
|
197
|
+
record.summary.pid = pty.pid;
|
|
198
|
+
record.summary.status = 'running';
|
|
199
|
+
record.summary.exitCode = null;
|
|
200
|
+
record.summary.updatedAt = this.timestamp();
|
|
201
|
+
record.dataDisposable = pty.onData((data) => {
|
|
202
|
+
record.output.push(data);
|
|
203
|
+
record.lastOutputAt = Date.now();
|
|
204
|
+
record.summary.updatedAt = this.timestamp();
|
|
205
|
+
this.publish(record, { type: 'output', terminalId: id, data });
|
|
206
|
+
});
|
|
207
|
+
record.exitDisposable = pty.onExit((event) => {
|
|
208
|
+
record.summary.status = 'exited';
|
|
209
|
+
record.summary.exitCode = event.exitCode;
|
|
210
|
+
record.summary.pid = null;
|
|
211
|
+
record.summary.updatedAt = this.timestamp();
|
|
212
|
+
record.pty = null;
|
|
213
|
+
this.publish(record, { type: 'exit', terminalId: id, exitCode: event.exitCode });
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
// Spawn a fresh local client for a restored session that hasn't been
|
|
217
|
+
// attached since startup. Called lazily on the first attachTerminal so
|
|
218
|
+
// sessions the operator never reopens don't consume processes.
|
|
219
|
+
reattachToSession(record) {
|
|
220
|
+
const pty = this.ptyAdapter.spawn({
|
|
221
|
+
sessionId: record.summary.id,
|
|
222
|
+
shell: this.config.shell,
|
|
223
|
+
cwd: record.summary.cwd,
|
|
224
|
+
cols: record.summary.cols,
|
|
225
|
+
rows: record.summary.rows,
|
|
226
|
+
env: terminalEnv()
|
|
227
|
+
});
|
|
228
|
+
this.wireUpPty(record, pty);
|
|
229
|
+
}
|
|
230
|
+
captureTerminalHistoryCursor(record) {
|
|
231
|
+
const capture = this.ptyAdapter.captureHistory?.(record.summary.id, {
|
|
232
|
+
beforeLine: 0,
|
|
233
|
+
limit: HISTORY_CURSOR_PROBE_LINES
|
|
234
|
+
});
|
|
235
|
+
if (!capture) {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
if (!capture.hasMore && capture.endLine < capture.startLine) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
startLine: 0,
|
|
243
|
+
endLine: 0,
|
|
244
|
+
hasMore: capture.hasMore || capture.endLine >= capture.startLine
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
listTerminals() {
|
|
248
|
+
return [...this.terminals.values()].map((record) => cloneSummary(record.summary));
|
|
249
|
+
}
|
|
250
|
+
getTerminal(id) {
|
|
251
|
+
const record = this.terminals.get(id);
|
|
252
|
+
return record ? cloneSummary(record.summary) : null;
|
|
253
|
+
}
|
|
254
|
+
getOutputSnapshot(id) {
|
|
255
|
+
return this.terminals.get(id)?.output.snapshot() ?? null;
|
|
256
|
+
}
|
|
257
|
+
getTerminalHistory(id, options = {}) {
|
|
258
|
+
const record = this.terminals.get(id);
|
|
259
|
+
if (!record || record.summary.status !== 'running') {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
const limit = normalizeHistoryLimit(options.limit);
|
|
263
|
+
const capture = this.ptyAdapter.captureHistory?.(id, {
|
|
264
|
+
...(options.beforeLine !== undefined ? { beforeLine: options.beforeLine } : {}),
|
|
265
|
+
limit
|
|
266
|
+
});
|
|
267
|
+
if (!capture) {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
return {
|
|
271
|
+
terminalId: id,
|
|
272
|
+
startLine: capture.startLine,
|
|
273
|
+
endLine: capture.endLine,
|
|
274
|
+
hasMore: capture.hasMore,
|
|
275
|
+
output: capture.output
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
getTerminalTranscriptHistory(id, options = {}) {
|
|
279
|
+
const record = this.terminals.get(id);
|
|
280
|
+
if (!record || record.summary.status !== 'running') {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
const source = this.ptyAdapter.resolveTranscriptSource?.(id);
|
|
284
|
+
if (!source) {
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
return readTranscriptHistoryPage(id, source, options);
|
|
288
|
+
}
|
|
289
|
+
getTerminalTranscriptSource(id) {
|
|
290
|
+
const record = this.terminals.get(id);
|
|
291
|
+
if (!record || record.summary.status !== 'running') {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
const source = this.ptyAdapter.resolveTranscriptSource?.(id);
|
|
295
|
+
if (!source) {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
terminalId: id,
|
|
300
|
+
source: { provider: source.provider, sessionId: source.sessionId }
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
async resolveTerminalCwd(id) {
|
|
304
|
+
const record = this.terminals.get(id);
|
|
305
|
+
if (!record || !this.ensureAttached(record)) {
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
return this.safeResolveCwd(record.pty.pid);
|
|
309
|
+
}
|
|
310
|
+
// Push a new human title to the record and the persistence adapter so the
|
|
311
|
+
// operator's rename of a tab survives both detach (the title shows up on
|
|
312
|
+
// the pill) and NTerminal restart (tmux holds the title as its window
|
|
313
|
+
// name). Returns the updated summary, or null when the id is unknown.
|
|
314
|
+
renameTerminal(id, title) {
|
|
315
|
+
const record = this.terminals.get(id);
|
|
316
|
+
if (!record)
|
|
317
|
+
return null;
|
|
318
|
+
const trimmed = title.trim();
|
|
319
|
+
if (!trimmed || trimmed === record.summary.title) {
|
|
320
|
+
return cloneSummary(record.summary);
|
|
321
|
+
}
|
|
322
|
+
record.summary.title = trimmed;
|
|
323
|
+
record.summary.updatedAt = this.timestamp();
|
|
324
|
+
this.ptyAdapter.setSessionTitle?.(id, trimmed);
|
|
325
|
+
this.publish(record, { type: 'terminal_updated', terminal: cloneSummary(record.summary) });
|
|
326
|
+
return cloneSummary(record.summary);
|
|
327
|
+
}
|
|
328
|
+
async refreshTerminalCwd(id) {
|
|
329
|
+
const record = this.terminals.get(id);
|
|
330
|
+
if (!record || !this.ensureAttached(record)) {
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
await this.refreshCwd(record);
|
|
334
|
+
return cloneSummary(record.summary);
|
|
335
|
+
}
|
|
336
|
+
attachTerminal(id, subscriber, options = {}) {
|
|
337
|
+
const record = this.terminals.get(id);
|
|
338
|
+
if (!record) {
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
// Lazy attach for restored sessions: if the record exists in memory but
|
|
342
|
+
// has no local PTY client (we recovered the sessionId from the adapter
|
|
343
|
+
// at startup but haven't reconnected yet), spawn one now. From the
|
|
344
|
+
// client's perspective this is indistinguishable from a normal attach
|
|
345
|
+
// — tmux replays the current screen on connect.
|
|
346
|
+
if (!this.ensureAttached(record) && record.summary.status === 'running') {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
if (record.summary.status === 'running') {
|
|
350
|
+
record.history = this.captureTerminalHistoryCursor(record);
|
|
351
|
+
}
|
|
352
|
+
const output = record.output.snapshot();
|
|
353
|
+
record.subscribers.add(subscriber);
|
|
354
|
+
if (options.replay ?? true) {
|
|
355
|
+
for (const data of output) {
|
|
356
|
+
subscriber({ type: 'output', terminalId: id, data });
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
let attachmentPaused = false;
|
|
360
|
+
const pause = () => {
|
|
361
|
+
if (attachmentPaused)
|
|
362
|
+
return;
|
|
363
|
+
attachmentPaused = true;
|
|
364
|
+
if (record.pauseCount++ === 0) {
|
|
365
|
+
record.pty?.pause();
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
const resume = () => {
|
|
369
|
+
if (!attachmentPaused)
|
|
370
|
+
return;
|
|
371
|
+
attachmentPaused = false;
|
|
372
|
+
if (--record.pauseCount === 0) {
|
|
373
|
+
record.pty?.resume();
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
return {
|
|
377
|
+
terminal: cloneSummary(record.summary),
|
|
378
|
+
output,
|
|
379
|
+
history: record.history,
|
|
380
|
+
pause,
|
|
381
|
+
resume,
|
|
382
|
+
dispose: () => {
|
|
383
|
+
// Release any outstanding pause this attachment held so we don't
|
|
384
|
+
// permanently stall the PTY when a paused subscriber drops.
|
|
385
|
+
resume();
|
|
386
|
+
record.subscribers.delete(subscriber);
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
writeToTerminal(id, data) {
|
|
391
|
+
const record = this.terminals.get(id);
|
|
392
|
+
if (!record?.pty || record.summary.status !== 'running') {
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
record.pty.write(data);
|
|
396
|
+
record.summary.updatedAt = this.timestamp();
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
resizeTerminal(id, cols, rows) {
|
|
400
|
+
const record = this.terminals.get(id);
|
|
401
|
+
if (!record?.pty || record.summary.status !== 'running') {
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
const normalizedCols = normalizeDimension(cols, record.summary.cols);
|
|
405
|
+
const normalizedRows = normalizeDimension(rows, record.summary.rows);
|
|
406
|
+
if (record.summary.cols === normalizedCols && record.summary.rows === normalizedRows) {
|
|
407
|
+
return true;
|
|
408
|
+
}
|
|
409
|
+
record.pty.resize(normalizedCols, normalizedRows);
|
|
410
|
+
record.summary.cols = normalizedCols;
|
|
411
|
+
record.summary.rows = normalizedRows;
|
|
412
|
+
record.summary.updatedAt = this.timestamp();
|
|
413
|
+
this.publish(record, { type: 'terminal_updated', terminal: cloneSummary(record.summary) });
|
|
414
|
+
return true;
|
|
415
|
+
}
|
|
416
|
+
closeTerminal(id) {
|
|
417
|
+
const record = this.terminals.get(id);
|
|
418
|
+
if (!record) {
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
this.disposeRecord(record);
|
|
422
|
+
this.terminals.delete(id);
|
|
423
|
+
return true;
|
|
424
|
+
}
|
|
425
|
+
closeAll() {
|
|
426
|
+
// Differs from closeTerminal: we tear down our in-memory bookkeeping but
|
|
427
|
+
// DO NOT call pty.kill() when the adapter is persistent (tmux). Killing
|
|
428
|
+
// here would destroy every tmux session on NTerminal shutdown — defeating
|
|
429
|
+
// the entire across-restart persistence design. For non-persistent
|
|
430
|
+
// adapters (NodePtyAdapter), the child shells get SIGHUP via process
|
|
431
|
+
// tree exit anyway, so explicitly killing is just being polite.
|
|
432
|
+
const persistent = typeof this.ptyAdapter.listExisting === 'function';
|
|
433
|
+
for (const record of this.terminals.values()) {
|
|
434
|
+
record.dataDisposable.dispose();
|
|
435
|
+
record.exitDisposable.dispose();
|
|
436
|
+
record.subscribers.clear();
|
|
437
|
+
if (!persistent && record.pty && record.summary.status === 'running') {
|
|
438
|
+
record.pty.kill();
|
|
439
|
+
}
|
|
440
|
+
record.pty = null;
|
|
441
|
+
}
|
|
442
|
+
this.terminals.clear();
|
|
443
|
+
}
|
|
444
|
+
ensureAttached(record) {
|
|
445
|
+
if (record.pty) {
|
|
446
|
+
return true;
|
|
447
|
+
}
|
|
448
|
+
if (record.summary.status !== 'running' || typeof this.ptyAdapter.listExisting !== 'function') {
|
|
449
|
+
return false;
|
|
450
|
+
}
|
|
451
|
+
try {
|
|
452
|
+
this.reattachToSession(record);
|
|
453
|
+
}
|
|
454
|
+
catch {
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
return record.pty !== null;
|
|
458
|
+
}
|
|
459
|
+
async resolveInitialCwd(options) {
|
|
460
|
+
if (options.cwd?.trim()) {
|
|
461
|
+
return path.resolve(options.cwd);
|
|
462
|
+
}
|
|
463
|
+
if (options.parentTerminalId) {
|
|
464
|
+
const parent = this.terminals.get(options.parentTerminalId);
|
|
465
|
+
if (parent) {
|
|
466
|
+
const resolved = parent.summary.pid ? await this.safeResolveCwd(parent.summary.pid) : null;
|
|
467
|
+
return resolved ?? parent.summary.cwd;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return this.config.workspaceRoot;
|
|
471
|
+
}
|
|
472
|
+
async safeResolveCwd(pid) {
|
|
473
|
+
try {
|
|
474
|
+
return await this.resolveCwd(pid);
|
|
475
|
+
}
|
|
476
|
+
catch {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
async refreshCwd(record) {
|
|
481
|
+
const pty = record.pty;
|
|
482
|
+
if (!pty || record.summary.status !== 'running') {
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
const cwd = await this.safeResolveCwd(pty.pid);
|
|
486
|
+
if (!cwd || record.pty !== pty || record.summary.status !== 'running' || cwd === record.summary.cwd) {
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
record.summary.cwd = cwd;
|
|
490
|
+
record.summary.title = this.createTitle(cwd);
|
|
491
|
+
record.summary.updatedAt = this.timestamp();
|
|
492
|
+
this.publish(record, { type: 'terminal_updated', terminal: cloneSummary(record.summary) });
|
|
493
|
+
}
|
|
494
|
+
publish(record, message) {
|
|
495
|
+
for (const subscriber of record.subscribers) {
|
|
496
|
+
subscriber(message);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
disposeRecord(record) {
|
|
500
|
+
record.dataDisposable.dispose();
|
|
501
|
+
record.exitDisposable.dispose();
|
|
502
|
+
record.subscribers.clear();
|
|
503
|
+
if (record.pty && record.summary.status === 'running') {
|
|
504
|
+
record.pty.kill();
|
|
505
|
+
}
|
|
506
|
+
record.pty = null;
|
|
507
|
+
}
|
|
508
|
+
createTitle(cwd) {
|
|
509
|
+
return path.basename(cwd) || 'Terminal';
|
|
510
|
+
}
|
|
511
|
+
timestamp() {
|
|
512
|
+
return this.now().toISOString();
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
function normalizeDimension(value, fallback) {
|
|
516
|
+
return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : fallback;
|
|
517
|
+
}
|
|
518
|
+
function normalizeHistoryLimit(value) {
|
|
519
|
+
if (typeof value !== 'number' || !Number.isInteger(value) || value <= 0) {
|
|
520
|
+
return HISTORY_PAGE_LINES;
|
|
521
|
+
}
|
|
522
|
+
return Math.min(value, HISTORY_PAGE_MAX_LINES);
|
|
523
|
+
}
|
|
524
|
+
function cloneSummary(summary) {
|
|
525
|
+
return { ...summary };
|
|
526
|
+
}
|
|
527
|
+
function terminalEnv() {
|
|
528
|
+
const env = {};
|
|
529
|
+
const allowedKeys = ['HOME', 'LANG', 'LC_ALL', 'LC_CTYPE', 'LOGNAME', 'PATH', 'SHELL', 'TMPDIR', 'USER'];
|
|
530
|
+
for (const key of allowedKeys) {
|
|
531
|
+
const value = process.env[key];
|
|
532
|
+
if (value !== undefined) {
|
|
533
|
+
env[key] = value;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
env.TERM = 'xterm-256color';
|
|
537
|
+
env.COLORTERM = process.env.COLORTERM ?? 'truecolor';
|
|
538
|
+
ensureUtf8TerminalLocale(env);
|
|
539
|
+
return env;
|
|
540
|
+
}
|
|
541
|
+
const fallbackTerminalLocale = 'en_US.UTF-8';
|
|
542
|
+
function ensureUtf8TerminalLocale(env) {
|
|
543
|
+
const characterLocale = env.LC_ALL ?? env.LC_CTYPE ?? env.LANG;
|
|
544
|
+
if (isUtf8Locale(characterLocale)) {
|
|
545
|
+
if (!env.LANG) {
|
|
546
|
+
env.LANG = characterLocale;
|
|
547
|
+
}
|
|
548
|
+
if (!env.LC_ALL && !env.LC_CTYPE) {
|
|
549
|
+
env.LC_CTYPE = characterLocale;
|
|
550
|
+
}
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
env.LANG = fallbackTerminalLocale;
|
|
554
|
+
if (!env.LC_ALL) {
|
|
555
|
+
env.LC_CTYPE = fallbackTerminalLocale;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
function isUtf8Locale(value) {
|
|
559
|
+
return value !== undefined && /utf-?8/i.test(value);
|
|
560
|
+
}
|
|
561
|
+
//# sourceMappingURL=TerminalManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TerminalManager.js","sourceRoot":"","sources":["../../../src/server/terminal/TerminalManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAkDnE,0EAA0E;AAC1E,oEAAoE;AACpE,0EAA0E;AAC1E,yEAAyE;AACzE,2BAA2B;AAC3B,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAEpC,0EAA0E;AAC1E,sEAAsE;AACtE,4EAA4E;AAC5E,wEAAwE;AACxE,kEAAkE;AAClE,MAAM,uBAAuB,GAAG,KAAK,CAAC;AACtC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AACpC,MAAM,0BAA0B,GAAG,CAAC,CAAC;AAErC,MAAM,OAAO,eAAe;IAYP;IACA;IAZF,SAAS,GAAG,IAAI,GAAG,EAA8B,CAAC;IAClD,UAAU,CAA0C;IACpD,GAAG,CAAa;IACjC,+DAA+D;IAC/D,uEAAuE;IACvE,8DAA8D;IAC7C,aAAa,CAAS;IAC/B,eAAe,GAA0B,IAAI,CAAC;IAC9C,kBAAkB,GAAG,KAAK,CAAC;IAEnC,YACmB,MAAiB,EACjB,UAAsB,EACvC,UAAkC,EAAE;QAFnB,WAAM,GAAN,MAAM,CAAW;QACjB,eAAU,GAAV,UAAU,CAAY;QAGvC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,iBAAiB,CAAC;QAC1D,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtD,IAAI,OAAO,IAAI,CAAC,UAAU,CAAC,YAAY,KAAK,UAAU,EAAE,CAAC;YACvD,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAEO,iBAAiB;QACvB,IAAI,IAAI,CAAC,eAAe;YAAE,OAAO;QACjC,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;YACtC,IAAI,IAAI,CAAC,kBAAkB;gBAAE,OAAO;YACpC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;YAC/B,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;gBAChC,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;YAClC,CAAC,CAAC,CAAC;QACL,CAAC,EAAE,uBAAuB,CAAC,CAAC;QAC5B,sEAAsE;QACtE,kEAAkE;QAClE,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,EAAE,CAAC;IACjC,CAAC;IAEO,KAAK,CAAC,QAAQ;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;QAC1C,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,MAA8D,CAAC;QACnE,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,UAAU,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,IAAI,MAAM,EAAE,CAAC;YAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC9C,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS;gBAAE,SAAS;YAC7D,uDAAuD;YACvD,iEAAiE;YACjE,mDAAmD;YACnD,mEAAmE;YACnE,mEAAmE;YACnE,8DAA8D;YAC9D,6DAA6D;YAC7D,uCAAuC;YACvC,qDAAqD;YACrD,MAAM,YAAY,GAAG,GAAG,GAAG,MAAM,CAAC,YAAY,GAAG,qBAAqB,CAAC;YACvE,MAAM,YAAY,GAAoB,IAAI,IAAI,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;YAC7E,MAAM,WAAW,GAAG,cAAc,KAAK,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC;YAClF,IACE,MAAM,CAAC,OAAO,CAAC,QAAQ,KAAK,YAAY;gBACxC,MAAM,CAAC,OAAO,CAAC,cAAc,KAAK,WAAW,EAC7C,CAAC;gBACD,SAAS;YACX,CAAC;YACD,MAAM,CAAC,OAAO,CAAC,QAAQ,GAAG,YAAY,CAAC;YACvC,MAAM,CAAC,OAAO,CAAC,cAAc,GAAG,WAAW,CAAC;YAC5C,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAC5C,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,4DAA4D;IAC5D,OAAO;QACL,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YACpC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,UAAiC,EAAE;QACtD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAClD,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;QACxB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QACnC,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAChC,SAAS,EAAE,EAAE;YACb,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK;YACxB,GAAG;YACH,IAAI;YACJ,IAAI;YACJ,GAAG,EAAE,WAAW,EAAE;YAClB,mEAAmE;YACnE,kEAAkE;YAClE,gEAAgE;YAChE,KAAK,EAAE,YAAY;SACpB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAmB;YAC7B,OAAO,EAAE;gBACP,EAAE;gBACF,KAAK,EAAE,YAAY;gBACnB,GAAG;gBACH,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,IAAI;gBACJ,IAAI;gBACJ,SAAS,EAAE,SAAS;gBACpB,SAAS,EAAE,SAAS;gBACpB,MAAM,EAAE,SAAS;gBACjB,QAAQ,EAAE,IAAI;aACf;YACD,GAAG;YACH,MAAM,EAAE,IAAI,YAAY,EAAE;YAC1B,WAAW,EAAE,IAAI,GAAG,EAAE;YACtB,cAAc,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE;YAC5C,cAAc,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE;YAC5C,UAAU,EAAE,CAAC;YACb,YAAY,EAAE,CAAC;YACf,OAAO,EAAE,IAAI;SACd,CAAC;QAEF,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC5B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC/B,OAAO,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,uEAAuE;IACvE,0EAA0E;IAC1E,4EAA4E;IAC5E,sEAAsE;IACtE,yEAAyE;IACzE,KAAK,CAAC,eAAe;QACnB,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC;QACxD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC7B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;YACpC,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC;gBAAE,SAAS;YAC5C,+DAA+D;YAC/D,gEAAgE;YAChE,mEAAmE;YACnE,oDAAoD;YACpD,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,YAAY,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YACnF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE;gBAC5B,OAAO,EAAE;oBACP,EAAE,EAAE,SAAS;oBACb,iEAAiE;oBACjE,0DAA0D;oBAC1D,iEAAiE;oBACjE,4DAA4D;oBAC5D,KAAK,EAAE,aAAa;oBACpB,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa;oBAC9B,GAAG,EAAE,IAAI;oBACT,IAAI,EAAE,EAAE;oBACR,IAAI,EAAE,EAAE;oBACR,SAAS,EAAE,GAAG;oBACd,SAAS,EAAE,GAAG;oBACd,MAAM,EAAE,SAAS;oBACjB,QAAQ,EAAE,IAAI;iBACf;gBACD,GAAG,EAAE,IAAI,EAAE,oDAAoD;gBAC/D,MAAM,EAAE,IAAI,YAAY,EAAE;gBAC1B,WAAW,EAAE,IAAI,GAAG,EAAE;gBACtB,cAAc,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE;gBAC5C,cAAc,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE;gBAC5C,UAAU,EAAE,CAAC;gBACb,YAAY,EAAE,CAAC;gBACf,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,MAAsB,EAAE,GAAe;QACvD,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC;QACjB,MAAM,CAAC,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;QAC7B,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;QAClC,MAAM,CAAC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC/B,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5C,MAAM,CAAC,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;YAC1C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzB,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACjC,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAC5C,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YAC3C,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC;YACjC,MAAM,CAAC,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;YACzC,MAAM,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;YAC1B,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAC5C,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC;YAClB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnF,CAAC,CAAC,CAAC;IACL,CAAC;IAED,qEAAqE;IACrE,uEAAuE;IACvE,+DAA+D;IACvD,iBAAiB,CAAC,MAAsB;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAChC,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE;YAC5B,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK;YACxB,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG;YACvB,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI;YACzB,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI;YACzB,GAAG,EAAE,WAAW,EAAE;SACnB,CAAC,CAAC;QACH,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,CAAC;IAEO,4BAA4B,CAAC,MAAsB;QACzD,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE;YAClE,UAAU,EAAE,CAAC;YACb,KAAK,EAAE,0BAA0B;SAClC,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;YAC5D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO;YACL,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,SAAS;SACjE,CAAC;IACJ,CAAC;IAED,aAAa;QACX,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACpF,CAAC;IAED,WAAW,CAAC,EAAc;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,OAAO,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACtD,CAAC;IAED,iBAAiB,CAAC,EAAc;QAC9B,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC;IAC3D,CAAC;IAED,kBAAkB,CAAC,EAAc,EAAE,UAAmD,EAAE;QACtF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACnD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAAG,qBAAqB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACnD,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,EAAE,EAAE;YACnD,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/E,KAAK;SACN,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO;YACL,UAAU,EAAE,EAAE;YACd,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC;IACJ,CAAC;IAED,4BAA4B,CAAC,EAAc,EAAE,UAA+C,EAAE;QAC5F,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACnD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,uBAAuB,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,yBAAyB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACxD,CAAC;IAED,2BAA2B,CAAC,EAAc;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACnD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,uBAAuB,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO;YACL,UAAU,EAAE,EAAE;YACd,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE;SACnE,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,EAAc;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED,0EAA0E;IAC1E,yEAAyE;IACzE,sEAAsE;IACtE,sEAAsE;IACtE,cAAc,CAAC,EAAc,EAAE,KAAa;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACjD,OAAO,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC;QACD,MAAM,CAAC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC;QAC/B,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5C,IAAI,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC3F,OAAO,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,EAAc;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC9B,OAAO,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,cAAc,CAAC,EAAc,EAAE,UAA8B,EAAE,UAAiC,EAAE;QAChG,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QACD,wEAAwE;QACxE,uEAAuE;QACvE,mEAAmE;QACnE,sEAAsE;QACtE,gDAAgD;QAChD,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACxE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACxC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,4BAA4B,CAAC,MAAM,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACnC,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;YAC3B,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;gBAC1B,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QACD,IAAI,gBAAgB,GAAG,KAAK,CAAC;QAC7B,MAAM,KAAK,GAAG,GAAG,EAAE;YACjB,IAAI,gBAAgB;gBAAE,OAAO;YAC7B,gBAAgB,GAAG,IAAI,CAAC;YACxB,IAAI,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;gBAC9B,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC;YACtB,CAAC;QACH,CAAC,CAAC;QACF,MAAM,MAAM,GAAG,GAAG,EAAE;YAClB,IAAI,CAAC,gBAAgB;gBAAE,OAAO;YAC9B,gBAAgB,GAAG,KAAK,CAAC;YACzB,IAAI,EAAE,MAAM,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;gBAC9B,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;YACvB,CAAC;QACH,CAAC,CAAC;QACF,OAAO;YACL,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC;YACtC,MAAM;YACN,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,KAAK;YACL,MAAM;YACN,OAAO,EAAE,GAAG,EAAE;gBACZ,iEAAiE;gBACjE,4DAA4D;gBAC5D,MAAM,EAAE,CAAC;gBACT,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACxC,CAAC;SACF,CAAC;IACJ,CAAC;IAED,eAAe,CAAC,EAAc,EAAE,IAAY;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACxD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvB,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,cAAc,CAAC,EAAc,EAAE,IAAY,EAAE,IAAY;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACxD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,cAAc,GAAG,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACrE,MAAM,cAAc,GAAG,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACrE,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,cAAc,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACrF,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;QAClD,MAAM,CAAC,OAAO,CAAC,IAAI,GAAG,cAAc,CAAC;QACrC,MAAM,CAAC,OAAO,CAAC,IAAI,GAAG,cAAc,CAAC;QACrC,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5C,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC3F,OAAO,IAAI,CAAC;IACd,CAAC;IAED,aAAa,CAAC,EAAc;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,QAAQ;QACN,yEAAyE;QACzE,wEAAwE;QACxE,0EAA0E;QAC1E,mEAAmE;QACnE,qEAAqE;QACrE,gEAAgE;QAChE,MAAM,UAAU,GAAG,OAAO,IAAI,CAAC,UAAU,CAAC,YAAY,KAAK,UAAU,CAAC;QACtE,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;YAC7C,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;YAChC,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;YAChC,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;YAC3B,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACrE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACpB,CAAC;YACD,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;IAEO,cAAc,CAAC,MAAsB;QAC3C,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,UAAU,CAAC,YAAY,KAAK,UAAU,EAAE,CAAC;YAC9F,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC;YACH,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,MAAM,CAAC,GAAG,KAAK,IAAI,CAAC;IAC7B,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,OAA8B;QAC5D,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YAC5D,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC3F,OAAO,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;YACxC,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,GAAW;QACtC,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,MAAsB;QAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChD,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,KAAK,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACpG,OAAO;QACT,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC;QACzB,MAAM,CAAC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC7C,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5C,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7F,CAAC;IAEO,OAAO,CAAC,MAAsB,EAAE,OAA8B;QACpE,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YAC5C,UAAU,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAEO,aAAa,CAAC,MAAsB;QAC1C,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;QAChC,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;QAChC,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACtD,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;QACD,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC;IACpB,CAAC;IAEO,WAAW,CAAC,GAAW;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC;IAC1C,CAAC;IAEO,SAAS;QACf,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;IAClC,CAAC;CACF;AAED,SAAS,kBAAkB,CAAC,KAAyB,EAAE,QAAgB;IACrE,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC9F,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAyB;IACtD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACxE,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,YAAY,CAAC,OAAwB;IAC5C,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;AACxB,CAAC;AAED,SAAS,WAAW;IAClB,MAAM,GAAG,GAAsB,EAAE,CAAC;IAClC,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACzG,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACnB,CAAC;IACH,CAAC;IACD,GAAG,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC5B,GAAG,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,WAAW,CAAC;IACrD,wBAAwB,CAAC,GAAG,CAAC,CAAC;IAC9B,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,sBAAsB,GAAG,aAAa,CAAC;AAE7C,SAAS,wBAAwB,CAAC,GAAsB;IACtD,MAAM,eAAe,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC;IAC/D,IAAI,YAAY,CAAC,eAAe,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACd,GAAG,CAAC,IAAI,GAAG,eAAe,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YACjC,GAAG,CAAC,QAAQ,GAAG,eAAe,CAAC;QACjC,CAAC;QACD,OAAO;IACT,CAAC;IAED,GAAG,CAAC,IAAI,GAAG,sBAAsB,CAAC;IAClC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAChB,GAAG,CAAC,QAAQ,GAAG,sBAAsB,CAAC;IACxC,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,KAAyB;IAC7C,OAAO,KAAK,KAAK,SAAS,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { PersistedSession, PtyAdapter, PtyHistoryCapture, PtyHistoryCaptureOptions, PtyProcess, PtySpawnOptions, PtyTranscriptSource } from './PtyAdapter.js';
|
|
2
|
+
export declare class TmuxPtyAdapter implements PtyAdapter {
|
|
3
|
+
private readonly configPath;
|
|
4
|
+
private readonly socket;
|
|
5
|
+
constructor(options?: {
|
|
6
|
+
configPath?: string;
|
|
7
|
+
socket?: string;
|
|
8
|
+
});
|
|
9
|
+
static detect(options?: {
|
|
10
|
+
configPath?: string;
|
|
11
|
+
}): TmuxPtyAdapter | null;
|
|
12
|
+
spawn(options: PtySpawnOptions & {
|
|
13
|
+
title?: string;
|
|
14
|
+
}): PtyProcess;
|
|
15
|
+
listExisting(): PersistedSession[];
|
|
16
|
+
pollSessions(): Promise<Map<string, {
|
|
17
|
+
currentCommand: string;
|
|
18
|
+
busy: boolean;
|
|
19
|
+
}>>;
|
|
20
|
+
setSessionTitle(sessionId: string, title: string): void;
|
|
21
|
+
captureHistory(sessionId: string, options: PtyHistoryCaptureOptions): PtyHistoryCapture | null;
|
|
22
|
+
resolveTranscriptSource(sessionId: string): PtyTranscriptSource | null;
|
|
23
|
+
private readPaneMetrics;
|
|
24
|
+
private readPanePid;
|
|
25
|
+
}
|