@triflux/core 10.44.0 → 10.46.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/hooks/codex-session-hook.mjs +67 -1
- package/hooks/cto-north-star-brief.mjs +3 -16
- package/hooks/error-context.mjs +3 -6
- package/hooks/hook-manager.mjs +1 -1
- package/hooks/hook-registry.json +0 -11
- package/hooks/keyword-rules.json +8 -4
- package/hooks/permission-safe-allow.mjs +36 -2
- package/hooks/session-start-fast.mjs +50 -1
- package/hooks/session-start-lake.mjs +3 -16
- package/hub/bridge.mjs +111 -5
- package/hub/dynamic-routing-engine.mjs +1 -1
- package/hub/gemini-adapter.mjs +29 -11
- package/hub/lib/memory-store.mjs +66 -30
- package/hub/lib/tfx-route-args.mjs +41 -4
- package/hub/reflexion.mjs +0 -57
- package/hub/router.mjs +202 -24
- package/hub/team/claude-daemon-control.mjs +2 -0
- package/hub/team/retry-state-machine.mjs +47 -16
- package/hud/cli-policy.mjs +69 -0
- package/hud/constants.mjs +20 -17
- package/hud/context-monitor.mjs +31 -21
- package/hud/hud-qos-status.mjs +81 -91
- package/hud/providers/claude.mjs +150 -84
- package/hud/providers/codex.mjs +10 -1
- package/hud/renderers.mjs +21 -59
- package/hud/utils.mjs +1 -15
- package/package.json +1 -1
- package/scripts/lib/agent-route-policy.mjs +47 -39
- package/scripts/lib/cli-agy.mjs +24 -4
- package/scripts/lib/codex-profile-config.mjs +45 -13
- package/scripts/lib/gemini-profiles.mjs +113 -29
- package/scripts/lib/keyword-rules.mjs +12 -0
- package/scripts/lib/logger.mjs +60 -43
- package/scripts/lib/machine-profile.mjs +293 -0
- package/scripts/lib/mcp-health.mjs +44 -18
package/hud/renderers.mjs
CHANGED
|
@@ -22,11 +22,9 @@ import {
|
|
|
22
22
|
import {
|
|
23
23
|
ACCOUNT_LABEL_WIDTH,
|
|
24
24
|
FIVE_HOUR_MS,
|
|
25
|
-
LEGACY_SV_ACCUMULATOR,
|
|
26
25
|
ONE_DAY_MS,
|
|
27
26
|
PROVIDER_PREFIX_WIDTH,
|
|
28
27
|
SEVEN_DAY_MS,
|
|
29
|
-
SV_ACCUMULATOR_PATH,
|
|
30
28
|
TEAM_STATE_PATH,
|
|
31
29
|
} from "./constants.mjs";
|
|
32
30
|
import { buildContextUsageView } from "./context-monitor.mjs";
|
|
@@ -40,13 +38,11 @@ import {
|
|
|
40
38
|
formatResetRemaining,
|
|
41
39
|
formatResetRemainingDayHour,
|
|
42
40
|
formatSavings,
|
|
43
|
-
formatSvPct,
|
|
44
41
|
formatTimeCell,
|
|
45
42
|
formatTimeCellDH,
|
|
46
43
|
formatTokenCount,
|
|
47
44
|
padAnsiRight,
|
|
48
45
|
readJson,
|
|
49
|
-
readJsonMigrate,
|
|
50
46
|
stripAnsi,
|
|
51
47
|
truncateAnsi,
|
|
52
48
|
} from "./utils.mjs";
|
|
@@ -88,25 +84,6 @@ export function readLatestBenchmarkDiff() {
|
|
|
88
84
|
}
|
|
89
85
|
}
|
|
90
86
|
|
|
91
|
-
// 토큰 절약액 누적치 읽기 (tfx-auto token tracker)
|
|
92
|
-
export function readTokenSavings() {
|
|
93
|
-
const savingsPath = join(
|
|
94
|
-
homedir(),
|
|
95
|
-
".omc",
|
|
96
|
-
"state",
|
|
97
|
-
"tfx-auto-tokens",
|
|
98
|
-
"savings-total.json",
|
|
99
|
-
);
|
|
100
|
-
const data = readJson(savingsPath, null);
|
|
101
|
-
if (!data || data.totalSaved === 0) return null;
|
|
102
|
-
return data;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// sv-accumulator.json에서 누적 토큰/비용 읽기
|
|
106
|
-
export function readSvAccumulator() {
|
|
107
|
-
return readJsonMigrate(SV_ACCUMULATOR_PATH, LEGACY_SV_ACCUMULATOR, null);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
87
|
/**
|
|
111
88
|
* 파이프라인 벤치마크 diff 결과를 HUD 요약 문자열로 포맷
|
|
112
89
|
*/
|
|
@@ -279,9 +256,12 @@ export function getMicroLine(
|
|
|
279
256
|
codexBuckets,
|
|
280
257
|
geminiSession,
|
|
281
258
|
geminiBucket,
|
|
282
|
-
combinedSvPct,
|
|
283
259
|
geminiMarker = "g",
|
|
260
|
+
options = {},
|
|
284
261
|
) {
|
|
262
|
+
// showCodex / showGemini 는 machine profile 의 TFX_DISABLE_* 게이트다. 기본값이
|
|
263
|
+
// true 라 8번째 인자를 주지 않는 기존 호출은 그대로 동작한다.
|
|
264
|
+
const { showCodex = true, showGemini = true } = options;
|
|
285
265
|
const ctxView = contextView || buildContextUsageView({}, null);
|
|
286
266
|
// Claude 5h/1w
|
|
287
267
|
const cF =
|
|
@@ -325,34 +305,27 @@ export function getMicroLine(
|
|
|
325
305
|
gVal = dim("--");
|
|
326
306
|
}
|
|
327
307
|
|
|
328
|
-
// sv
|
|
329
|
-
const sv = formatSvPct(combinedSvPct).trim();
|
|
330
|
-
|
|
331
308
|
const cols = getTerminalColumns() || 120;
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
`${bold(
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
309
|
+
// 세그먼트를 모아 join 한다. 차단된 프로바이더를 뺄 때 공백이 겹치지 않는다.
|
|
310
|
+
const segments = [`${bold(claudeOrange("c"))}${dim(":")}${cVal}`];
|
|
311
|
+
if (showCodex) {
|
|
312
|
+
segments.push(`${bold(codexWhite("x"))}${dim(":")}${xVal}`);
|
|
313
|
+
}
|
|
314
|
+
if (showGemini) {
|
|
315
|
+
segments.push(`${bold(geminiBlue(geminiMarker))}${dim(":")}${gVal}`);
|
|
316
|
+
}
|
|
317
|
+
segments.push(
|
|
318
|
+
`${dim("CTX:")}${colorByPercent(ctxView.percent, ctxView.display)}`,
|
|
319
|
+
);
|
|
320
|
+
return truncateAnsi(segments.join(" "), cols);
|
|
339
321
|
}
|
|
340
322
|
|
|
341
323
|
// ============================================================================
|
|
342
324
|
// Claude 행 렌더러
|
|
343
325
|
// ============================================================================
|
|
344
|
-
export function getClaudeRows(
|
|
345
|
-
currentTier,
|
|
346
|
-
contextView,
|
|
347
|
-
claudeUsage,
|
|
348
|
-
combinedSvPct,
|
|
349
|
-
) {
|
|
326
|
+
export function getClaudeRows(currentTier, contextView, claudeUsage) {
|
|
350
327
|
const ctxView = contextView || buildContextUsageView({}, null);
|
|
351
328
|
const prefix = `${bold(claudeOrange("c"))}:`;
|
|
352
|
-
// 절약 퍼센트
|
|
353
|
-
const svStr = formatSvPct(combinedSvPct);
|
|
354
|
-
const svSuffix = `${dim("sv:")}${svStr}`;
|
|
355
|
-
|
|
356
329
|
// API 실측 데이터
|
|
357
330
|
const fiveHourPercent = claudeUsage?.fiveHourPercent ?? null;
|
|
358
331
|
const weeklyPercent = claudeUsage?.weeklyPercent ?? null;
|
|
@@ -418,7 +391,7 @@ export function getClaudeRows(
|
|
|
418
391
|
const warning = ctxView.warningTag
|
|
419
392
|
? ` ${dim("|")} ${yellow(ctxView.warningTag)}`
|
|
420
393
|
: "";
|
|
421
|
-
const contextSection = `${
|
|
394
|
+
const contextSection = `${dim("CTX:")}${colorByPercent(ctxView.percent, ctxView.display)}${warning}`;
|
|
422
395
|
return [{ prefix, left: quotaSection, right: contextSection }];
|
|
423
396
|
}
|
|
424
397
|
|
|
@@ -428,7 +401,7 @@ export function getClaudeRows(
|
|
|
428
401
|
const warning = ctxView.warningTag
|
|
429
402
|
? ` ${dim("|")} ${yellow(ctxView.warningTag)}`
|
|
430
403
|
: "";
|
|
431
|
-
const contextSection = `${
|
|
404
|
+
const contextSection = `${dim("CTX:")}${colorByPercent(ctxView.percent, ctxView.display)}${warning}`;
|
|
432
405
|
return [{ prefix, left: quotaSection, right: contextSection }];
|
|
433
406
|
}
|
|
434
407
|
|
|
@@ -513,7 +486,6 @@ export function getProviderRow(
|
|
|
513
486
|
accountsState,
|
|
514
487
|
realQuota,
|
|
515
488
|
codexEmail,
|
|
516
|
-
savingsMultiplier,
|
|
517
489
|
modelLabel,
|
|
518
490
|
) {
|
|
519
491
|
const accountLabel = fitText(
|
|
@@ -521,10 +493,6 @@ export function getProviderRow(
|
|
|
521
493
|
ACCOUNT_LABEL_WIDTH,
|
|
522
494
|
);
|
|
523
495
|
|
|
524
|
-
// 절약 퍼센트 섹션
|
|
525
|
-
const svPct =
|
|
526
|
-
savingsMultiplier != null ? Math.round(savingsMultiplier * 100) : null;
|
|
527
|
-
const svStr = formatSvPct(svPct);
|
|
528
496
|
const _modelLabelStr = modelLabel ? ` ${markerColor(modelLabel)}` : "";
|
|
529
497
|
|
|
530
498
|
// 프로바이더별 색상 프로필
|
|
@@ -708,10 +676,7 @@ export function getProviderRow(
|
|
|
708
676
|
quotaSection = `${dim("5h:")}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCell("n/a"))} ${dim("1w:")}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCellDH("--d--h"))}`;
|
|
709
677
|
}
|
|
710
678
|
const prefix = `${bold(markerColor(`${marker}`))}:`;
|
|
711
|
-
const compactRight = [
|
|
712
|
-
svStr ? `${dim("sv:")}${svStr}` : "",
|
|
713
|
-
accountLabel ? markerColor(accountLabel) : "",
|
|
714
|
-
]
|
|
679
|
+
const compactRight = [accountLabel ? markerColor(accountLabel) : ""]
|
|
715
680
|
.filter(Boolean)
|
|
716
681
|
.join(" ");
|
|
717
682
|
return { prefix, left: quotaSection, right: compactRight };
|
|
@@ -800,11 +765,8 @@ export function getProviderRow(
|
|
|
800
765
|
|
|
801
766
|
const prefix = `${bold(markerColor(`${marker}`))}:`;
|
|
802
767
|
const accountSection = `${markerColor(accountLabel)}`;
|
|
803
|
-
const svSection = svStr ? `${dim("sv:")}${svStr}` : "";
|
|
804
768
|
const modelLabelSection = modelLabel ? markerColor(modelLabel) : "";
|
|
805
|
-
const rightParts = [
|
|
806
|
-
Boolean,
|
|
807
|
-
);
|
|
769
|
+
const rightParts = [accountSection, modelLabelSection].filter(Boolean);
|
|
808
770
|
return {
|
|
809
771
|
prefix,
|
|
810
772
|
left: quotaSection,
|
package/hud/utils.mjs
CHANGED
|
@@ -5,11 +5,7 @@
|
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
6
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { dirname } from "node:path";
|
|
8
|
-
import {
|
|
9
|
-
PERCENT_CELL_WIDTH,
|
|
10
|
-
SV_CELL_WIDTH,
|
|
11
|
-
TIME_CELL_INNER_WIDTH,
|
|
12
|
-
} from "./constants.mjs";
|
|
8
|
+
import { PERCENT_CELL_WIDTH, TIME_CELL_INNER_WIDTH } from "./constants.mjs";
|
|
13
9
|
|
|
14
10
|
export async function readStdinJson() {
|
|
15
11
|
if (process.stdin.isTTY) return {};
|
|
@@ -338,16 +334,6 @@ export function createHttpsPost(https, timeoutMs) {
|
|
|
338
334
|
};
|
|
339
335
|
}
|
|
340
336
|
|
|
341
|
-
// sv 퍼센트 포맷 (1000+ → k 표기, 5자 고정폭)
|
|
342
|
-
export function formatSvPct(value) {
|
|
343
|
-
if (value == null) return "--%".padStart(SV_CELL_WIDTH);
|
|
344
|
-
if (value >= 10000)
|
|
345
|
-
return `${Math.round(value / 1000)}k%`.padStart(SV_CELL_WIDTH);
|
|
346
|
-
if (value >= 1000)
|
|
347
|
-
return `${(value / 1000).toFixed(1)}k%`.padStart(SV_CELL_WIDTH);
|
|
348
|
-
return `${value}%`.padStart(SV_CELL_WIDTH);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
337
|
export function formatSavings(dollars) {
|
|
352
338
|
if (dollars >= 100) return `$${Math.round(dollars)}`;
|
|
353
339
|
if (dollars >= 10) return `$${dollars.toFixed(1)}`;
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
// Canonical Codex role policy. Concrete model IDs stay in profile config files.
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
normalizeCodexProfileName,
|
|
5
|
+
resolveCodexProfileConfigValues,
|
|
6
|
+
} from "./codex-profile-config.mjs";
|
|
4
7
|
|
|
5
8
|
const policy = {
|
|
6
9
|
executor: {
|
|
7
|
-
profile: "
|
|
10
|
+
profile: "gpt6_sol_high",
|
|
8
11
|
timeoutSec: 1080,
|
|
9
12
|
runMode: "fg",
|
|
10
13
|
opusOversight: false,
|
|
@@ -12,7 +15,7 @@ const policy = {
|
|
|
12
15
|
subcommand: "exec",
|
|
13
16
|
},
|
|
14
17
|
codex: {
|
|
15
|
-
profile: "
|
|
18
|
+
profile: "gpt6_sol_high",
|
|
16
19
|
timeoutSec: 1080,
|
|
17
20
|
runMode: "fg",
|
|
18
21
|
opusOversight: false,
|
|
@@ -20,7 +23,7 @@ const policy = {
|
|
|
20
23
|
subcommand: "exec",
|
|
21
24
|
},
|
|
22
25
|
"build-fixer": {
|
|
23
|
-
profile: "
|
|
26
|
+
profile: "gpt6_luna_high",
|
|
24
27
|
timeoutSec: 540,
|
|
25
28
|
runMode: "fg",
|
|
26
29
|
opusOversight: false,
|
|
@@ -28,7 +31,7 @@ const policy = {
|
|
|
28
31
|
subcommand: "exec",
|
|
29
32
|
},
|
|
30
33
|
cleanup: {
|
|
31
|
-
profile: "
|
|
34
|
+
profile: "gpt6_sol_med",
|
|
32
35
|
timeoutSec: 540,
|
|
33
36
|
runMode: "fg",
|
|
34
37
|
opusOversight: false,
|
|
@@ -36,7 +39,7 @@ const policy = {
|
|
|
36
39
|
subcommand: "exec",
|
|
37
40
|
},
|
|
38
41
|
deslop: {
|
|
39
|
-
profile: "
|
|
42
|
+
profile: "gpt6_sol_med",
|
|
40
43
|
timeoutSec: 540,
|
|
41
44
|
runMode: "fg",
|
|
42
45
|
opusOversight: false,
|
|
@@ -44,7 +47,7 @@ const policy = {
|
|
|
44
47
|
subcommand: "exec",
|
|
45
48
|
},
|
|
46
49
|
debugger: {
|
|
47
|
-
profile: "
|
|
50
|
+
profile: "gpt6_astra_xhigh",
|
|
48
51
|
timeoutSec: 900,
|
|
49
52
|
runMode: "bg",
|
|
50
53
|
opusOversight: false,
|
|
@@ -52,7 +55,7 @@ const policy = {
|
|
|
52
55
|
subcommand: "exec",
|
|
53
56
|
},
|
|
54
57
|
"deep-executor": {
|
|
55
|
-
profile: "
|
|
58
|
+
profile: "gpt6_astra_xhigh",
|
|
56
59
|
timeoutSec: 3600,
|
|
57
60
|
runMode: "bg",
|
|
58
61
|
opusOversight: true,
|
|
@@ -60,7 +63,7 @@ const policy = {
|
|
|
60
63
|
subcommand: "exec",
|
|
61
64
|
},
|
|
62
65
|
architect: {
|
|
63
|
-
profile: "
|
|
66
|
+
profile: "gpt6_astra_xhigh",
|
|
64
67
|
timeoutSec: 3600,
|
|
65
68
|
runMode: "bg",
|
|
66
69
|
opusOversight: true,
|
|
@@ -68,7 +71,7 @@ const policy = {
|
|
|
68
71
|
subcommand: "exec",
|
|
69
72
|
},
|
|
70
73
|
critic: {
|
|
71
|
-
profile: "
|
|
74
|
+
profile: "gpt6_astra_xhigh",
|
|
72
75
|
timeoutSec: 3600,
|
|
73
76
|
runMode: "bg",
|
|
74
77
|
opusOversight: true,
|
|
@@ -76,7 +79,7 @@ const policy = {
|
|
|
76
79
|
subcommand: "exec",
|
|
77
80
|
},
|
|
78
81
|
planner: {
|
|
79
|
-
profile: "
|
|
82
|
+
profile: "gpt6_astra_xhigh",
|
|
80
83
|
timeoutSec: 3600,
|
|
81
84
|
runMode: "fg",
|
|
82
85
|
opusOversight: true,
|
|
@@ -84,7 +87,7 @@ const policy = {
|
|
|
84
87
|
subcommand: "exec",
|
|
85
88
|
},
|
|
86
89
|
analyst: {
|
|
87
|
-
profile: "
|
|
90
|
+
profile: "gpt6_astra_xhigh",
|
|
88
91
|
timeoutSec: 3600,
|
|
89
92
|
runMode: "fg",
|
|
90
93
|
opusOversight: true,
|
|
@@ -92,7 +95,7 @@ const policy = {
|
|
|
92
95
|
subcommand: "exec",
|
|
93
96
|
},
|
|
94
97
|
"code-reviewer": {
|
|
95
|
-
profile: "
|
|
98
|
+
profile: "gpt6_sol_high",
|
|
96
99
|
timeoutSec: 1800,
|
|
97
100
|
runMode: "bg",
|
|
98
101
|
opusOversight: false,
|
|
@@ -100,7 +103,7 @@ const policy = {
|
|
|
100
103
|
subcommand: "review",
|
|
101
104
|
},
|
|
102
105
|
"quality-reviewer": {
|
|
103
|
-
profile: "
|
|
106
|
+
profile: "gpt6_sol_high",
|
|
104
107
|
timeoutSec: 1800,
|
|
105
108
|
runMode: "bg",
|
|
106
109
|
opusOversight: false,
|
|
@@ -108,7 +111,7 @@ const policy = {
|
|
|
108
111
|
subcommand: "review",
|
|
109
112
|
},
|
|
110
113
|
"security-reviewer": {
|
|
111
|
-
profile: "
|
|
114
|
+
profile: "gpt6_astra_xhigh",
|
|
112
115
|
timeoutSec: 1800,
|
|
113
116
|
runMode: "bg",
|
|
114
117
|
opusOversight: true,
|
|
@@ -116,7 +119,7 @@ const policy = {
|
|
|
116
119
|
subcommand: "review",
|
|
117
120
|
},
|
|
118
121
|
scientist: {
|
|
119
|
-
profile: "
|
|
122
|
+
profile: "gpt6_sol_high",
|
|
120
123
|
timeoutSec: 1440,
|
|
121
124
|
runMode: "bg",
|
|
122
125
|
opusOversight: false,
|
|
@@ -124,7 +127,7 @@ const policy = {
|
|
|
124
127
|
subcommand: "exec",
|
|
125
128
|
},
|
|
126
129
|
"document-specialist": {
|
|
127
|
-
profile: "
|
|
130
|
+
profile: "gpt6_sol_high",
|
|
128
131
|
timeoutSec: 1440,
|
|
129
132
|
runMode: "bg",
|
|
130
133
|
opusOversight: false,
|
|
@@ -132,7 +135,7 @@ const policy = {
|
|
|
132
135
|
subcommand: "exec",
|
|
133
136
|
},
|
|
134
137
|
"scientist-deep": {
|
|
135
|
-
profile: "
|
|
138
|
+
profile: "gpt6_astra_xhigh",
|
|
136
139
|
timeoutSec: 3600,
|
|
137
140
|
runMode: "bg",
|
|
138
141
|
opusOversight: false,
|
|
@@ -140,7 +143,7 @@ const policy = {
|
|
|
140
143
|
subcommand: "exec",
|
|
141
144
|
},
|
|
142
145
|
verifier: {
|
|
143
|
-
profile: "
|
|
146
|
+
profile: "gpt6_sol_high",
|
|
144
147
|
timeoutSec: 1200,
|
|
145
148
|
runMode: "fg",
|
|
146
149
|
opusOversight: false,
|
|
@@ -148,7 +151,7 @@ const policy = {
|
|
|
148
151
|
subcommand: "review",
|
|
149
152
|
},
|
|
150
153
|
"test-engineer": {
|
|
151
|
-
profile: "
|
|
154
|
+
profile: "gpt6_sol_high",
|
|
152
155
|
timeoutSec: 1200,
|
|
153
156
|
runMode: "bg",
|
|
154
157
|
opusOversight: false,
|
|
@@ -156,7 +159,7 @@ const policy = {
|
|
|
156
159
|
subcommand: "exec",
|
|
157
160
|
},
|
|
158
161
|
"qa-tester": {
|
|
159
|
-
profile: "
|
|
162
|
+
profile: "gpt6_sol_high",
|
|
160
163
|
timeoutSec: 1200,
|
|
161
164
|
runMode: "bg",
|
|
162
165
|
opusOversight: false,
|
|
@@ -164,7 +167,7 @@ const policy = {
|
|
|
164
167
|
subcommand: "review",
|
|
165
168
|
},
|
|
166
169
|
spark: {
|
|
167
|
-
profile: "
|
|
170
|
+
profile: "gpt6_luna_low",
|
|
168
171
|
timeoutSec: 180,
|
|
169
172
|
runMode: "fg",
|
|
170
173
|
opusOversight: false,
|
|
@@ -174,7 +177,7 @@ const policy = {
|
|
|
174
177
|
// These entries are only for explicit direct-Codex overrides. agent-map.json
|
|
175
178
|
// remains the provider-selection authority for their normal execution.
|
|
176
179
|
designer: {
|
|
177
|
-
profile: "
|
|
180
|
+
profile: "gpt6_astra_xhigh",
|
|
178
181
|
timeoutSec: 900,
|
|
179
182
|
runMode: "bg",
|
|
180
183
|
opusOversight: false,
|
|
@@ -182,7 +185,7 @@ const policy = {
|
|
|
182
185
|
subcommand: "exec",
|
|
183
186
|
},
|
|
184
187
|
writer: {
|
|
185
|
-
profile: "
|
|
188
|
+
profile: "gpt6_luna_high",
|
|
186
189
|
timeoutSec: 900,
|
|
187
190
|
runMode: "bg",
|
|
188
191
|
opusOversight: false,
|
|
@@ -207,12 +210,13 @@ export const DEFAULT_CODEX_AGENT = "executor";
|
|
|
207
210
|
|
|
208
211
|
export const CANONICAL_CODEX_PROFILE_OVERRIDES = Object.freeze(
|
|
209
212
|
new Set([
|
|
210
|
-
"
|
|
211
|
-
"
|
|
212
|
-
"
|
|
213
|
-
"
|
|
214
|
-
"
|
|
215
|
-
"
|
|
213
|
+
"gpt6_luna_low",
|
|
214
|
+
"gpt6_luna_high",
|
|
215
|
+
"gpt6_sol_med",
|
|
216
|
+
"gpt6_sol_high",
|
|
217
|
+
"gpt6_astra_xhigh",
|
|
218
|
+
"gpt6_astra_max",
|
|
219
|
+
"gpt6_astra_ultra",
|
|
216
220
|
]),
|
|
217
221
|
);
|
|
218
222
|
export const ULTRA_ELIGIBLE_CODEX_AGENTS = Object.freeze(
|
|
@@ -222,8 +226,8 @@ export const ULTRA_ELIGIBLE_CODEX_AGENTS = Object.freeze(
|
|
|
222
226
|
const NESTED_GLOBAL_PROFILE_OVERRIDES = new Set([
|
|
223
227
|
"max",
|
|
224
228
|
"ultra",
|
|
225
|
-
"
|
|
226
|
-
"
|
|
229
|
+
"gpt6_astra_max",
|
|
230
|
+
"gpt6_astra_ultra",
|
|
227
231
|
]);
|
|
228
232
|
|
|
229
233
|
export function resolveCodexAgentPolicy(agent) {
|
|
@@ -251,14 +255,16 @@ export function resolveCodexAgentProfile(
|
|
|
251
255
|
) {
|
|
252
256
|
const defaultProfile = resolveCodexAgentPolicy(agent).profile;
|
|
253
257
|
const retryRequested = String(retryProfile ?? "").trim();
|
|
254
|
-
const requested =
|
|
258
|
+
const requested = normalizeCodexProfileName(
|
|
259
|
+
retryRequested || String(profileOverride || "auto").trim(),
|
|
260
|
+
);
|
|
255
261
|
if (!requested || requested === "auto") return defaultProfile;
|
|
256
262
|
|
|
257
263
|
const canonical =
|
|
258
264
|
requested === "max"
|
|
259
|
-
? "
|
|
265
|
+
? "gpt6_astra_max"
|
|
260
266
|
: requested === "ultra"
|
|
261
|
-
? "
|
|
267
|
+
? "gpt6_astra_ultra"
|
|
262
268
|
: requested;
|
|
263
269
|
if (!CANONICAL_CODEX_PROFILE_OVERRIDES.has(canonical)) {
|
|
264
270
|
if (allowCustom) return requested;
|
|
@@ -266,9 +272,9 @@ export function resolveCodexAgentProfile(
|
|
|
266
272
|
`[agent-route-policy] unsupported profile override: ${requested}`,
|
|
267
273
|
);
|
|
268
274
|
}
|
|
269
|
-
if (canonical !== "
|
|
275
|
+
if (canonical !== "gpt6_astra_ultra") return canonical;
|
|
270
276
|
return nested || !ULTRA_ELIGIBLE_CODEX_AGENTS.has(agent)
|
|
271
|
-
? "
|
|
277
|
+
? "gpt6_astra_max"
|
|
272
278
|
: canonical;
|
|
273
279
|
}
|
|
274
280
|
|
|
@@ -287,7 +293,9 @@ export function resolveNestedCodexAgentProfile(
|
|
|
287
293
|
} = {},
|
|
288
294
|
) {
|
|
289
295
|
const explicitProfile = String(profileOverride || "auto").trim();
|
|
290
|
-
const globalOverride =
|
|
296
|
+
const globalOverride = normalizeCodexProfileName(
|
|
297
|
+
String(globalProfile || "auto").trim(),
|
|
298
|
+
);
|
|
291
299
|
// Headless lanes must select their role policy explicitly. Only the max and
|
|
292
300
|
// ultra exception lanes may cross the process environment boundary.
|
|
293
301
|
const effectiveOverride =
|
|
@@ -305,7 +313,7 @@ export function resolveNestedCodexAgentProfile(
|
|
|
305
313
|
});
|
|
306
314
|
const { effort } = resolveCodexProfileConfigValues(candidate, { codexHome });
|
|
307
315
|
if (!effort) return fallback;
|
|
308
|
-
return effort.toLowerCase() === "ultra" ? "
|
|
316
|
+
return effort.toLowerCase() === "ultra" ? "gpt6_astra_max" : candidate;
|
|
309
317
|
}
|
|
310
318
|
|
|
311
319
|
export function describeCodexAgentPolicy() {
|
package/scripts/lib/cli-agy.mjs
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
// cli-agy.mjs — Antigravity (agy) CLI adapter (Phase 0 PoC).
|
|
2
2
|
//
|
|
3
|
-
// 책임: agy --print 는
|
|
4
|
-
//
|
|
3
|
+
// 책임: agy 1.1.27 부터 --print 는 값(프롬프트)이 필수이고 stdin 프롬프트는 거부되므로
|
|
4
|
+
// plan() 은 프롬프트를 args 의 --print 값으로 넣고 stdinMode="argv" 를 돌려준다.
|
|
5
|
+
// --print 뒤에 다른 플래그가 오면 그 플래그를 프롬프트로 삼키므로 항상 마지막에 둔다.
|
|
5
6
|
//
|
|
6
7
|
// 출처: scripts/tfx-route.sh route_agent() L1052-L1059, run_codex_exec() L2036-L2046.
|
|
7
8
|
// .claude/rules/tfx-update-logic.md Antigravity CLI 1.0.0 정밀 sanity matrix.
|
|
8
9
|
// timeoutSec은 lane 예상 소요 시간(advisory)이다. hard ceiling 집행은 Bash route가 소유한다.
|
|
9
10
|
|
|
11
|
+
import {
|
|
12
|
+
resolveGeminiModel,
|
|
13
|
+
resolveGeminiProfileForPurpose,
|
|
14
|
+
} from "./gemini-profiles.mjs";
|
|
15
|
+
|
|
10
16
|
export const id = "agy";
|
|
11
17
|
export const cliType = "antigravity";
|
|
12
18
|
export const command = "agy";
|
|
@@ -38,6 +44,7 @@ export function plan({
|
|
|
38
44
|
mcpProfile = "auto",
|
|
39
45
|
timeoutSec,
|
|
40
46
|
contextFile,
|
|
47
|
+
geminiProfilesPath,
|
|
41
48
|
} = {}) {
|
|
42
49
|
if (!agent) {
|
|
43
50
|
throw new Error("[cli-agy] agent required");
|
|
@@ -49,8 +56,21 @@ export function plan({
|
|
|
49
56
|
command,
|
|
50
57
|
profile: cfg.profile,
|
|
51
58
|
effort: cfg.profile,
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
// effort 는 역할별 SSOT(gemini-profiles.mjs): designer → High, writer → Medium ...
|
|
60
|
+
geminiProfile: resolveGeminiProfileForPurpose(agent),
|
|
61
|
+
model: resolveGeminiModel(resolveGeminiProfileForPurpose(agent), {
|
|
62
|
+
profilesPath: geminiProfilesPath,
|
|
63
|
+
}),
|
|
64
|
+
args: [
|
|
65
|
+
"--dangerously-skip-permissions",
|
|
66
|
+
"--model",
|
|
67
|
+
resolveGeminiModel(resolveGeminiProfileForPurpose(agent), {
|
|
68
|
+
profilesPath: geminiProfilesPath,
|
|
69
|
+
}),
|
|
70
|
+
"--print",
|
|
71
|
+
prompt,
|
|
72
|
+
],
|
|
73
|
+
stdinMode: "argv",
|
|
54
74
|
timeoutMs: effectiveTimeoutSec * 1000,
|
|
55
75
|
runMode: cfg.runMode,
|
|
56
76
|
opusOversight: cfg.opusOversight,
|
|
@@ -19,14 +19,39 @@ const EFFORT_BY_SUFFIX = {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
const CANONICAL_PROFILE_VALUES = Object.freeze({
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
gpt6_luna_low: { model: "gpt-6-luna", effort: "low" },
|
|
23
|
+
gpt6_luna_high: { model: "gpt-6-luna", effort: "high" },
|
|
24
|
+
gpt6_sol_med: { model: "gpt-6-sol", effort: "medium" },
|
|
25
|
+
gpt6_sol_high: { model: "gpt-6-sol", effort: "high" },
|
|
26
|
+
gpt6_astra_xhigh: { model: "gpt-6-astra", effort: "xhigh" },
|
|
27
|
+
gpt6_astra_max: { model: "gpt-6-astra", effort: "max" },
|
|
28
|
+
gpt6_astra_ultra: { model: "gpt-6-astra", effort: "ultra" },
|
|
28
29
|
});
|
|
29
30
|
|
|
31
|
+
// GPT-5.6 lane names map to the GPT-6 lane with the same effort. GPT-6 has no
|
|
32
|
+
// Terra tier, so Terra lanes move to Sol.
|
|
33
|
+
const LEGACY_CANONICAL_PROFILE_ALIASES = Object.freeze({
|
|
34
|
+
gpt56_sol_xhigh: "gpt6_astra_xhigh",
|
|
35
|
+
gpt56_sol_max: "gpt6_astra_max",
|
|
36
|
+
gpt56_sol_ultra: "gpt6_astra_ultra",
|
|
37
|
+
gpt56_terra_high: "gpt6_sol_high",
|
|
38
|
+
gpt56_terra_med: "gpt6_sol_med",
|
|
39
|
+
gpt56_luna_low: "gpt6_luna_low",
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export function normalizeCodexProfileName(profileName) {
|
|
43
|
+
const normalized = String(profileName ?? "").trim();
|
|
44
|
+
return LEGACY_CANONICAL_PROFILE_ALIASES[normalized] || normalized;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Model ID of a canonical profile (after legacy normalization), or null. */
|
|
48
|
+
export function canonicalCodexProfileModel(profileName) {
|
|
49
|
+
return (
|
|
50
|
+
CANONICAL_PROFILE_VALUES[normalizeCodexProfileName(profileName)]?.model ??
|
|
51
|
+
null
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
30
55
|
function readProfileScalar(raw, key) {
|
|
31
56
|
const match = String(raw).match(
|
|
32
57
|
new RegExp(
|
|
@@ -40,7 +65,7 @@ function readProfileScalar(raw, key) {
|
|
|
40
65
|
}
|
|
41
66
|
|
|
42
67
|
/**
|
|
43
|
-
* Resolve a Codex effort profile name (e.g. "
|
|
68
|
+
* Resolve a Codex effort profile name (e.g. "gpt6_sol_high") to the `-c key=value`
|
|
44
69
|
* config overrides that `codex exec` accepts, so the headless CLI lanes can
|
|
45
70
|
* select a profile WITHOUT `codex exec --profile <name>`. codex 0.134+ rejects
|
|
46
71
|
* `--profile X` whenever config.toml still contains an inline `[profiles.X]`
|
|
@@ -58,38 +83,45 @@ function readProfileScalar(raw, key) {
|
|
|
58
83
|
*
|
|
59
84
|
* @param {string} profileName
|
|
60
85
|
* @param {{ codexHome?: string }} [opts]
|
|
61
|
-
* @returns {string[]} e.g. ['model="gpt-
|
|
86
|
+
* @returns {string[]} e.g. ['model="gpt-6-sol"', 'model_reasoning_effort="high"']
|
|
62
87
|
*/
|
|
63
88
|
export function resolveCodexProfileConfigValues(profileName, opts = {}) {
|
|
64
89
|
if (typeof profileName !== "string" || !profileName) {
|
|
65
90
|
return { model: null, effort: null };
|
|
66
91
|
}
|
|
92
|
+
const normalizedProfileName = normalizeCodexProfileName(profileName);
|
|
67
93
|
const codexHome =
|
|
68
94
|
opts.codexHome || process.env.CODEX_HOME || join(homedir(), ".codex");
|
|
69
95
|
let model = null;
|
|
70
96
|
let effort = null;
|
|
71
97
|
try {
|
|
72
98
|
const raw = readFileSync(
|
|
73
|
-
join(codexHome, `${
|
|
99
|
+
join(codexHome, `${normalizedProfileName}.config.toml`),
|
|
74
100
|
"utf8",
|
|
75
101
|
);
|
|
76
102
|
model = readProfileScalar(raw, "model");
|
|
77
103
|
effort = readProfileScalar(raw, "model_reasoning_effort");
|
|
78
104
|
} catch {
|
|
79
|
-
const suffix = /_(ultra|max|xhigh|high|med|medium|low)$/.exec(
|
|
105
|
+
const suffix = /_(ultra|max|xhigh|high|med|medium|low)$/.exec(
|
|
106
|
+
normalizedProfileName,
|
|
107
|
+
);
|
|
80
108
|
if (suffix) effort = EFFORT_BY_SUFFIX[suffix[1]] || null;
|
|
81
109
|
}
|
|
82
110
|
return { model, effort };
|
|
83
111
|
}
|
|
84
112
|
|
|
85
113
|
export function codexProfileConfigOverrides(profileName, opts = {}) {
|
|
86
|
-
|
|
114
|
+
const normalizedProfileName = normalizeCodexProfileName(profileName);
|
|
115
|
+
let { model, effort } = resolveCodexProfileConfigValues(
|
|
116
|
+
normalizedProfileName,
|
|
117
|
+
opts,
|
|
118
|
+
);
|
|
87
119
|
if (opts.enforceCanonicalProfile === true) {
|
|
88
|
-
const canonical = CANONICAL_PROFILE_VALUES[
|
|
120
|
+
const canonical = CANONICAL_PROFILE_VALUES[normalizedProfileName];
|
|
89
121
|
if (canonical) ({ model, effort } = canonical);
|
|
90
122
|
}
|
|
91
123
|
if (opts.disallowUltra === true && effort?.toLowerCase() === "ultra") {
|
|
92
|
-
model = "gpt-
|
|
124
|
+
model = "gpt-6-astra";
|
|
93
125
|
effort = "max";
|
|
94
126
|
}
|
|
95
127
|
const overrides = [];
|