@triflux/core 10.51.0 → 10.52.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/hub/bridge.mjs +65 -1172
- package/hub/index.mjs +2 -18
- package/hub/lib/process-utils.mjs +1 -33
- package/hub/team/claude-daemon-control.mjs +1 -2
- package/hub/team/claude-session-projection.mjs +5 -73
- package/hub/team/nativeProxy.mjs +759 -0
- package/hub/team/session-context.mjs +1 -1
- package/hud/constants.mjs +2 -0
- package/hud/hud-qos-status.mjs +21 -5
- package/hud/providers/gemini.mjs +20 -0
- package/hud/renderers.mjs +79 -46
- package/hud/utils.mjs +9 -5
- package/package.json +2 -4
- package/scripts/lib/agent-route-policy.mjs +0 -67
- package/scripts/lib/cli-claude.mjs +0 -12
- package/scripts/lib/env-probe.mjs +0 -70
- package/scripts/lib/legacy-mcp-cleanup.mjs +283 -0
- package/scripts/lib/mcp-guard-engine.mjs +40 -98
- package/scripts/lib/session-presence.mjs +1 -99
- package/hub/adaptive-diagnostic.mjs +0 -350
- package/hub/adaptive-inject.mjs +0 -224
- package/hub/adaptive-memory.mjs +0 -277
- package/hub/adaptive.mjs +0 -172
- package/hub/assign-callbacks.mjs +0 -170
- package/hub/delegator/contracts.mjs +0 -38
- package/hub/delegator/index.mjs +0 -14
- package/hub/delegator/schema/delegator-tools.schema.json +0 -250
- package/hub/delegator/service.mjs +0 -336
- package/hub/delegator/tool-definitions.mjs +0 -35
- package/hub/hitl.mjs +0 -202
- package/hub/lib/known-errors.json +0 -72
- package/hub/lib/memory-store.mjs +0 -1001
- package/hub/lib/phase-manager.mjs +0 -493
- package/hub/lib/state-snapshot.mjs +0 -293
- package/hub/lib/trace-recorder.mjs +0 -153
- package/hub/lib/uuidv7.mjs +0 -45
- package/hub/memory-doctor.mjs +0 -640
- package/hub/middleware/quota-middleware.mjs +0 -70
- package/hub/middleware/request-logger.mjs +0 -191
- package/hub/paths.mjs +0 -24
- package/hub/pipeline/index.mjs +0 -163
- package/hub/pipeline/state.mjs +0 -191
- package/hub/pipeline/transitions.mjs +0 -131
- package/hub/reflexion.mjs +0 -290
- package/hub/role-contract.mjs +0 -312
- package/hub/router.mjs +0 -2026
- package/hub/session-fingerprint.mjs +0 -418
- package/hub/state.mjs +0 -300
- package/hub/team/synapse-http.mjs +0 -311
- package/hub/team-bridge.mjs +0 -27
- package/scripts/lib/claudemd-scanner.mjs +0 -26
- package/scripts/lib/context.mjs +0 -51
- package/scripts/lib/handoff.mjs +0 -187
- package/scripts/lib/logger.mjs +0 -122
- package/scripts/lib/stealth-fetch.mjs +0 -176
|
@@ -96,7 +96,7 @@ export function contextGuard(
|
|
|
96
96
|
: {};
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
async function findCodexRollout(threadId) {
|
|
99
|
+
export async function findCodexRollout(threadId) {
|
|
100
100
|
if (!/^[a-zA-Z0-9-]+$/u.test(threadId || "")) return null;
|
|
101
101
|
const root = path.join(
|
|
102
102
|
process.env.CODEX_HOME || path.join(homedir(), ".codex"),
|
package/hud/constants.mjs
CHANGED
|
@@ -171,6 +171,8 @@ export const ANTIGRAVITY_REFRESH_LOCK_PATH = join(
|
|
|
171
171
|
".antigravity-refresh-lock",
|
|
172
172
|
);
|
|
173
173
|
export const ANTIGRAVITY_QUOTA_STALE_MS = 5 * 60 * 1000;
|
|
174
|
+
// 조회가 잠시 실패해도 이 시간 안에 성공한 적이 있으면 로그인 상태로 본다.
|
|
175
|
+
export const ANTIGRAVITY_SIGNED_IN_GRACE_MS = 60 * 60 * 1000;
|
|
174
176
|
export const ANTIGRAVITY_REFRESH_FLAG = "--refresh-antigravity-quota";
|
|
175
177
|
export const ACCOUNT_LABEL_WIDTH = 10;
|
|
176
178
|
export const PROVIDER_PREFIX_WIDTH = 2;
|
package/hud/hud-qos-status.mjs
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
CLAUDE_BAND_MARKER_DIR,
|
|
21
21
|
CLAUDE_BAND_MARKER_TTL_MS,
|
|
22
22
|
CLAUDE_REFRESH_FLAG,
|
|
23
|
+
CODEX_AUTH_PATH,
|
|
23
24
|
CODEX_REFRESH_FLAG,
|
|
24
25
|
} from "./constants.mjs";
|
|
25
26
|
import { buildContextUsageView } from "./context-monitor.mjs";
|
|
@@ -37,6 +38,7 @@ import {
|
|
|
37
38
|
} from "./providers/codex.mjs";
|
|
38
39
|
import {
|
|
39
40
|
getAntigravityAccountLabel,
|
|
41
|
+
getAntigravityAuthKind,
|
|
40
42
|
readAntigravityQuotaSnapshot,
|
|
41
43
|
refreshAntigravityQuotaCache,
|
|
42
44
|
scheduleAntigravityQuotaRefresh,
|
|
@@ -48,7 +50,12 @@ import {
|
|
|
48
50
|
renderAlignedRows,
|
|
49
51
|
} from "./renderers.mjs";
|
|
50
52
|
import { selectTier } from "./terminal.mjs";
|
|
51
|
-
import {
|
|
53
|
+
import {
|
|
54
|
+
formatTimeCell,
|
|
55
|
+
formatTimeCellDH,
|
|
56
|
+
readJson,
|
|
57
|
+
readStdinJson,
|
|
58
|
+
} from "./utils.mjs";
|
|
52
59
|
|
|
53
60
|
async function main() {
|
|
54
61
|
if (process.argv.includes(CLAUDE_REFRESH_FLAG)) {
|
|
@@ -95,12 +102,15 @@ async function main() {
|
|
|
95
102
|
? { ...claudeUsageSnapshot.data, stale: claudeUsageSnapshot.isStale }
|
|
96
103
|
: null;
|
|
97
104
|
const codexBuckets = codexSnapshot.buckets;
|
|
105
|
+
const antigravityQuota = antigravityAllowed
|
|
106
|
+
? { ...antigravitySnapshot?.data, auth: getAntigravityAuthKind() }
|
|
107
|
+
: null;
|
|
98
108
|
const currentTier = selectTier();
|
|
99
109
|
if (currentTier === "nano") {
|
|
100
110
|
const microLine = getMicroLine(contextView, claudeUsage, codexBuckets, {
|
|
101
111
|
showCodex,
|
|
102
112
|
showAntigravity: antigravityAllowed,
|
|
103
|
-
antigravityQuota
|
|
113
|
+
antigravityQuota,
|
|
104
114
|
});
|
|
105
115
|
process.stdout.write(`\x1b[0m${microLine}\n`);
|
|
106
116
|
return;
|
|
@@ -134,14 +144,20 @@ async function main() {
|
|
|
134
144
|
geminiBlue,
|
|
135
145
|
accountsConfig,
|
|
136
146
|
accountsState,
|
|
137
|
-
|
|
147
|
+
antigravityQuota,
|
|
138
148
|
getAntigravityAccountLabel(),
|
|
139
149
|
),
|
|
140
150
|
);
|
|
141
151
|
}
|
|
142
152
|
|
|
143
153
|
const outputLines = renderAlignedRows(rows);
|
|
144
|
-
|
|
154
|
+
// 회색은 로그인 안 된 경우에만 쓴다. 로그인 상태의 조회 공백은 --% 로만 보인다.
|
|
155
|
+
if (
|
|
156
|
+
outputLines[codexRowIndex] != null &&
|
|
157
|
+
!codexBuckets &&
|
|
158
|
+
!existsSync(CODEX_AUTH_PATH) &&
|
|
159
|
+
!hasBrokerCodexAccounts()
|
|
160
|
+
) {
|
|
145
161
|
outputLines[codexRowIndex] = `${DIM}${outputLines[codexRowIndex]}${RESET}`;
|
|
146
162
|
}
|
|
147
163
|
// 알림 배너와 TUI 스타일이 HUD 내용에 겹치지 않도록 한다.
|
|
@@ -152,7 +168,7 @@ async function main() {
|
|
|
152
168
|
|
|
153
169
|
main().catch(() => {
|
|
154
170
|
process.stdout.write(
|
|
155
|
-
`\x1b[0m${bold(claudeOrange("c"))}: ${dim(
|
|
171
|
+
`\x1b[0m${bold(claudeOrange("c"))}: ${dim(`5h:--% ${formatTimeCell("")} 1w:--% ${formatTimeCellDH("")} | CTX:--%`)}\n`,
|
|
156
172
|
);
|
|
157
173
|
});
|
|
158
174
|
|
package/hud/providers/gemini.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
ANTIGRAVITY_REFRESH_FLAG,
|
|
8
8
|
ANTIGRAVITY_REFRESH_LOCK_PATH,
|
|
9
9
|
ANTIGRAVITY_SETTINGS_PATH,
|
|
10
|
+
ANTIGRAVITY_SIGNED_IN_GRACE_MS,
|
|
10
11
|
SPAWN_LOCK_TTL_MS,
|
|
11
12
|
} from "../constants.mjs";
|
|
12
13
|
import { decodeJwtEmail, readJson, writeJsonSafe } from "../utils.mjs";
|
|
@@ -41,6 +42,18 @@ function isGcpProjectAuth() {
|
|
|
41
42
|
return Boolean(readJson(ANTIGRAVITY_SETTINGS_PATH, null)?.gcp?.project);
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
// Keychain 인증은 파일을 남기지 않으므로 최근 쿼터 조회 성공도 로그인 근거로 본다.
|
|
46
|
+
export function getAntigravityAuthKind() {
|
|
47
|
+
if (isGcpProjectAuth()) return "project";
|
|
48
|
+
if (getAntigravityAccountLabel()) return "account";
|
|
49
|
+
const cache = readJson(ANTIGRAVITY_QUOTA_CACHE_PATH, null);
|
|
50
|
+
const signedInAge = Date.now() - Number(cache?.signedInAt);
|
|
51
|
+
return cache?.accountLabel == null &&
|
|
52
|
+
signedInAge < ANTIGRAVITY_SIGNED_IN_GRACE_MS
|
|
53
|
+
? "account"
|
|
54
|
+
: null;
|
|
55
|
+
}
|
|
56
|
+
|
|
44
57
|
export function readAntigravityQuotaSnapshot() {
|
|
45
58
|
// 프로젝트 과금의 기본 응답을 개인 플랜의 0% 사용률로 표시하지 않는다.
|
|
46
59
|
if (isGcpProjectAuth()) return { data: null, shouldRefresh: false };
|
|
@@ -103,10 +116,17 @@ export function refreshAntigravityQuotaCache(execFileSyncFn = execFileSync) {
|
|
|
103
116
|
// 실패도 캐시해 인증 오류나 CLI 부재 시 매 렌더마다 실행하지 않는다.
|
|
104
117
|
}
|
|
105
118
|
if (accountLabel === getAntigravityAccountLabel()) {
|
|
119
|
+
const previous = readJson(ANTIGRAVITY_QUOTA_CACHE_PATH, null);
|
|
120
|
+
const signedInAt = buckets
|
|
121
|
+
? Date.now()
|
|
122
|
+
: previous?.accountLabel === accountLabel
|
|
123
|
+
? previous?.signedInAt
|
|
124
|
+
: undefined;
|
|
106
125
|
writeJsonSafe(ANTIGRAVITY_QUOTA_CACHE_PATH, {
|
|
107
126
|
timestamp: Date.now(),
|
|
108
127
|
accountLabel,
|
|
109
128
|
buckets,
|
|
129
|
+
signedInAt,
|
|
110
130
|
});
|
|
111
131
|
}
|
|
112
132
|
return buckets;
|
package/hud/renderers.mjs
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
PERCENT_CELL_WIDTH,
|
|
23
23
|
PROVIDER_PREFIX_WIDTH,
|
|
24
24
|
SEVEN_DAY_MS,
|
|
25
|
+
TIME_CELL_INNER_WIDTH,
|
|
25
26
|
} from "./constants.mjs";
|
|
26
27
|
import { buildContextUsageView } from "./context-monitor.mjs";
|
|
27
28
|
import { getTerminalColumns, tierBar, tierDimBar } from "./terminal.mjs";
|
|
@@ -124,7 +125,9 @@ export function getMicroLine(
|
|
|
124
125
|
segments.push(`${bold(codexWhite("x"))}${dim(":")}${xVal}`);
|
|
125
126
|
}
|
|
126
127
|
if (showAntigravity) {
|
|
127
|
-
const marker = options.antigravityQuota
|
|
128
|
+
const marker = options.antigravityQuota?.auth
|
|
129
|
+
? bold(geminiBlue("a"))
|
|
130
|
+
: dim("a");
|
|
128
131
|
segments.push(
|
|
129
132
|
`${marker}${dim(":")}${antigravityPercentText(options.antigravityQuota)}${options.antigravityQuota?.stale ? dim("*") : ""}`,
|
|
130
133
|
);
|
|
@@ -134,19 +137,22 @@ export function getMicroLine(
|
|
|
134
137
|
}
|
|
135
138
|
|
|
136
139
|
function antigravityPercentText(quota) {
|
|
140
|
+
if (quota?.auth === "project") {
|
|
141
|
+
return geminiBlue("GCP".padStart(PERCENT_CELL_WIDTH));
|
|
142
|
+
}
|
|
137
143
|
return quota?.usedPercent != null
|
|
138
144
|
? colorByProvider(
|
|
139
145
|
quota.usedPercent,
|
|
140
146
|
formatPercentCell(quota.usedPercent),
|
|
141
147
|
geminiBlue,
|
|
142
148
|
)
|
|
143
|
-
: dim(
|
|
149
|
+
: dim(formatPlaceholderPercentCell());
|
|
144
150
|
}
|
|
145
151
|
|
|
146
152
|
// context 는 토큰 수 대신 사용률만 보여 준다.
|
|
147
153
|
function contextPercentText(ctxView) {
|
|
148
|
-
|
|
149
|
-
return colorByPercent(ctxView.percent,
|
|
154
|
+
if (ctxView.display === "--") return dim("--%");
|
|
155
|
+
return colorByPercent(ctxView.percent, `${ctxView.percent}%`);
|
|
150
156
|
}
|
|
151
157
|
|
|
152
158
|
// ============================================================================
|
|
@@ -160,10 +166,10 @@ export function getClaudeRows(currentTier, contextView, claudeUsage) {
|
|
|
160
166
|
const weeklyPercent = claudeUsage?.weeklyPercent ?? null;
|
|
161
167
|
const fiveHourReset = claudeUsage?.fiveHourResetsAt
|
|
162
168
|
? formatResetRemaining(claudeUsage.fiveHourResetsAt, FIVE_HOUR_MS)
|
|
163
|
-
: "
|
|
169
|
+
: "";
|
|
164
170
|
const weeklyReset = claudeUsage?.weeklyResetsAt
|
|
165
171
|
? formatResetRemainingDayHour(claudeUsage.weeklyResetsAt, SEVEN_DAY_MS)
|
|
166
|
-
: "
|
|
172
|
+
: "";
|
|
167
173
|
|
|
168
174
|
const hasData = claudeUsage != null;
|
|
169
175
|
|
|
@@ -198,11 +204,11 @@ export function getClaudeRows(currentTier, contextView, claudeUsage) {
|
|
|
198
204
|
const fShort =
|
|
199
205
|
hasData && fiveHourPercent != null
|
|
200
206
|
? colorByProvider(fiveHourPercent, `${fiveHourPercent}%`, claudeOrange)
|
|
201
|
-
: dim("
|
|
207
|
+
: dim("--%");
|
|
202
208
|
const wShort =
|
|
203
209
|
hasData && weeklyPercent != null
|
|
204
210
|
? colorByProvider(weeklyPercent, `${weeklyPercent}%`, claudeOrange)
|
|
205
|
-
: dim("
|
|
211
|
+
: dim("--%");
|
|
206
212
|
const quotaSection = `${fShort}${dim("/")}${wShort}`;
|
|
207
213
|
return [{ prefix, left: quotaSection, right: "" }];
|
|
208
214
|
}
|
|
@@ -274,34 +280,13 @@ export function getProviderRow(
|
|
|
274
280
|
|
|
275
281
|
const prefix = `${bold(markerColor(marker))}:`;
|
|
276
282
|
if (provider === "antigravity") {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
left: quotaPercent,
|
|
285
|
-
right,
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
const bar = active
|
|
289
|
-
? tierBar(currentTier, usedPercent, GEMINI_BLUE)
|
|
290
|
-
: currentTier === "full"
|
|
291
|
-
? " ".repeat(GAUGE_WIDTH + 1)
|
|
292
|
-
: "";
|
|
293
|
-
const reset =
|
|
294
|
-
(Date.parse(realQuota?.resetTime) - Date.now() >= ONE_DAY_MS
|
|
295
|
-
? formatResetRemainingDayHour(realQuota.resetTime)
|
|
296
|
-
: formatResetRemaining(realQuota?.resetTime)) || "n/a";
|
|
297
|
-
const showTime = currentTier === "full" || currentTier === "compact";
|
|
298
|
-
// /usage의 모델별 값에는 5h/1w 식별자가 없으므로 창을 추측하지 않는다.
|
|
299
|
-
const slot = `${dim("--:")}${bar}${quotaPercent}${showTime ? ` ${dim(formatTimeCell(reset))}` : ""}`;
|
|
300
|
-
return {
|
|
301
|
-
prefix: active ? prefix : dim(`${marker}:`),
|
|
302
|
-
left: `${slot} ${" ".repeat(stripAnsi(slot).length)}`,
|
|
303
|
-
right,
|
|
304
|
-
};
|
|
283
|
+
return getAntigravityRow(
|
|
284
|
+
currentTier,
|
|
285
|
+
marker,
|
|
286
|
+
markerColor,
|
|
287
|
+
accountLabel,
|
|
288
|
+
realQuota,
|
|
289
|
+
);
|
|
305
290
|
}
|
|
306
291
|
const provAnsi = CODEX_WHITE;
|
|
307
292
|
const provFn = codexWhite;
|
|
@@ -337,7 +322,7 @@ export function getProviderRow(
|
|
|
337
322
|
};
|
|
338
323
|
}
|
|
339
324
|
}
|
|
340
|
-
return { prefix: minPrefix, left: dim("
|
|
325
|
+
return { prefix: minPrefix, left: dim("--%/--%"), right: "" };
|
|
341
326
|
}
|
|
342
327
|
|
|
343
328
|
if (currentTier === "minimal") {
|
|
@@ -397,16 +382,16 @@ export function getProviderRow(
|
|
|
397
382
|
weekP != null
|
|
398
383
|
? colorByProvider(weekP, formatPercentCell(weekP), provFn)
|
|
399
384
|
: dim(formatPlaceholderPercentCell());
|
|
400
|
-
const fiveReset =
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
385
|
+
const fiveReset = formatResetRemaining(main.primary?.resets_at);
|
|
386
|
+
const weekReset = formatResetRemainingDayHour(
|
|
387
|
+
main.secondary?.resets_at,
|
|
388
|
+
);
|
|
404
389
|
quotaSection = `${dim("5h:")}${fCell} ${dim(formatTimeCell(fiveReset))} ${dim("1w:")}${wCell} ${dim(formatTimeCellDH(weekReset))}`;
|
|
405
390
|
if (main.mixedWindows) quotaSection += dim("*");
|
|
406
391
|
}
|
|
407
392
|
}
|
|
408
393
|
if (!quotaSection) {
|
|
409
|
-
quotaSection = `${dim("5h:")}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCell("
|
|
394
|
+
quotaSection = `${dim("5h:")}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCell(""))} ${dim("1w:")}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCellDH(""))}`;
|
|
410
395
|
}
|
|
411
396
|
const compactRight = [accountLabel ? markerColor(accountLabel) : ""]
|
|
412
397
|
.filter(Boolean)
|
|
@@ -429,9 +414,8 @@ export function getProviderRow(
|
|
|
429
414
|
main.secondary?.used_percent != null
|
|
430
415
|
? clampPercent(main.secondary.used_percent)
|
|
431
416
|
: null;
|
|
432
|
-
const fiveReset = formatResetRemaining(main.primary?.resets_at)
|
|
433
|
-
const weekReset =
|
|
434
|
-
formatResetRemainingDayHour(main.secondary?.resets_at) || "n/a";
|
|
417
|
+
const fiveReset = formatResetRemaining(main.primary?.resets_at);
|
|
418
|
+
const weekReset = formatResetRemainingDayHour(main.secondary?.resets_at);
|
|
435
419
|
const fCell =
|
|
436
420
|
fiveP != null
|
|
437
421
|
? colorByProvider(fiveP, formatPercentCell(fiveP), provFn)
|
|
@@ -459,7 +443,7 @@ export function getProviderRow(
|
|
|
459
443
|
|
|
460
444
|
// 폴백
|
|
461
445
|
if (!quotaSection) {
|
|
462
|
-
quotaSection = `${dim("5h:")}${tierDimBar(currentTier)}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCell("
|
|
446
|
+
quotaSection = `${dim("5h:")}${tierDimBar(currentTier)}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCell(""))} ${dim("1w:")}${tierDimBar(currentTier)}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCellDH(""))}`;
|
|
463
447
|
}
|
|
464
448
|
|
|
465
449
|
const accountSection = `${markerColor(accountLabel)}`;
|
|
@@ -469,3 +453,52 @@ export function getProviderRow(
|
|
|
469
453
|
right: accountSection,
|
|
470
454
|
};
|
|
471
455
|
}
|
|
456
|
+
|
|
457
|
+
// 회색은 로그인 안 된 경우에만 쓴다. GCP 프로젝트 과금은 개인 쿼터가 없을 뿐 정상 상태다.
|
|
458
|
+
function getAntigravityRow(
|
|
459
|
+
currentTier,
|
|
460
|
+
marker,
|
|
461
|
+
markerColor,
|
|
462
|
+
accountLabel,
|
|
463
|
+
quota,
|
|
464
|
+
) {
|
|
465
|
+
const usedPercent = quota?.usedPercent;
|
|
466
|
+
const hasValue = usedPercent != null;
|
|
467
|
+
const loggedIn = quota?.auth != null;
|
|
468
|
+
const project = quota?.auth === "project";
|
|
469
|
+
const tint = loggedIn ? markerColor : dim;
|
|
470
|
+
const prefix = loggedIn ? `${bold(markerColor(marker))}:` : dim(`${marker}:`);
|
|
471
|
+
const stale = quota?.stale ? dim(" [stale]") : "";
|
|
472
|
+
const right = `${tint(accountLabel)}${stale}`;
|
|
473
|
+
const percent = antigravityPercentText(quota);
|
|
474
|
+
if (currentTier === "nano" || currentTier === "micro") {
|
|
475
|
+
return { prefix, left: percent, right };
|
|
476
|
+
}
|
|
477
|
+
const isFull = currentTier === "full";
|
|
478
|
+
const showTime = isFull || currentTier === "compact";
|
|
479
|
+
const reset =
|
|
480
|
+
Date.parse(quota?.resetTime) - Date.now() >= ONE_DAY_MS
|
|
481
|
+
? formatResetRemainingDayHour(quota.resetTime)
|
|
482
|
+
: formatResetRemaining(quota?.resetTime);
|
|
483
|
+
const timeCell = showTime ? ` ${dim(formatTimeCell(reset))}` : "";
|
|
484
|
+
// /usage의 모델별 값에는 5h/1w 식별자가 없으므로 창을 추측하지 않는다.
|
|
485
|
+
// 두 창(5h, 1w) 폭에 맞춰 c, x 행과 구분자 열을 맞춘다.
|
|
486
|
+
const windowWidth =
|
|
487
|
+
"5h:".length +
|
|
488
|
+
(isFull ? GAUGE_WIDTH + 1 : 0) +
|
|
489
|
+
PERCENT_CELL_WIDTH +
|
|
490
|
+
(showTime ? TIME_CELL_INNER_WIDTH + 3 : 0);
|
|
491
|
+
let slot;
|
|
492
|
+
if (project) {
|
|
493
|
+
// 쿼터 대신 과금 방식을 막대 자리(막대가 없는 표시에서는 퍼센트 자리)에 보인다.
|
|
494
|
+
const mark = isFull ? `${markerColor("GCP".padEnd(GAUGE_WIDTH))} ` : "";
|
|
495
|
+
const cell = isFull ? dim(formatPlaceholderPercentCell()) : percent;
|
|
496
|
+
slot = `${dim("--:")}${mark}${cell}${timeCell}`;
|
|
497
|
+
} else {
|
|
498
|
+
const bar = hasValue
|
|
499
|
+
? tierBar(currentTier, usedPercent, GEMINI_BLUE)
|
|
500
|
+
: tierDimBar(currentTier);
|
|
501
|
+
slot = `${dim("--:")}${bar}${percent}${timeCell}`;
|
|
502
|
+
}
|
|
503
|
+
return { prefix, left: padAnsiRight(slot, windowWidth * 2 + 1), right };
|
|
504
|
+
}
|
package/hud/utils.mjs
CHANGED
|
@@ -145,7 +145,7 @@ export function formatPlaceholderPercentCell() {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
export function normalizeTimeToken(value) {
|
|
148
|
-
const text = String(value || "
|
|
148
|
+
const text = String(value || "");
|
|
149
149
|
const hourMinute = text.match(/^(\d+)h(\d+)m$/);
|
|
150
150
|
if (hourMinute) {
|
|
151
151
|
return `${Number(hourMinute[1])}h${String(Number(hourMinute[2])).padStart(2, "0")}m`;
|
|
@@ -157,16 +157,20 @@ export function normalizeTimeToken(value) {
|
|
|
157
157
|
return text;
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
// 값이 없는 시간 칸은 단위 모양을 남겨 정상 값과 같은 폭으로 그린다.
|
|
161
|
+
function emptyTimeCell(unit) {
|
|
162
|
+
return unit === "dh" ? "(--d--h)" : "(--h--m)";
|
|
163
|
+
}
|
|
164
|
+
|
|
160
165
|
export function formatTimeCell(value) {
|
|
161
166
|
const text = normalizeTimeToken(value);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return `(${text.padStart(TIME_CELL_INNER_WIDTH, padChar)})`;
|
|
167
|
+
if (!/\d/.test(text)) return emptyTimeCell("hm");
|
|
168
|
+
return `(${text.padStart(TIME_CELL_INNER_WIDTH, "0")})`;
|
|
165
169
|
}
|
|
166
170
|
|
|
167
|
-
// n/a도 정상 주간 시간과 같은 너비를 유지한다.
|
|
168
171
|
export function formatTimeCellDH(value) {
|
|
169
172
|
const text = normalizeTimeToken(value);
|
|
173
|
+
if (!/\d/.test(text)) return emptyTimeCell("dh");
|
|
170
174
|
return `(${text.padStart(TIME_CELL_INNER_WIDTH, " ")})`;
|
|
171
175
|
}
|
|
172
176
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@triflux/core",
|
|
3
|
-
"version": "10.
|
|
4
|
-
"description": "triflux core — CLI routing,
|
|
3
|
+
"version": "10.52.0",
|
|
4
|
+
"description": "triflux core — CLI routing, adapters, account broker. Zero native dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "hub/index.mjs",
|
|
7
7
|
"exports": {
|
|
@@ -14,8 +14,6 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@iarna/toml": "^2.2.5",
|
|
17
|
-
"pino": "^10.3.1",
|
|
18
|
-
"pino-pretty": "^13.1.3",
|
|
19
17
|
"zod": "^4.0.0"
|
|
20
18
|
},
|
|
21
19
|
"files": [
|
|
@@ -12,168 +12,126 @@ const policy = {
|
|
|
12
12
|
executor: {
|
|
13
13
|
profile: "gpt61_sol_high",
|
|
14
14
|
timeoutSec: 1080,
|
|
15
|
-
runMode: "fg",
|
|
16
|
-
opusOversight: false,
|
|
17
15
|
mcpHint: "implement",
|
|
18
16
|
subcommand: "exec",
|
|
19
17
|
},
|
|
20
18
|
codex: {
|
|
21
19
|
profile: "gpt61_sol_high",
|
|
22
20
|
timeoutSec: 1080,
|
|
23
|
-
runMode: "fg",
|
|
24
|
-
opusOversight: false,
|
|
25
21
|
mcpHint: "implement",
|
|
26
22
|
subcommand: "exec",
|
|
27
23
|
},
|
|
28
24
|
"build-fixer": {
|
|
29
25
|
profile: "gpt6_luna_high",
|
|
30
26
|
timeoutSec: 540,
|
|
31
|
-
runMode: "fg",
|
|
32
|
-
opusOversight: false,
|
|
33
27
|
mcpHint: "implement",
|
|
34
28
|
subcommand: "exec",
|
|
35
29
|
},
|
|
36
30
|
cleanup: {
|
|
37
31
|
profile: "gpt61_sol_med",
|
|
38
32
|
timeoutSec: 540,
|
|
39
|
-
runMode: "fg",
|
|
40
|
-
opusOversight: false,
|
|
41
33
|
mcpHint: "implement",
|
|
42
34
|
subcommand: "exec",
|
|
43
35
|
},
|
|
44
36
|
deslop: {
|
|
45
37
|
profile: "gpt61_sol_med",
|
|
46
38
|
timeoutSec: 540,
|
|
47
|
-
runMode: "fg",
|
|
48
|
-
opusOversight: false,
|
|
49
39
|
mcpHint: "implement",
|
|
50
40
|
subcommand: "exec",
|
|
51
41
|
},
|
|
52
42
|
debugger: {
|
|
53
43
|
profile: "gpt6_astra_xhigh",
|
|
54
44
|
timeoutSec: 900,
|
|
55
|
-
runMode: "bg",
|
|
56
|
-
opusOversight: false,
|
|
57
45
|
mcpHint: "implement",
|
|
58
46
|
subcommand: "exec",
|
|
59
47
|
},
|
|
60
48
|
"deep-executor": {
|
|
61
49
|
profile: "gpt6_astra_xhigh",
|
|
62
50
|
timeoutSec: 3600,
|
|
63
|
-
runMode: "bg",
|
|
64
|
-
opusOversight: true,
|
|
65
51
|
mcpHint: "implement",
|
|
66
52
|
subcommand: "exec",
|
|
67
53
|
},
|
|
68
54
|
architect: {
|
|
69
55
|
profile: "gpt6_astra_xhigh",
|
|
70
56
|
timeoutSec: 3600,
|
|
71
|
-
runMode: "bg",
|
|
72
|
-
opusOversight: true,
|
|
73
57
|
mcpHint: "analyze",
|
|
74
58
|
subcommand: "exec",
|
|
75
59
|
},
|
|
76
60
|
critic: {
|
|
77
61
|
profile: "gpt6_astra_xhigh",
|
|
78
62
|
timeoutSec: 3600,
|
|
79
|
-
runMode: "bg",
|
|
80
|
-
opusOversight: true,
|
|
81
63
|
mcpHint: "analyze",
|
|
82
64
|
subcommand: "exec",
|
|
83
65
|
},
|
|
84
66
|
planner: {
|
|
85
67
|
profile: "gpt6_astra_xhigh",
|
|
86
68
|
timeoutSec: 3600,
|
|
87
|
-
runMode: "fg",
|
|
88
|
-
opusOversight: true,
|
|
89
69
|
mcpHint: "analyze",
|
|
90
70
|
subcommand: "exec",
|
|
91
71
|
},
|
|
92
72
|
analyst: {
|
|
93
73
|
profile: "gpt6_astra_xhigh",
|
|
94
74
|
timeoutSec: 3600,
|
|
95
|
-
runMode: "fg",
|
|
96
|
-
opusOversight: true,
|
|
97
75
|
mcpHint: "analyze",
|
|
98
76
|
subcommand: "exec",
|
|
99
77
|
},
|
|
100
78
|
"code-reviewer": {
|
|
101
79
|
profile: "gpt61_sol_high",
|
|
102
80
|
timeoutSec: 1800,
|
|
103
|
-
runMode: "bg",
|
|
104
|
-
opusOversight: false,
|
|
105
81
|
mcpHint: "review",
|
|
106
82
|
subcommand: "review",
|
|
107
83
|
},
|
|
108
84
|
"quality-reviewer": {
|
|
109
85
|
profile: "gpt61_sol_high",
|
|
110
86
|
timeoutSec: 1800,
|
|
111
|
-
runMode: "bg",
|
|
112
|
-
opusOversight: false,
|
|
113
87
|
mcpHint: "review",
|
|
114
88
|
subcommand: "review",
|
|
115
89
|
},
|
|
116
90
|
"security-reviewer": {
|
|
117
91
|
profile: "gpt6_astra_xhigh",
|
|
118
92
|
timeoutSec: 1800,
|
|
119
|
-
runMode: "bg",
|
|
120
|
-
opusOversight: true,
|
|
121
93
|
mcpHint: "review",
|
|
122
94
|
subcommand: "review",
|
|
123
95
|
},
|
|
124
96
|
scientist: {
|
|
125
97
|
profile: "gpt61_sol_high",
|
|
126
98
|
timeoutSec: 1440,
|
|
127
|
-
runMode: "bg",
|
|
128
|
-
opusOversight: false,
|
|
129
99
|
mcpHint: "analyze",
|
|
130
100
|
subcommand: "exec",
|
|
131
101
|
},
|
|
132
102
|
"document-specialist": {
|
|
133
103
|
profile: "gpt61_sol_high",
|
|
134
104
|
timeoutSec: 1440,
|
|
135
|
-
runMode: "bg",
|
|
136
|
-
opusOversight: false,
|
|
137
105
|
mcpHint: "analyze",
|
|
138
106
|
subcommand: "exec",
|
|
139
107
|
},
|
|
140
108
|
"scientist-deep": {
|
|
141
109
|
profile: "gpt6_astra_xhigh",
|
|
142
110
|
timeoutSec: 3600,
|
|
143
|
-
runMode: "bg",
|
|
144
|
-
opusOversight: false,
|
|
145
111
|
mcpHint: "analyze",
|
|
146
112
|
subcommand: "exec",
|
|
147
113
|
},
|
|
148
114
|
verifier: {
|
|
149
115
|
profile: "gpt61_sol_high",
|
|
150
116
|
timeoutSec: 1200,
|
|
151
|
-
runMode: "fg",
|
|
152
|
-
opusOversight: false,
|
|
153
117
|
mcpHint: "review",
|
|
154
118
|
subcommand: "review",
|
|
155
119
|
},
|
|
156
120
|
"test-engineer": {
|
|
157
121
|
profile: "gpt61_sol_high",
|
|
158
122
|
timeoutSec: 1200,
|
|
159
|
-
runMode: "bg",
|
|
160
|
-
opusOversight: false,
|
|
161
123
|
mcpHint: "implement",
|
|
162
124
|
subcommand: "exec",
|
|
163
125
|
},
|
|
164
126
|
"qa-tester": {
|
|
165
127
|
profile: "gpt61_sol_high",
|
|
166
128
|
timeoutSec: 1200,
|
|
167
|
-
runMode: "bg",
|
|
168
|
-
opusOversight: false,
|
|
169
129
|
mcpHint: "review",
|
|
170
130
|
subcommand: "review",
|
|
171
131
|
},
|
|
172
132
|
spark: {
|
|
173
133
|
profile: "gpt6_luna_low",
|
|
174
134
|
timeoutSec: 180,
|
|
175
|
-
runMode: "fg",
|
|
176
|
-
opusOversight: false,
|
|
177
135
|
mcpHint: "implement",
|
|
178
136
|
subcommand: "exec",
|
|
179
137
|
},
|
|
@@ -182,16 +140,12 @@ const policy = {
|
|
|
182
140
|
designer: {
|
|
183
141
|
profile: "gpt6_astra_xhigh",
|
|
184
142
|
timeoutSec: 900,
|
|
185
|
-
runMode: "bg",
|
|
186
|
-
opusOversight: false,
|
|
187
143
|
mcpHint: "implement",
|
|
188
144
|
subcommand: "exec",
|
|
189
145
|
},
|
|
190
146
|
writer: {
|
|
191
147
|
profile: "gpt6_luna_high",
|
|
192
148
|
timeoutSec: 900,
|
|
193
|
-
runMode: "bg",
|
|
194
|
-
opusOversight: false,
|
|
195
149
|
mcpHint: "implement",
|
|
196
150
|
subcommand: "exec",
|
|
197
151
|
},
|
|
@@ -319,22 +273,6 @@ export function resolveNestedCodexAgentProfile(
|
|
|
319
273
|
return effort.toLowerCase() === "ultra" ? "gpt6_astra_max" : candidate;
|
|
320
274
|
}
|
|
321
275
|
|
|
322
|
-
const MIN_TIMEOUT_BY_AGENT = Object.freeze({
|
|
323
|
-
"deep-executor": 900,
|
|
324
|
-
architect: 900,
|
|
325
|
-
planner: 900,
|
|
326
|
-
critic: 900,
|
|
327
|
-
analyst: 900,
|
|
328
|
-
"document-specialist": 900,
|
|
329
|
-
scientist: 900,
|
|
330
|
-
"scientist-deep": 900,
|
|
331
|
-
"code-reviewer": 600,
|
|
332
|
-
"security-reviewer": 600,
|
|
333
|
-
"quality-reviewer": 600,
|
|
334
|
-
executor: 300,
|
|
335
|
-
debugger: 300,
|
|
336
|
-
});
|
|
337
|
-
|
|
338
276
|
const EXPECTED_DURATION_BY_AGENT = Object.freeze({
|
|
339
277
|
writer: 90,
|
|
340
278
|
verifier: 90,
|
|
@@ -409,14 +347,11 @@ export function resolveAgentRoute(
|
|
|
409
347
|
provider,
|
|
410
348
|
policy.profile,
|
|
411
349
|
policy.timeoutSec,
|
|
412
|
-
policy.runMode,
|
|
413
|
-
policy.opusOversight,
|
|
414
350
|
policy.mcpHint,
|
|
415
351
|
policy.subcommand,
|
|
416
352
|
normalizedOverride,
|
|
417
353
|
resolvedOverride,
|
|
418
354
|
geminiProfileResolver(agent),
|
|
419
|
-
MIN_TIMEOUT_BY_AGENT[agent] ?? 120,
|
|
420
355
|
EXPECTED_DURATION_BY_AGENT[agent] ?? 30,
|
|
421
356
|
NATIVE_CODEX_AGENTS.has(agent),
|
|
422
357
|
];
|
|
@@ -495,8 +430,6 @@ async function runCli() {
|
|
|
495
430
|
[
|
|
496
431
|
resolved.profile,
|
|
497
432
|
resolved.timeoutSec,
|
|
498
|
-
resolved.runMode,
|
|
499
|
-
resolved.opusOversight,
|
|
500
433
|
resolved.mcpHint,
|
|
501
434
|
resolved.subcommand,
|
|
502
435
|
].join("\t"),
|
|
@@ -12,32 +12,22 @@ export const command = null;
|
|
|
12
12
|
const AGENT_PROFILES = {
|
|
13
13
|
explore: {
|
|
14
14
|
timeoutSec: 600,
|
|
15
|
-
runMode: "fg",
|
|
16
|
-
opusOversight: false,
|
|
17
15
|
model: "haiku",
|
|
18
16
|
},
|
|
19
17
|
claude: {
|
|
20
18
|
timeoutSec: 600,
|
|
21
|
-
runMode: "fg",
|
|
22
|
-
opusOversight: false,
|
|
23
19
|
model: "haiku",
|
|
24
20
|
},
|
|
25
21
|
"test-engineer": {
|
|
26
22
|
timeoutSec: 1200,
|
|
27
|
-
runMode: "bg",
|
|
28
|
-
opusOversight: false,
|
|
29
23
|
model: "sonnet",
|
|
30
24
|
},
|
|
31
25
|
"qa-tester": {
|
|
32
26
|
timeoutSec: 1200,
|
|
33
|
-
runMode: "bg",
|
|
34
|
-
opusOversight: false,
|
|
35
27
|
model: "sonnet",
|
|
36
28
|
},
|
|
37
29
|
verifier: {
|
|
38
30
|
timeoutSec: 1200,
|
|
39
|
-
runMode: "fg",
|
|
40
|
-
opusOversight: false,
|
|
41
31
|
model: "sonnet",
|
|
42
32
|
},
|
|
43
33
|
};
|
|
@@ -62,8 +52,6 @@ export function plan({
|
|
|
62
52
|
profile: "claude-native",
|
|
63
53
|
effort: "n/a",
|
|
64
54
|
timeoutMs: effectiveTimeoutSec * 1000,
|
|
65
|
-
runMode: cfg.runMode,
|
|
66
|
-
opusOversight: cfg.opusOversight,
|
|
67
55
|
model: cfg.model,
|
|
68
56
|
mcpProfile: mcpProfile === "auto" ? null : mcpProfile,
|
|
69
57
|
promptLength: prompt.length,
|