triflux 5.1.0 → 5.1.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.
@@ -248,14 +248,29 @@ function listPaneDetails(sessionName) {
248
248
  return parsePaneDetails(output);
249
249
  }
250
250
 
251
+ function paneTitleToIndex(name) {
252
+ const lower = String(name).toLowerCase();
253
+ if (lower === "lead") return 0;
254
+ const m = /^worker-(\d+)$/.exec(lower);
255
+ if (!m) return -1;
256
+ const idx = parseInt(m[1], 10);
257
+ // worker-0은 유효하지 않음 (lead와 충돌, toPaneTitle은 worker-0을 생성하지 않음)
258
+ return idx >= 1 ? idx : -1;
259
+ }
260
+
251
261
  function resolvePane(sessionName, paneNameOrTarget) {
252
262
  const wanted = String(paneNameOrTarget);
253
- const pane = listPaneDetails(sessionName)
254
- .find((entry) => entry.title === wanted || entry.paneId === wanted);
255
- if (!pane) {
256
- throw new Error(`Pane을 찾을 없습니다: ${paneNameOrTarget}`);
257
- }
258
- return pane;
263
+ const panes = listPaneDetails(sessionName);
264
+
265
+ // 1차: title 또는 paneId 직접 매칭
266
+ const direct = panes.find((entry) => entry.title === wanted || entry.paneId === wanted);
267
+ if (direct) return direct;
268
+
269
+ // 2차: psmux title 미설정 fallback — "lead"→0, "worker-N"→N 인덱스 매칭
270
+ const idx = paneTitleToIndex(wanted);
271
+ if (idx >= 0 && idx < panes.length) return panes[idx];
272
+
273
+ throw new Error(`Pane을 찾을 수 없습니다: ${paneNameOrTarget}`);
259
274
  }
260
275
 
261
276
  function refreshCaptureSnapshot(sessionName, paneNameOrTarget) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "triflux",
3
- "version": "5.1.0",
3
+ "version": "5.1.2",
4
4
  "description": "CLI-first multi-model orchestrator for Claude Code — route tasks to Codex, Gemini, and Claude",
5
5
  "type": "module",
