@volter/supercode-teams 0.2.74 → 0.2.76
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/popup-terminals.mjs +36 -5
- package/terminal-look.mjs +11 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-teams",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.76",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A machine daemon serving this machine's doors, and a local or remote Teams server for shared session discovery, OpenTelemetry ingestion and access to enrolled machines.",
|
|
6
6
|
"license": "MIT",
|
package/popup-terminals.mjs
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
// daemon's ConPTY host on Windows, holds it); the pane ending ends the client, and the terminal closes the window as
|
|
5
5
|
// its command exits. Adapters are tried in rank order; SUPERCODE_POPUP_TERMINAL names one (or `none`).
|
|
6
6
|
import { spawn, spawnSync } from 'node:child_process';
|
|
7
|
-
import { chmodSync, existsSync, writeFileSync } from 'node:fs';
|
|
8
|
-
import { tmpdir } from 'node:os';
|
|
7
|
+
import { chmodSync, existsSync, readdirSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import { homedir, tmpdir } from 'node:os';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
10
|
import { randomBytes } from 'node:crypto';
|
|
11
11
|
import { weztermConfigFile } from './terminal-look.mjs';
|
|
@@ -27,11 +27,42 @@ function selfDeletingScript(argv, extension) {
|
|
|
27
27
|
return path;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
// Supercode's windows share one WezTerm process, as Terminal.app's windows share one app: a window opened into a
|
|
31
|
+
// running process is on screen in about 0.3 s, where a process started per window took 0.7 to 2 s (measured on macOS
|
|
32
|
+
// 26 with WezTerm 20240203). The process is known by its class; it listens on ~/.local/share/wezterm/gui-sock-<pid>.
|
|
33
|
+
// A window goes into it with `wezterm cli spawn --new-window`, and when there is none, or the spawn fails, the window
|
|
34
|
+
// starts it. The fallback runs in the launched shell, so the daemon never waits on WezTerm.
|
|
35
|
+
const WEZTERM_CLASS = 'dev.volter.supercode';
|
|
36
|
+
|
|
37
|
+
/** The socket of a running supercode WezTerm process, or null. */
|
|
38
|
+
function weztermSocket() {
|
|
39
|
+
const dir = join(homedir(), '.local', 'share', 'wezterm');
|
|
40
|
+
let names;
|
|
41
|
+
try { names = readdirSync(dir); } catch { return null; }
|
|
42
|
+
for (const name of names) {
|
|
43
|
+
const pid = Number(/^gui-sock-(\d+)$/.exec(name)?.[1]);
|
|
44
|
+
if (!pid) continue;
|
|
45
|
+
try { process.kill(pid, 0); } catch { continue; }
|
|
46
|
+
const command = spawnSync('ps', ['-p', String(pid), '-o', 'command='], { encoding: 'utf8', timeout: 2_000 }).stdout ?? '';
|
|
47
|
+
if (command.includes(`--class ${WEZTERM_CLASS}`)) return join(dir, name);
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** WezTerm's launch: a window in supercode's running WezTerm, else a new one with supercode's look (terminal-look.mjs). */
|
|
53
|
+
function weztermLaunch(program, argv) {
|
|
54
|
+
const start = [program, '--config-file', weztermConfigFile(), 'start', '--always-new-process', '--class', WEZTERM_CLASS, '--', ...argv];
|
|
55
|
+
const socket = process.platform === 'win32' ? null : weztermSocket();
|
|
56
|
+
if (!socket) return [start[0], start.slice(1)];
|
|
57
|
+
const quote = (arg) => `'${String(arg).replaceAll("'", `'"'"'`)}'`;
|
|
58
|
+
const spawnWindow = [program, 'cli', '--no-auto-start', 'spawn', '--new-window', '--', ...argv].map(quote).join(' ');
|
|
59
|
+
return ['/bin/sh', ['-c', `WEZTERM_UNIX_SOCKET=${quote(socket)} ${spawnWindow} >/dev/null 2>&1 || exec ${start.map(quote).join(' ')}`]];
|
|
60
|
+
}
|
|
61
|
+
|
|
30
62
|
/** Adapters by platform, in rank order: { name, find() → program or null, launch(program, argv) → [command, args] }. */
|
|
31
63
|
const ADAPTERS = {
|
|
32
64
|
darwin: [
|
|
33
|
-
|
|
34
|
-
{ name: 'wezterm', find: () => onPath('wezterm') ?? firstPath('/Applications/WezTerm.app/Contents/MacOS/wezterm'), launch: (p, argv) => [p, ['--config-file', weztermConfigFile(), 'start', '--always-new-process', '--', ...argv]] },
|
|
65
|
+
{ name: 'wezterm', find: () => onPath('wezterm') ?? firstPath('/Applications/WezTerm.app/Contents/MacOS/wezterm'), launch: weztermLaunch },
|
|
35
66
|
{ name: 'kitty', find: () => onPath('kitty') ?? firstPath('/Applications/kitty.app/Contents/MacOS/kitty'), launch: (p, argv) => [p, argv] },
|
|
36
67
|
{ name: 'ghostty', find: () => firstPath('/Applications/Ghostty.app'), launch: (p, argv) => ['open', ['-na', p, '--args', '-e', ...argv]] },
|
|
37
68
|
{ name: 'alacritty', find: () => onPath('alacritty') ?? firstPath('/Applications/Alacritty.app/Contents/MacOS/alacritty'), launch: (p, argv) => [p, ['-e', ...argv]] },
|
|
@@ -49,7 +80,7 @@ const ADAPTERS = {
|
|
|
49
80
|
{ name: 'conhost', find: () => firstPath(join(process.env.SystemRoot ?? 'C:\\Windows', 'System32', 'conhost.exe')), launch: (p, argv) => [p, argv] },
|
|
50
81
|
],
|
|
51
82
|
linux: [
|
|
52
|
-
{ name: 'wezterm', find: () => onPath('wezterm'), launch:
|
|
83
|
+
{ name: 'wezterm', find: () => onPath('wezterm'), launch: weztermLaunch },
|
|
53
84
|
{ name: 'kitty', find: () => onPath('kitty'), launch: (p, argv) => [p, argv] },
|
|
54
85
|
{ name: 'ghostty', find: () => onPath('ghostty'), launch: (p, argv) => [p, ['-e', ...argv]] },
|
|
55
86
|
{ name: 'alacritty', find: () => onPath('alacritty'), launch: (p, argv) => [p, ['-e', ...argv]] },
|
package/terminal-look.mjs
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// Basic profile (terminal-basic.mjs, the brand's terminal roles), light or dark with the system's appearance as Basic is.
|
|
6
6
|
// The config is WezTerm's own file, passed with `--config-file`; the person's ~/.wezterm.lua is not read for it.
|
|
7
7
|
import { execFileSync } from 'node:child_process';
|
|
8
|
-
import { existsSync, renameSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import { existsSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
9
9
|
import { tmpdir } from 'node:os';
|
|
10
10
|
import { join } from 'node:path';
|
|
11
11
|
import { TERMINAL_BASIC } from './terminal-basic.mjs';
|
|
@@ -125,17 +125,25 @@ export function weztermConfig(profile, { fontDirs = existsSync(TERMINAL_FONTS) ?
|
|
|
125
125
|
'config.enable_scroll_bar = false',
|
|
126
126
|
// Terminal.app does not ask before closing a window whose process is tmux (its default "ask before closing" list).
|
|
127
127
|
"config.window_close_confirmation = 'NeverPrompt'",
|
|
128
|
+
// A config reload re-arms WezTerm's file watcher while it holds the lock every key and mouse event takes, and
|
|
129
|
+
// arming the watcher waits on fseventsd: open windows stopped taking input for up to 2.3 s after each popup's
|
|
130
|
+
// launch (sampled on macOS 26). The file is written for each launch, so the next process takes any change.
|
|
131
|
+
'config.automatically_reload_config = false',
|
|
128
132
|
'return config',
|
|
129
133
|
'',
|
|
130
134
|
];
|
|
131
135
|
return lines.join('\n');
|
|
132
136
|
}
|
|
133
137
|
|
|
134
|
-
/** Writes the config for this machine and returns its path. */
|
|
138
|
+
/** Writes the config for this machine, when it differs from the one on disk, and returns its path. */
|
|
135
139
|
export function weztermConfigFile(platform = process.platform) {
|
|
136
140
|
const path = join(tmpdir(), `supercode-wezterm-${process.getuid?.() ?? 'user'}.lua`);
|
|
141
|
+
const config = weztermConfig(terminalAppProfile(platform));
|
|
142
|
+
let current = null;
|
|
143
|
+
try { current = readFileSync(path, 'utf8'); } catch { /* not written yet */ }
|
|
144
|
+
if (current === config) return path;
|
|
137
145
|
const next = `${path}.${process.pid}`;
|
|
138
|
-
writeFileSync(next,
|
|
146
|
+
writeFileSync(next, config);
|
|
139
147
|
renameSync(next, path);
|
|
140
148
|
return path;
|
|
141
149
|
}
|