@triflux/core 10.50.1 → 10.50.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/hub/index.mjs +2 -8
- package/hub/lib/cto-env.mjs +0 -23
- package/hub/paths.mjs +0 -6
- package/hub/pipeline/index.mjs +0 -190
- package/hub/pipeline/transitions.mjs +0 -10
- package/hub/reflexion.mjs +1 -84
- package/hud/cli-policy.mjs +1 -5
- package/hud/colors.mjs +0 -13
- package/hud/constants.mjs +4 -135
- package/hud/context-monitor.mjs +3 -64
- package/hud/hud-qos-status.mjs +43 -225
- package/hud/providers/claude.mjs +4 -16
- package/hud/providers/gemini.mjs +7 -698
- package/hud/renderers.mjs +40 -294
- package/hud/terminal.mjs +1 -63
- package/hud/utils.mjs +0 -24
- package/package.json +1 -2
- package/scripts/lib/gemini-profiles.mjs +1 -1
- package/scripts/lib/legacy-mcp-cleanup.mjs +14 -3
- package/scripts/lib/psmux-info.mjs +18 -49
- package/scripts/lib/skill-template.mjs +0 -26
- package/hub/codex-compat.mjs +0 -12
- package/hub/fullcycle.mjs +0 -113
- package/hub/gemini-adapter.mjs +0 -174
- package/hub/intent.mjs +0 -321
- package/hub/lib/mcp-response-cache.mjs +0 -239
- package/hub/lib/path-utils.mjs +0 -165
- package/hub/lib/timeline-adapter.mjs +0 -190
- package/hub/pipeline/gates/confidence.mjs +0 -75
- package/hub/pipeline/gates/consensus.mjs +0 -106
- package/hub/pipeline/gates/index.mjs +0 -9
- package/hub/pipeline/gates/selfcheck.mjs +0 -120
- package/hub/quality/deslop.mjs +0 -274
- package/hub/research.mjs +0 -155
- package/hub/role-control-events.mjs +0 -113
- package/hub/routing/complexity.mjs +0 -269
- package/hub/routing/index.mjs +0 -122
- package/hub/routing/q-learning.mjs +0 -387
- package/hub/token-mode.mjs +0 -228
- package/hud/mission-board.mjs +0 -56
- package/hud/providers/cto.mjs +0 -76
- package/scripts/lib/agent-json.mjs +0 -27
- package/scripts/lib/async.mjs +0 -174
- package/scripts/lib/cli-agy.mjs +0 -85
- package/scripts/lib/cli-codex.mjs +0 -62
- package/scripts/lib/cli-gemini.mjs +0 -37
- package/scripts/lib/env.mjs +0 -14
- package/scripts/lib/hub.mjs +0 -48
- package/scripts/lib/pid.mjs +0 -63
- package/scripts/lib/quota.mjs +0 -47
- package/scripts/lib/skill-state.mjs +0 -220
- package/scripts/lib/team.mjs +0 -75
- package/scripts/lib/timeout.mjs +0 -66
- package/scripts/lib/tmp.mjs +0 -26
- package/scripts/lib/toml.mjs +0 -132
package/hub/index.mjs
CHANGED
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
// Adapters
|
|
3
3
|
export { buildExecCommand, sleep, gte, FEATURES, CODEX_MCP_TRANSPORT_EXIT_CODE, normalizePathForShell, shellQuote } from './cli-adapter-base.mjs';
|
|
4
4
|
export { execute as executeCodex, buildExecArgs as buildCodexArgs, buildLaunchScript, getCircuitState as getCodexCircuit } from './codex-adapter.mjs';
|
|
5
|
-
export { execute as executeGemini, buildExecArgs as buildGeminiArgs, getCircuitState as getGeminiCircuit } from './gemini-adapter.mjs';
|
|
6
5
|
export { getCodexVersion, runPreflight } from './codex-preflight.mjs';
|
|
7
6
|
|
|
8
|
-
// Routing
|
|
7
|
+
// Routing
|
|
9
8
|
export { createRouter } from './router.mjs';
|
|
10
|
-
export { classifyIntent, quickClassify, INTENT_CATEGORIES, refineClassification } from './intent.mjs';
|
|
11
9
|
|
|
12
10
|
// State & Paths & Platform
|
|
13
11
|
export * from './paths.mjs';
|
|
@@ -18,12 +16,8 @@ export { createHitlManager } from './hitl.mjs';
|
|
|
18
16
|
export { createAssignCallbackServer } from './assign-callbacks.mjs';
|
|
19
17
|
export { getHubUrl, getHubPipePath, requestJson, post, connectPipe, parseArgs, parseJsonSafe } from './bridge.mjs';
|
|
20
18
|
|
|
21
|
-
// Fullcycle & Research
|
|
22
|
-
export { createFullcycleRunId, getFullcycleRunDir, ensureFullcycleRunDir, saveFullcycleArtifact, readFullcycleArtifact, writeFullcycleState, readFullcycleState, shouldStopQaLoop } from './fullcycle.mjs';
|
|
23
|
-
export { generateQueries, normalizeResults, buildReport, saveReport } from './research.mjs';
|
|
24
|
-
|
|
25
19
|
// Reflexion (adaptive error learning)
|
|
26
|
-
export { normalizeError,
|
|
20
|
+
export { normalizeError, adaptiveRuleFromError } from './reflexion.mjs';
|
|
27
21
|
|
|
28
22
|
// Neural Memory (Lake 1.5)
|
|
29
23
|
export { createAdaptiveEngine } from './adaptive.mjs';
|
package/hub/lib/cto-env.mjs
CHANGED
|
@@ -64,30 +64,7 @@ export function isCtoDisabled() {
|
|
|
64
64
|
return isExplicitlyOff("TFX_CTO");
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
export function isCtoManagerEnabled() {
|
|
68
|
-
if (isCtoDisabled()) return false;
|
|
69
|
-
return isExplicitlyOn("TFX_CTO_MANAGER");
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function getCtoHygieneApplyMode() {
|
|
73
|
-
if (isExplicitlyOff("TFX_CTO")) return "off";
|
|
74
|
-
return normalizeEnvValue("TFX_CTO_HYGIENE_APPLY") === "archive"
|
|
75
|
-
? "archive"
|
|
76
|
-
: "off";
|
|
77
|
-
}
|
|
78
|
-
|
|
79
67
|
export function isCtoRetentionEnabled() {
|
|
80
68
|
if (isExplicitlyOff("TFX_CTO")) return false;
|
|
81
69
|
return isExplicitlyOn("TFX_CTO_RETENTION");
|
|
82
70
|
}
|
|
83
|
-
|
|
84
|
-
export function getCtoMode() {
|
|
85
|
-
return normalizeEnvValue("TFX_CTO_MODE") === "bridge" ? "bridge" : "bounded";
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function getCtoMaxTokens() {
|
|
89
|
-
const raw = normalizeEnvValue("TFX_CTO_MAX_TOKENS");
|
|
90
|
-
if (!raw) return 0;
|
|
91
|
-
const value = Number(raw);
|
|
92
|
-
return Number.isSafeInteger(value) && value > 0 ? value : 0;
|
|
93
|
-
}
|
package/hub/paths.mjs
CHANGED
|
@@ -6,10 +6,7 @@ import { join } from "node:path";
|
|
|
6
6
|
export const TFX_WORK_DIR = ".tfx";
|
|
7
7
|
export const TFX_PLANS_DIR = join(TFX_WORK_DIR, "plans");
|
|
8
8
|
export const TFX_REPORTS_DIR = join(TFX_WORK_DIR, "reports");
|
|
9
|
-
export const TFX_HANDOFFS_DIR = join(TFX_WORK_DIR, "handoffs");
|
|
10
|
-
export const TFX_LOGS_DIR = join(TFX_WORK_DIR, "logs");
|
|
11
9
|
export const TFX_STATE_DIR = join(TFX_WORK_DIR, "state");
|
|
12
|
-
export const TFX_FULLCYCLE_DIR = join(TFX_WORK_DIR, "fullcycle");
|
|
13
10
|
|
|
14
11
|
/**
|
|
15
12
|
* triflux 워킹 디렉토리 구조를 보장한다.
|
|
@@ -20,10 +17,7 @@ export function ensureTfxDirs(baseDir) {
|
|
|
20
17
|
TFX_WORK_DIR,
|
|
21
18
|
TFX_PLANS_DIR,
|
|
22
19
|
TFX_REPORTS_DIR,
|
|
23
|
-
TFX_HANDOFFS_DIR,
|
|
24
|
-
TFX_LOGS_DIR,
|
|
25
20
|
TFX_STATE_DIR,
|
|
26
|
-
TFX_FULLCYCLE_DIR,
|
|
27
21
|
]) {
|
|
28
22
|
mkdirSync(join(baseDir, relativeDir), { recursive: true });
|
|
29
23
|
}
|
package/hub/pipeline/index.mjs
CHANGED
|
@@ -3,11 +3,7 @@
|
|
|
3
3
|
// 상태(state.mjs) + 전이(transitions.mjs) 통합 인터페이스
|
|
4
4
|
|
|
5
5
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
6
|
-
import { homedir } from "node:os";
|
|
7
6
|
import { join, resolve } from "node:path";
|
|
8
|
-
import { classifyIntent as _classifyIntent } from "../intent.mjs";
|
|
9
|
-
import { runConfidenceCheck } from "./gates/confidence.mjs";
|
|
10
|
-
import { runSelfCheck } from "./gates/selfcheck.mjs";
|
|
11
7
|
import {
|
|
12
8
|
ensurePipelineTable,
|
|
13
9
|
initPipelineState,
|
|
@@ -21,7 +17,6 @@ import {
|
|
|
21
17
|
TERMINAL,
|
|
22
18
|
transitionPhase,
|
|
23
19
|
} from "./transitions.mjs";
|
|
24
|
-
// deslop gate: 호출자가 scanDirectory/detectSlop 결과를 전달
|
|
25
20
|
|
|
26
21
|
/**
|
|
27
22
|
* 파이프라인 매니저 생성
|
|
@@ -162,192 +157,7 @@ export function createPipeline(db, teamName, opts = {}) {
|
|
|
162
157
|
remove() {
|
|
163
158
|
return removePipelineState(db, teamName);
|
|
164
159
|
},
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Confidence Gate 실행 + 자동 전이
|
|
168
|
-
* prd → confidence → exec/failed
|
|
169
|
-
* @param {string|object} planArtifact
|
|
170
|
-
* @param {object} context - { checks?, codebaseFiles?, existingTests? }
|
|
171
|
-
* @returns {{ ok: boolean, gate: object, state?: object, error?: string }}
|
|
172
|
-
*/
|
|
173
|
-
runConfidenceGate(planArtifact, context = {}) {
|
|
174
|
-
const current = readPipelineState(db, teamName);
|
|
175
|
-
if (!current) return { ok: false, error: `파이프라인 없음: ${teamName}` };
|
|
176
|
-
|
|
177
|
-
if (current.phase !== "confidence") {
|
|
178
|
-
return {
|
|
179
|
-
ok: false,
|
|
180
|
-
error: `confidence gate는 confidence 단계에서만 실행 가능 (현재: ${current.phase})`,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const gate = runConfidenceCheck(planArtifact, context);
|
|
185
|
-
this.setArtifact("confidence_result", gate);
|
|
186
|
-
|
|
187
|
-
if (gate.decision === "abort") {
|
|
188
|
-
const result = this.advance("failed");
|
|
189
|
-
return { ok: true, gate, state: result.state };
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// proceed 또는 alternative → exec로 전이
|
|
193
|
-
const result = this.advance("exec");
|
|
194
|
-
return { ok: result.ok, gate, state: result.state, error: result.error };
|
|
195
|
-
},
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Deslop Gate 실행 + 자동 전이
|
|
199
|
-
* exec → deslop → verify
|
|
200
|
-
* 호출자가 미리 deslop 결과를 생성하여 전달.
|
|
201
|
-
* @param {object} [deslopResult] - scanDirectory() 또는 detectSlop() 결과
|
|
202
|
-
* @returns {{ ok: boolean, gate: object, state?: object, error?: string }}
|
|
203
|
-
*/
|
|
204
|
-
runDeslopGate(deslopResult = null) {
|
|
205
|
-
const current = readPipelineState(db, teamName);
|
|
206
|
-
if (!current) return { ok: false, error: `파이프라인 없음: ${teamName}` };
|
|
207
|
-
|
|
208
|
-
if (current.phase !== "deslop") {
|
|
209
|
-
return {
|
|
210
|
-
ok: false,
|
|
211
|
-
error: `deslop gate는 deslop 단계에서만 실행 가능 (현재: ${current.phase})`,
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const gate = deslopResult || {
|
|
216
|
-
files: [],
|
|
217
|
-
summary: { total: 0, clean: 0 },
|
|
218
|
-
};
|
|
219
|
-
this.setArtifact("deslop_result", gate);
|
|
220
|
-
|
|
221
|
-
// deslop은 항상 verify로 전이 (정보 제공 게이트, 차단 없음)
|
|
222
|
-
const result = this.advance("verify");
|
|
223
|
-
return { ok: result.ok, gate, state: result.state, error: result.error };
|
|
224
|
-
},
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Self-Check Gate 실행 + 자동 전이
|
|
228
|
-
* verify → selfcheck → complete/fix
|
|
229
|
-
* @param {string|object} execResult
|
|
230
|
-
* @param {string|object} verifyResult
|
|
231
|
-
* @param {object} requirements - { hasDiff?, evidence? }
|
|
232
|
-
* @returns {{ ok: boolean, gate: object, state?: object, error?: string }}
|
|
233
|
-
*/
|
|
234
|
-
runSelfCheckGate(execResult, verifyResult, requirements = {}) {
|
|
235
|
-
const current = readPipelineState(db, teamName);
|
|
236
|
-
if (!current) return { ok: false, error: `파이프라인 없음: ${teamName}` };
|
|
237
|
-
|
|
238
|
-
if (current.phase !== "selfcheck") {
|
|
239
|
-
return {
|
|
240
|
-
ok: false,
|
|
241
|
-
error: `selfcheck gate는 selfcheck 단계에서만 실행 가능 (현재: ${current.phase})`,
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
const gate = runSelfCheck(execResult, verifyResult, requirements);
|
|
246
|
-
this.setArtifact("selfcheck_result", gate);
|
|
247
|
-
|
|
248
|
-
if (gate.passed) {
|
|
249
|
-
const result = this.advance("complete");
|
|
250
|
-
return {
|
|
251
|
-
ok: result.ok,
|
|
252
|
-
gate,
|
|
253
|
-
state: result.state,
|
|
254
|
-
error: result.error,
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Red Flag 탐지 또는 필수 질문 실패 → fix
|
|
259
|
-
const result = this.advance("fix");
|
|
260
|
-
return { ok: result.ok, gate, state: result.state, error: result.error };
|
|
261
|
-
},
|
|
262
160
|
};
|
|
263
161
|
}
|
|
264
|
-
|
|
265
|
-
// ── 토큰 벤치마크 훅 ──
|
|
266
|
-
|
|
267
|
-
let _tokenSnapshotMod = null;
|
|
268
|
-
|
|
269
|
-
async function loadTokenSnapshot() {
|
|
270
|
-
if (_tokenSnapshotMod) return _tokenSnapshotMod;
|
|
271
|
-
try {
|
|
272
|
-
_tokenSnapshotMod = await import("../../scripts/token-snapshot.mjs");
|
|
273
|
-
} catch {
|
|
274
|
-
_tokenSnapshotMod = null;
|
|
275
|
-
}
|
|
276
|
-
return _tokenSnapshotMod;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* 파이프라인 시작 시 토큰 스냅샷 캡처
|
|
281
|
-
* @param {string} label - 스냅샷 라벨 (e.g. teamName + timestamp)
|
|
282
|
-
* @returns {Promise<{label: string, snapshot: object}|null>}
|
|
283
|
-
*/
|
|
284
|
-
export async function benchmarkStart(label) {
|
|
285
|
-
const mod = await loadTokenSnapshot();
|
|
286
|
-
if (!mod?.takeSnapshot) return null;
|
|
287
|
-
try {
|
|
288
|
-
const snapshot = mod.takeSnapshot(label);
|
|
289
|
-
return { label, snapshot };
|
|
290
|
-
} catch {
|
|
291
|
-
return null;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* 파이프라인 종료 시 diff 계산 + 결과 저장
|
|
297
|
-
* @param {string} preLabel - 시작 스냅샷 라벨
|
|
298
|
-
* @param {string} postLabel - 종료 스냅샷 라벨
|
|
299
|
-
* @param {object} options - { agent?, cli?, id? }
|
|
300
|
-
* @returns {Promise<object|null>} diff 결과
|
|
301
|
-
*/
|
|
302
|
-
export async function benchmarkEnd(preLabel, postLabel, options = {}) {
|
|
303
|
-
const mod = await loadTokenSnapshot();
|
|
304
|
-
if (!mod?.takeSnapshot || !mod?.computeDiff) return null;
|
|
305
|
-
try {
|
|
306
|
-
// 종료 스냅샷 캡처
|
|
307
|
-
mod.takeSnapshot(postLabel);
|
|
308
|
-
// diff 계산 (결과는 DIFFS_DIR에 자동 저장됨)
|
|
309
|
-
const diff = mod.computeDiff(preLabel, postLabel, options);
|
|
310
|
-
|
|
311
|
-
// 추가로 타임스탬프 기반 사본 저장
|
|
312
|
-
const diffsDir = join(
|
|
313
|
-
homedir(),
|
|
314
|
-
".omc",
|
|
315
|
-
"state",
|
|
316
|
-
"cx-auto-tokens",
|
|
317
|
-
"diffs",
|
|
318
|
-
);
|
|
319
|
-
mkdirSync(diffsDir, { recursive: true });
|
|
320
|
-
const ts = new Date().toISOString().replace(/[:.]/g, "-");
|
|
321
|
-
const outPath = join(diffsDir, `${ts}.json`);
|
|
322
|
-
writeFileSync(outPath, JSON.stringify(diff, null, 2));
|
|
323
|
-
|
|
324
|
-
return diff;
|
|
325
|
-
} catch {
|
|
326
|
-
return null;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
/**
|
|
331
|
-
* 트리아지 통합: quickClassify 고신뢰 시 Codex 분류 스킵 판정
|
|
332
|
-
* @param {string} prompt
|
|
333
|
-
* @param {number} [threshold=0.8]
|
|
334
|
-
* @returns {{ skip: boolean, routing: object|null, classification: object }}
|
|
335
|
-
*/
|
|
336
|
-
export function triageWithIntent(prompt, threshold = 0.8) {
|
|
337
|
-
const classification = _classifyIntent(prompt);
|
|
338
|
-
if (classification.confidence >= threshold) {
|
|
339
|
-
return { skip: true, routing: classification.routing, classification };
|
|
340
|
-
}
|
|
341
|
-
return { skip: false, routing: null, classification };
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
export {
|
|
345
|
-
classifyIntent,
|
|
346
|
-
INTENT_CATEGORIES,
|
|
347
|
-
quickClassify,
|
|
348
|
-
} from "../intent.mjs";
|
|
349
|
-
export { autoFixSlop, detectSlop, scanDirectory } from "../quality/deslop.mjs";
|
|
350
|
-
export { CRITERIA, runConfidenceCheck } from "./gates/confidence.mjs";
|
|
351
|
-
export { QUESTIONS, RED_FLAGS, runSelfCheck } from "./gates/selfcheck.mjs";
|
|
352
162
|
export { ensurePipelineTable } from "./state.mjs";
|
|
353
163
|
export { ALLOWED, canTransition, PHASES, TERMINAL } from "./transitions.mjs";
|
|
@@ -73,19 +73,9 @@ export function transitionPhase(state, nextPhase) {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
// fix → exec 재진입 시 (fix 후 재실행)
|
|
77
|
-
if (current === "fix" && nextPhase === "exec") {
|
|
78
|
-
// fix_attempt 유지 (이미 fix 진입 시 증가됨)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
76
|
// verify → fix → ... → verify 반복 후 fix_max 초과 시 ralph loop
|
|
82
77
|
if (nextPhase === "failed" && current === "fix") {
|
|
83
|
-
// ralph loop 반복 증가
|
|
84
78
|
next.ralph_iteration = (state.ralph_iteration || 0) + 1;
|
|
85
|
-
if (next.ralph_iteration > (state.ralph_max || 10)) {
|
|
86
|
-
// 최종 실패 — ralph loop도 초과
|
|
87
|
-
next.phase = "failed";
|
|
88
|
-
}
|
|
89
79
|
}
|
|
90
80
|
|
|
91
81
|
// phase_history 기록
|
package/hub/reflexion.mjs
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
//
|
|
2
|
-
// 에러를 구조화 저장 → 다음 세션에서 유사 에러 패턴 매칭 → 자동 솔루션 적용
|
|
1
|
+
// 오류 패턴 정규화 및 adaptive rule 관리
|
|
3
2
|
|
|
4
|
-
const DEFAULT_REFLEXION_TYPE = "reflexion";
|
|
5
3
|
export const ADAPTIVE_RULE_TYPE = "adaptive";
|
|
6
4
|
const DEFAULT_CONFIDENCE = 0.5;
|
|
7
|
-
const ACTIVE_RULE_CONFIDENCE = 0.5;
|
|
8
5
|
const ADAPTIVE_PROMOTION_STEP = 0.1;
|
|
9
6
|
const ADAPTIVE_DECAY_STEP = 0.1;
|
|
10
7
|
const ADAPTIVE_DELETE_THRESHOLD = 0.3;
|
|
@@ -100,12 +97,6 @@ function buildAdaptiveSolution(errorContext = {}, errorText = "") {
|
|
|
100
97
|
return `${toolName} 재시도 전 실패 원인을 검증하세요: ${summary}`;
|
|
101
98
|
}
|
|
102
99
|
|
|
103
|
-
function filterEntriesByType(entries, type) {
|
|
104
|
-
return entries.filter(
|
|
105
|
-
(entry) => (entry.type || DEFAULT_REFLEXION_TYPE) === type,
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
100
|
function parseAdaptiveRuleId(ruleId, projectSlug = "") {
|
|
110
101
|
const value = pickString(ruleId);
|
|
111
102
|
if (!value) return null;
|
|
@@ -187,68 +178,6 @@ export function normalizeError(errorMessage) {
|
|
|
187
178
|
return p.toLowerCase().replace(/\s+/g, " ").trim();
|
|
188
179
|
}
|
|
189
180
|
|
|
190
|
-
/**
|
|
191
|
-
* 에러에 대한 기존 솔루션 검색
|
|
192
|
-
* @deprecated reflexion_entries 기반. adaptive_rules로 통합 예정. 현재 런타임 호출 없음.
|
|
193
|
-
* @param {object} store - createStore() 반환 객체
|
|
194
|
-
* @param {string} errorMessage - 원본 에러 메시지
|
|
195
|
-
* @param {object} [context={}] - { file, function, cli, agent }
|
|
196
|
-
* @returns {{ found: boolean, entries: Array, bestMatch: object|null }}
|
|
197
|
-
*/
|
|
198
|
-
export function lookupSolution(store, errorMessage, context = {}) {
|
|
199
|
-
const pattern = normalizeError(errorMessage);
|
|
200
|
-
if (!pattern) return { found: false, entries: [], bestMatch: null };
|
|
201
|
-
const entries = store.findReflexion(pattern, context);
|
|
202
|
-
if (!entries.length) return { found: false, entries: [], bestMatch: null };
|
|
203
|
-
return { found: true, entries, bestMatch: entries[0] };
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* 에러 해결 후 학습 저장
|
|
208
|
-
* @deprecated reflexion_entries 기반. adaptive_rules로 통합 예정. 현재 런타임 호출 없음.
|
|
209
|
-
* 동일 패턴이 존재하면 hit 업데이트, 없으면 새로 생성
|
|
210
|
-
* @param {object} store
|
|
211
|
-
* @param {{ error: string, solution: string, context?: object, success?: boolean }} opts
|
|
212
|
-
* @returns {object|null}
|
|
213
|
-
*/
|
|
214
|
-
export function learnFromError(
|
|
215
|
-
store,
|
|
216
|
-
{ error, solution, context = {}, success = false },
|
|
217
|
-
) {
|
|
218
|
-
const pattern = normalizeError(error);
|
|
219
|
-
if (!pattern || !solution) return null;
|
|
220
|
-
const existing = filterEntriesByType(
|
|
221
|
-
store.findReflexion(pattern, context),
|
|
222
|
-
DEFAULT_REFLEXION_TYPE,
|
|
223
|
-
);
|
|
224
|
-
if (existing.length && existing[0].error_pattern === pattern) {
|
|
225
|
-
return store.updateReflexionHit(existing[0].id, success);
|
|
226
|
-
}
|
|
227
|
-
const newEntry = store.addReflexion({
|
|
228
|
-
type: DEFAULT_REFLEXION_TYPE,
|
|
229
|
-
error_pattern: pattern,
|
|
230
|
-
error_message: error,
|
|
231
|
-
context,
|
|
232
|
-
solution,
|
|
233
|
-
solution_code: null,
|
|
234
|
-
});
|
|
235
|
-
return success && newEntry
|
|
236
|
-
? store.updateReflexionHit(newEntry.id, true)
|
|
237
|
-
: newEntry;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* 솔루션 적용 결과 피드백
|
|
242
|
-
* @deprecated reflexion_entries 기반. adaptive_rules로 통합 예정. 현재 런타임 호출 없음.
|
|
243
|
-
* @param {object} store
|
|
244
|
-
* @param {string} entryId
|
|
245
|
-
* @param {boolean} success
|
|
246
|
-
* @returns {object|null}
|
|
247
|
-
*/
|
|
248
|
-
export function reportOutcome(store, entryId, success) {
|
|
249
|
-
return store.updateReflexionHit(entryId, success);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
181
|
/**
|
|
253
182
|
* PostToolUseFailure 컨텍스트에서 adaptive rule payload 생성
|
|
254
183
|
* @param {object} errorContext
|
|
@@ -347,18 +276,6 @@ export function decayRules(store, _sessionCount, projectSlug) {
|
|
|
347
276
|
return result;
|
|
348
277
|
}
|
|
349
278
|
|
|
350
|
-
/**
|
|
351
|
-
* 현재 활성화된 adaptive rules 조회
|
|
352
|
-
* @param {object} store — store-adapter 인스턴스 (listAdaptiveRules 필요)
|
|
353
|
-
* @param {string} projectSlug
|
|
354
|
-
* @returns {Array}
|
|
355
|
-
*/
|
|
356
|
-
export function getActiveAdaptiveRules(store, projectSlug) {
|
|
357
|
-
return listAdaptiveRulesFromStore(store, projectSlug).filter(
|
|
358
|
-
(rule) => rule.confidence >= ACTIVE_RULE_CONFIDENCE,
|
|
359
|
-
);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
279
|
/**
|
|
363
280
|
* 신뢰도 자동 조정 (success_count / hit_count, 샘플 크기 기반 감쇠)
|
|
364
281
|
* hit_count가 작으면 0.5(기본값)쪽으로 보수적으로 수렴
|
package/hud/cli-policy.mjs
CHANGED
|
@@ -52,8 +52,6 @@ export function resolveHudCliVisibility(env = process.env, opts = {}) {
|
|
|
52
52
|
* antigravityAllowed?: boolean,
|
|
53
53
|
* antigravityReady?: boolean,
|
|
54
54
|
* geminiEmail?: unknown,
|
|
55
|
-
* geminiBucket?: unknown,
|
|
56
|
-
* geminiSession?: unknown,
|
|
57
55
|
* }} [args]
|
|
58
56
|
* @returns {boolean}
|
|
59
57
|
*/
|
|
@@ -61,9 +59,7 @@ export function shouldRenderGeminiFallbackRow({
|
|
|
61
59
|
antigravityAllowed = true,
|
|
62
60
|
antigravityReady = false,
|
|
63
61
|
geminiEmail = null,
|
|
64
|
-
geminiBucket = null,
|
|
65
|
-
geminiSession = null,
|
|
66
62
|
} = {}) {
|
|
67
63
|
if (antigravityAllowed || antigravityReady) return true;
|
|
68
|
-
return Boolean(geminiEmail
|
|
64
|
+
return Boolean(geminiEmail);
|
|
69
65
|
}
|
package/hud/colors.mjs
CHANGED
|
@@ -47,20 +47,7 @@ export function colorByPercent(value, text) {
|
|
|
47
47
|
return green(text);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
export function colorCooldown(seconds, text) {
|
|
51
|
-
if (seconds > 120) return red(text);
|
|
52
|
-
if (seconds > 0) return yellow(text);
|
|
53
|
-
return dim(text);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function colorParallel(current, cap) {
|
|
57
|
-
if (current >= cap) return green(`${current}/${cap}`);
|
|
58
|
-
if (current > 1) return yellow(`${current}/${cap}`);
|
|
59
|
-
return red(`${current}/${cap}`);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
50
|
export const GAUGE_WIDTH = 5;
|
|
63
|
-
export const GAUGE_BLOCKS = ["░", "▒", "▓", "█"]; // 밝기 0~3
|
|
64
51
|
|
|
65
52
|
export function coloredBar(percent, width = GAUGE_WIDTH, baseColor = null) {
|
|
66
53
|
const safePercent = Math.min(100, Math.max(0, percent));
|
package/hud/constants.mjs
CHANGED
|
@@ -6,13 +6,6 @@ import { join } from "node:path";
|
|
|
6
6
|
|
|
7
7
|
export const VERSION = "2.0";
|
|
8
8
|
|
|
9
|
-
export const QOS_PATH = join(
|
|
10
|
-
homedir(),
|
|
11
|
-
".claude",
|
|
12
|
-
"cache",
|
|
13
|
-
"tfx-hub",
|
|
14
|
-
"cli_qos_profile.json",
|
|
15
|
-
);
|
|
16
9
|
export const ACCOUNTS_CONFIG_PATH = join(
|
|
17
10
|
homedir(),
|
|
18
11
|
".claude",
|
|
@@ -38,21 +31,9 @@ export const CLAUDE_BAND_MARKER_DIR = join(
|
|
|
38
31
|
);
|
|
39
32
|
export const CLAUDE_BAND_MARKER_TTL_MS = 12 * 60 * 60 * 1000;
|
|
40
33
|
|
|
41
|
-
// tfx-multi 상태
|
|
42
|
-
export const
|
|
43
|
-
homedir(),
|
|
44
|
-
".claude",
|
|
45
|
-
"cache",
|
|
46
|
-
"tfx-hub",
|
|
47
|
-
"team-state.json",
|
|
48
|
-
);
|
|
49
|
-
export const CTO_LAKE_CURRENT_RELATIVE_PATH = join(
|
|
50
|
-
".triflux",
|
|
51
|
-
"lake",
|
|
52
|
-
"current.md",
|
|
53
|
-
);
|
|
54
|
-
export const CTO_STATUS_STALE_MS = 60 * 60 * 1000; // 1시간
|
|
55
|
-
export const CTO_STATUS_LINE_MAX_CHARS = 140;
|
|
34
|
+
// tfx-multi 세션 상태 디렉터리
|
|
35
|
+
export const TEAM_STATE_DIR =
|
|
36
|
+
process.env.TFX_HUB_PID_DIR || join(homedir(), ".claude", "cache", "tfx-hub");
|
|
56
37
|
export const CONTEXT_MONITOR_CACHE_PATH = join(
|
|
57
38
|
homedir(),
|
|
58
39
|
".claude",
|
|
@@ -67,12 +48,6 @@ export const HUB_REQUEST_MONITOR_CACHE_PATH = join(
|
|
|
67
48
|
"tfx-hub",
|
|
68
49
|
"hub-request-context-monitor.json",
|
|
69
50
|
);
|
|
70
|
-
export const CONTEXT_MONITOR_LEGACY_PATH = join(
|
|
71
|
-
homedir(),
|
|
72
|
-
".omc",
|
|
73
|
-
"state",
|
|
74
|
-
"context-monitor.json",
|
|
75
|
-
);
|
|
76
51
|
export const CONTEXT_MONITOR_LOG_DIR = join(
|
|
77
52
|
homedir(),
|
|
78
53
|
".claude",
|
|
@@ -81,16 +56,6 @@ export const CONTEXT_MONITOR_LOG_DIR = join(
|
|
|
81
56
|
"logs",
|
|
82
57
|
);
|
|
83
58
|
|
|
84
|
-
// 원격 프로브 캐시 (tfx-remote)
|
|
85
|
-
export const REMOTE_ENV_CACHE_DIR = join(
|
|
86
|
-
homedir(),
|
|
87
|
-
".claude",
|
|
88
|
-
"cache",
|
|
89
|
-
"tfx-hub",
|
|
90
|
-
"remote-env",
|
|
91
|
-
);
|
|
92
|
-
export const REMOTE_ENV_CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24시간
|
|
93
|
-
|
|
94
59
|
// Claude OAuth Usage API (api.anthropic.com/api/oauth/usage)
|
|
95
60
|
export const CLAUDE_CREDENTIALS_PATH = join(
|
|
96
61
|
homedir(),
|
|
@@ -182,21 +147,8 @@ export const CODEX_REFRESH_LOCK_PATH = join(
|
|
|
182
147
|
"cache",
|
|
183
148
|
".codex-refresh-lock",
|
|
184
149
|
);
|
|
185
|
-
export const GEMINI_QUOTA_REFRESH_LOCK_PATH = join(
|
|
186
|
-
homedir(),
|
|
187
|
-
".claude",
|
|
188
|
-
"cache",
|
|
189
|
-
".gemini-quota-refresh-lock",
|
|
190
|
-
);
|
|
191
|
-
export const GEMINI_SESSION_REFRESH_LOCK_PATH = join(
|
|
192
|
-
homedir(),
|
|
193
|
-
".claude",
|
|
194
|
-
"cache",
|
|
195
|
-
".gemini-session-refresh-lock",
|
|
196
|
-
);
|
|
197
150
|
export const SPAWN_LOCK_TTL_MS = 30 * 1000; // 30초 spawn dedup
|
|
198
151
|
|
|
199
|
-
// Gemini 쿼터 API 관련
|
|
200
152
|
export const GEMINI_OAUTH_PATH = join(homedir(), ".gemini", "oauth_creds.json");
|
|
201
153
|
export const ANTIGRAVITY_OAUTH_PATHS = [
|
|
202
154
|
join(homedir(), ".gemini", "antigravity-cli", "oauth_creds.json"),
|
|
@@ -212,10 +164,8 @@ export const ANTIGRAVITY_SETTINGS_PATH = join(
|
|
|
212
164
|
"settings.json",
|
|
213
165
|
);
|
|
214
166
|
// Antigravity CLI 현재 장착 모델 라벨 → HUD 2자 약어 매핑
|
|
215
|
-
// /usage 실측 (2026-05-22): Gemini 4개 모델이 동일 reset window 공유 (family-pool).
|
|
216
|
-
// Claude/GPT-OSS family는 Gemini와 별도 quota 윈도우.
|
|
217
167
|
export const ANTIGRAVITY_MODEL_ABBREV = {
|
|
218
|
-
//
|
|
168
|
+
// Flash 세대와 등급을 구분한다.
|
|
219
169
|
"Gemini 3.8 Flash (High)": "8h",
|
|
220
170
|
"Gemini 3.8 Flash (Medium)": "8m",
|
|
221
171
|
"Gemini 3.8 Flash (Low)": "8l",
|
|
@@ -228,33 +178,7 @@ export const ANTIGRAVITY_MODEL_ABBREV = {
|
|
|
228
178
|
"Gemini 3.5 Flash (High)": "Fh",
|
|
229
179
|
"Gemini 3.5 Flash (Medium)": "Fm",
|
|
230
180
|
"Gemini 3.5 Flash (Low)": "Fl",
|
|
231
|
-
"Gemini 3.1 Pro (High)": "Ph",
|
|
232
|
-
"Gemini 3.1 Pro (Low)": "Pl",
|
|
233
|
-
"Gemini 3 Flash": "F3",
|
|
234
|
-
// Claude family — 각자 별도 quota
|
|
235
|
-
"Claude Sonnet 4.6 (Thinking)": "Cs",
|
|
236
|
-
"Claude Opus 4.6 (Thinking)": "Co",
|
|
237
|
-
// GPT-OSS family — 각자 별도 quota
|
|
238
|
-
"GPT-OSS 120B (Medium)": "Go",
|
|
239
181
|
};
|
|
240
|
-
export const GEMINI_QUOTA_CACHE_PATH = join(
|
|
241
|
-
homedir(),
|
|
242
|
-
".claude",
|
|
243
|
-
"cache",
|
|
244
|
-
"gemini-quota-cache.json",
|
|
245
|
-
);
|
|
246
|
-
export const GEMINI_PROJECT_CACHE_PATH = join(
|
|
247
|
-
homedir(),
|
|
248
|
-
".claude",
|
|
249
|
-
"cache",
|
|
250
|
-
"gemini-project-id.json",
|
|
251
|
-
);
|
|
252
|
-
export const GEMINI_SESSION_CACHE_PATH = join(
|
|
253
|
-
homedir(),
|
|
254
|
-
".claude",
|
|
255
|
-
"cache",
|
|
256
|
-
"gemini-session-cache.json",
|
|
257
|
-
);
|
|
258
182
|
export const TFX_PREFLIGHT_CACHE_PATH = join(
|
|
259
183
|
homedir(),
|
|
260
184
|
".claude",
|
|
@@ -262,42 +186,6 @@ export const TFX_PREFLIGHT_CACHE_PATH = join(
|
|
|
262
186
|
"tfx-preflight.json",
|
|
263
187
|
);
|
|
264
188
|
export const TFX_PREFLIGHT_CACHE_STALE_MS = 60 * 60 * 1000;
|
|
265
|
-
export const GEMINI_RPM_TRACKER_PATH = join(
|
|
266
|
-
homedir(),
|
|
267
|
-
".claude",
|
|
268
|
-
"cache",
|
|
269
|
-
"gemini-rpm-tracker.json",
|
|
270
|
-
);
|
|
271
|
-
// 이전 .omc/ 경로 fallback (기존 환경 호환)
|
|
272
|
-
export const LEGACY_GEMINI_QUOTA_CACHE = join(
|
|
273
|
-
homedir(),
|
|
274
|
-
".omc",
|
|
275
|
-
"state",
|
|
276
|
-
"gemini_quota_cache.json",
|
|
277
|
-
);
|
|
278
|
-
export const LEGACY_GEMINI_PROJECT_CACHE = join(
|
|
279
|
-
homedir(),
|
|
280
|
-
".omc",
|
|
281
|
-
"state",
|
|
282
|
-
"gemini_project_id.json",
|
|
283
|
-
);
|
|
284
|
-
export const LEGACY_GEMINI_SESSION_CACHE = join(
|
|
285
|
-
homedir(),
|
|
286
|
-
".omc",
|
|
287
|
-
"state",
|
|
288
|
-
"gemini_session_tokens_cache.json",
|
|
289
|
-
);
|
|
290
|
-
export const LEGACY_GEMINI_RPM_TRACKER = join(
|
|
291
|
-
homedir(),
|
|
292
|
-
".omc",
|
|
293
|
-
"state",
|
|
294
|
-
"gemini_rpm_tracker.json",
|
|
295
|
-
);
|
|
296
|
-
|
|
297
|
-
export const GEMINI_RPM_WINDOW_MS = 60 * 1000; // 60초 슬라이딩 윈도우
|
|
298
|
-
export const GEMINI_QUOTA_STALE_MS = 5 * 60 * 1000; // 5분
|
|
299
|
-
export const GEMINI_SESSION_STALE_MS = 30 * 1000; // 30초
|
|
300
|
-
export const GEMINI_API_TIMEOUT_MS = 3000; // 3초
|
|
301
189
|
|
|
302
190
|
export const ACCOUNT_LABEL_WIDTH = 10;
|
|
303
191
|
export const PROVIDER_PREFIX_WIDTH = 2;
|
|
@@ -306,27 +194,8 @@ export const TIME_CELL_INNER_WIDTH = 6;
|
|
|
306
194
|
|
|
307
195
|
export const CLAUDE_REFRESH_FLAG = "--refresh-claude-usage";
|
|
308
196
|
export const CODEX_REFRESH_FLAG = "--refresh-codex-rate-limits";
|
|
309
|
-
export const GEMINI_REFRESH_FLAG = "--refresh-gemini-quota";
|
|
310
|
-
export const GEMINI_SESSION_REFRESH_FLAG = "--refresh-gemini-session";
|
|
311
197
|
|
|
312
198
|
// 모바일/Termux 컴팩트 모드 감지
|
|
313
199
|
export const HUD_CONFIG_PATH = join(homedir(), ".omc", "config", "hud.json");
|
|
314
200
|
export const COMPACT_COLS_THRESHOLD = 80;
|
|
315
201
|
export const MINIMAL_COLS_THRESHOLD = 60;
|
|
316
|
-
|
|
317
|
-
// rows 임계값 상수 (selectTier 에서 tier 결정에 사용)
|
|
318
|
-
export const ROWS_BUDGET_FULL = 40;
|
|
319
|
-
export const ROWS_BUDGET_LARGE = 35;
|
|
320
|
-
export const ROWS_BUDGET_MEDIUM = 28;
|
|
321
|
-
export const ROWS_BUDGET_SMALL = 22;
|
|
322
|
-
|
|
323
|
-
// Gemini Pro 풀 공유 그룹: 같은 remainingFraction을 공유하는 모델 ID들
|
|
324
|
-
export const GEMINI_PRO_POOL = new Set([
|
|
325
|
-
"gemini-2.5-pro",
|
|
326
|
-
"gemini-3-pro-preview",
|
|
327
|
-
"gemini-3.1-pro-preview",
|
|
328
|
-
]);
|
|
329
|
-
export const GEMINI_FLASH_POOL = new Set([
|
|
330
|
-
"gemini-2.5-flash",
|
|
331
|
-
"gemini-3-flash-preview",
|
|
332
|
-
]);
|