tmuxes 0.1.7 → 0.1.9
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/.node-version +1 -0
- package/.nvmrc +1 -0
- package/.tmp-npm-cache/_cacache/content-v2/sha512/43/27/5e000b8b9c56a6ccc66f709485499f4304e2cb1982582ba571321c07b3ef56fcabd2c671898cc8003365a0485b6fd8e73e7b17b073cec0f7d1628c1a99df +0 -0
- package/.tmp-npm-cache/_cacache/content-v2/sha512/51/cf/4301295d74559ed494bae160d54d8741077f89faebb311882ac065019246951e7b53f3dcb913793c42b331e14c7070c4810c3cdc27a427d103a7db4614e0 +0 -0
- package/.tmp-npm-cache/_cacache/content-v2/sha512/c3/4d/d68a454a916e74c2617f586fbf770981b33811d667c2547eb0e9fc21938f4ee7e98f1ceee4bde8ad8815b5f6efe21b60eee798837d68f51a3340d7e5bb7a +0 -0
- package/.tmp-npm-cache/_cacache/content-v2/sha512/fe/40/2abfbefc96299e8bf714aa91d62607190ae299e102cf5933db2e2904640d65d25d67dbbb6fa2ddc92a17f00b9dbfdf2e37487f67d96ec36c64a285b59a7d +0 -0
- package/.tmp-npm-cache/_cacache/index-v5/27/fe/81a3de6ce7ae3d1e41a3421de20c5629998c4ee5d0ffe2037630f03b03b2 +4 -0
- package/.tmp-npm-cache/_cacache/index-v5/65/22/dd66711f62681fce09aabb2357a2907b4a0c778ac5227c4baf9603fd86e8 +4 -0
- package/.tmp-npm-cache/_update-notifier-last-checked +0 -0
- package/AGENTS.md +15 -0
- package/CLAUDE.md +3 -0
- package/LICENSE +21 -21
- package/README.en.md +304 -0
- package/README.md +301 -289
- package/SECURITY.md +31 -0
- package/{public → client}/index.html +12 -13
- package/client/package.json +29 -0
- package/client/src/App.tsx +123 -0
- package/client/src/activity.ts +5 -0
- package/client/src/api.ts +130 -0
- package/client/src/attention.tsx +157 -0
- package/client/src/components/FileExplorer.tsx +156 -0
- package/client/src/components/FileViewer.tsx +194 -0
- package/client/src/components/SessionRow.tsx +108 -0
- package/client/src/components/SessionTree.tsx +197 -0
- package/client/src/components/SettingsButton.tsx +122 -0
- package/client/src/components/Sidebar.tsx +96 -0
- package/client/src/components/StatusBanner.tsx +31 -0
- package/client/src/components/TargetGroup.tsx +275 -0
- package/client/src/components/TerminalPanel.tsx +192 -0
- package/client/src/folders.ts +245 -0
- package/client/src/hooks/useTerminal.ts +67 -0
- package/client/src/hooks/useTmuxSocket.ts +65 -0
- package/client/src/i18n.ts +213 -0
- package/client/src/main.tsx +17 -0
- package/client/src/settings.tsx +87 -0
- package/client/src/styles.css +723 -0
- package/client/src/types.ts +93 -0
- package/client/src/util.ts +65 -0
- package/client/tsconfig.json +13 -0
- package/client/vite.config.ts +15 -0
- package/fig/fig1.png +0 -0
- package/package.json +28 -61
- package/scripts/prepack.mjs +35 -0
- package/{bin → server/bin}/tmuxes.js +36 -36
- package/server/package.json +61 -0
- package/server/src/agentHooks.ts +120 -0
- package/server/src/agentOutput.ts +36 -0
- package/server/src/agentState.ts +70 -0
- package/server/src/config.ts +31 -0
- package/server/src/exe.ts +34 -0
- package/server/src/exec.ts +61 -0
- package/server/src/files.ts +330 -0
- package/server/src/foldersStore.ts +114 -0
- package/server/src/index.ts +114 -0
- package/server/src/logger.ts +16 -0
- package/{dist/monitor.js → server/src/monitor.ts} +10 -9
- package/server/src/openBrowser.ts +28 -0
- package/{dist/platform.js → server/src/platform.ts} +4 -5
- package/server/src/rest/router.ts +290 -0
- package/server/src/targetCommand.ts +79 -0
- package/server/src/targets.ts +152 -0
- package/server/src/tmux/builder.ts +198 -0
- package/server/src/tmux/formats.ts +95 -0
- package/server/src/tmux/sessions.ts +204 -0
- package/server/src/validate.ts +79 -0
- package/server/src/windowsSsh.ts +239 -0
- package/server/src/winshell/manager.ts +296 -0
- package/server/src/ws/protocol.ts +15 -0
- package/server/src/ws/sshState.ts +36 -0
- package/server/src/ws/terminalSession.ts +207 -0
- package/server/src/ws/wsServer.ts +153 -0
- package/server/src/wsl.ts +38 -0
- package/server/test/agentHooks.test.ts +66 -0
- package/server/test/agentOutput.test.ts +26 -0
- package/server/test/agentState.test.ts +24 -0
- package/server/test/builder.test.ts +162 -0
- package/server/test/files.test.ts +81 -0
- package/server/test/formats.test.ts +123 -0
- package/server/test/monitor.test.ts +25 -0
- package/server/test/validate.test.ts +71 -0
- package/server/test/wsl.test.ts +18 -0
- package/server/tsconfig.json +9 -0
- package/server/vitest.config.ts +12 -0
- package/start.cmd +30 -0
- package/start.command +20 -0
- package/start.sh +20 -0
- package/tsconfig.base.json +19 -0
- package/dist/agentHooks.js +0 -91
- package/dist/agentHooks.js.map +0 -1
- package/dist/agentOutput.js +0 -30
- package/dist/agentOutput.js.map +0 -1
- package/dist/agentState.js +0 -45
- package/dist/agentState.js.map +0 -1
- package/dist/config.js +0 -32
- package/dist/config.js.map +0 -1
- package/dist/exe.js +0 -37
- package/dist/exe.js.map +0 -1
- package/dist/exec.js +0 -43
- package/dist/exec.js.map +0 -1
- package/dist/files.js +0 -243
- package/dist/files.js.map +0 -1
- package/dist/foldersStore.js +0 -103
- package/dist/foldersStore.js.map +0 -1
- package/dist/index.js +0 -117
- package/dist/index.js.map +0 -1
- package/dist/logger.js +0 -16
- package/dist/logger.js.map +0 -1
- package/dist/monitor.js.map +0 -1
- package/dist/openBrowser.js +0 -31
- package/dist/openBrowser.js.map +0 -1
- package/dist/platform.js.map +0 -1
- package/dist/rest/router.js +0 -190
- package/dist/rest/router.js.map +0 -1
- package/dist/targetCommand.js +0 -41
- package/dist/targetCommand.js.map +0 -1
- package/dist/targets.js +0 -131
- package/dist/targets.js.map +0 -1
- package/dist/tmux/builder.js +0 -173
- package/dist/tmux/builder.js.map +0 -1
- package/dist/tmux/formats.js +0 -61
- package/dist/tmux/formats.js.map +0 -1
- package/dist/tmux/sessions.js +0 -157
- package/dist/tmux/sessions.js.map +0 -1
- package/dist/validate.js +0 -65
- package/dist/validate.js.map +0 -1
- package/dist/winshell/manager.js +0 -267
- package/dist/winshell/manager.js.map +0 -1
- package/dist/ws/protocol.js +0 -4
- package/dist/ws/protocol.js.map +0 -1
- package/dist/ws/sshState.js +0 -35
- package/dist/ws/sshState.js.map +0 -1
- package/dist/ws/terminalSession.js +0 -204
- package/dist/ws/terminalSession.js.map +0 -1
- package/dist/ws/wsServer.js +0 -151
- package/dist/ws/wsServer.js.map +0 -1
- package/dist/wsl.js +0 -35
- package/dist/wsl.js.map +0 -1
- package/public/assets/index-BpVrfoZw.js +0 -44
- package/public/assets/index-D_X5SnGx.css +0 -1
package/dist/openBrowser.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openBrowser.js","sourceRoot":"","sources":["../src/openBrowser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC;mDACmD;AACnD,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,CAAC;QACH,IAAI,IAAY,CAAC;QACjB,IAAI,IAAc,CAAC;QACnB,IAAI,SAAS,EAAE,CAAC;YACd,4EAA4E;YAC5E,IAAI,GAAG,SAAS,CAAC;YACjB,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;QAClC,CAAC;aAAM,IAAI,KAAK,EAAE,CAAC;YACjB,IAAI,GAAG,MAAM,CAAC;YACd,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,UAAU,CAAC;YAClB,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC3E,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,IAAI,CAAC,2BAA2B,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpF,CAAC;AACH,CAAC"}
|
package/dist/platform.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA;sDACsD;AACtD,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;AACtD,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC"}
|
package/dist/rest/router.js
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import { Router } from 'express';
|
|
2
|
-
import { getTarget, isValidTargetId, refreshTargets } from '../targets.js';
|
|
3
|
-
import { isValidSessionName } from '../validate.js';
|
|
4
|
-
import { TmuxError, listSessions, createSession, renameSession, killSession, listWindows, launchAgentInSession, } from '../tmux/sessions.js';
|
|
5
|
-
import { annotate } from '../monitor.js';
|
|
6
|
-
import { getSessionCwd, listDirectory, readFilePreview, resolveScopedPath, writeFile } from '../files.js';
|
|
7
|
-
import { readFolders, writeFolders } from '../foldersStore.js';
|
|
8
|
-
import { winShell, ManagerError } from '../winshell/manager.js';
|
|
9
|
-
/** Cap on a saved file's size (matches the editor's text-only use). */
|
|
10
|
-
const MAX_WRITE_BYTES = 5_000_000;
|
|
11
|
-
const wrap = (fn) => (req, res, next) => {
|
|
12
|
-
fn(req, res).catch(next);
|
|
13
|
-
};
|
|
14
|
-
/** Resolve :id → Target or throw a TmuxError with the right status. */
|
|
15
|
-
function requireTarget(req) {
|
|
16
|
-
const id = req.params.id;
|
|
17
|
-
if (!isValidTargetId(id))
|
|
18
|
-
throw new TmuxError(400, 'invalid target id');
|
|
19
|
-
const target = getTarget(id);
|
|
20
|
-
if (!target)
|
|
21
|
-
throw new TmuxError(404, 'target not found');
|
|
22
|
-
return target;
|
|
23
|
-
}
|
|
24
|
-
function requireSessionName(raw) {
|
|
25
|
-
if (!isValidSessionName(raw))
|
|
26
|
-
throw new TmuxError(400, 'invalid session name');
|
|
27
|
-
return raw;
|
|
28
|
-
}
|
|
29
|
-
function requireLaunchAgent(raw) {
|
|
30
|
-
if (raw === 'claude' || raw === 'codex')
|
|
31
|
-
return raw;
|
|
32
|
-
throw new TmuxError(400, 'invalid agent');
|
|
33
|
-
}
|
|
34
|
-
/** A filesystem path supplied via query. Passed as a single argv element (no
|
|
35
|
-
* shell), so we only sanity-check shape, not contents — this app already
|
|
36
|
-
* grants full shell access on the target by design. */
|
|
37
|
-
function requirePath(raw) {
|
|
38
|
-
if (typeof raw !== 'string' || raw.length === 0 || raw.length > 4096 || raw.includes('\0')) {
|
|
39
|
-
throw new TmuxError(400, 'invalid path');
|
|
40
|
-
}
|
|
41
|
-
return raw;
|
|
42
|
-
}
|
|
43
|
-
async function requireSessionScopedPath(target, session, path, opts = {}) {
|
|
44
|
-
const name = requireSessionName(session);
|
|
45
|
-
const rawPath = requirePath(path);
|
|
46
|
-
const cwd = await getSessionCwd(target, name);
|
|
47
|
-
return resolveScopedPath(target, cwd, rawPath, opts);
|
|
48
|
-
}
|
|
49
|
-
export const apiRouter = Router();
|
|
50
|
-
apiRouter.get('/health', (_req, res) => {
|
|
51
|
-
res.json({ ok: true });
|
|
52
|
-
});
|
|
53
|
-
apiRouter.get('/targets', wrap(async (_req, res) => {
|
|
54
|
-
// Re-discover (WSL distros / ssh config can change between loads).
|
|
55
|
-
res.json({ targets: await refreshTargets() });
|
|
56
|
-
}));
|
|
57
|
-
apiRouter.get('/targets/:id/sessions', wrap(async (req, res) => {
|
|
58
|
-
const target = requireTarget(req);
|
|
59
|
-
const sessions = target.kind === 'winlocal' ? winShell.list() : await listSessions(target);
|
|
60
|
-
res.json({ sessions: annotate(target.id, sessions) });
|
|
61
|
-
}));
|
|
62
|
-
apiRouter.post('/targets/:id/sessions', wrap(async (req, res) => {
|
|
63
|
-
const target = requireTarget(req);
|
|
64
|
-
const body = (req.body ?? {});
|
|
65
|
-
const name = body.name === undefined || body.name === '' ? undefined : body.name;
|
|
66
|
-
if (name !== undefined && !isValidSessionName(name)) {
|
|
67
|
-
throw new TmuxError(400, 'invalid session name');
|
|
68
|
-
}
|
|
69
|
-
const command = typeof body.command === 'string' && body.command.length > 0 ? body.command : undefined;
|
|
70
|
-
if (target.kind === 'winlocal') {
|
|
71
|
-
const shellId = typeof body.shell === 'string' ? body.shell : undefined;
|
|
72
|
-
res.status(201).json(winShell.create({ name, shellId, command }));
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
const result = await createSession(target, { name, command });
|
|
76
|
-
res.status(201).json(result);
|
|
77
|
-
}));
|
|
78
|
-
apiRouter.patch('/targets/:id/sessions/:name', wrap(async (req, res) => {
|
|
79
|
-
const target = requireTarget(req);
|
|
80
|
-
const name = requireSessionName(req.params.name);
|
|
81
|
-
const newName = (req.body ?? {}).newName;
|
|
82
|
-
if (!isValidSessionName(newName))
|
|
83
|
-
throw new TmuxError(400, 'invalid new session name');
|
|
84
|
-
if (target.kind === 'winlocal') {
|
|
85
|
-
winShell.rename(name, newName);
|
|
86
|
-
res.json({ name: newName });
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
await renameSession(target, name, newName);
|
|
90
|
-
res.json({ name: newName });
|
|
91
|
-
}));
|
|
92
|
-
apiRouter.post('/targets/:id/sessions/:name/agent', wrap(async (req, res) => {
|
|
93
|
-
const target = requireTarget(req);
|
|
94
|
-
if (target.kind === 'winlocal')
|
|
95
|
-
throw new TmuxError(400, 'agent hooks require a tmux target');
|
|
96
|
-
const name = requireSessionName(req.params.name);
|
|
97
|
-
const agent = requireLaunchAgent((req.body ?? {}).agent);
|
|
98
|
-
await launchAgentInSession(target, name, agent);
|
|
99
|
-
res.json({ ok: true });
|
|
100
|
-
}));
|
|
101
|
-
apiRouter.delete('/targets/:id/sessions/:name', wrap(async (req, res) => {
|
|
102
|
-
const target = requireTarget(req);
|
|
103
|
-
const name = requireSessionName(req.params.name);
|
|
104
|
-
if (target.kind === 'winlocal') {
|
|
105
|
-
winShell.kill(name);
|
|
106
|
-
res.status(204).end();
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
await killSession(target, name);
|
|
110
|
-
res.status(204).end();
|
|
111
|
-
}));
|
|
112
|
-
apiRouter.get('/targets/:id/sessions/:name/windows', wrap(async (req, res) => {
|
|
113
|
-
const target = requireTarget(req);
|
|
114
|
-
const name = requireSessionName(req.params.name);
|
|
115
|
-
if (target.kind === 'winlocal') {
|
|
116
|
-
res.json({ windows: winShell.windows(name) });
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
res.json({ windows: await listWindows(target, name) });
|
|
120
|
-
}));
|
|
121
|
-
/** The file browser relies on tmux's pane cwd; native Windows shells have none. */
|
|
122
|
-
function rejectIfWinlocal(target) {
|
|
123
|
-
if (target.kind === 'winlocal') {
|
|
124
|
-
throw new TmuxError(400, 'file browsing is not available for native shell sessions');
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
// --- File browser (current pane cwd + directory listing + file preview) ---
|
|
128
|
-
apiRouter.get('/targets/:id/sessions/:name/cwd', wrap(async (req, res) => {
|
|
129
|
-
const target = requireTarget(req);
|
|
130
|
-
rejectIfWinlocal(target);
|
|
131
|
-
const name = requireSessionName(req.params.name);
|
|
132
|
-
res.json({ cwd: await getSessionCwd(target, name) });
|
|
133
|
-
}));
|
|
134
|
-
apiRouter.get('/targets/:id/files', wrap(async (req, res) => {
|
|
135
|
-
const target = requireTarget(req);
|
|
136
|
-
rejectIfWinlocal(target);
|
|
137
|
-
const path = await requireSessionScopedPath(target, req.query.session, req.query.path);
|
|
138
|
-
res.json({ path, entries: await listDirectory(target, path) });
|
|
139
|
-
}));
|
|
140
|
-
apiRouter.get('/targets/:id/file', wrap(async (req, res) => {
|
|
141
|
-
const target = requireTarget(req);
|
|
142
|
-
rejectIfWinlocal(target);
|
|
143
|
-
const path = await requireSessionScopedPath(target, req.query.session, req.query.path);
|
|
144
|
-
res.json(await readFilePreview(target, path));
|
|
145
|
-
}));
|
|
146
|
-
apiRouter.put('/targets/:id/file', wrap(async (req, res) => {
|
|
147
|
-
const target = requireTarget(req);
|
|
148
|
-
rejectIfWinlocal(target);
|
|
149
|
-
const body = (req.body ?? {});
|
|
150
|
-
const path = await requireSessionScopedPath(target, body.session, body.path, { forWrite: true });
|
|
151
|
-
if (typeof body.content !== 'string')
|
|
152
|
-
throw new TmuxError(400, 'content must be a string');
|
|
153
|
-
if (Buffer.byteLength(body.content, 'utf8') > MAX_WRITE_BYTES) {
|
|
154
|
-
throw new TmuxError(413, 'file too large to save');
|
|
155
|
-
}
|
|
156
|
-
await writeFile(target, path, body.content);
|
|
157
|
-
res.json({ ok: true });
|
|
158
|
-
}));
|
|
159
|
-
// --- Sidebar folder organization, persisted on the target (syncs clients) ---
|
|
160
|
-
apiRouter.get('/targets/:id/folders', wrap(async (req, res) => {
|
|
161
|
-
const target = requireTarget(req);
|
|
162
|
-
res.json(await readFolders(target));
|
|
163
|
-
}));
|
|
164
|
-
apiRouter.put('/targets/:id/folders', wrap(async (req, res) => {
|
|
165
|
-
const target = requireTarget(req);
|
|
166
|
-
const body = req.body;
|
|
167
|
-
if (!body ||
|
|
168
|
-
typeof body !== 'object' ||
|
|
169
|
-
Array.isArray(body) ||
|
|
170
|
-
!Array.isArray(body.folders) ||
|
|
171
|
-
typeof body.assign !== 'object' ||
|
|
172
|
-
body.assign === null) {
|
|
173
|
-
throw new TmuxError(400, 'invalid folders payload');
|
|
174
|
-
}
|
|
175
|
-
await writeFolders(target, {
|
|
176
|
-
folders: body.folders,
|
|
177
|
-
assign: body.assign,
|
|
178
|
-
});
|
|
179
|
-
res.json({ ok: true });
|
|
180
|
-
}));
|
|
181
|
-
// Central error mapper.
|
|
182
|
-
apiRouter.use((err, _req, res, _next) => {
|
|
183
|
-
if (err instanceof TmuxError || err instanceof ManagerError) {
|
|
184
|
-
res.status(err.status).json({ error: err.message });
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
const message = err instanceof Error ? err.message : 'internal error';
|
|
188
|
-
res.status(500).json({ error: message });
|
|
189
|
-
});
|
|
190
|
-
//# sourceMappingURL=router.js.map
|
package/dist/rest/router.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/rest/router.ts"],"names":[],"mappings":"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"}
|
package/dist/targetCommand.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { unlinkSync } from 'node:fs';
|
|
2
|
-
import { runCommand } from './exec.js';
|
|
3
|
-
import { sshControlPath } from './tmux/builder.js';
|
|
4
|
-
const SSH_INTERRUPTION_RE = /mux_client_request_session|Control socket connect|Broken pipe|Connection reset|Connection closed|Connection to .* closed|Connection timed out|Operation timed out|No route to host|Network is unreachable|Connection refused|kex_exchange_identification|banner exchange|stdio forwarding failed/i;
|
|
5
|
-
const SSH_CLIENT_FAILURE_RE = /Permission denied \(|Host key verification failed|REMOTE HOST IDENTIFICATION HAS CHANGED|Could not resolve hostname|Too many authentication failures|Connection timed out|Operation timed out|No route to host|Network is unreachable|Connection refused|Connection reset|Connection closed|Connection to .* closed|Broken pipe|kex_exchange_identification|banner exchange/i;
|
|
6
|
-
function firstLine(stderr) {
|
|
7
|
-
return stderr.trim().split('\n')[0] || 'ssh command failed';
|
|
8
|
-
}
|
|
9
|
-
function isInterruptedSsh(result) {
|
|
10
|
-
return result.code !== 0 && SSH_INTERRUPTION_RE.test(result.stderr);
|
|
11
|
-
}
|
|
12
|
-
function isSshClientFailure(result) {
|
|
13
|
-
return result.code !== 0 && SSH_CLIENT_FAILURE_RE.test(result.stderr);
|
|
14
|
-
}
|
|
15
|
-
/** Run a target command. If an SSH control master is stale/interrupted, retry
|
|
16
|
-
* exactly once using a fresh direct SSH connection. Authentication failures are
|
|
17
|
-
* not retried, to avoid repeated failed-login noise. */
|
|
18
|
-
export async function runTargetCommand(target, buildArgv, opts = {}) {
|
|
19
|
-
const firstArgv = buildArgv({ multiplex: true });
|
|
20
|
-
const first = await runCommand(firstArgv.file, firstArgv.args, opts);
|
|
21
|
-
if (target.kind !== 'ssh' || !isInterruptedSsh(first))
|
|
22
|
-
return first;
|
|
23
|
-
const controlPath = sshControlPath(target);
|
|
24
|
-
if (controlPath) {
|
|
25
|
-
try {
|
|
26
|
-
unlinkSync(controlPath);
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
/* stale socket may already be gone */
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
const retryArgv = buildArgv({ multiplex: false });
|
|
33
|
-
const retry = await runCommand(retryArgv.file, retryArgv.args, opts);
|
|
34
|
-
if (retry.code === 0 || !isSshClientFailure(retry))
|
|
35
|
-
return retry;
|
|
36
|
-
return {
|
|
37
|
-
...retry,
|
|
38
|
-
stderr: `SSH connection interrupted; one reconnect attempt failed: ${firstLine(retry.stderr)}\n${retry.stderr}`,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
//# sourceMappingURL=targetCommand.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"targetCommand.js","sourceRoot":"","sources":["../src/targetCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAuC,MAAM,WAAW,CAAC;AAE5E,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAInD,MAAM,mBAAmB,GACvB,mSAAmS,CAAC;AAEtS,MAAM,qBAAqB,GACzB,8WAA8W,CAAC;AAEjX,SAAS,SAAS,CAAC,MAAc;IAC/B,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,oBAAoB,CAAC;AAC9D,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAqB;IAC7C,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACtE,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAqB;IAC/C,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACxE,CAAC;AAED;;wDAEwD;AACxD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAc,EACd,SAAoB,EACpB,OAAmB,EAAE;IAErB,MAAM,SAAS,GAAG,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrE,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEpE,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,UAAU,CAAC,WAAW,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,sCAAsC;QACxC,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,SAAS,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrE,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEjE,OAAO;QACL,GAAG,KAAK;QACR,MAAM,EAAE,6DAA6D,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,MAAM,EAAE;KAChH,CAAC;AACJ,CAAC"}
|
package/dist/targets.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { isValidHostAlias, parseHostSpec } from './validate.js';
|
|
5
|
-
import { isWindows } from './platform.js';
|
|
6
|
-
import { listWslDistros } from './wsl.js';
|
|
7
|
-
import { winShell } from './winshell/manager.js';
|
|
8
|
-
import { log } from './logger.js';
|
|
9
|
-
/** Native Windows shells (PowerShell/cmd via ConPTY). Enabled on Windows, or
|
|
10
|
-
* anywhere via TMUXES_FAKE_WINSHELL for testing the path on Linux/macOS. */
|
|
11
|
-
const WINSHELL_ENABLED = isWindows || !!process.env.TMUXES_FAKE_WINSHELL;
|
|
12
|
-
function winlocalTarget() {
|
|
13
|
-
return {
|
|
14
|
-
id: 'winlocal',
|
|
15
|
-
kind: 'winlocal',
|
|
16
|
-
label: isWindows ? 'Windows (local)' : 'Local shell (fake)',
|
|
17
|
-
shells: winShell.listShells(),
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
const ID_RE = /^[A-Za-z0-9._-]{1,128}$/;
|
|
21
|
-
export function isValidTargetId(id) {
|
|
22
|
-
return typeof id === 'string' && ID_RE.test(id);
|
|
23
|
-
}
|
|
24
|
-
function slug(s) {
|
|
25
|
-
return s.replace(/[^A-Za-z0-9._-]/g, '-');
|
|
26
|
-
}
|
|
27
|
-
const LOCAL = { id: 'local', kind: 'local', label: 'Local' };
|
|
28
|
-
/** Best-effort, read-only parse of ~/.ssh/config Host aliases (no wildcards). */
|
|
29
|
-
function parseSshConfig() {
|
|
30
|
-
const path = join(homedir(), '.ssh', 'config');
|
|
31
|
-
let text;
|
|
32
|
-
try {
|
|
33
|
-
text = readFileSync(path, 'utf8');
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
return []; // no config file is normal
|
|
37
|
-
}
|
|
38
|
-
const targets = [];
|
|
39
|
-
const seen = new Set();
|
|
40
|
-
for (const rawLine of text.split('\n')) {
|
|
41
|
-
const line = rawLine.trim();
|
|
42
|
-
if (!line || line.startsWith('#'))
|
|
43
|
-
continue;
|
|
44
|
-
const m = /^Host\s+(.+)$/i.exec(line);
|
|
45
|
-
if (!m)
|
|
46
|
-
continue;
|
|
47
|
-
for (const token of m[1].split(/\s+/)) {
|
|
48
|
-
// Skip wildcard / negated patterns — they aren't concrete hosts.
|
|
49
|
-
if (token.includes('*') || token.includes('?') || token.startsWith('!'))
|
|
50
|
-
continue;
|
|
51
|
-
if (!isValidHostAlias(token) || seen.has(token))
|
|
52
|
-
continue;
|
|
53
|
-
seen.add(token);
|
|
54
|
-
targets.push({ id: `cfg-${slug(token)}`, kind: 'ssh', label: token, host: token });
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return targets;
|
|
58
|
-
}
|
|
59
|
-
/** Parse the TMUXES_HOSTS="alice@web1,bob@db2:2222" override. */
|
|
60
|
-
function parseEnvHosts() {
|
|
61
|
-
const env = process.env.TMUXES_HOSTS;
|
|
62
|
-
if (!env)
|
|
63
|
-
return [];
|
|
64
|
-
const targets = [];
|
|
65
|
-
for (const part of env.split(',')) {
|
|
66
|
-
const spec = parseHostSpec(part);
|
|
67
|
-
if (!spec) {
|
|
68
|
-
log.warn(`ignoring invalid TMUXES_HOSTS entry: ${part.trim()}`);
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
const label = `${spec.user ? `${spec.user}@` : ''}${spec.host}${spec.port ? `:${spec.port}` : ''}`;
|
|
72
|
-
targets.push({
|
|
73
|
-
id: `env-${slug(label)}`,
|
|
74
|
-
kind: 'ssh',
|
|
75
|
-
label,
|
|
76
|
-
host: spec.host,
|
|
77
|
-
user: spec.user,
|
|
78
|
-
port: spec.port,
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
return targets;
|
|
82
|
-
}
|
|
83
|
-
function sshTargets() {
|
|
84
|
-
const all = [...parseEnvHosts(), ...parseSshConfig()];
|
|
85
|
-
const byId = new Map();
|
|
86
|
-
for (const t of all)
|
|
87
|
-
if (!byId.has(t.id))
|
|
88
|
-
byId.set(t.id, t);
|
|
89
|
-
return [...byId.values()];
|
|
90
|
-
}
|
|
91
|
-
/** The synchronous part of the target list (everything except WSL discovery). */
|
|
92
|
-
function baseTargets() {
|
|
93
|
-
const base = [];
|
|
94
|
-
if (WINSHELL_ENABLED)
|
|
95
|
-
base.push(winlocalTarget());
|
|
96
|
-
// Windows has no native tmux; its "local" machine is reached through WSL.
|
|
97
|
-
if (!isWindows)
|
|
98
|
-
base.push(LOCAL);
|
|
99
|
-
return [...base, ...sshTargets()];
|
|
100
|
-
}
|
|
101
|
-
// Cache so the (async, Windows-only) WSL discovery doesn't run on the WS
|
|
102
|
-
// upgrade path. The client always GETs /api/targets first, which refreshes it.
|
|
103
|
-
let cachedTargets = baseTargets();
|
|
104
|
-
/** Recompute the full target list, including WSL distros on Windows. */
|
|
105
|
-
export async function refreshTargets() {
|
|
106
|
-
if (isWindows) {
|
|
107
|
-
const distros = await listWslDistros();
|
|
108
|
-
const wsl = distros.map((name) => ({
|
|
109
|
-
id: `wsl-${slug(name)}`,
|
|
110
|
-
kind: 'wsl',
|
|
111
|
-
label: name,
|
|
112
|
-
distro: name,
|
|
113
|
-
}));
|
|
114
|
-
cachedTargets = [winlocalTarget(), ...wsl, ...sshTargets()];
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
cachedTargets = baseTargets();
|
|
118
|
-
}
|
|
119
|
-
return cachedTargets;
|
|
120
|
-
}
|
|
121
|
-
export function listTargets() {
|
|
122
|
-
return cachedTargets;
|
|
123
|
-
}
|
|
124
|
-
export function getTarget(id) {
|
|
125
|
-
return cachedTargets.find((t) => t.id === id);
|
|
126
|
-
}
|
|
127
|
-
/** ssh destination string: "user@host" or just the config alias / host. */
|
|
128
|
-
export function sshDestination(t) {
|
|
129
|
-
return t.user ? `${t.user}@${t.host}` : `${t.host}`;
|
|
130
|
-
}
|
|
131
|
-
//# sourceMappingURL=targets.js.map
|
package/dist/targets.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"targets.js","sourceRoot":"","sources":["../src/targets.ts"],"names":[],"mappings":"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"}
|
package/dist/tmux/builder.js
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
2
|
-
import { mkdirSync } from 'node:fs';
|
|
3
|
-
import { homedir, tmpdir } from 'node:os';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
import { config } from '../config.js';
|
|
6
|
-
import { sshDestination } from '../targets.js';
|
|
7
|
-
import { isWindows } from '../platform.js';
|
|
8
|
-
/**
|
|
9
|
-
* Single-quote a string for a POSIX shell. Needed ONLY for the remote ssh path:
|
|
10
|
-
* ssh concatenates the remote command words with spaces and re-parses them
|
|
11
|
-
* through the remote login shell, so each tmux arg must survive that re-parse.
|
|
12
|
-
* Local commands use pure argv (no shell) and need no quoting.
|
|
13
|
-
*/
|
|
14
|
-
export function sshQuote(arg) {
|
|
15
|
-
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
16
|
-
}
|
|
17
|
-
/** Local tmux management/attach argv — passed straight to spawn (shell:false). */
|
|
18
|
-
export function localTmux(sub) {
|
|
19
|
-
return ['tmux', ...sub];
|
|
20
|
-
}
|
|
21
|
-
function sshControlDir() {
|
|
22
|
-
// OpenSSH connection sharing avoids repeated TCP/auth handshakes for sidebar
|
|
23
|
-
// polling and file operations. Windows OpenSSH does not reliably support Unix
|
|
24
|
-
// control sockets, so leave that platform on plain ssh.
|
|
25
|
-
if (isWindows)
|
|
26
|
-
return null;
|
|
27
|
-
const uid = process.getuid?.() ?? 'user';
|
|
28
|
-
const dir = join(tmpdir(), `tmuxes-ssh-${uid}`);
|
|
29
|
-
try {
|
|
30
|
-
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
return dir;
|
|
36
|
-
}
|
|
37
|
-
export function sshControlPath(t) {
|
|
38
|
-
const dir = sshControlDir();
|
|
39
|
-
if (!dir)
|
|
40
|
-
return null;
|
|
41
|
-
const key = `${sshDestination(t)}:${t.port ?? 22}:${t.id}`;
|
|
42
|
-
return join(dir, createHash('sha1').update(key).digest('hex'));
|
|
43
|
-
}
|
|
44
|
-
function sshMultiplexArgs(t) {
|
|
45
|
-
const path = sshControlPath(t);
|
|
46
|
-
if (!path)
|
|
47
|
-
return [];
|
|
48
|
-
return [
|
|
49
|
-
'-o',
|
|
50
|
-
'ControlMaster=auto',
|
|
51
|
-
'-o',
|
|
52
|
-
`ControlPath=${path}`,
|
|
53
|
-
'-o',
|
|
54
|
-
`ControlPersist=${config.ssh.controlPersist}`,
|
|
55
|
-
];
|
|
56
|
-
}
|
|
57
|
-
export function sshClientArgs(t, opts) {
|
|
58
|
-
const portArgs = t.port ? ['-p', String(t.port)] : [];
|
|
59
|
-
return [
|
|
60
|
-
'ssh',
|
|
61
|
-
...(opts.tty ? ['-tt'] : []),
|
|
62
|
-
...(opts.batchMode ? ['-o', 'BatchMode=yes'] : []),
|
|
63
|
-
'-o',
|
|
64
|
-
`ConnectTimeout=${opts.connectTimeout}`,
|
|
65
|
-
...(opts.multiplex === false ? ['-o', 'ControlMaster=no'] : sshMultiplexArgs(t)),
|
|
66
|
-
...portArgs,
|
|
67
|
-
sshDestination(t),
|
|
68
|
-
];
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Remote tmux argv via the system ssh binary.
|
|
72
|
-
* - tty:false (management) → BatchMode + short ConnectTimeout so it fails fast
|
|
73
|
-
* and never hangs on a prompt. Remote args are sshQuote'd.
|
|
74
|
-
* - tty:true (interactive attach) → -tt forces a remote PTY (and SIGWINCH
|
|
75
|
-
* propagation). BatchMode is left default so host-key/agent prompts surface
|
|
76
|
-
* in the terminal. tmuxes does not force ServerAliveInterval; users can set
|
|
77
|
-
* keepalives in ~/.ssh/config if their site allows them. Remote args are NOT
|
|
78
|
-
* quoted here: this argv is handed to a PTY where the remote command words go
|
|
79
|
-
* to ssh as separate argv elements and our inputs are already allowlist-
|
|
80
|
-
* validated.
|
|
81
|
-
*/
|
|
82
|
-
export function remoteTmux(t, sub, opts) {
|
|
83
|
-
if (opts.tty) {
|
|
84
|
-
return [
|
|
85
|
-
...sshClientArgs(t, {
|
|
86
|
-
tty: true,
|
|
87
|
-
connectTimeout: config.ssh.connectTimeoutTty,
|
|
88
|
-
multiplex: opts.multiplex,
|
|
89
|
-
}),
|
|
90
|
-
'tmux',
|
|
91
|
-
...sub,
|
|
92
|
-
];
|
|
93
|
-
}
|
|
94
|
-
return [
|
|
95
|
-
...sshClientArgs(t, {
|
|
96
|
-
batchMode: true,
|
|
97
|
-
connectTimeout: config.ssh.connectTimeoutMgmt,
|
|
98
|
-
multiplex: opts.multiplex,
|
|
99
|
-
}),
|
|
100
|
-
'tmux',
|
|
101
|
-
...sub.map(sshQuote),
|
|
102
|
-
];
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* tmux inside a WSL distro (Windows host). We use `--exec` (NOT `--`): `--`
|
|
106
|
-
* runs the command through the distro's login shell, which would re-parse tmux
|
|
107
|
-
* format strings (`#{...}` is a comment, `|` a pipe) and mangle them; `--exec`
|
|
108
|
-
* execs the binary directly with no shell, so argv maps straight through with
|
|
109
|
-
* no quoting — like the local path. The interactive case sets TERM via `env`
|
|
110
|
-
* because WSL does not inherit the Windows TERM.
|
|
111
|
-
*/
|
|
112
|
-
export function wslTmux(distro, sub, opts) {
|
|
113
|
-
const prefix = opts.tty ? ['env', 'TERM=xterm-256color', 'tmux'] : ['tmux'];
|
|
114
|
-
return ['wsl.exe', '-d', distro, '--exec', ...prefix, ...sub];
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Build a non-PTY argv to run an ARBITRARY command on a target (tmux, ls, cat,
|
|
118
|
-
* display-message, …). Same transport rules as management tmux: local runs the
|
|
119
|
-
* argv directly, wsl uses `--exec` (no shell), ssh uses BatchMode + sshQuote.
|
|
120
|
-
*/
|
|
121
|
-
export function commandArgv(t, argv, opts = {}) {
|
|
122
|
-
let full;
|
|
123
|
-
if (t.kind === 'local') {
|
|
124
|
-
full = argv;
|
|
125
|
-
}
|
|
126
|
-
else if (t.kind === 'wsl') {
|
|
127
|
-
full = ['wsl.exe', '-d', t.distro ?? '', '--exec', ...argv];
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
full = [
|
|
131
|
-
...sshClientArgs(t, {
|
|
132
|
-
batchMode: true,
|
|
133
|
-
connectTimeout: config.ssh.connectTimeoutMgmt,
|
|
134
|
-
multiplex: opts.multiplex,
|
|
135
|
-
}),
|
|
136
|
-
...argv.map(sshQuote),
|
|
137
|
-
];
|
|
138
|
-
}
|
|
139
|
-
return { file: full[0], args: full.slice(1) };
|
|
140
|
-
}
|
|
141
|
-
/** Build a management argv (no PTY) for a local / ssh / wsl target. */
|
|
142
|
-
export function managementArgv(t, sub, opts = {}) {
|
|
143
|
-
return commandArgv(t, ['tmux', ...sub], opts);
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Build the create-a-new-session argv, always starting in the user's HOME:
|
|
147
|
-
* - local → tmux `-c <homedir>` (explicit, regardless of the server's cwd),
|
|
148
|
-
* - wsl → `wsl --cd ~` runs the command from the distro's home; tmux inherits,
|
|
149
|
-
* - ssh → the remote command already runs from the remote `$HOME`; tmux inherits.
|
|
150
|
-
* `sub` is the new-session subcommand (named or auto-named `-P` form).
|
|
151
|
-
*/
|
|
152
|
-
export function newSessionArgv(t, sub, opts = {}) {
|
|
153
|
-
if (t.kind === 'local') {
|
|
154
|
-
return { file: 'tmux', args: [...sub, '-c', homedir()] };
|
|
155
|
-
}
|
|
156
|
-
if (t.kind === 'wsl') {
|
|
157
|
-
return { file: 'wsl.exe', args: ['-d', t.distro ?? '', '--cd', '~', '--exec', 'tmux', ...sub] };
|
|
158
|
-
}
|
|
159
|
-
return commandArgv(t, ['tmux', ...sub], opts);
|
|
160
|
-
}
|
|
161
|
-
/** Build an interactive attach argv (run inside a PTY) for a local / ssh / wsl target. */
|
|
162
|
-
export function attachArgv(t, session) {
|
|
163
|
-
const sub = ['new-session', '-A', '-s', session]; // NO -d: the PTY supplies the terminal
|
|
164
|
-
let argv;
|
|
165
|
-
if (t.kind === 'local')
|
|
166
|
-
argv = localTmux(sub);
|
|
167
|
-
else if (t.kind === 'wsl')
|
|
168
|
-
argv = wslTmux(t.distro ?? '', sub, { tty: true });
|
|
169
|
-
else
|
|
170
|
-
argv = remoteTmux(t, sub, { tty: true });
|
|
171
|
-
return { file: argv[0], args: argv.slice(1) };
|
|
172
|
-
}
|
|
173
|
-
//# sourceMappingURL=builder.js.map
|
package/dist/tmux/builder.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/tmux/builder.ts"],"names":[],"mappings":"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"}
|
package/dist/tmux/formats.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/** tmux -F format strings + parsers.
|
|
2
|
-
*
|
|
3
|
-
* tmux ESCAPES control characters in -F output (e.g. 0x1f comes back as the
|
|
4
|
-
* literal text "\037"), so we cannot use a control byte as a separator. We use
|
|
5
|
-
* a printable "|" and place the only free-form field (the name) LAST, then
|
|
6
|
-
* rejoin the remainder — robust even if a name itself contains "|", because
|
|
7
|
-
* the leading numeric fields never do. */
|
|
8
|
-
import { AGENT_OPTION, parseAgentValue } from '../agentState.js';
|
|
9
|
-
const SEP = '|';
|
|
10
|
-
export const SESSION_FORMAT = [
|
|
11
|
-
'#{session_windows}',
|
|
12
|
-
'#{session_attached}',
|
|
13
|
-
'#{session_created}',
|
|
14
|
-
'#{session_activity}', // epoch from tmux; kept for display/debug
|
|
15
|
-
`#{${AGENT_OPTION}}`, // agent hook state: "<kind>:<state>:<reason>:<event>:<nonce>"
|
|
16
|
-
'#{session_name}', // free-form → must be last
|
|
17
|
-
].join(SEP);
|
|
18
|
-
export const WINDOW_FORMAT = [
|
|
19
|
-
'#{window_index}',
|
|
20
|
-
'#{window_panes}',
|
|
21
|
-
'#{window_active}',
|
|
22
|
-
'#{window_name}', // free-form → must be last
|
|
23
|
-
].join(SEP);
|
|
24
|
-
export function parseSessions(stdout) {
|
|
25
|
-
return stdout
|
|
26
|
-
.split('\n')
|
|
27
|
-
.filter((l) => l.length > 0)
|
|
28
|
-
.map((line) => {
|
|
29
|
-
const parts = line.split(SEP);
|
|
30
|
-
const agent = parseAgentValue(parts[4] || '');
|
|
31
|
-
return {
|
|
32
|
-
windows: Number(parts[0]) || 0,
|
|
33
|
-
attached: Number(parts[1]) > 0,
|
|
34
|
-
created: Number(parts[2]) || 0,
|
|
35
|
-
lastActivity: Number(parts[3]) || 0,
|
|
36
|
-
...agent,
|
|
37
|
-
name: parts.slice(5).join(SEP), // name may legitimately contain "|"
|
|
38
|
-
};
|
|
39
|
-
})
|
|
40
|
-
.filter((s) => s.name);
|
|
41
|
-
}
|
|
42
|
-
export function parseWindows(stdout) {
|
|
43
|
-
return stdout
|
|
44
|
-
.split('\n')
|
|
45
|
-
.filter((l) => l.length > 0)
|
|
46
|
-
.map((line) => {
|
|
47
|
-
const parts = line.split(SEP);
|
|
48
|
-
return {
|
|
49
|
-
index: Number(parts[0]) || 0,
|
|
50
|
-
panes: Number(parts[1]) || 0,
|
|
51
|
-
active: Number(parts[2]) > 0,
|
|
52
|
-
name: parts.slice(3).join(SEP),
|
|
53
|
-
};
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
/** stderr patterns that mean "no sessions" rather than a real error. */
|
|
57
|
-
const EMPTY_RE = /no server running|no sessions|error connecting to/i;
|
|
58
|
-
export function isEmptySessionsError(stderr) {
|
|
59
|
-
return EMPTY_RE.test(stderr);
|
|
60
|
-
}
|
|
61
|
-
//# sourceMappingURL=formats.js.map
|
package/dist/tmux/formats.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"formats.js","sourceRoot":"","sources":["../../src/tmux/formats.ts"],"names":[],"mappings":"AAAA;;;;;;2CAM2C;AAE3C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAyD,MAAM,kBAAkB,CAAC;AAExH,MAAM,GAAG,GAAG,GAAG,CAAC;AAEhB,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,oBAAoB;IACpB,qBAAqB;IACrB,oBAAoB;IACpB,qBAAqB,EAAE,0CAA0C;IACjE,KAAK,YAAY,GAAG,EAAE,8DAA8D;IACpF,iBAAiB,EAAE,2BAA2B;CAC/C,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,iBAAiB;IACjB,iBAAiB;IACjB,kBAAkB;IAClB,gBAAgB,EAAE,2BAA2B;CAC9C,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AA6BZ,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,MAAM;SACV,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;SAC3B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9C,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC9B,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAC9B,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC9B,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACnC,GAAG,KAAK;YACR,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,oCAAoC;SACrE,CAAC;IACJ,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,OAAO,MAAM;SACV,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;SAC3B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC5B,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC5B,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAC5B,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;SAC/B,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC;AAED,wEAAwE;AACxE,MAAM,QAAQ,GAAG,oDAAoD,CAAC;AAEtE,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|