@dmsdc-ai/aigentry-telepty 0.1.68 → 0.1.70

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.
@@ -0,0 +1,137 @@
1
+ 'use strict';
2
+
3
+ const { execSync } = require('child_process');
4
+
5
+ // Detect terminal environment at daemon level
6
+ function detectTerminal() {
7
+ // 1. cmux: check env var or cmux ping
8
+ if (process.env.CMUX_WORKSPACE_ID) {
9
+ try {
10
+ execSync('cmux ping', { timeout: 2000, stdio: ['pipe', 'pipe', 'pipe'] });
11
+ return 'cmux';
12
+ } catch {}
13
+ }
14
+
15
+ // 2. kitty: check for socket
16
+ try {
17
+ const files = require('fs').readdirSync('/tmp').filter(f => f.startsWith('kitty-sock'));
18
+ if (files.length > 0) return 'kitty';
19
+ } catch {}
20
+
21
+ // 3. headless fallback
22
+ return 'headless';
23
+ }
24
+
25
+ // Cache: sessionId -> surfaceRef
26
+ const surfaceCache = new Map();
27
+ let lastCacheRefresh = 0;
28
+ const CACHE_TTL = 30000; // 30 seconds
29
+
30
+ // Build session -> cmux surface mapping from tab titles
31
+ function refreshSurfaceCache() {
32
+ const now = Date.now();
33
+ if (now - lastCacheRefresh < CACHE_TTL && surfaceCache.size > 0) return;
34
+
35
+ try {
36
+ // Find number of workspaces from list-windows
37
+ const windowsOutput = execSync('cmux list-windows', { timeout: 5000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
38
+ const workspacesMatch = windowsOutput.match(/workspaces=(\d+)/);
39
+ const workspaceCount = workspacesMatch ? parseInt(workspacesMatch[1]) : 10;
40
+
41
+ surfaceCache.clear();
42
+ for (let i = 1; i <= workspaceCount; i++) {
43
+ try {
44
+ const output = execSync(`cmux list-pane-surfaces --workspace workspace:${i}`, {
45
+ timeout: 3000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe']
46
+ });
47
+ // Parse: "* surface:1 ⚡ telepty :: aigentry-orchestrator-claude [selected]"
48
+ const lines = output.split('\n').filter(l => l.trim());
49
+ for (const line of lines) {
50
+ const surfaceMatch = line.match(/surface:(\d+)/);
51
+ const sessionMatch = line.match(/telepty\s*::\s*(\S+)/);
52
+ if (surfaceMatch && sessionMatch) {
53
+ surfaceCache.set(sessionMatch[1], `surface:${surfaceMatch[1]}`);
54
+ }
55
+ }
56
+ } catch {}
57
+ }
58
+ lastCacheRefresh = now;
59
+ console.log(`[BACKEND] Refreshed cmux surface cache: ${surfaceCache.size} sessions mapped`);
60
+ } catch (err) {
61
+ console.error(`[BACKEND] Failed to refresh surface cache:`, err.message);
62
+ }
63
+ }
64
+
65
+ // Find cmux surface ref for a session
66
+ function findSurface(sessionId) {
67
+ refreshSurfaceCache();
68
+
69
+ // Direct match
70
+ if (surfaceCache.has(sessionId)) return surfaceCache.get(sessionId);
71
+
72
+ // Prefix match (e.g., "aigentry-orchestrator" matches "aigentry-orchestrator-claude")
73
+ for (const [id, ref] of surfaceCache.entries()) {
74
+ if (id.startsWith(sessionId) || sessionId.startsWith(id)) return ref;
75
+ }
76
+
77
+ return null;
78
+ }
79
+
80
+ // Send text to a cmux surface
81
+ function cmuxSendText(sessionId, text) {
82
+ const surface = findSurface(sessionId);
83
+ if (!surface) return false;
84
+
85
+ try {
86
+ // Escape single quotes for shell
87
+ const escaped = text.replace(/'/g, "'\\''");
88
+ execSync(`cmux send --surface ${surface} '${escaped}'`, {
89
+ timeout: 5000, stdio: ['pipe', 'pipe', 'pipe']
90
+ });
91
+ console.log(`[BACKEND] cmux send text to ${sessionId} (${surface})`);
92
+ return true;
93
+ } catch (err) {
94
+ console.error(`[BACKEND] cmux send failed for ${sessionId}:`, err.message);
95
+ // Invalidate cache entry
96
+ surfaceCache.delete(sessionId);
97
+ return false;
98
+ }
99
+ }
100
+
101
+ // Send enter key to a cmux surface
102
+ function cmuxSendEnter(sessionId) {
103
+ const surface = findSurface(sessionId);
104
+ if (!surface) return false;
105
+
106
+ try {
107
+ execSync(`cmux send-key --surface ${surface} return`, {
108
+ timeout: 5000, stdio: ['pipe', 'pipe', 'pipe']
109
+ });
110
+ console.log(`[BACKEND] cmux send-key return to ${sessionId} (${surface})`);
111
+ return true;
112
+ } catch (err) {
113
+ console.error(`[BACKEND] cmux send-key failed for ${sessionId}:`, err.message);
114
+ surfaceCache.delete(sessionId);
115
+ return false;
116
+ }
117
+ }
118
+
119
+ // Invalidate cache for a session (e.g., when surface changes)
120
+ function invalidateCache(sessionId) {
121
+ surfaceCache.delete(sessionId);
122
+ }
123
+
124
+ function clearCache() {
125
+ surfaceCache.clear();
126
+ lastCacheRefresh = 0;
127
+ }
128
+
129
+ module.exports = {
130
+ detectTerminal,
131
+ findSurface,
132
+ cmuxSendText,
133
+ cmuxSendEnter,
134
+ refreshSurfaceCache,
135
+ invalidateCache,
136
+ clearCache
137
+ };