triflux 4.2.1 → 4.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "triflux",
3
- "version": "4.2.1",
3
+ "version": "4.2.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": {
@@ -2,22 +2,58 @@
2
2
  // scripts/preflight-cache.mjs — 세션 시작 시 preflight 점검 캐싱
3
3
 
4
4
  import { writeFileSync, mkdirSync, existsSync, readFileSync } from "node:fs";
5
- import { join } from "node:path";
5
+ import { join, dirname } from "node:path";
6
6
  import { homedir } from "node:os";
7
- import { execSync } from "node:child_process";
7
+ import { execSync, spawn } from "node:child_process";
8
+ import { fileURLToPath } from "node:url";
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const PKG_ROOT = join(dirname(__filename), "..");
12
+
13
+ // 동기 대기 (Atomics.wait — Node.js main thread에서 사용 가능)
14
+ const _sab = new Int32Array(new SharedArrayBuffer(4));
15
+ function sleepSync(ms) { Atomics.wait(_sab, 0, 0, ms); }
8
16
 
9
17
  const CACHE_DIR = join(homedir(), ".claude", "cache");
10
18
  const CACHE_FILE = join(CACHE_DIR, "tfx-preflight.json");
11
19
  const CACHE_TTL_MS = 30_000; // 30초
12
20
 
13
21
  function checkHub() {
22
+ // 1차 시도
14
23
  try {
15
24
  const res = execSync("curl -sf http://127.0.0.1:27888/status", { timeout: 3000, encoding: "utf8", windowsHide: true });
16
25
  const data = JSON.parse(res);
17
26
  return { ok: true, state: data?.hub?.state || "unknown", pid: data?.pid };
27
+ } catch {}
28
+
29
+ // Hub 미응답 → 자동 재시작 시도 (bridge.mjs tryRestartHub 동기 버전)
30
+ const serverPath = join(PKG_ROOT, "hub", "server.mjs");
31
+ if (!existsSync(serverPath)) return { ok: false, state: "unreachable", restart: "no_server" };
32
+
33
+ try {
34
+ const child = spawn(process.execPath, [serverPath], {
35
+ detached: true,
36
+ stdio: "ignore",
37
+ windowsHide: true,
38
+ });
39
+ child.unref();
18
40
  } catch {
19
- return { ok: false, state: "unreachable" };
41
+ return { ok: false, state: "unreachable", restart: "spawn_failed" };
20
42
  }
43
+
44
+ // 최대 4초 폴링 (500ms × 8)
45
+ for (let i = 0; i < 8; i++) {
46
+ sleepSync(500);
47
+ try {
48
+ const res = execSync("curl -sf http://127.0.0.1:27888/status", { timeout: 1000, encoding: "utf8", windowsHide: true });
49
+ const data = JSON.parse(res);
50
+ if (data?.hub?.state === "healthy") {
51
+ return { ok: true, state: "healthy", pid: data?.pid, restarted: true };
52
+ }
53
+ } catch {}
54
+ }
55
+
56
+ return { ok: false, state: "unreachable", restart: "timeout" };
21
57
  }
22
58
 
23
59
  function checkRoute() {
@@ -63,6 +99,14 @@ function runPreflight() {
63
99
  ok: false,
64
100
  };
65
101
  result.ok = result.hub.ok && result.route.ok;
102
+
103
+ // CLI 가용성 → available_agents (triage에서 참조)
104
+ const agents = [];
105
+ if (result.codex.ok) agents.push("codex");
106
+ if (result.gemini.ok) agents.push("gemini");
107
+ agents.push("claude"); // claude는 항상 가용
108
+ result.available_agents = agents;
109
+
66
110
  return result;
67
111
  }
68
112
 
@@ -84,7 +128,9 @@ if (process.argv[1]?.endsWith("preflight-cache.mjs")) {
84
128
  const summary = result.ok ? "preflight: ok" : "preflight: FAIL";
85
129
  const details = [];
86
130
  if (!result.hub.ok) details.push("hub:" + result.hub.state);
131
+ else if (result.hub.restarted) details.push("hub:restarted");
87
132
  if (!result.route.ok) details.push("route:missing");
133
+ if (result.available_agents.length === 1) details.push("agents:claude-only");
88
134
  console.log(details.length ? `${summary} (${details.join(", ")})` : summary);
89
135
  }
90
136