@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/hud/providers/cto.mjs
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { readFileSync, statSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { resolveRoleControlSnapshot } from "../../hub/lib/cto-env.mjs";
|
|
4
|
-
import {
|
|
5
|
-
CTO_LAKE_CURRENT_RELATIVE_PATH,
|
|
6
|
-
CTO_STATUS_LINE_MAX_CHARS,
|
|
7
|
-
CTO_STATUS_STALE_MS,
|
|
8
|
-
} from "../constants.mjs";
|
|
9
|
-
|
|
10
|
-
function oneLine(value) {
|
|
11
|
-
return String(value || "")
|
|
12
|
-
.replace(/\x1b\[[0-9;]*m/g, "")
|
|
13
|
-
.replace(/\s+/g, " ")
|
|
14
|
-
.trim();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function capLine(line) {
|
|
18
|
-
const text = oneLine(line);
|
|
19
|
-
if (text.length <= CTO_STATUS_LINE_MAX_CHARS) return text;
|
|
20
|
-
return `${text.slice(0, CTO_STATUS_LINE_MAX_CHARS - 3)}...`;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function resolveCurrentPath({ currentPath, rootDir } = {}) {
|
|
24
|
-
if (currentPath) return currentPath;
|
|
25
|
-
return join(rootDir || process.cwd(), CTO_LAKE_CURRENT_RELATIVE_PATH);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function extractBriefVersion(lines) {
|
|
29
|
-
const versionLine = lines.find((line) => /^brief_version:\s*/i.test(line));
|
|
30
|
-
return oneLine(versionLine?.replace(/^brief_version:\s*/i, "")) || null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function extractStatusLine(lines) {
|
|
34
|
-
const summaryLine = lines.find((line) => /^summary:\s*/i.test(line));
|
|
35
|
-
const summary = oneLine(summaryLine?.replace(/^summary:\s*/i, ""));
|
|
36
|
-
if (summary) return capLine(summary);
|
|
37
|
-
|
|
38
|
-
const sectionHeaders = new Set([
|
|
39
|
-
"repo_state",
|
|
40
|
-
"active_goals",
|
|
41
|
-
"swarm_shards",
|
|
42
|
-
"hub_status",
|
|
43
|
-
"recent_events",
|
|
44
|
-
"generated_at",
|
|
45
|
-
"injection_note",
|
|
46
|
-
]);
|
|
47
|
-
const fallback = lines.find((line) => {
|
|
48
|
-
const clean = oneLine(line);
|
|
49
|
-
return (
|
|
50
|
-
clean && !/^brief_version:\s*/i.test(clean) && !sectionHeaders.has(clean)
|
|
51
|
-
);
|
|
52
|
-
});
|
|
53
|
-
return fallback ? capLine(fallback) : null;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function readCtoStatus(options = {}) {
|
|
57
|
-
if (!resolveRoleControlSnapshot(options.env).auto_collect_enabled)
|
|
58
|
-
return null;
|
|
59
|
-
try {
|
|
60
|
-
const currentPath = resolveCurrentPath(options);
|
|
61
|
-
const stat = statSync(currentPath);
|
|
62
|
-
const raw = readFileSync(currentPath, "utf8");
|
|
63
|
-
const lines = raw.split(/\r?\n/u).map(oneLine).filter(Boolean);
|
|
64
|
-
const line = extractStatusLine(lines);
|
|
65
|
-
if (!line) return null;
|
|
66
|
-
|
|
67
|
-
const version = extractBriefVersion(lines);
|
|
68
|
-
const isStale = Date.now() - stat.mtimeMs > CTO_STATUS_STALE_MS;
|
|
69
|
-
return {
|
|
70
|
-
line,
|
|
71
|
-
rightTag: isStale ? "stale" : version || "cto",
|
|
72
|
-
};
|
|
73
|
-
} catch {
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
|
|
4
|
-
export function agentJsonPath({ tmpDir, pid = process.pid }) {
|
|
5
|
-
return join(tmpDir, `tfx-agent-${pid}.json`);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function registerAgent({
|
|
9
|
-
tmpDir,
|
|
10
|
-
pid = process.pid,
|
|
11
|
-
cli = "",
|
|
12
|
-
agent = "",
|
|
13
|
-
started = Math.floor(Date.now() / 1000),
|
|
14
|
-
}) {
|
|
15
|
-
mkdirSync(tmpDir, { recursive: true });
|
|
16
|
-
const file = agentJsonPath({ tmpDir, pid });
|
|
17
|
-
writeFileSync(
|
|
18
|
-
file,
|
|
19
|
-
`${JSON.stringify({ pid, cli, agent, started })}\n`,
|
|
20
|
-
"utf8",
|
|
21
|
-
);
|
|
22
|
-
return file;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function removeAgent({ tmpDir, pid = process.pid }) {
|
|
26
|
-
rmSync(agentJsonPath({ tmpDir, pid }), { force: true });
|
|
27
|
-
}
|
package/scripts/lib/async.mjs
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import { randomUUID } from "node:crypto";
|
|
3
|
-
import {
|
|
4
|
-
existsSync,
|
|
5
|
-
mkdirSync,
|
|
6
|
-
readFileSync,
|
|
7
|
-
statSync,
|
|
8
|
-
writeFileSync,
|
|
9
|
-
} from "node:fs";
|
|
10
|
-
import { join } from "node:path";
|
|
11
|
-
|
|
12
|
-
function jobDir(jobsDir, jobId) {
|
|
13
|
-
return join(jobsDir, jobId);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function readState(dir) {
|
|
17
|
-
const path = join(dir, "state.json");
|
|
18
|
-
if (!existsSync(path)) return null;
|
|
19
|
-
return JSON.parse(readFileSync(path, "utf8"));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function writeState(dir, state) {
|
|
23
|
-
writeFileSync(join(dir, "state.json"), `${JSON.stringify(state, null, 2)}\n`);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function fileSize(path) {
|
|
27
|
-
try {
|
|
28
|
-
return statSync(path).size;
|
|
29
|
-
} catch {
|
|
30
|
-
return 0;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function isAlive(pid) {
|
|
35
|
-
if (!pid || pid === "starting") return false;
|
|
36
|
-
try {
|
|
37
|
-
process.kill(Number(pid), 0);
|
|
38
|
-
return true;
|
|
39
|
-
} catch {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function createJob({
|
|
45
|
-
jobsDir,
|
|
46
|
-
command,
|
|
47
|
-
args = [],
|
|
48
|
-
env = process.env,
|
|
49
|
-
cwd = process.cwd(),
|
|
50
|
-
timeoutMs = 0,
|
|
51
|
-
}) {
|
|
52
|
-
mkdirSync(jobsDir, { recursive: true });
|
|
53
|
-
const id = randomUUID();
|
|
54
|
-
const dir = jobDir(jobsDir, id);
|
|
55
|
-
mkdirSync(dir, { recursive: true });
|
|
56
|
-
const startedAt = Date.now();
|
|
57
|
-
const stdoutPath = join(dir, "result.log");
|
|
58
|
-
const stderrPath = join(dir, "stderr.log");
|
|
59
|
-
writeState(dir, {
|
|
60
|
-
id,
|
|
61
|
-
state: "starting",
|
|
62
|
-
startedAt,
|
|
63
|
-
command,
|
|
64
|
-
args,
|
|
65
|
-
timeoutMs,
|
|
66
|
-
});
|
|
67
|
-
writeFileSync(join(dir, "pid"), "starting");
|
|
68
|
-
writeFileSync(join(dir, "start_time"), String(Math.floor(startedAt / 1000)));
|
|
69
|
-
|
|
70
|
-
const child = spawn(command, args, {
|
|
71
|
-
cwd,
|
|
72
|
-
env,
|
|
73
|
-
detached: true,
|
|
74
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
75
|
-
});
|
|
76
|
-
child.unref?.();
|
|
77
|
-
writeFileSync(join(dir, "pid"), String(child.pid));
|
|
78
|
-
writeState(dir, {
|
|
79
|
-
id,
|
|
80
|
-
state: "running",
|
|
81
|
-
pid: child.pid,
|
|
82
|
-
startedAt,
|
|
83
|
-
command,
|
|
84
|
-
args,
|
|
85
|
-
timeoutMs,
|
|
86
|
-
});
|
|
87
|
-
child.stdout?.on("data", (chunk) => {
|
|
88
|
-
writeFileSync(stdoutPath, chunk, { flag: "a" });
|
|
89
|
-
});
|
|
90
|
-
child.stderr?.on("data", (chunk) => {
|
|
91
|
-
writeFileSync(stderrPath, chunk, { flag: "a" });
|
|
92
|
-
});
|
|
93
|
-
let timer = null;
|
|
94
|
-
let timedOut = false;
|
|
95
|
-
if (timeoutMs > 0) {
|
|
96
|
-
timer = setTimeout(() => {
|
|
97
|
-
timedOut = true;
|
|
98
|
-
try {
|
|
99
|
-
process.kill(child.pid, "SIGTERM");
|
|
100
|
-
} catch {
|
|
101
|
-
// Process already exited.
|
|
102
|
-
}
|
|
103
|
-
}, timeoutMs);
|
|
104
|
-
timer.unref?.();
|
|
105
|
-
}
|
|
106
|
-
child.on("exit", (code) => {
|
|
107
|
-
if (timer) clearTimeout(timer);
|
|
108
|
-
const exitCode = timedOut ? 124 : (code ?? 1);
|
|
109
|
-
writeFileSync(join(dir, "exit_code"), String(exitCode));
|
|
110
|
-
writeFileSync(join(dir, "done"), "");
|
|
111
|
-
writeState(dir, {
|
|
112
|
-
id,
|
|
113
|
-
state: exitCode === 0 ? "done" : exitCode === 124 ? "timeout" : "failed",
|
|
114
|
-
pid: child.pid,
|
|
115
|
-
startedAt,
|
|
116
|
-
finishedAt: Date.now(),
|
|
117
|
-
exitCode,
|
|
118
|
-
command,
|
|
119
|
-
args,
|
|
120
|
-
timeoutMs,
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
return { id, dir, pid: child.pid };
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export function getJobStatus(jobId, { jobsDir }) {
|
|
128
|
-
const dir = jobDir(jobsDir, jobId);
|
|
129
|
-
if (!existsSync(dir))
|
|
130
|
-
return { state: "error", text: "error: job not found", exitCode: 1 };
|
|
131
|
-
const state = readState(dir);
|
|
132
|
-
if (state?.state === "done") return { ...state, text: "done" };
|
|
133
|
-
if (state?.state === "timeout") return { ...state, text: "timeout" };
|
|
134
|
-
if (state?.state === "failed") return { ...state, text: "failed" };
|
|
135
|
-
const pidText = existsSync(join(dir, "pid"))
|
|
136
|
-
? readFileSync(join(dir, "pid"), "utf8").trim()
|
|
137
|
-
: "";
|
|
138
|
-
if (pidText === "starting")
|
|
139
|
-
return { ...(state ?? {}), state: "starting", text: "starting" };
|
|
140
|
-
if (isAlive(pidText)) {
|
|
141
|
-
const start =
|
|
142
|
-
Number(readFileSync(join(dir, "start_time"), "utf8")) ||
|
|
143
|
-
Math.floor(Date.now() / 1000);
|
|
144
|
-
const elapsed = Math.max(0, Math.floor(Date.now() / 1000) - start);
|
|
145
|
-
const bytes = fileSize(join(dir, "result.log"));
|
|
146
|
-
return {
|
|
147
|
-
...(state ?? {}),
|
|
148
|
-
state: "running",
|
|
149
|
-
text: `running elapsed=${elapsed}s output=${bytes}B`,
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
return { ...(state ?? {}), state: "failed", text: "failed" };
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export function getJobResult(jobId, { jobsDir }) {
|
|
156
|
-
const dir = jobDir(jobsDir, jobId);
|
|
157
|
-
if (!existsSync(dir)) throw new Error("job not found");
|
|
158
|
-
const status = getJobStatus(jobId, { jobsDir });
|
|
159
|
-
if (!["done", "timeout", "failed"].includes(status.state)) {
|
|
160
|
-
throw new Error("job still running");
|
|
161
|
-
}
|
|
162
|
-
const stdout = existsSync(join(dir, "result.log"))
|
|
163
|
-
? readFileSync(join(dir, "result.log"), "utf8")
|
|
164
|
-
: "";
|
|
165
|
-
const stderr = existsSync(join(dir, "stderr.log"))
|
|
166
|
-
? readFileSync(join(dir, "stderr.log"), "utf8")
|
|
167
|
-
: "";
|
|
168
|
-
return {
|
|
169
|
-
state: status.state,
|
|
170
|
-
exitCode: status.exitCode ?? 1,
|
|
171
|
-
stdout: stdout || stderr,
|
|
172
|
-
stderr,
|
|
173
|
-
};
|
|
174
|
-
}
|
package/scripts/lib/cli-agy.mjs
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
// cli-agy.mjs — Antigravity (agy) CLI adapter (Phase 0 PoC).
|
|
2
|
-
//
|
|
3
|
-
// 책임: agy 1.1.27 부터 --print 는 값(프롬프트)이 필수이고 stdin 프롬프트는 거부되므로
|
|
4
|
-
// plan() 은 프롬프트를 args 의 --print 값으로 넣고 stdinMode="argv" 를 돌려준다.
|
|
5
|
-
// --print 뒤에 다른 플래그가 오면 그 플래그를 프롬프트로 삼키므로 항상 마지막에 둔다.
|
|
6
|
-
//
|
|
7
|
-
// 출처: scripts/tfx-route.sh route_agent() L1052-L1059, run_codex_exec() L2036-L2046.
|
|
8
|
-
// .claude/rules/tfx-update-logic.md Antigravity CLI 1.0.0 정밀 sanity matrix.
|
|
9
|
-
// timeoutSec은 lane 예상 소요 시간(advisory)이다. hard ceiling 집행은 Bash route가 소유한다.
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
resolveGeminiModel,
|
|
13
|
-
resolveGeminiProfileForPurpose,
|
|
14
|
-
} from "./gemini-profiles.mjs";
|
|
15
|
-
|
|
16
|
-
export const id = "agy";
|
|
17
|
-
export const cliType = "antigravity";
|
|
18
|
-
export const command = "agy";
|
|
19
|
-
|
|
20
|
-
// #310: agent-map.json normalizes upstream callers to antigravity,
|
|
21
|
-
// but this adapter also accepts the direct `agy` route for compatibility.
|
|
22
|
-
const AGENT_PROFILES = {
|
|
23
|
-
antigravity: {
|
|
24
|
-
profile: "agy_v1",
|
|
25
|
-
timeoutSec: 900,
|
|
26
|
-
runMode: "bg",
|
|
27
|
-
opusOversight: false,
|
|
28
|
-
mcpHint: "docs",
|
|
29
|
-
},
|
|
30
|
-
agy: {
|
|
31
|
-
profile: "agy_v1",
|
|
32
|
-
timeoutSec: 900,
|
|
33
|
-
runMode: "bg",
|
|
34
|
-
opusOversight: false,
|
|
35
|
-
mcpHint: "docs",
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const DEFAULT_PROFILE = AGENT_PROFILES.antigravity;
|
|
40
|
-
|
|
41
|
-
export function plan({
|
|
42
|
-
agent,
|
|
43
|
-
prompt = "",
|
|
44
|
-
mcpProfile = "auto",
|
|
45
|
-
timeoutSec,
|
|
46
|
-
contextFile,
|
|
47
|
-
geminiProfilesPath,
|
|
48
|
-
} = {}) {
|
|
49
|
-
if (!agent) {
|
|
50
|
-
throw new Error("[cli-agy] agent required");
|
|
51
|
-
}
|
|
52
|
-
const cfg = AGENT_PROFILES[agent] ?? DEFAULT_PROFILE;
|
|
53
|
-
const effectiveTimeoutSec =
|
|
54
|
-
Number.isFinite(timeoutSec) && timeoutSec > 0 ? timeoutSec : cfg.timeoutSec;
|
|
55
|
-
return {
|
|
56
|
-
command,
|
|
57
|
-
profile: cfg.profile,
|
|
58
|
-
effort: cfg.profile,
|
|
59
|
-
// effort 는 역할별 SSOT(gemini-profiles.mjs): designer → High, writer → Medium ...
|
|
60
|
-
geminiProfile: resolveGeminiProfileForPurpose(agent),
|
|
61
|
-
model: resolveGeminiModel(resolveGeminiProfileForPurpose(agent), {
|
|
62
|
-
profilesPath: geminiProfilesPath,
|
|
63
|
-
}),
|
|
64
|
-
args: [
|
|
65
|
-
"--dangerously-skip-permissions",
|
|
66
|
-
"--model",
|
|
67
|
-
resolveGeminiModel(resolveGeminiProfileForPurpose(agent), {
|
|
68
|
-
profilesPath: geminiProfilesPath,
|
|
69
|
-
}),
|
|
70
|
-
"--print",
|
|
71
|
-
prompt,
|
|
72
|
-
],
|
|
73
|
-
stdinMode: "argv",
|
|
74
|
-
timeoutMs: effectiveTimeoutSec * 1000,
|
|
75
|
-
runMode: cfg.runMode,
|
|
76
|
-
opusOversight: cfg.opusOversight,
|
|
77
|
-
mcpProfile: mcpProfile === "auto" ? cfg.mcpHint : mcpProfile,
|
|
78
|
-
promptLength: prompt.length,
|
|
79
|
-
contextFile: contextFile || null,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function describe() {
|
|
84
|
-
return { id, cliType, command, agents: Object.keys(AGENT_PROFILES) };
|
|
85
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
// cli-codex.mjs — Codex CLI adapter (Phase 0 PoC).
|
|
2
|
-
//
|
|
3
|
-
// 책임: agent 이름과 입력 파라미터를 받아 Codex 실행 계획(profile/effort/timeout/runMode)을
|
|
4
|
-
// 산출한다. 실제 spawn 은 Phase 1 에서 이관된다 (현재는 tfx-route.sh 가 수행).
|
|
5
|
-
//
|
|
6
|
-
// 진입점: tfx-route.mjs → selectAdapter("codex") → plan({...}).
|
|
7
|
-
// 출처: agent-route-policy.mjs 의 canonical Codex role policy.
|
|
8
|
-
// timeoutSec은 lane 예상 소요 시간(advisory)이다. hard ceiling 집행은 Bash route가 소유한다.
|
|
9
|
-
|
|
10
|
-
export const id = "codex";
|
|
11
|
-
export const cliType = "codex";
|
|
12
|
-
export const command = "codex";
|
|
13
|
-
|
|
14
|
-
import {
|
|
15
|
-
CODEX_AGENT_POLICY,
|
|
16
|
-
resolveCodexAgentPolicy,
|
|
17
|
-
resolveCodexAgentProfile,
|
|
18
|
-
resolveNestedCodexAgentProfile,
|
|
19
|
-
} from "./agent-route-policy.mjs";
|
|
20
|
-
|
|
21
|
-
// Compatibility re-exports for launchers which historically imported these
|
|
22
|
-
// helpers from this adapter. The policy module owns the semantics.
|
|
23
|
-
export { resolveCodexAgentProfile, resolveNestedCodexAgentProfile };
|
|
24
|
-
|
|
25
|
-
export function plan({
|
|
26
|
-
agent,
|
|
27
|
-
prompt = "",
|
|
28
|
-
mcpProfile = "auto",
|
|
29
|
-
timeoutSec,
|
|
30
|
-
contextFile,
|
|
31
|
-
profileOverride = "auto",
|
|
32
|
-
retryProfile = null,
|
|
33
|
-
nested = false,
|
|
34
|
-
} = {}) {
|
|
35
|
-
if (!agent) {
|
|
36
|
-
throw new Error("[cli-codex] agent required");
|
|
37
|
-
}
|
|
38
|
-
const cfg = resolveCodexAgentPolicy(agent);
|
|
39
|
-
const profile = resolveCodexAgentProfile(agent, {
|
|
40
|
-
profileOverride,
|
|
41
|
-
retryProfile,
|
|
42
|
-
nested,
|
|
43
|
-
});
|
|
44
|
-
const effectiveTimeoutSec =
|
|
45
|
-
Number.isFinite(timeoutSec) && timeoutSec > 0 ? timeoutSec : cfg.timeoutSec;
|
|
46
|
-
return {
|
|
47
|
-
command,
|
|
48
|
-
subcommand: cfg.subcommand ?? "exec",
|
|
49
|
-
profile,
|
|
50
|
-
effort: profile,
|
|
51
|
-
timeoutMs: effectiveTimeoutSec * 1000,
|
|
52
|
-
runMode: cfg.runMode,
|
|
53
|
-
opusOversight: cfg.opusOversight,
|
|
54
|
-
mcpProfile: mcpProfile === "auto" ? cfg.mcpHint : mcpProfile,
|
|
55
|
-
promptLength: prompt.length,
|
|
56
|
-
contextFile: contextFile || null,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function describe() {
|
|
61
|
-
return { id, cliType, command, agents: Object.keys(CODEX_AGENT_POLICY) };
|
|
62
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// cli-gemini.mjs — legacy Gemini adapter alias.
|
|
2
|
-
// The public "gemini" label remains accepted, but the executable plan is AGY.
|
|
3
|
-
|
|
4
|
-
import * as agyAdapter from "./cli-agy.mjs";
|
|
5
|
-
|
|
6
|
-
export const id = "gemini";
|
|
7
|
-
export const cliType = "antigravity";
|
|
8
|
-
export const command = "agy";
|
|
9
|
-
|
|
10
|
-
export function plan({
|
|
11
|
-
agent,
|
|
12
|
-
prompt = "",
|
|
13
|
-
mcpProfile = "auto",
|
|
14
|
-
timeoutSec,
|
|
15
|
-
contextFile,
|
|
16
|
-
} = {}) {
|
|
17
|
-
if (!agent) {
|
|
18
|
-
throw new Error("[cli-gemini] agent required");
|
|
19
|
-
}
|
|
20
|
-
return agyAdapter.plan({
|
|
21
|
-
agent: agent === "gemini" ? "antigravity" : agent,
|
|
22
|
-
prompt,
|
|
23
|
-
mcpProfile,
|
|
24
|
-
timeoutSec,
|
|
25
|
-
contextFile,
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function describe() {
|
|
30
|
-
return {
|
|
31
|
-
id,
|
|
32
|
-
cliType,
|
|
33
|
-
command,
|
|
34
|
-
aliases: ["gemini"],
|
|
35
|
-
agents: ["gemini", "designer", "writer", "antigravity", "agy"],
|
|
36
|
-
};
|
|
37
|
-
}
|
package/scripts/lib/env.mjs
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export function buildPreflightEnv(env = process.env) {
|
|
2
|
-
return {
|
|
3
|
-
...env,
|
|
4
|
-
GIT_TERMINAL_PROMPT: env.GIT_TERMINAL_PROMPT ?? "0",
|
|
5
|
-
GIT_ASKPASS: env.GIT_ASKPASS ?? "false",
|
|
6
|
-
npm_config_yes: env.npm_config_yes ?? "true",
|
|
7
|
-
};
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function shouldWarnGhAuth(env = process.env, checks = {}) {
|
|
11
|
-
if (!checks.ghExists) return false;
|
|
12
|
-
if (env.GH_TOKEN || env.GITHUB_TOKEN) return false;
|
|
13
|
-
return checks.ghAuthenticated === false;
|
|
14
|
-
}
|
package/scripts/lib/hub.mjs
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
|
|
3
|
-
export function parseHubPort(hubUrl = "") {
|
|
4
|
-
try {
|
|
5
|
-
const parsed = new URL(hubUrl);
|
|
6
|
-
return parsed.port || "27888";
|
|
7
|
-
} catch {
|
|
8
|
-
return "27888";
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export async function restartHub({
|
|
13
|
-
hubUrl = process.env.TFX_HUB_URL || "http://127.0.0.1:27888",
|
|
14
|
-
hubServer,
|
|
15
|
-
nodeBin = process.execPath,
|
|
16
|
-
spawnFn = spawn,
|
|
17
|
-
fetchFn = globalThis.fetch,
|
|
18
|
-
sleepMs = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
19
|
-
attempts = 8,
|
|
20
|
-
} = {}) {
|
|
21
|
-
if (!hubServer) return { ok: false, error: "hub_server_missing" };
|
|
22
|
-
const port = parseHubPort(hubUrl);
|
|
23
|
-
const child = spawnFn(nodeBin, [hubServer], {
|
|
24
|
-
env: { ...process.env, TFX_HUB_PORT: port },
|
|
25
|
-
stdio: "ignore",
|
|
26
|
-
detached: true,
|
|
27
|
-
});
|
|
28
|
-
child.unref?.();
|
|
29
|
-
|
|
30
|
-
for (let i = 0; i < attempts; i += 1) {
|
|
31
|
-
await sleepMs(500);
|
|
32
|
-
try {
|
|
33
|
-
const response = await fetchFn(`${hubUrl.replace(/\/$/, "")}/status`);
|
|
34
|
-
if (response?.ok) return { ok: true, pid: child.pid };
|
|
35
|
-
} catch {
|
|
36
|
-
// Keep polling until attempts are exhausted.
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return { ok: false, pid: child.pid };
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export async function withHubRestart({ action, restart }) {
|
|
43
|
-
const first = await action();
|
|
44
|
-
if (first?.ok) return first;
|
|
45
|
-
const restarted = await restart();
|
|
46
|
-
if (!restarted?.ok) return first;
|
|
47
|
-
return action();
|
|
48
|
-
}
|
package/scripts/lib/pid.mjs
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { appendFileSync, existsSync, readFileSync, rmSync } from "node:fs";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
|
-
|
|
4
|
-
const require = createRequire(import.meta.url);
|
|
5
|
-
let treeKill = null;
|
|
6
|
-
try {
|
|
7
|
-
treeKill = require("tree-kill");
|
|
8
|
-
} catch {
|
|
9
|
-
treeKill = null;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function defaultIsAlive(pid) {
|
|
13
|
-
try {
|
|
14
|
-
process.kill(pid, 0);
|
|
15
|
-
return true;
|
|
16
|
-
} catch {
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function defaultKillTree(pid) {
|
|
22
|
-
return new Promise((resolve) => {
|
|
23
|
-
if (treeKill) {
|
|
24
|
-
treeKill(pid, "SIGTERM", () => resolve());
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
try {
|
|
28
|
-
process.kill(pid, "SIGTERM");
|
|
29
|
-
} catch {
|
|
30
|
-
// Process already exited.
|
|
31
|
-
}
|
|
32
|
-
resolve();
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export class PidTracker {
|
|
37
|
-
constructor(path, options = {}) {
|
|
38
|
-
this.path = path;
|
|
39
|
-
this.isAlive = options.isAlive ?? defaultIsAlive;
|
|
40
|
-
this.killTree = options.killTree ?? defaultKillTree;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
track(pid) {
|
|
44
|
-
if (!pid) return;
|
|
45
|
-
appendFileSync(this.path, `${pid}\n`);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
list() {
|
|
49
|
-
if (!existsSync(this.path)) return [];
|
|
50
|
-
return readFileSync(this.path, "utf8")
|
|
51
|
-
.split(/\r?\n/)
|
|
52
|
-
.map((line) => Number(line.trim()))
|
|
53
|
-
.filter((pid) => Number.isInteger(pid) && pid > 0);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async cleanup() {
|
|
57
|
-
for (const pid of this.list()) {
|
|
58
|
-
if (!this.isAlive(pid)) continue;
|
|
59
|
-
await this.killTree(pid);
|
|
60
|
-
}
|
|
61
|
-
rmSync(this.path, { force: true });
|
|
62
|
-
}
|
|
63
|
-
}
|
package/scripts/lib/quota.mjs
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
export const QUOTA_PATTERNS = [
|
|
2
|
-
/usage limit exceeded/i,
|
|
3
|
-
/rate limit exceeded/i,
|
|
4
|
-
/rate limit reached/i,
|
|
5
|
-
/try again at/i,
|
|
6
|
-
/purchase more credits/i,
|
|
7
|
-
/quota exceeded/i,
|
|
8
|
-
/RESOURCE_EXHAUSTED/i,
|
|
9
|
-
/rateLimitExceeded/i,
|
|
10
|
-
/Too Many Requests/i,
|
|
11
|
-
/rate_limit_error/i,
|
|
12
|
-
/overloaded_error/i,
|
|
13
|
-
/insufficient_quota/i,
|
|
14
|
-
];
|
|
15
|
-
|
|
16
|
-
export class QuotaStreamBuffer {
|
|
17
|
-
constructor({ maxBytes = 65536 } = {}) {
|
|
18
|
-
this.maxBytes = maxBytes;
|
|
19
|
-
this.text = "";
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
push(chunk) {
|
|
23
|
-
this.text += Buffer.isBuffer(chunk)
|
|
24
|
-
? chunk.toString("utf8")
|
|
25
|
-
: String(chunk);
|
|
26
|
-
if (this.text.length > this.maxBytes) {
|
|
27
|
-
this.text = this.text.slice(-this.maxBytes);
|
|
28
|
-
}
|
|
29
|
-
return detectQuotaText(this.text);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function detectQuotaText(text = "") {
|
|
34
|
-
return QUOTA_PATTERNS.some((pattern) => pattern.test(text));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function getRerouteTarget(cliType) {
|
|
38
|
-
switch (cliType) {
|
|
39
|
-
case "codex":
|
|
40
|
-
case "gemini":
|
|
41
|
-
return "antigravity";
|
|
42
|
-
case "antigravity":
|
|
43
|
-
return "codex";
|
|
44
|
-
default:
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
}
|