triflux 10.9.28 → 10.9.29
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/account-broker.mjs
CHANGED
|
@@ -77,7 +77,7 @@ function persistState(stateMap) {
|
|
|
77
77
|
}
|
|
78
78
|
mkdirSync(AUTH_BASE_PATH, { recursive: true });
|
|
79
79
|
writeFileSync(STATE_PERSIST_PATH, JSON.stringify({ ts: now, entries }));
|
|
80
|
-
} catch {
|
|
80
|
+
} catch (err) { try { console.error("[account-broker] persistState failed:", err.message); } catch {} }
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
function loadPersistedState() {
|
package/hub/server.mjs
CHANGED
|
@@ -80,6 +80,7 @@ const AIMD_WINDOW_MS = 30 * 60 * 1000;
|
|
|
80
80
|
const AIMD_INITIAL_BATCH_SIZE = 3;
|
|
81
81
|
const AIMD_MIN_BATCH_SIZE = 1;
|
|
82
82
|
const AIMD_MAX_BATCH_SIZE = 10;
|
|
83
|
+
const SYNAPSE_VALID_OPS = new Set(["checkout", "rebase", "cherry-pick", "reset", "stash-pop", "worktree-remove"]);
|
|
83
84
|
const HUB_IDLE_TIMEOUT_DEFAULT_MS = 0; // 0 = 영구 실행 (idle shutdown 비활성). TFX_HUB_IDLE_TIMEOUT_MS 환경변수로 오버라이드 가능
|
|
84
85
|
const HUB_IDLE_SWEEP_DEFAULT_MS = 60 * 1000;
|
|
85
86
|
const STATIC_CONTENT_TYPES = Object.freeze({
|
|
@@ -839,14 +840,13 @@ export async function startHub({
|
|
|
839
840
|
}
|
|
840
841
|
|
|
841
842
|
if (path === "/synapse/preflight" && req.method === "POST") {
|
|
842
|
-
const VALID_OPS = new Set(["checkout", "rebase", "cherry-pick", "reset", "stash-pop", "worktree-remove"]);
|
|
843
843
|
try {
|
|
844
844
|
const body = await parseBody(req);
|
|
845
845
|
const { op, args = {}, sessionContext = {} } = body;
|
|
846
846
|
if (!op || typeof op !== "string") {
|
|
847
847
|
return writeJson(res, 400, { ok: false, error: "op 필수" });
|
|
848
848
|
}
|
|
849
|
-
if (!
|
|
849
|
+
if (!SYNAPSE_VALID_OPS.has(op)) {
|
|
850
850
|
return writeJson(res, 400, { ok: false, error: `invalid op: ${op}` });
|
|
851
851
|
}
|
|
852
852
|
const result = gitPreflight.check(op, args, sessionContext);
|
|
@@ -1814,6 +1814,7 @@ const QUOTA_CACHE_PATH = join(CACHE_DIR, "broker-quota-cache.json");
|
|
|
1814
1814
|
async function checkSingleAccountQuota(acct) {
|
|
1815
1815
|
try {
|
|
1816
1816
|
const authPath = join(PID_DIR, acct.authFile);
|
|
1817
|
+
if (!authPath.startsWith(PID_DIR + sep)) return { id: acct.id, status: "path_blocked" };
|
|
1817
1818
|
if (!existsSync(authPath)) return { id: acct.id, status: "no_auth" };
|
|
1818
1819
|
const auth = JSON.parse(readFileSync(authPath, "utf8"));
|
|
1819
1820
|
if (acct.provider === "codex") {
|
|
@@ -152,7 +152,7 @@ export function createSynapseRegistry(opts = {}) {
|
|
|
152
152
|
const staled = { ...current, status: "stale" };
|
|
153
153
|
sessions.set(sessionId, staled);
|
|
154
154
|
schedulePersist();
|
|
155
|
-
setImmediate(() => notifyStale(staled));
|
|
155
|
+
setImmediate(() => { if (!destroyed) notifyStale(staled); });
|
|
156
156
|
}
|
|
157
157
|
}, intervalFor(session));
|
|
158
158
|
|
package/package.json
CHANGED
|
@@ -173,7 +173,9 @@ function autoRoute(updatedCommand, reason) {
|
|
|
173
173
|
const HEADLESS_FALLBACK_COMMAND =
|
|
174
174
|
"Bash(\"tfx multi --teammate-mode headless --assign 'codex:prompt:role' ...\")";
|
|
175
175
|
const DIRECT_CLI_BYPASS_HINT =
|
|
176
|
-
"
|
|
176
|
+
"이 차단은 하드스톱이다. 환경변수 우회, SSH 원격 실행, 스크립트 배포 등 어떤 형태의 우회도 시도하지 마라. " +
|
|
177
|
+
"Hub가 미가용이면 hub-ensure로 Hub를 시작한 뒤 tfx multi를 사용하라. " +
|
|
178
|
+
"Hub 시작이 불가능하면 사용자에게 'Hub 필요' 보고 후 중단하라.";
|
|
177
179
|
|
|
178
180
|
async function main() {
|
|
179
181
|
// P0: TFX_ALLOW_DIRECT_CLI는 hasDirectCli 블록 안에서만 체크 (CLI deny만 스킵)
|
|
@@ -752,6 +752,19 @@ function shellArray(name, values) {
|
|
|
752
752
|
return `${name}=(${values.map((value) => shellEscape(value)).join(" ")})`;
|
|
753
753
|
}
|
|
754
754
|
|
|
755
|
+
export function toDelimited(policy) {
|
|
756
|
+
const RS = "\x1e";
|
|
757
|
+
return [
|
|
758
|
+
policy.requestedProfile,
|
|
759
|
+
policy.resolvedProfile,
|
|
760
|
+
policy.hint,
|
|
761
|
+
policy.geminiAllowedServers.join(","),
|
|
762
|
+
policy.codexConfigOverrides.flatMap((o) => ["-c", o]).join(","),
|
|
763
|
+
JSON.stringify(policy.codexConfig),
|
|
764
|
+
policy.resolvedPhase || "",
|
|
765
|
+
].join(RS);
|
|
766
|
+
}
|
|
767
|
+
|
|
755
768
|
export function toShellExports(policy) {
|
|
756
769
|
const lines = [
|
|
757
770
|
`MCP_PROFILE_REQUESTED=${shellEscape(policy.requestedProfile)}`,
|
|
@@ -856,6 +869,10 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
856
869
|
process.stdout.write(`${toShellExports(policy)}\n`);
|
|
857
870
|
return;
|
|
858
871
|
}
|
|
872
|
+
if (args.command === "delimited") {
|
|
873
|
+
process.stdout.write(toDelimited(policy));
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
859
876
|
|
|
860
877
|
process.stdout.write(`${JSON.stringify(policy, null, 2)}\n`);
|
|
861
878
|
}
|
package/scripts/tfx-route.sh
CHANGED
|
@@ -64,6 +64,7 @@ track_worker_pid() {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
cleanup_workers() {
|
|
67
|
+
_codex_config_swap "restore" 2>/dev/null || true
|
|
67
68
|
deregister_agent 2>/dev/null || true
|
|
68
69
|
[[ ! -f "$_PID_TRACK" ]] && return
|
|
69
70
|
while IFS= read -r pid; do
|
|
@@ -1203,7 +1204,7 @@ resolve_mcp_policy() {
|
|
|
1203
1204
|
fi
|
|
1204
1205
|
|
|
1205
1206
|
local -a cmd=(
|
|
1206
|
-
"$NODE_BIN" "$filter_script"
|
|
1207
|
+
"$NODE_BIN" "$filter_script" delimited
|
|
1207
1208
|
"--agent" "$AGENT_TYPE"
|
|
1208
1209
|
"--profile" "$MCP_PROFILE"
|
|
1209
1210
|
"--available" "$available_servers"
|
|
@@ -1213,13 +1214,18 @@ resolve_mcp_policy() {
|
|
|
1213
1214
|
[[ -n "$TFX_SEARCH_TOOL" ]] && cmd+=("--search-tool" "$TFX_SEARCH_TOOL")
|
|
1214
1215
|
[[ -n "$TFX_WORKER_INDEX" ]] && cmd+=("--worker-index" "$TFX_WORKER_INDEX")
|
|
1215
1216
|
|
|
1216
|
-
local
|
|
1217
|
-
if !
|
|
1217
|
+
local _raw
|
|
1218
|
+
if ! _raw="$("${cmd[@]}")"; then
|
|
1218
1219
|
echo "[tfx-route] ERROR: MCP 정책 계산 실패" >&2
|
|
1219
1220
|
return 1
|
|
1220
1221
|
fi
|
|
1221
1222
|
|
|
1222
|
-
|
|
1223
|
+
local _gemini_servers _codex_flags _phase
|
|
1224
|
+
IFS=$'\x1e' read -r MCP_PROFILE_REQUESTED MCP_RESOLVED_PROFILE MCP_HINT \
|
|
1225
|
+
_gemini_servers _codex_flags CODEX_CONFIG_JSON _phase <<< "$_raw"
|
|
1226
|
+
IFS=',' read -r -a GEMINI_ALLOWED_SERVERS <<< "$_gemini_servers"
|
|
1227
|
+
IFS=',' read -r -a CODEX_CONFIG_FLAGS <<< "$_codex_flags"
|
|
1228
|
+
[[ -n "$_phase" ]] && MCP_PIPELINE_PHASE="$_phase"
|
|
1223
1229
|
}
|
|
1224
1230
|
|
|
1225
1231
|
get_claude_model() {
|