@triflux/remote 10.50.1 → 10.51.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.
Files changed (120) hide show
  1. package/cto/brief.mjs +0 -12
  2. package/cto/collect.mjs +16 -247
  3. package/cto/current.schema.json +4 -20
  4. package/cto/events.mjs +13 -294
  5. package/cto/hygiene.mjs +26 -346
  6. package/cto/lake-root.mjs +114 -16
  7. package/cto/status.mjs +33 -128
  8. package/hub/index.mjs +0 -8
  9. package/hub/store-adapter.mjs +1 -1
  10. package/hub/team/agent-map.json +0 -1
  11. package/hub/team/ansi.mjs +1 -35
  12. package/hub/team/backend.mjs +9 -145
  13. package/hub/team/cli/commands/attach.mjs +1 -17
  14. package/hub/team/cli/commands/control.mjs +12 -38
  15. package/hub/team/cli/commands/debug.mjs +1 -37
  16. package/hub/team/cli/commands/focus.mjs +5 -31
  17. package/hub/team/cli/commands/interrupt.mjs +6 -25
  18. package/hub/team/cli/commands/kill.mjs +1 -30
  19. package/hub/team/cli/commands/list.mjs +0 -16
  20. package/hub/team/cli/commands/send.mjs +6 -26
  21. package/hub/team/cli/commands/start/index.mjs +41 -133
  22. package/hub/team/cli/commands/start/parse-args.mjs +15 -40
  23. package/hub/team/cli/commands/start/start-headless.mjs +138 -105
  24. package/hub/team/cli/commands/start/start-mux.mjs +0 -3
  25. package/hub/team/cli/commands/status.mjs +2 -57
  26. package/hub/team/cli/commands/stop.mjs +14 -19
  27. package/hub/team/cli/help.mjs +4 -5
  28. package/hub/team/cli/manifest.mjs +5 -1
  29. package/hub/team/cli/render.mjs +0 -12
  30. package/hub/team/cli/services/hub-client.mjs +2 -88
  31. package/hub/team/cli/services/runtime-mode.mjs +27 -98
  32. package/hub/team/handoff.mjs +3 -34
  33. package/hub/team/headless.mjs +14 -755
  34. package/hub/team/orchestrator.mjs +4 -30
  35. package/hub/team/pane.mjs +6 -28
  36. package/hub/team/psmux.mjs +16 -403
  37. package/hub/team/remote-session.mjs +1 -2
  38. package/hub/team/session.mjs +8 -119
  39. package/hub/team/swarm-intent.mjs +0 -198
  40. package/hub/team/terminal-opener.mjs +11 -35
  41. package/hub/team/tui-core.mjs +1 -1
  42. package/hub/team/tui-viewer.mjs +2 -2
  43. package/hub/team/tui.mjs +8 -269
  44. package/hub/team/wt-manager.mjs +2 -2
  45. package/hub/workers/factory.mjs +4 -37
  46. package/hub/workers/lib/jsonrpc-ws-uds.mjs +0 -2
  47. package/package.json +1 -1
  48. package/scripts/lib/agent-route-policy.mjs +162 -14
  49. package/scripts/lib/claudemd-scanner.mjs +2 -199
  50. package/scripts/lib/cli-claude.mjs +0 -2
  51. package/scripts/lib/context.mjs +3 -19
  52. package/scripts/lib/env-probe.mjs +5 -64
  53. package/scripts/lib/gemini-profiles.mjs +2 -69
  54. package/scripts/lib/legacy-mcp-cleanup.mjs +14 -3
  55. package/scripts/lib/machine-profile.mjs +3 -17
  56. package/scripts/lib/mcp-filter.mjs +109 -53
  57. package/scripts/lib/mcp-health.mjs +2 -2
  58. package/scripts/lib/mcp-server-catalog.mjs +2 -2
  59. package/scripts/lib/psmux-info.mjs +25 -104
  60. package/scripts/lib/skill-template.mjs +0 -271
  61. package/cto/hygiene-actions.mjs +0 -355
  62. package/cto/hygiene-notify.mjs +0 -170
  63. package/hub/team/build-worker-prompt.mjs +0 -92
  64. package/hub/team/check-mcp-hub.mjs +0 -49
  65. package/hub/team/claude-native-bridge.mjs +0 -987
  66. package/hub/team/cli/commands/start/start-in-process.mjs +0 -50
  67. package/hub/team/cli/commands/start/start-wt.mjs +0 -86
  68. package/hub/team/cli/services/native-control.mjs +0 -145
  69. package/hub/team/codex-review.mjs +0 -520
  70. package/hub/team/conductor-mesh-bridge.mjs +0 -122
  71. package/hub/team/conductor.mjs +0 -1529
  72. package/hub/team/consensus-meta.mjs +0 -176
  73. package/hub/team/cto-pull.mjs +0 -31
  74. package/hub/team/daemon-pty-tmux-bridge.mjs +0 -146
  75. package/hub/team/dashboard.mjs +0 -322
  76. package/hub/team/event-log.mjs +0 -84
  77. package/hub/team/execution-mode.mjs +0 -324
  78. package/hub/team/extract-completion-payload.mjs +0 -110
  79. package/hub/team/headless-bridge-session.mjs +0 -17
  80. package/hub/team/health-probe.mjs +0 -435
  81. package/hub/team/interactive-native-launcher.mjs +0 -119
  82. package/hub/team/interactive-native-worker.mjs +0 -80
  83. package/hub/team/interactive-tui-transport.mjs +0 -479
  84. package/hub/team/launcher-template.mjs +0 -144
  85. package/hub/team/mcp-selector.mjs +0 -145
  86. package/hub/team/native-supervisor.mjs +0 -460
  87. package/hub/team/native.mjs +0 -727
  88. package/hub/team/recovery-store.mjs +0 -149
  89. package/hub/team/remote-probe.mjs +0 -292
  90. package/hub/team/remote-watcher.mjs +0 -506
  91. package/hub/team/runtime-strategy.mjs +0 -200
  92. package/hub/team/schemas/worker-completion.json +0 -39
  93. package/hub/team/sentinel-capture.mjs +0 -127
  94. package/hub/team/swarm-cli.mjs +0 -390
  95. package/hub/team/swarm-hypervisor.mjs +0 -2206
  96. package/hub/team/swarm-locks.mjs +0 -335
  97. package/hub/team/swarm-planner.mjs +0 -371
  98. package/hub/team/swarm-preflight.mjs +0 -366
  99. package/hub/team/swarm-reconciler.mjs +0 -242
  100. package/hub/team/tui-remote-adapter.mjs +0 -377
  101. package/hub/team/worker-completion-validator.mjs +0 -79
  102. package/hub/team/worktree-lifecycle.mjs +0 -639
  103. package/hub/team/wt-templates.json +0 -43
  104. package/hub/workers/antigravity-route-worker.mjs +0 -179
  105. package/hub/workers/gemini-worker.mjs +0 -217
  106. package/scripts/lib/agent-json.mjs +0 -27
  107. package/scripts/lib/async.mjs +0 -174
  108. package/scripts/lib/cli-agy.mjs +0 -85
  109. package/scripts/lib/cli-codex.mjs +0 -62
  110. package/scripts/lib/cli-gemini.mjs +0 -37
  111. package/scripts/lib/dynamic-route-cli.mjs +0 -107
  112. package/scripts/lib/env.mjs +0 -14
  113. package/scripts/lib/hub.mjs +0 -48
  114. package/scripts/lib/pid.mjs +0 -63
  115. package/scripts/lib/quota.mjs +0 -47
  116. package/scripts/lib/skill-state.mjs +0 -220
  117. package/scripts/lib/team.mjs +0 -75
  118. package/scripts/lib/timeout.mjs +0 -66
  119. package/scripts/lib/tmp.mjs +0 -26
  120. package/scripts/lib/toml.mjs +0 -132
