@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
|
@@ -464,25 +464,46 @@ export function sendClaudeControlRequest(
|
|
|
464
464
|
|
|
465
465
|
// claude daemon 은 control.sock 의 mutating op(dispatch 등)에 control-key
|
|
466
466
|
// 인증을 강제한다 (미제시 시 EAUTH "didn't present the daemon control key").
|
|
467
|
-
//
|
|
468
|
-
//
|
|
467
|
+
// OMC runtime config 는 .omc-launch-profile.json 의 sourceConfigDir 에서 key 를
|
|
468
|
+
// 발급한다. control.sock 은 runtime config hash 를 쓰더라도 auth 는 발급 config
|
|
469
|
+
// 에서 읽어야 한다. 일반 daemon 은 <configDir>/daemon/control.key 를 사용한다.
|
|
470
|
+
// 어느 경로에도 파일이 없으면 인증 미강제 daemon 으로 보고 auth 를 생략한다
|
|
471
|
+
// (fail-open — 구버전 호환).
|
|
469
472
|
export async function readDaemonControlKey(
|
|
470
473
|
configDir = resolveClaudeConfigDir(),
|
|
474
|
+
{ diagnostics } = {},
|
|
471
475
|
) {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
476
|
+
if (!configDir) return undefined;
|
|
477
|
+
|
|
478
|
+
const runtimeConfigDir = path.resolve(configDir);
|
|
479
|
+
const omcProfile = await readOmcLaunchProfile(runtimeConfigDir);
|
|
480
|
+
const keyConfigDirs = [omcProfile?.sourceConfigDir, runtimeConfigDir].filter(
|
|
481
|
+
(candidate, index, entries) =>
|
|
482
|
+
candidate && entries.indexOf(candidate) === index,
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
for (const keyConfigDir of keyConfigDirs) {
|
|
486
|
+
const keyPath = path.join(keyConfigDir, "daemon", "control.key");
|
|
487
|
+
try {
|
|
488
|
+
const key = await fs.readFile(keyPath, "utf8");
|
|
489
|
+
if (key.trim()) return key.trim();
|
|
490
|
+
} catch (error) {
|
|
491
|
+
if (error?.code === "ENOENT") continue;
|
|
492
|
+
if (Array.isArray(diagnostics)) {
|
|
493
|
+
diagnostics.push({
|
|
494
|
+
code: error?.code || "UNKNOWN",
|
|
495
|
+
path: keyPath,
|
|
496
|
+
message: error?.message || String(error),
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
}
|
|
480
500
|
}
|
|
501
|
+
return undefined;
|
|
481
502
|
}
|
|
482
503
|
|
|
483
|
-
export async function buildDaemonControlAuth(configDir) {
|
|
504
|
+
export async function buildDaemonControlAuth(configDir, opts = {}) {
|
|
484
505
|
if (!configDir) return {};
|
|
485
|
-
const auth = await readDaemonControlKey(configDir);
|
|
506
|
+
const auth = await readDaemonControlKey(configDir, opts);
|
|
486
507
|
return auth ? { auth } : {};
|
|
487
508
|
}
|
|
488
509
|
|
|
@@ -74,7 +74,7 @@ export function parseTeamArgs(args = []) {
|
|
|
74
74
|
const assigns = []; // --assign "codex:프롬프트:역할" 형식
|
|
75
75
|
let autoAttach = true;
|
|
76
76
|
let progressive = true;
|
|
77
|
-
let timeoutSec =
|
|
77
|
+
let timeoutSec = 0;
|
|
78
78
|
let verbose = false;
|
|
79
79
|
let dashboard = true;
|
|
80
80
|
let dashboardLayout = "lite";
|
|
@@ -130,7 +130,7 @@ export function parseTeamArgs(args = []) {
|
|
|
130
130
|
} else if (current === "--no-progressive") {
|
|
131
131
|
progressive = false;
|
|
132
132
|
} else if (current === "--timeout" && args[index + 1]) {
|
|
133
|
-
timeoutSec = Number(args[++index]) ||
|
|
133
|
+
timeoutSec = Number(args[++index]) || 0;
|
|
134
134
|
} else if (current === "--mcp-profile" && args[index + 1]) {
|
|
135
135
|
mcpProfile = args[++index].trim();
|
|
136
136
|
} else if ((current === "--model" || current === "-m") && args[index + 1]) {
|
package/hub/team/conductor.mjs
CHANGED
|
@@ -19,6 +19,8 @@ import {
|
|
|
19
19
|
import { homedir } from "node:os";
|
|
20
20
|
import { dirname, join } from "node:path";
|
|
21
21
|
import { createRegistry } from "@triflux/core/mesh/mesh-registry.mjs";
|
|
22
|
+
import { resolveNestedCodexAgentProfile } from "../../scripts/lib/cli-codex.mjs";
|
|
23
|
+
import { codexProfileConfigOverrides } from "../../scripts/lib/codex-profile-config.mjs";
|
|
22
24
|
import { broker } from "@triflux/core/hub/account-broker.mjs";
|
|
23
25
|
import { runPreflight as runCodexPreflight } from "@triflux/core/hub/codex-preflight.mjs";
|
|
24
26
|
import {
|
|
@@ -608,7 +610,9 @@ export function createConductor(opts = {}) {
|
|
|
608
610
|
cli: session.config.agent,
|
|
609
611
|
prompt: session.config.prompt,
|
|
610
612
|
profile: session.config.profile,
|
|
613
|
+
role: session.config.role,
|
|
611
614
|
model: session.config.model,
|
|
615
|
+
env: session.config.env,
|
|
612
616
|
mcpServers: session.config.mcpServers,
|
|
613
617
|
excludeMcpServers,
|
|
614
618
|
resolveCommand: opts.deps?.resolveCliExecutable,
|
|
@@ -902,8 +906,25 @@ export function createConductor(opts = {}) {
|
|
|
902
906
|
} else if (agent === "gemini") {
|
|
903
907
|
remoteBin = "gemini -y";
|
|
904
908
|
} else {
|
|
905
|
-
|
|
906
|
-
|
|
909
|
+
const codexHome = session.config.env?.CODEX_HOME;
|
|
910
|
+
const profile = resolveNestedCodexAgentProfile(
|
|
911
|
+
session.config.role || "executor",
|
|
912
|
+
{
|
|
913
|
+
profileOverride: session.config.profile ?? "auto",
|
|
914
|
+
globalProfile:
|
|
915
|
+
session.config.env?.TFX_CODEX_PROFILE ??
|
|
916
|
+
process.env.TFX_CODEX_PROFILE,
|
|
917
|
+
codexHome,
|
|
918
|
+
},
|
|
919
|
+
);
|
|
920
|
+
const configArgs = codexProfileConfigOverrides(profile, {
|
|
921
|
+
codexHome,
|
|
922
|
+
disallowUltra: true,
|
|
923
|
+
enforceCanonicalProfile: true,
|
|
924
|
+
})
|
|
925
|
+
.map((override) => `-c '${override.replace(/'/g, `'\\''`)}'`)
|
|
926
|
+
.join(" ");
|
|
927
|
+
remoteBin = `codex exec${configArgs ? ` ${configArgs}` : ""} -s danger-full-access --dangerously-bypass-approvals-and-sandbox`;
|
|
907
928
|
}
|
|
908
929
|
|
|
909
930
|
// prompt는 stdin으로 전달 — 셸 이스케이프 문제 완전 회피
|
|
@@ -2,12 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { dirname, resolve as pathResolve } from "node:path";
|
|
5
|
-
|
|
6
|
-
// scripts/lib is bundled into @triflux/remote itself (package.json files), so
|
|
7
|
-
// import the local mirror relatively rather than via @triflux/core. The core
|
|
8
|
-
// peer range (^10.0.0-alpha.1) could resolve to a build that predates this
|
|
9
|
-
// export, which would fail at import time; the bundled copy is version-skew
|
|
10
|
-
// safe and always carries the matching codexProfileConfigOverrides.
|
|
5
|
+
import { resolveNestedCodexAgentProfile } from "../../scripts/lib/cli-codex.mjs";
|
|
11
6
|
import { codexProfileConfigOverrides } from "../../scripts/lib/codex-profile-config.mjs";
|
|
12
7
|
import { whichCommand } from "@triflux/core/hub/platform.mjs";
|
|
13
8
|
|
|
@@ -165,7 +160,17 @@ export function buildSpawnSpecForMode(mode, opts = {}) {
|
|
|
165
160
|
// still contains an inline [profiles.X] table (which codex re-injects on
|
|
166
161
|
// config rewrite). These go straight to spawn argv (shell: false), so push
|
|
167
162
|
// the raw TOML-scalar overrides without shell-quoting.
|
|
168
|
-
|
|
163
|
+
const codexHome = opts.env?.CODEX_HOME;
|
|
164
|
+
const codexProfile = resolveNestedCodexAgentProfile(opts.role || "executor", {
|
|
165
|
+
profileOverride: opts.profile ?? "auto",
|
|
166
|
+
globalProfile: opts.env?.TFX_CODEX_PROFILE ?? process.env.TFX_CODEX_PROFILE,
|
|
167
|
+
codexHome,
|
|
168
|
+
});
|
|
169
|
+
for (const override of codexProfileConfigOverrides(codexProfile, {
|
|
170
|
+
codexHome,
|
|
171
|
+
disallowUltra: true,
|
|
172
|
+
enforceCanonicalProfile: true,
|
|
173
|
+
})) {
|
|
169
174
|
args.push("-c", override);
|
|
170
175
|
}
|
|
171
176
|
if (Array.isArray(opts.mcpServers)) {
|