dsh-im-ops/bin/dsh-im.mjs
2026-08-15 06:09:19 +08:00

99 lines
3.5 KiB
JavaScript
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
import { readFile } from 'node:fs/promises';
import { homedir, tmpdir } from 'node:os';
import { isAbsolute, join, resolve } from 'node:path';
import { spawnSync } from 'node:child_process';
const PACKAGE_NAME = '@xmanrui/dsh-im';
const DEFAULT_SOURCE = 'github:xmanrui/dsh-im';
const LEGACY_PACKAGES = [
'@xmanrui/dsh-feishu',
'@xmanrui/dsh-weixin',
'@xmanrui/dsh-dingtalk',
];
function usage() {
console.log(`Usage:
dsh-im install [--profile web] [--source <package-spec>]
dsh-im uninstall [--profile web]
Examples:
npx -y github:xmanrui/dsh-im install
dsh-im install --source .`);
}
function takeOption(args, name, fallback) {
const index = args.indexOf(name);
if (index < 0) return fallback;
const value = args[index + 1];
if (!value || value.startsWith('--')) throw new Error(`${name} requires a value`);
args.splice(index, 2);
return value;
}
function runDsh(args) {
const result = spawnSync('dsh', args, {
cwd: tmpdir(),
stdio: 'inherit',
shell: false,
});
if (result.error?.code === 'ENOENT') {
throw new Error('找不到 dsh,请先安装 DeepSeek Harness 并确保 dsh 在 PATH 中。');
}
if (result.error) throw result.error;
if (result.status !== 0) throw new Error(`dsh 退出,状态码 ${result.status ?? 1}`);
}
async function directProfilePackages(profile) {
const dshHome = process.env.DSH_HOME || join(homedir(), '.dsh');
const profilePackage = join(dshHome, 'profiles', profile, 'package.json');
try {
const manifest = JSON.parse(await readFile(profilePackage, 'utf8'));
const bundles = new Set(manifest.dsh?.profile?.bundles ?? []);
const dependencies = manifest.dependencies ?? {};
return new Set(LEGACY_PACKAGES.filter((name) => dependencies[name] || bundles.has(name)));
} catch (error) {
if (error?.code === 'ENOENT') return new Set();
throw new Error(`无法读取 Harness 配置 ${profilePackage}:${error.message}`);
}
}
const args = process.argv.slice(2);
const command = args.shift();
if (!command || command === '--help' || command === '-h') {
usage();
process.exit(0);
}
try {
const profile = takeOption(args, '--profile', 'web');
if (command === 'install') {
const requested = takeOption(args, '--source', DEFAULT_SOURCE);
const source = requested === '.' || requested === '..'
|| requested.startsWith('./') || requested.startsWith('../')
? resolve(process.cwd(), requested)
: (isAbsolute(requested) ? requested : requested);
if (args.length > 0) throw new Error(`无法识别的参数:${args.join(' ')}`);
const legacy = await directProfilePackages(profile);
runDsh(['plugin', '--profile', profile, 'add', '--save-exact', source]);
for (const packageName of legacy) {
runDsh(['plugin', '--profile', profile, 'remove', packageName]);
}
console.log('\nIM 机器人插件已安装。请重启 dsh web,然后打开「设置 → 插件 → IM机器人」。');
if (legacy.size > 0) {
console.log('已用 dsh-im 替换独立飞书/微信/钉钉插件;原有凭据和扫码绑定保持不变。');
}
} else if (command === 'uninstall') {
if (args.length > 0) throw new Error(`无法识别的参数:${args.join(' ')}`);
runDsh(['plugin', '--profile', profile, 'remove', PACKAGE_NAME]);
console.log('\nIM 机器人插件已卸载。请重启 dsh web。');
} else {
throw new Error(`无法识别的命令:${command}`);
}
} catch (error) {
console.error(`dsh-im: ${error.message}`);
process.exit(1);
}