@@ -1,179 +0,0 @@
1
- // hub/workers/antigravity-route-worker.mjs — SDK-free Antigravity route worker
2
-
3
- import { spawn } from "node:child_process";
4
- import { existsSync } from "node:fs";
5
- import { dirname, resolve } from "node:path";
6
- import { fileURLToPath } from "node:url";
7
-
8
- const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
9
- const DEFAULT_TIMEOUT_MS = 15 * 60 * 1000;
10
-
11
- function resolveCandidatePath(candidate, cwd = process.cwd()) {
12
- if (!candidate) return null;
13
- const normalized = String(candidate).startsWith("/")
14
- ? String(candidate)
15
- : resolve(cwd, String(candidate));
16
- return existsSync(normalized) ? normalized : null;
17
- }
18
-
19
- function resolveRouteScript(
20
- explicitPath,
21
- cwd = process.cwd(),
22
- env = process.env,
23
- ) {
24
- const candidates = [
25
- explicitPath,
26
- env.TFX_DELEGATOR_ROUTE_SCRIPT,
27
- env.TFX_ROUTE_SCRIPT,
28
- resolve(SCRIPT_DIR, "..", "..", "scripts", "tfx-route.sh"),
29
- resolve(cwd, "scripts", "tfx-route.sh"),
30
- ];
31
-
32
- for (const candidate of candidates) {
33
- const resolved = resolveCandidatePath(candidate, cwd);
34
- if (resolved) return resolved;
35
- }
36
-
37
- return null;
38
- }
39
-
40
- function parseRouteType(stderr = "") {
41
- const match = String(stderr).match(/type=([a-z-]+)/);
42
- if (!match) return "antigravity";
43
- return match[1] === "gemini" ? "antigravity" : match[1];
44
- }
45
-
46
- function normalizeResult(result = {}) {
47
- const output = result.output || result.error || "";
48
- const exitCode = result.exitCode ?? (result.ok ? 0 : 1);
49
- return {
50
- response: output,
51
- output,
52
- exitCode,
53
- stderr: result.stderr || "",
54
- raw: result,
55
- };
56
- }
57
-
58
- export class AntigravityRouteWorker {
59
- type = "antigravity";
60
-
61
- constructor(options = {}) {
62
- this.cwd = options.cwd || process.cwd();
63
- this.env = { ...process.env, ...(options.env || {}) };
64
- this.routeScript = resolveRouteScript(
65
- options.routeScript,
66
- this.cwd,
67
- this.env,
68
- );
69
- this.bashCommand = options.bashCommand || this.env.BASH_BIN || "bash";
70
- this.timeoutMs =
71
- Number.isFinite(Number(options.timeoutMs)) &&
72
- Number(options.timeoutMs) > 0
73
- ? Number(options.timeoutMs)
74
- : DEFAULT_TIMEOUT_MS;
75
- this.children = new Set();
76
- }
77
-
78
- isReady() {
79
- return Boolean(this.routeScript);
80
- }
81
-
82
- async start() {}
83
-
84
- async stop() {
85
- for (const child of this.children) {
86
- child.kill("SIGTERM");
87
- }
88
- this.children.clear();
89
- }
90
-
91
- async run(prompt, options = {}) {
92
- if (!this.routeScript) {
93
- return normalizeResult({
94
- ok: false,
95
- output: "tfx-route.sh 경로를 찾지 못했습니다.",
96
- exitCode: 70,
97
- });
98
- }
99
-
100
- const timeoutMs =
101
- Number.isFinite(Number(options.timeoutMs)) &&
102
- Number(options.timeoutMs) > 0
103
- ? Number(options.timeoutMs)
104
- : this.timeoutMs;
105
- const timeoutSec = Math.max(1, Math.ceil(timeoutMs / 1000));
106
- const childArgs = [
107
- this.routeScript,
108
- options.agentType || "executor",
109
- String(prompt ?? ""),
110
- options.mcpProfile || "auto",
111
- String(timeoutSec),
112
- ];
113
- const childEnv = {
114
- ...this.env,
115
- ...(options.env || {}),
116
- TFX_CLI_MODE: "antigravity",
117
- };
118
-
119
- const result = await new Promise((resolveResult) => {
120
- const child = spawn(this.bashCommand, childArgs, {
121
- cwd: options.cwd || this.cwd,
122
- env: childEnv,
123
- stdio: ["ignore", "pipe", "pipe"],
124
- });
125
- this.children.add(child);
126
-
127
- let stdout = "";
128
- let stderr = "";
129
- const timeout = setTimeout(() => {
130
- child.kill("SIGTERM");
131
- }, timeoutMs);
132
- timeout.unref?.();
133
-
134
- child.stdout?.setEncoding("utf8");
135
- child.stderr?.setEncoding("utf8");
136
- child.stdout?.on("data", (chunk) => {
137
- stdout += chunk;
138
- });
139
- child.stderr?.on("data", (chunk) => {
140
- stderr += chunk;
141
- });
142
- child.on("close", (code, signal) => {
143
- clearTimeout(timeout);
144
- this.children.delete(child);
145
- const timedOut = signal === "SIGTERM" && code === null;
146
- resolveResult({
147
- ok: code === 0,
148
- output: stdout.trim() || stderr.trim(),
149
- stderr: stderr.trim(),
150
- exitCode: timedOut ? 124 : (code ?? 1),
151
- providerResolved: parseRouteType(stderr),
152
- });
153
- });
154
- child.on("error", (error) => {
155
- clearTimeout(timeout);
156
- this.children.delete(child);
157
- resolveResult({
158
- ok: false,
159
- output: error.message,
160
- stderr,
161
- exitCode: 1,
162
- });
163
- });
164
- });
165
-
166
- return normalizeResult(result);
167
- }
168
-
169
- async execute(prompt, options = {}) {
170
- const result = await this.run(prompt, options);
171
- return {
172
- output: result.output,
173
- exitCode: result.exitCode,
174
- threadId: null,
175
- sessionKey: null,
176
- raw: result.raw,
177
- };
178
- }
179
- }
@@ -1,217 +0,0 @@
1
- // hub/workers/gemini-worker.mjs
2
- // Deprecated compatibility surface. Direct Gemini CLI execution is removed;
3
- // old imports now route through Antigravity.
4
-
5
- import { existsSync } from "node:fs";
6
- import { extname } from "node:path";
7
-
8
- import { AntigravityRouteWorker } from "./antigravity-route-worker.mjs";
9
- import { withRetry } from "./worker-utils.mjs";
10
-
11
- function toStringList(value) {
12
- if (!Array.isArray(value)) return [];
13
- return value.map((item) => String(item ?? "").trim()).filter(Boolean);
14
- }
15
-
16
- /**
17
- * Windows에서 cmd.exe에 전달할 인자를 안전하게 quoting한다.
18
- */
19
- function quoteWindowsCmdArg(value) {
20
- const raw = String(value ?? "").replace(/[\r\n]/g, " ");
21
- if (raw.length === 0) return '""';
22
- if (!/[\s"()^&|<>%!]/.test(raw)) return raw;
23
- const escaped = raw
24
- .replace(/%/g, "%%")
25
- .replace(/(\\*)"/g, '$1$1\\"')
26
- .replace(/(\\+)$/g, "$1$1");
27
- return `"${escaped}"`;
28
- }
29
-
30
- /**
31
- * Windows npm shim(.cmd) spawn 문제를 해결한다.
32
- */
33
- function buildSpawnSpec(command, args) {
34
- if (process.platform !== "win32") {
35
- return { command, args, shell: false };
36
- }
37
-
38
- let resolved = command;
39
- if (!extname(resolved)) {
40
- for (const ext of [".exe", ".cmd", ".bat"]) {
41
- if (existsSync(resolved + ext)) {
42
- resolved = resolved + ext;
43
- break;
44
- }
45
- }
46
- }
47
-
48
- if (/\.(cmd|bat)$/i.test(resolved)) {
49
- const line = [resolved, ...args].map(quoteWindowsCmdArg).join(" ");
50
- return {
51
- command: "cmd.exe",
52
- args: ["/d", "/s", "/v:off", "/c", line],
53
- shell: false,
54
- };
55
- }
56
-
57
- return { command: resolved, args, shell: false };
58
- }
59
-
60
- function createWorkerError(message, details = {}) {
61
- const error = new Error(message);
62
- Object.assign(error, details);
63
- return error;
64
- }
65
-
66
- function normalizeRetryOptions(retryOptions) {
67
- if (!retryOptions || typeof retryOptions !== "object") {
68
- return Object.freeze({});
69
- }
70
- return Object.freeze({ ...retryOptions });
71
- }
72
-
73
- function isAntigravityRetryable(error) {
74
- return (
75
- error?.code === "WORKER_EXIT" &&
76
- error?.result?.exitCode !== 0 &&
77
- error?.result?.exitCode !== 2
78
- );
79
- }
80
-
81
- function detectAntigravityCategory(error) {
82
- const combined =
83
- `${error?.message || ""}\n${error?.stderr || ""}`.toLowerCase();
84
-
85
- if (
86
- /(unauthorized|forbidden|auth|login|token|credential|apikey|api key)/.test(
87
- combined,
88
- )
89
- ) {
90
- return "auth";
91
- }
92
- if (
93
- error?.result?.exitCode === 2 ||
94
- /unknown option|invalid option|config|route script/.test(combined)
95
- ) {
96
- return "config";
97
- }
98
-
99
- return "transient";
100
- }
101
-
102
- function buildAntigravityErrorInfo(error, attempts) {
103
- const category = detectAntigravityCategory(error);
104
- const retryable = isAntigravityRetryable(error);
105
- let recovery =
106
- "Retry the Antigravity route worker after correcting the issue.";
107
-
108
- if (category === "auth") {
109
- recovery = "Refresh the Antigravity authentication state and retry.";
110
- } else if (category === "config") {
111
- recovery = "Check the Antigravity route worker configuration.";
112
- }
113
-
114
- return Object.freeze({
115
- code: error?.code || "ANTIGRAVITY_EXECUTION_ERROR",
116
- retryable,
117
- attempts,
118
- category,
119
- recovery,
120
- });
121
- }
122
-
123
- export class GeminiWorker extends AntigravityRouteWorker {
124
- type = "antigravity";
125
-
126
- constructor(options = {}) {
127
- const { command, commandArgs, args, model, approvalMode, yolo, ...rest } =
128
- options;
129
- void commandArgs;
130
- void args;
131
- void model;
132
- void approvalMode;
133
- void yolo;
134
- super(rest);
135
- this.command = command || "agy";
136
- this.retryOptions = normalizeRetryOptions(options.retryOptions);
137
- this.lastRun = null;
138
- }
139
-
140
- getStatus() {
141
- return {
142
- type: "antigravity",
143
- state: this.children.size > 0 ? "running" : "idle",
144
- pid: null,
145
- last_run_at_ms: this.lastRun?.finishedAtMs || null,
146
- last_exit_code: this.lastRun?.exitCode ?? null,
147
- };
148
- }
149
-
150
- async run(prompt, options = {}) {
151
- const startedAtMs = Date.now();
152
- const result = await super.run(prompt, options);
153
- const normalized = {
154
- type: "antigravity",
155
- command: this.command,
156
- args: toStringList(options.extraArgs),
157
- response: result.response || result.output || "",
158
- output: result.output || result.response || "",
159
- stderr: result.stderr || "",
160
- exitCode: result.exitCode ?? 1,
161
- exitSignal: null,
162
- timedOut: result.exitCode === 124,
163
- startedAtMs,
164
- finishedAtMs: Date.now(),
165
- raw: result.raw || result,
166
- };
167
- this.lastRun = normalized;
168
-
169
- if (normalized.exitCode !== 0) {
170
- throw createWorkerError(
171
- `Antigravity route worker exited with code ${normalized.exitCode}`,
172
- {
173
- code: "WORKER_EXIT",
174
- result: normalized,
175
- stderr: normalized.stderr,
176
- },
177
- );
178
- }
179
-
180
- return normalized;
181
- }
182
-
183
- async execute(prompt, options = {}) {
184
- let attempts = 0;
185
-
186
- try {
187
- const result = await withRetry(
188
- async () => {
189
- attempts += 1;
190
- return this.run(prompt, options);
191
- },
192
- {
193
- ...this.retryOptions,
194
- shouldRetry: (error) => isAntigravityRetryable(error),
195
- },
196
- );
197
-
198
- return {
199
- output: result.response,
200
- exitCode: 0,
201
- sessionKey: options.sessionKey || null,
202
- raw: result,
203
- };
204
- } catch (error) {
205
- return {
206
- output: error.stderr || error.message || "Antigravity worker failed",
207
- exitCode: error.code === "ETIMEDOUT" ? 124 : 1,
208
- sessionKey: options.sessionKey || null,
209
- error: buildAntigravityErrorInfo(error, attempts || 1),
210
- raw: error.result || null,
211
- };
212
- }
213
- }
214
- }
215
-
216
- /** @visibleForTesting - 테스트 전용 export. 외부 소비 금지. */
217
- export { buildSpawnSpec, quoteWindowsCmdArg };
@@ -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
- }
@@ -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
- }
@@ -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
- }