mioku 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["query: string","hits: NpmPackageHit[]","prefix: string","packageName: string","version","meta: NpmPackageMeta | null","pluginNames: readonly string[]","message: string","items: Array<{ label: string; value: string }>","initial: string[]","name: string","cwd: string","pkgName: string","cmd: string","args: string[]","options: { cwd?: string }","args","dir: string","err: any","packages: string[]","cwd?: string","p: string","fileTree: Record<string, string | Record<string, unknown>>","base: string","version: string","options?: OmitTypeWithRequired<{ initial?: boolean }>","options?: OmitTypeWithRequired<{ default?: string; placeholder?: string }>","cmdArgs: string[]","helpInfo: string","pkgName: string","packages: string[]","cwd: string","prefix: string","name?: string","cmdArgs: string[]","name: string","fileTree: Record<string, string | Record<string, unknown>>","message: string","prefix: string","initial: string[]","options: { exclude?: string[] }","version: string","pkg","version","args"],"sources":["../../src/cli/shared.ts","../../src/cli/install.ts","../../src/cli/update.ts","../../src/cli/scaffold.ts","../../src/cli/index.ts"],"sourcesContent":["import fs, { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport consola from \"consola\";\nimport dedent from \"dedent\";\nimport {\n clearCommandCache,\n commandExists,\n resolveCommand,\n runCommandInherit,\n} from \"../internal/exec\";\n\nexport const PLUGIN_PREFIX = \"mioku-plugin-\";\nexport const SERVICE_PREFIX = \"mioku-service-\";\nexport const ADAPTER_PREFIX = \"mioku-adapter-\";\n\nexport const NPM_REGISTRY = \"https://registry.npmjs.org\";\nexport const OFFICIAL_REGISTRY_URL =\n \"https://raw.githubusercontent.com/mioku-lab/mioku/main/official-registry.json\";\n\nexport interface NpmPackageHit {\n name: string;\n description: string;\n version: string;\n keywords: string[];\n}\n\nasync function searchNpm(query: string, size = 250): Promise<NpmPackageHit[]> {\n try {\n const url = `${NPM_REGISTRY}/-/v1/search?text=${encodeURIComponent(query)}&size=${size}`;\n const res = await fetch(url, {\n headers: { Accept: \"application/json\", \"User-Agent\": \"mioku-cli\" },\n });\n if (!res.ok) return [];\n const data = (await res.json()) as {\n objects?: Array<{\n package?: {\n name?: string;\n description?: string;\n version?: string;\n keywords?: string[];\n };\n }>;\n };\n const hits: NpmPackageHit[] = [];\n for (const obj of data.objects ?? []) {\n const pkg = obj.package ?? {};\n const name = String(pkg.name ?? \"\").trim();\n if (!name) continue;\n hits.push({\n name,\n description: String(pkg.description ?? \"\").trim(),\n version: String(pkg.version ?? \"\").trim(),\n keywords: Array.isArray(pkg.keywords) ? pkg.keywords.map(String) : [],\n });\n }\n return hits;\n } catch {\n return [];\n }\n}\n\nexport async function searchMiokuPackages(\n prefix: string,\n): Promise<NpmPackageHit[]> {\n const [broad, targeted] = await Promise.all([\n searchNpm(\"mioku\"),\n searchNpm(prefix.replace(/-$/, \"\")),\n ]);\n const seen = new Set<string>();\n const hits: NpmPackageHit[] = [];\n for (const hit of [...broad, ...targeted]) {\n if (!hit.name.startsWith(prefix)) continue;\n if (!hit.keywords.includes(\"mioku\")) continue;\n if (seen.has(hit.name)) continue;\n seen.add(hit.name);\n hits.push(hit);\n }\n return hits.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport interface OfficialRegistryEntry {\n npm?: string;\n builtin?: boolean;\n}\n\nexport interface OfficialRegistry {\n plugins?: Record<string, OfficialRegistryEntry>;\n services?: Record<string, OfficialRegistryEntry>;\n adapters?: Record<string, OfficialRegistryEntry>;\n}\n\nexport async function fetchOfficialRegistry(): Promise<OfficialRegistry | null> {\n try {\n const res = await fetch(OFFICIAL_REGISTRY_URL, {\n headers: { Accept: \"application/json\", \"User-Agent\": \"mioku-cli\" },\n });\n if (!res.ok) return null;\n return (await res.json()) as OfficialRegistry;\n } catch {\n return null;\n }\n}\n\nexport interface NpmPackageMeta {\n version: string;\n description: string;\n keywords: string[];\n mioku?: unknown;\n}\n\nexport async function fetchNpmPackageMeta(\n packageName: string,\n): Promise<NpmPackageMeta | null> {\n try {\n const res = await fetch(\n `${NPM_REGISTRY}/${encodeURIComponent(packageName)}`,\n {\n headers: { Accept: \"application/json\", \"User-Agent\": \"mioku-cli\" },\n },\n );\n if (!res.ok) return null;\n const data = (await res.json()) as any;\n const latest = String(data?.[\"dist-tags\"]?.latest || \"\").trim();\n const version = latest ? (data?.versions?.[latest] ?? {}) : {};\n return {\n version: latest,\n description: String(version?.description || \"\").trim(),\n keywords: Array.isArray(version?.keywords)\n ? version.keywords.map(String)\n : [],\n mioku: version?.mioku,\n };\n } catch {\n return null;\n }\n}\n\nexport function declaredServicesOf(meta: NpmPackageMeta | null): string[] {\n const mioku = meta?.mioku;\n if (Array.isArray(mioku)) {\n return mioku.filter(\n (s): s is string => typeof s === \"string\" && s.length > 0,\n );\n }\n if (mioku && typeof mioku === \"object\") {\n const services = (mioku as { services?: unknown }).services;\n if (Array.isArray(services)) {\n return services.filter(\n (s): s is string => typeof s === \"string\" && s.length > 0,\n );\n }\n }\n return [];\n}\n\nexport async function resolveRequiredServices(\n pluginNames: readonly string[],\n): Promise<string[]> {\n const registry = await fetchOfficialRegistry();\n const serviceMap = new Map<string, string>();\n if (registry) {\n for (const [short, entry] of Object.entries(registry.services ?? {})) {\n if (entry?.npm) serviceMap.set(short, entry.npm);\n }\n }\n\n const required = new Set<string>();\n for (const pluginName of pluginNames) {\n const meta = await fetchNpmPackageMeta(pluginName);\n for (const short of declaredServicesOf(meta)) {\n const npm = serviceMap.get(short) ?? `${SERVICE_PREFIX}${short}`;\n if (serviceMap.has(short)) {\n required.add(npm);\n continue;\n }\n const check = await fetchNpmPackageMeta(npm);\n if (check && check.keywords.includes(\"mioku\")) {\n required.add(npm);\n } else {\n consola.warn(\n `${pluginName} 声明了服务 \"${short}\",但未找到对应的 mioku 服务包,已跳过`,\n );\n }\n }\n }\n return Array.from(required);\n}\n\nexport async function multiSelect(\n message: string,\n items: Array<{ label: string; value: string }>,\n initial: string[] = [],\n): Promise<string[]> {\n if (items.length === 0) return [];\n const result = await consola.prompt(message, {\n type: \"multiselect\",\n options: items,\n initial,\n cancel: \"reject\",\n });\n return (result as Array<string | { value: string }>).map((item) =>\n typeof item === \"string\" ? item : item.value,\n );\n}\n\nexport function runAdapterCli(name: string, cwd: string): void {\n const binPath = path.join(\n cwd,\n \"node_modules\",\n \".bin\",\n `mioku-adapter-${name}`,\n );\n if (fs.existsSync(binPath)) {\n run(binPath, [], { cwd });\n return;\n }\n run(\"bunx\", [`mioku-adapter-${name}`], { cwd });\n}\n\nexport function shortNameOfPackage(pkgName: string): string {\n for (const prefix of [PLUGIN_PREFIX, SERVICE_PREFIX, ADAPTER_PREFIX]) {\n if (pkgName.startsWith(prefix)) return pkgName.slice(prefix.length);\n }\n return pkgName;\n}\n\nexport function run(\n cmd: string,\n args: string[] = [],\n options: { cwd?: string } = {},\n): void {\n runCommandInherit(cmd, args, options);\n}\n\nexport async function rmrf(dir: string, retries = 5): Promise<void> {\n for (let i = 0; i < retries; i++) {\n try {\n fs.rmSync(dir, { recursive: true, force: true });\n return;\n } catch (err: any) {\n if (i === retries - 1) throw err;\n const code = err?.code;\n if (\n code === \"EPERM\" ||\n code === \"EBUSY\" ||\n code === \"ENOTEMPTY\" ||\n code === \"ENOENT\"\n ) {\n await new Promise((resolve) => setTimeout(resolve, 300 * (i + 1)));\n } else {\n throw err;\n }\n }\n }\n}\n\nexport function hasCommand(cmd: string): boolean {\n return commandExists(cmd);\n}\n\nfunction findNpmPath(): string | null {\n const resolved = resolveCommand(\"npm\");\n if (resolved) return resolved;\n if (process.platform !== \"win32\") return null;\n\n const fallbacks = [\n path.join(process.env.ProgramFiles || \"\", \"nodejs\", \"npm.cmd\"),\n path.join(process.env[\"ProgramFiles(x86)\"] || \"\", \"nodejs\", \"npm.cmd\"),\n path.join(process.env.APPDATA || \"\", \"npm\", \"npm.cmd\"),\n ];\n\n return fallbacks.find((candidate) => resolveCommand(candidate)) ?? null;\n}\n\nexport function ensurePackageManager(): void {\n if (hasCommand(\"bun\")) return;\n console.log(\"安装 bun...\");\n const npmPath = findNpmPath();\n if (!npmPath) {\n consola.error(\"未找到 npm,请确保 Node.js 已安装并包含 npm\");\n process.exit(1);\n }\n run(npmPath, [\"install\", \"-g\", \"bun\"]);\n // bun was just put on PATH; drop the cached miss so the next lookup finds it.\n clearCommandCache();\n}\n\nexport function getAddCommand(packages: string[]): [string, string[]] {\n return [\"bun\", [\"add\", ...packages]];\n}\n\nexport function normalizePackageName(input: string): string {\n if (input.startsWith(PLUGIN_PREFIX) || input.startsWith(SERVICE_PREFIX)) {\n return input;\n }\n if (input.startsWith(\"mioku-\")) return input;\n return `${PLUGIN_PREFIX}${input}`;\n}\n\nexport function detectType(name: string): \"plugin\" | \"service\" | \"unknown\" {\n if (name.startsWith(PLUGIN_PREFIX)) return \"plugin\";\n if (name.startsWith(SERVICE_PREFIX)) return \"service\";\n return \"unknown\";\n}\n\nexport function execAdd(packages: string[], cwd?: string): void {\n const [cmd, args] = getAddCommand(packages);\n console.log(`执行: ${cmd} ${args.join(\" \")}`);\n run(cmd, args, { cwd });\n}\n\nexport function appendToMiokuPlugins(cwd: string, pkgName: string): boolean {\n if (!pkgName.startsWith(PLUGIN_PREFIX)) return false;\n const shortName = pkgName.slice(PLUGIN_PREFIX.length);\n\n const packageJsonPath = path.join(cwd, \"package.json\");\n if (!fs.existsSync(packageJsonPath)) return false;\n\n const pkg = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n const mioku = pkg.mioku ?? {};\n const plugins = Array.isArray(mioku.plugins) ? [...mioku.plugins] : [];\n if (plugins.includes(shortName)) return false;\n\n plugins.push(shortName);\n pkg.mioku = { ...mioku, plugins };\n fs.writeFileSync(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\\n`);\n return true;\n}\n\nexport async function getInstalledPackages(cwd: string): Promise<string[]> {\n try {\n const pkg = JSON.parse(\n readFileSync(path.join(cwd, \"package.json\"), \"utf-8\"),\n );\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n return Object.keys(deps).filter((k) => k.startsWith(\"mioku-\"));\n } catch {\n return [];\n }\n}\n\nexport function withRoot(p: string): string {\n return path.resolve(process.cwd(), p);\n}\n\nexport async function fetchNpmKeywords(\n packageName: string,\n): Promise<string[] | null> {\n try {\n const res = await fetch(\n `${NPM_REGISTRY}/${encodeURIComponent(packageName)}`,\n {\n headers: { Accept: \"application/json\", \"User-Agent\": \"mioku-cli\" },\n },\n );\n if (!res.ok) return null;\n const data = (await res.json()) as any;\n const latestVersion = String(data?.[\"dist-tags\"]?.latest || \"\").trim();\n const keywords = latestVersion\n ? data?.versions?.[latestVersion]?.keywords\n : data?.keywords;\n return Array.isArray(keywords) ? keywords.map(String) : [];\n } catch {\n return null;\n }\n}\n\nexport function gracefullyExit(): void {\n console.log(\"Bye!\");\n process.exit(0);\n}\n\nexport function makeFileTree(\n fileTree: Record<string, string | Record<string, unknown>>,\n base: string,\n): void {\n for (const [name, content] of Object.entries(fileTree)) {\n if (typeof content === \"object\" && content !== null) {\n const subPath = `${base}/${name}`;\n if (!fs.existsSync(subPath)) fs.mkdirSync(subPath, { recursive: true });\n for (const [subName, subContent] of Object.entries(content)) {\n if (typeof subContent === \"object\") {\n makeFileTree(\n subContent as Record<string, string | Record<string, unknown>>,\n path.join(subPath, subName),\n );\n } else {\n fs.writeFileSync(`${subPath}/${subName}`, subContent as string);\n }\n }\n } else {\n const filePath = `${base}/${name}`;\n const dirname = path.dirname(filePath);\n if (!fs.existsSync(dirname)) fs.mkdirSync(dirname, { recursive: true });\n fs.writeFileSync(filePath, content as string);\n }\n }\n}\n\nexport function buildHelpInfo(version: string): string {\n return dedent(`\n mioku 命令行工具 v${version}\n\n 用法: mioku <命令> [选项]\n\n 命令:\n install plugin <名称> 安装插件,自动补全 mioku-plugin- 前缀\n install service <名称> 安装服务,自动补全 mioku-service- 前缀\n update [包名|self|all] 更新插件或服务\n update - 检查可用更新\n update all - 更新所有 mioku- 包\n update self - 更新 mioku 框架\n update xxx - 更新指定包\n\n 选项:\n -h, --help 显示帮助信息\n -v, --version 显示版本号\n --name <name> 指定项目/文件夹名称,默认 mioku-bot\n --protocol <protocol> 指定 NapCat 协议,默认 ws\n --host <host> 指定 NapCat 主机,默认 localhost\n --port <port> 指定 NapCat 端口,默认 3001\n --token <token> 指定 NapCat 连接 Token,默认空\n --prefix <prefix> 指定命令前缀,默认 #\n --owners <owners> 指定主人 QQ,英文逗号分隔,必填\n --admins <admins> 指定管理员 QQ,英文逗号分隔,可空\n --use-npm-mirror 使用 npm 镜像源加速依赖安装,默认否\n `);\n}\n\ntype OmitTypeWithRequired<T> = Omit<T, \"type\" | \"required\"> & {\n required?: boolean;\n};\n\nexport async function confirm(\n message: string,\n options?: OmitTypeWithRequired<{ initial?: boolean }>,\n): Promise<boolean> {\n return consola.prompt(message, {\n type: \"confirm\",\n cancel: \"reject\",\n ...options,\n });\n}\n\nexport async function input(\n message: string,\n options?: OmitTypeWithRequired<{ default?: string; placeholder?: string }>,\n): Promise<string> {\n const result = await consola.prompt(message, {\n type: \"text\",\n cancel: \"reject\",\n ...options,\n });\n if (options?.required && !result) return input(message, options);\n return result;\n}\n","import consola from \"consola\";\nimport {\n ensurePackageManager,\n appendToMiokuPlugins,\n execAdd,\n fetchNpmKeywords,\n PLUGIN_PREFIX,\n SERVICE_PREFIX,\n confirm,\n} from \"./shared\";\n\nexport async function installCommand(\n cmdArgs: string[],\n helpInfo: string,\n): Promise<number> {\n ensurePackageManager();\n const cwd = process.cwd();\n const [type, name] = cmdArgs;\n\n if (!type || !name) {\n consola.error(\n \"请指定类型和名称: mioku install plugin <名称> 或 mioku install service <名称>\",\n );\n console.log(helpInfo);\n return 1;\n }\n\n if (type !== \"plugin\" && type !== \"service\") {\n consola.error(`无效的类型 \"${type}\",请使用 plugin 或 service`);\n console.log(helpInfo);\n return 1;\n }\n\n const prefix = type === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const normalized = `${prefix}${name}`;\n\n if (type === \"plugin\") {\n const proceed = await warnIfPrivatePlugin(normalized);\n if (!proceed) {\n consola.info(\"已取消安装\");\n return 1;\n }\n }\n\n try {\n execAdd([normalized], cwd);\n consola.success(`已安装 ${normalized}`);\n\n if (type === \"plugin\") {\n const shortName = normalized.slice(PLUGIN_PREFIX.length);\n if (appendToMiokuPlugins(cwd, normalized)) {\n consola.success(`已在 mioku.plugins 中启用 ${shortName}`);\n } else {\n consola.info(`${shortName} 已在 mioku.plugins 中,跳过`);\n }\n }\n return 0;\n } catch {\n consola.error(`安装失败: ${normalized}`);\n return 1;\n }\n}\n\nasync function warnIfPrivatePlugin(pkgName: string): Promise<boolean> {\n const keywords = await fetchNpmKeywords(pkgName);\n if (keywords === null) return true;\n if (keywords.includes(\"mioku\")) return true;\n\n consola.warn(`${pkgName} 看起来是私有插件\"`);\n consola.warn(\"该插件未上架插件市场,可能存在风险\");\n return confirm(\"仍要继续安装吗?\", { initial: false });\n}\n","import consola from \"consola\";\nimport {\n run,\n ensurePackageManager,\n getInstalledPackages,\n PLUGIN_PREFIX,\n SERVICE_PREFIX,\n} from \"./shared\";\n\nasync function updatePackages(packages: string[], cwd: string): Promise<void> {\n if (packages.length === 0) {\n consola.info(\"未找到 mioku- 相关依赖\");\n return;\n }\n console.log(`执行: bun update ${packages.join(\" \")} --latest`);\n run(\"bun\", [\"update\", ...packages, \"--latest\"], { cwd });\n}\n\nasync function updateByPrefix(\n prefix: string,\n cwd: string,\n name?: string,\n): Promise<void> {\n if (name) {\n const normalized = name.startsWith(prefix) ? name : `${prefix}${name}`;\n console.log(`执行: bun update ${normalized} --latest`);\n run(\"bun\", [\"update\", normalized, \"--latest\"], { cwd });\n return;\n }\n const packages = (await getInstalledPackages(cwd)).filter((p) =>\n p.startsWith(prefix),\n );\n if (packages.length === 0) {\n consola.info(`未找到 ${prefix}* 相关依赖`);\n return;\n }\n await updatePackages(packages, cwd);\n}\n\nexport async function updateCommand(cmdArgs: string[]): Promise<number> {\n ensurePackageManager();\n const cwd = process.cwd();\n const [target, name] = cmdArgs;\n\n if (!target || target === \"check\") {\n run(\"bun\", [\"update\", \"-i\"], { cwd });\n return 0;\n }\n\n if (target === \"all\") {\n await updatePackages(await getInstalledPackages(cwd), cwd);\n return 0;\n }\n\n if (target === \"self\") {\n console.log(\"执行: bun update mioku --latest\");\n run(\"bun\", [\"update\", \"mioku\", \"--latest\"], { cwd });\n return 0;\n }\n\n if (target === \"plugin\" || target === \"service\") {\n const prefix = target === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n await updateByPrefix(prefix, cwd, name);\n return 0;\n }\n\n console.log(`执行: bun update ${target} --latest`);\n run(\"bun\", [\"update\", target, \"--latest\"], { cwd });\n return 0;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport dedent from \"dedent\";\nimport consola from \"consola\";\nimport {\n ADAPTER_PREFIX,\n PLUGIN_PREFIX,\n ensurePackageManager,\n getAddCommand,\n multiSelect,\n run,\n runAdapterCli,\n searchMiokuPackages,\n shortNameOfPackage,\n resolveRequiredServices,\n rmrf,\n withRoot,\n gracefullyExit,\n makeFileTree,\n input,\n confirm,\n} from \"./shared\";\n\n/** stdin 会话对应的主人标识,默认追加到 mioku.owners */\nexport const STDIN_OWNER = \"stdin\";\n\n/** 系统自带适配器:必装且不可取消,默认启用 */\nexport const SYSTEM_ADAPTERS = [\"mioku-adapter-stdin\"];\n\n/** 系统自带插件:必装且不可取消 */\nexport const SYSTEM_PLUGINS = [\"mioku-plugin-help\", \"mioku-plugin-chat\"];\n\n/** 系统服务:框架运行所必需,无条件安装 */\nexport const SYSTEM_SERVICES = [\n \"mioku-service-ai\",\n \"mioku-service-config\",\n \"mioku-service-screenshot\",\n \"mioku-service-help\",\n];\n\nasync function createNewProject(\n name: string,\n fileTree: Record<string, string | Record<string, unknown>>,\n): Promise<string> {\n const projectPath = withRoot(`./${name}`);\n\n if (fs.existsSync(projectPath)) {\n const overwrite = await confirm(`项目 ${name} 已存在,是否覆盖?`);\n if (!overwrite) gracefullyExit();\n\n if (projectPath === process.cwd()) {\n if (fs.readdirSync(projectPath).length !== 0) {\n const confirmOver = await confirm(\n \"项目路径与当前路径相同,将删除当前目录下所有内容再创建,是否继续?\",\n );\n if (!confirmOver) gracefullyExit();\n }\n }\n await rmrf(projectPath);\n }\n\n fs.mkdirSync(projectPath, { recursive: true });\n makeFileTree(fileTree, projectPath);\n console.log(`项目 ${name} 创建成功!`);\n\n console.log(\"正在安装基础依赖 (bun i) ...\");\n run(\"bun\", [\"i\"], { cwd: projectPath });\n return projectPath;\n}\n\nasync function selectPackages(\n message: string,\n prefix: string,\n initial: string[] = [],\n options: { exclude?: string[] } = {},\n): Promise<string[]> {\n console.log(`\\n正在从 npm 拉取 ${prefix}* 包...`);\n const hits = await searchMiokuPackages(prefix);\n if (hits.length === 0) {\n consola.warn(`未在 npm 上找到任何 ${prefix}* 包`);\n return [];\n }\n const excludeSet = new Set(options.exclude ?? []);\n const items = hits\n .filter((hit) => !excludeSet.has(hit.name))\n .map((hit) => ({\n label: `${hit.name} (${hit.description || \"暂无介绍\"})`,\n value: hit.name,\n }));\n return multiSelect(message, items, initial);\n}\n\nexport async function scaffoldCommand(version: string): Promise<number> {\n const name = await input(\"请输入项目名称\", {\n default: \"mioku-bot\",\n placeholder: \"mioku-bot\",\n required: true,\n });\n const owners = await input(\"请输入主人 QQ (最高权限,英文逗号分隔,必填)\", {\n placeholder: \"请输入\",\n default: \"\",\n required: true,\n });\n\n ensurePackageManager();\n\n // stdin 会话默认拥有主人权限:自动追加到 owners\n const ownersList = [\n ...String(owners)\n .split(\",\")\n .map((o) => o.trim())\n .filter(Boolean),\n STDIN_OWNER,\n ].join(\", \");\n\n const adapterNames = await selectPackages(\n \"选择要安装的适配器(上下键选择,空格勾选,回车确认,系统适配器 stdin 将自动安装)\",\n ADAPTER_PREFIX,\n [],\n { exclude: SYSTEM_ADAPTERS },\n );\n const allAdapterNames = [...SYSTEM_ADAPTERS, ...adapterNames];\n if (adapterNames.length === 0) {\n consola.warn(\"未选择其他适配器,将仅启用系统适配器 stdin(终端输入)\");\n }\n\n const pkgJson = dedent(`\n {\n \"name\": \"${name}\",\n \"private\": true,\n \"type\": \"module\",\n \"dependencies\": {\n \"mioku\": \"latest\"\n ${allAdapterNames.map((pkg) => `,\\n \"${pkg}\": \"latest\"`).join(\"\")}\n },\n \"mioku\": {\n \"prefix\": \".\",\n \"owners\": [${ownersList}],\n \"admins\": [],\n \"plugins\": [\"demo\"],\n \"log_level\": \"info\",\n \"online_push\": false,\n \"error_push\": false,\n \"adapters\": {\n \"stdin\": {}\n }\n },\n \"scripts\": {\n \"start\": \"bun run app.ts\",\n \"dev\": \"bun run --watch app.ts\"\n }\n }\n `);\n\n const pluginCode = dedent(`\n import { definePlugin } from 'mioku'\n\n export default definePlugin({\n name: 'demo',\n version: '${version}',\n async setup(ctx) {\n ctx.logger.info('Demo 插件已加载')\n\n ctx.handle('message', async (e) => {\n if (e.raw_message === 'hello') {\n e.reply('world', true)\n }\n })\n\n return () => {\n ctx.logger.info('Demo 插件已卸载')\n }\n },\n })\n `);\n\n const fileTree: Record<string, string | Record<string, unknown>> = {\n \"app.ts\":\n \"import { start } from 'mioku'\\n\\nstart({ cwd: import.meta.dirname }).then()\\n\",\n \"package.json\": pkgJson,\n plugins: { demo: { \"index.ts\": pluginCode } },\n config: {},\n data: {},\n };\n\n const projectPath = await createNewProject(name, fileTree);\n\n // 仅为用户额外选择的适配器运行配置向导(系统适配器 stdin 免配置)\n for (const adapterPkg of adapterNames) {\n const adapterName = shortNameOfPackage(adapterPkg);\n consola.info(`正在运行 ${adapterPkg} 配置向导...`);\n runAdapterCli(adapterName, projectPath);\n }\n consola.info(\n `已自动安装并启用系统适配器: ${SYSTEM_ADAPTERS.map(shortNameOfPackage).join(\", \")}`,\n );\n\n // 系统插件必装且不可取消:从选择列表中剔除,自动启用\n const pluginNames = await selectPackages(\n \"选择要安装的插件(上下键选择,空格勾选,回车确认)\",\n PLUGIN_PREFIX,\n [],\n { exclude: SYSTEM_PLUGINS },\n );\n consola.info(\n `系统插件将自动安装: ${SYSTEM_PLUGINS.map(shortNameOfPackage).join(\", \")}`,\n );\n\n const enabledPlugins = [\n \"demo\",\n ...SYSTEM_PLUGINS.map(shortNameOfPackage),\n ...pluginNames.map(shortNameOfPackage),\n ];\n const pkgPath = path.join(projectPath, \"package.json\");\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n pkg.mioku = { ...pkg.mioku, plugins: enabledPlugins };\n fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`);\n\n const serviceNames = new Set<string>(SYSTEM_SERVICES);\n for (const service of await resolveRequiredServices(pluginNames)) {\n serviceNames.add(service);\n }\n consola.info(\n `将自动安装服务: ${Array.from(serviceNames).map(shortNameOfPackage).join(\", \")}`,\n );\n\n const installWebui = await confirm(\"是否安装 WebUI 管理面板?(建议安装)\", {\n initial: true,\n });\n\n const addPackages = [...pluginNames, ...Array.from(serviceNames)];\n if (installWebui) addPackages.push(\"mioku-service-webui\");\n\n if (addPackages.length > 0) {\n const [cmd, args] = getAddCommand(addPackages);\n console.log(`正在安装插件与服务: ${cmd} ${args.join(\" \")}`);\n run(cmd, args, { cwd: projectPath });\n }\n\n console.log(\"\\n若需启动机器人,请运行:\");\n console.log(\" cd\", name);\n console.log(\" bun run start\");\n return 0;\n}\n","#!/usr/bin/env node\n\nimport mri from \"mri\";\nimport { version } from \"../../package.json\";\nimport { buildHelpInfo } from \"./shared\";\nimport { installCommand } from \"./install\";\nimport { updateCommand } from \"./update\";\nimport { scaffoldCommand } from \"./scaffold\";\n\ninterface CliOptions {\n help?: boolean;\n version?: boolean;\n}\n\nconst args = process.argv.slice(2);\n\n(async () => {\n const cli = mri<CliOptions>(args, { alias: { v: \"version\", h: \"help\" } });\n const helpInfo = buildHelpInfo(version);\n const [cmd, ...cmdArgs] = args;\n\n switch (cmd) {\n case \"install\":\n process.exitCode = await installCommand(cmdArgs, helpInfo);\n return;\n case \"update\":\n process.exitCode = await updateCommand(cmdArgs);\n return;\n default:\n if (cli.version) {\n console.log(`v${version}`);\n return;\n }\n if (cli.help) {\n console.log(helpInfo);\n return;\n }\n process.exitCode = await scaffoldCommand(version);\n return;\n }\n})();\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["query: string","hits: NpmPackageHit[]","prefix: string","packageName: string","version","meta: NpmPackageMeta | null","pluginNames: readonly string[]","message: string","items: Array<{ label: string; value: string }>","initial: string[]","name: string","cwd: string","pkgName: string","cmd: string","args: string[]","options: { cwd?: string }","args","dir: string","err: any","packages: string[]","cwd?: string","p: string","fileTree: Record<string, string | Record<string, unknown>>","base: string","version: string","options?: OmitTypeWithRequired<{ initial?: boolean }>","options?: OmitTypeWithRequired<{ default?: string; placeholder?: string }>","cmdArgs: string[]","helpInfo: string","pkgName: string","packages: string[]","cwd: string","prefix: string","name?: string","cmdArgs: string[]","name: string","fileTree: Record<string, string | Record<string, unknown>>","message: string","prefix: string","initial: string[]","options: { exclude?: string[] }","version: string","version","args"],"sources":["../../src/cli/shared.ts","../../src/cli/install.ts","../../src/cli/update.ts","../../src/cli/scaffold.ts","../../src/cli/index.ts"],"sourcesContent":["import fs, { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport consola from \"consola\";\nimport dedent from \"dedent\";\nimport {\n clearCommandCache,\n commandExists,\n resolveCommand,\n runCommandInherit,\n} from \"../internal/exec\";\n\nexport const PLUGIN_PREFIX = \"mioku-plugin-\";\nexport const SERVICE_PREFIX = \"mioku-service-\";\nexport const ADAPTER_PREFIX = \"mioku-adapter-\";\n\nexport const NPM_REGISTRY = \"https://registry.npmjs.org\";\nexport const OFFICIAL_REGISTRY_URL =\n \"https://raw.githubusercontent.com/mioku-lab/mioku/main/official-registry.json\";\n\nexport interface NpmPackageHit {\n name: string;\n description: string;\n version: string;\n keywords: string[];\n}\n\nasync function searchNpm(query: string, size = 250): Promise<NpmPackageHit[]> {\n try {\n const url = `${NPM_REGISTRY}/-/v1/search?text=${encodeURIComponent(query)}&size=${size}`;\n const res = await fetch(url, {\n headers: { Accept: \"application/json\", \"User-Agent\": \"mioku-cli\" },\n });\n if (!res.ok) return [];\n const data = (await res.json()) as {\n objects?: Array<{\n package?: {\n name?: string;\n description?: string;\n version?: string;\n keywords?: string[];\n };\n }>;\n };\n const hits: NpmPackageHit[] = [];\n for (const obj of data.objects ?? []) {\n const pkg = obj.package ?? {};\n const name = String(pkg.name ?? \"\").trim();\n if (!name) continue;\n hits.push({\n name,\n description: String(pkg.description ?? \"\").trim(),\n version: String(pkg.version ?? \"\").trim(),\n keywords: Array.isArray(pkg.keywords) ? pkg.keywords.map(String) : [],\n });\n }\n return hits;\n } catch {\n return [];\n }\n}\n\nexport async function searchMiokuPackages(\n prefix: string,\n): Promise<NpmPackageHit[]> {\n const [broad, targeted] = await Promise.all([\n searchNpm(\"mioku\"),\n searchNpm(prefix.replace(/-$/, \"\")),\n ]);\n const seen = new Set<string>();\n const hits: NpmPackageHit[] = [];\n for (const hit of [...broad, ...targeted]) {\n if (!hit.name.startsWith(prefix)) continue;\n if (!hit.keywords.includes(\"mioku\")) continue;\n if (seen.has(hit.name)) continue;\n seen.add(hit.name);\n hits.push(hit);\n }\n return hits.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport interface OfficialRegistryEntry {\n npm?: string;\n builtin?: boolean;\n}\n\nexport interface OfficialRegistry {\n plugins?: Record<string, OfficialRegistryEntry>;\n services?: Record<string, OfficialRegistryEntry>;\n adapters?: Record<string, OfficialRegistryEntry>;\n}\n\nexport async function fetchOfficialRegistry(): Promise<OfficialRegistry | null> {\n try {\n const res = await fetch(OFFICIAL_REGISTRY_URL, {\n headers: { Accept: \"application/json\", \"User-Agent\": \"mioku-cli\" },\n });\n if (!res.ok) return null;\n return (await res.json()) as OfficialRegistry;\n } catch {\n return null;\n }\n}\n\nexport interface NpmPackageMeta {\n version: string;\n description: string;\n keywords: string[];\n mioku?: unknown;\n}\n\nexport async function fetchNpmPackageMeta(\n packageName: string,\n): Promise<NpmPackageMeta | null> {\n try {\n const res = await fetch(\n `${NPM_REGISTRY}/${encodeURIComponent(packageName)}`,\n {\n headers: { Accept: \"application/json\", \"User-Agent\": \"mioku-cli\" },\n },\n );\n if (!res.ok) return null;\n const data = (await res.json()) as any;\n const latest = String(data?.[\"dist-tags\"]?.latest || \"\").trim();\n const version = latest ? (data?.versions?.[latest] ?? {}) : {};\n return {\n version: latest,\n description: String(version?.description || \"\").trim(),\n keywords: Array.isArray(version?.keywords)\n ? version.keywords.map(String)\n : [],\n mioku: version?.mioku,\n };\n } catch {\n return null;\n }\n}\n\nexport function declaredServicesOf(meta: NpmPackageMeta | null): string[] {\n const mioku = meta?.mioku;\n if (Array.isArray(mioku)) {\n return mioku.filter(\n (s): s is string => typeof s === \"string\" && s.length > 0,\n );\n }\n if (mioku && typeof mioku === \"object\") {\n const services = (mioku as { services?: unknown }).services;\n if (Array.isArray(services)) {\n return services.filter(\n (s): s is string => typeof s === \"string\" && s.length > 0,\n );\n }\n }\n return [];\n}\n\nexport async function resolveRequiredServices(\n pluginNames: readonly string[],\n): Promise<string[]> {\n const registry = await fetchOfficialRegistry();\n const serviceMap = new Map<string, string>();\n if (registry) {\n for (const [short, entry] of Object.entries(registry.services ?? {})) {\n if (entry?.npm) serviceMap.set(short, entry.npm);\n }\n }\n\n const required = new Set<string>();\n for (const pluginName of pluginNames) {\n const meta = await fetchNpmPackageMeta(pluginName);\n for (const short of declaredServicesOf(meta)) {\n const npm = serviceMap.get(short) ?? `${SERVICE_PREFIX}${short}`;\n if (serviceMap.has(short)) {\n required.add(npm);\n continue;\n }\n const check = await fetchNpmPackageMeta(npm);\n if (check && check.keywords.includes(\"mioku\")) {\n required.add(npm);\n } else {\n consola.warn(\n `${pluginName} 声明了服务 \"${short}\",但未找到对应的 mioku 服务包,已跳过`,\n );\n }\n }\n }\n return Array.from(required);\n}\n\nexport async function multiSelect(\n message: string,\n items: Array<{ label: string; value: string }>,\n initial: string[] = [],\n): Promise<string[]> {\n if (items.length === 0) return [];\n const result = await consola.prompt(message, {\n type: \"multiselect\",\n options: items,\n initial,\n cancel: \"reject\",\n });\n return (result as Array<string | { value: string }>).map((item) =>\n typeof item === \"string\" ? item : item.value,\n );\n}\n\nexport function runAdapterCli(name: string, cwd: string): void {\n const isWin = process.platform === \"win32\";\n const exts = isWin ? [\"\", \".cmd\", \".ps1\", \".bat\"] : [\"\"];\n for (const ext of exts) {\n const binPath = path.join(\n cwd,\n \"node_modules\",\n \".bin\",\n `mioku-adapter-${name}${ext}`,\n );\n if (fs.existsSync(binPath)) {\n run(binPath, [], { cwd });\n return;\n }\n }\n run(\"bunx\", [`mioku-adapter-${name}`], { cwd });\n}\n\nexport function shortNameOfPackage(pkgName: string): string {\n for (const prefix of [PLUGIN_PREFIX, SERVICE_PREFIX, ADAPTER_PREFIX]) {\n if (pkgName.startsWith(prefix)) return pkgName.slice(prefix.length);\n }\n return pkgName;\n}\n\nexport function run(\n cmd: string,\n args: string[] = [],\n options: { cwd?: string } = {},\n): void {\n runCommandInherit(cmd, args, options);\n}\n\nexport async function rmrf(dir: string, retries = 5): Promise<void> {\n for (let i = 0; i < retries; i++) {\n try {\n fs.rmSync(dir, { recursive: true, force: true });\n return;\n } catch (err: any) {\n if (i === retries - 1) throw err;\n const code = err?.code;\n if (\n code === \"EPERM\" ||\n code === \"EBUSY\" ||\n code === \"ENOTEMPTY\" ||\n code === \"ENOENT\"\n ) {\n await new Promise((resolve) => setTimeout(resolve, 300 * (i + 1)));\n } else {\n throw err;\n }\n }\n }\n}\n\nexport function hasCommand(cmd: string): boolean {\n return commandExists(cmd);\n}\n\nfunction findNpmPath(): string | null {\n const resolved = resolveCommand(\"npm\");\n if (resolved) return resolved;\n if (process.platform !== \"win32\") return null;\n\n const fallbacks = [\n path.join(process.env.ProgramFiles || \"\", \"nodejs\", \"npm.cmd\"),\n path.join(process.env[\"ProgramFiles(x86)\"] || \"\", \"nodejs\", \"npm.cmd\"),\n path.join(process.env.APPDATA || \"\", \"npm\", \"npm.cmd\"),\n ];\n\n return fallbacks.find((candidate) => resolveCommand(candidate)) ?? null;\n}\n\nfunction installBunViaOfficialScript(): void {\n console.log(\"安装 bun...\");\n if (process.platform === \"win32\") {\n const ps =\n process.env.SystemRoot &&\n path.join(\n process.env.SystemRoot,\n \"System32\",\n \"WindowsPowerShell\",\n \"v1.0\",\n \"powershell.exe\",\n );\n const psExe = ps && resolveCommand(ps) ? ps : \"powershell\";\n run(psExe, [\n \"-NoProfile\",\n \"-NonInteractive\",\n \"-ExecutionPolicy\",\n \"Bypass\",\n \"-Command\",\n \"irm bun.sh/install.ps1 | iex\",\n ]);\n } else {\n run(\"bash\", [\"-c\", \"curl -fsSL https://bun.sh/install | bash\"]);\n }\n clearCommandCache();\n}\n\nexport function ensurePackageManager(): void {\n if (hasCommand(\"bun\")) return;\n try {\n installBunViaOfficialScript();\n } catch (err) {\n const npmPath = findNpmPath();\n if (!npmPath) {\n consola.error(\"未找到 npm,请确保 Node.js 已安装并包含 npm\");\n consola.error(\n '自动安装 bun 失败,请手动执行:\\n macOS / Linux: curl -fsSL https://bun.sh/install | bash\\n Windows: powershell -c \"irm bun.sh/install.ps1 | iex\"',\n );\n throw err;\n }\n consola.warn(\"官方安装脚本失败,回退到 npm 全局安装 bun ...\");\n run(npmPath, [\"install\", \"-g\", \"bun\"]);\n clearCommandCache();\n }\n if (!hasCommand(\"bun\")) {\n consola.error(\n \"bun 安装后仍无法在 PATH 中找到,请重启终端或将 bun 的安装目录加入 PATH 后重试\",\n );\n process.exit(1);\n }\n}\n\nexport function getAddCommand(packages: string[]): [string, string[]] {\n return [\"bun\", [\"add\", ...packages]];\n}\n\nexport function normalizePackageName(input: string): string {\n if (input.startsWith(PLUGIN_PREFIX) || input.startsWith(SERVICE_PREFIX)) {\n return input;\n }\n if (input.startsWith(\"mioku-\")) return input;\n return `${PLUGIN_PREFIX}${input}`;\n}\n\nexport function detectType(name: string): \"plugin\" | \"service\" | \"unknown\" {\n if (name.startsWith(PLUGIN_PREFIX)) return \"plugin\";\n if (name.startsWith(SERVICE_PREFIX)) return \"service\";\n return \"unknown\";\n}\n\nexport function execAdd(packages: string[], cwd?: string): void {\n const [cmd, args] = getAddCommand(packages);\n console.log(`执行: ${cmd} ${args.join(\" \")}`);\n run(cmd, args, { cwd });\n}\n\nexport function appendToMiokuPlugins(cwd: string, pkgName: string): boolean {\n if (!pkgName.startsWith(PLUGIN_PREFIX)) return false;\n const shortName = pkgName.slice(PLUGIN_PREFIX.length);\n\n const packageJsonPath = path.join(cwd, \"package.json\");\n if (!fs.existsSync(packageJsonPath)) return false;\n\n const pkg = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n const mioku = pkg.mioku ?? {};\n const plugins = Array.isArray(mioku.plugins) ? [...mioku.plugins] : [];\n if (plugins.includes(shortName)) return false;\n\n plugins.push(shortName);\n pkg.mioku = { ...mioku, plugins };\n fs.writeFileSync(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\\n`);\n return true;\n}\n\nexport async function getInstalledPackages(cwd: string): Promise<string[]> {\n try {\n const pkg = JSON.parse(\n readFileSync(path.join(cwd, \"package.json\"), \"utf-8\"),\n );\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n return Object.keys(deps).filter((k) => k.startsWith(\"mioku-\"));\n } catch {\n return [];\n }\n}\n\nexport function withRoot(p: string): string {\n return path.resolve(process.cwd(), p);\n}\n\nexport async function fetchNpmKeywords(\n packageName: string,\n): Promise<string[] | null> {\n try {\n const res = await fetch(\n `${NPM_REGISTRY}/${encodeURIComponent(packageName)}`,\n {\n headers: { Accept: \"application/json\", \"User-Agent\": \"mioku-cli\" },\n },\n );\n if (!res.ok) return null;\n const data = (await res.json()) as any;\n const latestVersion = String(data?.[\"dist-tags\"]?.latest || \"\").trim();\n const keywords = latestVersion\n ? data?.versions?.[latestVersion]?.keywords\n : data?.keywords;\n return Array.isArray(keywords) ? keywords.map(String) : [];\n } catch {\n return null;\n }\n}\n\nexport function gracefullyExit(): void {\n console.log(\"Bye!\");\n process.exit(0);\n}\n\nexport function makeFileTree(\n fileTree: Record<string, string | Record<string, unknown>>,\n base: string,\n): void {\n for (const [name, content] of Object.entries(fileTree)) {\n if (typeof content === \"object\" && content !== null) {\n const subPath = path.join(base, name);\n if (!fs.existsSync(subPath)) fs.mkdirSync(subPath, { recursive: true });\n for (const [subName, subContent] of Object.entries(content)) {\n if (typeof subContent === \"object\") {\n makeFileTree(\n subContent as Record<string, string | Record<string, unknown>>,\n path.join(subPath, subName),\n );\n } else {\n fs.writeFileSync(path.join(subPath, subName), subContent as string);\n }\n }\n } else {\n const filePath = path.join(base, name);\n const dirname = path.dirname(filePath);\n if (!fs.existsSync(dirname)) fs.mkdirSync(dirname, { recursive: true });\n fs.writeFileSync(filePath, content as string);\n }\n }\n}\n\nexport function buildHelpInfo(version: string): string {\n return dedent(`\n mioku 命令行工具 v${version}\n\n 用法: mioku <命令> [选项]\n\n 命令:\n install plugin <名称> 安装插件,自动补全 mioku-plugin- 前缀\n install service <名称> 安装服务,自动补全 mioku-service- 前缀\n update [包名|self|all] 更新插件或服务\n update - 检查可用更新\n update all - 更新所有 mioku- 包\n update self - 更新 mioku 框架\n update xxx - 更新指定包\n\n 选项:\n -h, --help 显示帮助信息\n -v, --version 显示版本号\n --name <name> 指定项目/文件夹名称,默认 mioku-bot\n --protocol <protocol> 指定 NapCat 协议,默认 ws\n --host <host> 指定 NapCat 主机,默认 localhost\n --port <port> 指定 NapCat 端口,默认 3001\n --token <token> 指定 NapCat 连接 Token,默认空\n --prefix <prefix> 指定命令前缀,默认 #\n --owners <owners> 指定主人 QQ,英文逗号分隔,必填\n --admins <admins> 指定管理员 QQ,英文逗号分隔,可空\n --use-npm-mirror 使用 npm 镜像源加速依赖安装,默认否\n `);\n}\n\ntype OmitTypeWithRequired<T> = Omit<T, \"type\" | \"required\"> & {\n required?: boolean;\n};\n\nexport async function confirm(\n message: string,\n options?: OmitTypeWithRequired<{ initial?: boolean }>,\n): Promise<boolean> {\n return consola.prompt(message, {\n type: \"confirm\",\n cancel: \"reject\",\n ...options,\n });\n}\n\nexport async function input(\n message: string,\n options?: OmitTypeWithRequired<{ default?: string; placeholder?: string }>,\n): Promise<string> {\n const result = await consola.prompt(message, {\n type: \"text\",\n cancel: \"reject\",\n ...options,\n });\n if (options?.required && !result) return input(message, options);\n return result;\n}\n","import consola from \"consola\";\nimport {\n ensurePackageManager,\n appendToMiokuPlugins,\n execAdd,\n fetchNpmKeywords,\n PLUGIN_PREFIX,\n SERVICE_PREFIX,\n confirm,\n} from \"./shared\";\n\nexport async function installCommand(\n cmdArgs: string[],\n helpInfo: string,\n): Promise<number> {\n ensurePackageManager();\n const cwd = process.cwd();\n const [type, name] = cmdArgs;\n\n if (!type || !name) {\n consola.error(\n \"请指定类型和名称: mioku install plugin <名称> 或 mioku install service <名称>\",\n );\n console.log(helpInfo);\n return 1;\n }\n\n if (type !== \"plugin\" && type !== \"service\") {\n consola.error(`无效的类型 \"${type}\",请使用 plugin 或 service`);\n console.log(helpInfo);\n return 1;\n }\n\n const prefix = type === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const normalized = `${prefix}${name}`;\n\n if (type === \"plugin\") {\n const proceed = await warnIfPrivatePlugin(normalized);\n if (!proceed) {\n consola.info(\"已取消安装\");\n return 1;\n }\n }\n\n try {\n execAdd([normalized], cwd);\n consola.success(`已安装 ${normalized}`);\n\n if (type === \"plugin\") {\n const shortName = normalized.slice(PLUGIN_PREFIX.length);\n if (appendToMiokuPlugins(cwd, normalized)) {\n consola.success(`已在 mioku.plugins 中启用 ${shortName}`);\n } else {\n consola.info(`${shortName} 已在 mioku.plugins 中,跳过`);\n }\n }\n return 0;\n } catch {\n consola.error(`安装失败: ${normalized}`);\n return 1;\n }\n}\n\nasync function warnIfPrivatePlugin(pkgName: string): Promise<boolean> {\n const keywords = await fetchNpmKeywords(pkgName);\n if (keywords === null) return true;\n if (keywords.includes(\"mioku\")) return true;\n\n consola.warn(`${pkgName} 看起来是私有插件\"`);\n consola.warn(\"该插件未上架插件市场,可能存在风险\");\n return confirm(\"仍要继续安装吗?\", { initial: false });\n}\n","import consola from \"consola\";\nimport {\n run,\n ensurePackageManager,\n getInstalledPackages,\n PLUGIN_PREFIX,\n SERVICE_PREFIX,\n} from \"./shared\";\n\nasync function updatePackages(packages: string[], cwd: string): Promise<void> {\n if (packages.length === 0) {\n consola.info(\"未找到 mioku- 相关依赖\");\n return;\n }\n console.log(`执行: bun update ${packages.join(\" \")} --latest`);\n run(\"bun\", [\"update\", ...packages, \"--latest\"], { cwd });\n}\n\nasync function updateByPrefix(\n prefix: string,\n cwd: string,\n name?: string,\n): Promise<void> {\n if (name) {\n const normalized = name.startsWith(prefix) ? name : `${prefix}${name}`;\n console.log(`执行: bun update ${normalized} --latest`);\n run(\"bun\", [\"update\", normalized, \"--latest\"], { cwd });\n return;\n }\n const packages = (await getInstalledPackages(cwd)).filter((p) =>\n p.startsWith(prefix),\n );\n if (packages.length === 0) {\n consola.info(`未找到 ${prefix}* 相关依赖`);\n return;\n }\n await updatePackages(packages, cwd);\n}\n\nexport async function updateCommand(cmdArgs: string[]): Promise<number> {\n ensurePackageManager();\n const cwd = process.cwd();\n const [target, name] = cmdArgs;\n\n if (!target || target === \"check\") {\n run(\"bun\", [\"update\", \"-i\"], { cwd });\n return 0;\n }\n\n if (target === \"all\") {\n await updatePackages(await getInstalledPackages(cwd), cwd);\n return 0;\n }\n\n if (target === \"self\") {\n console.log(\"执行: bun update mioku --latest\");\n run(\"bun\", [\"update\", \"mioku\", \"--latest\"], { cwd });\n return 0;\n }\n\n if (target === \"plugin\" || target === \"service\") {\n const prefix = target === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n await updateByPrefix(prefix, cwd, name);\n return 0;\n }\n\n console.log(`执行: bun update ${target} --latest`);\n run(\"bun\", [\"update\", target, \"--latest\"], { cwd });\n return 0;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport dedent from \"dedent\";\nimport consola from \"consola\";\nimport {\n ADAPTER_PREFIX,\n PLUGIN_PREFIX,\n ensurePackageManager,\n getAddCommand,\n multiSelect,\n run,\n runAdapterCli,\n searchMiokuPackages,\n shortNameOfPackage,\n resolveRequiredServices,\n rmrf,\n withRoot,\n gracefullyExit,\n makeFileTree,\n input,\n confirm,\n} from \"./shared\";\n\n/** stdin 会话对应的主人标识,默认追加到 mioku.owners */\nexport const STDIN_OWNER = \"stdin\";\n\n/** 系统自带适配器:必装且不可取消,默认启用 */\nexport const SYSTEM_ADAPTERS = [\"mioku-adapter-stdin\"];\n\n/** 系统自带插件:必装且不可取消 */\nexport const SYSTEM_PLUGINS = [\"mioku-plugin-help\", \"mioku-plugin-chat\"];\n\n/** 系统服务:框架运行所必需,无条件安装 */\nexport const SYSTEM_SERVICES = [\n \"mioku-service-ai\",\n \"mioku-service-config\",\n \"mioku-service-screenshot\",\n \"mioku-service-help\",\n];\n\nasync function createNewProject(\n name: string,\n fileTree: Record<string, string | Record<string, unknown>>,\n): Promise<string> {\n const projectPath = withRoot(`./${name}`);\n\n if (fs.existsSync(projectPath)) {\n const overwrite = await confirm(`项目 ${name} 已存在,是否覆盖?`);\n if (!overwrite) gracefullyExit();\n\n if (projectPath === process.cwd()) {\n if (fs.readdirSync(projectPath).length !== 0) {\n const confirmOver = await confirm(\n \"项目路径与当前路径相同,将删除当前目录下所有内容再创建,是否继续?\",\n );\n if (!confirmOver) gracefullyExit();\n }\n }\n await rmrf(projectPath);\n }\n\n fs.mkdirSync(projectPath, { recursive: true });\n makeFileTree(fileTree, projectPath);\n console.log(`项目 ${name} 创建成功!`);\n\n console.log(\"正在安装基础依赖 (bun i) ...\");\n run(\"bun\", [\"i\"], { cwd: projectPath });\n return projectPath;\n}\n\nasync function selectPackages(\n message: string,\n prefix: string,\n initial: string[] = [],\n options: { exclude?: string[] } = {},\n): Promise<string[]> {\n console.log(`\\n正在从 npm 拉取 ${prefix}* 包...`);\n const hits = await searchMiokuPackages(prefix);\n if (hits.length === 0) {\n consola.warn(`未在 npm 上找到任何 ${prefix}* 包`);\n return [];\n }\n const excludeSet = new Set(options.exclude ?? []);\n const items = hits\n .filter((hit) => !excludeSet.has(hit.name))\n .map((hit) => ({\n label: `${hit.name} (${hit.description || \"暂无介绍\"})`,\n value: hit.name,\n }));\n return multiSelect(message, items, initial);\n}\n\nexport async function scaffoldCommand(version: string): Promise<number> {\n const name = await input(\"请输入项目名称\", {\n default: \"mioku-bot\",\n placeholder: \"mioku-bot\",\n required: true,\n });\n const owners = await input(\"请输入主人 QQ (最高权限,英文逗号分隔,必填)\", {\n placeholder: \"请输入\",\n default: \"\",\n required: true,\n });\n\n ensurePackageManager();\n\n // stdin 会话默认拥有主人权限:自动追加到 owners\n const ownersList = [\n ...String(owners)\n .split(\",\")\n .map((o) => o.trim())\n .filter(Boolean),\n STDIN_OWNER,\n ];\n\n const adapterNames = await selectPackages(\n \"选择要安装的适配器(上下键选择,空格勾选,回车确认,系统适配器 stdin 将自动安装)\",\n ADAPTER_PREFIX,\n [],\n { exclude: SYSTEM_ADAPTERS },\n );\n const allAdapterNames = [...SYSTEM_ADAPTERS, ...adapterNames];\n if (adapterNames.length === 0) {\n consola.warn(\"未选择其他适配器,将仅启用系统适配器 stdin(终端输入)\");\n }\n\n const pkgJsonObj = {\n name,\n private: true,\n type: \"module\" as const,\n dependencies: {\n mioku: \"latest\",\n ...Object.fromEntries(allAdapterNames.map((p) => [p, \"latest\"])),\n },\n mioku: {\n prefix: \".\",\n owners: ownersList,\n admins: [] as string[],\n plugins: [\"demo\"],\n log_level: \"info\",\n online_push: false,\n error_push: false,\n adapters: {\n stdin: {},\n },\n },\n scripts: {\n start: \"bun run app.ts\",\n dev: \"bun run --watch app.ts\",\n },\n };\n const pkgJson = `${JSON.stringify(pkgJsonObj, null, 2)}\\n`;\n\n const pluginCode = dedent(`\n import { definePlugin } from 'mioku'\n\n export default definePlugin({\n name: 'demo',\n version: '${version}',\n async setup(ctx) {\n ctx.logger.info('Demo 插件已加载')\n\n ctx.handle('message', async (e) => {\n if (e.raw_message === 'hello') {\n e.reply('world', true)\n }\n })\n\n return () => {\n ctx.logger.info('Demo 插件已卸载')\n }\n },\n })\n `);\n\n const fileTree: Record<string, string | Record<string, unknown>> = {\n \"app.ts\":\n \"import { start } from 'mioku'\\n\\nstart({ cwd: import.meta.dirname }).then()\\n\",\n \"package.json\": pkgJson,\n plugins: { demo: { \"index.ts\": pluginCode } },\n config: {},\n data: {},\n };\n\n const projectPath = await createNewProject(name, fileTree);\n\n // 仅为用户额外选择的适配器运行配置向导(系统适配器 stdin 免配置)\n for (const adapterPkg of adapterNames) {\n const adapterName = shortNameOfPackage(adapterPkg);\n consola.info(`正在运行 ${adapterPkg} 配置向导...`);\n runAdapterCli(adapterName, projectPath);\n }\n consola.info(\n `已自动安装并启用系统适配器: ${SYSTEM_ADAPTERS.map(shortNameOfPackage).join(\", \")}`,\n );\n\n // 系统插件必装且不可取消:从选择列表中剔除,自动启用\n const pluginNames = await selectPackages(\n \"选择要安装的插件(上下键选择,空格勾选,回车确认)\",\n PLUGIN_PREFIX,\n [],\n { exclude: SYSTEM_PLUGINS },\n );\n consola.info(\n `系统插件将自动安装: ${SYSTEM_PLUGINS.map(shortNameOfPackage).join(\", \")}`,\n );\n\n const enabledPlugins = [\n \"demo\",\n ...SYSTEM_PLUGINS.map(shortNameOfPackage),\n ...pluginNames.map(shortNameOfPackage),\n ];\n const pkgPath = path.join(projectPath, \"package.json\");\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n pkg.mioku = { ...pkg.mioku, plugins: enabledPlugins };\n fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`);\n\n const serviceNames = new Set<string>(SYSTEM_SERVICES);\n for (const service of await resolveRequiredServices(pluginNames)) {\n serviceNames.add(service);\n }\n consola.info(\n `将自动安装服务: ${Array.from(serviceNames).map(shortNameOfPackage).join(\", \")}`,\n );\n\n const installWebui = await confirm(\"是否安装 WebUI 管理面板?(建议安装)\", {\n initial: true,\n });\n\n const addPackages = [...pluginNames, ...Array.from(serviceNames)];\n if (installWebui) addPackages.push(\"mioku-service-webui\");\n\n if (addPackages.length > 0) {\n const [cmd, args] = getAddCommand(addPackages);\n console.log(`正在安装插件与服务: ${cmd} ${args.join(\" \")}`);\n run(cmd, args, { cwd: projectPath });\n }\n\n console.log(\"\\n若需启动机器人,请运行:\");\n console.log(\" cd\", name);\n console.log(\" bun run start\");\n return 0;\n}\n","#!/usr/bin/env node\n\nimport mri from \"mri\";\nimport { version } from \"../../package.json\";\nimport { buildHelpInfo } from \"./shared\";\nimport { installCommand } from \"./install\";\nimport { updateCommand } from \"./update\";\nimport { scaffoldCommand } from \"./scaffold\";\n\ninterface CliOptions {\n help?: boolean;\n version?: boolean;\n}\n\nconst args = process.argv.slice(2);\n\n(async () => {\n const cli = mri<CliOptions>(args, { alias: { v: \"version\", h: \"help\" } });\n const helpInfo = buildHelpInfo(version);\n const [cmd, ...cmdArgs] = args;\n\n switch (cmd) {\n case \"install\":\n process.exitCode = await installCommand(cmdArgs, helpInfo);\n return;\n case \"update\":\n process.exitCode = await updateCommand(cmdArgs);\n return;\n default:\n if (cli.version) {\n console.log(`v${version}`);\n return;\n }\n if (cli.help) {\n console.log(helpInfo);\n return;\n }\n process.exitCode = await scaffoldCommand(version);\n return;\n }\n})();\n"],"mappings":"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"}
@@ -27,7 +27,7 @@ const node_os = __toESM(require("node:os"));
27
27
  const node_child_process = __toESM(require("node:child_process"));
