chore: rebrand runtime and docs to EJClaw

This commit is contained in:
Eyejoker
2026-03-23 08:09:15 +09:00
parent 634db6f6a9
commit d28b6151a8
36 changed files with 138 additions and 335 deletions

View File

@@ -87,14 +87,14 @@ function buildBaseRunnerEnv(args: {
: currentPath,
TZ: TIMEZONE,
HOME: os.homedir(),
NANOCLAW_GROUP_DIR: args.groupDir,
NANOCLAW_IPC_DIR: args.groupIpcDir,
NANOCLAW_GLOBAL_DIR: args.globalDir,
...(args.group.workDir ? { NANOCLAW_WORK_DIR: args.group.workDir } : {}),
NANOCLAW_CHAT_JID: args.chatJid,
NANOCLAW_GROUP_FOLDER: args.group.folder,
NANOCLAW_IS_MAIN: args.isMain ? '1' : '0',
NANOCLAW_AGENT_TYPE: args.agentType,
EJCLAW_GROUP_DIR: args.groupDir,
EJCLAW_IPC_DIR: args.groupIpcDir,
EJCLAW_GLOBAL_DIR: args.globalDir,
...(args.group.workDir ? { EJCLAW_WORK_DIR: args.group.workDir } : {}),
EJCLAW_CHAT_JID: args.chatJid,
EJCLAW_GROUP_FOLDER: args.group.folder,
EJCLAW_IS_MAIN: args.isMain ? '1' : '0',
EJCLAW_AGENT_TYPE: args.agentType,
CLAUDE_CONFIG_DIR: args.groupSessionsDir,
};
}
@@ -240,22 +240,22 @@ function prepareCodexSessionEnvironment(args: {
let toml = fs.existsSync(sessionConfigPath)
? fs.readFileSync(sessionConfigPath, 'utf-8')
: '';
toml = toml.replace(/\n?\[mcp_servers\.nanoclaw\][\s\S]*?(?=\n\[|$)/, '');
toml = toml.replace(/\n?\[mcp_servers\.ejclaw\][\s\S]*?(?=\n\[|$)/, '');
toml = toml.replace(
/\n?\[mcp_servers\.memento-mcp\][\s\S]*?(?=\n\[|$)/,
'',
);
const mcpSection = `
[mcp_servers.nanoclaw]
[mcp_servers.ejclaw]
command = "node"
args = [${JSON.stringify(mcpServerPath)}]
[mcp_servers.nanoclaw.env]
NANOCLAW_IPC_DIR = ${JSON.stringify(args.env.NANOCLAW_IPC_DIR)}
NANOCLAW_CHAT_JID = ${JSON.stringify(args.chatJid)}
NANOCLAW_GROUP_FOLDER = ${JSON.stringify(args.group.folder)}
NANOCLAW_IS_MAIN = ${JSON.stringify(args.isMain ? '1' : '0')}
NANOCLAW_AGENT_TYPE = ${JSON.stringify(args.env.NANOCLAW_AGENT_TYPE)}
[mcp_servers.ejclaw.env]
EJCLAW_IPC_DIR = ${JSON.stringify(args.env.EJCLAW_IPC_DIR)}
EJCLAW_CHAT_JID = ${JSON.stringify(args.chatJid)}
EJCLAW_GROUP_FOLDER = ${JSON.stringify(args.group.folder)}
EJCLAW_IS_MAIN = ${JSON.stringify(args.isMain ? '1' : '0')}
EJCLAW_AGENT_TYPE = ${JSON.stringify(args.env.EJCLAW_AGENT_TYPE)}
`;
const mementoSseUrl =
args.envVars.MEMENTO_MCP_SSE_URL || process.env.MEMENTO_MCP_SSE_URL;

View File

@@ -5,15 +5,15 @@ import fs from 'fs';
import { spawn } from 'child_process';
// Sentinel markers must match agent-runner.ts
const OUTPUT_START_MARKER = '---NANOCLAW_OUTPUT_START---';
const OUTPUT_END_MARKER = '---NANOCLAW_OUTPUT_END---';
const OUTPUT_START_MARKER = '---EJCLAW_OUTPUT_START---';
const OUTPUT_END_MARKER = '---EJCLAW_OUTPUT_END---';
// Mock config
vi.mock('./config.js', () => ({
AGENT_MAX_OUTPUT_SIZE: 10485760,
AGENT_TIMEOUT: 1800000, // 30min
DATA_DIR: '/tmp/nanoclaw-test-data',
GROUPS_DIR: '/tmp/nanoclaw-test-groups',
DATA_DIR: '/tmp/ejclaw-test-data',
GROUPS_DIR: '/tmp/ejclaw-test-groups',
IDLE_TIMEOUT: 1800000, // 30min
TIMEZONE: 'America/Los_Angeles',
}));
@@ -287,7 +287,7 @@ describe('agent-runner timeout behavior', () => {
const spawnEnv = vi.mocked(spawn).mock.calls[0]?.[2]?.env as
| Record<string, string>
| undefined;
expect(spawnEnv?.NANOCLAW_CHAT_JID).toBe(testInput.chatJid);
expect(spawnEnv?.EJCLAW_CHAT_JID).toBe(testInput.chatJid);
const tomlWrite = vi
.mocked(fs.writeFileSync)
@@ -295,7 +295,7 @@ describe('agent-runner timeout behavior', () => {
String(call[0]).endsWith('/.codex/config.toml'),
);
expect(String(tomlWrite?.[1])).toContain(
`NANOCLAW_CHAT_JID = ${JSON.stringify(testInput.chatJid)}`,
`EJCLAW_CHAT_JID = ${JSON.stringify(testInput.chatJid)}`,
);
});
@@ -322,11 +322,11 @@ describe('agent-runner timeout behavior', () => {
const spawnEnv = vi.mocked(spawn).mock.calls.at(-1)?.[2]?.env as
| Record<string, string>
| undefined;
expect(spawnEnv?.NANOCLAW_IPC_DIR).toBe(
'/tmp/nanoclaw-test-data/ipc/test-group/tasks/task-123',
expect(spawnEnv?.EJCLAW_IPC_DIR).toBe(
'/tmp/ejclaw-test-data/ipc/test-group/tasks/task-123',
);
expect(spawnEnv?.CLAUDE_CONFIG_DIR).toBe(
'/tmp/nanoclaw-test-data/sessions/test-group/tasks/task-123/.claude',
'/tmp/ejclaw-test-data/sessions/test-group/tasks/task-123/.claude',
);
});
@@ -353,11 +353,11 @@ describe('agent-runner timeout behavior', () => {
const spawnEnv = vi.mocked(spawn).mock.calls.at(-1)?.[2]?.env as
| Record<string, string>
| undefined;
expect(spawnEnv?.NANOCLAW_IPC_DIR).toBe(
'/tmp/nanoclaw-test-data/ipc/test-group/tasks/task-watch-group',
expect(spawnEnv?.EJCLAW_IPC_DIR).toBe(
'/tmp/ejclaw-test-data/ipc/test-group/tasks/task-watch-group',
);
expect(spawnEnv?.CLAUDE_CONFIG_DIR).toBe(
'/tmp/nanoclaw-test-data/sessions/test-group/.claude',
'/tmp/ejclaw-test-data/sessions/test-group/.claude',
);
});
@@ -365,9 +365,9 @@ describe('agent-runner timeout behavior', () => {
vi.useRealTimers();
fakeProc = createFakeProcess();
const overlayPath =
'/tmp/nanoclaw-test-groups/test-group/.codex/config.toml';
'/tmp/ejclaw-test-groups/test-group/.codex/config.toml';
const sessionConfigPath =
'/tmp/nanoclaw-test-data/sessions/test-group/.codex/config.toml';
'/tmp/ejclaw-test-data/sessions/test-group/.codex/config.toml';
let sessionToml = `model = "gpt-5.4"\n`;
vi.mocked(fs.existsSync).mockImplementation((p: fs.PathLike) => {
@@ -428,7 +428,7 @@ OUROBOROS_LLM_BACKEND = "codex"
const toml = String(tomlWrite?.[1]);
expect(toml).toContain('[mcp_servers.ouroboros]');
expect(toml).toContain('OUROBOROS_AGENT_RUNTIME = "codex"');
expect(toml).toContain('[mcp_servers.nanoclaw]');
expect(toml).toContain('[mcp_servers.ejclaw]');
});
it('waits for queued streamed output before resolving an error exit', async () => {

View File

@@ -1,5 +1,5 @@
/**
* Agent Process Runner for NanoClaw
* Agent Process Runner for EJClaw
* Spawns agent execution as direct host processes and handles IPC
*/
import { ChildProcess, spawn } from 'child_process';
@@ -21,8 +21,8 @@ import { logger } from './logger.js';
import { AgentType, RegisteredGroup } from './types.js';
// Sentinel markers for robust output parsing (must match agent-runner)
const OUTPUT_START_MARKER = '---NANOCLAW_OUTPUT_START---';
const OUTPUT_END_MARKER = '---NANOCLAW_OUTPUT_END---';
const OUTPUT_START_MARKER = '---EJCLAW_OUTPUT_START---';
const OUTPUT_END_MARKER = '---EJCLAW_OUTPUT_END---';
export interface AgentInput {
prompt: string;
@@ -75,12 +75,12 @@ export async function runAgentProcess(
}
}
if (input.runId) {
env.NANOCLAW_RUN_ID = input.runId;
env.EJCLAW_RUN_ID = input.runId;
}
const safeName = group.folder.replace(/[^a-zA-Z0-9-]/g, '-');
const processSuffix = input.runId || `${Date.now()}`;
const processName = `nanoclaw-${safeName}-${processSuffix}`;
const processName = `ejclaw-${safeName}-${processSuffix}`;
// Check if runner is built
const distEntry = path.join(runnerDir, 'dist', 'index.js');
@@ -119,7 +119,7 @@ export async function runAgentProcess(
env,
});
onProcess(proc, processName, env.NANOCLAW_IPC_DIR);
onProcess(proc, processName, env.EJCLAW_IPC_DIR);
let stdout = '';
let stderr = '';

View File

@@ -12,8 +12,8 @@ vi.mock('../env.js', () => ({ readEnvFile: vi.fn(() => ({})) }));
vi.mock('../config.js', () => ({
ASSISTANT_NAME: 'Andy',
TRIGGER_PATTERN: /^@Andy\b/i,
DATA_DIR: '/tmp/nanoclaw-test-data',
CACHE_DIR: '/tmp/nanoclaw-test-cache',
DATA_DIR: '/tmp/ejclaw-test-data',
CACHE_DIR: '/tmp/ejclaw-test-cache',
}));
// Mock logger

View File

@@ -40,17 +40,17 @@ const HOME_DIR = process.env.HOME || os.homedir();
export const SENDER_ALLOWLIST_PATH = path.join(
HOME_DIR,
'.config',
'nanoclaw',
'ejclaw',
'sender-allowlist.json',
);
export const STORE_DIR = path.resolve(
process.env.NANOCLAW_STORE_DIR || path.join(PROJECT_ROOT, 'store'),
process.env.EJCLAW_STORE_DIR || path.join(PROJECT_ROOT, 'store'),
);
export const GROUPS_DIR = path.resolve(
process.env.NANOCLAW_GROUPS_DIR || path.join(PROJECT_ROOT, 'groups'),
process.env.EJCLAW_GROUPS_DIR || path.join(PROJECT_ROOT, 'groups'),
);
export const DATA_DIR = path.resolve(
process.env.NANOCLAW_DATA_DIR || path.join(PROJECT_ROOT, 'data'),
process.env.EJCLAW_DATA_DIR || path.join(PROJECT_ROOT, 'data'),
);
// Shared cache directory (same across both services for dedup)
export const CACHE_DIR = path.join(PROJECT_ROOT, 'cache');

View File

@@ -474,7 +474,7 @@ const isDirectRun =
if (isDirectRun) {
main().catch((err) => {
logger.error({ err }, 'Failed to start NanoClaw');
logger.error({ err }, 'Failed to start EJClaw');
process.exit(1);
});
}

View File

@@ -7,7 +7,7 @@ vi.mock('./agent-runner.js', () => ({
}));
vi.mock('./config.js', () => ({
DATA_DIR: '/tmp/nanoclaw-test-data',
DATA_DIR: '/tmp/ejclaw-test-data',
isSessionCommandSenderAllowed: vi.fn(() => false),
}));