botmux 2.51.1 → 2.53.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/README.en.md +22 -265
- package/README.md +21 -296
- package/dist/adapters/backend/session-backend-selector.d.ts +5 -1
- package/dist/adapters/backend/session-backend-selector.d.ts.map +1 -1
- package/dist/adapters/backend/session-backend-selector.js +15 -1
- package/dist/adapters/backend/session-backend-selector.js.map +1 -1
- package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-backend.js +3 -0
- package/dist/adapters/backend/tmux-backend.js.map +1 -1
- package/dist/adapters/backend/types.d.ts +22 -0
- package/dist/adapters/backend/types.d.ts.map +1 -1
- package/dist/adapters/backend/types.js +7 -1
- package/dist/adapters/backend/types.js.map +1 -1
- package/dist/adapters/backend/zellij-backend.d.ts +132 -0
- package/dist/adapters/backend/zellij-backend.d.ts.map +1 -0
- package/dist/adapters/backend/zellij-backend.js +375 -0
- package/dist/adapters/backend/zellij-backend.js.map +1 -0
- package/dist/adapters/backend/zellij-observe-backend.d.ts +62 -0
- package/dist/adapters/backend/zellij-observe-backend.d.ts.map +1 -0
- package/dist/adapters/backend/zellij-observe-backend.js +218 -0
- package/dist/adapters/backend/zellij-observe-backend.js.map +1 -0
- package/dist/adapters/cli/claude-code.d.ts +39 -5
- package/dist/adapters/cli/claude-code.d.ts.map +1 -1
- package/dist/adapters/cli/claude-code.js +53 -31
- package/dist/adapters/cli/claude-code.js.map +1 -1
- package/dist/adapters/cli/registry.d.ts +2 -1
- package/dist/adapters/cli/registry.d.ts.map +1 -1
- package/dist/adapters/cli/registry.js +3 -1
- package/dist/adapters/cli/registry.js.map +1 -1
- package/dist/adapters/cli/seed.d.ts +29 -0
- package/dist/adapters/cli/seed.d.ts.map +1 -0
- package/dist/adapters/cli/seed.js +63 -0
- package/dist/adapters/cli/seed.js.map +1 -0
- package/dist/adapters/cli/types.d.ts +17 -1
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/bot-registry.d.ts +31 -1
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +31 -0
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +37 -27
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +7 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -1
- package/dist/core/ask-hook/registry.d.ts.map +1 -1
- package/dist/core/ask-hook/registry.js +4 -0
- package/dist/core/ask-hook/registry.js.map +1 -1
- package/dist/core/command-handler.d.ts +4 -1
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +100 -8
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +37 -0
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dispatch.d.ts +33 -0
- package/dist/core/dispatch.d.ts.map +1 -1
- package/dist/core/dispatch.js +26 -0
- package/dist/core/dispatch.js.map +1 -1
- package/dist/core/session-discovery.d.ts +13 -4
- package/dist/core/session-discovery.d.ts.map +1 -1
- package/dist/core/session-discovery.js +5 -5
- package/dist/core/session-discovery.js.map +1 -1
- package/dist/core/session-manager.d.ts +10 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +43 -18
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/types.d.ts +5 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts +1 -1
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +22 -9
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/core/zellij-adopt-discovery.d.ts +28 -0
- package/dist/core/zellij-adopt-discovery.d.ts.map +1 -0
- package/dist/core/zellij-adopt-discovery.js +255 -0
- package/dist/core/zellij-adopt-discovery.js.map +1 -0
- package/dist/core/zellij-session-discovery.d.ts +73 -0
- package/dist/core/zellij-session-discovery.d.ts.map +1 -0
- package/dist/core/zellij-session-discovery.js +259 -0
- package/dist/core/zellij-session-discovery.js.map +1 -0
- package/dist/daemon.d.ts +3 -0
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +145 -13
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js +114 -0
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +23 -1
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +1 -0
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/workflows.js +1 -1
- package/dist/dashboard/web/workflows.js.map +1 -1
- package/dist/dashboard-web/app.js +449 -426
- package/dist/dashboard.js +20 -0
- package/dist/dashboard.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +15 -1
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +16 -2
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts +8 -3
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +74 -5
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +72 -10
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts +12 -0
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +39 -31
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/grant-command.d.ts +26 -0
- package/dist/im/lark/grant-command.d.ts.map +1 -1
- package/dist/im/lark/grant-command.js +142 -3
- package/dist/im/lark/grant-command.js.map +1 -1
- package/dist/im/lark/grant-pending.d.ts +7 -4
- package/dist/im/lark/grant-pending.d.ts.map +1 -1
- package/dist/im/lark/grant-pending.js +12 -6
- package/dist/im/lark/grant-pending.js.map +1 -1
- package/dist/services/codex-app-threads.d.ts +20 -0
- package/dist/services/codex-app-threads.d.ts.map +1 -0
- package/dist/services/codex-app-threads.js +165 -0
- package/dist/services/codex-app-threads.js.map +1 -0
- package/dist/services/grant-prefs-store.d.ts +23 -0
- package/dist/services/grant-prefs-store.d.ts.map +1 -0
- package/dist/services/grant-prefs-store.js +94 -0
- package/dist/services/grant-prefs-store.js.map +1 -0
- package/dist/services/grant-store.d.ts +34 -2
- package/dist/services/grant-store.d.ts.map +1 -1
- package/dist/services/grant-store.js +160 -9
- package/dist/services/grant-store.js.map +1 -1
- package/dist/services/quota-dedup.d.ts +33 -0
- package/dist/services/quota-dedup.d.ts.map +1 -0
- package/dist/services/quota-dedup.js +67 -0
- package/dist/services/quota-dedup.js.map +1 -0
- package/dist/setup/bot-config-editor.d.ts +1 -1
- package/dist/setup/bot-config-editor.d.ts.map +1 -1
- package/dist/setup/bot-config-editor.js +5 -4
- package/dist/setup/bot-config-editor.js.map +1 -1
- package/dist/setup/ensure-zellij.d.ts +48 -0
- package/dist/setup/ensure-zellij.d.ts.map +1 -0
- package/dist/setup/ensure-zellij.js +93 -0
- package/dist/setup/ensure-zellij.js.map +1 -0
- package/dist/types.d.ts +9 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/anchor-serializer.d.ts +3 -2
- package/dist/utils/anchor-serializer.d.ts.map +1 -1
- package/dist/utils/anchor-serializer.js +20 -5
- package/dist/utils/anchor-serializer.js.map +1 -1
- package/dist/utils/transient-snapshot.js +2 -2
- package/dist/utils/transient-snapshot.js.map +1 -1
- package/dist/worker.js +124 -30
- package/dist/worker.js.map +1 -1
- package/dist/workflows/attempt-resume.d.ts +1 -1
- package/dist/workflows/attempt-resume.d.ts.map +1 -1
- package/dist/workflows/attempt-resume.js +1 -1
- package/dist/workflows/attempt-resume.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { SessionBackend, SpawnOpts } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* ZellijBackend — session backend using zellij for process persistence.
|
|
4
|
+
*
|
|
5
|
+
* Architecture: pty-under-zellij (the "B route"), the zellij analogue of the
|
|
6
|
+
* legacy TmuxBackend (pty-under-tmux):
|
|
7
|
+
* - A node-pty process runs `zellij --session … --layout-string …` (fresh)
|
|
8
|
+
* or `zellij attach …` (reattach). The node-pty is the only zellij client.
|
|
9
|
+
* - All output flows through the pty (onData/onExit work unchanged) — we get
|
|
10
|
+
* the raw rendered byte stream for free, sidestepping zellij `subscribe`'s
|
|
11
|
+
* "whole-viewport-snapshot" model that doesn't fit botmux's xterm pipeline.
|
|
12
|
+
* - Input goes through pty.write(). We start zellij in **locked mode with
|
|
13
|
+
* keybindings cleared** (generated config), so every byte we write —
|
|
14
|
+
* including Ctrl-C, arrows, bracketed-paste markers — passes straight to
|
|
15
|
+
* the focused CLI pane with zero keybinding interception (the moral
|
|
16
|
+
* equivalent of tmux's single prefix key, but with nothing reserved).
|
|
17
|
+
* - resize() is pty.resize(): the attached client's size drives the pane, so
|
|
18
|
+
* the headless-default 25-column problem never bites (the pty is the size).
|
|
19
|
+
* - kill() only detaches (kills the pty client); the zellij server keeps the
|
|
20
|
+
* CLI running, so a daemon restart re-attaches with `zellij attach`.
|
|
21
|
+
* - destroySession() runs `zellij delete-session -f` (kill + purge the
|
|
22
|
+
* resurrectable corpse) on explicit /close.
|
|
23
|
+
*
|
|
24
|
+
* Naming: zellij sessions are named `bmx-<sessionId.slice(0,8)>`, same as tmux.
|
|
25
|
+
*/
|
|
26
|
+
export declare class ZellijBackend implements SessionBackend {
|
|
27
|
+
private process;
|
|
28
|
+
private readonly sessionName;
|
|
29
|
+
private readonly ownsSession;
|
|
30
|
+
private reattaching;
|
|
31
|
+
private configPath;
|
|
32
|
+
private tmpConfigDir;
|
|
33
|
+
/** Set by kill()/destroySession() so the pty-client exit they cause (an
|
|
34
|
+
* intentional detach/teardown — the zellij session survives) is NOT
|
|
35
|
+
* reported as a CLI exit. A real CLI exit leaves this false. */
|
|
36
|
+
private intentionalExit;
|
|
37
|
+
/** Cached CLI pid. The CLI subprocess starts asynchronously after spawn(),
|
|
38
|
+
* so the first getChildPid() may be null; once resolved it's stable for the
|
|
39
|
+
* session lifetime (single CLI pane → pane exit ends the session). */
|
|
40
|
+
private resolvedCliPid;
|
|
41
|
+
/** Explicit pane target for adopt mode (e.g. "terminal_2"). When null,
|
|
42
|
+
* zellij `action` commands address the focused pane — correct for managed
|
|
43
|
+
* mode where the single CLI pane is always focused. */
|
|
44
|
+
private readonly paneId;
|
|
45
|
+
claudeJsonlPath?: string;
|
|
46
|
+
cliPid?: number;
|
|
47
|
+
cliCwd?: string;
|
|
48
|
+
constructor(sessionName: string, opts?: {
|
|
49
|
+
ownsSession?: boolean;
|
|
50
|
+
isReattach?: boolean;
|
|
51
|
+
paneId?: string;
|
|
52
|
+
});
|
|
53
|
+
static isAvailable(): boolean;
|
|
54
|
+
static sessionName(sessionId: string): string;
|
|
55
|
+
/** Names of LIVE (non-exited) zellij sessions. A killed-but-serialised
|
|
56
|
+
* session lingers in `list-sessions` as "(EXITED - attach to resurrect)";
|
|
57
|
+
* we must not treat those as reattachable, so filter them out. */
|
|
58
|
+
static liveSessions(): string[];
|
|
59
|
+
static hasSession(name: string): boolean;
|
|
60
|
+
/** Kill + purge a session (so no resurrectable corpse accumulates). */
|
|
61
|
+
static killSession(name: string): void;
|
|
62
|
+
static listBotmuxSessions(): string[];
|
|
63
|
+
spawn(bin: string, args: string[], opts: SpawnOpts): void;
|
|
64
|
+
/** Write the per-session config (locked mode + cleared keybinds so pty.write
|
|
65
|
+
* passes through untouched, no startup tips / pane frames) and, for a fresh
|
|
66
|
+
* spawn, the single-pane layout file. Both live in one temp dir cleaned on
|
|
67
|
+
* kill(). On reattach the layout file is unused but harmless. */
|
|
68
|
+
private writeRuntimeFiles;
|
|
69
|
+
get isReattach(): boolean;
|
|
70
|
+
write(data: string): void;
|
|
71
|
+
/** Literal text, no Enter. */
|
|
72
|
+
sendText(text: string): void;
|
|
73
|
+
/** Special keys by tmux-style name (Enter, Escape, C-c, M-Enter, …). */
|
|
74
|
+
sendSpecialKeys(...keys: string[]): void;
|
|
75
|
+
/** Bracketed paste: wrap with \e[200~ … \e[201~ so TUIs (CoCo/Ink/Codex)
|
|
76
|
+
* detect the paste boundary and don't treat embedded \n as Enter. Mirrors
|
|
77
|
+
* `tmux paste-buffer -p`. */
|
|
78
|
+
pasteText(text: string): void;
|
|
79
|
+
resize(cols: number, rows: number): void;
|
|
80
|
+
/** Must be called AFTER spawn(). */
|
|
81
|
+
onData(cb: (data: string) => void): void;
|
|
82
|
+
/** Must be called AFTER spawn(). */
|
|
83
|
+
onExit(cb: (code: number | null, signal: string | null) => void): void;
|
|
84
|
+
/** CLI pid. May be null immediately after spawn() (the CLI subprocess starts
|
|
85
|
+
* asynchronously); the worker retries. Cached once resolved. */
|
|
86
|
+
getChildPid(): number | null;
|
|
87
|
+
/** Detach only — kills the pty client, leaves the zellij session running. */
|
|
88
|
+
kill(): void;
|
|
89
|
+
/** Kill the zellij session permanently (explicit /close). */
|
|
90
|
+
destroySession(): void;
|
|
91
|
+
private cleanupConfig;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Locked mode + cleared keybinds => the client pty forwards every byte to the
|
|
95
|
+
* focused pane with no zellij interception. No startup tips / pane frames so
|
|
96
|
+
* the captured stream is just the CLI (we don't need to hide chrome, but a
|
|
97
|
+
* clean single pane keeps screenshots faithful and the renderer simple).
|
|
98
|
+
*/
|
|
99
|
+
export declare const ZELLIJ_CONFIG_KDL = "// botmux-generated \u2014 do not edit\nshow_startup_tips false\npane_frames false\ndefault_mode \"locked\"\nkeybinds clear-defaults=true {\n}\n";
|
|
100
|
+
/** Escape a string for a KDL double-quoted value. */
|
|
101
|
+
export declare function kdlString(s: string): string;
|
|
102
|
+
/**
|
|
103
|
+
* Build the `--layout-string` KDL: a single full-screen pane that execs the CLI
|
|
104
|
+
* through the user's shell (same wrapper TmuxBackend uses, so PATH / NVM / pnpm
|
|
105
|
+
* / mise shims load from rcfiles). Command + args go in via execvp semantics —
|
|
106
|
+
* no shell-quoting needed (KDL strings carry spaces/quotes), only KDL escaping.
|
|
107
|
+
*
|
|
108
|
+
* pane command="<shell>" close_on_exit=true {
|
|
109
|
+
* args "<flag>"… "-c" "<script>" "_" "<cwd>" "KEY=VAL"… "<bin>" "<arg>"…
|
|
110
|
+
* }
|
|
111
|
+
*/
|
|
112
|
+
export declare function buildLayoutString(bin: string, args: string[], opts: SpawnOpts): string;
|
|
113
|
+
/**
|
|
114
|
+
* Map a tmux-style key name to the raw bytes a terminal emits for it. Covers
|
|
115
|
+
* the names botmux's adapters / worker actually send (Enter, Escape, C-<x>,
|
|
116
|
+
* M-<x>, arrows, Tab, BSpace, …). Unknown names fall back to the literal string
|
|
117
|
+
* so a missing mapping degrades to "typed as-is" rather than dropping input.
|
|
118
|
+
*/
|
|
119
|
+
export declare function tmuxKeyToBytes(key: string): string;
|
|
120
|
+
/**
|
|
121
|
+
* Find the zellij `--server …/<sessionName>` process pid. The session name is
|
|
122
|
+
* the trailing path component of the server's socket argument, so we match the
|
|
123
|
+
* cmdline ending in `/<sessionName>`.
|
|
124
|
+
*/
|
|
125
|
+
export declare function findServerPid(sessionName: string): number | null;
|
|
126
|
+
/**
|
|
127
|
+
* Best-effort CLI pid for the managed pane. With the SHELL_WRAPPER_SCRIPT's
|
|
128
|
+
* `exec /usr/bin/env "$@"`, the CLI replaces the shell and becomes a direct
|
|
129
|
+
* child of the zellij server, so the server's lone non-zellij child is the CLI.
|
|
130
|
+
*/
|
|
131
|
+
export declare function findPaneCliPid(sessionName: string, _binBasename: string): number | null;
|
|
132
|
+
//# sourceMappingURL=zellij-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zellij-backend.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/zellij-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
import * as pty from 'node-pty';
|
|
2
|
+
import { execFileSync, spawnSync } from 'node:child_process';
|
|
3
|
+
import { mkdtempSync, writeFileSync, rmSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { zellijEnv, probeZellijFunctional } from '../../setup/ensure-zellij.js';
|
|
7
|
+
import { resolveUserShell, buildBotmuxEnvAssignments, SHELL_WRAPPER_SCRIPT } from './tmux-backend.js';
|
|
8
|
+
import { logger } from '../../utils/logger.js';
|
|
9
|
+
/**
|
|
10
|
+
* ZellijBackend — session backend using zellij for process persistence.
|
|
11
|
+
*
|
|
12
|
+
* Architecture: pty-under-zellij (the "B route"), the zellij analogue of the
|
|
13
|
+
* legacy TmuxBackend (pty-under-tmux):
|
|
14
|
+
* - A node-pty process runs `zellij --session … --layout-string …` (fresh)
|
|
15
|
+
* or `zellij attach …` (reattach). The node-pty is the only zellij client.
|
|
16
|
+
* - All output flows through the pty (onData/onExit work unchanged) — we get
|
|
17
|
+
* the raw rendered byte stream for free, sidestepping zellij `subscribe`'s
|
|
18
|
+
* "whole-viewport-snapshot" model that doesn't fit botmux's xterm pipeline.
|
|
19
|
+
* - Input goes through pty.write(). We start zellij in **locked mode with
|
|
20
|
+
* keybindings cleared** (generated config), so every byte we write —
|
|
21
|
+
* including Ctrl-C, arrows, bracketed-paste markers — passes straight to
|
|
22
|
+
* the focused CLI pane with zero keybinding interception (the moral
|
|
23
|
+
* equivalent of tmux's single prefix key, but with nothing reserved).
|
|
24
|
+
* - resize() is pty.resize(): the attached client's size drives the pane, so
|
|
25
|
+
* the headless-default 25-column problem never bites (the pty is the size).
|
|
26
|
+
* - kill() only detaches (kills the pty client); the zellij server keeps the
|
|
27
|
+
* CLI running, so a daemon restart re-attaches with `zellij attach`.
|
|
28
|
+
* - destroySession() runs `zellij delete-session -f` (kill + purge the
|
|
29
|
+
* resurrectable corpse) on explicit /close.
|
|
30
|
+
*
|
|
31
|
+
* Naming: zellij sessions are named `bmx-<sessionId.slice(0,8)>`, same as tmux.
|
|
32
|
+
*/
|
|
33
|
+
export class ZellijBackend {
|
|
34
|
+
process = null;
|
|
35
|
+
sessionName;
|
|
36
|
+
ownsSession;
|
|
37
|
+
reattaching = false;
|
|
38
|
+
configPath = null;
|
|
39
|
+
tmpConfigDir = null;
|
|
40
|
+
/** Set by kill()/destroySession() so the pty-client exit they cause (an
|
|
41
|
+
* intentional detach/teardown — the zellij session survives) is NOT
|
|
42
|
+
* reported as a CLI exit. A real CLI exit leaves this false. */
|
|
43
|
+
intentionalExit = false;
|
|
44
|
+
/** Cached CLI pid. The CLI subprocess starts asynchronously after spawn(),
|
|
45
|
+
* so the first getChildPid() may be null; once resolved it's stable for the
|
|
46
|
+
* session lifetime (single CLI pane → pane exit ends the session). */
|
|
47
|
+
resolvedCliPid = null;
|
|
48
|
+
/** Explicit pane target for adopt mode (e.g. "terminal_2"). When null,
|
|
49
|
+
* zellij `action` commands address the focused pane — correct for managed
|
|
50
|
+
* mode where the single CLI pane is always focused. */
|
|
51
|
+
paneId;
|
|
52
|
+
// PtyHandle fields the worker sets (parallel to TmuxBackend / PtyBackend) so
|
|
53
|
+
// the claude-code adapter can verify submits and follow the session id.
|
|
54
|
+
claudeJsonlPath;
|
|
55
|
+
cliPid;
|
|
56
|
+
cliCwd;
|
|
57
|
+
constructor(sessionName, opts) {
|
|
58
|
+
this.sessionName = sessionName;
|
|
59
|
+
this.ownsSession = opts?.ownsSession ?? true;
|
|
60
|
+
this.reattaching = opts?.isReattach ?? false;
|
|
61
|
+
this.paneId = opts?.paneId ?? null;
|
|
62
|
+
}
|
|
63
|
+
// ─── Static helpers (mirror TmuxBackend) ──────────────────────────────────
|
|
64
|
+
static isAvailable() {
|
|
65
|
+
return probeZellijFunctional().ok;
|
|
66
|
+
}
|
|
67
|
+
static sessionName(sessionId) {
|
|
68
|
+
return `bmx-${sessionId.slice(0, 8)}`;
|
|
69
|
+
}
|
|
70
|
+
/** Names of LIVE (non-exited) zellij sessions. A killed-but-serialised
|
|
71
|
+
* session lingers in `list-sessions` as "(EXITED - attach to resurrect)";
|
|
72
|
+
* we must not treat those as reattachable, so filter them out. */
|
|
73
|
+
static liveSessions() {
|
|
74
|
+
try {
|
|
75
|
+
const out = execFileSync('zellij', ['list-sessions', '--no-formatting'], {
|
|
76
|
+
encoding: 'utf-8',
|
|
77
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
78
|
+
timeout: 3000,
|
|
79
|
+
env: zellijEnv(),
|
|
80
|
+
});
|
|
81
|
+
return out
|
|
82
|
+
.split('\n')
|
|
83
|
+
.map(l => l.trim())
|
|
84
|
+
.filter(l => l.length > 0 && !/EXITED/i.test(l))
|
|
85
|
+
.map(l => l.split(/\s+/)[0])
|
|
86
|
+
.filter(Boolean);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
static hasSession(name) {
|
|
93
|
+
return ZellijBackend.liveSessions().includes(name);
|
|
94
|
+
}
|
|
95
|
+
/** Kill + purge a session (so no resurrectable corpse accumulates). */
|
|
96
|
+
static killSession(name) {
|
|
97
|
+
try {
|
|
98
|
+
spawnSync('zellij', ['delete-session', name, '-f'], { stdio: 'ignore', timeout: 4000, env: zellijEnv() });
|
|
99
|
+
}
|
|
100
|
+
catch { /* doesn't exist */ }
|
|
101
|
+
}
|
|
102
|
+
static listBotmuxSessions() {
|
|
103
|
+
return ZellijBackend.liveSessions().filter(s => s.startsWith('bmx-'));
|
|
104
|
+
}
|
|
105
|
+
// ─── SessionBackend implementation ────────────────────────────────────────
|
|
106
|
+
spawn(bin, args, opts) {
|
|
107
|
+
// Reattach if the session is already live (daemon restarted, CLI survived).
|
|
108
|
+
this.reattaching = this.reattaching || ZellijBackend.hasSession(this.sessionName);
|
|
109
|
+
logger.debug(`[zellij:${this.sessionName}] spawn ${this.reattaching ? 'reattach' : 'new'} ` +
|
|
110
|
+
`bin=${bin} args=${JSON.stringify(args)} cwd=${opts.cwd} ${opts.cols}x${opts.rows}`);
|
|
111
|
+
const { configPath, layoutPath } = this.writeRuntimeFiles(bin, args, opts);
|
|
112
|
+
this.configPath = configPath;
|
|
113
|
+
const childEnv = zellijEnv(opts.env);
|
|
114
|
+
// Fresh: `--new-session-with-layout <file>` FORCES a new named session with
|
|
115
|
+
// our layout (plain `--session … --layout-string` instead ATTACHES to the
|
|
116
|
+
// name and errors "no active session"). Reattach: `attach <name>` rejoins
|
|
117
|
+
// the surviving session (daemon restarted, CLI still running inside).
|
|
118
|
+
const zellijArgs = this.reattaching
|
|
119
|
+
? ['--config', configPath, 'attach', this.sessionName]
|
|
120
|
+
: ['--config', configPath, '--session', this.sessionName,
|
|
121
|
+
'--new-session-with-layout', layoutPath];
|
|
122
|
+
this.process = pty.spawn('zellij', zellijArgs, {
|
|
123
|
+
name: 'xterm-256color',
|
|
124
|
+
cols: opts.cols,
|
|
125
|
+
rows: opts.rows,
|
|
126
|
+
cwd: opts.cwd,
|
|
127
|
+
env: childEnv,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/** Write the per-session config (locked mode + cleared keybinds so pty.write
|
|
131
|
+
* passes through untouched, no startup tips / pane frames) and, for a fresh
|
|
132
|
+
* spawn, the single-pane layout file. Both live in one temp dir cleaned on
|
|
133
|
+
* kill(). On reattach the layout file is unused but harmless. */
|
|
134
|
+
writeRuntimeFiles(bin, args, opts) {
|
|
135
|
+
this.tmpConfigDir = mkdtempSync(join(tmpdir(), 'bmx-zellij-'));
|
|
136
|
+
const configPath = join(this.tmpConfigDir, 'config.kdl');
|
|
137
|
+
const layoutPath = join(this.tmpConfigDir, 'layout.kdl');
|
|
138
|
+
writeFileSync(configPath, ZELLIJ_CONFIG_KDL);
|
|
139
|
+
if (!this.reattaching)
|
|
140
|
+
writeFileSync(layoutPath, buildLayoutString(bin, args, opts));
|
|
141
|
+
return { configPath, layoutPath };
|
|
142
|
+
}
|
|
143
|
+
get isReattach() {
|
|
144
|
+
return this.reattaching;
|
|
145
|
+
}
|
|
146
|
+
// ── Input ──
|
|
147
|
+
// In locked mode with cleared keybinds, raw bytes written to the client pty
|
|
148
|
+
// are forwarded verbatim to the focused pane — so every input path collapses
|
|
149
|
+
// to pty.write(), exactly like TmuxBackend.write().
|
|
150
|
+
write(data) {
|
|
151
|
+
this.process?.write(data);
|
|
152
|
+
}
|
|
153
|
+
/** Literal text, no Enter. */
|
|
154
|
+
sendText(text) {
|
|
155
|
+
this.process?.write(text);
|
|
156
|
+
}
|
|
157
|
+
/** Special keys by tmux-style name (Enter, Escape, C-c, M-Enter, …). */
|
|
158
|
+
sendSpecialKeys(...keys) {
|
|
159
|
+
for (const key of keys) {
|
|
160
|
+
this.process?.write(tmuxKeyToBytes(key));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/** Bracketed paste: wrap with \e[200~ … \e[201~ so TUIs (CoCo/Ink/Codex)
|
|
164
|
+
* detect the paste boundary and don't treat embedded \n as Enter. Mirrors
|
|
165
|
+
* `tmux paste-buffer -p`. */
|
|
166
|
+
pasteText(text) {
|
|
167
|
+
this.process?.write(`\x1b[200~${text}\x1b[201~`);
|
|
168
|
+
}
|
|
169
|
+
resize(cols, rows) {
|
|
170
|
+
this.process?.resize(cols, rows);
|
|
171
|
+
}
|
|
172
|
+
/** Must be called AFTER spawn(). */
|
|
173
|
+
onData(cb) {
|
|
174
|
+
this.process?.onData(cb);
|
|
175
|
+
}
|
|
176
|
+
/** Must be called AFTER spawn(). */
|
|
177
|
+
onExit(cb) {
|
|
178
|
+
this.process?.onExit(({ exitCode, signal }) => {
|
|
179
|
+
// Suppress the pty-client exit caused by our own kill()/destroySession()
|
|
180
|
+
// (intentional detach/teardown — the zellij session survives, so a
|
|
181
|
+
// claude_exit here would falsely tear the worker down on restart). A real
|
|
182
|
+
// CLI exit (pane closes → single-pane session ends) leaves intentionalExit
|
|
183
|
+
// false and is forwarded. Mirrors TmuxPipeBackend's intentional-detach
|
|
184
|
+
// semantics (pty-under TmuxBackend lacked this — the gap Codex flagged).
|
|
185
|
+
if (this.intentionalExit)
|
|
186
|
+
return;
|
|
187
|
+
cb(exitCode, signal !== undefined ? String(signal) : null);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/** CLI pid. May be null immediately after spawn() (the CLI subprocess starts
|
|
191
|
+
* asynchronously); the worker retries. Cached once resolved. */
|
|
192
|
+
getChildPid() {
|
|
193
|
+
if (this.resolvedCliPid !== null)
|
|
194
|
+
return this.resolvedCliPid;
|
|
195
|
+
this.resolvedCliPid = findPaneCliPid(this.sessionName, '');
|
|
196
|
+
return this.resolvedCliPid;
|
|
197
|
+
}
|
|
198
|
+
/** Detach only — kills the pty client, leaves the zellij session running. */
|
|
199
|
+
kill() {
|
|
200
|
+
this.intentionalExit = true;
|
|
201
|
+
if (this.process) {
|
|
202
|
+
try {
|
|
203
|
+
this.process.kill();
|
|
204
|
+
}
|
|
205
|
+
catch { /* already dead */ }
|
|
206
|
+
this.process = null;
|
|
207
|
+
}
|
|
208
|
+
this.cleanupConfig();
|
|
209
|
+
}
|
|
210
|
+
/** Kill the zellij session permanently (explicit /close). */
|
|
211
|
+
destroySession() {
|
|
212
|
+
this.kill();
|
|
213
|
+
if (this.ownsSession) {
|
|
214
|
+
ZellijBackend.killSession(this.sessionName);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
cleanupConfig() {
|
|
218
|
+
if (this.tmpConfigDir) {
|
|
219
|
+
try {
|
|
220
|
+
rmSync(this.tmpConfigDir, { recursive: true, force: true });
|
|
221
|
+
}
|
|
222
|
+
catch { /* benign */ }
|
|
223
|
+
this.tmpConfigDir = null;
|
|
224
|
+
this.configPath = null;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// ─── Pure helpers (unit-testable) ───────────────────────────────────────────
|
|
229
|
+
/**
|
|
230
|
+
* Locked mode + cleared keybinds => the client pty forwards every byte to the
|
|
231
|
+
* focused pane with no zellij interception. No startup tips / pane frames so
|
|
232
|
+
* the captured stream is just the CLI (we don't need to hide chrome, but a
|
|
233
|
+
* clean single pane keeps screenshots faithful and the renderer simple).
|
|
234
|
+
*/
|
|
235
|
+
export const ZELLIJ_CONFIG_KDL = `// botmux-generated — do not edit
|
|
236
|
+
show_startup_tips false
|
|
237
|
+
pane_frames false
|
|
238
|
+
default_mode "locked"
|
|
239
|
+
keybinds clear-defaults=true {
|
|
240
|
+
}
|
|
241
|
+
`;
|
|
242
|
+
/** Escape a string for a KDL double-quoted value. */
|
|
243
|
+
export function kdlString(s) {
|
|
244
|
+
return `"${s.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Build the `--layout-string` KDL: a single full-screen pane that execs the CLI
|
|
248
|
+
* through the user's shell (same wrapper TmuxBackend uses, so PATH / NVM / pnpm
|
|
249
|
+
* / mise shims load from rcfiles). Command + args go in via execvp semantics —
|
|
250
|
+
* no shell-quoting needed (KDL strings carry spaces/quotes), only KDL escaping.
|
|
251
|
+
*
|
|
252
|
+
* pane command="<shell>" close_on_exit=true {
|
|
253
|
+
* args "<flag>"… "-c" "<script>" "_" "<cwd>" "KEY=VAL"… "<bin>" "<arg>"…
|
|
254
|
+
* }
|
|
255
|
+
*/
|
|
256
|
+
export function buildLayoutString(bin, args, opts) {
|
|
257
|
+
const shellSpec = resolveUserShell();
|
|
258
|
+
const envAssignments = buildBotmuxEnvAssignments(opts.env);
|
|
259
|
+
const paneArgs = [
|
|
260
|
+
...shellSpec.flags, '-c', SHELL_WRAPPER_SCRIPT, '_',
|
|
261
|
+
opts.cwd,
|
|
262
|
+
...envAssignments,
|
|
263
|
+
bin, ...args,
|
|
264
|
+
];
|
|
265
|
+
const argsKdl = paneArgs.map(kdlString).join(' ');
|
|
266
|
+
return [
|
|
267
|
+
'layout {',
|
|
268
|
+
` pane command=${kdlString(shellSpec.shell)} close_on_exit=true {`,
|
|
269
|
+
` args ${argsKdl}`,
|
|
270
|
+
' }',
|
|
271
|
+
'}',
|
|
272
|
+
].join('\n');
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Map a tmux-style key name to the raw bytes a terminal emits for it. Covers
|
|
276
|
+
* the names botmux's adapters / worker actually send (Enter, Escape, C-<x>,
|
|
277
|
+
* M-<x>, arrows, Tab, BSpace, …). Unknown names fall back to the literal string
|
|
278
|
+
* so a missing mapping degrades to "typed as-is" rather than dropping input.
|
|
279
|
+
*/
|
|
280
|
+
export function tmuxKeyToBytes(key) {
|
|
281
|
+
const named = {
|
|
282
|
+
Enter: '\r',
|
|
283
|
+
Tab: '\t',
|
|
284
|
+
Escape: '\x1b',
|
|
285
|
+
Esc: '\x1b',
|
|
286
|
+
Space: ' ',
|
|
287
|
+
BSpace: '\x7f',
|
|
288
|
+
Backspace: '\x7f',
|
|
289
|
+
Up: '\x1b[A',
|
|
290
|
+
Down: '\x1b[B',
|
|
291
|
+
Right: '\x1b[C',
|
|
292
|
+
Left: '\x1b[D',
|
|
293
|
+
Home: '\x1b[H',
|
|
294
|
+
End: '\x1b[F',
|
|
295
|
+
PageUp: '\x1b[5~',
|
|
296
|
+
PageDown: '\x1b[6~',
|
|
297
|
+
'M-Enter': '\x1b\r',
|
|
298
|
+
};
|
|
299
|
+
if (key in named)
|
|
300
|
+
return named[key];
|
|
301
|
+
// C-<x>: control byte. C-a..C-z → 0x01..0x1a; C-c → ETX (0x03), etc.
|
|
302
|
+
const ctrl = key.match(/^C-([A-Za-z])$/);
|
|
303
|
+
if (ctrl) {
|
|
304
|
+
const c = ctrl[1].toLowerCase().charCodeAt(0) - 96; // 'a' -> 1
|
|
305
|
+
return String.fromCharCode(c);
|
|
306
|
+
}
|
|
307
|
+
// M-<x>: ESC prefix (Alt).
|
|
308
|
+
const meta = key.match(/^M-(.)$/);
|
|
309
|
+
if (meta)
|
|
310
|
+
return `\x1b${meta[1]}`;
|
|
311
|
+
// Unknown: best-effort literal.
|
|
312
|
+
return key;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Find the zellij `--server …/<sessionName>` process pid. The session name is
|
|
316
|
+
* the trailing path component of the server's socket argument, so we match the
|
|
317
|
+
* cmdline ending in `/<sessionName>`.
|
|
318
|
+
*/
|
|
319
|
+
export function findServerPid(sessionName) {
|
|
320
|
+
try {
|
|
321
|
+
const out = execFileSync('ps', ['-eo', 'pid=,args='], {
|
|
322
|
+
encoding: 'utf-8',
|
|
323
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
324
|
+
timeout: 3000,
|
|
325
|
+
env: zellijEnv(),
|
|
326
|
+
});
|
|
327
|
+
for (const line of out.split('\n')) {
|
|
328
|
+
const m = line.trim().match(/^(\d+)\s+(.*)$/);
|
|
329
|
+
if (!m)
|
|
330
|
+
continue;
|
|
331
|
+
const argv = m[2];
|
|
332
|
+
if (/zellij\b.*--server\b/.test(argv) && new RegExp(`/${escapeRe(sessionName)}$`).test(argv.trim())) {
|
|
333
|
+
return Number(m[1]);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch { /* ps unavailable */ }
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Best-effort CLI pid for the managed pane. With the SHELL_WRAPPER_SCRIPT's
|
|
342
|
+
* `exec /usr/bin/env "$@"`, the CLI replaces the shell and becomes a direct
|
|
343
|
+
* child of the zellij server, so the server's lone non-zellij child is the CLI.
|
|
344
|
+
*/
|
|
345
|
+
export function findPaneCliPid(sessionName, _binBasename) {
|
|
346
|
+
const server = findServerPid(sessionName);
|
|
347
|
+
if (!server)
|
|
348
|
+
return null;
|
|
349
|
+
try {
|
|
350
|
+
const out = execFileSync('ps', ['-eo', 'pid=,ppid=,comm='], {
|
|
351
|
+
encoding: 'utf-8',
|
|
352
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
353
|
+
timeout: 3000,
|
|
354
|
+
env: zellijEnv(),
|
|
355
|
+
});
|
|
356
|
+
const children = [];
|
|
357
|
+
for (const line of out.split('\n')) {
|
|
358
|
+
const m = line.trim().match(/^(\d+)\s+(\d+)\s+(.*)$/);
|
|
359
|
+
if (!m)
|
|
360
|
+
continue;
|
|
361
|
+
const [pid, ppid, comm] = [Number(m[1]), Number(m[2]), m[3]];
|
|
362
|
+
if (ppid === server && comm !== 'zellij')
|
|
363
|
+
children.push(pid);
|
|
364
|
+
}
|
|
365
|
+
// Single CLI pane → exactly one such child.
|
|
366
|
+
return children.length > 0 ? children[0] : null;
|
|
367
|
+
}
|
|
368
|
+
catch {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
function escapeRe(s) {
|
|
373
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
374
|
+
}
|
|
375
|
+
//# sourceMappingURL=zellij-backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zellij-backend.js","sourceRoot":"","sources":["../../../src/adapters/backend/zellij-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { ObserveBackend, SpawnOpts } from './types.js';
|
|
2
|
+
export declare class ZellijObserveBackend implements ObserveBackend {
|
|
3
|
+
private readonly session;
|
|
4
|
+
private readonly paneId;
|
|
5
|
+
private readonly cliPid;
|
|
6
|
+
private cols;
|
|
7
|
+
private rows;
|
|
8
|
+
private dataCbs;
|
|
9
|
+
private exitCbs;
|
|
10
|
+
private pollTimer;
|
|
11
|
+
private livenessTimer;
|
|
12
|
+
private lastSnapshot;
|
|
13
|
+
private exited;
|
|
14
|
+
claudeJsonlPath?: string;
|
|
15
|
+
cliCwd?: string;
|
|
16
|
+
constructor(session: string, paneId: string, opts?: {
|
|
17
|
+
cliPid?: number;
|
|
18
|
+
});
|
|
19
|
+
/** bin/args are ignored — we observe an existing pane, we don't launch. */
|
|
20
|
+
spawn(_bin: string, _args: string[], opts: SpawnOpts): void;
|
|
21
|
+
private poll;
|
|
22
|
+
private checkLiveness;
|
|
23
|
+
/** Whether the adopted CLI process is still running. Unknown pid → defer to
|
|
24
|
+
* pane liveness only. EPERM (exists, not ours) counts as alive; ESRCH = gone. */
|
|
25
|
+
private isCliPidAlive;
|
|
26
|
+
private handlePaneExit;
|
|
27
|
+
write(data: string): void;
|
|
28
|
+
/** Literal text via write-chars (preserves UTF-8). */
|
|
29
|
+
sendText(text: string): void;
|
|
30
|
+
/** Special keys by tmux-style name → raw bytes → `action write`. */
|
|
31
|
+
sendSpecialKeys(...keys: string[]): void;
|
|
32
|
+
/** Bracketed paste — wrap so TUIs detect the boundary (mirrors paste-buffer -p). */
|
|
33
|
+
pasteText(text: string): void;
|
|
34
|
+
/** Write arbitrary bytes via `action write <decimal>…` (handles control/escape).
|
|
35
|
+
* Chunked so a large web-terminal paste can't blow the argv limit; zellij
|
|
36
|
+
* serialises the writes in arrival order. */
|
|
37
|
+
private writeBytes;
|
|
38
|
+
/** Resize is a NO-OP in observe mode — the pane size is the user's, and
|
|
39
|
+
* resizing it would disturb their layout. The transient snapshot reads the
|
|
40
|
+
* real pane size via getPaneSize(). */
|
|
41
|
+
resize(_cols: number, _rows: number): void;
|
|
42
|
+
onData(cb: (data: string) => void): void;
|
|
43
|
+
onExit(cb: (code: number | null, signal: string | null) => void): void;
|
|
44
|
+
getChildPid(): number | null;
|
|
45
|
+
/** Detach observer — stop polling. Never touches the user's zellij session. */
|
|
46
|
+
kill(): void;
|
|
47
|
+
/** Adopt owns nothing — destroy == detach (don't kill the user's session). */
|
|
48
|
+
destroySession(): void;
|
|
49
|
+
private stopTimers;
|
|
50
|
+
captureCurrentScreen(): string;
|
|
51
|
+
captureViewport(): string;
|
|
52
|
+
getPaneSize(): {
|
|
53
|
+
cols: number;
|
|
54
|
+
rows: number;
|
|
55
|
+
} | null;
|
|
56
|
+
isPaneAlive(): boolean;
|
|
57
|
+
private dumpScreen;
|
|
58
|
+
private listPane;
|
|
59
|
+
/** Run a `zellij --session S action …`, returning stdout or null on failure. */
|
|
60
|
+
private action;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=zellij-observe-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zellij-observe-backend.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/zellij-observe-backend.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAiC5D,qBAAa,oBAAqB,YAAW,cAAc;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,IAAI,CAAS;IAErB,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,OAAO,CAAmE;IAClF,OAAO,CAAC,SAAS,CAA+C;IAChE,OAAO,CAAC,aAAa,CAA+C;IACpE,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,MAAM,CAAS;IAGvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;gBAEJ,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IAUvE,2EAA2E;IAC3E,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAQ3D,OAAO,CAAC,IAAI;IASZ,OAAO,CAAC,aAAa;IAUrB;sFACkF;IAClF,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,cAAc;IAStB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIzB,sDAAsD;IACtD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK5B,oEAAoE;IACpE,eAAe,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAIxC,oFAAoF;IACpF,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM7B;;kDAE8C;IAC9C,OAAO,CAAC,UAAU;IAUlB;;4CAEwC;IACxC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAE1C,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IACxC,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI;IAEtE,WAAW,IAAI,MAAM,GAAG,IAAI;IAE5B,+EAA+E;IAC/E,IAAI,IAAI,IAAI;IAEZ,8EAA8E;IAC9E,cAAc,IAAI,IAAI;IAEtB,OAAO,CAAC,UAAU;IAOlB,oBAAoB,IAAI,MAAM;IAI9B,eAAe,IAAI,MAAM;IAIzB,WAAW,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IASpD,WAAW,IAAI,OAAO;IAOtB,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,QAAQ;IAahB,gFAAgF;IAChF,OAAO,CAAC,MAAM;CAUf"}
|