@triflux/remote 10.91.0 → 10.92.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/team/headless.mjs
CHANGED
|
@@ -11,11 +11,15 @@ import {
|
|
|
11
11
|
writeFileSync,
|
|
12
12
|
} from "node:fs";
|
|
13
13
|
import { createRequire } from "node:module";
|
|
14
|
+
import { homedir } from "node:os";
|
|
14
15
|
import { delimiter, dirname, isAbsolute, join, resolve } from "node:path";
|
|
15
16
|
import { fileURLToPath } from "node:url";
|
|
16
17
|
import { resolveNestedCodexAgentProfile } from "../../scripts/lib/agent-route-policy.mjs";
|
|
17
18
|
import { escapePwshSingleQuoted } from "@triflux/core/hub/cli-adapter-base.mjs";
|
|
18
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
judgeWorkerHealth,
|
|
21
|
+
recordMcpSelectionShadow,
|
|
22
|
+
} from "@triflux/core/hub/lib/jev-addon.mjs";
|
|
19
23
|
import { privateTmpDir } from "@triflux/core/hub/lib/private-tmp.mjs";
|
|
20
24
|
import {
|
|
21
25
|
createActivityLifecycle,
|
|
@@ -227,6 +231,34 @@ const MCP_PROFILE_HINTS = {
|
|
|
227
231
|
docs: "Focus on documentation and explanation tasks.",
|
|
228
232
|
};
|
|
229
233
|
|
|
234
|
+
function claudeMcpServerNames(cwd = process.cwd()) {
|
|
235
|
+
const names = new Set();
|
|
236
|
+
for (const file of [
|
|
237
|
+
join(process.env.HOME || homedir(), ".claude.json"),
|
|
238
|
+
join(cwd, ".mcp.json"),
|
|
239
|
+
]) {
|
|
240
|
+
try {
|
|
241
|
+
const servers = JSON.parse(readFileSync(file, "utf8")).mcpServers;
|
|
242
|
+
for (const name of Object.keys(servers ?? {})) names.add(name);
|
|
243
|
+
} catch {
|
|
244
|
+
// 없는 설정 파일은 후보에서 뺀다.
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return [...names];
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// 워커 실행과 무관한 기록이라 기다리지 않고, 실패해도 워커에 영향을 주지 않는다.
|
|
251
|
+
function shadowClaudeMcpSelection(assignment) {
|
|
252
|
+
if (assignment.cli !== "claude") return;
|
|
253
|
+
recordMcpSelectionShadow({
|
|
254
|
+
taskText: assignment.prompt,
|
|
255
|
+
agentType: assignment.role || "default",
|
|
256
|
+
availableServers: claudeMcpServerNames(
|
|
257
|
+
assignment.cwd || assignment.workdir,
|
|
258
|
+
),
|
|
259
|
+
}).catch(() => {});
|
|
260
|
+
}
|
|
261
|
+
|
|
230
262
|
export function buildHeadlessCommand(cli, prompt, resultFile, opts = {}) {
|
|
231
263
|
const { handoff = true, mcp, contextFile, model, cwd } = opts;
|
|
232
264
|
const resolvedCli = resolveCliType(cli);
|
|
@@ -599,6 +631,7 @@ async function dispatchProgressive(sessionName, assignments, opts = {}) {
|
|
|
599
631
|
const resultFile = headlessResultFile(sessionName, paneName);
|
|
600
632
|
// Issue #118 review R1 HIGH: stale artifact 제거 (이전 run / restart 잔재)
|
|
601
633
|
cleanStaleResultArtifacts(resultFile);
|
|
634
|
+
shadowClaudeMcpSelection(assignment);
|
|
602
635
|
const cmd = buildHeadlessCommand(
|
|
603
636
|
assignment.cli,
|
|
604
637
|
assignment.prompt,
|
|
@@ -687,6 +720,7 @@ async function dispatchBatch(sessionName, assignments, opts = {}) {
|
|
|
687
720
|
const resultFile = headlessResultFile(sessionName, paneName);
|
|
688
721
|
// Issue #118 review R1 HIGH: stale artifact 제거 (이전 run / restart 잔재)
|
|
689
722
|
cleanStaleResultArtifacts(resultFile);
|
|
723
|
+
shadowClaudeMcpSelection(assignment);
|
|
690
724
|
const cmd = buildHeadlessCommand(
|
|
691
725
|
assignment.cli,
|
|
692
726
|
assignment.prompt,
|
package/package.json
CHANGED
|
@@ -187,6 +187,15 @@ const CANONICAL_CODEX_PROFILE_OVERRIDES = Object.freeze(
|
|
|
187
187
|
"astra_ultra",
|
|
188
188
|
]),
|
|
189
189
|
);
|
|
190
|
+
// 비용 순서다. Jev 는 방향만 답하고 등급은 여기서 한 단계만 옮긴다.
|
|
191
|
+
const CODEX_TIER_LADDER = Object.freeze([
|
|
192
|
+
"luna_low",
|
|
193
|
+
"luna_high",
|
|
194
|
+
"sol_med",
|
|
195
|
+
"sol_high",
|
|
196
|
+
"astra_xhigh",
|
|
197
|
+
]);
|
|
198
|
+
const NO_LOWER_CODEX_AGENTS = Object.freeze(new Set(["security-reviewer"]));
|
|
190
199
|
const ULTRA_ELIGIBLE_CODEX_AGENTS = Object.freeze(
|
|
191
200
|
new Set(["deep-executor", "scientist-deep"]),
|
|
192
201
|
);
|
|
@@ -212,6 +221,16 @@ export function resolveCodexAgentPolicy(agent) {
|
|
|
212
221
|
* later process-level `TFX_CODEX_PROFILE`. Ultra is reserved for an eligible
|
|
213
222
|
* top-level role; every nested/sandboxed or ineligible request is max.
|
|
214
223
|
*/
|
|
224
|
+
export function shiftCodexAgentProfile(agent, tierShift) {
|
|
225
|
+
const { profile } = resolveDirectCodexRoutePolicy(agent);
|
|
226
|
+
const index = CODEX_TIER_LADDER.indexOf(profile);
|
|
227
|
+
if (index === -1) return profile;
|
|
228
|
+
if (tierShift === "raise") return CODEX_TIER_LADDER[index + 1] ?? profile;
|
|
229
|
+
if (tierShift === "lower" && !NO_LOWER_CODEX_AGENTS.has(agent))
|
|
230
|
+
return CODEX_TIER_LADDER[index - 1] ?? profile;
|
|
231
|
+
return profile;
|
|
232
|
+
}
|
|
233
|
+
|
|
215
234
|
export function resolveCodexAgentProfile(
|
|
216
235
|
agent,
|
|
217
236
|
{
|
|
@@ -400,6 +419,7 @@ function parseCliArgs(argv) {
|
|
|
400
419
|
let profileOverride = "auto";
|
|
401
420
|
let geminiProfilesModule = "";
|
|
402
421
|
let nested = false;
|
|
422
|
+
let tierShift = "";
|
|
403
423
|
while (args.length > 0) {
|
|
404
424
|
const flag = args.shift();
|
|
405
425
|
if (flag === "--format") format = args.shift() || "";
|
|
@@ -410,6 +430,7 @@ function parseCliArgs(argv) {
|
|
|
410
430
|
else if (flag === "--gemini-profiles-module")
|
|
411
431
|
geminiProfilesModule = args.shift() || "";
|
|
412
432
|
else if (flag === "--nested") nested = true;
|
|
433
|
+
else if (flag === "--tier-shift") tierShift = args.shift() || "";
|
|
413
434
|
else throw new Error(`unknown argument: ${flag}`);
|
|
414
435
|
}
|
|
415
436
|
if (!new Set(["json", "tsv", "route"]).has(format)) {
|
|
@@ -422,6 +443,7 @@ function parseCliArgs(argv) {
|
|
|
422
443
|
profileOverride,
|
|
423
444
|
geminiProfilesModule,
|
|
424
445
|
nested,
|
|
446
|
+
tierShift,
|
|
425
447
|
};
|
|
426
448
|
}
|
|
427
449
|
|
|
@@ -433,9 +455,14 @@ async function runCli() {
|
|
|
433
455
|
profileOverride,
|
|
434
456
|
geminiProfilesModule,
|
|
435
457
|
nested,
|
|
458
|
+
tierShift,
|
|
436
459
|
} = parseCliArgs(process.argv.slice(2));
|
|
437
460
|
if (format === "route") {
|
|
438
461
|
if (!mapFile) throw new Error("--map-file is required for route format");
|
|
462
|
+
const routedProfile =
|
|
463
|
+
tierShift && normalizeCodexProfileName(profileOverride) === "auto"
|
|
464
|
+
? shiftCodexAgentProfile(agent, tierShift)
|
|
465
|
+
: profileOverride;
|
|
439
466
|
const map = JSON.parse(readFileSync(mapFile, "utf8"));
|
|
440
467
|
let weeklyPercent = 0;
|
|
441
468
|
if (agent === "code-reviewer" || agent === "quality-reviewer") {
|
|
@@ -470,7 +497,7 @@ async function runCli() {
|
|
|
470
497
|
}
|
|
471
498
|
}
|
|
472
499
|
process.stdout.write(
|
|
473
|
-
resolveAgentRoute(agent, map,
|
|
500
|
+
resolveAgentRoute(agent, map, routedProfile, nested, resolver, {
|
|
474
501
|
reviewAuthor: process.env.TFX_REVIEW_AUTHOR ?? "codex",
|
|
475
502
|
weeklyPercent,
|
|
476
503
|
}).join("\x1e"),
|