6
6
  "bin": {
@@ -696,7 +696,14 @@ export async function runCli(argv = process.argv.slice(2)) {
696
696
  return;
697
697
  }
698
698
 
699
- const policy = buildMcpPolicy(args);
699
+ let policy;
700
+ try {
701
+ policy = buildMcpPolicy(args);
702
+ } catch (error) {
703
+ console.error(`[mcp-filter] ${error instanceof Error ? error.message : String(error)}`);
704
+ process.exitCode = 65;
705
+ return;
706
+ }
700
707
  if (args.command === 'shell') {
701
708
  process.stdout.write(`${toShellExports(policy)}\n`);
702
709
  return;
@@ -121,6 +121,23 @@ MCP_PROFILE="${3:-auto}"
121
121
  USER_TIMEOUT="${4:-}"
122
122
  CONTEXT_FILE="${5:-}"
123
123
 
124
+ # ── 인자 검증: CLI 이름을 role 자리에 사용한 경우 안내 ──
125
+ case "$AGENT_TYPE" in
126
+ codex|gemini|claude|claude-native)
127
+ echo "ERROR: '$AGENT_TYPE'는 CLI 이름이지 에이전트 역할이 아닙니다." >&2
128
+ echo "올바른 사용법: TFX_CLI_MODE=$AGENT_TYPE bash tfx-route.sh <역할> \"프롬프트\"" >&2
129
+ echo "사용 가능한 역할: executor, code-reviewer, scientist, designer, architect, verifier 등" >&2
130
+ exit 64 ;;
131
+ esac
132
+
133
+ # ── 인자 검증: MCP_PROFILE이 --flag 형태인 경우 거절 ──
134
+ if [[ "$MCP_PROFILE" == --* ]]; then
135
+ echo "ERROR: MCP 프로필 위치(3번째 인자)에 플래그 '$MCP_PROFILE'가 들어왔습니다." >&2
136
+ echo "사용법: tfx-route.sh <역할> \"프롬프트\" [mcp_profile] [timeout]" >&2
137
+ echo "지원 프로필: auto, executor, analyze, implement, review, minimal, full" >&2
138
+ exit 64
139
+ fi
140
+
124
141
  # ── CLI 경로 해석 (Windows npm global 대응) ──
125
142
  NODE_BIN="${NODE_BIN:-$(command -v node 2>/dev/null || echo node)}"
126
143
  CODEX_BIN="${CODEX_BIN:-$(command -v codex 2>/dev/null || echo codex)}"
@@ -461,22 +478,22 @@ team_claim_task() {
461
478
  esac
462
479
  }
463
480
 
464
- team_complete_task() {
465
- local result="${1:-success}" # success/failed/timeout
466
- local result_summary="${2:-작업 완료}"
467
- [[ -z "$TFX_TEAM_NAME" || -z "$TFX_TEAM_TASK_ID" ]] && return 0
468
-
469
- local summary_trimmed result_payload
470
- summary_trimmed=$(echo "$result_summary" | head -c 4096)
471
- result_payload=$(bridge_json_stringify task-result "$TFX_TEAM_TASK_ID" "$result" 2>/dev/null || true)
472
-
473
- # task 파일 completion 쓰기는 Worker Step 6 TaskUpdate가 authority다.
474
- # route 레벨에서는 task.result 발행 + 로컬 backup만 유지한다.
475
-
476
- # Hub result 발행 (poll_messages 채널 활성화)
477
- if [[ -n "$result_payload" ]]; then
478
- if ! bridge_cli_with_restart "Hub result 발행" "Hub 재시작 후 Hub result 발행 성공." \
479
- result \
481
+ team_complete_task() {
482
+ local result="${1:-success}" # success/failed/timeout
483
+ local result_summary="${2:-작업 완료}"
484
+ [[ -z "$TFX_TEAM_NAME" || -z "$TFX_TEAM_TASK_ID" ]] && return 0
485
+
486
+ local summary_trimmed result_payload
487
+ summary_trimmed=$(echo "$result_summary" | head -c 4096)
488
+ result_payload=$(bridge_json_stringify task-result "$TFX_TEAM_TASK_ID" "$result" 2>/dev/null || true)
489
+
490
+ # task 파일 completion 쓰기는 Worker Step 6 TaskUpdate가 authority다.
491
+ # route 레벨에서는 task.result 발행 + 로컬 backup만 유지한다.
492
+
493
+ # Hub result 발행 (poll_messages 채널 활성화)
494
+ if [[ -n "$result_payload" ]]; then
495
+ if ! bridge_cli_with_restart "Hub result 발행" "Hub 재시작 후 Hub result 발행 성공." \
496
+ result \
480
497
  --agent "$TFX_TEAM_AGENT_NAME" \
481
498
  --topic task.result \
482
499
  --payload "$result_payload" \
@@ -637,13 +654,13 @@ route_agent() {
637
654
  CLI_ARGS="-m gemini-3-flash-preview -y --prompt"
638
655
  CLI_EFFORT="flash"; DEFAULT_TIMEOUT=900; RUN_MODE="bg"; OPUS_OVERSIGHT="false" ;;
639
656
 
640
- # ─── 탐색/검증/테스트 (Claude-native 우선, TFX_NO_CLAUDE_NATIVE=1일 때만 Codex 리매핑) ───
641
- explore|verifier|test-engineer|qa-tester)
642
- CLI_TYPE="claude-native"; CLI_CMD=""; CLI_ARGS=""
643
- CLI_EFFORT="n/a"; DEFAULT_TIMEOUT=600; RUN_MODE="fg"; OPUS_OVERSIGHT="false"
644
- case "$agent" in
645
- test-engineer|qa-tester) DEFAULT_TIMEOUT=1200; RUN_MODE="bg" ;;
646
- esac
657
+ # ─── 탐색/검증/테스트 (Claude-native 우선, TFX_NO_CLAUDE_NATIVE=1일 때만 Codex 리매핑) ───
658
+ explore|verifier|test-engineer|qa-tester)
659
+ CLI_TYPE="claude-native"; CLI_CMD=""; CLI_ARGS=""
660
+ CLI_EFFORT="n/a"; DEFAULT_TIMEOUT=600; RUN_MODE="fg"; OPUS_OVERSIGHT="false"
661
+ case "$agent" in
662
+ test-engineer|qa-tester) DEFAULT_TIMEOUT=1200; RUN_MODE="bg" ;;
663
+ esac
647
664
  ;;
648
665
 
649
666
  # ─── 경량 ───