@triflux/remote 10.47.0 → 10.48.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/codex-review.mjs +2 -3
- package/hub/team/cto-auto-collect.mjs +1 -1
- package/hub/team/cto-pull.mjs +1 -1
- package/hub/team/launcher-template.mjs +2 -1
- package/hub/workers/codex-mcp.mjs +27 -3
- package/package.json +1 -1
- package/scripts/lib/agent-route-policy.mjs +13 -13
- package/scripts/lib/codex-profile-config.mjs +10 -7
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Codex headless review helper. Runs a cross-model review of a git diff
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// intentionally because `tfx` is the sanctioned entry point).
|
|
2
|
+
// through node `spawn` rather than the Bash tool, because `tfx` is the
|
|
3
|
+
// sanctioned entry point for Codex.
|
|
5
4
|
//
|
|
6
5
|
// Contract:
|
|
7
6
|
// runCodexReview({ ref = "HEAD", base?: string, timeoutMs = 180_000 })
|
|
@@ -2,7 +2,7 @@ import { existsSync, statSync } from "node:fs";
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
4
|
import { resolveLakeRootDir } from "../../cto/lake-root.mjs";
|
|
5
|
-
import { resolveRoleControlSnapshot } from "
|
|
5
|
+
import { resolveRoleControlSnapshot } from "../lib/cto-env.mjs";
|
|
6
6
|
|
|
7
7
|
const DEFAULT_DEBOUNCE_MS = 120_000;
|
|
8
8
|
|
package/hub/team/cto-pull.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
-
import { resolveRoleControlSnapshot } from "
|
|
4
|
+
import { resolveRoleControlSnapshot } from "../lib/cto-env.mjs";
|
|
5
5
|
|
|
6
6
|
function defaultLakeRoot() {
|
|
7
7
|
return join(process.cwd(), ".triflux", "lake");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// hub/team/launcher-template.mjs — 결정론적 런처 생성
|
|
2
|
-
// 기존 codex-adapter와 Antigravity
|
|
2
|
+
// 기존 codex-adapter와 Antigravity print-value 계약을 소비하여
|
|
3
3
|
// 동일 입력 → 동일 args 배열을 보장한다.
|
|
4
4
|
// F1 해결: codex adapter가 --dangerously-bypass-approvals-and-sandbox 자동 추가
|
|
5
5
|
// F4 해결: codex exec "prompt" 인라인 (파이프/리다이렉트 아님)
|
|
@@ -18,6 +18,7 @@ function shellSingleQuote(value) {
|
|
|
18
18
|
|
|
19
19
|
function buildAntigravityArgs(opts = {}) {
|
|
20
20
|
const prompt = typeof opts.prompt === "string" ? opts.prompt : "";
|
|
21
|
+
// agy 1.1.27: --print 는 값(프롬프트) 필수, stdin 프롬프트 불가.
|
|
21
22
|
const command = `agy --dangerously-skip-permissions --print ${shellSingleQuote(prompt)}`;
|
|
22
23
|
if (opts.resultFile) {
|
|
23
24
|
return `${command} > ${shellSingleQuote(opts.resultFile)} 2>${shellSingleQuote(`${opts.resultFile}.err`)}`;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// hub/workers/codex-mcp.mjs — Codex MCP 서버 래퍼
|
|
2
|
-
import { readFileSync } from "node:fs";
|
|
2
|
+
import { appendFileSync, readFileSync } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import process from "node:process";
|
|
@@ -120,7 +120,7 @@ function readTomlScalar(raw, key) {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
|
-
* Resolve a Codex effort profile name (e.g. "
|
|
123
|
+
* Resolve a Codex effort profile name (e.g. "gpt61_sol_high") to its concrete
|
|
124
124
|
* `model` + reasoning effort. SSOT = the per-profile file written by
|
|
125
125
|
* `tfx setup` at `~/.codex/<profile>.config.toml`. Falls back to deriving the
|
|
126
126
|
* effort from the `<...>_<effort>` naming convention when the file is absent.
|
|
@@ -263,6 +263,21 @@ function isNoiseOnlyOutput(text) {
|
|
|
263
263
|
return NOISE_ONLY_OUTPUT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
+
// MCP tool responses are completion-buffered, so stdout cannot distinguish an
|
|
267
|
+
// active long-running call from a stuck one. The SDK delivers only genuine
|
|
268
|
+
// `notifications/progress` callbacks here; append one record per event for
|
|
269
|
+
// tfx-route's per-run heartbeat sidecar. This is intentionally best-effort:
|
|
270
|
+
// inability to write observability data must never change tool execution.
|
|
271
|
+
function recordMcpProgress(activityFile) {
|
|
272
|
+
if (typeof activityFile !== "string" || !activityFile) return;
|
|
273
|
+
try {
|
|
274
|
+
appendFileSync(activityFile, "progress\n");
|
|
275
|
+
} catch {
|
|
276
|
+
// The route's liveness file is diagnostic only. A missing/readonly file
|
|
277
|
+
// must leave the normal MCP request path untouched.
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
266
281
|
function watchBootstrapClose(transport) {
|
|
267
282
|
let active = true;
|
|
268
283
|
const promise = new Promise((_, reject) => {
|
|
@@ -429,6 +444,10 @@ export class CodexMcpWorker {
|
|
|
429
444
|
? options.bootstrapTimeoutMs
|
|
430
445
|
: DEFAULT_CODEX_MCP_BOOTSTRAP_TIMEOUT_MS;
|
|
431
446
|
this.retryOptions = normalizeRetryOptions(options.retryOptions);
|
|
447
|
+
this.activityFile =
|
|
448
|
+
typeof options.activityFile === "string"
|
|
449
|
+
? options.activityFile
|
|
450
|
+
: this.env.TFX_CODEX_MCP_ACTIVITY_FILE || "";
|
|
432
451
|
|
|
433
452
|
this.client = null;
|
|
434
453
|
this.transport = null;
|
|
@@ -614,7 +633,12 @@ export class CodexMcpWorker {
|
|
|
614
633
|
const nextRawResult = await this.client.callTool(
|
|
615
634
|
{ name: toolName, arguments: toolArguments },
|
|
616
635
|
undefined,
|
|
617
|
-
{
|
|
636
|
+
{
|
|
637
|
+
timeout: timeoutMs,
|
|
638
|
+
...(this.activityFile
|
|
639
|
+
? { onprogress: () => recordMcpProgress(this.activityFile) }
|
|
640
|
+
: {}),
|
|
641
|
+
},
|
|
618
642
|
);
|
|
619
643
|
|
|
620
644
|
const textContent = collectTextContent(nextRawResult.content);
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
|
|
8
8
|
const policy = {
|
|
9
9
|
executor: {
|
|
10
|
-
profile: "
|
|
10
|
+
profile: "gpt61_sol_high",
|
|
11
11
|
timeoutSec: 1080,
|
|
12
12
|
runMode: "fg",
|
|
13
13
|
opusOversight: false,
|
|
@@ -15,7 +15,7 @@ const policy = {
|
|
|
15
15
|
subcommand: "exec",
|
|
16
16
|
},
|
|
17
17
|
codex: {
|
|
18
|
-
profile: "
|
|
18
|
+
profile: "gpt61_sol_high",
|
|
19
19
|
timeoutSec: 1080,
|
|
20
20
|
runMode: "fg",
|
|
21
21
|
opusOversight: false,
|
|
@@ -31,7 +31,7 @@ const policy = {
|
|
|
31
31
|
subcommand: "exec",
|
|
32
32
|
},
|
|
33
33
|
cleanup: {
|
|
34
|
-
profile: "
|
|
34
|
+
profile: "gpt61_sol_med",
|
|
35
35
|
timeoutSec: 540,
|
|
36
36
|
runMode: "fg",
|
|
37
37
|
opusOversight: false,
|
|
@@ -39,7 +39,7 @@ const policy = {
|
|
|
39
39
|
subcommand: "exec",
|
|
40
40
|
},
|
|
41
41
|
deslop: {
|
|
42
|
-
profile: "
|
|
42
|
+
profile: "gpt61_sol_med",
|
|
43
43
|
timeoutSec: 540,
|
|
44
44
|
runMode: "fg",
|
|
45
45
|
opusOversight: false,
|
|
@@ -95,7 +95,7 @@ const policy = {
|
|
|
95
95
|
subcommand: "exec",
|
|
96
96
|
},
|
|
97
97
|
"code-reviewer": {
|
|
98
|
-
profile: "
|
|
98
|
+
profile: "gpt61_sol_high",
|
|
99
99
|
timeoutSec: 1800,
|
|
100
100
|
runMode: "bg",
|
|
101
101
|
opusOversight: false,
|
|
@@ -103,7 +103,7 @@ const policy = {
|
|
|
103
103
|
subcommand: "review",
|
|
104
104
|
},
|
|
105
105
|
"quality-reviewer": {
|
|
106
|
-
profile: "
|
|
106
|
+
profile: "gpt61_sol_high",
|
|
107
107
|
timeoutSec: 1800,
|
|
108
108
|
runMode: "bg",
|
|
109
109
|
opusOversight: false,
|
|
@@ -119,7 +119,7 @@ const policy = {
|
|
|
119
119
|
subcommand: "review",
|
|
120
120
|
},
|
|
121
121
|
scientist: {
|
|
122
|
-
profile: "
|
|
122
|
+
profile: "gpt61_sol_high",
|
|
123
123
|
timeoutSec: 1440,
|
|
124
124
|
runMode: "bg",
|
|
125
125
|
opusOversight: false,
|
|
@@ -127,7 +127,7 @@ const policy = {
|
|
|
127
127
|
subcommand: "exec",
|
|
128
128
|
},
|
|
129
129
|
"document-specialist": {
|
|
130
|
-
profile: "
|
|
130
|
+
profile: "gpt61_sol_high",
|
|
131
131
|
timeoutSec: 1440,
|
|
132
132
|
runMode: "bg",
|
|
133
133
|
opusOversight: false,
|
|
@@ -143,7 +143,7 @@ const policy = {
|
|
|
143
143
|
subcommand: "exec",
|
|
144
144
|
},
|
|
145
145
|
verifier: {
|
|
146
|
-
profile: "
|
|
146
|
+
profile: "gpt61_sol_high",
|
|
147
147
|
timeoutSec: 1200,
|
|
148
148
|
runMode: "fg",
|
|
149
149
|
opusOversight: false,
|
|
@@ -151,7 +151,7 @@ const policy = {
|
|
|
151
151
|
subcommand: "review",
|
|
152
152
|
},
|
|
153
153
|
"test-engineer": {
|
|
154
|
-
profile: "
|
|
154
|
+
profile: "gpt61_sol_high",
|
|
155
155
|
timeoutSec: 1200,
|
|
156
156
|
runMode: "bg",
|
|
157
157
|
opusOversight: false,
|
|
@@ -159,7 +159,7 @@ const policy = {
|
|
|
159
159
|
subcommand: "exec",
|
|
160
160
|
},
|
|
161
161
|
"qa-tester": {
|
|
162
|
-
profile: "
|
|
162
|
+
profile: "gpt61_sol_high",
|
|
163
163
|
timeoutSec: 1200,
|
|
164
164
|
runMode: "bg",
|
|
165
165
|
opusOversight: false,
|
|
@@ -212,8 +212,8 @@ export const CANONICAL_CODEX_PROFILE_OVERRIDES = Object.freeze(
|
|
|
212
212
|
new Set([
|
|
213
213
|
"gpt6_luna_low",
|
|
214
214
|
"gpt6_luna_high",
|
|
215
|
-
"
|
|
216
|
-
"
|
|
215
|
+
"gpt61_sol_med",
|
|
216
|
+
"gpt61_sol_high",
|
|
217
217
|
"gpt6_astra_xhigh",
|
|
218
218
|
"gpt6_astra_max",
|
|
219
219
|
"gpt6_astra_ultra",
|
|
@@ -21,22 +21,25 @@ const EFFORT_BY_SUFFIX = {
|
|
|
21
21
|
const CANONICAL_PROFILE_VALUES = Object.freeze({
|
|
22
22
|
gpt6_luna_low: { model: "gpt-6-luna", effort: "low" },
|
|
23
23
|
gpt6_luna_high: { model: "gpt-6-luna", effort: "high" },
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
gpt61_sol_med: { model: "gpt-6.1-sol", effort: "medium" },
|
|
25
|
+
gpt61_sol_high: { model: "gpt-6.1-sol", effort: "high" },
|
|
26
26
|
gpt6_astra_xhigh: { model: "gpt-6-astra", effort: "xhigh" },
|
|
27
27
|
gpt6_astra_max: { model: "gpt-6-astra", effort: "max" },
|
|
28
28
|
gpt6_astra_ultra: { model: "gpt-6-astra", effort: "ultra" },
|
|
29
29
|
});
|
|
30
30
|
|
|
31
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.
|
|
32
|
+
// Terra tier, so Terra lanes move to Sol. GPT-6 Sol lane names map to GPT-6.1
|
|
33
|
+
// Sol with the same effort.
|
|
33
34
|
const LEGACY_CANONICAL_PROFILE_ALIASES = Object.freeze({
|
|
34
35
|
gpt56_sol_xhigh: "gpt6_astra_xhigh",
|
|
35
36
|
gpt56_sol_max: "gpt6_astra_max",
|
|
36
37
|
gpt56_sol_ultra: "gpt6_astra_ultra",
|
|
37
|
-
gpt56_terra_high: "
|
|
38
|
-
gpt56_terra_med: "
|
|
38
|
+
gpt56_terra_high: "gpt61_sol_high",
|
|
39
|
+
gpt56_terra_med: "gpt61_sol_med",
|
|
39
40
|
gpt56_luna_low: "gpt6_luna_low",
|
|
41
|
+
gpt6_sol_high: "gpt61_sol_high",
|
|
42
|
+
gpt6_sol_med: "gpt61_sol_med",
|
|
40
43
|
});
|
|
41
44
|
|
|
42
45
|
export function normalizeCodexProfileName(profileName) {
|
|
@@ -65,7 +68,7 @@ function readProfileScalar(raw, key) {
|
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
/**
|
|
68
|
-
* Resolve a Codex effort profile name (e.g. "
|
|
71
|
+
* Resolve a Codex effort profile name (e.g. "gpt61_sol_high") to the `-c key=value`
|
|
69
72
|
* config overrides that `codex exec` accepts, so the headless CLI lanes can
|
|
70
73
|
* select a profile WITHOUT `codex exec --profile <name>`. codex 0.134+ rejects
|
|
71
74
|
* `--profile X` whenever config.toml still contains an inline `[profiles.X]`
|
|
@@ -83,7 +86,7 @@ function readProfileScalar(raw, key) {
|
|
|
83
86
|
*
|
|
84
87
|
* @param {string} profileName
|
|
85
88
|
* @param {{ codexHome?: string }} [opts]
|
|
86
|
-
* @returns {string[]} e.g. ['model="gpt-6-sol"', 'model_reasoning_effort="high"']
|
|
89
|
+
* @returns {string[]} e.g. ['model="gpt-6.1-sol"', 'model_reasoning_effort="high"']
|
|
87
90
|
*/
|
|
88
91
|
export function resolveCodexProfileConfigValues(profileName, opts = {}) {
|
|
89
92
|
if (typeof profileName !== "string" || !profileName) {
|