28
28
 
29
29
  //#region package.json
30
- var version = "1.0.0";
30
+ var version = "1.0.2";
31
31
 
32
32
  //#endregion
33
33
  //#region src/internal/exec.ts
@@ -97,11 +97,6 @@ function needsCmdShell(resolved) {
97
97
  const ext = node_path.extname(resolved).toLowerCase();
98
98
  return ext === ".cmd" || ext === ".bat";
99
99
  }
100
- function quoteForCmd(arg) {
101
- if (arg === "") return "\"\"";
102
- const escaped = arg.replace(/(\\*)"/g, "$1$1\\\"").replace(/(\\+)$/, "$1$1");
103
- return `"${escaped}"`;
104
- }
105
100
  /** 生成跨平台的 spawn 参数,Windows 下 .cmd/.bat 会改经 cmd.exe 执行 */
106
101
  function buildSpawnPlan(command, args) {
107
102
  const resolved = resolveCommand(command);
@@ -113,17 +108,10 @@ function buildSpawnPlan(command, args) {
113
108
  file: resolved,
114
109
  args
115
110
  };
116
- const comspec = process.env.ComSpec || process.env.COMSPEC || "cmd.exe";
117
- const line = [resolved, ...args].map(quoteForCmd).join(" ");
118
111
  return {
119
- file: comspec,
120
- args: [
121
- "/d",
122
- "/s",
123
- "/c",
124
- `"${line}"`
125
- ],
126
- windowsVerbatimArguments: true
112
+ file: resolved,
113
+ args,
114
+ shell: true
127
115
  };
128
116
  }
