triflux 10.61.0 → 10.61.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.
@@ -29,7 +29,7 @@ tfx-live ask --cli codex --session cx1 --prompt "현재 변경사항을 요약
29
29
  tfx-live stop --cli codex --session cx1
30
30
  ```
31
31
 
32
- macOS의 iTerm2에서 로컬 tmux 세션을 `start`하면 리드가 있는 창에 attach 탭이나 패인을 연다. `LC_TERMINAL=iTerm2` 또는 `TERM_PROGRAM=iTerm.app`일 때만 적용하며, 원격과 tmux 세션이 없는 daemon 경로는 제외한다. 같은 `--group NAME`은 한 탭에서 세로로 나누고 다른 그룹은 새 탭을 연다. `--group`을 생략하면 대상 CLI인 `claude`, `codex`, `agy`를 그룹으로 쓴다. `stop --session`은 tmux 종료 뒤 남은 iTerm 패인도 닫는다. 연동이 실패해도 세션 시작과 종료는 계속하며 결과의 `itermWarning`에 원인을 남긴다. 탭 제목은 iTerm2 Python 런타임으로 고정하며 처음 쓸 때 iTerm2 Scripts 폴더에 스크립트 하나를 설치하고, 런타임이 없으면 제목만 바뀌지 않는다.
32
+ macOS의 iTerm2에서 로컬 tmux 세션을 `start`하면 리드가 있는 창에 attach 탭이나 패인을 연다. `LC_TERMINAL=iTerm2` 또는 `TERM_PROGRAM=iTerm.app`일 때만 적용하며, 원격과 tmux 세션이 없는 daemon 경로는 제외하고, ssh 로 들어온 셸처럼 리드가 이 기기의 iTerm2 창에 보이지 않으면 열지 않는다. 같은 `--group NAME`은 한 탭에서 세로로 나누고 다른 그룹은 새 탭을 연다. `--group`을 생략하면 대상 CLI인 `claude`, `codex`, `agy`를 그룹으로 쓴다. `stop --session`은 tmux 종료 뒤 남은 iTerm 패인도 닫는다. 연동이 실패해도 세션 시작과 종료는 계속하며 결과의 `itermWarning`에 원인을 남긴다. 탭 제목은 iTerm2 Python 런타임으로 고정하며 처음 쓸 때 iTerm2 Scripts 폴더에 스크립트 하나를 설치하고, 런타임이 없으면 제목만 바뀌지 않는다.
33
33
 
34
34
  새 세션 이름은 `<월>.<일> <주제>`로 짓는다. `start --name`을 생략하면 자동으로 만들고 `nameGenerated: true`를 보고한다. `--resume` 또는 `--resume-last`는 `--name`을 명시한 경우에만 이름을 적용한다. 승계 세션에는 기존 이름 뒤에 ` 2`, 이후 ` 3`을 붙인다. 이름 적용을 요청한 경우 결과의 `nameApplied: false`는 미적용을 뜻한다. agy의 `namePending: true`는 첫 일반 ask에서 적용할 이름이 보류됐다는 뜻이다. Codex `start`는 `/rename` 제출을 입력창이 빌 때까지 확인하고, 이름으로 찾은 thread UUID를 `threadId`로 돌려주며 tmux 세션 옵션 `@tfx_codex_thread`에 남긴다. 로컬 Codex `--resume-last`는 Codex가 고른 thread를 사후에 찾는다. 띄운 뒤 공유 app-server daemon에 로드된 같은 cwd의 thread 중 rollout에 그 시각 이후의 resume 기록(`thread_settings_applied`)이 생긴 것이 정확히 하나이고 1.5초 뒤에도 같을 때만 `threadId`로 쓴다. 이 확인은 5초 안에 끝난다. TUI가 daemon을 쓰지 않거나 같은 cwd에서 동시에 resume이 일어나면 `null`이다. 기존 Codex UDS thread는 `tfx-live rename --cli codex --transport uds --thread ID --name "<이름>"`으로 이름을 바꾼다.
35
35
 
package/bin/tfx-live.mjs CHANGED
@@ -2545,7 +2545,6 @@ async function openItermSession(session, group) {
2545
2545
  `${shellQuote([realpathSync(tmuxPath.trim()), "attach-session", "-t"])} '=${session.replace(/'/g, `'"'"'`)}'`,
2546
2546
  );
2547
2547
  const script = `tell application "iTerm2"
2548
- set leaderWindow to current window
2549
2548
  set ttyWindow to missing value
2550
2549
  set idWindow to missing value
2551
2550
  repeat with candidateWindow in windows
@@ -2556,10 +2555,13 @@ async function openItermSession(session, group) {
2556
2555
  end repeat
2557
2556
  end repeat
2558
2557
  end repeat
2558
+ -- 리드가 이 기기의 iTerm 창에 없으면(ssh 로 LC_TERMINAL 만 넘어온 경우 등) 열지 않는다.
2559
2559
  if ttyWindow is not missing value then
2560
2560
  set leaderWindow to ttyWindow
2561
2561
  else if idWindow is not missing value then
2562
2562
  set leaderWindow to idWindow
2563
+ else
2564
+ return ""
2563
2565
  end if
2564
2566
  set groupSession to missing value
2565
2567
  repeat with candidateTab in tabs of leaderWindow
@@ -2591,6 +2593,7 @@ end tell`;
2591
2593
  timeout: 5000,
