codedash-app 3.0.1 → 3.0.2
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/package.json +1 -1
- package/src/frontend/app.js +6 -13
- package/src/server.js +14 -1
- package/src/terminals.js +50 -1
package/package.json
CHANGED
package/src/frontend/app.js
CHANGED
|
@@ -1626,22 +1626,15 @@ function focusSession(sessionId) {
|
|
|
1626
1626
|
var a = activeSessions[sessionId];
|
|
1627
1627
|
if (!a) { showToast('Session not active'); return; }
|
|
1628
1628
|
|
|
1629
|
-
|
|
1630
|
-
var terminal = localStorage.getItem('codedash-terminal') || '';
|
|
1631
|
-
fetch('/api/launch', {
|
|
1629
|
+
fetch('/api/focus', {
|
|
1632
1630
|
method: 'POST',
|
|
1633
1631
|
headers: { 'Content-Type': 'application/json' },
|
|
1634
|
-
body: JSON.stringify({
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
project: a.cwd || '',
|
|
1639
|
-
terminal: terminal,
|
|
1640
|
-
})
|
|
1641
|
-
}).then(function() {
|
|
1642
|
-
showToast('Focused terminal');
|
|
1632
|
+
body: JSON.stringify({ pid: a.pid })
|
|
1633
|
+
}).then(function(r) { return r.json(); }).then(function(data) {
|
|
1634
|
+
if (data.ok) showToast('Switched to terminal (PID ' + a.pid + ')');
|
|
1635
|
+
else showToast('Could not focus — try clicking the terminal manually');
|
|
1643
1636
|
}).catch(function() {
|
|
1644
|
-
showToast('
|
|
1637
|
+
showToast('Focus failed');
|
|
1645
1638
|
});
|
|
1646
1639
|
}
|
|
1647
1640
|
|
package/src/server.js
CHANGED
|
@@ -4,7 +4,7 @@ const https = require('https');
|
|
|
4
4
|
const { URL } = require('url');
|
|
5
5
|
const { exec } = require('child_process');
|
|
6
6
|
const { loadSessions, loadSessionDetail, deleteSession, getGitCommits, exportSessionMarkdown, getSessionPreview, searchFullText, getActiveSessions, getSessionReplay, getCostAnalytics } = require('./data');
|
|
7
|
-
const { detectTerminals, openInTerminal } = require('./terminals');
|
|
7
|
+
const { detectTerminals, openInTerminal, focusTerminalByPid } = require('./terminals');
|
|
8
8
|
const { getHTML } = require('./html');
|
|
9
9
|
|
|
10
10
|
function startServer(port, openBrowser = true) {
|
|
@@ -110,6 +110,19 @@ function startServer(port, openBrowser = true) {
|
|
|
110
110
|
json(res, active);
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
// ── Focus terminal ──────────────────────
|
|
114
|
+
else if (req.method === 'POST' && pathname === '/api/focus') {
|
|
115
|
+
readBody(req, body => {
|
|
116
|
+
try {
|
|
117
|
+
const { pid } = JSON.parse(body);
|
|
118
|
+
const ok = focusTerminalByPid(pid);
|
|
119
|
+
json(res, { ok });
|
|
120
|
+
} catch (e) {
|
|
121
|
+
json(res, { ok: false, error: e.message }, 400);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
113
126
|
// ── Session preview ─────────────────────
|
|
114
127
|
else if (req.method === 'GET' && pathname.startsWith('/api/preview/')) {
|
|
115
128
|
const sessionId = pathname.split('/').pop();
|
package/src/terminals.js
CHANGED
|
@@ -157,4 +157,53 @@ function openInTerminal(sessionId, tool, flags, projectDir, terminalId) {
|
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
// ── Focus existing terminal by PID ──────────────────────────
|
|
161
|
+
|
|
162
|
+
function focusTerminalByPid(pid) {
|
|
163
|
+
const platform = process.platform;
|
|
164
|
+
|
|
165
|
+
if (platform === 'darwin') {
|
|
166
|
+
// Find which terminal app owns this PID's TTY, then activate it
|
|
167
|
+
try {
|
|
168
|
+
// Get TTY of the process
|
|
169
|
+
const ttyOut = execSync(`ps -p ${pid} -o tty= 2>/dev/null`, { encoding: 'utf8' }).trim();
|
|
170
|
+
if (!ttyOut) throw new Error('no tty');
|
|
171
|
+
|
|
172
|
+
// Try iTerm2 first — activate and select session by tty
|
|
173
|
+
try {
|
|
174
|
+
const script = `
|
|
175
|
+
tell application "iTerm"
|
|
176
|
+
activate
|
|
177
|
+
repeat with w in windows
|
|
178
|
+
repeat with t in tabs of w
|
|
179
|
+
repeat with s in sessions of t
|
|
180
|
+
if tty of s contains "${ttyOut}" then
|
|
181
|
+
select t
|
|
182
|
+
return
|
|
183
|
+
end if
|
|
184
|
+
end repeat
|
|
185
|
+
end repeat
|
|
186
|
+
end repeat
|
|
187
|
+
end tell
|
|
188
|
+
`;
|
|
189
|
+
execSync(`osascript -e '${script.replace(/'/g, "'\\''")}'`, { stdio: 'pipe', timeout: 3000 });
|
|
190
|
+
return true;
|
|
191
|
+
} catch {}
|
|
192
|
+
|
|
193
|
+
// Fallback: just activate iTerm2 or Terminal.app
|
|
194
|
+
try {
|
|
195
|
+
execSync(`osascript -e 'tell application "iTerm" to activate'`, { stdio: 'pipe' });
|
|
196
|
+
return true;
|
|
197
|
+
} catch {}
|
|
198
|
+
try {
|
|
199
|
+
execSync(`osascript -e 'tell application "Terminal" to activate'`, { stdio: 'pipe' });
|
|
200
|
+
return true;
|
|
201
|
+
} catch {}
|
|
202
|
+
} catch {}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Linux/other: not much we can do without window manager integration
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
module.exports = { detectTerminals, openInTerminal, focusTerminalByPid };
|