triflux 6.0.6 → 6.0.8
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/hub/team/headless.mjs +85 -19
- package/package.json +1 -1
package/hub/team/headless.mjs
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// v6.0.0: Lead-direct 모드 (runHeadlessInteractive, autoAttachTerminal)
|
|
5
5
|
// 의존성: psmux.mjs (Node.js 내장 모듈만 사용)
|
|
6
6
|
import { join } from "node:path";
|
|
7
|
-
import { readFileSync, existsSync, mkdirSync } from "node:fs";
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
import { execSync, execFileSync } from "node:child_process";
|
|
10
10
|
import {
|
|
@@ -20,6 +20,15 @@ import {
|
|
|
20
20
|
|
|
21
21
|
const RESULT_DIR = join(tmpdir(), "tfx-headless");
|
|
22
22
|
|
|
23
|
+
/** CLI별 브랜드 — 이모지 + ANSI 색상 (시각적 구분) */
|
|
24
|
+
const CLI_BRAND = {
|
|
25
|
+
codex: { emoji: "\u{1F7E2}", label: "Codex", ansi: "\x1b[32m" }, // 🟢 green
|
|
26
|
+
gemini: { emoji: "\u{1F535}", label: "Gemini", ansi: "\x1b[34m" }, // 🔵 blue
|
|
27
|
+
claude: { emoji: "\u{1F7E0}", label: "Claude", ansi: "\x1b[33m" }, // 🟠 yellow/orange
|
|
28
|
+
};
|
|
29
|
+
const ANSI_RESET = "\x1b[0m";
|
|
30
|
+
const ANSI_DIM = "\x1b[2m";
|
|
31
|
+
|
|
23
32
|
/**
|
|
24
33
|
* CLI별 헤드리스 명령 빌더
|
|
25
34
|
* @param {'codex'|'gemini'|'claude'} cli
|
|
@@ -96,25 +105,34 @@ export async function runHeadless(sessionName, assignments, opts = {}) {
|
|
|
96
105
|
|
|
97
106
|
dispatches = assignments.map((assignment, i) => {
|
|
98
107
|
const paneName = `worker-${i + 1}`;
|
|
108
|
+
const brand = CLI_BRAND[assignment.cli] || { emoji: "\u{25CF}", label: assignment.cli, ansi: "" };
|
|
99
109
|
const paneTitle = assignment.role
|
|
100
|
-
? `${assignment.cli} (${assignment.role})`
|
|
101
|
-
: `${assignment.cli}-${i + 1}`;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
? `${brand.emoji} ${assignment.cli} (${assignment.role})`
|
|
111
|
+
: `${brand.emoji} ${assignment.cli}-${i + 1}`;
|
|
112
|
+
|
|
113
|
+
let newPaneId;
|
|
114
|
+
if (i === 0) {
|
|
115
|
+
// 첫 번째 워커: 빈 lead pane을 직접 사용 (빈 pane 제거)
|
|
116
|
+
newPaneId = `${sessionName}:0.0`;
|
|
117
|
+
} else {
|
|
118
|
+
// 2번째+: split-window로 추가
|
|
119
|
+
newPaneId = psmuxExec([
|
|
120
|
+
"split-window", "-t", sessionName, "-P", "-F",
|
|
121
|
+
"#{session_name}:#{window_index}.#{pane_index}",
|
|
122
|
+
]);
|
|
123
|
+
}
|
|
108
124
|
|
|
109
|
-
// 타이틀 설정
|
|
125
|
+
// 타이틀 설정 (이모지 포함)
|
|
110
126
|
try { psmuxExec(["select-pane", "-t", newPaneId, "-T", paneTitle]); } catch { /* 무시 */ }
|
|
111
127
|
|
|
112
128
|
if (safeProgress) safeProgress({ type: "worker_added", paneName, cli: assignment.cli, paneTitle });
|
|
113
129
|
|
|
114
|
-
// 캡처 시작 +
|
|
130
|
+
// 캡처 시작 + 컬러 배너 + 명령 dispatch
|
|
115
131
|
const resultFile = join(RESULT_DIR, `${sessionName}-${paneName}.txt`).replace(/\\/g, "/");
|
|
116
132
|
const cmd = buildHeadlessCommand(assignment.cli, assignment.prompt, resultFile);
|
|
117
133
|
startCapture(sessionName, newPaneId);
|
|
134
|
+
// pane 간 pipe-pane EBUSY 방지 — capture 스크립트 파일 잠금 해제 대기
|
|
135
|
+
if (i > 0) { try { Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 300); } catch {} }
|
|
118
136
|
const dispatch = dispatchCommand(sessionName, newPaneId, cmd);
|
|
119
137
|
|
|
120
138
|
if (safeProgress) safeProgress({ type: "dispatched", paneName, cli: assignment.cli });
|
|
@@ -257,6 +275,54 @@ export function applyTrifluxTheme(sessionName) {
|
|
|
257
275
|
}
|
|
258
276
|
}
|
|
259
277
|
|
|
278
|
+
/**
|
|
279
|
+
* Windows Terminal에 triflux 프로필을 자동 생성/갱신한다.
|
|
280
|
+
* 반투명 + 비포커스 시 더 투명 + Catppuccin 테마.
|
|
281
|
+
* @returns {boolean} 성공 여부
|
|
282
|
+
*/
|
|
283
|
+
export function ensureWtProfile() {
|
|
284
|
+
const settingsPaths = [
|
|
285
|
+
join(process.env.LOCALAPPDATA || "", "Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState/settings.json"),
|
|
286
|
+
join(process.env.LOCALAPPDATA || "", "Microsoft/Windows Terminal/settings.json"),
|
|
287
|
+
];
|
|
288
|
+
|
|
289
|
+
for (const settingsPath of settingsPaths) {
|
|
290
|
+
if (!existsSync(settingsPath)) continue;
|
|
291
|
+
try {
|
|
292
|
+
const raw = readFileSync(settingsPath, "utf8");
|
|
293
|
+
// JSON with comments — 간단한 strip (// 주석만)
|
|
294
|
+
const cleaned = raw.replace(/^\s*\/\/.*$/gm, "");
|
|
295
|
+
const settings = JSON.parse(cleaned);
|
|
296
|
+
if (!settings.profiles?.list) continue;
|
|
297
|
+
|
|
298
|
+
const existing = settings.profiles.list.findIndex(p => p.name === "triflux");
|
|
299
|
+
const profile = {
|
|
300
|
+
name: "triflux",
|
|
301
|
+
commandline: "psmux",
|
|
302
|
+
icon: "\u{1F53A}", // 🔺
|
|
303
|
+
tabTitle: "triflux",
|
|
304
|
+
suppressApplicationTitle: true,
|
|
305
|
+
opacity: 85,
|
|
306
|
+
useAcrylic: true,
|
|
307
|
+
unfocusedAppearance: { opacity: 50 },
|
|
308
|
+
colorScheme: "One Half Dark",
|
|
309
|
+
font: { size: 11 },
|
|
310
|
+
hidden: true, // 프로필 목록에는 숨김 (triflux에서만 사용)
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
if (existing >= 0) {
|
|
314
|
+
settings.profiles.list[existing] = { ...settings.profiles.list[existing], ...profile };
|
|
315
|
+
} else {
|
|
316
|
+
settings.profiles.list.push(profile);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2), "utf8");
|
|
320
|
+
return true;
|
|
321
|
+
} catch { /* 파싱 실패 — 다음 경로 */ }
|
|
322
|
+
}
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
|
|
260
326
|
// ─── v6.0.0: Lead-Direct Interactive Mode ───
|
|
261
327
|
|
|
262
328
|
/**
|
|
@@ -276,17 +342,17 @@ export function autoAttachTerminal(sessionName, opts = {}) {
|
|
|
276
342
|
return false; // wt.exe 미설치 — 사용자에게 수동 attach 안내 필요
|
|
277
343
|
}
|
|
278
344
|
|
|
279
|
-
//
|
|
280
|
-
|
|
281
|
-
|
|
345
|
+
// triflux WT 프로필 확보 (투명도 + 테마)
|
|
346
|
+
ensureWtProfile();
|
|
347
|
+
|
|
348
|
+
// PowerShell 래핑 + "--" 구분자 + 포커스 비탈취
|
|
282
349
|
const shells = ["pwsh.exe", "powershell.exe"];
|
|
283
350
|
for (const shell of shells) {
|
|
284
351
|
try {
|
|
285
|
-
|
|
286
|
-
"
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
], { stdio: "ignore" });
|
|
352
|
+
execSync(
|
|
353
|
+
`start "" /b wt.exe nt --profile triflux --title triflux -- ${shell} -NoExit -Command "psmux attach -t ${sessionName}"`,
|
|
354
|
+
{ stdio: "ignore", shell: true, timeout: 5000 },
|
|
355
|
+
);
|
|
290
356
|
return true;
|
|
291
357
|
} catch { /* 다음 shell 시도 */ }
|
|
292
358
|
}
|