Files
stack/plugins/macp/src/index.ts
Jason Woltje 1b317e8a0a
Some checks failed
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
style: fix prettier formatting in plugins/macp (consolidation follow-up)
2026-03-30 20:43:54 -05:00

103 lines
3.1 KiB
TypeScript

import { createRequire } from 'node:module';
import * as os from 'node:os';
import * as path from 'node:path';
import { MacpRuntime } from './macp-runtime.js';
// Resolve OC plugin SDK dynamically — works on any machine with openclaw installed globally
const ocRequire = createRequire(import.meta.url);
const sdkRoot = path.dirname(ocRequire.resolve('openclaw/dist/plugin-sdk/index.js'));
// Dynamic imports for runtime SDK functions
const { registerAcpRuntimeBackend, unregisterAcpRuntimeBackend } = (await import(
`${sdkRoot}/acp-runtime.js`
)) as {
registerAcpRuntimeBackend: (backend: {
id: string;
runtime: any;
healthy: () => boolean;
}) => void;
unregisterAcpRuntimeBackend: (id: string) => void;
};
type PluginConfig = {
defaultModel?: string;
systemPrompt?: string;
timeoutMs?: number;
logDir?: string;
repoRoot?: string;
orchDir?: string;
defaultDispatch?: string;
defaultRuntime?: string;
};
function expandHome(rawPath: string): string {
if (rawPath === '~') {
return os.homedir();
}
if (rawPath.startsWith('~/')) {
return path.join(os.homedir(), rawPath.slice(2));
}
return rawPath;
}
function resolveConfig(pluginConfig?: Record<string, unknown>, stateDir?: string) {
const config = (pluginConfig ?? {}) as PluginConfig;
const repoRoot = config.repoRoot?.trim()
? path.resolve(expandHome(config.repoRoot))
: path.resolve(os.homedir(), 'src', 'mosaic-stack');
return {
defaultModel: config.defaultModel?.trim() || 'openai/gpt-5-mini',
systemPrompt: config.systemPrompt ?? '',
timeoutMs:
typeof config.timeoutMs === 'number' &&
Number.isFinite(config.timeoutMs) &&
config.timeoutMs > 0
? config.timeoutMs
: 300_000,
stateDir: config.logDir?.trim()
? path.resolve(expandHome(config.logDir))
: (stateDir ?? process.cwd()),
repoRoot,
orchDir: config.orchDir?.trim()
? path.resolve(expandHome(config.orchDir))
: path.join(repoRoot, '.mosaic', 'orchestrator'),
defaultDispatch: config.defaultDispatch?.trim() || 'yolo',
defaultRuntime: config.defaultRuntime?.trim() || 'codex',
};
}
function createMacpRuntimeService(pluginConfig?: Record<string, unknown>) {
let runtime: MacpRuntime | null = null;
return {
id: 'macp-runtime',
async start(ctx: { stateDir: string; logger: { info: (msg: string) => void } }) {
const resolved = resolveConfig(pluginConfig, ctx.stateDir);
runtime = new MacpRuntime({
...resolved,
logger: ctx.logger,
});
registerAcpRuntimeBackend({
id: 'macp',
runtime,
healthy: () => runtime !== null,
});
ctx.logger.info(
`macp runtime backend registered (defaultRuntime: ${resolved.defaultRuntime}, defaultDispatch: ${resolved.defaultDispatch}, timeoutMs: ${resolved.timeoutMs})`,
);
},
async stop() {
if (runtime) {
unregisterAcpRuntimeBackend('macp');
runtime = null;
}
},
};
}
export default function register(api: any) {
const service = createMacpRuntimeService(api.pluginConfig);
api.registerService(service);
}