129
117
  /** 执行命令并收集 stdout/stderr 与退出码,失败不抛异常 */
@@ -138,7 +126,7 @@ function runCommand(command, args, options = {}) {
138
126
  "pipe",
139
127
  "pipe"
140
128
  ],
141
- windowsVerbatimArguments: plan.windowsVerbatimArguments
129
+ shell: plan.shell
142
130
  });
143
131
  let stdout = "";
144
132
  let stderr = "";
@@ -170,7 +158,7 @@ function runCommandInherit(command, args, options = {}) {
170
158
  const result = (0, node_child_process.spawnSync)(plan.file, plan.args, {
171
159
  cwd: options.cwd,
172
160
  stdio: "inherit",
173
- windowsVerbatimArguments: plan.windowsVerbatimArguments
161
+ shell: plan.shell
174
162
  });
175
163
  if (result.error) throw result.error;
176
164
  if (result.status !== 0) throw new Error(`${command} 退出码 ${result.status}`);
@@ -229,4 +217,4 @@ Object.defineProperty(exports, 'version', {
229
217
  return version;
230
218
  }
231
219
  });
232
- //# sourceMappingURL=exec-gpip41w9.cjs.map
220
+ //# sourceMappingURL=exec-B4lXl4No.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec-B4lXl4No.cjs","names":["path","candidate: string","command: string","resolved: string | null","resolved: string","args: string[]","options: { cwd?: string; env?: NodeJS.ProcessEnv }","options: { cwd?: string }"],"sources":["../package.json","../src/internal/exec.ts"],"sourcesContent":["{\n \"name\": \"mioku\",\n \"type\": \"module\",\n \"version\": \"1.0.2\",\n \"packageManager\": \"bun@1.2.0\",\n \"description\": \"Mioku - A plugin-based QQ bot framework\",\n \"keywords\": [\n \"onebot\",\n \"framework\",\n \"bot\",\n \"mioku\"\n ],\n \"bin\": {\n \"mioku\": \"./dist/cli/index.js\"\n },\n \"engines\": {\n \"node\": \">= 22.18.0\"\n },\n \"homepage\": \"https://github.com/mioku-lab/mioku#readme\",\n \"files\": [\n \"dist\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/mioku-lab/mioku/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/mioku-lab/mioku.git\",\n \"directory\": \"packages/mioku\"\n },\n \"scripts\": {\n \"dev\": \"tsdown -w\",\n \"build\": \"tsdown\",\n \"typecheck\": \"tsc --noEmit\"\n },\n \"exports\": {\n \".\": {\n \"require\": \"./dist/index.cjs\",\n \"import\": \"./dist/index.js\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"author\": \"Jerryplusy <jerryplusy@outlook.com>\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"napcat-sdk\": \"^0.16.0\",\n \"consola\": \"^3.4.2\",\n \"dayjs\": \"^1.11.19\",\n \"dedent\": \"^1.7.1\",\n \"filesize\": \"^11.0.13\",\n \"inquirer\": \"^10.0.0\",\n \"jiti\": \"^2.6.1\",\n \"lowdb\": \"^7.0.1\",\n \"mri\": \"^1.2.0\",\n \"node-cron\": \"^4.2.1\",\n \"pretty-ms\": \"^9.3.0\",\n \"string2argv\": \"^1.0.2\",\n \"lodash\": \"^4.17.21\"\n },\n \"devDependencies\": {\n \"@types/lodash\": \"^4.17.0\",\n \"@types/node\": \"^22.0.0\",\n \"tsdown\": \"^0.11.0\",\n \"typescript\": \"^5.8.0\"\n }\n}\n","import { spawn, spawnSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\n\nconst isWindows = process.platform === \"win32\";\n\nconst resolveCache = new Map<string, string | null>();\n\nfunction windowsExtensions(): string[] {\n const raw = process.env.PATHEXT || \".COM;.EXE;.BAT;.CMD\";\n return raw\n .split(\");\")\n .map((ext) => ext.trim())\n .filter(Boolean);\n}\n\n// PATH is a snapshot taken at process start, so a package manager installed\n// mid-run won't be on it. These are the standard install prefixes for bun and\n// for npm's global bin, which is where `npm i -g bun` actually lands.\nfunction searchDirs(): string[] {\n const raw = process.env.PATH || process.env.Path || \"\";\n const dirs = raw\n .split(path.delimiter)\n .map((d) => d.trim())\n .filter(Boolean);\n const home = os.homedir();\n\n const extra = isWindows\n ? [\n path.join(home, \".bun\", \"bin\"),\n path.join(process.env.APPDATA || \"\", \"npm\"),\n path.join(process.env.ProgramFiles || \"\", \"nodejs\"),\n ]\n : [\n path.join(home, \".bun\", \"bin\"),\n \"/usr/local/bin\",\n \"/opt/homebrew/bin\",\n path.join(home, \".npm-global\", \"bin\"),\n ];\n\n return [...dirs, ...extra.filter((dir) => dir && !dir.endsWith(path.sep))];\n}\n\nfunction isExecutableFile(candidate: string): boolean {\n try {\n return fs.statSync(candidate).isFile();\n } catch {\n return false;\n }\n}\n\n/** 在 PATH 及常见安装目录中解析命令的完整路径,结果带缓存 */\nexport function resolveCommand(command: string): string | null {\n if (resolveCache.has(command)) return resolveCache.get(command) ?? null;\n\n let resolved: string | null = null;\n\n if (command.includes(\"/\") || command.includes(path.sep)) {\n resolved = isExecutableFile(command) ? path.resolve(command) : null;\n } else {\n const exts = isWindows ? windowsExtensions() : [\"\"];\n const hasKnownExt =\n isWindows &&\n exts.some((ext) => command.toLowerCase().endsWith(ext.toLowerCase()));\n\n outer: for (const dir of searchDirs()) {\n if (hasKnownExt) {\n const direct = path.join(dir, command);\n if (isExecutableFile(direct)) {\n resolved = direct;\n break;\n }\n continue;\n }\n for (const ext of exts) {\n const candidate = path.join(dir, command + ext);\n if (isExecutableFile(candidate)) {\n resolved = candidate;\n break outer;\n }\n }\n }\n }\n\n resolveCache.set(command, resolved);\n return resolved;\n}\n\nexport function clearCommandCache(): void {\n resolveCache.clear();\n}\n\nfunction needsCmdShell(resolved: string): boolean {\n if (!isWindows) return false;\n const ext = path.extname(resolved).toLowerCase();\n return ext === \".cmd\" || ext === \".bat\";\n}\n\nexport interface SpawnPlan {\n file: string;\n args: string[];\n windowsVerbatimArguments?: boolean;\n shell?: boolean | string;\n}\n\n// Windows can't CreateProcess a .cmd/.bat shim directly (npm installs bun as\n// bun.cmd), so those get routed through cmd.exe via shell: true. Previously\n// we hand-rolled a cmd.exe invocation with windowsVerbatimArguments: true,\n// but that combination misbehaves with spawnSync + stdio:\"inherit\" on\n// Node.js >= 20 (manifests as the spawned process printing \"undefined\" or\n// a spurious EINVAL), so we let Node's shell wrapper do the quoting.\n/** 生成跨平台的 spawn 参数,Windows 下 .cmd/.bat 会改经 cmd.exe 执行 */\nexport function buildSpawnPlan(command: string, args: string[]): SpawnPlan {\n const resolved = resolveCommand(command);\n\n if (!resolved) {\n return { file: command, args };\n }\n\n if (!needsCmdShell(resolved)) {\n return { file: resolved, args };\n }\n\n return {\n file: resolved,\n args,\n shell: true,\n };\n}\n\nexport interface RunCommandResult {\n stdout: string;\n stderr: string;\n code: number;\n}\n\n/** 执行命令并收集 stdout/stderr 与退出码,失败不抛异常 */\nexport function runCommand(\n command: string,\n args: string[],\n options: { cwd?: string; env?: NodeJS.ProcessEnv } = {},\n): Promise<RunCommandResult> {\n const plan = buildSpawnPlan(command, args);\n\n return new Promise((resolve) => {\n const child = spawn(plan.file, plan.args, {\n cwd: options.cwd,\n env: options.env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n shell: plan.shell,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (chunk) => {\n stdout += String(chunk);\n });\n child.stderr?.on(\"data\", (chunk) => {\n stderr += String(chunk);\n });\n\n child.on(\"close\", (code) => {\n resolve({ stdout, stderr, code: code ?? 1 });\n });\n child.on(\"error\", (error) => {\n resolve({\n stdout,\n stderr: `${stderr}\\n${error.message}`.trim(),\n code: 1,\n });\n });\n });\n}\n\n/** 同步执行命令并继承当前终端的输入输出,非零退出码时抛错 */\nexport function runCommandInherit(\n command: string,\n args: string[],\n options: { cwd?: string } = {},\n): void {\n const plan = buildSpawnPlan(command, args);\n const result = spawnSync(plan.file, plan.args, {\n cwd: options.cwd,\n stdio: \"inherit\",\n shell: plan.shell,\n });\n\n if (result.error) throw result.error;\n if (result.status !== 0) {\n throw new Error(`${command} 退出码 ${result.status}`);\n }\n}\n\n/** 判断命令是否可用 */\nexport function commandExists(command: string): boolean {\n return resolveCommand(command) !== null;\n}\n"],"mappings":"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"}
@@ -4,7 +4,7 @@ import * as os$1 from "node:os";
4
4
  import { spawn, spawnSync } from "node:child_process";
