@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.
@@ -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
- // key 는 <configDir>/daemon/control.key (configDir 스코프별). 파일이 없으면
468
- // 인증 미강제 daemon 으로 보고 auth 필드를 생략한다 (fail-open — 구버전 호환).
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
- try {
473
- const key = await fs.readFile(
474
- path.join(configDir, "daemon", "control.key"),
475
- "utf8",
476
- );
477
- return key.trim() || undefined;
478
- } catch {
479
- return undefined;
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 = 300;
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]) || 300;
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]) {
@@ -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
- remoteBin =
906
- "codex exec -s danger-full-access --dangerously-bypass-approvals-and-sandbox";
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
- for (const override of codexProfileConfigOverrides(opts.profile)) {
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)) {