message / apps /cloud /src /cli.mjs
dot
Deliver native DSH market and authenticated cloud MCP with HF deployment
1140c43
Raw History Blame Contribute Delete
4.22 kB
#!/usr/bin/env node
import { initializeProfile, startRuntime, removeBundleOffline, configureProfile, pluginViews, environmentAllowlist, installStreamRedaction, assertProfileStopped } from '@message/runtime';
import { randomUUID } from 'node:crypto';
const [command, profile, ...args] = process.argv.slice(2);
// 仅worker读取获准的环境引用值;stdout协议和stderr启动诊断都进行已知值脱敏。
if (command === 'http' || command === 'mcp' || command === 'call') {
const secrets = new Set([...environmentAllowlist()].map(name => process.env[name]).filter(Boolean));
installStreamRedaction(secrets);
}
const commands = new Set(['init', 'install', 'remove', 'configure', 'enable', 'disable', 'list', 'call', 'mcp', 'http']);
const print = value => process.stdout.write(`${JSON.stringify(value)}\n`);
let runtime;
try {
if (!commands.has(command) || !profile) {
throw new Error('用法: node apps/cloud/src/cli.mjs <init|install|remove|configure|enable|disable|list|call|mcp|http> <profile绝对路径> [包/工具] [JSON参数]');
}
if (command === 'init') {
print({ profile: initializeProfile(profile) });
} else if (command === 'configure') {
print(await configureProfile(profile, args[0], JSON.parse(args[1] ?? '{}')));
} else if (command === 'remove') {
const abort = new AbortController();
const cancel = () => abort.abort();
process.on('SIGTERM', cancel); process.on('SIGINT', cancel);
const result = await removeBundleOffline(profile, args[0], abort.signal);
print(result);
if (result.application === 'failed') process.exitCode = 1;
process.off('SIGTERM', cancel); process.off('SIGINT', cancel);
} else {
if (command === 'install') assertProfileStopped(profile);
runtime = await startRuntime(profile, { transport: command === 'mcp' ? 'stdio' : command === 'http' ? 'http' : 'disabled', port: command === 'http' ? Number(args[0] ?? 0) : 0, management: ['install', 'enable', 'disable', 'list'].includes(command) });
const manager = runtime.ctx.pluginManager;
if (command === 'mcp' || command === 'http') {
// stdio 完全交给 MCP;HTTP 仅公布本机地址,收到信号时释放整个 profile。
if (command === 'http') {
const endpoint = runtime.ctx.get('messageMcpExport');
if (!endpoint?.url) throw new Error('HTTP MCP 插件未成功启动');
process.stderr.write(`${JSON.stringify(endpoint)}\n`);
}
let closing;
const close = () => closing ??= runtime.close().catch(error => {
process.stderr.write(`${error.message}\n`); process.exitCode = 1;
});
if (command === 'mcp') process.stdin.on('end', close);
process.once('SIGTERM', close);
process.once('SIGINT', close);
} else {
let result;
if (command === 'list') result = { version: runtime.version, bundles: await manager.listBundles(), plugins: await pluginViews(runtime), tools: runtime.ctx.tools.schemas() };
else if (!args[0]) throw new Error('缺少包名、安装路径或工具名称');
else if (command === 'install') {
const requestId = randomUUID();
// 取消交给官方manager等待子进程退出与manifest恢复,不能只杀宿主留下pnpm。
const cancel = () => { void manager.cancelInstall(requestId).catch(error => process.stderr.write(`${error.message}\n`)); };
process.on('SIGTERM', cancel); process.on('SIGINT', cancel);
try { result = await manager.installBundle(args[0], { requestId }); }
finally { process.off('SIGTERM', cancel); process.off('SIGINT', cancel); }
}
else if (command === 'enable' || command === 'disable') result = await manager.setBundleEnabled(args[0], command === 'enable');
else result = await runtime.ctx.tools.execute({
callId: 'message-cli', name: args[0], arguments: JSON.parse(args[1] ?? '{}'), signal: new AbortController().signal,
});
print(result);
if (result.application === 'failed' || result.isError) process.exitCode = 1;
await runtime.close();
}
}
} catch (error) {
process.stderr.write(`${error.stack ?? error.message}\n`);
if (runtime) await runtime.close();
process.exitCode = 1;
}