triflux 9.8.0 → 9.8.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/bin/triflux.mjs +10 -1
- package/hub/team/psmux.mjs +6 -1
- package/package.json +1 -1
- package/scripts/headless-guard.mjs +4 -1
- package/scripts/setup.mjs +16 -1
package/bin/triflux.mjs
CHANGED
|
@@ -2363,13 +2363,22 @@ async function cmdDoctor(options = {}) {
|
|
|
2363
2363
|
e.hooks.some((h) => typeof h?.command === "string" && h.command.includes("hook-orchestrator")),
|
|
2364
2364
|
);
|
|
2365
2365
|
if (!hasOrch) continue;
|
|
2366
|
-
// orchestrator
|
|
2366
|
+
// 패턴 A: orchestrator 없는 별도 엔트리 제거
|
|
2367
2367
|
const before = entries.length;
|
|
2368
2368
|
fixedSettings.hooks[event] = entries.filter((e) =>
|
|
2369
2369
|
Array.isArray(e?.hooks) &&
|
|
2370
2370
|
e.hooks.some((h) => typeof h?.command === "string" && h.command.includes("hook-orchestrator")),
|
|
2371
2371
|
);
|
|
2372
2372
|
removed += before - fixedSettings.hooks[event].length;
|
|
2373
|
+
// 패턴 B: orchestrator 엔트리 내부의 개별 훅 제거
|
|
2374
|
+
for (const entry of fixedSettings.hooks[event]) {
|
|
2375
|
+
if (!Array.isArray(entry.hooks) || entry.hooks.length <= 1) continue;
|
|
2376
|
+
const beforeInner = entry.hooks.length;
|
|
2377
|
+
entry.hooks = entry.hooks.filter(
|
|
2378
|
+
(h) => typeof h?.command === "string" && h.command.includes("hook-orchestrator"),
|
|
2379
|
+
);
|
|
2380
|
+
removed += beforeInner - entry.hooks.length;
|
|
2381
|
+
}
|
|
2373
2382
|
}
|
|
2374
2383
|
if (removed > 0) {
|
|
2375
2384
|
writeFileSync(settingsPath, JSON.stringify(fixedSettings, null, 2) + "\n", "utf8");
|
package/hub/team/psmux.mjs
CHANGED
|
@@ -195,6 +195,9 @@ function ensureCaptureHelper() {
|
|
|
195
195
|
" New-Item -ItemType Directory -Force -Path $parent | Out-Null",
|
|
196
196
|
"}",
|
|
197
197
|
"",
|
|
198
|
+
"# Force UTF-8 encoding — CP949 등 non-UTF-8 codepage에서 Gemini stdout 캡처 실패 방지",
|
|
199
|
+
"[Console]::InputEncoding = [System.Text.Encoding]::UTF8",
|
|
200
|
+
"",
|
|
198
201
|
"$reader = [Console]::In",
|
|
199
202
|
"while (($line = $reader.ReadLine()) -ne $null) {",
|
|
200
203
|
" Add-Content -LiteralPath $Path -Value $line -Encoding utf8",
|
|
@@ -877,7 +880,9 @@ export function dispatchCommand(sessionName, paneNameOrTarget, commandText) {
|
|
|
877
880
|
|
|
878
881
|
const token = randomToken(paneName);
|
|
879
882
|
const safeCommand = wrapCliForBash(commandText);
|
|
880
|
-
|
|
883
|
+
// CP949 등 non-UTF-8 codepage 환경에서 CLI stdout이 깨지는 문제 방지 (belt-and-suspenders)
|
|
884
|
+
const chcpPrefix = process.platform === "win32" ? "chcp 65001 > $null; " : "";
|
|
885
|
+
const wrapped = `${chcpPrefix}try { ${safeCommand} } finally { $trifluxExit = if ($null -ne $LASTEXITCODE) { [int]$LASTEXITCODE } else { 0 }; Write-Output "${COMPLETION_PREFIX}${token}:$trifluxExit" }`;
|
|
881
886
|
|
|
882
887
|
sendLiteralToPane(pane.paneId, wrapped, true);
|
|
883
888
|
|
package/package.json
CHANGED
|
@@ -189,8 +189,11 @@ async function main() {
|
|
|
189
189
|
process.exit(0);
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
// codex/gemini 직접 CLI 호출 → deny
|
|
192
|
+
// codex/gemini 직접 CLI 호출 → deny (인라인 TFX_ALLOW_DIRECT_CLI=1 우회 허용)
|
|
193
193
|
if (/\bcodex\b.*\bexec\b/.test(cmd) || /\bgemini\s+(-p|--prompt)\b/.test(cmd)) {
|
|
194
|
+
if (/\bTFX_ALLOW_DIRECT_CLI=1\b/.test(cmd)) {
|
|
195
|
+
nudge("[headless-guard] direct CLI mode (inline TFX_ALLOW_DIRECT_CLI=1)");
|
|
196
|
+
}
|
|
194
197
|
deny(
|
|
195
198
|
"[headless-guard] codex/gemini 직접 호출은 spawn-session에서 차단됩니다. " +
|
|
196
199
|
`승인된 경로: ${HEADLESS_FALLBACK_COMMAND}. ` +
|
package/scripts/setup.mjs
CHANGED
|
@@ -630,7 +630,10 @@ function ensureHooksInSettings({
|
|
|
630
630
|
}
|
|
631
631
|
if (!settings.hooks || typeof settings.hooks !== "object") settings.hooks = {};
|
|
632
632
|
|
|
633
|
-
// ── 이중 실행 정리: orchestrator가 있는 이벤트에서 개별 훅
|
|
633
|
+
// ── 이중 실행 정리: orchestrator가 있는 이벤트에서 개별 훅 제거 ──
|
|
634
|
+
// 두 가지 패턴 모두 처리:
|
|
635
|
+
// A) orchestrator 엔트리와 별도 개별 훅 엔트리가 공존 → 개별 엔트리 제거
|
|
636
|
+
// B) orchestrator와 개별 훅이 같은 엔트리의 hooks[] 안에 공존 → 개별 훅 제거
|
|
634
637
|
let dedupRemoved = 0;
|
|
635
638
|
for (const [event, entries] of Object.entries(settings.hooks)) {
|
|
636
639
|
if (!Array.isArray(entries)) continue;
|
|
@@ -639,12 +642,24 @@ function ensureHooksInSettings({
|
|
|
639
642
|
e.hooks.some((h) => typeof h?.command === "string" && h.command.includes("hook-orchestrator")),
|
|
640
643
|
);
|
|
641
644
|
if (!hasOrch) continue;
|
|
645
|
+
|
|
646
|
+
// 패턴 A: orchestrator 없는 별도 엔트리 제거
|
|
642
647
|
const before = entries.length;
|
|
643
648
|
settings.hooks[event] = entries.filter((e) =>
|
|
644
649
|
Array.isArray(e?.hooks) &&
|
|
645
650
|
e.hooks.some((h) => typeof h?.command === "string" && h.command.includes("hook-orchestrator")),
|
|
646
651
|
);
|
|
647
652
|
dedupRemoved += before - settings.hooks[event].length;
|
|
653
|
+
|
|
654
|
+
// 패턴 B: orchestrator가 있는 엔트리 내부에서 개별 훅 제거
|
|
655
|
+
for (const entry of settings.hooks[event]) {
|
|
656
|
+
if (!Array.isArray(entry.hooks) || entry.hooks.length <= 1) continue;
|
|
657
|
+
const beforeInner = entry.hooks.length;
|
|
658
|
+
entry.hooks = entry.hooks.filter(
|
|
659
|
+
(h) => typeof h?.command === "string" && h.command.includes("hook-orchestrator"),
|
|
660
|
+
);
|
|
661
|
+
dedupRemoved += beforeInner - entry.hooks.length;
|
|
662
|
+
}
|
|
648
663
|
}
|
|
649
664
|
|
|
650
665
|
const added = [];
|