5
5
 
6
6
  //#region package.json
7
- var version = "1.0.0";
7
+ var version = "1.0.2";
8
8
 
9
9
  //#endregion
10
10
  //#region src/internal/exec.ts
@@ -74,11 +74,6 @@ function needsCmdShell(resolved) {
74
74
  const ext = path$1.extname(resolved).toLowerCase();
75
75
  return ext === ".cmd" || ext === ".bat";
76
76
  }
77
- function quoteForCmd(arg) {
78
- if (arg === "") return "\"\"";
79
- const escaped = arg.replace(/(\\*)"/g, "$1$1\\\"").replace(/(\\+)$/, "$1$1");
80
- return `"${escaped}"`;
81
- }
82
77
  /** 生成跨平台的 spawn 参数,Windows 下 .cmd/.bat 会改经 cmd.exe 执行 */
83
78
  function buildSpawnPlan(command, args) {
84
79
  const resolved = resolveCommand(command);
@@ -90,17 +85,10 @@ function buildSpawnPlan(command, args) {
90
85
  file: resolved,
91
86
  args
92
87
  };
93
- const comspec = process.env.ComSpec || process.env.COMSPEC || "cmd.exe";
94
- const line = [resolved, ...args].map(quoteForCmd).join(" ");
95
88
  return {
96
- file: comspec,
97
- args: [
98
- "/d",
99
- "/s",
100
- "/c",
101
- `"${line}"`
102
- ],
103
- windowsVerbatimArguments: true
89
+ file: resolved,
90
+ args,
91
+ shell: true
104
92
  };
105
93
  }
