backup current stable ejclaw state

This commit is contained in:
Codex
2026-05-27 10:53:05 +09:00
parent 646bc34372
commit 1509108e04
57 changed files with 7127 additions and 154 deletions

View File

@@ -32,7 +32,7 @@ import {
getEffectiveChannelLease,
hasReviewerLease,
} from './service-routing.js';
import type { AgentType, RegisteredGroup } from './types.js';
import type { AgentType, PairedRoomRole, RegisteredGroup } from './types.js';
// writeCodexApiKeyAuth removed — Codex uses OAuth only.
// API key auth caused unintended billing.
@@ -232,6 +232,7 @@ function prepareClaudeEnvironment(args: {
env: Record<string, string>;
envVars: Record<string, string>;
group: RegisteredGroup;
roomRole?: PairedRoomRole;
}): void {
if (args.envVars.ANTHROPIC_API_KEY || process.env.ANTHROPIC_API_KEY) {
args.env.ANTHROPIC_API_KEY =
@@ -279,6 +280,15 @@ function prepareClaudeEnvironment(args: {
if (args.group.agentConfig?.claudeEffort) {
args.env.CLAUDE_EFFORT = args.group.agentConfig.claudeEffort;
}
// Per-role overrides (paired room): take precedence over the flat values.
if (args.roomRole) {
const modelByRole =
args.group.agentConfig?.claudeModelByRole?.[args.roomRole];
if (modelByRole) args.env.CLAUDE_MODEL = modelByRole;
const effortByRole =
args.group.agentConfig?.claudeEffortByRole?.[args.roomRole];
if (effortByRole) args.env.CLAUDE_EFFORT = effortByRole;
}
if (args.group.agentConfig?.claudeThinking) {
args.env.CLAUDE_THINKING = args.group.agentConfig.claudeThinking;
}
@@ -301,19 +311,29 @@ function prepareCodexSessionEnvironment(args: {
isPairedRoom: boolean;
useFailoverPromptPack: boolean;
memoryBriefing?: string;
roomRole?: PairedRoomRole;
}): void {
// API key auth intentionally removed — Codex uses OAuth only.
// Never pass any API key to Codex child process to prevent API billing.
delete args.env.OPENAI_API_KEY;
delete args.env.CODEX_OPENAI_API_KEY;
// Per-role overrides (paired room) win over flat config which wins over env.
const codexModelByRole = args.roomRole
? args.group.agentConfig?.codexModelByRole?.[args.roomRole]
: undefined;
const codexModel =
codexModelByRole ||
args.group.agentConfig?.codexModel ||
args.envVars.CODEX_MODEL ||
process.env.CODEX_MODEL;
if (codexModel) args.env.CODEX_MODEL = codexModel;
const codexEffortByRole = args.roomRole
? args.group.agentConfig?.codexEffortByRole?.[args.roomRole]
: undefined;
const codexEffort =
codexEffortByRole ||
args.group.agentConfig?.codexEffort ||
args.envVars.CODEX_EFFORT ||
process.env.CODEX_EFFORT;
@@ -338,6 +358,23 @@ function prepareCodexSessionEnvironment(args: {
}
const sessionAgentsPath = path.join(sessionCodexDir, 'AGENTS.md');
const codexGlobalDir = path.join(GROUPS_DIR, 'global');
const codexGlobalClaudeMdPath = path.join(codexGlobalDir, 'CLAUDE.md');
const codexGlobalMemory =
!args.isMain && fs.existsSync(codexGlobalClaudeMdPath)
? fs.readFileSync(codexGlobalClaudeMdPath, 'utf-8').trim()
: undefined;
const codexGroupClaudeMdPath = path.join(
GROUPS_DIR,
args.group.folder,
'CLAUDE.md',
);
const codexGroupMemory =
args.group.folder !== 'global' &&
args.group.folder !== 'main' &&
fs.existsSync(codexGroupClaudeMdPath)
? fs.readFileSync(codexGroupClaudeMdPath, 'utf-8').trim()
: undefined;
const sessionAgents = (
args.useFailoverPromptPack
? [
@@ -352,9 +389,12 @@ function prepareCodexSessionEnvironment(args: {
'owner-common-paired-room.md',
)
: undefined,
codexGlobalMemory,
codexGroupMemory,
args.memoryBriefing,
]
: [
readOptionalPromptFile(args.projectRoot, 'owner-common-platform.md'),
readPlatformPrompt('codex', args.projectRoot),
args.isPairedRoom
? readOptionalPromptFile(
@@ -362,6 +402,8 @@ function prepareCodexSessionEnvironment(args: {
'owner-common-paired-room.md',
)
: undefined,
codexGlobalMemory,
codexGroupMemory,
args.memoryBriefing,
]
)
@@ -429,6 +471,13 @@ export function prepareGroupEnvironment(
memoryBriefing?: string;
runtimeTaskId?: string;
useTaskScopedSession?: boolean;
/**
* When provided, the runner consults `agentConfig.{claudeModel,claudeEffort,
* codexModel,codexEffort}ByRole[roomRole]` and lets those entries override
* the flat per-group values. Used by paired rooms to spend the expensive
* model on a specific role (typically arbiter) only.
*/
roomRole?: PairedRoomRole;
},
): PreparedGroupEnvironment {
const projectRoot = process.cwd();
@@ -494,6 +543,13 @@ export function prepareGroupEnvironment(
!isMain && fs.existsSync(globalClaudeMdPath)
? fs.readFileSync(globalClaudeMdPath, 'utf-8').trim()
: undefined;
const groupClaudeMdPath = path.join(GROUPS_DIR, group.folder, 'CLAUDE.md');
const groupClaudeMemory =
group.folder !== 'global' &&
group.folder !== 'main' &&
fs.existsSync(groupClaudeMdPath)
? fs.readFileSync(groupClaudeMdPath, 'utf-8').trim()
: undefined;
// Owner CLAUDE.md: platform rules + owner paired room rules.
// Reviewer paired room rules are NOT included — those belong to the
// Read-only reviewer/arbiter session only (via prepareReadonlySessionEnvironment).
@@ -502,6 +558,7 @@ export function prepareGroupEnvironment(
claudePlatformPrompt,
ownerCommonPairedRoomPrompt,
globalClaudeMemory,
groupClaudeMemory,
options?.memoryBriefing,
]
.filter((value): value is string => Boolean(value))
@@ -559,9 +616,15 @@ export function prepareGroupEnvironment(
isPairedRoom,
useFailoverPromptPack: useCodexReviewFailoverPromptPack,
memoryBriefing: options?.memoryBriefing,
roomRole: options?.roomRole,
});
} else {
prepareClaudeEnvironment({ env, envVars, group });
prepareClaudeEnvironment({
env,
envVars,
group,
roomRole: options?.roomRole,
});
}
return { env, groupDir, runnerDir };
@@ -626,11 +689,19 @@ export function prepareReadonlySessionEnvironment(args: {
!isMain && fs.existsSync(globalClaudeMdPath)
? fs.readFileSync(globalClaudeMdPath, 'utf-8').trim()
: undefined;
const groupClaudeMdPath = path.join(GROUPS_DIR, groupFolder, 'CLAUDE.md');
const groupClaudeMemory =
groupFolder !== 'global' &&
groupFolder !== 'main' &&
fs.existsSync(groupClaudeMdPath)
? fs.readFileSync(groupClaudeMdPath, 'utf-8').trim()
: undefined;
const sessionClaudeMd = [
claudePlatformPrompt,
claudePairedRoomPrompt,
globalClaudeMemory,
groupClaudeMemory,
memoryBriefing,
]
.filter((value): value is string => Boolean(value))