fix: load ejclaw mcp tools on claude first turn
This commit is contained in:
@@ -60,6 +60,7 @@ import {
|
|||||||
createSanitizeBashHook,
|
createSanitizeBashHook,
|
||||||
} from './runner-hooks.js';
|
} from './runner-hooks.js';
|
||||||
import { buildClaudeSdkEnv } from './sdk-env.js';
|
import { buildClaudeSdkEnv } from './sdk-env.js';
|
||||||
|
import { buildEjclawMcpServerConfig } from './mcp-config.js';
|
||||||
|
|
||||||
interface RunnerInput {
|
interface RunnerInput {
|
||||||
prompt: string;
|
prompt: string;
|
||||||
@@ -299,23 +300,15 @@ async function runQuery(
|
|||||||
settingSources: ['project', 'user'],
|
settingSources: ['project', 'user'],
|
||||||
abortController: agentAbortController,
|
abortController: agentAbortController,
|
||||||
mcpServers: {
|
mcpServers: {
|
||||||
ejclaw: {
|
ejclaw: buildEjclawMcpServerConfig(mcpServerPath, {
|
||||||
command: 'node',
|
chatJid: runnerInput.chatJid,
|
||||||
args: [mcpServerPath],
|
groupFolder: runnerInput.groupFolder,
|
||||||
env: {
|
isMain: runnerInput.isMain,
|
||||||
EJCLAW_CHAT_JID: runnerInput.chatJid,
|
agentType: process.env.EJCLAW_AGENT_TYPE || 'claude-code',
|
||||||
EJCLAW_GROUP_FOLDER: runnerInput.groupFolder,
|
roomRole: runnerInput.roomRoleContext?.role || '',
|
||||||
EJCLAW_IS_MAIN: runnerInput.isMain ? '1' : '0',
|
ipcDir: process.env.EJCLAW_IPC_DIR,
|
||||||
EJCLAW_AGENT_TYPE: process.env.EJCLAW_AGENT_TYPE || 'claude-code',
|
hostIpcDir: process.env.EJCLAW_HOST_IPC_DIR,
|
||||||
EJCLAW_ROOM_ROLE: runnerInput.roomRoleContext?.role || '',
|
|
||||||
...(process.env.EJCLAW_IPC_DIR && {
|
|
||||||
EJCLAW_IPC_DIR: process.env.EJCLAW_IPC_DIR,
|
|
||||||
}),
|
}),
|
||||||
...(process.env.EJCLAW_HOST_IPC_DIR && {
|
|
||||||
EJCLAW_HOST_IPC_DIR: process.env.EJCLAW_HOST_IPC_DIR,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
hooks: {
|
hooks: {
|
||||||
PreCompact: [
|
PreCompact: [
|
||||||
|
|||||||
35
runners/agent-runner/src/mcp-config.ts
Normal file
35
runners/agent-runner/src/mcp-config.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import type { McpStdioServerConfig } from '@anthropic-ai/claude-agent-sdk';
|
||||||
|
|
||||||
|
export interface EjclawMcpServerConfigInput {
|
||||||
|
chatJid: string;
|
||||||
|
groupFolder: string;
|
||||||
|
isMain: boolean;
|
||||||
|
agentType: string;
|
||||||
|
roomRole: string;
|
||||||
|
ipcDir?: string;
|
||||||
|
hostIpcDir?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildEjclawMcpServerConfig(
|
||||||
|
mcpServerPath: string,
|
||||||
|
input: EjclawMcpServerConfigInput,
|
||||||
|
): McpStdioServerConfig {
|
||||||
|
return {
|
||||||
|
command: 'node',
|
||||||
|
args: [mcpServerPath],
|
||||||
|
alwaysLoad: true,
|
||||||
|
env: {
|
||||||
|
EJCLAW_CHAT_JID: input.chatJid,
|
||||||
|
EJCLAW_GROUP_FOLDER: input.groupFolder,
|
||||||
|
EJCLAW_IS_MAIN: input.isMain ? '1' : '0',
|
||||||
|
EJCLAW_AGENT_TYPE: input.agentType,
|
||||||
|
EJCLAW_ROOM_ROLE: input.roomRole,
|
||||||
|
...(input.ipcDir && {
|
||||||
|
EJCLAW_IPC_DIR: input.ipcDir,
|
||||||
|
}),
|
||||||
|
...(input.hostIpcDir && {
|
||||||
|
EJCLAW_HOST_IPC_DIR: input.hostIpcDir,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
32
runners/agent-runner/test/mcp-config.test.ts
Normal file
32
runners/agent-runner/test/mcp-config.test.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
import { buildEjclawMcpServerConfig } from '../src/mcp-config.js';
|
||||||
|
|
||||||
|
describe('ejclaw MCP config', () => {
|
||||||
|
it('always loads EJClaw MCP tools on turn one and preserves runtime env', () => {
|
||||||
|
expect(
|
||||||
|
buildEjclawMcpServerConfig('/runner/dist/ipc-mcp-stdio.js', {
|
||||||
|
chatJid: 'dc:room',
|
||||||
|
groupFolder: 'ejclaw',
|
||||||
|
isMain: true,
|
||||||
|
agentType: 'claude-code',
|
||||||
|
roomRole: 'reviewer',
|
||||||
|
ipcDir: '/tmp/ipc/task',
|
||||||
|
hostIpcDir: '/tmp/ipc/host',
|
||||||
|
}),
|
||||||
|
).toEqual({
|
||||||
|
command: 'node',
|
||||||
|
args: ['/runner/dist/ipc-mcp-stdio.js'],
|
||||||
|
alwaysLoad: true,
|
||||||
|
env: {
|
||||||
|
EJCLAW_CHAT_JID: 'dc:room',
|
||||||
|
EJCLAW_GROUP_FOLDER: 'ejclaw',
|
||||||
|
EJCLAW_IS_MAIN: '1',
|
||||||
|
EJCLAW_AGENT_TYPE: 'claude-code',
|
||||||
|
EJCLAW_ROOM_ROLE: 'reviewer',
|
||||||
|
EJCLAW_IPC_DIR: '/tmp/ipc/task',
|
||||||
|
EJCLAW_HOST_IPC_DIR: '/tmp/ipc/host',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"types": "./src/index.ts",
|
"types": "./src/index.ts",
|
||||||
"default": "./src/index.ts"
|
"default": "./dist/index.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
19
runners/shared/test/package-exports.test.ts
Normal file
19
runners/shared/test/package-exports.test.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
describe('runner shared package exports', () => {
|
||||||
|
it('points runtime imports at built JavaScript for node-launched MCP servers', () => {
|
||||||
|
const packageJson = JSON.parse(
|
||||||
|
fs.readFileSync(
|
||||||
|
path.resolve(import.meta.dirname, '../package.json'),
|
||||||
|
'utf8',
|
||||||
|
),
|
||||||
|
) as { exports: { '.': { default: string; types: string } } };
|
||||||
|
|
||||||
|
expect(packageJson.exports['.']).toEqual({
|
||||||
|
types: './src/index.ts',
|
||||||
|
default: './dist/index.js',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user