106
94
  /** 执行命令并收集 stdout/stderr 与退出码,失败不抛异常 */
@@ -115,7 +103,7 @@ function runCommand(command, args, options = {}) {
115
103
  "pipe",
116
104
  "pipe"
117
105
  ],
118
- windowsVerbatimArguments: plan.windowsVerbatimArguments
106
+ shell: plan.shell
119
107
  });
120
108
  let stdout = "";
121
109
  let stderr = "";
@@ -147,7 +135,7 @@ function runCommandInherit(command, args, options = {}) {
147
135
  const result = spawnSync(plan.file, plan.args, {
148
136
  cwd: options.cwd,
149
137
  stdio: "inherit",
150
- windowsVerbatimArguments: plan.windowsVerbatimArguments
138
+ shell: plan.shell
151
139
  });
152
140
  if (result.error) throw result.error;
153
141
  if (result.status !== 0) throw new Error(`${command} 退出码 ${result.status}`);
@@ -159,4 +147,4 @@ function commandExists(command) {
159
147
 
160
148
  //#endregion
161
149
  export { buildSpawnPlan, clearCommandCache, commandExists, resolveCommand, runCommand, runCommandInherit, version };
162
- //# sourceMappingURL=exec-CUvS9y6X.js.map
150
+ //# sourceMappingURL=exec-DmpZrf3S.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec-DmpZrf3S.js","names":["path","candidate: string","command: string","resolved: string | null","resolved: string","args: string[]","options: { cwd?: string; env?: NodeJS.ProcessEnv }","options: { cwd?: string }"],"sources":["../package.json","../src/internal/exec.ts"],"sourcesContent":["{\n \"name\": \"mioku\",\n \"type\": \"module\",\n \"version\": \"1.0.2\",\n \"packageManager\": \"bun@1.2.0\",\n \"description\": \"Mioku - A plugin-based QQ bot framework\",\n \"keywords\": [\n \"onebot\",\n \"framework\",\n \"bot\",\n \"mioku\"\n ],\n \"bin\": {\n \"mioku\": \"./dist/cli/index.js\"\n },\n \"engines\": {\n \"node\": \">= 22.18.0\"\n },\n \"homepage\": \"https://github.com/mioku-lab/mioku#readme\",\n \"files\": [\n \"dist\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/mioku-lab/mioku/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/mioku-lab/mioku.git\",\n \"directory\": \"packages/mioku\"\n },\n \"scripts\": {\n \"dev\": \"tsdown -w\",\n \"build\": \"tsdown\",\n \"typecheck\": \"tsc --noEmit\"\n },\n \"exports\": {\n \".\": {\n \"require\": \"./dist/index.cjs\",\n \"import\": \"./dist/index.js\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"author\": \"Jerryplusy <jerryplusy@outlook.com>\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"napcat-sdk\": \"^0.16.0\",\n \"consola\": \"^3.4.2\",\n \"dayjs\": \"^1.11.19\",\n \"dedent\": \"^1.7.1\",\n \"filesize\": \"^11.0.13\",\n \"inquirer\": \"^10.0.0\",\n \"jiti\": \"^2.6.1\",\n \"lowdb\": \"^7.0.1\",\n \"mri\": \"^1.2.0\",\n \"node-cron\": \"^4.2.1\",\n \"pretty-ms\": \"^9.3.0\",\n \"string2argv\": \"^1.0.2\",\n \"lodash\": \"^4.17.21\"\n },\n \"devDependencies\": {\n \"@types/lodash\": \"^4.17.0\",\n \"@types/node\": \"^22.0.0\",\n \"tsdown\": \"^0.11.0\",\n \"typescript\": \"^5.8.0\"\n }\n}\n","import { spawn, spawnSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\n\nconst isWindows = process.platform === \"win32\";\n\nconst resolveCache = new Map<string, string | null>();\n\nfunction windowsExtensions(): string[] {\n const raw = process.env.PATHEXT || \".COM;.EXE;.BAT;.CMD\";\n return raw\n .split(\");\")\n .map((ext) => ext.trim())\n .filter(Boolean);\n}\n\n// PATH is a snapshot taken at process start, so a package manager installed\n// mid-run won't be on it. These are the standard install prefixes for bun and\n// for npm's global bin, which is where `npm i -g bun` actually lands.\nfunction searchDirs(): string[] {\n const raw = process.env.PATH || process.env.Path || \"\";\n const dirs = raw\n .split(path.delimiter)\n .map((d) => d.trim())\n .filter(Boolean);\n const home = os.homedir();\n\n const extra = isWindows\n ? [\n path.join(home, \".bun\", \"bin\"),\n path.join(process.env.APPDATA || \"\", \"npm\"),\n path.join(process.env.ProgramFiles || \"\", \"nodejs\"),\n ]\n : [\n path.join(home, \".bun\", \"bin\"),\n \"/usr/local/bin\",\n \"/opt/homebrew/bin\",\n path.join(home, \".npm-global\", \"bin\"),\n ];\n\n return [...dirs, ...extra.filter((dir) => dir && !dir.endsWith(path.sep))];\n}\n\nfunction isExecutableFile(candidate: string): boolean {\n try {\n return fs.statSync(candidate).isFile();\n } catch {\n return false;\n }\n}\n\n/** 在 PATH 及常见安装目录中解析命令的完整路径,结果带缓存 */\nexport function resolveCommand(command: string): string | null {\n if (resolveCache.has(command)) return resolveCache.get(command) ?? null;\n\n let resolved: string | null = null;\n\n if (command.includes(\"/\") || command.includes(path.sep)) {\n resolved = isExecutableFile(command) ? path.resolve(command) : null;\n } else {\n const exts = isWindows ? windowsExtensions() : [\"\"];\n const hasKnownExt =\n isWindows &&\n exts.some((ext) => command.toLowerCase().endsWith(ext.toLowerCase()));\n\n outer: for (const dir of searchDirs()) {\n if (hasKnownExt) {\n const direct = path.join(dir, command);\n if (isExecutableFile(direct)) {\n resolved = direct;\n break;\n }\n continue;\n }\n for (const ext of exts) {\n const candidate = path.join(dir, command + ext);\n if (isExecutableFile(candidate)) {\n resolved = candidate;\n break outer;\n }\n }\n }\n }\n\n resolveCache.set(command, resolved);\n return resolved;\n}\n\nexport function clearCommandCache(): void {\n resolveCache.clear();\n}\n\nfunction needsCmdShell(resolved: string): boolean {\n if (!isWindows) return false;\n const ext = path.extname(resolved).toLowerCase();\n return ext === \".cmd\" || ext === \".bat\";\n}\n\nexport interface SpawnPlan {\n file: string;\n args: string[];\n windowsVerbatimArguments?: boolean;\n shell?: boolean | string;\n}\n\n// Windows can't CreateProcess a .cmd/.bat shim directly (npm installs bun as\n// bun.cmd), so those get routed through cmd.exe via shell: true. Previously\n// we hand-rolled a cmd.exe invocation with windowsVerbatimArguments: true,\n// but that combination misbehaves with spawnSync + stdio:\"inherit\" on\n// Node.js >= 20 (manifests as the spawned process printing \"undefined\" or\n// a spurious EINVAL), so we let Node's shell wrapper do the quoting.\n/** 生成跨平台的 spawn 参数,Windows 下 .cmd/.bat 会改经 cmd.exe 执行 */\nexport function buildSpawnPlan(command: string, args: string[]): SpawnPlan {\n const resolved = resolveCommand(command);\n\n if (!resolved) {\n return { file: command, args };\n }\n\n if (!needsCmdShell(resolved)) {\n return { file: resolved, args };\n }\n\n return {\n file: resolved,\n args,\n shell: true,\n };\n}\n\nexport interface RunCommandResult {\n stdout: string;\n stderr: string;\n code: number;\n}\n\n/** 执行命令并收集 stdout/stderr 与退出码,失败不抛异常 */\nexport function runCommand(\n command: string,\n args: string[],\n options: { cwd?: string; env?: NodeJS.ProcessEnv } = {},\n): Promise<RunCommandResult> {\n const plan = buildSpawnPlan(command, args);\n\n return new Promise((resolve) => {\n const child = spawn(plan.file, plan.args, {\n cwd: options.cwd,\n env: options.env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n shell: plan.shell,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (chunk) => {\n stdout += String(chunk);\n });\n child.stderr?.on(\"data\", (chunk) => {\n stderr += String(chunk);\n });\n\n child.on(\"close\", (code) => {\n resolve({ stdout, stderr, code: code ?? 1 });\n });\n child.on(\"error\", (error) => {\n resolve({\n stdout,\n stderr: `${stderr}\\n${error.message}`.trim(),\n code: 1,\n });\n });\n });\n}\n\n/** 同步执行命令并继承当前终端的输入输出,非零退出码时抛错 */\nexport function runCommandInherit(\n command: string,\n args: string[],\n options: { cwd?: string } = {},\n): void {\n const plan = buildSpawnPlan(command, args);\n const result = spawnSync(plan.file, plan.args, {\n cwd: options.cwd,\n stdio: \"inherit\",\n shell: plan.shell,\n });\n\n if (result.error) throw result.error;\n if (result.status !== 0) {\n throw new Error(`${command} 退出码 ${result.status}`);\n }\n}\n\n/** 判断命令是否可用 */\nexport function commandExists(command: string): boolean {\n return resolveCommand(command) !== null;\n}\n"],"mappings":";;;;;;cAGa;;;;ACEb,MAAM,YAAY,QAAQ,aAAa;AAEvC,MAAM,eAAe,IAAI;AAEzB,SAAS,oBAA8B;CACrC,MAAM,MAAM,QAAQ,IAAI,WAAW;AACnC,QAAO,IACJ,MAAM,KAAK,CACX,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,CACxB,OAAO,QAAQ;AACnB;AAKD,SAAS,aAAuB;CAC9B,MAAM,MAAM,QAAQ,IAAI,QAAQ,QAAQ,IAAI,QAAQ;CACpD,MAAM,OAAO,IACV,MAAMA,OAAK,UAAU,CACrB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CACpB,OAAO,QAAQ;CAClB,MAAM,OAAO,KAAG,SAAS;CAEzB,MAAM,QAAQ,YACV;EACE,OAAK,KAAK,MAAM,QAAQ,MAAM;EAC9B,OAAK,KAAK,QAAQ,IAAI,WAAW,IAAI,MAAM;EAC3C,OAAK,KAAK,QAAQ,IAAI,gBAAgB,IAAI,SAAS;CACpD,IACD;EACE,OAAK,KAAK,MAAM,QAAQ,MAAM;EAC9B;EACA;EACA,OAAK,KAAK,MAAM,eAAe,MAAM;CACtC;AAEL,QAAO,CAAC,GAAG,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,QAAQ,IAAI,SAASA,OAAK,IAAI,CAAC,AAAC;AAC3E;AAED,SAAS,iBAAiBC,WAA4B;AACpD,KAAI;AACF,SAAO,KAAG,SAAS,UAAU,CAAC,QAAQ;CACvC,QAAO;AACN,SAAO;CACR;AACF;;AAGD,SAAgB,eAAeC,SAAgC;AAC7D,KAAI,aAAa,IAAI,QAAQ,CAAE,QAAO,aAAa,IAAI,QAAQ,IAAI;CAEnE,IAAIC,WAA0B;AAE9B,KAAI,QAAQ,SAAS,IAAI,IAAI,QAAQ,SAASH,OAAK,IAAI,CACrD,YAAW,iBAAiB,QAAQ,GAAG,OAAK,QAAQ,QAAQ,GAAG;MAC1D;EACL,MAAM,OAAO,YAAY,mBAAmB,GAAG,CAAC,EAAG;EACnD,MAAM,cACJ,aACA,KAAK,KAAK,CAAC,QAAQ,QAAQ,aAAa,CAAC,SAAS,IAAI,aAAa,CAAC,CAAC;AAEvE,QAAO,MAAK,MAAM,OAAO,YAAY,EAAE;AACrC,OAAI,aAAa;IACf,MAAM,SAAS,OAAK,KAAK,KAAK,QAAQ;AACtC,QAAI,iBAAiB,OAAO,EAAE;AAC5B,gBAAW;AACX;IACD;AACD;GACD;AACD,QAAK,MAAM,OAAO,MAAM;IACtB,MAAM,YAAY,OAAK,KAAK,KAAK,UAAU,IAAI;AAC/C,QAAI,iBAAiB,UAAU,EAAE;AAC/B,gBAAW;AACX,WAAM;IACP;GACF;EACF;CACF;AAED,cAAa,IAAI,SAAS,SAAS;AACnC,QAAO;AACR;AAED,SAAgB,oBAA0B;AACxC,cAAa,OAAO;AACrB;AAED,SAAS,cAAcI,UAA2B;AAChD,MAAK,UAAW,QAAO;CACvB,MAAM,MAAM,OAAK,QAAQ,SAAS,CAAC,aAAa;AAChD,QAAO,QAAQ,UAAU,QAAQ;AAClC;;AAgBD,SAAgB,eAAeF,SAAiBG,MAA2B;CACzE,MAAM,WAAW,eAAe,QAAQ;AAExC,MAAK,SACH,QAAO;EAAE,MAAM;EAAS;CAAM;AAGhC,MAAK,cAAc,SAAS,CAC1B,QAAO;EAAE,MAAM;EAAU;CAAM;AAGjC,QAAO;EACL,MAAM;EACN;EACA,OAAO;CACR;AACF;;AASD,SAAgB,WACdH,SACAG,MACAC,UAAqD,CAAE,GAC5B;CAC3B,MAAM,OAAO,eAAe,SAAS,KAAK;AAE1C,QAAO,IAAI,QAAQ,CAAC,YAAY;EAC9B,MAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,MAAM;GACxC,KAAK,QAAQ;GACb,KAAK,QAAQ;GACb,OAAO;IAAC;IAAU;IAAQ;GAAO;GACjC,OAAO,KAAK;EACb,EAAC;EAEF,IAAI,SAAS;EACb,IAAI,SAAS;AAEb,QAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU;AAClC,aAAU,OAAO,MAAM;EACxB,EAAC;AACF,QAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU;AAClC,aAAU,OAAO,MAAM;EACxB,EAAC;AAEF,QAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,WAAQ;IAAE;IAAQ;IAAQ,MAAM,QAAQ;GAAG,EAAC;EAC7C,EAAC;AACF,QAAM,GAAG,SAAS,CAAC,UAAU;AAC3B,WAAQ;IACN;IACA,QAAQ,CAAC,EAAE,OAAO,IAAI,MAAM,QAAQ,EAAE,MAAM;IAC5C,MAAM;GACP,EAAC;EACH,EAAC;CACH;AACF;;AAGD,SAAgB,kBACdJ,SACAG,MACAE,UAA4B,CAAE,GACxB;CACN,MAAM,OAAO,eAAe,SAAS,KAAK;CAC1C,MAAM,SAAS,UAAU,KAAK,MAAM,KAAK,MAAM;EAC7C,KAAK,QAAQ;EACb,OAAO;EACP,OAAO,KAAK;CACb,EAAC;AAEF,KAAI,OAAO,MAAO,OAAM,OAAO;AAC/B,KAAI,OAAO,WAAW,EACpB,OAAM,IAAI,OAAO,EAAE,QAAQ,OAAO,OAAO,OAAO;AAEnD;;AAGD,SAAgB,cAAcL,SAA0B;AACtD,QAAO,eAAe,QAAQ,KAAK;AACpC"}