- src/services/tmux.js: parse tmux panes (claude/node->codex engine match), collect running agents, launch agent in new or existing session via new-window/new-session + send-keys (window survives agent exit) - routes: GET/POST /api/tmux/agents, GET /api/auth/check (for nginx auth_request), liveAgents in /api/dashboard aggregate - tests for the pure parser Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
47 lines
1.3 KiB
JavaScript
47 lines
1.3 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { parseTmuxPanes } from '../src/services/tmux.js';
|
|
|
|
test('parseTmuxPanes maps claude and node panes to engines', () => {
|
|
const output = [
|
|
'main\t0\tclaude:kanban\t%3\tclaude\t/home/gahow/projects/kanban',
|
|
'main\t1\tcodex:vllm\t%5\tnode\t/home/gahow/projects/vllm',
|
|
'main\t2\tshell\t%7\tbash\t/home/gahow'
|
|
].join('\n');
|
|
assert.deepEqual(parseTmuxPanes(output), [
|
|
{
|
|
engine: 'claude',
|
|
session: 'main',
|
|
windowIndex: 0,
|
|
windowName: 'claude:kanban',
|
|
paneId: '%3',
|
|
cwd: '/home/gahow/projects/kanban'
|
|
},
|
|
{
|
|
engine: 'codex',
|
|
session: 'main',
|
|
windowIndex: 1,
|
|
windowName: 'codex:vllm',
|
|
paneId: '%5',
|
|
cwd: '/home/gahow/projects/vllm'
|
|
}
|
|
]);
|
|
});
|
|
|
|
test('parseTmuxPanes drops unrelated commands', () => {
|
|
const output = [
|
|
'dev\t0\teditor\t%1\tvim\t/home/gahow',
|
|
'dev\t1\tmonitor\t%2\thtop\t/home/gahow'
|
|
].join('\n');
|
|
assert.deepEqual(parseTmuxPanes(output), []);
|
|
});
|
|
|
|
test('parseTmuxPanes handles empty output', () => {
|
|
assert.deepEqual(parseTmuxPanes(''), []);
|
|
assert.deepEqual(parseTmuxPanes(null), []);
|
|
});
|
|
|
|
test('parseTmuxPanes ignores malformed lines', () => {
|
|
assert.deepEqual(parseTmuxPanes('garbage-without-tabs\n\n'), []);
|
|
});
|