2592
2594
  maxBuffer: 64 * 1024,
2593
2595
  });
2596
+ if (!stdout.trim()) return null;
2594
2597
  const [sessionId, split] = stdout.trim().split("\n");
2595
2598
  if (!sessionId || !["true", "false"].includes(split))
2596
2599
  throw new Error("iTerm did not return a session ID and split status");
@@ -2808,34 +2811,35 @@ async function doStart(adapter, opts) {
2808
2811
  if (ready && shouldUseIterm(remote)) {
2809
2812
  try {
2810
2813
  iterm = await openItermSession(session, opts.group || adapter.cli);
2811
- await runTmux(null, [
2812
- "set-option",
2813
- "-t",
2814
- session,
2815
- "@tfx_iterm_session",
2816
- iterm.sessionId,
2817
- ]);
2818
- const scriptsDir = pathJoin(
2819
- homedir(),
2820
- "Library",
2821
- "Application Support",
2822
- "iTerm2",
2823
- "Scripts",
2824
- );
2825
- const scriptPath = pathJoin(scriptsDir, ITERM_TITLE_SCRIPT_NAME);
2826
- await mkdir(scriptsDir, { recursive: true });
2827
- const installed = await readFile(scriptPath, "utf8").catch((error) => {
2828
- if (error.code === "ENOENT") return null;
2829
- throw error;
2830
- });
2831
- if (installed !== ITERM_TITLE_SCRIPT)
2832
- await writeFile(scriptPath, ITERM_TITLE_SCRIPT, { mode: 0o700 });
2833
- await chmod(scriptPath, 0o700);
2834
- const titleArgs = [iterm.sessionId, iterm.group, opts.name ?? session]
2835
- .map(appleScriptString)
2836
- .join(", ");
2837
- // 절대 경로는 최초 설치 직후의 메뉴 캐시 지연을 피하고, 적용 표식은 비동기 실패를 잡는다.
2838
- const titleScript = `tell application "iTerm2"
2814
+ if (iterm) {
2815
+ await runTmux(null, [
2816
+ "set-option",
2817
+ "-t",
2818
+ session,
2819
+ "@tfx_iterm_session",
2820
+ iterm.sessionId,
2821
+ ]);
2822
+ const scriptsDir = pathJoin(
2823
+ homedir(),
2824
+ "Library",
2825
+ "Application Support",
2826
+ "iTerm2",
2827
+ "Scripts",
2828
+ );
2829
+ const scriptPath = pathJoin(scriptsDir, ITERM_TITLE_SCRIPT_NAME);
2830
+ await mkdir(scriptsDir, { recursive: true });
2831
+ const installed = await readFile(scriptPath, "utf8").catch((error) => {
2832
+ if (error.code === "ENOENT") return null;
2833
+ throw error;
2834
+ });
2835
+ if (installed !== ITERM_TITLE_SCRIPT)
2836
+ await writeFile(scriptPath, ITERM_TITLE_SCRIPT, { mode: 0o700 });
2837
+ await chmod(scriptPath, 0o700);
2838
+ const titleArgs = [iterm.sessionId, iterm.group, opts.name ?? session]
2839
+ .map(appleScriptString)
2840
+ .join(", ");
2841
+ // 절대 경로는 최초 설치 직후의 메뉴 캐시 지연을 피하고, 적용 표식은 비동기 실패를 잡는다.
2842
+ const titleScript = `tell application "iTerm2"
2839
2843
  set titleSession to missing value
2840
2844
  repeat with candidateWindow in windows
2841
2845
  repeat with candidateTab in tabs of candidateWindow
@@ -2855,10 +2859,11 @@ async function doStart(adapter, opts) {
2855
2859
  end repeat
2856
2860
  error "iTerm title update was not confirmed; check the iTerm2 Python runtime and Script Console"
2857
2861
  end tell`;
2858
- await execFileAsync("/usr/bin/osascript", ["-e", titleScript], {
2859
- timeout: 5000,
2860
- maxBuffer: 64 * 1024,
2861
- });
2862
+ await execFileAsync("/usr/bin/osascript", ["-e", titleScript], {
2863
+ timeout: 5000,
2864
+ maxBuffer: 64 * 1024,
2865
+ });
2866
+ }
2862
2867
  } catch (error) {
2863
2868
  itermWarning = error.message;
2864
2869
  }
@@ -4,12 +4,13 @@ import { homedir } from "node:os";
4
4
  import path from "node:path";
5
5
  import { StringDecoder } from "node:string_decoder";
6
6
 
7
- // https://platform.claude.com/docs/en/build-with-claude/context-windows 2026-10-08
7
+ // https://platform.claude.com/docs/en/build-with-claude/context-windows 2026-10-12
8
8
  // https://developers.openai.com/api/docs/models 2026-10-08
9
9
  const MODEL_CONTEXT = [
10
10
  {
11
11
  cli: "claude",
12
- model: /^(?:claude-)?(?:fable-5[.-]1|opus-5[.-]5|sonnet-5[.-]5)(?:$|[-[])/i,
12
+ model:
13
+ /^(?:claude-)?(?:fable-5[.-]1|opus-5[.-]5|sonnet-5[.-]5|haiku-5[.-]5)(?:$|[-[])/i,
13
14
  tokens: 1_000_000,
14
15
  source:
15
16
  "https://platform.claude.com/docs/en/build-with-claude/context-windows",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "triflux",
3
- "version": "10.61.0",
3
+ "version": "10.61.2",
4
4
  "description": "CLI-first multi-model orchestrator for Claude Code — route tasks to Codex, Antigravity, and Claude",
5
5
  "type": "module",
6
6
  "bin": {
@@ -25,7 +25,7 @@ tfx-live ask --cli codex --session cx1 --prompt "현재 변경사항을 요약
25
25
  tfx-live stop --cli codex --session cx1
26
26
  ```
27
27
 
28
- macOS의 iTerm2에서 로컬 tmux 세션을 `start`하면 리드가 있는 창에 attach 탭이나 패인을 연다. `LC_TERMINAL=iTerm2` 또는 `TERM_PROGRAM=iTerm.app`일 때만 적용하며, 원격과 tmux 세션이 없는 daemon 경로는 제외한다. 같은 `--group NAME`은 한 탭에서 세로로 나누고 다른 그룹은 새 탭을 연다. `--group`을 생략하면 대상 CLI인 `claude`, `codex`, `agy`를 그룹으로 쓴다. `stop --session`은 tmux 종료 뒤 남은 iTerm 패인도 닫는다. 연동이 실패해도 세션 시작과 종료는 계속하며 결과의 `itermWarning`에 원인을 남긴다. 탭 제목은 iTerm2 Python 런타임으로 고정하며 처음 쓸 때 iTerm2 Scripts 폴더에 스크립트 하나를 설치하고, 런타임이 없으면 제목만 바뀌지 않는다.
28
+ macOS의 iTerm2에서 로컬 tmux 세션을 `start`하면 리드가 있는 창에 attach 탭이나 패인을 연다. `LC_TERMINAL=iTerm2` 또는 `TERM_PROGRAM=iTerm.app`일 때만 적용하며, 원격과 tmux 세션이 없는 daemon 경로는 제외하고, ssh 로 들어온 셸처럼 리드가 이 기기의 iTerm2 창에 보이지 않으면 열지 않는다. 같은 `--group NAME`은 한 탭에서 세로로 나누고 다른 그룹은 새 탭을 연다. `--group`을 생략하면 대상 CLI인 `claude`, `codex`, `agy`를 그룹으로 쓴다. `stop --session`은 tmux 종료 뒤 남은 iTerm 패인도 닫는다. 연동이 실패해도 세션 시작과 종료는 계속하며 결과의 `itermWarning`에 원인을 남긴다. 탭 제목은 iTerm2 Python 런타임으로 고정하며 처음 쓸 때 iTerm2 Scripts 폴더에 스크립트 하나를 설치하고, 런타임이 없으면 제목만 바뀌지 않는다.
29
29
 
30
30
  새 세션 이름은 `<월>.<일> <주제>`로 짓는다. `start --name`을 생략하면 자동으로 만들고 `nameGenerated: true`를 보고한다. `--resume` 또는 `--resume-last`는 `--name`을 명시한 경우에만 이름을 적용한다. 승계 세션에는 기존 이름 뒤에 ` 2`, 이후 ` 3`을 붙인다. 이름 적용을 요청한 경우 결과의 `nameApplied: false`는 미적용을 뜻한다. agy의 `namePending: true`는 첫 일반 ask에서 적용할 이름이 보류됐다는 뜻이다. Codex `start`는 `/rename` 제출을 입력창이 빌 때까지 확인하고, 이름으로 찾은 thread UUID를 `threadId`로 돌려주며 tmux 세션 옵션 `@tfx_codex_thread`에 남긴다. 로컬 Codex `--resume-last`는 Codex가 고른 thread를 사후에 찾는다. 띄운 뒤 공유 app-server daemon에 로드된 같은 cwd의 thread 중 rollout에 그 시각 이후의 resume 기록(`thread_settings_applied`)이 생긴 것이 정확히 하나이고 1.5초 뒤에도 같을 때만 `threadId`로 쓴다. 이 확인은 5초 안에 끝난다. TUI가 daemon을 쓰지 않거나 같은 cwd에서 동시에 resume이 일어나면 `null`이다. 기존 Codex UDS thread는 `tfx-live rename --cli codex --transport uds --thread ID --name "<이름>"`으로 이름을 바꾼다.
31
31