Apply room skill overrides to runner spawn
This commit is contained in:
@@ -108,6 +108,15 @@ const group: RegisteredGroup = {
|
||||
agentType: 'codex',
|
||||
};
|
||||
|
||||
function writeSkill(dir: string, name: string): void {
|
||||
const skillDir = path.join(dir, name);
|
||||
fs.mkdirSync(skillDir, { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(skillDir, 'SKILL.md'),
|
||||
`---\nname: ${name}\ndescription: ${name} skill\n---\n`,
|
||||
);
|
||||
}
|
||||
|
||||
describe('prepareGroupEnvironment codex auth handling', () => {
|
||||
let tempRoot: string;
|
||||
let previousCwd: string;
|
||||
@@ -370,6 +379,133 @@ describe('prepareGroupEnvironment codex auth handling', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('prepareGroupEnvironment room skill overrides', () => {
|
||||
let tempRoot: string;
|
||||
let previousCwd: string;
|
||||
|
||||
beforeEach(() => {
|
||||
tempRoot = fs.mkdtempSync(path.join('/tmp', 'ejclaw-agent-skills-'));
|
||||
previousCwd = process.cwd();
|
||||
process.chdir(tempRoot);
|
||||
process.env.EJ_TEST_ROOT = tempRoot;
|
||||
process.env.EJ_TEST_HOME = path.join(tempRoot, 'home');
|
||||
fs.mkdirSync(path.join(process.env.EJ_TEST_HOME, '.codex'), {
|
||||
recursive: true,
|
||||
});
|
||||
mockReadEnvFile.mockReset();
|
||||
mockGetActiveCodexAuthPath.mockReset();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.chdir(previousCwd);
|
||||
delete process.env.EJ_TEST_ROOT;
|
||||
delete process.env.EJ_TEST_HOME;
|
||||
fs.rmSync(tempRoot, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it('filters Claude session skills with room overrides at spawn time', () => {
|
||||
mockReadEnvFile.mockReturnValue({});
|
||||
const homeSkills = path.join(
|
||||
process.env.EJ_TEST_HOME!,
|
||||
'.claude',
|
||||
'skills',
|
||||
);
|
||||
const workDir = path.join(tempRoot, 'workdir');
|
||||
const runnerSkills = path.join(tempRoot, 'runners', 'skills');
|
||||
writeSkill(homeSkills, 'claude-keep');
|
||||
writeSkill(path.join(workDir, '.claude', 'skills'), 'workdir-keep');
|
||||
writeSkill(runnerSkills, 'runner-keep');
|
||||
writeSkill(runnerSkills, 'runner-off');
|
||||
|
||||
prepareGroupEnvironment(
|
||||
{ ...group, agentType: 'claude-code', workDir },
|
||||
false,
|
||||
'dc:test',
|
||||
{
|
||||
skillOverrides: [
|
||||
{
|
||||
chatJid: 'dc:test',
|
||||
agentType: 'claude-code',
|
||||
skillScope: 'runner',
|
||||
skillName: 'runner-off',
|
||||
enabled: false,
|
||||
createdAt: '2026-05-04T00:00:00.000Z',
|
||||
updatedAt: '2026-05-04T00:00:00.000Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
const sessionSkills = path.join(
|
||||
tempRoot,
|
||||
'sessions',
|
||||
group.folder,
|
||||
'services',
|
||||
'codex-main',
|
||||
'.claude',
|
||||
'skills',
|
||||
);
|
||||
expect(fs.existsSync(path.join(sessionSkills, 'claude-keep'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(sessionSkills, 'workdir-keep'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(sessionSkills, 'runner-keep'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(sessionSkills, 'runner-off'))).toBe(false);
|
||||
});
|
||||
|
||||
it('uses a session-scoped Codex home when room overrides disable skills', () => {
|
||||
mockReadEnvFile.mockReturnValue({});
|
||||
const codexSkills = path.join(
|
||||
process.env.EJ_TEST_HOME!,
|
||||
'.agents',
|
||||
'skills',
|
||||
);
|
||||
const runnerSkills = path.join(tempRoot, 'runners', 'skills');
|
||||
writeSkill(codexSkills, 'codex-keep');
|
||||
writeSkill(codexSkills, 'codex-off');
|
||||
writeSkill(runnerSkills, 'runner-keep');
|
||||
writeSkill(runnerSkills, 'runner-off');
|
||||
|
||||
const prepared = prepareGroupEnvironment(group, false, 'dc:test', {
|
||||
skillOverrides: [
|
||||
{
|
||||
chatJid: 'dc:test',
|
||||
agentType: 'codex',
|
||||
skillScope: 'codex-user',
|
||||
skillName: 'codex-off',
|
||||
enabled: false,
|
||||
createdAt: '2026-05-04T00:00:00.000Z',
|
||||
updatedAt: '2026-05-04T00:00:00.000Z',
|
||||
},
|
||||
{
|
||||
chatJid: 'dc:test',
|
||||
agentType: 'codex',
|
||||
skillScope: 'runner',
|
||||
skillName: 'runner-off',
|
||||
enabled: false,
|
||||
createdAt: '2026-05-04T00:00:00.000Z',
|
||||
updatedAt: '2026-05-04T00:00:00.000Z',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const sessionRoot = path.join(
|
||||
tempRoot,
|
||||
'sessions',
|
||||
group.folder,
|
||||
'services',
|
||||
'codex-main',
|
||||
);
|
||||
const sessionHome = path.join(sessionRoot, 'home');
|
||||
const sessionSkills = path.join(sessionHome, '.agents', 'skills');
|
||||
expect(prepared.env.HOME).toBe(sessionHome);
|
||||
expect(prepared.env.CODEX_HOME).toBe(path.join(sessionRoot, '.codex'));
|
||||
expect(fs.existsSync(path.join(sessionSkills, 'codex-keep'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(sessionSkills, 'runner-keep'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(sessionSkills, 'codex-off'))).toBe(false);
|
||||
expect(fs.existsSync(path.join(sessionSkills, 'runner-off'))).toBe(false);
|
||||
expect(fs.existsSync(path.join(codexSkills, 'codex-off'))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('prepareGroupEnvironment Codex goals handling', () => {
|
||||
let tempRoot: string;
|
||||
let previousCwd: string;
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
hasReviewerLease,
|
||||
} from './service-routing.js';
|
||||
import type { AgentType, RegisteredGroup } from './types.js';
|
||||
import type { StoredRoomSkillOverride } from './db/rooms.js';
|
||||
|
||||
// writeCodexApiKeyAuth removed — Codex uses OAuth only.
|
||||
// API key auth caused unintended billing.
|
||||
@@ -53,6 +54,72 @@ function syncDirectoryEntries(sources: string[], destination: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
type SkillSyncScope = 'codex-user' | 'claude-user' | 'runner' | 'workdir';
|
||||
|
||||
interface SkillSyncSource {
|
||||
dir: string;
|
||||
scope: SkillSyncScope;
|
||||
}
|
||||
|
||||
function getDisabledSkillNamesByScope(
|
||||
overrides: StoredRoomSkillOverride[] | undefined,
|
||||
agentType: AgentType,
|
||||
): Map<SkillSyncScope, Set<string>> {
|
||||
const disabled = new Map<SkillSyncScope, Set<string>>();
|
||||
for (const override of overrides ?? []) {
|
||||
if (override.agentType !== agentType || override.enabled !== false)
|
||||
continue;
|
||||
if (
|
||||
override.skillScope !== 'codex-user' &&
|
||||
override.skillScope !== 'claude-user' &&
|
||||
override.skillScope !== 'runner'
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const names = disabled.get(override.skillScope) ?? new Set<string>();
|
||||
names.add(override.skillName);
|
||||
disabled.set(override.skillScope, names);
|
||||
}
|
||||
return disabled;
|
||||
}
|
||||
|
||||
function hasDisabledSkillOverrides(
|
||||
overrides: StoredRoomSkillOverride[] | undefined,
|
||||
agentType: AgentType,
|
||||
): boolean {
|
||||
return (overrides ?? []).some(
|
||||
(override) =>
|
||||
override.agentType === agentType && override.enabled === false,
|
||||
);
|
||||
}
|
||||
|
||||
function syncRoomSkillDirectories(args: {
|
||||
sources: SkillSyncSource[];
|
||||
destination: string;
|
||||
agentType: AgentType;
|
||||
overrides?: StoredRoomSkillOverride[];
|
||||
}): void {
|
||||
const disabledNamesByScope = getDisabledSkillNamesByScope(
|
||||
args.overrides,
|
||||
args.agentType,
|
||||
);
|
||||
|
||||
fs.rmSync(args.destination, { recursive: true, force: true });
|
||||
fs.mkdirSync(args.destination, { recursive: true });
|
||||
|
||||
for (const source of args.sources) {
|
||||
if (!fs.existsSync(source.dir)) continue;
|
||||
for (const entry of fs.readdirSync(source.dir, { withFileTypes: true })) {
|
||||
if (!entry.isDirectory()) continue;
|
||||
if (disabledNamesByScope.get(source.scope)?.has(entry.name)) continue;
|
||||
|
||||
const srcPath = path.join(source.dir, entry.name);
|
||||
const dstPath = path.join(args.destination, entry.name);
|
||||
fs.cpSync(srcPath, dstPath, { recursive: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function readOptionalPromptFile(
|
||||
projectRoot: string,
|
||||
filename: string,
|
||||
@@ -301,6 +368,7 @@ function prepareCodexSessionEnvironment(args: {
|
||||
isPairedRoom: boolean;
|
||||
useFailoverPromptPack: boolean;
|
||||
memoryBriefing?: string;
|
||||
skillOverrides?: StoredRoomSkillOverride[];
|
||||
}): void {
|
||||
// API key auth intentionally removed — Codex uses OAuth only.
|
||||
// Never pass any API key to Codex child process to prevent API billing.
|
||||
@@ -385,7 +453,30 @@ function prepareCodexSessionEnvironment(args: {
|
||||
|
||||
// Codex reads skills from ~/.agents/skills/ (user-level) and
|
||||
// {workDir}/.agents/skills/ (project-level), NOT from .codex/skills/.
|
||||
// Sync to the user-level path so all Codex sessions can discover them.
|
||||
if (hasDisabledSkillOverrides(args.skillOverrides, 'codex')) {
|
||||
const sessionHomeDir = path.join(args.sessionRootDir, 'home');
|
||||
args.env.HOME = sessionHomeDir;
|
||||
syncRoomSkillDirectories({
|
||||
sources: [
|
||||
{
|
||||
dir: path.join(os.homedir(), '.claude', 'skills'),
|
||||
scope: 'codex-user',
|
||||
},
|
||||
{
|
||||
dir: path.join(os.homedir(), '.agents', 'skills'),
|
||||
scope: 'codex-user',
|
||||
},
|
||||
{
|
||||
dir: path.join(args.projectRoot, 'runners', 'skills'),
|
||||
scope: 'runner',
|
||||
},
|
||||
],
|
||||
destination: path.join(sessionHomeDir, '.agents', 'skills'),
|
||||
agentType: 'codex',
|
||||
overrides: args.skillOverrides,
|
||||
});
|
||||
} else {
|
||||
// Preserve the historical global sync path when no room override exists.
|
||||
const codexSkillsDir = path.join(os.homedir(), '.agents', 'skills');
|
||||
syncDirectoryEntries(
|
||||
[
|
||||
@@ -394,6 +485,7 @@ function prepareCodexSessionEnvironment(args: {
|
||||
],
|
||||
codexSkillsDir,
|
||||
);
|
||||
}
|
||||
|
||||
const mcpServerPath = path.join(
|
||||
args.projectRoot,
|
||||
@@ -411,7 +503,7 @@ function prepareCodexSessionEnvironment(args: {
|
||||
chatJid: args.chatJid,
|
||||
groupFolder: args.group.folder,
|
||||
isMain: args.isMain,
|
||||
agentType: args.group.agentType || 'claude-code',
|
||||
agentType: 'codex',
|
||||
workDir:
|
||||
args.env.EJCLAW_WORK_DIR || args.group.workDir || args.projectRoot,
|
||||
});
|
||||
@@ -430,6 +522,10 @@ export interface PreparedGroupEnvironment {
|
||||
runnerDir: string;
|
||||
}
|
||||
|
||||
export interface PreparedReadonlySessionEnvironment {
|
||||
codexHomeDir?: string;
|
||||
}
|
||||
|
||||
export function prepareGroupEnvironment(
|
||||
group: RegisteredGroup,
|
||||
isMain: boolean,
|
||||
@@ -438,6 +534,7 @@ export function prepareGroupEnvironment(
|
||||
memoryBriefing?: string;
|
||||
runtimeTaskId?: string;
|
||||
useTaskScopedSession?: boolean;
|
||||
skillOverrides?: StoredRoomSkillOverride[];
|
||||
},
|
||||
): PreparedGroupEnvironment {
|
||||
const projectRoot = process.cwd();
|
||||
@@ -463,12 +560,26 @@ export function prepareGroupEnvironment(
|
||||
const workDirClaude = group.workDir
|
||||
? path.join(group.workDir, '.claude')
|
||||
: null;
|
||||
const skillSources = [
|
||||
path.join(os.homedir(), '.claude', 'skills'),
|
||||
...(workDirClaude ? [path.join(workDirClaude, 'skills')] : []),
|
||||
path.join(projectRoot, 'runners', 'skills'),
|
||||
];
|
||||
syncDirectoryEntries(skillSources, path.join(groupSessionsDir, 'skills'));
|
||||
syncRoomSkillDirectories({
|
||||
sources: [
|
||||
{
|
||||
dir: path.join(os.homedir(), '.claude', 'skills'),
|
||||
scope: 'claude-user',
|
||||
},
|
||||
...(workDirClaude
|
||||
? [
|
||||
{
|
||||
dir: path.join(workDirClaude, 'skills'),
|
||||
scope: 'workdir' as const,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{ dir: path.join(projectRoot, 'runners', 'skills'), scope: 'runner' },
|
||||
],
|
||||
destination: path.join(groupSessionsDir, 'skills'),
|
||||
agentType: 'claude-code',
|
||||
overrides: options?.skillOverrides,
|
||||
});
|
||||
|
||||
const groupIpcDir = runtimeTaskId
|
||||
? resolveTaskRuntimeIpcPath(group.folder, runtimeTaskId)
|
||||
@@ -566,6 +677,7 @@ export function prepareGroupEnvironment(
|
||||
isPairedRoom,
|
||||
useFailoverPromptPack: useCodexReviewFailoverPromptPack,
|
||||
memoryBriefing: options?.memoryBriefing,
|
||||
skillOverrides: options?.skillOverrides,
|
||||
});
|
||||
} else {
|
||||
prepareClaudeEnvironment({ env, envVars, group });
|
||||
@@ -594,7 +706,8 @@ export function prepareReadonlySessionEnvironment(args: {
|
||||
ipcDir?: string;
|
||||
hostIpcDir?: string;
|
||||
workDir?: string;
|
||||
}): void {
|
||||
skillOverrides?: StoredRoomSkillOverride[];
|
||||
}): PreparedReadonlySessionEnvironment {
|
||||
const {
|
||||
sessionDir,
|
||||
chatJid,
|
||||
@@ -606,6 +719,7 @@ export function prepareReadonlySessionEnvironment(args: {
|
||||
ipcDir = '/workspace/ipc',
|
||||
hostIpcDir = ipcDir,
|
||||
workDir = '/workspace/project',
|
||||
skillOverrides,
|
||||
} = args;
|
||||
const projectRoot = process.cwd();
|
||||
|
||||
@@ -614,11 +728,40 @@ export function prepareReadonlySessionEnvironment(args: {
|
||||
ensureClaudeGlobalSettingsFile(sessionDir);
|
||||
|
||||
// Sync skills from host
|
||||
const skillSources = [
|
||||
path.join(os.homedir(), '.claude', 'skills'),
|
||||
path.join(projectRoot, 'runners', 'skills'),
|
||||
];
|
||||
syncDirectoryEntries(skillSources, path.join(sessionDir, 'skills'));
|
||||
syncRoomSkillDirectories({
|
||||
sources: [
|
||||
{
|
||||
dir: path.join(os.homedir(), '.claude', 'skills'),
|
||||
scope: agentType === 'codex' ? 'codex-user' : 'claude-user',
|
||||
},
|
||||
{ dir: path.join(projectRoot, 'runners', 'skills'), scope: 'runner' },
|
||||
],
|
||||
destination: path.join(sessionDir, 'skills'),
|
||||
agentType,
|
||||
overrides: skillOverrides,
|
||||
});
|
||||
const codexHomeDir =
|
||||
agentType === 'codex' && hasDisabledSkillOverrides(skillOverrides, 'codex')
|
||||
? sessionDir
|
||||
: undefined;
|
||||
if (codexHomeDir) {
|
||||
syncRoomSkillDirectories({
|
||||
sources: [
|
||||
{
|
||||
dir: path.join(os.homedir(), '.claude', 'skills'),
|
||||
scope: 'codex-user',
|
||||
},
|
||||
{
|
||||
dir: path.join(os.homedir(), '.agents', 'skills'),
|
||||
scope: 'codex-user',
|
||||
},
|
||||
{ dir: path.join(projectRoot, 'runners', 'skills'), scope: 'runner' },
|
||||
],
|
||||
destination: path.join(codexHomeDir, '.agents', 'skills'),
|
||||
agentType,
|
||||
overrides: skillOverrides,
|
||||
});
|
||||
}
|
||||
|
||||
// Build CLAUDE.md with role-appropriate prompts (reviewer or arbiter)
|
||||
const claudePlatformPrompt = readPlatformPrompt('claude-code', projectRoot);
|
||||
@@ -688,4 +831,5 @@ export function prepareReadonlySessionEnvironment(args: {
|
||||
} else if (fs.existsSync(sessionClaudeMdPath)) {
|
||||
fs.unlinkSync(sessionClaudeMdPath);
|
||||
}
|
||||
return { codexHomeDir };
|
||||
}
|
||||
|
||||
@@ -71,6 +71,10 @@ vi.mock('./service-routing.js', () => ({
|
||||
hasReviewerLease: vi.fn(() => true),
|
||||
}));
|
||||
|
||||
vi.mock('./db.js', () => ({
|
||||
getStoredRoomSkillOverrides: vi.fn(() => []),
|
||||
}));
|
||||
|
||||
// Create a controllable fake ChildProcess
|
||||
function createFakeProcess() {
|
||||
const proc = new EventEmitter() as EventEmitter & {
|
||||
@@ -108,6 +112,7 @@ vi.mock('child_process', async () => {
|
||||
|
||||
import { runAgentProcess, AgentOutput } from './agent-runner.js';
|
||||
import * as agentRunnerEnvironment from './agent-runner-environment.js';
|
||||
import { getStoredRoomSkillOverrides } from './db.js';
|
||||
import type { RegisteredGroup } from './types.js';
|
||||
|
||||
const testGroup: RegisteredGroup = {
|
||||
@@ -681,10 +686,61 @@ OUROBOROS_LLM_BACKEND = "codex"
|
||||
});
|
||||
});
|
||||
|
||||
describe('agent-runner room skill overrides', () => {
|
||||
beforeEach(() => {
|
||||
vi.useRealTimers();
|
||||
vi.clearAllMocks();
|
||||
vi.mocked(getStoredRoomSkillOverrides).mockReturnValue([]);
|
||||
fakeProc = createFakeProcess();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('passes room skill overrides into runner environment setup', async () => {
|
||||
const skillOverride = {
|
||||
chatJid: testInput.chatJid,
|
||||
agentType: 'claude-code' as const,
|
||||
skillScope: 'runner',
|
||||
skillName: 'runner-off',
|
||||
enabled: false,
|
||||
createdAt: '2026-05-04T00:00:00.000Z',
|
||||
updatedAt: '2026-05-04T00:00:00.000Z',
|
||||
};
|
||||
vi.mocked(getStoredRoomSkillOverrides).mockReturnValue([skillOverride]);
|
||||
const prepareGroupEnvironmentSpy = vi.spyOn(
|
||||
agentRunnerEnvironment,
|
||||
'prepareGroupEnvironment',
|
||||
);
|
||||
|
||||
const resultPromise = runAgentProcess(
|
||||
testGroup,
|
||||
testInput,
|
||||
() => {},
|
||||
async () => {},
|
||||
);
|
||||
|
||||
fakeProc.emit('close', 0);
|
||||
const result = await resultPromise;
|
||||
expect(result.status).toBe('success');
|
||||
expect(getStoredRoomSkillOverrides).toHaveBeenCalledWith(testInput.chatJid);
|
||||
expect(prepareGroupEnvironmentSpy).toHaveBeenCalledWith(
|
||||
testGroup,
|
||||
testInput.isMain,
|
||||
testInput.chatJid,
|
||||
expect.objectContaining({
|
||||
skillOverrides: [skillOverride],
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('agent-runner Codex goals', () => {
|
||||
beforeEach(() => {
|
||||
vi.useRealTimers();
|
||||
vi.clearAllMocks();
|
||||
vi.mocked(getStoredRoomSkillOverrides).mockReturnValue([]);
|
||||
fakeProc = createFakeProcess();
|
||||
vi.mocked(fs.existsSync).mockImplementation((p: fs.PathLike) => {
|
||||
const str = String(p);
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
prepareGroupEnvironment,
|
||||
} from './agent-runner-environment.js';
|
||||
import { runSpawnedAgentProcess } from './agent-runner-process.js';
|
||||
import { getStoredRoomSkillOverrides } from './db.js';
|
||||
export {
|
||||
type AvailableGroup,
|
||||
writeGroupsSnapshot,
|
||||
@@ -20,6 +21,7 @@ export {
|
||||
} from './agent-runner-snapshot.js';
|
||||
import { logger } from './logger.js';
|
||||
import { RegisteredGroup, RoomRoleContext } from './types.js';
|
||||
import type { StoredRoomSkillOverride } from './db/rooms.js';
|
||||
|
||||
export interface AgentInput {
|
||||
prompt: string;
|
||||
@@ -50,6 +52,23 @@ export interface AgentOutput {
|
||||
error?: string;
|
||||
}
|
||||
|
||||
function readRoomSkillOverridesForRunner(
|
||||
chatJid: string,
|
||||
): StoredRoomSkillOverride[] {
|
||||
try {
|
||||
return getStoredRoomSkillOverrides(chatJid);
|
||||
} catch (err) {
|
||||
logger.warn(
|
||||
{
|
||||
err,
|
||||
chatJid,
|
||||
},
|
||||
'Failed to read room skill overrides; falling back to default skills',
|
||||
);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export async function runAgentProcess(
|
||||
group: RegisteredGroup,
|
||||
input: AgentInput,
|
||||
@@ -65,6 +84,7 @@ export async function runAgentProcess(
|
||||
|
||||
// ── Host process mode (owner) ───────────────────────────────────
|
||||
const startTime = Date.now();
|
||||
const skillOverrides = readRoomSkillOverridesForRunner(input.chatJid);
|
||||
const { env, groupDir, runnerDir } = prepareGroupEnvironment(
|
||||
group,
|
||||
input.isMain,
|
||||
@@ -73,6 +93,7 @@ export async function runAgentProcess(
|
||||
memoryBriefing: input.memoryBriefing,
|
||||
runtimeTaskId: input.runtimeTaskId,
|
||||
useTaskScopedSession: input.useTaskScopedSession,
|
||||
skillOverrides,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -88,7 +109,7 @@ export async function runAgentProcess(
|
||||
(input.roomRoleContext?.role === 'reviewer' ||
|
||||
input.roomRoleContext?.role === 'arbiter')
|
||||
) {
|
||||
prepareReadonlySessionEnvironment({
|
||||
const readonlySession = prepareReadonlySessionEnvironment({
|
||||
sessionDir: envOverrides.CLAUDE_CONFIG_DIR,
|
||||
chatJid: input.chatJid,
|
||||
isMain: input.isMain,
|
||||
@@ -99,9 +120,13 @@ export async function runAgentProcess(
|
||||
ipcDir: env.EJCLAW_IPC_DIR,
|
||||
hostIpcDir: env.EJCLAW_HOST_IPC_DIR,
|
||||
workDir: envOverrides.EJCLAW_WORK_DIR || env.EJCLAW_WORK_DIR,
|
||||
skillOverrides,
|
||||
});
|
||||
if ((group.agentType || 'claude-code') === 'codex') {
|
||||
env.CODEX_HOME = path.join(envOverrides.CLAUDE_CONFIG_DIR, '.codex');
|
||||
if (readonlySession.codexHomeDir) {
|
||||
env.HOME = readonlySession.codexHomeDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (input.runId) {
|
||||
|
||||
Reference in New Issue
Block a user