triflux 10.38.0 → 10.39.0
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 +1 -1
- package/scripts/lib/gemini-profiles.mjs +73 -9
- package/scripts/tfx-route.sh +43 -9
package/package.json
CHANGED
|
@@ -8,23 +8,49 @@ import {
|
|
|
8
8
|
import { homedir } from "node:os";
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
|
|
11
|
+
// 모델명 SSOT. 값은 agy 1.0.x `agy models` 가 출력하는 display name 형식이다
|
|
12
|
+
// (`--model` 인자가 이 문자열을 받는다). 옛 `gemini-*-preview` ID 형식이 아님.
|
|
11
13
|
const DEFAULT_GEMINI_PROFILES = {
|
|
12
|
-
model: "
|
|
14
|
+
model: "Gemini 3.5 Flash (Medium)",
|
|
13
15
|
profiles: {
|
|
16
|
+
flash35_low: {
|
|
17
|
+
model: "Gemini 3.5 Flash (Low)",
|
|
18
|
+
hint: "3.5 Flash (Low) — 경량·저비용",
|
|
19
|
+
},
|
|
20
|
+
flash35: {
|
|
21
|
+
model: "Gemini 3.5 Flash (Medium)",
|
|
22
|
+
hint: "3.5 Flash (Medium) — 기본, 비용·속도 균형",
|
|
23
|
+
},
|
|
24
|
+
flash35_high: {
|
|
25
|
+
model: "Gemini 3.5 Flash (High)",
|
|
26
|
+
hint: "3.5 Flash (High) — 코드/추론 강화",
|
|
27
|
+
},
|
|
28
|
+
pro31_low: {
|
|
29
|
+
model: "Gemini 3.1 Pro (Low)",
|
|
30
|
+
hint: "3.1 Pro (Low) — 플래그십 경량",
|
|
31
|
+
},
|
|
14
32
|
pro31: {
|
|
15
|
-
model: "
|
|
16
|
-
hint: "3.1 Pro — 플래그십 (
|
|
33
|
+
model: "Gemini 3.1 Pro (High)",
|
|
34
|
+
hint: "3.1 Pro (High) — 플래그십 최고 (긴 컨텍스트/복잡 추론)",
|
|
17
35
|
},
|
|
18
36
|
flash3: {
|
|
19
|
-
model: "
|
|
20
|
-
hint: "3.0 Flash —
|
|
37
|
+
model: "Gemini 3 Flash",
|
|
38
|
+
hint: "3.0 Flash — 레거시 호환",
|
|
21
39
|
},
|
|
22
|
-
pro25: { model: "gemini-2.5-pro", hint: "2.5 Pro — 안정 (추론 강화)" },
|
|
23
|
-
flash25: { model: "gemini-2.5-flash", hint: "2.5 Flash — 경량 범용" },
|
|
24
|
-
lite25: { model: "gemini-2.5-flash-lite", hint: "2.5 Flash Lite — 최경량" },
|
|
25
40
|
},
|
|
26
41
|
};
|
|
27
42
|
|
|
43
|
+
// 1회 마이그레이션 테이블: 옛 ID 형식 모델값 → agy display name.
|
|
44
|
+
// null = deprecated(2.5 계열) → 해당 프로필 제거 대상.
|
|
45
|
+
const LEGACY_MODEL_MIGRATION = {
|
|
46
|
+
"gemini-3.1-pro-preview": "Gemini 3.1 Pro (High)",
|
|
47
|
+
"gemini-3-flash-preview": "Gemini 3 Flash",
|
|
48
|
+
"gemini-2.5-pro": null,
|
|
49
|
+
"gemini-2.5-flash": null,
|
|
50
|
+
"gemini-2.5-flash-lite": null,
|
|
51
|
+
};
|
|
52
|
+
const LEGACY_PROFILE_NAMES = ["pro25", "flash25", "lite25"];
|
|
53
|
+
|
|
28
54
|
const DEFAULT_PROFILE_COUNT = Object.keys(
|
|
29
55
|
DEFAULT_GEMINI_PROFILES.profiles,
|
|
30
56
|
).length;
|
|
@@ -80,6 +106,39 @@ function ensureGeminiProfiles({
|
|
|
80
106
|
)
|
|
81
107
|
cfg.profiles = {};
|
|
82
108
|
|
|
109
|
+
// ── 1회 마이그레이션: deprecated 2.5 프로필 prune + 옛 ID 형식 → display name ──
|
|
110
|
+
// merge-only 로직만으로는 기존 사용자 파일에 남은 stale 프로필/옛 모델 ID 가
|
|
111
|
+
// 정리되지 않으므로, 신규 default 를 채우기 전에 마이그레이션을 먼저 적용한다.
|
|
112
|
+
let migrated = false;
|
|
113
|
+
for (const legacy of LEGACY_PROFILE_NAMES) {
|
|
114
|
+
if (cfg.profiles[legacy]) {
|
|
115
|
+
delete cfg.profiles[legacy];
|
|
116
|
+
migrated = true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
for (const [pname, pval] of Object.entries(cfg.profiles)) {
|
|
120
|
+
const mid = typeof pval === "string" ? pval : pval?.model;
|
|
121
|
+
if (mid && Object.hasOwn(LEGACY_MODEL_MIGRATION, mid)) {
|
|
122
|
+
const repl = LEGACY_MODEL_MIGRATION[mid];
|
|
123
|
+
if (repl === null) {
|
|
124
|
+
delete cfg.profiles[pname];
|
|
125
|
+
} else if (typeof pval === "string") {
|
|
126
|
+
cfg.profiles[pname] = repl;
|
|
127
|
+
} else {
|
|
128
|
+
cfg.profiles[pname].model = repl;
|
|
129
|
+
}
|
|
130
|
+
migrated = true;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (
|
|
134
|
+
typeof cfg.model === "string" &&
|
|
135
|
+
Object.hasOwn(LEGACY_MODEL_MIGRATION, cfg.model)
|
|
136
|
+
) {
|
|
137
|
+
// 옛 ID 형식 기본값은 구버전 자동 생성값이므로 새 기본(DEFAULT)으로 정규화한다.
|
|
138
|
+
cfg.model = DEFAULT_GEMINI_PROFILES.model;
|
|
139
|
+
migrated = true;
|
|
140
|
+
}
|
|
141
|
+
|
|
83
142
|
let added = 0;
|
|
84
143
|
for (const [name, value] of Object.entries(
|
|
85
144
|
DEFAULT_GEMINI_PROFILES.profiles,
|
|
@@ -91,7 +150,12 @@ function ensureGeminiProfiles({
|
|
|
91
150
|
}
|
|
92
151
|
if (!cfg.model) cfg.model = DEFAULT_GEMINI_PROFILES.model;
|
|
93
152
|
|
|
94
|
-
if (added > 0) {
|
|
153
|
+
if (added > 0 || migrated) {
|
|
154
|
+
if (migrated) {
|
|
155
|
+
try {
|
|
156
|
+
copyFileSync(profilesPath, profilesPath + `.bak.${Date.now()}`);
|
|
157
|
+
} catch {}
|
|
158
|
+
}
|
|
95
159
|
writeFileSync(profilesPath, JSON.stringify(cfg, null, 2) + "\n", {
|
|
96
160
|
encoding: "utf8",
|
|
97
161
|
mode: 0o600,
|
package/scripts/tfx-route.sh
CHANGED
|
@@ -1121,11 +1121,12 @@ resolve_gemini_profile() {
|
|
|
1121
1121
|
const primaryRaw = process.argv[2] || '{}';
|
|
1122
1122
|
const settingsRaw = process.argv[3] || '{}';
|
|
1123
1123
|
const defaults = {
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1124
|
+
flash35_low: 'Gemini 3.5 Flash (Low)',
|
|
1125
|
+
flash35: 'Gemini 3.5 Flash (Medium)',
|
|
1126
|
+
flash35_high: 'Gemini 3.5 Flash (High)',
|
|
1127
|
+
pro31_low: 'Gemini 3.1 Pro (Low)',
|
|
1128
|
+
pro31: 'Gemini 3.1 Pro (High)',
|
|
1129
|
+
flash3: 'Gemini 3 Flash'
|
|
1129
1130
|
};
|
|
1130
1131
|
|
|
1131
1132
|
if (typeof name === 'string' && name.startsWith('gemini-')) {
|
|
@@ -1193,9 +1194,9 @@ resolve_gemini_profile() {
|
|
|
1193
1194
|
}
|
|
1194
1195
|
}
|
|
1195
1196
|
|
|
1196
|
-
process.stdout.write(defaults[name] || defaults[process.env.TFX_GEMINI_DEFAULT_PROFILE] || defaults.
|
|
1197
|
+
process.stdout.write(defaults[name] || defaults[process.env.TFX_GEMINI_DEFAULT_PROFILE] || defaults.flash35);
|
|
1197
1198
|
" "$profile" "$_GEMINI_PROFILE_CACHE" "$settings_cache" 2>/dev/null)
|
|
1198
|
-
echo "${result:-
|
|
1199
|
+
echo "${result:-Gemini 3.5 Flash (Medium)}"
|
|
1199
1200
|
}
|
|
1200
1201
|
|
|
1201
1202
|
# ── 라우팅 테이블 ──
|
|
@@ -1289,13 +1290,28 @@ route_agent() {
|
|
|
1289
1290
|
CLI_EFFORT="gpt55_xhigh"; DEFAULT_TIMEOUT=3600; RUN_MODE="bg"; OPUS_OVERSIGHT="false" ;;
|
|
1290
1291
|
|
|
1291
1292
|
# ─── Antigravity CLI 레인 (Gemini CLI 후속) ───
|
|
1292
|
-
#
|
|
1293
|
+
# effort 차등: agent 별 GEMINI_PROFILE 을 설정하면 run_antigravity_exec() 가
|
|
1294
|
+
# resolve_gemini_profile 로 해석해 `--model "<display name>"`을 agy_args 에
|
|
1295
|
+
# 주입한다. 우선순위는 TFX_GEMINI_PROFILE(env) > GEMINI_PROFILE(agent) > flash35.
|
|
1296
|
+
# CLI_ARGS 는 read -a 로 word-split 되므로 공백 포함 모델명을 여기 넣지 않는다.
|
|
1293
1297
|
# #310: upstream callers are normalized through agent-map.json, but this
|
|
1294
1298
|
# direct route entrypoint intentionally keeps agy as a compatibility alias.
|
|
1295
|
-
designer
|
|
1299
|
+
designer)
|
|
1300
|
+
# 디자인 = 시각/UX 추론 → 3.5 Flash (High)
|
|
1301
|
+
CLI_ARGS="--print --dangerously-skip-permissions"
|
|
1302
|
+
GEMINI_PROFILE="flash35_high"
|
|
1303
|
+
CLI_EFFORT="agy_v1"; DEFAULT_TIMEOUT=900; RUN_MODE="bg"; OPUS_OVERSIGHT="false" ;;
|
|
1304
|
+
writer)
|
|
1305
|
+
# 문서 작성 = 균형 → 3.5 Flash (Medium)
|
|
1306
|
+
CLI_ARGS="--print --dangerously-skip-permissions"
|
|
1307
|
+
GEMINI_PROFILE="flash35"
|
|
1308
|
+
CLI_EFFORT="agy_v1"; DEFAULT_TIMEOUT=900; RUN_MODE="bg"; OPUS_OVERSIGHT="false" ;;
|
|
1309
|
+
gemini|antigravity|agy)
|
|
1310
|
+
# 직접 호출 alias — 기본 flash35. TFX_GEMINI_PROFILE 로 override 가능.
|
|
1296
1311
|
# agy --print + --dangerously-skip-permissions 조합은 positional prompt에서
|
|
1297
1312
|
# timeout이 재현되므로 wrapper 호출은 stdin pipe로 고정한다.
|
|
1298
1313
|
CLI_ARGS="--print --dangerously-skip-permissions"
|
|
1314
|
+
GEMINI_PROFILE="flash35"
|
|
1299
1315
|
CLI_EFFORT="agy_v1"; DEFAULT_TIMEOUT=900; RUN_MODE="bg"; OPUS_OVERSIGHT="false" ;;
|
|
1300
1316
|
|
|
1301
1317
|
# ─── 탐색 (Claude-native: Glob/Grep/Read 직접 접근) ───
|
|
@@ -1488,6 +1504,12 @@ apply_cli_mode() {
|
|
|
1488
1504
|
CLI_TYPE="antigravity"
|
|
1489
1505
|
CLI_CMD="agy"
|
|
1490
1506
|
CLI_ARGS="--print --dangerously-skip-permissions"
|
|
1507
|
+
# 주 라우팅(route_agent)과 동일하게 designer 만 effort 상향. 나머지는
|
|
1508
|
+
# run_antigravity_exec 폴백(flash35) 또는 TFX_GEMINI_PROFILE override.
|
|
1509
|
+
case "$AGENT_TYPE" in
|
|
1510
|
+
designer) GEMINI_PROFILE="flash35_high" ;;
|
|
1511
|
+
*) GEMINI_PROFILE="flash35" ;;
|
|
1512
|
+
esac
|
|
1491
1513
|
CLI_EFFORT="agy_v1"
|
|
1492
1514
|
DEFAULT_TIMEOUT=900
|
|
1493
1515
|
echo "[tfx-route] TFX_CLI_MODE=antigravity: $AGENT_TYPE → antigravity($CLI_EFFORT)로 리매핑" >&2
|
|
@@ -2180,6 +2202,18 @@ run_antigravity_exec() {
|
|
|
2180
2202
|
local -a agy_args=()
|
|
2181
2203
|
read -r -a agy_args <<< "$CLI_ARGS"
|
|
2182
2204
|
|
|
2205
|
+
# ── 프로필 기반 모델 주입 ──
|
|
2206
|
+
# display name 에 공백/괄호가 있으므로(예: "Gemini 3.5 Flash (Medium)") CLI_ARGS
|
|
2207
|
+
# 문자열이 아니라 agy_args 배열에 두 원소(--model, <display name>)로 append 해야
|
|
2208
|
+
# "${agy_args[@]}" expand 시 단일 인자로 보존된다. 모델 SSOT 는 프로필 설정이다.
|
|
2209
|
+
if [[ -z "${TFX_GEMINI_NO_MODEL:-}" ]]; then
|
|
2210
|
+
local _agy_model
|
|
2211
|
+
_agy_model="$(resolve_gemini_profile "${TFX_GEMINI_PROFILE:-${GEMINI_PROFILE:-flash35}}")"
|
|
2212
|
+
if [[ -n "$_agy_model" ]]; then
|
|
2213
|
+
agy_args+=("--model" "$_agy_model")
|
|
2214
|
+
fi
|
|
2215
|
+
fi
|
|
2216
|
+
|
|
2183
2217
|
if ! agy_supports_headless "$CLI_CMD"; then
|
|
2184
2218
|
echo "[tfx-route] Antigravity CLI headless flags unsupported or missing: $CLI_CMD" >"$STDERR_LOG"
|
|
2185
2219
|
return 127
|