247-cli 0.3.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.md +112 -0
- package/agent/dist/config.d.ts +29 -0
- package/agent/dist/config.d.ts.map +1 -0
- package/agent/dist/config.js +56 -0
- package/agent/dist/config.js.map +1 -0
- package/agent/dist/db/environments.d.ts +60 -0
- package/agent/dist/db/environments.d.ts.map +1 -0
- package/agent/dist/db/environments.js +235 -0
- package/agent/dist/db/environments.js.map +1 -0
- package/agent/dist/db/history.d.ts +37 -0
- package/agent/dist/db/history.d.ts.map +1 -0
- package/agent/dist/db/history.js +98 -0
- package/agent/dist/db/history.js.map +1 -0
- package/agent/dist/db/index.d.ts +37 -0
- package/agent/dist/db/index.d.ts.map +1 -0
- package/agent/dist/db/index.js +225 -0
- package/agent/dist/db/index.js.map +1 -0
- package/agent/dist/db/schema.d.ts +70 -0
- package/agent/dist/db/schema.d.ts.map +1 -0
- package/agent/dist/db/schema.js +79 -0
- package/agent/dist/db/schema.js.map +1 -0
- package/agent/dist/db/sessions.d.ts +75 -0
- package/agent/dist/db/sessions.d.ts.map +1 -0
- package/agent/dist/db/sessions.js +244 -0
- package/agent/dist/db/sessions.js.map +1 -0
- package/agent/dist/editor.d.ts +18 -0
- package/agent/dist/editor.d.ts.map +1 -0
- package/agent/dist/editor.js +222 -0
- package/agent/dist/editor.js.map +1 -0
- package/agent/dist/environments.d.ts +59 -0
- package/agent/dist/environments.d.ts.map +1 -0
- package/agent/dist/environments.js +229 -0
- package/agent/dist/environments.js.map +1 -0
- package/agent/dist/git.d.ts +39 -0
- package/agent/dist/git.d.ts.map +1 -0
- package/agent/dist/git.js +436 -0
- package/agent/dist/git.js.map +1 -0
- package/agent/dist/index.d.ts +2 -0
- package/agent/dist/index.d.ts.map +1 -0
- package/agent/dist/index.js +18 -0
- package/agent/dist/index.js.map +1 -0
- package/agent/dist/logger.d.ts +15 -0
- package/agent/dist/logger.d.ts.map +1 -0
- package/agent/dist/logger.js +44 -0
- package/agent/dist/logger.js.map +1 -0
- package/agent/dist/routes/editor.d.ts +9 -0
- package/agent/dist/routes/editor.d.ts.map +1 -0
- package/agent/dist/routes/editor.js +63 -0
- package/agent/dist/routes/editor.js.map +1 -0
- package/agent/dist/routes/environments.d.ts +6 -0
- package/agent/dist/routes/environments.d.ts.map +1 -0
- package/agent/dist/routes/environments.js +94 -0
- package/agent/dist/routes/environments.js.map +1 -0
- package/agent/dist/routes/files.d.ts +6 -0
- package/agent/dist/routes/files.d.ts.map +1 -0
- package/agent/dist/routes/files.js +84 -0
- package/agent/dist/routes/files.js.map +1 -0
- package/agent/dist/routes/hooks.d.ts +6 -0
- package/agent/dist/routes/hooks.d.ts.map +1 -0
- package/agent/dist/routes/hooks.js +80 -0
- package/agent/dist/routes/hooks.js.map +1 -0
- package/agent/dist/routes/index.d.ts +10 -0
- package/agent/dist/routes/index.d.ts.map +1 -0
- package/agent/dist/routes/index.js +10 -0
- package/agent/dist/routes/index.js.map +1 -0
- package/agent/dist/routes/projects.d.ts +6 -0
- package/agent/dist/routes/projects.d.ts.map +1 -0
- package/agent/dist/routes/projects.js +69 -0
- package/agent/dist/routes/projects.js.map +1 -0
- package/agent/dist/routes/sessions.d.ts +6 -0
- package/agent/dist/routes/sessions.d.ts.map +1 -0
- package/agent/dist/routes/sessions.js +194 -0
- package/agent/dist/routes/sessions.js.map +1 -0
- package/agent/dist/server.d.ts +6 -0
- package/agent/dist/server.d.ts.map +1 -0
- package/agent/dist/server.js +129 -0
- package/agent/dist/server.js.map +1 -0
- package/agent/dist/status.d.ts +42 -0
- package/agent/dist/status.d.ts.map +1 -0
- package/agent/dist/status.js +134 -0
- package/agent/dist/status.js.map +1 -0
- package/agent/dist/terminal.d.ts +15 -0
- package/agent/dist/terminal.d.ts.map +1 -0
- package/agent/dist/terminal.js +135 -0
- package/agent/dist/terminal.js.map +1 -0
- package/agent/dist/websocket-handlers.d.ts +13 -0
- package/agent/dist/websocket-handlers.d.ts.map +1 -0
- package/agent/dist/websocket-handlers.js +266 -0
- package/agent/dist/websocket-handlers.js.map +1 -0
- package/agent/node_modules/247-shared/dist/index.d.ts +2 -0
- package/agent/node_modules/247-shared/dist/index.d.ts.map +1 -0
- package/agent/node_modules/247-shared/dist/index.js +2 -0
- package/agent/node_modules/247-shared/dist/index.js.map +1 -0
- package/agent/node_modules/247-shared/dist/types/index.d.ts +215 -0
- package/agent/node_modules/247-shared/dist/types/index.d.ts.map +1 -0
- package/agent/node_modules/247-shared/dist/types/index.js +48 -0
- package/agent/node_modules/247-shared/dist/types/index.js.map +1 -0
- package/agent/node_modules/247-shared/package.json +29 -0
- package/dist/commands/doctor.d.ts +3 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +279 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/hooks.d.ts +3 -0
- package/dist/commands/hooks.d.ts.map +1 -0
- package/dist/commands/hooks.js +127 -0
- package/dist/commands/hooks.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +130 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/logs.d.ts +3 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +38 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/profile.d.ts +3 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +156 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/commands/service.d.ts +3 -0
- package/dist/commands/service.d.ts.map +1 -0
- package/dist/commands/service.js +235 -0
- package/dist/commands/service.js.map +1 -0
- package/dist/commands/start.d.ts +3 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +120 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +62 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/stop.d.ts +3 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +23 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/commands/update.d.ts +3 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +121 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/hooks/installer.d.ts +36 -0
- package/dist/hooks/installer.d.ts.map +1 -0
- package/dist/hooks/installer.js +175 -0
- package/dist/hooks/installer.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +71 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +161 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/paths.d.ts +34 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +76 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/prerequisites.d.ts +36 -0
- package/dist/lib/prerequisites.d.ts.map +1 -0
- package/dist/lib/prerequisites.js +181 -0
- package/dist/lib/prerequisites.js.map +1 -0
- package/dist/lib/process.d.ts +40 -0
- package/dist/lib/process.d.ts.map +1 -0
- package/dist/lib/process.js +192 -0
- package/dist/lib/process.js.map +1 -0
- package/dist/service/index.d.ts +44 -0
- package/dist/service/index.d.ts.map +1 -0
- package/dist/service/index.js +18 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/launchd.d.ts +18 -0
- package/dist/service/launchd.d.ts.map +1 -0
- package/dist/service/launchd.js +208 -0
- package/dist/service/launchd.js.map +1 -0
- package/dist/service/systemd.d.ts +18 -0
- package/dist/service/systemd.d.ts.map +1 -0
- package/dist/service/systemd.js +196 -0
- package/dist/service/systemd.js.map +1 -0
- package/hooks/.claude-plugin/plugin.json +5 -0
- package/hooks/hooks/hooks.json +66 -0
- package/hooks/scripts/check-duplication.sh +91 -0
- package/hooks/scripts/notify-status.sh +89 -0
- package/package.json +77 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main server entry point - Express HTTP server with WebSocket support.
|
|
3
|
+
* Routes and handlers are split into separate modules for maintainability.
|
|
4
|
+
*/
|
|
5
|
+
export declare function createServer(): Promise<import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>>;
|
|
6
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA+BH,wBAAsB,YAAY,gHAgIjC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main server entry point - Express HTTP server with WebSocket support.
|
|
3
|
+
* Routes and handlers are split into separate modules for maintainability.
|
|
4
|
+
*/
|
|
5
|
+
import express from 'express';
|
|
6
|
+
import cors from 'cors';
|
|
7
|
+
import { WebSocketServer } from 'ws';
|
|
8
|
+
import { createServer as createHttpServer } from 'http';
|
|
9
|
+
import httpProxy from 'http-proxy';
|
|
10
|
+
import { initEditor, shutdownAllEditors } from './editor.js';
|
|
11
|
+
import { initDatabase, closeDatabase, migrateEnvironmentsFromJson } from './db/index.js';
|
|
12
|
+
import { ensureDefaultEnvironment } from './db/environments.js';
|
|
13
|
+
import * as sessionsDb from './db/sessions.js';
|
|
14
|
+
import { config } from './config.js';
|
|
15
|
+
// Routes
|
|
16
|
+
import { createProjectRoutes, createEnvironmentRoutes, createSessionRoutes, createHooksRoutes, createEditorRoutes, createFilesRoutes, isProjectAllowed, updateEditorActivity, getOrStartEditor, } from './routes/index.js';
|
|
17
|
+
// Status and WebSocket
|
|
18
|
+
import { tmuxSessionStatus, cleanupStatusMaps, getActiveTmuxSessions } from './status.js';
|
|
19
|
+
import { handleTerminalConnection, handleStatusConnection } from './websocket-handlers.js';
|
|
20
|
+
export async function createServer() {
|
|
21
|
+
const app = express();
|
|
22
|
+
app.use(cors());
|
|
23
|
+
app.use(express.json());
|
|
24
|
+
const server = createHttpServer(app);
|
|
25
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
26
|
+
// Initialize editor manager
|
|
27
|
+
const typedConfig = config;
|
|
28
|
+
await initEditor(typedConfig.editor, config.projects.basePath);
|
|
29
|
+
// Initialize SQLite database
|
|
30
|
+
const db = initDatabase();
|
|
31
|
+
migrateEnvironmentsFromJson(db);
|
|
32
|
+
ensureDefaultEnvironment();
|
|
33
|
+
// Reconcile sessions with active tmux sessions
|
|
34
|
+
const activeTmuxSessions = getActiveTmuxSessions();
|
|
35
|
+
sessionsDb.reconcileWithTmux(activeTmuxSessions);
|
|
36
|
+
// Populate in-memory Map from database
|
|
37
|
+
const dbSessions = sessionsDb.getAllSessions();
|
|
38
|
+
for (const session of dbSessions) {
|
|
39
|
+
tmuxSessionStatus.set(session.name, sessionsDb.toHookStatus(session));
|
|
40
|
+
}
|
|
41
|
+
console.log(`[DB] Loaded ${dbSessions.length} sessions from database`);
|
|
42
|
+
// Create proxy for code-server
|
|
43
|
+
const editorProxy = httpProxy.createProxyServer({ ws: true, changeOrigin: true });
|
|
44
|
+
editorProxy.on('error', (err, _req, res) => {
|
|
45
|
+
console.error('[Editor Proxy] HTTP Error:', err.message);
|
|
46
|
+
if (res && 'writeHead' in res) {
|
|
47
|
+
res.writeHead(502, { 'Content-Type': 'application/json' });
|
|
48
|
+
res.end(JSON.stringify({ error: 'Editor proxy error', message: err.message }));
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
// Mount API routes
|
|
52
|
+
app.use('/api', createProjectRoutes());
|
|
53
|
+
app.use('/api/environments', createEnvironmentRoutes());
|
|
54
|
+
app.use('/api/sessions', createSessionRoutes());
|
|
55
|
+
app.use('/api/hooks', createHooksRoutes());
|
|
56
|
+
app.use('/api/editor', createEditorRoutes());
|
|
57
|
+
app.use('/api/files', createFilesRoutes());
|
|
58
|
+
// Editor proxy middleware
|
|
59
|
+
app.use('/editor/:project', async (req, res) => {
|
|
60
|
+
const { project } = req.params;
|
|
61
|
+
if (!isProjectAllowed(project)) {
|
|
62
|
+
return res.status(403).json({ error: 'Project not allowed' });
|
|
63
|
+
}
|
|
64
|
+
if (!typedConfig.editor?.enabled) {
|
|
65
|
+
return res.status(400).json({ error: 'Editor is disabled in config' });
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
const editor = await getOrStartEditor(project);
|
|
69
|
+
updateEditorActivity(project);
|
|
70
|
+
req.url = req.url.replace(`/editor/${project}`, '') || '/';
|
|
71
|
+
editorProxy.web(req, res, { target: `http://127.0.0.1:${editor.port}` });
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
console.error('[Editor Proxy] Failed:', err);
|
|
75
|
+
res.status(502).json({ error: 'Failed to proxy to editor' });
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
// Handle WebSocket upgrades
|
|
79
|
+
server.on('upgrade', async (req, socket, head) => {
|
|
80
|
+
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
81
|
+
if (url.pathname === '/terminal') {
|
|
82
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
83
|
+
handleTerminalConnection(ws, url);
|
|
84
|
+
});
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (url.pathname === '/status') {
|
|
88
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
89
|
+
handleStatusConnection(ws);
|
|
90
|
+
});
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (url.pathname.startsWith('/editor/')) {
|
|
94
|
+
const pathParts = url.pathname.split('/');
|
|
95
|
+
const project = pathParts[2];
|
|
96
|
+
if (!project || !isProjectAllowed(project) || !typedConfig.editor?.enabled) {
|
|
97
|
+
socket.destroy();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
const editor = await getOrStartEditor(project);
|
|
102
|
+
updateEditorActivity(project);
|
|
103
|
+
const rewrittenPath = url.pathname.replace(`/editor/${project}`, '') || '/';
|
|
104
|
+
req.url = rewrittenPath + url.search;
|
|
105
|
+
editorProxy.ws(req, socket, head, { target: `http://127.0.0.1:${editor.port}` });
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
console.error('[Editor WS] Failed:', err);
|
|
109
|
+
socket.destroy();
|
|
110
|
+
}
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
socket.destroy();
|
|
114
|
+
});
|
|
115
|
+
// Periodic cleanup
|
|
116
|
+
setInterval(cleanupStatusMaps, 60 * 60 * 1000);
|
|
117
|
+
// Graceful shutdown
|
|
118
|
+
const shutdown = () => {
|
|
119
|
+
console.log('[Server] Shutting down...');
|
|
120
|
+
shutdownAllEditors();
|
|
121
|
+
closeDatabase();
|
|
122
|
+
server.close();
|
|
123
|
+
process.exit(0);
|
|
124
|
+
};
|
|
125
|
+
process.on('SIGTERM', shutdown);
|
|
126
|
+
process.on('SIGINT', shutdown);
|
|
127
|
+
return server;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session status management and WebSocket broadcast utilities.
|
|
3
|
+
* Handles real-time status updates between Claude Code hooks and the dashboard.
|
|
4
|
+
*/
|
|
5
|
+
import { WebSocket } from 'ws';
|
|
6
|
+
import type { SessionStatus, AttentionReason, WSSessionInfo } from '247-shared';
|
|
7
|
+
export interface HookStatus {
|
|
8
|
+
status: SessionStatus;
|
|
9
|
+
attentionReason?: AttentionReason;
|
|
10
|
+
lastEvent: string;
|
|
11
|
+
lastActivity: number;
|
|
12
|
+
lastStatusChange: number;
|
|
13
|
+
project?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const tmuxSessionStatus: Map<string, HookStatus>;
|
|
16
|
+
export declare const activeConnections: Map<string, Set<WebSocket>>;
|
|
17
|
+
export declare const statusSubscribers: Set<WebSocket>;
|
|
18
|
+
/**
|
|
19
|
+
* Broadcast status update to all subscribers
|
|
20
|
+
*/
|
|
21
|
+
export declare function broadcastStatusUpdate(session: WSSessionInfo): void;
|
|
22
|
+
/**
|
|
23
|
+
* Broadcast session removed to all subscribers
|
|
24
|
+
*/
|
|
25
|
+
export declare function broadcastSessionRemoved(sessionName: string): void;
|
|
26
|
+
/**
|
|
27
|
+
* Broadcast session archived to all subscribers
|
|
28
|
+
*/
|
|
29
|
+
export declare function broadcastSessionArchived(sessionName: string, session: WSSessionInfo): void;
|
|
30
|
+
/**
|
|
31
|
+
* Generate human-readable session names with project prefix
|
|
32
|
+
*/
|
|
33
|
+
export declare function generateSessionName(project: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Clean up stale status entries (called periodically)
|
|
36
|
+
*/
|
|
37
|
+
export declare function cleanupStatusMaps(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Get active tmux sessions from the system
|
|
40
|
+
*/
|
|
41
|
+
export declare function getActiveTmuxSessions(): Set<string>;
|
|
42
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAE/B,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,aAAa,EAEd,MAAM,YAAY,CAAC;AAMpB,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,aAAa,CAAC;IACtB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAGD,eAAO,MAAM,iBAAiB,yBAAgC,CAAC;AAG/D,eAAO,MAAM,iBAAiB,6BAAoC,CAAC;AAGnE,eAAO,MAAM,iBAAiB,gBAAuB,CAAC;AAEtD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAclE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAYjE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CAY1F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAkB3D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CA0CxC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,GAAG,CAAC,MAAM,CAAC,CASnD"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session status management and WebSocket broadcast utilities.
|
|
3
|
+
* Handles real-time status updates between Claude Code hooks and the dashboard.
|
|
4
|
+
*/
|
|
5
|
+
import { WebSocket } from 'ws';
|
|
6
|
+
import { execSync } from 'child_process';
|
|
7
|
+
import { RETENTION_CONFIG } from './db/index.js';
|
|
8
|
+
import * as sessionsDb from './db/sessions.js';
|
|
9
|
+
import * as historyDb from './db/history.js';
|
|
10
|
+
// Store by tmux session name - single source of truth for status
|
|
11
|
+
export const tmuxSessionStatus = new Map();
|
|
12
|
+
// Track active WebSocket connections per session
|
|
13
|
+
export const activeConnections = new Map();
|
|
14
|
+
// Track WebSocket subscribers for status updates (real-time push)
|
|
15
|
+
export const statusSubscribers = new Set();
|
|
16
|
+
/**
|
|
17
|
+
* Broadcast status update to all subscribers
|
|
18
|
+
*/
|
|
19
|
+
export function broadcastStatusUpdate(session) {
|
|
20
|
+
if (statusSubscribers.size === 0)
|
|
21
|
+
return;
|
|
22
|
+
const message = { type: 'status-update', session };
|
|
23
|
+
const messageStr = JSON.stringify(message);
|
|
24
|
+
for (const ws of statusSubscribers) {
|
|
25
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
26
|
+
ws.send(messageStr);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
console.log(`[Status WS] Broadcast status update for ${session.name}: ${session.status} to ${statusSubscribers.size} subscribers`);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Broadcast session removed to all subscribers
|
|
33
|
+
*/
|
|
34
|
+
export function broadcastSessionRemoved(sessionName) {
|
|
35
|
+
if (statusSubscribers.size === 0)
|
|
36
|
+
return;
|
|
37
|
+
const message = { type: 'session-removed', sessionName };
|
|
38
|
+
const messageStr = JSON.stringify(message);
|
|
39
|
+
for (const ws of statusSubscribers) {
|
|
40
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
41
|
+
ws.send(messageStr);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
console.log(`[Status WS] Broadcast session removed: ${sessionName}`);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Broadcast session archived to all subscribers
|
|
48
|
+
*/
|
|
49
|
+
export function broadcastSessionArchived(sessionName, session) {
|
|
50
|
+
if (statusSubscribers.size === 0)
|
|
51
|
+
return;
|
|
52
|
+
const message = { type: 'session-archived', sessionName, session };
|
|
53
|
+
const messageStr = JSON.stringify(message);
|
|
54
|
+
for (const ws of statusSubscribers) {
|
|
55
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
56
|
+
ws.send(messageStr);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
console.log(`[Status WS] Broadcast session archived: ${sessionName}`);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Generate human-readable session names with project prefix
|
|
63
|
+
*/
|
|
64
|
+
export function generateSessionName(project) {
|
|
65
|
+
const adjectives = [
|
|
66
|
+
'brave',
|
|
67
|
+
'swift',
|
|
68
|
+
'calm',
|
|
69
|
+
'bold',
|
|
70
|
+
'wise',
|
|
71
|
+
'keen',
|
|
72
|
+
'fair',
|
|
73
|
+
'wild',
|
|
74
|
+
'bright',
|
|
75
|
+
'cool',
|
|
76
|
+
];
|
|
77
|
+
const nouns = ['lion', 'hawk', 'wolf', 'bear', 'fox', 'owl', 'deer', 'lynx', 'eagle', 'tiger'];
|
|
78
|
+
const adj = adjectives[Math.floor(Math.random() * adjectives.length)];
|
|
79
|
+
const noun = nouns[Math.floor(Math.random() * nouns.length)];
|
|
80
|
+
const num = Math.floor(Math.random() * 100);
|
|
81
|
+
return `${project}--${adj}-${noun}-${num}`;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Clean up stale status entries (called periodically)
|
|
85
|
+
*/
|
|
86
|
+
export function cleanupStatusMaps() {
|
|
87
|
+
const now = Date.now();
|
|
88
|
+
const STALE_THRESHOLD = RETENTION_CONFIG.sessionMaxAge;
|
|
89
|
+
let cleanedTmux = 0;
|
|
90
|
+
// Get active tmux sessions
|
|
91
|
+
let activeSessions = new Set();
|
|
92
|
+
try {
|
|
93
|
+
const output = execSync('tmux list-sessions -F "#{session_name}" 2>/dev/null', {
|
|
94
|
+
encoding: 'utf-8',
|
|
95
|
+
});
|
|
96
|
+
activeSessions = new Set(output.trim().split('\n').filter(Boolean));
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// No tmux sessions exist
|
|
100
|
+
}
|
|
101
|
+
// Clean tmuxSessionStatus - remove if session doesn't exist OR is stale
|
|
102
|
+
for (const [sessionName, status] of tmuxSessionStatus) {
|
|
103
|
+
const sessionExists = activeSessions.has(sessionName);
|
|
104
|
+
const isStale = now - status.lastActivity > STALE_THRESHOLD;
|
|
105
|
+
if (!sessionExists || isStale) {
|
|
106
|
+
tmuxSessionStatus.delete(sessionName);
|
|
107
|
+
cleanedTmux++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (cleanedTmux > 0) {
|
|
111
|
+
console.log(`[Status Cleanup] Removed ${cleanedTmux} stale status entries from memory`);
|
|
112
|
+
}
|
|
113
|
+
// Also cleanup SQLite database
|
|
114
|
+
const dbSessionsCleaned = sessionsDb.cleanupStaleSessions(STALE_THRESHOLD, RETENTION_CONFIG.archivedMaxAge);
|
|
115
|
+
const dbHistoryCleaned = historyDb.cleanupOldHistory(RETENTION_CONFIG.historyMaxAge);
|
|
116
|
+
if (dbSessionsCleaned > 0 || dbHistoryCleaned > 0) {
|
|
117
|
+
console.log(`[DB Cleanup] Sessions: ${dbSessionsCleaned}, History: ${dbHistoryCleaned}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get active tmux sessions from the system
|
|
122
|
+
*/
|
|
123
|
+
export function getActiveTmuxSessions() {
|
|
124
|
+
try {
|
|
125
|
+
const output = execSync('tmux list-sessions -F "#{session_name}" 2>/dev/null', {
|
|
126
|
+
encoding: 'utf-8',
|
|
127
|
+
});
|
|
128
|
+
return new Set(output.trim().split('\n').filter(Boolean));
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return new Set();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface Terminal {
|
|
2
|
+
write(data: string): void;
|
|
3
|
+
resize(cols: number, rows: number): void;
|
|
4
|
+
onData(callback: (data: string) => void): void;
|
|
5
|
+
onExit(callback: (info: {
|
|
6
|
+
exitCode: number;
|
|
7
|
+
}) => void): void;
|
|
8
|
+
kill(): void;
|
|
9
|
+
detach(): void;
|
|
10
|
+
captureHistory(lines?: number): Promise<string>;
|
|
11
|
+
isExistingSession(): boolean;
|
|
12
|
+
onReady(callback: () => void): void;
|
|
13
|
+
}
|
|
14
|
+
export declare function createTerminal(cwd: string, sessionName: string, customEnvVars?: Record<string, string>): Terminal;
|
|
15
|
+
//# sourceMappingURL=terminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC/C,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IAC7D,IAAI,IAAI,IAAI,CAAC;IACb,MAAM,IAAI,IAAI,CAAC;IACf,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,iBAAiB,IAAI,OAAO,CAAC;IAC7B,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CACrC;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,aAAa,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACzC,QAAQ,CAsJV"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import * as pty from '@homebridge/node-pty-prebuilt-multiarch';
|
|
2
|
+
import { exec, execSync } from 'child_process';
|
|
3
|
+
import { promisify } from 'util';
|
|
4
|
+
const execAsync = promisify(exec);
|
|
5
|
+
export function createTerminal(cwd, sessionName, customEnvVars = {}) {
|
|
6
|
+
// Check if session already exists before spawning
|
|
7
|
+
let existingSession = false;
|
|
8
|
+
try {
|
|
9
|
+
execSync(`tmux has-session -t "${sessionName}" 2>/dev/null`);
|
|
10
|
+
existingSession = true;
|
|
11
|
+
console.log(`[Terminal] Session '${sessionName}' exists, will attach`);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
existingSession = false;
|
|
15
|
+
console.log(`[Terminal] Session '${sessionName}' does not exist, will create`);
|
|
16
|
+
}
|
|
17
|
+
if (Object.keys(customEnvVars).length > 0) {
|
|
18
|
+
console.log(`[Terminal] Custom env vars for injection: ${Object.keys(customEnvVars).join(', ')}`);
|
|
19
|
+
}
|
|
20
|
+
// Use tmux for session persistence
|
|
21
|
+
// For existing sessions: use attach-session (more reliable)
|
|
22
|
+
// For new sessions: use new-session with -A flag
|
|
23
|
+
// Note: We DON'T use -e flags here because they pollute tmux's global environment
|
|
24
|
+
const tmuxArgs = existingSession
|
|
25
|
+
? ['attach-session', '-t', sessionName]
|
|
26
|
+
: ['new-session', '-A', '-s', sessionName, '-c', cwd];
|
|
27
|
+
console.log(`[Terminal] Spawning: tmux ${tmuxArgs.join(' ')}`);
|
|
28
|
+
const shell = pty.spawn('tmux', tmuxArgs, {
|
|
29
|
+
name: 'xterm-256color',
|
|
30
|
+
cols: 120,
|
|
31
|
+
rows: 30,
|
|
32
|
+
cwd,
|
|
33
|
+
env: {
|
|
34
|
+
...process.env,
|
|
35
|
+
// Note: customEnvVars are NOT included here to avoid polluting the pty environment
|
|
36
|
+
// They will be injected per-session using tmux send-keys
|
|
37
|
+
TERM: 'xterm-256color',
|
|
38
|
+
CLAUDE_TMUX_SESSION: sessionName, // Always set for hook detection
|
|
39
|
+
PATH: `/opt/homebrew/bin:${process.env.PATH}`,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
// Debug: log any immediate output or errors
|
|
43
|
+
let initialOutput = '';
|
|
44
|
+
const debugHandler = (data) => {
|
|
45
|
+
initialOutput += data;
|
|
46
|
+
if (initialOutput.length < 500) {
|
|
47
|
+
console.log(`[Terminal] Initial output: ${data.substring(0, 100)}`);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
shell.onData(debugHandler);
|
|
51
|
+
// Remove debug handler after 2 seconds to prevent memory leak
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
shell.removeListener('data', debugHandler);
|
|
54
|
+
}, 2000);
|
|
55
|
+
// Debug: log when shell exits
|
|
56
|
+
shell.onExit(({ exitCode, signal }) => {
|
|
57
|
+
console.log(`[Terminal] Shell exited: code=${exitCode}, signal=${signal}, session='${sessionName}'`);
|
|
58
|
+
});
|
|
59
|
+
// Track terminal readiness state for onReady callback
|
|
60
|
+
let isReady = existingSession; // Existing sessions are ready immediately
|
|
61
|
+
const readyCallbacks = [];
|
|
62
|
+
const fireReadyCallbacks = () => {
|
|
63
|
+
isReady = true;
|
|
64
|
+
readyCallbacks.forEach((cb) => cb());
|
|
65
|
+
readyCallbacks.length = 0; // Clear the array
|
|
66
|
+
};
|
|
67
|
+
// Configure tmux options and inject environment variables
|
|
68
|
+
if (!existingSession) {
|
|
69
|
+
setTimeout(() => {
|
|
70
|
+
exec(`tmux set-option -t "${sessionName}" history-limit 10000`);
|
|
71
|
+
exec(`tmux set-option -t "${sessionName}" mouse on`);
|
|
72
|
+
// ALWAYS inject CLAUDE_TMUX_SESSION into the shell for hook detection
|
|
73
|
+
// This is critical for hooks to identify which session they belong to
|
|
74
|
+
const baseExport = `export CLAUDE_TMUX_SESSION="${sessionName}"`;
|
|
75
|
+
// Add custom environment variables if present (filter out empty values)
|
|
76
|
+
const nonEmptyVars = Object.entries(customEnvVars).filter(([, value]) => value && value.trim() !== '');
|
|
77
|
+
const allExports = nonEmptyVars.length > 0
|
|
78
|
+
? `${baseExport}; ${nonEmptyVars
|
|
79
|
+
.map(([key, value]) => `export ${key}="${value.replace(/"/g, '\\"')}"`)
|
|
80
|
+
.join('; ')}`
|
|
81
|
+
: baseExport;
|
|
82
|
+
console.log(`[Terminal] Injecting CLAUDE_TMUX_SESSION and ${nonEmptyVars.length} custom vars into NEW session '${sessionName}'`);
|
|
83
|
+
// Séquences ANSI pour effacer les lignes après exécution
|
|
84
|
+
// \033[1A = remonter d'une ligne, \033[2K = effacer la ligne
|
|
85
|
+
// On efface 2 lignes: la commande tapée + le prompt précédent
|
|
86
|
+
const clearSequence = `printf '\\033[1A\\033[2K\\033[1A\\033[2K'`;
|
|
87
|
+
exec(`tmux send-keys -t "${sessionName}" "${allExports}; ${clearSequence}" C-m`, () => {
|
|
88
|
+
// Fire ready callbacks after init commands are sent
|
|
89
|
+
fireReadyCallbacks();
|
|
90
|
+
});
|
|
91
|
+
}, 100);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// For existing sessions, just ensure mouse is enabled
|
|
95
|
+
// Environment variables were already injected when the session was created
|
|
96
|
+
// isReady is already true for existing sessions (set above)
|
|
97
|
+
setTimeout(() => {
|
|
98
|
+
exec(`tmux set-option -t "${sessionName}" mouse on`);
|
|
99
|
+
}, 100);
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
write: (data) => shell.write(data),
|
|
103
|
+
resize: (cols, rows) => shell.resize(cols, rows),
|
|
104
|
+
onData: (callback) => shell.onData(callback),
|
|
105
|
+
onExit: (callback) => shell.onExit(callback),
|
|
106
|
+
kill: () => shell.kill(),
|
|
107
|
+
detach: () => {
|
|
108
|
+
// Send tmux detach command (Ctrl+B, d)
|
|
109
|
+
shell.write('\x02d');
|
|
110
|
+
},
|
|
111
|
+
isExistingSession: () => existingSession,
|
|
112
|
+
onReady: (callback) => {
|
|
113
|
+
if (isReady) {
|
|
114
|
+
callback();
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
readyCallbacks.push(callback);
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
captureHistory: async (lines = 10000) => {
|
|
121
|
+
try {
|
|
122
|
+
// Capture scrollback buffer from tmux
|
|
123
|
+
// -p = print to stdout
|
|
124
|
+
// -S -N = start from N lines back (negative = from start of history)
|
|
125
|
+
// -J = preserve trailing spaces for proper formatting
|
|
126
|
+
const { stdout } = await execAsync(`tmux capture-pane -t "${sessionName}" -p -S -${lines} -J 2>/dev/null`);
|
|
127
|
+
return stdout;
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return '';
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket handlers for terminal connections and status subscriptions.
|
|
3
|
+
*/
|
|
4
|
+
import { WebSocket } from 'ws';
|
|
5
|
+
/**
|
|
6
|
+
* Handle terminal WebSocket connections
|
|
7
|
+
*/
|
|
8
|
+
export declare function handleTerminalConnection(ws: WebSocket, url: URL): void;
|
|
9
|
+
/**
|
|
10
|
+
* Handle status WebSocket connections (real-time session updates)
|
|
11
|
+
*/
|
|
12
|
+
export declare function handleStatusConnection(ws: WebSocket): void;
|
|
13
|
+
//# sourceMappingURL=websocket-handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket-handlers.d.ts","sourceRoot":"","sources":["../src/websocket-handlers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AA0B/B;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CA2JtE;AAsDD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI,CAwE1D"}
|