@triflux/remote 10.42.0 → 10.44.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/cto/hygiene.mjs +1 -1
- package/hub/lib/cto-env.mjs +1 -0
- package/hub/pipe.mjs +9 -0
- package/hub/schema.sql +62 -2
- package/hub/server.mjs +131 -44
- package/hub/store.mjs +616 -19
- package/hub/team/claude-daemon-control.mjs +33 -12
- package/hub/team/cli/commands/start/parse-args.mjs +2 -2
- package/hub/team/conductor.mjs +23 -2
- package/hub/team/execution-mode.mjs +12 -7
- package/hub/team/headless.mjs +311 -24
- package/hub/team/intervention.mjs +530 -0
- package/hub/team/notify.mjs +31 -11
- package/hub/team/retry-state-machine.mjs +12 -3
- package/hub/team/swarm-hypervisor.mjs +21 -2
- package/hub/team/swarm-locks.mjs +17 -1
- package/hub/team/swarm-preflight.mjs +47 -0
- package/hub/team/uds-orchestrator.mjs +62 -9
- package/hub/team/worktree-lifecycle.mjs +56 -59
- package/hub/tools.mjs +16 -3
- package/hub/workers/codex-app-server-worker.mjs +54 -5
- package/hub/workers/codex-mcp.mjs +21 -5
- package/hub/workers/delegator-mcp.mjs +3 -49
- package/package.json +1 -1
- package/scripts/lib/agent-route-policy.mjs +307 -0
- package/scripts/lib/cli-agy.mjs +1 -0
- package/scripts/lib/cli-claude.mjs +1 -0
- package/scripts/lib/cli-codex.mjs +21 -160
- package/scripts/lib/codex-profile-config.mjs +31 -5
- package/scripts/lib/keyword-rules.mjs +12 -0
- package/cto/steward.mjs +0 -362
- package/hub/log-retention.mjs +0 -726
|
@@ -12,6 +12,12 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
12
12
|
import { isAbsolute } from "node:path";
|
|
13
13
|
import process from "node:process";
|
|
14
14
|
|
|
15
|
+
import {
|
|
16
|
+
createActivityLifecycle,
|
|
17
|
+
isActivityLifecycleEnabled,
|
|
18
|
+
resolveHardCeilingMs,
|
|
19
|
+
resolveStallInterventionMs,
|
|
20
|
+
} from "@triflux/core/hub/lib/worker-lifecycle.mjs";
|
|
15
21
|
import {
|
|
16
22
|
JsonRpcProtocolError,
|
|
17
23
|
JsonRpcStdioClient,
|
|
@@ -25,6 +31,7 @@ export const CODEX_APP_SERVER_TRANSPORT_EXIT_CODE = 70;
|
|
|
25
31
|
export const CODEX_APP_SERVER_TIMEOUT_EXIT_CODE = 124;
|
|
26
32
|
|
|
27
33
|
export const DEFAULT_CODEX_APP_SERVER_BOOTSTRAP_TIMEOUT_MS = 10_000;
|
|
34
|
+
// Legacy wall-clock default retained for TFX_ACTIVITY_LIFECYCLE=0 compatibility.
|
|
28
35
|
export const DEFAULT_CODEX_APP_SERVER_EXECUTION_TIMEOUT_MS = 10 * 60 * 1000;
|
|
29
36
|
export const DEFAULT_UNKNOWN_METHOD_WARN_THRESHOLD = 5;
|
|
30
37
|
/**
|
|
@@ -327,6 +334,7 @@ export class CodexAppServerWorker {
|
|
|
327
334
|
* @param {number} [options.unknownMethodWarnThreshold]
|
|
328
335
|
* @param {(method: string) => void} [options.onUnknownMethod]
|
|
329
336
|
* @param {(label: string, payload: object) => void} [options.warn]
|
|
337
|
+
* @param {(context: object) => Promise<boolean|string>|boolean|string} [options.interveneFn]
|
|
330
338
|
*/
|
|
331
339
|
constructor(options = {}) {
|
|
332
340
|
this.command = options.command || process.env.CODEX_BIN || "codex";
|
|
@@ -370,6 +378,8 @@ export class CodexAppServerWorker {
|
|
|
370
378
|
typeof options.onUnknownMethod === "function"
|
|
371
379
|
? options.onUnknownMethod
|
|
372
380
|
: null;
|
|
381
|
+
this._interveneFn =
|
|
382
|
+
typeof options.interveneFn === "function" ? options.interveneFn : null;
|
|
373
383
|
|
|
374
384
|
/** @type {import('node:child_process').ChildProcess | null} */
|
|
375
385
|
this.child = null;
|
|
@@ -643,6 +653,8 @@ export class CodexAppServerWorker {
|
|
|
643
653
|
}
|
|
644
654
|
|
|
645
655
|
const outputParts = [];
|
|
656
|
+
let lastActivityAt = Date.now();
|
|
657
|
+
let activityLifecycle = null;
|
|
646
658
|
const unknownMethodsThisTurn = new Set();
|
|
647
659
|
let threadId =
|
|
648
660
|
typeof opts.threadId === "string" && opts.threadId ? opts.threadId : null;
|
|
@@ -714,6 +726,10 @@ export class CodexAppServerWorker {
|
|
|
714
726
|
};
|
|
715
727
|
|
|
716
728
|
const handleNotification = (method, params) => {
|
|
729
|
+
// Any notification, including unknown and opt-out methods, proves the
|
|
730
|
+
// transport is live. Content filtering below remains unchanged.
|
|
731
|
+
lastActivityAt = Date.now();
|
|
732
|
+
activityLifecycle?.observe();
|
|
717
733
|
// AC5 defense: opt-out should already be filtered server-side.
|
|
718
734
|
if (OPT_OUT_METHODS.includes(method)) return;
|
|
719
735
|
|
|
@@ -854,16 +870,40 @@ export class CodexAppServerWorker {
|
|
|
854
870
|
};
|
|
855
871
|
}
|
|
856
872
|
|
|
857
|
-
//
|
|
873
|
+
// In activity mode timeoutMs is the inactivity window. Notifications
|
|
874
|
+
// re-arm the lifecycle; hardCeilingMs remains the leak-prevention bound.
|
|
875
|
+
const activityEnabled = isActivityLifecycleEnabled();
|
|
858
876
|
const timeoutMs = Number.isFinite(opts.timeoutMs)
|
|
859
877
|
? opts.timeoutMs
|
|
860
|
-
:
|
|
878
|
+
: activityEnabled
|
|
879
|
+
? resolveStallInterventionMs()
|
|
880
|
+
: DEFAULT_CODEX_APP_SERVER_EXECUTION_TIMEOUT_MS;
|
|
881
|
+
const hardCeilingMs = Number.isFinite(opts.hardCeilingMs)
|
|
882
|
+
? opts.hardCeilingMs
|
|
883
|
+
: resolveHardCeilingMs();
|
|
861
884
|
// Capture current child so a stale timer (post-result) cannot SIGTERM a
|
|
862
885
|
// later reused worker's child process.
|
|
863
886
|
const capturedChild = this.child;
|
|
887
|
+
activityLifecycle = createActivityLifecycle({
|
|
888
|
+
enabled: activityEnabled,
|
|
889
|
+
interventionMs: timeoutMs,
|
|
890
|
+
hardCeilingMs,
|
|
891
|
+
onIntervene: async (context) => {
|
|
892
|
+
if (this._interveneFn) {
|
|
893
|
+
const result = await this._interveneFn({
|
|
894
|
+
threadId,
|
|
895
|
+
client,
|
|
896
|
+
lastActivityAt,
|
|
897
|
+
...context,
|
|
898
|
+
});
|
|
899
|
+
return result === true || result === "resolved";
|
|
900
|
+
}
|
|
901
|
+
return false;
|
|
902
|
+
},
|
|
903
|
+
});
|
|
864
904
|
const timeoutPromise = new Promise((resolve) => {
|
|
865
|
-
|
|
866
|
-
this._warn("execution timeout", { timeoutMs });
|
|
905
|
+
const fire = (reason) => {
|
|
906
|
+
this._warn("execution timeout", { timeoutMs, reason });
|
|
867
907
|
try {
|
|
868
908
|
capturedChild?.kill?.("SIGTERM");
|
|
869
909
|
} catch {}
|
|
@@ -878,7 +918,16 @@ export class CodexAppServerWorker {
|
|
|
878
918
|
),
|
|
879
919
|
raw: null,
|
|
880
920
|
});
|
|
881
|
-
}
|
|
921
|
+
};
|
|
922
|
+
const arm = () => {
|
|
923
|
+
timer = setTimeout(async () => {
|
|
924
|
+
if (!activityEnabled) return fire("timeout");
|
|
925
|
+
const reason = await activityLifecycle.check({ threadId, client });
|
|
926
|
+
if (reason) return fire(reason);
|
|
927
|
+
arm();
|
|
928
|
+
}, timeoutMs);
|
|
929
|
+
};
|
|
930
|
+
arm();
|
|
882
931
|
});
|
|
883
932
|
|
|
884
933
|
const result = await Promise.race([resultPromise, timeoutPromise]);
|
|
@@ -119,7 +119,7 @@ function readTomlScalar(raw, key) {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
/**
|
|
122
|
-
* Resolve a Codex effort profile name (e.g. "
|
|
122
|
+
* Resolve a Codex effort profile name (e.g. "gpt56_terra_high") to its concrete
|
|
123
123
|
* `model` + reasoning effort. SSOT = the per-profile file written by
|
|
124
124
|
* `tfx setup` at `~/.codex/<profile>.config.toml`. Falls back to deriving the
|
|
125
125
|
* effort from the `<...>_<effort>` naming convention when the file is absent.
|
|
@@ -146,9 +146,11 @@ export function resolveCodexProfileConfig(profileName) {
|
|
|
146
146
|
} catch {
|
|
147
147
|
// Profile file absent (non-file alias). Derive effort from the naming
|
|
148
148
|
// convention; leave model unset so codex uses its config.toml default.
|
|
149
|
-
const suffix = /_(xhigh|high|med|medium|low)$/.exec(profileName);
|
|
149
|
+
const suffix = /_(ultra|max|xhigh|high|med|medium|low)$/.exec(profileName);
|
|
150
150
|
if (suffix) {
|
|
151
151
|
const map = {
|
|
152
|
+
ultra: "ultra",
|
|
153
|
+
max: "max",
|
|
152
154
|
xhigh: "xhigh",
|
|
153
155
|
high: "high",
|
|
154
156
|
med: "medium",
|
|
@@ -193,16 +195,27 @@ export function buildCodexArguments(prompt, opts = {}) {
|
|
|
193
195
|
// profile effort merges on top of any opts.config.
|
|
194
196
|
if (typeof opts.profile === "string" && opts.profile) {
|
|
195
197
|
const resolved = resolveCodexProfileConfig(opts.profile);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
+
const profileDerivedUltra =
|
|
199
|
+
resolved.reasoningEffort?.toLowerCase() === "ultra";
|
|
200
|
+
if (typeof args.model !== "string") {
|
|
201
|
+
if (profileDerivedUltra) args.model = "gpt-5.6-sol";
|
|
202
|
+
else if (resolved.model) args.model = resolved.model;
|
|
198
203
|
}
|
|
199
204
|
if (resolved.reasoningEffort) {
|
|
200
205
|
args.config = {
|
|
201
206
|
...(args.config || {}),
|
|
202
|
-
model_reasoning_effort:
|
|
207
|
+
model_reasoning_effort: profileDerivedUltra
|
|
208
|
+
? "max"
|
|
209
|
+
: resolved.reasoningEffort,
|
|
203
210
|
};
|
|
204
211
|
}
|
|
205
212
|
}
|
|
213
|
+
if (typeof opts.reasoningEffort === "string" && opts.reasoningEffort) {
|
|
214
|
+
args.config = {
|
|
215
|
+
...(args.config || {}),
|
|
216
|
+
model_reasoning_effort: opts.reasoningEffort,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
206
219
|
|
|
207
220
|
return args;
|
|
208
221
|
}
|
|
@@ -694,6 +707,9 @@ function parseCliArgs(argv) {
|
|
|
694
707
|
case "--model":
|
|
695
708
|
options.model = next();
|
|
696
709
|
break;
|
|
710
|
+
case "--reasoning-effort":
|
|
711
|
+
options.reasoningEffort = next();
|
|
712
|
+
break;
|
|
697
713
|
case "--approval-policy":
|
|
698
714
|
options.approvalPolicy = next();
|
|
699
715
|
break;
|
|
@@ -11,6 +11,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
11
11
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
12
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
13
13
|
import * as z from "zod";
|
|
14
|
+
import { resolveCodexAgentPolicy } from "@triflux/core/scripts/lib/agent-route-policy.mjs";
|
|
14
15
|
import { resolveBashExecutable } from "@triflux/core/hub/lib/bash-path.mjs";
|
|
15
16
|
import { runHeadlessWithCleanup } from "../team/headless.mjs";
|
|
16
17
|
import { buildWorkerSandboxEnv } from "../team/worker-sandbox.mjs";
|
|
@@ -33,57 +34,11 @@ const { buildPromptHint, getCodexMcpConfig, SUPPORTED_MCP_PROFILES } =
|
|
|
33
34
|
await import(pathToFileURL(mcpFilterPath).href);
|
|
34
35
|
const SERVER_INFO = { name: "triflux-delegator", version: "1.0.0" };
|
|
35
36
|
const DEFAULT_CONTEXT_BYTES = 32 * 1024;
|
|
36
|
-
const DEFAULT_ROUTE_TIMEOUT_SEC = 120;
|
|
37
37
|
const DIRECT_PROGRESS_START = 5;
|
|
38
38
|
const DIRECT_PROGRESS_RUNNING = 60;
|
|
39
39
|
const DIRECT_PROGRESS_DONE = 100;
|
|
40
40
|
const SEARCH_ENGINE_CACHE_PATH = [".omc", "state", "search-engines.json"];
|
|
41
41
|
|
|
42
|
-
const AGENT_TIMEOUT_SEC = Object.freeze({
|
|
43
|
-
executor: 1080,
|
|
44
|
-
"build-fixer": 540,
|
|
45
|
-
debugger: 900,
|
|
46
|
-
"deep-executor": 3600,
|
|
47
|
-
architect: 3600,
|
|
48
|
-
planner: 3600,
|
|
49
|
-
critic: 3600,
|
|
50
|
-
analyst: 3600,
|
|
51
|
-
"code-reviewer": 1800,
|
|
52
|
-
"security-reviewer": 1800,
|
|
53
|
-
"quality-reviewer": 1800,
|
|
54
|
-
scientist: 1440,
|
|
55
|
-
"scientist-deep": 3600,
|
|
56
|
-
"document-specialist": 1440,
|
|
57
|
-
designer: 900,
|
|
58
|
-
writer: 900,
|
|
59
|
-
explore: 300,
|
|
60
|
-
verifier: 1200,
|
|
61
|
-
"test-engineer": 300,
|
|
62
|
-
"qa-tester": 300,
|
|
63
|
-
spark: 180,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
const CODEX_PROFILE_BY_AGENT = Object.freeze({
|
|
67
|
-
executor: "gpt55_high",
|
|
68
|
-
"build-fixer": "gpt55_low",
|
|
69
|
-
debugger: "gpt55_xhigh",
|
|
70
|
-
"deep-executor": "gpt55_xhigh",
|
|
71
|
-
architect: "gpt55_xhigh",
|
|
72
|
-
planner: "gpt55_xhigh",
|
|
73
|
-
critic: "gpt55_xhigh",
|
|
74
|
-
analyst: "gpt55_xhigh",
|
|
75
|
-
"code-reviewer": "gpt55_high",
|
|
76
|
-
"security-reviewer": "gpt55_xhigh",
|
|
77
|
-
"quality-reviewer": "gpt55_high",
|
|
78
|
-
scientist: "gpt55_high",
|
|
79
|
-
"scientist-deep": "gpt55_xhigh",
|
|
80
|
-
"document-specialist": "gpt55_high",
|
|
81
|
-
verifier: "gpt55_high",
|
|
82
|
-
designer: "gpt55_xhigh",
|
|
83
|
-
writer: "gpt55_low",
|
|
84
|
-
spark: "gpt55_low",
|
|
85
|
-
});
|
|
86
|
-
|
|
87
42
|
const REVIEW_INSTRUCTION_BY_AGENT = Object.freeze({
|
|
88
43
|
"code-reviewer":
|
|
89
44
|
"코드 리뷰 모드로 동작하라. 버그, 리스크, 회귀, 테스트 누락을 우선 식별하라.",
|
|
@@ -137,7 +92,7 @@ function resolveRouteScript(explicitPath, cwd = process.cwd()) {
|
|
|
137
92
|
}
|
|
138
93
|
|
|
139
94
|
function resolveCodexProfile(agentType) {
|
|
140
|
-
return
|
|
95
|
+
return resolveCodexAgentPolicy(agentType).profile;
|
|
141
96
|
}
|
|
142
97
|
|
|
143
98
|
function normalizeProvider(provider = "auto") {
|
|
@@ -154,8 +109,7 @@ function resolveTimeoutMs(agentType, timeoutMs) {
|
|
|
154
109
|
return Math.trunc(timeoutMs);
|
|
155
110
|
}
|
|
156
111
|
|
|
157
|
-
|
|
158
|
-
return timeoutSec * 1000;
|
|
112
|
+
return resolveCodexAgentPolicy(agentType).timeoutSec * 1000;
|
|
159
113
|
}
|
|
160
114
|
|
|
161
115
|
function resolveTimeoutSec(agentType, timeoutMs) {
|
package/package.json
CHANGED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
// Canonical Codex role policy. Concrete model IDs stay in profile config files.
|
|
2
|
+
|
|
3
|
+
import { resolveCodexProfileConfigValues } from "./codex-profile-config.mjs";
|
|
4
|
+
|
|
5
|
+
const policy = {
|
|
6
|
+
executor: {
|
|
7
|
+
profile: "gpt56_terra_high",
|
|
8
|
+
timeoutSec: 1080,
|
|
9
|
+
runMode: "fg",
|
|
10
|
+
opusOversight: false,
|
|
11
|
+
mcpHint: "implement",
|
|
12
|
+
subcommand: "exec",
|
|
13
|
+
},
|
|
14
|
+
codex: {
|
|
15
|
+
profile: "gpt56_terra_high",
|
|
16
|
+
timeoutSec: 1080,
|
|
17
|
+
runMode: "fg",
|
|
18
|
+
opusOversight: false,
|
|
19
|
+
mcpHint: "implement",
|
|
20
|
+
subcommand: "exec",
|
|
21
|
+
},
|
|
22
|
+
"build-fixer": {
|
|
23
|
+
profile: "gpt56_luna_low",
|
|
24
|
+
timeoutSec: 540,
|
|
25
|
+
runMode: "fg",
|
|
26
|
+
opusOversight: false,
|
|
27
|
+
mcpHint: "implement",
|
|
28
|
+
subcommand: "exec",
|
|
29
|
+
},
|
|
30
|
+
cleanup: {
|
|
31
|
+
profile: "gpt56_terra_med",
|
|
32
|
+
timeoutSec: 540,
|
|
33
|
+
runMode: "fg",
|
|
34
|
+
opusOversight: false,
|
|
35
|
+
mcpHint: "implement",
|
|
36
|
+
subcommand: "exec",
|
|
37
|
+
},
|
|
38
|
+
deslop: {
|
|
39
|
+
profile: "gpt56_terra_med",
|
|
40
|
+
timeoutSec: 540,
|
|
41
|
+
runMode: "fg",
|
|
42
|
+
opusOversight: false,
|
|
43
|
+
mcpHint: "implement",
|
|
44
|
+
subcommand: "exec",
|
|
45
|
+
},
|
|
46
|
+
debugger: {
|
|
47
|
+
profile: "gpt56_sol_xhigh",
|
|
48
|
+
timeoutSec: 900,
|
|
49
|
+
runMode: "bg",
|
|
50
|
+
opusOversight: false,
|
|
51
|
+
mcpHint: "implement",
|
|
52
|
+
subcommand: "exec",
|
|
53
|
+
},
|
|
54
|
+
"deep-executor": {
|
|
55
|
+
profile: "gpt56_sol_xhigh",
|
|
56
|
+
timeoutSec: 3600,
|
|
57
|
+
runMode: "bg",
|
|
58
|
+
opusOversight: true,
|
|
59
|
+
mcpHint: "implement",
|
|
60
|
+
subcommand: "exec",
|
|
61
|
+
},
|
|
62
|
+
architect: {
|
|
63
|
+
profile: "gpt56_sol_xhigh",
|
|
64
|
+
timeoutSec: 3600,
|
|
65
|
+
runMode: "bg",
|
|
66
|
+
opusOversight: true,
|
|
67
|
+
mcpHint: "analyze",
|
|
68
|
+
subcommand: "exec",
|
|
69
|
+
},
|
|
70
|
+
critic: {
|
|
71
|
+
profile: "gpt56_sol_xhigh",
|
|
72
|
+
timeoutSec: 3600,
|
|
73
|
+
runMode: "bg",
|
|
74
|
+
opusOversight: true,
|
|
75
|
+
mcpHint: "analyze",
|
|
76
|
+
subcommand: "exec",
|
|
77
|
+
},
|
|
78
|
+
planner: {
|
|
79
|
+
profile: "gpt56_sol_xhigh",
|
|
80
|
+
timeoutSec: 3600,
|
|
81
|
+
runMode: "fg",
|
|
82
|
+
opusOversight: true,
|
|
83
|
+
mcpHint: "analyze",
|
|
84
|
+
subcommand: "exec",
|
|
85
|
+
},
|
|
86
|
+
analyst: {
|
|
87
|
+
profile: "gpt56_sol_xhigh",
|
|
88
|
+
timeoutSec: 3600,
|
|
89
|
+
runMode: "fg",
|
|
90
|
+
opusOversight: true,
|
|
91
|
+
mcpHint: "analyze",
|
|
92
|
+
subcommand: "exec",
|
|
93
|
+
},
|
|
94
|
+
"code-reviewer": {
|
|
95
|
+
profile: "gpt56_terra_high",
|
|
96
|
+
timeoutSec: 1800,
|
|
97
|
+
runMode: "bg",
|
|
98
|
+
opusOversight: false,
|
|
99
|
+
mcpHint: "review",
|
|
100
|
+
subcommand: "review",
|
|
101
|
+
},
|
|
102
|
+
"quality-reviewer": {
|
|
103
|
+
profile: "gpt56_terra_high",
|
|
104
|
+
timeoutSec: 1800,
|
|
105
|
+
runMode: "bg",
|
|
106
|
+
opusOversight: false,
|
|
107
|
+
mcpHint: "review",
|
|
108
|
+
subcommand: "review",
|
|
109
|
+
},
|
|
110
|
+
"security-reviewer": {
|
|
111
|
+
profile: "gpt56_sol_xhigh",
|
|
112
|
+
timeoutSec: 1800,
|
|
113
|
+
runMode: "bg",
|
|
114
|
+
opusOversight: true,
|
|
115
|
+
mcpHint: "review",
|
|
116
|
+
subcommand: "review",
|
|
117
|
+
},
|
|
118
|
+
scientist: {
|
|
119
|
+
profile: "gpt56_terra_high",
|
|
120
|
+
timeoutSec: 1440,
|
|
121
|
+
runMode: "bg",
|
|
122
|
+
opusOversight: false,
|
|
123
|
+
mcpHint: "analyze",
|
|
124
|
+
subcommand: "exec",
|
|
125
|
+
},
|
|
126
|
+
"document-specialist": {
|
|
127
|
+
profile: "gpt56_terra_high",
|
|
128
|
+
timeoutSec: 1440,
|
|
129
|
+
runMode: "bg",
|
|
130
|
+
opusOversight: false,
|
|
131
|
+
mcpHint: "analyze",
|
|
132
|
+
subcommand: "exec",
|
|
133
|
+
},
|
|
134
|
+
"scientist-deep": {
|
|
135
|
+
profile: "gpt56_sol_xhigh",
|
|
136
|
+
timeoutSec: 3600,
|
|
137
|
+
runMode: "bg",
|
|
138
|
+
opusOversight: false,
|
|
139
|
+
mcpHint: "analyze",
|
|
140
|
+
subcommand: "exec",
|
|
141
|
+
},
|
|
142
|
+
verifier: {
|
|
143
|
+
profile: "gpt56_terra_high",
|
|
144
|
+
timeoutSec: 1200,
|
|
145
|
+
runMode: "fg",
|
|
146
|
+
opusOversight: false,
|
|
147
|
+
mcpHint: "review",
|
|
148
|
+
subcommand: "review",
|
|
149
|
+
},
|
|
150
|
+
"test-engineer": {
|
|
151
|
+
profile: "gpt56_terra_high",
|
|
152
|
+
timeoutSec: 1200,
|
|
153
|
+
runMode: "bg",
|
|
154
|
+
opusOversight: false,
|
|
155
|
+
mcpHint: "implement",
|
|
156
|
+
subcommand: "exec",
|
|
157
|
+
},
|
|
158
|
+
"qa-tester": {
|
|
159
|
+
profile: "gpt56_terra_high",
|
|
160
|
+
timeoutSec: 1200,
|
|
161
|
+
runMode: "bg",
|
|
162
|
+
opusOversight: false,
|
|
163
|
+
mcpHint: "review",
|
|
164
|
+
subcommand: "review",
|
|
165
|
+
},
|
|
166
|
+
spark: {
|
|
167
|
+
profile: "gpt56_luna_low",
|
|
168
|
+
timeoutSec: 180,
|
|
169
|
+
runMode: "fg",
|
|
170
|
+
opusOversight: false,
|
|
171
|
+
mcpHint: "implement",
|
|
172
|
+
subcommand: "exec",
|
|
173
|
+
},
|
|
174
|
+
// These entries are only for explicit direct-Codex overrides. agent-map.json
|
|
175
|
+
// remains the provider-selection authority for their normal execution.
|
|
176
|
+
designer: {
|
|
177
|
+
profile: "gpt56_sol_xhigh",
|
|
178
|
+
timeoutSec: 900,
|
|
179
|
+
runMode: "bg",
|
|
180
|
+
opusOversight: false,
|
|
181
|
+
mcpHint: "implement",
|
|
182
|
+
subcommand: "exec",
|
|
183
|
+
},
|
|
184
|
+
writer: {
|
|
185
|
+
profile: "gpt56_luna_low",
|
|
186
|
+
timeoutSec: 900,
|
|
187
|
+
runMode: "bg",
|
|
188
|
+
opusOversight: false,
|
|
189
|
+
mcpHint: "implement",
|
|
190
|
+
subcommand: "exec",
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
function freezePolicy(entry) {
|
|
195
|
+
return Object.freeze({ ...entry });
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export const CODEX_AGENT_POLICY = Object.freeze(
|
|
199
|
+
Object.fromEntries(
|
|
200
|
+
Object.entries(policy).map(([agent, entry]) => [
|
|
201
|
+
agent,
|
|
202
|
+
freezePolicy(entry),
|
|
203
|
+
]),
|
|
204
|
+
),
|
|
205
|
+
);
|
|
206
|
+
export const DEFAULT_CODEX_AGENT = "executor";
|
|
207
|
+
|
|
208
|
+
export const CANONICAL_CODEX_PROFILE_OVERRIDES = Object.freeze(
|
|
209
|
+
new Set([
|
|
210
|
+
"gpt56_luna_low", "gpt56_terra_med", "gpt56_terra_high", "gpt56_sol_xhigh",
|
|
211
|
+
"gpt56_sol_max", "gpt56_sol_ultra",
|
|
212
|
+
]),
|
|
213
|
+
);
|
|
214
|
+
export const ULTRA_ELIGIBLE_CODEX_AGENTS = Object.freeze(
|
|
215
|
+
new Set(["deep-executor", "scientist-deep"]),
|
|
216
|
+
);
|
|
217
|
+
const NESTED_GLOBAL_PROFILE_OVERRIDES = new Set([
|
|
218
|
+
"max", "ultra", "gpt56_sol_max", "gpt56_sol_ultra",
|
|
219
|
+
]);
|
|
220
|
+
|
|
221
|
+
export function resolveCodexAgentPolicy(agent) {
|
|
222
|
+
return freezePolicy(
|
|
223
|
+
CODEX_AGENT_POLICY[agent] ?? CODEX_AGENT_POLICY[DEFAULT_CODEX_AGENT],
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function resolveCodexAgentProfile(
|
|
228
|
+
agent,
|
|
229
|
+
{ profileOverride = "auto", retryProfile = null, nested = false, allowCustom = false } = {},
|
|
230
|
+
) {
|
|
231
|
+
const defaultProfile = resolveCodexAgentPolicy(agent).profile;
|
|
232
|
+
const retryRequested = String(retryProfile ?? "").trim();
|
|
233
|
+
const requested = retryRequested || String(profileOverride || "auto").trim();
|
|
234
|
+
if (!requested || requested === "auto") return defaultProfile;
|
|
235
|
+
const canonical = requested === "max" ? "gpt56_sol_max" : requested === "ultra" ? "gpt56_sol_ultra" : requested;
|
|
236
|
+
if (!CANONICAL_CODEX_PROFILE_OVERRIDES.has(canonical)) {
|
|
237
|
+
if (allowCustom) return requested;
|
|
238
|
+
throw new Error(`[agent-route-policy] unsupported profile override: ${requested}`);
|
|
239
|
+
}
|
|
240
|
+
if (canonical !== "gpt56_sol_ultra") return canonical;
|
|
241
|
+
return nested || !ULTRA_ELIGIBLE_CODEX_AGENTS.has(agent) ? "gpt56_sol_max" : canonical;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function resolveNestedCodexAgentProfile(
|
|
245
|
+
agent,
|
|
246
|
+
{ profileOverride = "auto", globalProfile = "auto", retryProfile = null, codexHome } = {},
|
|
247
|
+
) {
|
|
248
|
+
const explicitProfile = String(profileOverride || "auto").trim();
|
|
249
|
+
const globalOverride = String(globalProfile || "auto").trim();
|
|
250
|
+
const effectiveOverride = explicitProfile !== "auto" ? explicitProfile : NESTED_GLOBAL_PROFILE_OVERRIDES.has(globalOverride) ? globalOverride : "auto";
|
|
251
|
+
const fallback = resolveCodexAgentProfile(agent);
|
|
252
|
+
const candidate = resolveCodexAgentProfile(agent, { profileOverride: effectiveOverride, retryProfile, nested: true, allowCustom: true });
|
|
253
|
+
const { effort } = resolveCodexProfileConfigValues(candidate, { codexHome });
|
|
254
|
+
if (!effort) return fallback;
|
|
255
|
+
return effort.toLowerCase() === "ultra" ? "gpt56_sol_max" : candidate;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export function describeCodexAgentPolicy() {
|
|
259
|
+
return {
|
|
260
|
+
defaultAgent: DEFAULT_CODEX_AGENT,
|
|
261
|
+
agents: Object.keys(CODEX_AGENT_POLICY),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function parseCliArgs(argv) {
|
|
266
|
+
const args = [...argv];
|
|
267
|
+
let format = "json";
|
|
268
|
+
let agent = DEFAULT_CODEX_AGENT;
|
|
269
|
+
while (args.length > 0) {
|
|
270
|
+
const flag = args.shift();
|
|
271
|
+
if (flag === "--format") format = args.shift() || "";
|
|
272
|
+
else if (flag === "--agent") agent = args.shift() || "";
|
|
273
|
+
else throw new Error(`unknown argument: ${flag}`);
|
|
274
|
+
}
|
|
275
|
+
if (!new Set(["json", "tsv"]).has(format)) {
|
|
276
|
+
throw new Error(`unsupported format: ${format}`);
|
|
277
|
+
}
|
|
278
|
+
return { format, agent };
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function runCli() {
|
|
282
|
+
const { format, agent } = parseCliArgs(process.argv.slice(2));
|
|
283
|
+
const resolved = resolveCodexAgentPolicy(agent);
|
|
284
|
+
if (format === "tsv") {
|
|
285
|
+
process.stdout.write(
|
|
286
|
+
[
|
|
287
|
+
resolved.profile,
|
|
288
|
+
resolved.timeoutSec,
|
|
289
|
+
resolved.runMode,
|
|
290
|
+
resolved.opusOversight,
|
|
291
|
+
resolved.mcpHint,
|
|
292
|
+
resolved.subcommand,
|
|
293
|
+
].join("\t"),
|
|
294
|
+
);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
process.stdout.write(`${JSON.stringify(resolved)}\n`);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (import.meta.url === new URL(process.argv[1], "file:").href) {
|
|
301
|
+
try {
|
|
302
|
+
runCli();
|
|
303
|
+
} catch (error) {
|
|
304
|
+
process.stderr.write(`[agent-route-policy] ${error.message}\n`);
|
|
305
|
+
process.exitCode = 1;
|
|
306
|
+
}
|
|
307
|
+
}
|
package/scripts/lib/cli-agy.mjs
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
//
|
|
6
6
|
// 출처: scripts/tfx-route.sh route_agent() L1052-L1059, run_codex_exec() L2036-L2046.
|
|
7
7
|
// .claude/rules/tfx-update-logic.md Antigravity CLI 1.0.0 정밀 sanity matrix.
|
|
8
|
+
// timeoutSec은 lane 예상 소요 시간(advisory)이다. hard ceiling 집행은 Bash route가 소유한다.
|
|
8
9
|
|
|
9
10
|
export const id = "agy";
|
|
10
11
|
export const cliType = "antigravity";
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
//
|
|
6
6
|
// 출처: scripts/tfx-route.sh route_agent() L1062-L1063 (explore|claude),
|
|
7
7
|
// L1196-L1203 (TFX_CLI_MODE=gemini fallback), TFX_VERIFIER_OVERRIDE=claude.
|
|
8
|
+
// timeoutSec은 lane 예상 소요 시간(advisory)이다. hard ceiling 집행은 Bash route가 소유한다.
|
|
8
9
|
|
|
9
10
|
export const id = "claude";
|
|
10
11
|
export const cliType = "claude-native";
|