mioku 0.8.16 → 0.8.18
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.
- package/dist/cli.cjs +18 -91
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +18 -91
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
package/dist/cli.cjs
CHANGED
|
@@ -4,13 +4,11 @@ const node_fs = require_chunk.__toESM(require("node:fs"));
|
|
|
4
4
|
const node_child_process = require_chunk.__toESM(require("node:child_process"));
|
|
5
5
|
const mri = require_chunk.__toESM(require("mri"));
|
|
6
6
|
const node_path = require_chunk.__toESM(require("node:path"));
|
|
7
|
-
const node_os = require_chunk.__toESM(require("node:os"));
|
|
8
7
|
const dedent = require_chunk.__toESM(require("dedent"));
|
|
9
8
|
const consola = require_chunk.__toESM(require("consola"));
|
|
10
|
-
const adm_zip = require_chunk.__toESM(require("adm-zip"));
|
|
11
9
|
|
|
12
10
|
//#region package.json
|
|
13
|
-
var version = "0.8.
|
|
11
|
+
var version = "0.8.18";
|
|
14
12
|
|
|
15
13
|
//#endregion
|
|
16
14
|
//#region src/cli.ts
|
|
@@ -114,87 +112,6 @@ function detectType(name) {
|
|
|
114
112
|
if (name.startsWith(SERVICE_PREFIX)) return "service";
|
|
115
113
|
return "unknown";
|
|
116
114
|
}
|
|
117
|
-
async function installWebUIDist(projectPath) {
|
|
118
|
-
consola.default.info("正在安装 WebUI...");
|
|
119
|
-
try {
|
|
120
|
-
run("bun", ["add", "mioku-service-webui"], { cwd: projectPath });
|
|
121
|
-
consola.default.success("mioku-service-webui 安装成功");
|
|
122
|
-
} catch (err) {
|
|
123
|
-
consola.default.error("安装 mioku-service-webui 失败");
|
|
124
|
-
console.error(err);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
const nodeModulesWebui = node_path.default.join(projectPath, "node_modules", "mioku-service-webui");
|
|
128
|
-
const targetDist = node_path.default.join(nodeModulesWebui, "dist");
|
|
129
|
-
consola.default.info(`WebUI dist 目录: ${targetDist}`);
|
|
130
|
-
try {
|
|
131
|
-
consola.default.info("正在获取 WebUI Release 信息...");
|
|
132
|
-
const releaseRes = await fetch("https://api.github.com/repos/mioku-lab/mioku-webui/releases/latest", { headers: {
|
|
133
|
-
Accept: "application/vnd.github+json",
|
|
134
|
-
"User-Agent": "mioku-cli"
|
|
135
|
-
} });
|
|
136
|
-
if (!releaseRes.ok) {
|
|
137
|
-
consola.default.error(`GitHub API 请求失败: ${releaseRes.status}`);
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
const release = await releaseRes.json();
|
|
141
|
-
consola.default.success(`获取 Release 成功: ${release.tag_name}`);
|
|
142
|
-
const distAsset = release.assets.find((a) => a.name.includes("dist") || a.name.endsWith(".zip"));
|
|
143
|
-
if (!distAsset) {
|
|
144
|
-
consola.default.error("未找到 dist zip 资源");
|
|
145
|
-
console.log("可用资源:", release.assets.map((a) => a.name));
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
consola.default.info(`下载资源: ${distAsset.name}`);
|
|
149
|
-
const zipRes = await fetch(distAsset.browser_download_url, { headers: { "User-Agent": "mioku-cli" } });
|
|
150
|
-
if (!zipRes.ok) {
|
|
151
|
-
consola.default.error(`下载失败: ${zipRes.status}`);
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
const buffer = Buffer.from(await zipRes.arrayBuffer());
|
|
155
|
-
const tmpZip = node_path.default.join(node_os.default.tmpdir(), `mioku-webui-${Date.now()}.zip`);
|
|
156
|
-
node_fs.default.writeFileSync(tmpZip, buffer);
|
|
157
|
-
consola.default.success(`ZIP 下载完成: ${tmpZip}`);
|
|
158
|
-
const tmpUnpack = node_path.default.join(node_os.default.tmpdir(), `mioku-webui-unpack-${Date.now()}`);
|
|
159
|
-
node_fs.default.mkdirSync(tmpUnpack, { recursive: true });
|
|
160
|
-
consola.default.info("正在解压 WebUI...");
|
|
161
|
-
const zip = new adm_zip.default(tmpZip);
|
|
162
|
-
zip.extractAllTo(tmpUnpack, true);
|
|
163
|
-
consola.default.success("解压完成");
|
|
164
|
-
const sourceDir = findDistSourceDir(tmpUnpack);
|
|
165
|
-
if (!sourceDir) {
|
|
166
|
-
consola.default.error("未找到 dist/index.html");
|
|
167
|
-
consola.default.info(`解压目录: ${tmpUnpack}`);
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
consola.default.success(`找到 dist: ${sourceDir}`);
|
|
171
|
-
node_fs.default.mkdirSync(targetDist, { recursive: true });
|
|
172
|
-
node_fs.default.cpSync(sourceDir, targetDist, {
|
|
173
|
-
recursive: true,
|
|
174
|
-
force: true
|
|
175
|
-
});
|
|
176
|
-
consola.default.success("WebUI dist 安装成功");
|
|
177
|
-
await rmrf(tmpZip);
|
|
178
|
-
await rmrf(tmpUnpack);
|
|
179
|
-
consola.default.success("临时文件清理完成");
|
|
180
|
-
} catch (err) {
|
|
181
|
-
consola.default.error("安装 WebUI dist 失败");
|
|
182
|
-
console.error(err);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
function findDistSourceDir(unpackDir) {
|
|
186
|
-
const directCandidates = [node_path.default.join(unpackDir, "dist"), unpackDir];
|
|
187
|
-
for (const candidate of directCandidates) if (node_fs.default.existsSync(node_path.default.join(candidate, "index.html"))) return candidate;
|
|
188
|
-
const children = node_fs.default.readdirSync(unpackDir);
|
|
189
|
-
for (const child of children) {
|
|
190
|
-
const childPath = node_path.default.join(unpackDir, child);
|
|
191
|
-
if (node_fs.default.statSync(childPath).isDirectory()) {
|
|
192
|
-
const subCandidate = node_path.default.join(childPath, "dist");
|
|
193
|
-
if (node_fs.default.existsSync(node_path.default.join(subCandidate, "index.html"))) return subCandidate;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return null;
|
|
197
|
-
}
|
|
198
115
|
function execAdd(packages, cwd) {
|
|
199
116
|
const [cmd, args$1] = getAddCommand(packages);
|
|
200
117
|
console.log(`执行: ${cmd} ${args$1.join(" ")}`);
|
|
@@ -345,7 +262,17 @@ async function getInstalledPackages(cwd) {
|
|
|
345
262
|
process.exitCode = 0;
|
|
346
263
|
return;
|
|
347
264
|
}
|
|
348
|
-
|
|
265
|
+
const updates = await checkUpdates(packages$1, cwd);
|
|
266
|
+
if (updates.length === 0) {
|
|
267
|
+
consola.default.info("所有 mioku 依赖已是最新版本");
|
|
268
|
+
process.exitCode = 0;
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
console.log("\n可用更新:");
|
|
272
|
+
updates.forEach((u) => consola.default.warn(` ${u}`));
|
|
273
|
+
const confirm$1 = await confirm$1(`确认更新以上 ${updates.length} 个包?`);
|
|
274
|
+
if (!confirm$1) gracefullyExit();
|
|
275
|
+
await Promise.all(packages$1.map((pkg) => updatePackage(pkg, cwd)));
|
|
349
276
|
process.exitCode = 0;
|
|
350
277
|
return;
|
|
351
278
|
}
|
|
@@ -420,7 +347,6 @@ async function getInstalledPackages(cwd) {
|
|
|
420
347
|
required: true
|
|
421
348
|
}));
|
|
422
349
|
const token = await input("请输入 NapCat WS Token(如无则留空)", { placeholder: "请输入" });
|
|
423
|
-
const installWebui = await confirm("是否安装 WebUI?(建议安装)", { initial: true });
|
|
424
350
|
ensurePackageManager();
|
|
425
351
|
const pkgJson = (0, dedent.default)(`
|
|
426
352
|
{
|
|
@@ -479,15 +405,15 @@ async function getInstalledPackages(cwd) {
|
|
|
479
405
|
config: {},
|
|
480
406
|
data: {}
|
|
481
407
|
};
|
|
482
|
-
await
|
|
483
|
-
|
|
484
|
-
console.log("\n
|
|
408
|
+
const installWebui = await confirm("是否安装 WebUI 管理面板?(建议安装)", { initial: true });
|
|
409
|
+
await createNewProject(name, fileTree, installWebui);
|
|
410
|
+
console.log("\n若需启动机器人,请运行:");
|
|
485
411
|
console.log(" cd", name);
|
|
486
412
|
console.log(" bun run start");
|
|
487
413
|
}
|
|
488
414
|
}
|
|
489
415
|
})();
|
|
490
|
-
async function createNewProject(name, fileTree) {
|
|
416
|
+
async function createNewProject(name, fileTree, installWebui = false) {
|
|
491
417
|
const projectName = name;
|
|
492
418
|
const projectPath = withRoot(`./${projectName}`);
|
|
493
419
|
if (node_fs.default.existsSync(projectPath)) {
|
|
@@ -504,7 +430,8 @@ async function createNewProject(name, fileTree) {
|
|
|
504
430
|
node_fs.default.mkdirSync(projectPath, { recursive: true });
|
|
505
431
|
makeFileTree(fileTree, projectPath);
|
|
506
432
|
console.log(`项目 ${projectName} 创建成功!`);
|
|
507
|
-
const
|
|
433
|
+
const packages = installWebui ? DEFAULT_PACKAGES : DEFAULT_PACKAGES.filter((p) => p !== "mioku-service-webui");
|
|
434
|
+
const [cmd, args$1] = getAddCommand(packages);
|
|
508
435
|
console.log(`正在安装 Mioku 依赖: ${cmd} ${args$1.join(" ")}`);
|
|
509
436
|
run(cmd, args$1, { cwd: projectPath });
|
|
510
437
|
}
|
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.cjs","names":["cmd: string","args: string[]","options: Parameters<typeof execFileSync>[2]","args","dir: string","err: any","packages: string[]","input: string","input","name: string","projectPath: string","a: { name: string; browser_download_url: string }","a: { name: string }","AdmZip","unpackDir: string","cwd?: string","updates: string[]","cwd: string","packages","cli","fileTree: Record<string, any>","_path: string","message: string","options?: OmitTypeWithRequired<{ initial?: boolean }>","options?: OmitTypeWithRequired<{ default?: string; placeholder?: string }>","fileTree: Record<\n string,\n string | Record<string, string | Record<string, string>>\n >","base: string"],"sources":["../package.json","../src/cli.ts"],"sourcesContent":["{\n \"name\": \"mioku\",\n \"type\": \"module\",\n \"version\": \"0.8.15\",\n \"packageManager\": \"bun@1.2.0\",\n \"description\": \"Mioku - Plugin framework extended from mioki for NapCat OneBot v11\",\n \"keywords\": [\n \"onebot\",\n \"framework\",\n \"bot\",\n \"mioki\",\n \"mioku\"\n ],\n \"bin\": {\n \"mioku\": \"./dist/cli.js\"\n },\n \"engines\": {\n \"node\": \">= 22.18.0\"\n },\n \"homepage\": \"https://github.com/jerryplusy/mioku#readme\",\n \"files\": [\n \"dist\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/jerryplusy/mioku/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/jerryplusy/mioku.git\",\n \"directory\": \"src/packages/mioku\"\n },\n \"scripts\": {\n \"dev\": \"tsdown -w\",\n \"build\": \"tsdown\"\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 \"mioki\": \"^0.16.0\",\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 \"openai\": \"^4.0.0\",\n \"puppeteer\": \"^23.10.0\",\n \"pretty-ms\": \"^9.3.0\",\n \"string2argv\": \"^1.0.2\",\n \"systeminformation\": \"^5.30.7\",\n \"lodash\": \"^4.17.21\",\n \"adm-zip\": \"^0.5.16\"\n },\n \"devDependencies\": {\n \"@types/lodash\": \"^4.17.0\",\n \"@types/node\": \"^22.0.0\",\n \"@types/puppeteer\": \"^7.0.4\",\n \"tsdown\": \"^0.11.0\",\n \"typescript\": \"^5.8.0\"\n }\n}\n","#!/usr/bin/env node\n\nimport fs from \"node:fs\";\nimport { execFileSync } from \"node:child_process\";\nimport mri from \"mri\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport dedent from \"dedent\";\nimport consola from \"consola\";\nimport { version } from \"../package.json\";\nimport { readFileSync } from \"node:fs\";\nimport AdmZip from \"adm-zip\";\n\nconst DEFAULT_PACKAGES = [\n \"mioku\",\n \"mioku-plugin-boot\",\n \"mioku-plugin-help\",\n \"mioku-plugin-chat\",\n \"mioku-service-config\",\n \"mioku-service-ai\",\n \"mioku-service-screenshot\",\n \"mioku-service-help\",\n];\n\nconst PLUGIN_PREFIX = \"mioku-plugin-\";\nconst SERVICE_PREFIX = \"mioku-service-\";\n\nconst args = process.argv.slice(2);\n\nfunction run(\n cmd: string,\n args: string[] = [],\n options: Parameters<typeof execFileSync>[2] = {},\n) {\n return execFileSync(cmd, args, {\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n ...options,\n });\n}\n\nasync 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\ninterface CliOptions {\n name?: string;\n protocol?: string;\n host?: string;\n port?: number;\n token?: string;\n prefix?: string;\n owners?: string;\n admins?: string;\n help?: boolean;\n version?: boolean;\n \"use-npm-mirror\"?: boolean;\n}\n\nfunction hasCommand(cmd: string): boolean {\n try {\n execFileSync(cmd, [\"--version\"], {\n stdio: \"ignore\",\n shell: process.platform === \"win32\",\n });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction findNpmPath(): string | null {\n if (process.platform !== \"win32\") {\n return \"npm\";\n }\n\n const candidates = [\n \"npm.cmd\",\n \"npm.exe\",\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 for (const candidate of candidates) {\n try {\n execFileSync(candidate, [\"--version\"], {\n stdio: \"ignore\",\n shell: true,\n });\n return candidate;\n } catch {}\n }\n\n try {\n const result = execFileSync(\"where\", [\"npm\"], {\n encoding: \"utf-8\",\n shell: true,\n });\n\n const lines = result\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean);\n\n const cmdPath = lines.find((line) => line.endsWith(\".cmd\"));\n return cmdPath || lines[0] || null;\n } catch {\n return null;\n }\n}\n\nfunction ensurePackageManager() {\n if (hasCommand(\"bun\")) return;\n\n console.log(\"安装 bun...\");\n\n const npmPath = findNpmPath();\n if (!npmPath) {\n consola.error(\"未找到 npm,请确保 Node.js 已安装并包含 npm\");\n process.exit(1);\n }\n\n run(npmPath, [\"install\", \"-g\", \"bun\"]);\n}\n\nfunction getAddCommand(packages: string[]): [string, string[]] {\n return [\"bun\", [\"add\", ...packages]];\n}\n\nfunction normalizePackageName(input: string): string {\n if (input.startsWith(PLUGIN_PREFIX) || input.startsWith(SERVICE_PREFIX)) {\n return input;\n }\n if (input.startsWith(\"mioku-\")) {\n // 已经是完整名称,如 mioku-plugin-xxx\n return input;\n }\n // 默认当作 plugin 处理\n return `${PLUGIN_PREFIX}${input}`;\n}\n\nfunction 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\nasync function installWebUIDist(projectPath: string) {\n consola.info(\"正在安装 WebUI...\");\n\n try {\n run(\"bun\", [\"add\", \"mioku-service-webui\"], {\n cwd: projectPath,\n });\n\n consola.success(\"mioku-service-webui 安装成功\");\n } catch (err) {\n consola.error(\"安装 mioku-service-webui 失败\");\n console.error(err);\n return;\n }\n\n const nodeModulesWebui = path.join(\n projectPath,\n \"node_modules\",\n \"mioku-service-webui\",\n );\n\n const targetDist = path.join(nodeModulesWebui, \"dist\");\n\n consola.info(`WebUI dist 目录: ${targetDist}`);\n\n try {\n consola.info(\"正在获取 WebUI Release 信息...\");\n\n const releaseRes = await fetch(\n \"https://api.github.com/repos/mioku-lab/mioku-webui/releases/latest\",\n {\n headers: {\n Accept: \"application/vnd.github+json\",\n \"User-Agent\": \"mioku-cli\",\n },\n },\n );\n\n if (!releaseRes.ok) {\n consola.error(`GitHub API 请求失败: ${releaseRes.status}`);\n return;\n }\n\n const release = (await releaseRes.json()) as {\n tag_name: string;\n assets: Array<{ name: string; browser_download_url: string }>;\n };\n\n consola.success(`获取 Release 成功: ${release.tag_name}`);\n const distAsset = release.assets.find(\n (a: { name: string; browser_download_url: string }) =>\n a.name.includes(\"dist\") || a.name.endsWith(\".zip\"),\n );\n\n if (!distAsset) {\n consola.error(\"未找到 dist zip 资源\");\n console.log(\n \"可用资源:\",\n release.assets.map((a: { name: string }) => a.name),\n );\n return;\n }\n\n consola.info(`下载资源: ${distAsset.name}`);\n\n const zipRes = await fetch(distAsset.browser_download_url, {\n headers: {\n \"User-Agent\": \"mioku-cli\",\n },\n });\n\n if (!zipRes.ok) {\n consola.error(`下载失败: ${zipRes.status}`);\n return;\n }\n\n const buffer = Buffer.from(await zipRes.arrayBuffer());\n\n const tmpZip = path.join(os.tmpdir(), `mioku-webui-${Date.now()}.zip`);\n\n fs.writeFileSync(tmpZip, buffer);\n\n consola.success(`ZIP 下载完成: ${tmpZip}`);\n\n const tmpUnpack = path.join(\n os.tmpdir(),\n `mioku-webui-unpack-${Date.now()}`,\n );\n\n fs.mkdirSync(tmpUnpack, {\n recursive: true,\n });\n\n consola.info(\"正在解压 WebUI...\");\n\n const zip = new AdmZip(tmpZip);\n zip.extractAllTo(tmpUnpack, true);\n\n consola.success(\"解压完成\");\n\n const sourceDir = findDistSourceDir(tmpUnpack);\n\n if (!sourceDir) {\n consola.error(\"未找到 dist/index.html\");\n consola.info(`解压目录: ${tmpUnpack}`);\n return;\n }\n\n consola.success(`找到 dist: ${sourceDir}`);\n\n fs.mkdirSync(targetDist, {\n recursive: true,\n });\n\n fs.cpSync(sourceDir, targetDist, {\n recursive: true,\n force: true,\n });\n\n consola.success(\"WebUI dist 安装成功\");\n\n await rmrf(tmpZip);\n await rmrf(tmpUnpack);\n\n consola.success(\"临时文件清理完成\");\n } catch (err) {\n consola.error(\"安装 WebUI dist 失败\");\n console.error(err);\n }\n}\n\nfunction findDistSourceDir(unpackDir: string): string | null {\n const directCandidates = [path.join(unpackDir, \"dist\"), unpackDir];\n for (const candidate of directCandidates) {\n if (fs.existsSync(path.join(candidate, \"index.html\"))) {\n return candidate;\n }\n }\n const children = fs.readdirSync(unpackDir);\n for (const child of children) {\n const childPath = path.join(unpackDir, child);\n if (fs.statSync(childPath).isDirectory()) {\n const subCandidate = path.join(childPath, \"dist\");\n if (fs.existsSync(path.join(subCandidate, \"index.html\"))) {\n return subCandidate;\n }\n }\n }\n return null;\n}\n\nfunction execAdd(packages: string[], cwd?: string) {\n const [cmd, args] = getAddCommand(packages);\n\n console.log(`执行: ${cmd} ${args.join(\" \")}`);\n\n run(cmd, args, {\n cwd,\n });\n}\n\nasync function installPackage(name: string, cwd?: string) {\n const normalized = normalizePackageName(name);\n const type = detectType(normalized);\n if (type === \"unknown\") {\n consola.error(`无法识别的包类型: ${name}`);\n return false;\n }\n try {\n execAdd([normalized], cwd);\n consola.success(`已安装 ${normalized}`);\n return true;\n } catch {\n consola.error(`安装失败: ${normalized}`);\n return false;\n }\n}\n\nasync function updatePackage(name: string, cwd?: string) {\n try {\n console.log(`执行: bun update ${name}`);\n\n run(\"bun\", [\"update\", name], {\n cwd,\n });\n consola.success(`已更新 ${name}`);\n return true;\n } catch {\n consola.error(`更新失败: ${name}`);\n return false;\n }\n}\n\nasync function checkUpdates(packages: string[], cwd?: string) {\n try {\n const output = execFileSync(\"bun\", [\"pm\", \"outdated\", \"--json\"], {\n cwd,\n encoding: \"utf-8\",\n stdio: \"pipe\",\n shell: process.platform === \"win32\",\n });\n if (!output.trim()) {\n consola.info(\"所有依赖已是最新版本\");\n return [];\n }\n const outdated = JSON.parse(output);\n const updates: string[] = [];\n for (const pkg of packages) {\n if (outdated[pkg]) {\n updates.push(\n `${pkg}: ${outdated[pkg].current} → ${outdated[pkg].latest}`,\n );\n }\n }\n return updates;\n } catch {\n return [];\n }\n}\n\nasync function getInstalledPackages(cwd: string): Promise<string[]> {\n try {\n const pkgPath = path.join(cwd, \"package.json\");\n const content = readFileSync(pkgPath, \"utf-8\");\n const pkg = JSON.parse(content);\n const deps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n return Object.keys(deps).filter((k) => k.startsWith(\"mioku-\"));\n } catch {\n return [];\n }\n}\n\n(async () => {\n const cli = mri<CliOptions>(args, {\n alias: {\n v: \"version\",\n h: \"help\",\n },\n });\n\n const helpInfo = 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 const [cmd, ...cmdArgs] = args;\n\n switch (cmd) {\n case \"install\": {\n ensurePackageManager();\n const cwd = process.cwd();\n const type = cmdArgs[0];\n const name = cmdArgs[1];\n\n if (!type || !name) {\n consola.error(\n \"请指定类型和名称: mioku install plugin <名称> 或 mioku install service <名称>\",\n );\n console.log(helpInfo);\n process.exitCode = 1;\n return;\n }\n\n if (type !== \"plugin\" && type !== \"service\") {\n consola.error(`无效的类型 \"${type}\",请使用 plugin 或 service`);\n console.log(helpInfo);\n process.exitCode = 1;\n return;\n }\n\n const prefix = type === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const normalized = `${prefix}${name}`;\n const success = await installPackage(normalized, cwd);\n process.exitCode = success ? 0 : 1;\n return;\n }\n\n case \"update\": {\n ensurePackageManager();\n const cwd = process.cwd();\n\n if (!cmdArgs.length || cmdArgs[0] === \"check\") {\n // 检查更新\n const packages = await getInstalledPackages(cwd);\n const updates = await checkUpdates(packages, cwd);\n if (updates.length === 0) {\n consola.info(\"所有 mioku 依赖已是最新版本\");\n } else {\n console.log(\"\\n可用更新:\");\n updates.forEach((u) => consola.warn(` ${u}`));\n console.log(\"\\n运行 npx mioku update all 更新所有包\");\n }\n process.exitCode = 0;\n return;\n }\n\n const target = cmdArgs[0];\n\n if (target === \"all\") {\n // 更新所有 mioku- 包\n const packages = await getInstalledPackages(cwd);\n if (packages.length === 0) {\n consola.info(\"未找到 mioku 相关依赖\");\n process.exitCode = 0;\n return;\n }\n for (const pkg of packages) {\n await updatePackage(pkg, cwd);\n }\n process.exitCode = 0;\n return;\n }\n\n if (target === \"self\") {\n await updatePackage(\"mioku\", cwd);\n process.exitCode = 0;\n return;\n }\n\n if (target === \"plugin\" || target === \"service\") {\n // update plugin/service [name]\n const name = cmdArgs[1];\n if (!name) {\n // 更新所有指定类型的包\n const packages = await getInstalledPackages(cwd);\n const prefix = target === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const filtered = packages.filter((p) => p.startsWith(prefix));\n if (filtered.length === 0) {\n consola.info(`未找到 ${prefix}* 相关依赖`);\n process.exitCode = 0;\n return;\n }\n for (const pkg of filtered) {\n await updatePackage(pkg, cwd);\n }\n } else {\n const prefix = target === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const normalized = name.startsWith(prefix)\n ? name\n : `${prefix}${name}`;\n await updatePackage(normalized, cwd);\n }\n process.exitCode = 0;\n return;\n }\n\n // update xxx - 更新指定包,自动识别前缀\n const packages = await getInstalledPackages(cwd);\n if (packages.includes(target)) {\n await updatePackage(target, cwd);\n } else {\n const normalized = normalizePackageName(target);\n await updatePackage(normalized, cwd);\n }\n process.exitCode = 0;\n return;\n }\n\n default: {\n // 原始交互式项目创建\n const cli = mri<CliOptions>(args, {\n alias: {\n v: \"version\",\n h: \"help\",\n },\n });\n\n switch (true) {\n case cli.version:\n console.log(`v${version}`);\n process.exitCode = 0;\n return;\n // fall through\n\n case cli.help:\n console.log(helpInfo);\n process.exitCode = 0;\n return;\n // fall through\n\n default:\n break;\n }\n\n const name = await input(\"请输入项目名称\", {\n default: \"mioku-bot\",\n placeholder: \"mioku-bot\",\n required: true,\n });\n\n const owners = await input(\n \"请输入主人 QQ (最高权限,英文逗号分隔,必填)\",\n {\n placeholder: \"请输入\",\n default: \"\",\n required: true,\n },\n );\n\n const host = await input(\"请输入 NapCat WS 主机\", {\n default: \"localhost\",\n placeholder: \"localhost\",\n required: true,\n });\n\n const port = parseInt(\n await input(\"请输入 NapCat WS 端口\", {\n default: \"3001\",\n placeholder: \"3001\",\n required: true,\n }),\n );\n\n const token = await input(\"请输入 NapCat WS Token(如无则留空)\", {\n placeholder: \"请输入\",\n });\n\n const installWebui = await confirm(\"是否安装 WebUI?(建议安装)\", {\n initial: true,\n });\n\n ensurePackageManager();\n\n const pkgJson = dedent(`\n {\n \"name\": \"${name}\",\n \"private\": true,\n \"type\": \"module\",\n \"dependencies\": {},\n \"mioki\": {\n \"prefix\": \"#\",\n \"owners\": [${String(owners)\n .split(\",\")\n .map((o) => o.trim())\n .join(\", \")}],\n \"admins\": [],\n \"plugins\": [\"boot\", \"help\", \"chat\", \"demo\"],\n \"log_level\": \"info\",\n \"online_push\": false,\n \"error_push\": false,\n \"napcat\": [\n {\n \"protocol\": \"ws\",\n \"port\": ${port},\n \"host\": \"${host}\",\n \"token\": \"${token}\"\n }\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, any> = {\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 await createNewProject(name, fileTree);\n\n if (installWebui) {\n await installWebUIDist(path.join(process.cwd(), name));\n }\n\n console.log(\"\\n接下来的操作:\");\n console.log(\" cd\", name);\n console.log(\" bun run start\");\n }\n }\n})();\n\nasync function createNewProject(name: string, fileTree: Record<string, any>) {\n const projectName = name;\n const projectPath = withRoot(`./${projectName}`);\n\n if (fs.existsSync(projectPath)) {\n const overwrite = await confirm(`项目 ${projectName} 已存在,是否覆盖?`);\n\n if (!overwrite) {\n gracefullyExit();\n }\n\n if (projectPath === process.cwd()) {\n if (fs.readdirSync(projectPath).length !== 0) {\n const confirmOver = await confirm(\n \"项目路径与当前路径相同,将删除当前目录下所有内容再创建,是否继续?\",\n );\n if (!confirmOver) {\n gracefullyExit();\n }\n }\n }\n\n await rmrf(projectPath);\n }\n\n fs.mkdirSync(projectPath, { recursive: true });\n\n makeFileTree(fileTree, projectPath);\n\n console.log(`项目 ${projectName} 创建成功!`);\n\n const [cmd, args] = getAddCommand(DEFAULT_PACKAGES);\n console.log(`正在安装 Mioku 依赖: ${cmd} ${args.join(\" \")}`);\n run(cmd, args, {\n cwd: projectPath,\n });\n}\n\nfunction gracefullyExit() {\n console.log(\"Bye!\");\n process.exit(0);\n}\n\nfunction withRoot(_path: string) {\n return path.resolve(process.cwd(), _path);\n}\n\ntype OmitTypeWithRequired<T> = Omit<T, \"type\" | \"required\"> & {\n required?: boolean;\n};\n\nasync function confirm(\n message: string,\n options?: OmitTypeWithRequired<{ initial?: boolean }>,\n) {\n return consola.prompt(message, {\n type: \"confirm\",\n cancel: \"reject\",\n ...options,\n });\n}\n\nasync function input(\n message: string,\n options?: OmitTypeWithRequired<{ default?: string; placeholder?: string }>,\n) {\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\nfunction makeFileTree(\n fileTree: Record<\n string,\n string | Record<string, string | Record<string, string>>\n >,\n base: string,\n) {\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)) {\n fs.mkdirSync(subPath, { recursive: true });\n }\n for (const [subName, subContent] of Object.entries(content)) {\n if (typeof subContent === \"object\") {\n makeFileTree(\n subContent as typeof fileTree,\n path.join(subPath, subName),\n );\n } else {\n fs.writeFileSync(`${subPath}/${subName}`, subContent);\n }\n }\n } else {\n const filePath = `${base}/${name}`;\n const dirname = path.dirname(filePath);\n if (!fs.existsSync(dirname)) {\n fs.mkdirSync(dirname, { recursive: true });\n }\n fs.writeFileSync(filePath, content);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;cAGa;;;;ACUb,MAAM,mBAAmB;CACvB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD;AAED,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AAEvB,MAAM,OAAO,QAAQ,KAAK,MAAM,EAAE;AAElC,SAAS,IACPA,KACAC,SAAiB,CAAE,GACnBC,UAA8C,CAAE,GAChD;AACA,QAAO,qCAAa,KAAKC,QAAM;EAC7B,OAAO;EACP,OAAO,QAAQ,aAAa;EAC5B,GAAG;CACJ,EAAC;AACH;AAED,eAAe,KAAKC,KAAa,UAAU,GAAkB;AAC3D,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,IAC3B,KAAI;AACF,kBAAG,OAAO,KAAK;GAAE,WAAW;GAAM,OAAO;EAAM,EAAC;AAChD;CACD,SAAQC,KAAU;AACjB,MAAI,MAAM,UAAU,EAAG,OAAM;EAC7B,MAAM,OAAO,KAAK;AAClB,MACE,SAAS,WACT,SAAS,WACT,SAAS,eACT,SAAS,SAET,OAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,OAAO,IAAI,GAAG;MAEjE,OAAM;CAET;AAEJ;AAgBD,SAAS,WAAWL,KAAsB;AACxC,KAAI;AACF,uCAAa,KAAK,CAAC,WAAY,GAAE;GAC/B,OAAO;GACP,OAAO,QAAQ,aAAa;EAC7B,EAAC;AACF,SAAO;CACR,QAAO;AACN,SAAO;CACR;AACF;AAED,SAAS,cAA6B;AACpC,KAAI,QAAQ,aAAa,QACvB,QAAO;CAGT,MAAM,aAAa;EACjB;EACA;EACA,kBAAK,KAAK,QAAQ,IAAI,gBAAgB,IAAI,UAAU,UAAU;EAC9D,kBAAK,KAAK,QAAQ,IAAI,wBAAwB,IAAI,UAAU,UAAU;EACtE,kBAAK,KAAK,QAAQ,IAAI,WAAW,IAAI,OAAO,UAAU;CACvD;AAED,MAAK,MAAM,aAAa,WACtB,KAAI;AACF,uCAAa,WAAW,CAAC,WAAY,GAAE;GACrC,OAAO;GACP,OAAO;EACR,EAAC;AACF,SAAO;CACR,QAAO,CAAE;AAGZ,KAAI;EACF,MAAM,SAAS,qCAAa,SAAS,CAAC,KAAM,GAAE;GAC5C,UAAU;GACV,OAAO;EACR,EAAC;EAEF,MAAM,QAAQ,OACX,MAAM,QAAQ,CACd,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC,CAC1B,OAAO,QAAQ;EAElB,MAAM,UAAU,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,OAAO,CAAC;AAC3D,SAAO,WAAW,MAAM,MAAM;CAC/B,QAAO;AACN,SAAO;CACR;AACF;AAED,SAAS,uBAAuB;AAC9B,KAAI,WAAW,MAAM,CAAE;AAEvB,SAAQ,IAAI,YAAY;CAExB,MAAM,UAAU,aAAa;AAC7B,MAAK,SAAS;AACZ,kBAAQ,MAAM,iCAAiC;AAC/C,UAAQ,KAAK,EAAE;CAChB;AAED,KAAI,SAAS;EAAC;EAAW;EAAM;CAAM,EAAC;AACvC;AAED,SAAS,cAAcM,UAAwC;AAC7D,QAAO,CAAC,OAAO,CAAC,OAAO,GAAG,QAAS,CAAC;AACrC;AAED,SAAS,qBAAqBC,SAAuB;AACnD,KAAI,QAAM,WAAW,cAAc,IAAI,QAAM,WAAW,eAAe,CACrE,QAAOC;AAET,KAAI,QAAM,WAAW,SAAS,CAE5B,QAAOA;AAGT,SAAQ,EAAE,cAAc,EAAEA,QAAM;AACjC;AAED,SAAS,WAAWC,MAAgD;AAClE,KAAI,KAAK,WAAW,cAAc,CAAE,QAAO;AAC3C,KAAI,KAAK,WAAW,eAAe,CAAE,QAAO;AAC5C,QAAO;AACR;AAED,eAAe,iBAAiBC,aAAqB;AACnD,iBAAQ,KAAK,gBAAgB;AAE7B,KAAI;AACF,MAAI,OAAO,CAAC,OAAO,qBAAsB,GAAE,EACzC,KAAK,YACN,EAAC;AAEF,kBAAQ,QAAQ,2BAA2B;CAC5C,SAAQ,KAAK;AACZ,kBAAQ,MAAM,4BAA4B;AAC1C,UAAQ,MAAM,IAAI;AAClB;CACD;CAED,MAAM,mBAAmB,kBAAK,KAC5B,aACA,gBACA,sBACD;CAED,MAAM,aAAa,kBAAK,KAAK,kBAAkB,OAAO;AAEtD,iBAAQ,MAAM,iBAAiB,WAAW,EAAE;AAE5C,KAAI;AACF,kBAAQ,KAAK,2BAA2B;EAExC,MAAM,aAAa,MAAM,MACvB,sEACA,EACE,SAAS;GACP,QAAQ;GACR,cAAc;EACf,EACF,EACF;AAED,OAAK,WAAW,IAAI;AAClB,mBAAQ,OAAO,mBAAmB,WAAW,OAAO,EAAE;AACtD;EACD;EAED,MAAM,UAAW,MAAM,WAAW,MAAM;AAKxC,kBAAQ,SAAS,iBAAiB,QAAQ,SAAS,EAAE;EACrD,MAAM,YAAY,QAAQ,OAAO,KAC/B,CAACC,MACC,EAAE,KAAK,SAAS,OAAO,IAAI,EAAE,KAAK,SAAS,OAAO,CACrD;AAED,OAAK,WAAW;AACd,mBAAQ,MAAM,kBAAkB;AAChC,WAAQ,IACN,SACA,QAAQ,OAAO,IAAI,CAACC,MAAwB,EAAE,KAAK,CACpD;AACD;EACD;AAED,kBAAQ,MAAM,QAAQ,UAAU,KAAK,EAAE;EAEvC,MAAM,SAAS,MAAM,MAAM,UAAU,sBAAsB,EACzD,SAAS,EACP,cAAc,YACf,EACF,EAAC;AAEF,OAAK,OAAO,IAAI;AACd,mBAAQ,OAAO,QAAQ,OAAO,OAAO,EAAE;AACvC;EACD;EAED,MAAM,SAAS,OAAO,KAAK,MAAM,OAAO,aAAa,CAAC;EAEtD,MAAM,SAAS,kBAAK,KAAK,gBAAG,QAAQ,GAAG,cAAc,KAAK,KAAK,CAAC,MAAM;AAEtE,kBAAG,cAAc,QAAQ,OAAO;AAEhC,kBAAQ,SAAS,YAAY,OAAO,EAAE;EAEtC,MAAM,YAAY,kBAAK,KACrB,gBAAG,QAAQ,GACV,qBAAqB,KAAK,KAAK,CAAC,EAClC;AAED,kBAAG,UAAU,WAAW,EACtB,WAAW,KACZ,EAAC;AAEF,kBAAQ,KAAK,gBAAgB;EAE7B,MAAM,MAAM,IAAIC,gBAAO;AACvB,MAAI,aAAa,WAAW,KAAK;AAEjC,kBAAQ,QAAQ,OAAO;EAEvB,MAAM,YAAY,kBAAkB,UAAU;AAE9C,OAAK,WAAW;AACd,mBAAQ,MAAM,sBAAsB;AACpC,mBAAQ,MAAM,QAAQ,UAAU,EAAE;AAClC;EACD;AAED,kBAAQ,SAAS,WAAW,UAAU,EAAE;AAExC,kBAAG,UAAU,YAAY,EACvB,WAAW,KACZ,EAAC;AAEF,kBAAG,OAAO,WAAW,YAAY;GAC/B,WAAW;GACX,OAAO;EACR,EAAC;AAEF,kBAAQ,QAAQ,kBAAkB;AAElC,QAAM,KAAK,OAAO;AAClB,QAAM,KAAK,UAAU;AAErB,kBAAQ,QAAQ,WAAW;CAC5B,SAAQ,KAAK;AACZ,kBAAQ,MAAM,mBAAmB;AACjC,UAAQ,MAAM,IAAI;CACnB;AACF;AAED,SAAS,kBAAkBC,WAAkC;CAC3D,MAAM,mBAAmB,CAAC,kBAAK,KAAK,WAAW,OAAO,EAAE,SAAU;AAClE,MAAK,MAAM,aAAa,iBACtB,KAAI,gBAAG,WAAW,kBAAK,KAAK,WAAW,aAAa,CAAC,CACnD,QAAO;CAGX,MAAM,WAAW,gBAAG,YAAY,UAAU;AAC1C,MAAK,MAAM,SAAS,UAAU;EAC5B,MAAM,YAAY,kBAAK,KAAK,WAAW,MAAM;AAC7C,MAAI,gBAAG,SAAS,UAAU,CAAC,aAAa,EAAE;GACxC,MAAM,eAAe,kBAAK,KAAK,WAAW,OAAO;AACjD,OAAI,gBAAG,WAAW,kBAAK,KAAK,cAAc,aAAa,CAAC,CACtD,QAAO;EAEV;CACF;AACD,QAAO;AACR;AAED,SAAS,QAAQR,UAAoBS,KAAc;CACjD,MAAM,CAAC,KAAKZ,OAAK,GAAG,cAAc,SAAS;AAE3C,SAAQ,KAAK,MAAM,IAAI,GAAG,OAAK,KAAK,IAAI,CAAC,EAAE;AAE3C,KAAI,KAAKA,QAAM,EACb,IACD,EAAC;AACH;AAED,eAAe,eAAeM,MAAcM,KAAc;CACxD,MAAM,aAAa,qBAAqB,KAAK;CAC7C,MAAM,OAAO,WAAW,WAAW;AACnC,KAAI,SAAS,WAAW;AACtB,kBAAQ,OAAO,YAAY,KAAK,EAAE;AAClC,SAAO;CACR;AACD,KAAI;AACF,UAAQ,CAAC,UAAW,GAAE,IAAI;AAC1B,kBAAQ,SAAS,MAAM,WAAW,EAAE;AACpC,SAAO;CACR,QAAO;AACN,kBAAQ,OAAO,QAAQ,WAAW,EAAE;AACpC,SAAO;CACR;AACF;AAED,eAAe,cAAcN,MAAcM,KAAc;AACvD,KAAI;AACF,UAAQ,KAAK,iBAAiB,KAAK,EAAE;AAErC,MAAI,OAAO,CAAC,UAAU,IAAK,GAAE,EAC3B,IACD,EAAC;AACF,kBAAQ,SAAS,MAAM,KAAK,EAAE;AAC9B,SAAO;CACR,QAAO;AACN,kBAAQ,OAAO,QAAQ,KAAK,EAAE;AAC9B,SAAO;CACR;AACF;AAED,eAAe,aAAaT,UAAoBS,KAAc;AAC5D,KAAI;EACF,MAAM,SAAS,qCAAa,OAAO;GAAC;GAAM;GAAY;EAAS,GAAE;GAC/D;GACA,UAAU;GACV,OAAO;GACP,OAAO,QAAQ,aAAa;EAC7B,EAAC;AACF,OAAK,OAAO,MAAM,EAAE;AAClB,mBAAQ,KAAK,aAAa;AAC1B,UAAO,CAAE;EACV;EACD,MAAM,WAAW,KAAK,MAAM,OAAO;EACnC,MAAMC,UAAoB,CAAE;AAC5B,OAAK,MAAM,OAAO,SAChB,KAAI,SAAS,KACX,SAAQ,MACL,EAAE,IAAI,IAAI,SAAS,KAAK,QAAQ,KAAK,SAAS,KAAK,OAAO,EAC5D;AAGL,SAAO;CACR,QAAO;AACN,SAAO,CAAE;CACV;AACF;AAED,eAAe,qBAAqBC,KAAgC;AAClE,KAAI;EACF,MAAM,UAAU,kBAAK,KAAK,KAAK,eAAe;EAC9C,MAAM,UAAU,0BAAa,SAAS,QAAQ;EAC9C,MAAM,MAAM,KAAK,MAAM,QAAQ;EAC/B,MAAM,OAAO;GACX,GAAG,IAAI;GACP,GAAG,IAAI;EACR;AACD,SAAO,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,CAAC;CAC/D,QAAO;AACN,SAAO,CAAE;CACV;AACF;AAED,CAAC,YAAY;CACX,MAAM,MAAM,iBAAgB,MAAM,EAChC,OAAO;EACL,GAAG;EACH,GAAG;CACJ,EACF,EAAC;CAEF,MAAM,WAAW,qBAAQ;iBACV,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;IAyBrB;CAEF,MAAM,CAAC,KAAK,GAAG,QAAQ,GAAG;AAE1B,SAAQ,KAAR;EACE,KAAK,WAAW;AACd,yBAAsB;GACtB,MAAM,MAAM,QAAQ,KAAK;GACzB,MAAM,OAAO,QAAQ;GACrB,MAAM,OAAO,QAAQ;AAErB,QAAK,SAAS,MAAM;AAClB,oBAAQ,MACN,mEACD;AACD,YAAQ,IAAI,SAAS;AACrB,YAAQ,WAAW;AACnB;GACD;AAED,OAAI,SAAS,YAAY,SAAS,WAAW;AAC3C,oBAAQ,OAAO,SAAS,KAAK,wBAAwB;AACrD,YAAQ,IAAI,SAAS;AACrB,YAAQ,WAAW;AACnB;GACD;GAED,MAAM,SAAS,SAAS,WAAW,gBAAgB;GACnD,MAAM,cAAc,EAAE,OAAO,EAAE,KAAK;GACpC,MAAM,UAAU,MAAM,eAAe,YAAY,IAAI;AACrD,WAAQ,WAAW,UAAU,IAAI;AACjC;EACD;EAED,KAAK,UAAU;AACb,yBAAsB;GACtB,MAAM,MAAM,QAAQ,KAAK;AAEzB,QAAK,QAAQ,UAAU,QAAQ,OAAO,SAAS;IAE7C,MAAMC,aAAW,MAAM,qBAAqB,IAAI;IAChD,MAAM,UAAU,MAAM,aAAaA,YAAU,IAAI;AACjD,QAAI,QAAQ,WAAW,EACrB,iBAAQ,KAAK,oBAAoB;SAC5B;AACL,aAAQ,IAAI,UAAU;AACtB,aAAQ,QAAQ,CAAC,MAAM,gBAAQ,MAAM,IAAI,EAAE,EAAE,CAAC;AAC9C,aAAQ,IAAI,kCAAkC;IAC/C;AACD,YAAQ,WAAW;AACnB;GACD;GAED,MAAM,SAAS,QAAQ;AAEvB,OAAI,WAAW,OAAO;IAEpB,MAAMA,aAAW,MAAM,qBAAqB,IAAI;AAChD,QAAIA,WAAS,WAAW,GAAG;AACzB,qBAAQ,KAAK,iBAAiB;AAC9B,aAAQ,WAAW;AACnB;IACD;AACD,SAAK,MAAM,OAAOA,WAChB,OAAM,cAAc,KAAK,IAAI;AAE/B,YAAQ,WAAW;AACnB;GACD;AAED,OAAI,WAAW,QAAQ;AACrB,UAAM,cAAc,SAAS,IAAI;AACjC,YAAQ,WAAW;AACnB;GACD;AAED,OAAI,WAAW,YAAY,WAAW,WAAW;IAE/C,MAAM,OAAO,QAAQ;AACrB,SAAK,MAAM;KAET,MAAMA,aAAW,MAAM,qBAAqB,IAAI;KAChD,MAAM,SAAS,WAAW,WAAW,gBAAgB;KACrD,MAAM,WAAW,WAAS,OAAO,CAAC,MAAM,EAAE,WAAW,OAAO,CAAC;AAC7D,SAAI,SAAS,WAAW,GAAG;AACzB,sBAAQ,MAAM,MAAM,OAAO,QAAQ;AACnC,cAAQ,WAAW;AACnB;KACD;AACD,UAAK,MAAM,OAAO,SAChB,OAAM,cAAc,KAAK,IAAI;IAEhC,OAAM;KACL,MAAM,SAAS,WAAW,WAAW,gBAAgB;KACrD,MAAM,aAAa,KAAK,WAAW,OAAO,GACtC,QACC,EAAE,OAAO,EAAE,KAAK;AACrB,WAAM,cAAc,YAAY,IAAI;IACrC;AACD,YAAQ,WAAW;AACnB;GACD;GAGD,MAAM,WAAW,MAAM,qBAAqB,IAAI;AAChD,OAAI,SAAS,SAAS,OAAO,CAC3B,OAAM,cAAc,QAAQ,IAAI;QAC3B;IACL,MAAM,aAAa,qBAAqB,OAAO;AAC/C,UAAM,cAAc,YAAY,IAAI;GACrC;AACD,WAAQ,WAAW;AACnB;EACD;EAED,SAAS;GAEP,MAAMC,QAAM,iBAAgB,MAAM,EAChC,OAAO;IACL,GAAG;IACH,GAAG;GACJ,EACF,EAAC;AAEF,WAAQ,MAAR;IACE,KAAKA,MAAI;AACP,aAAQ,KAAK,GAAG,QAAQ,EAAE;AAC1B,aAAQ,WAAW;AACnB;IAGF,KAAKA,MAAI;AACP,aAAQ,IAAI,SAAS;AACrB,aAAQ,WAAW;AACnB;IAGF,QACE;GACH;GAED,MAAM,OAAO,MAAM,MAAM,WAAW;IAClC,SAAS;IACT,aAAa;IACb,UAAU;GACX,EAAC;GAEF,MAAM,SAAS,MAAM,MACnB,6BACA;IACE,aAAa;IACb,SAAS;IACT,UAAU;GACX,EACF;GAED,MAAM,OAAO,MAAM,MAAM,oBAAoB;IAC3C,SAAS;IACT,aAAa;IACb,UAAU;GACX,EAAC;GAEF,MAAM,OAAO,SACX,MAAM,MAAM,oBAAoB;IAC9B,SAAS;IACT,aAAa;IACb,UAAU;GACX,EAAC,CACH;GAED,MAAM,QAAQ,MAAM,MAAM,8BAA8B,EACtD,aAAa,MACd,EAAC;GAEF,MAAM,eAAe,MAAM,QAAQ,qBAAqB,EACtD,SAAS,KACV,EAAC;AAEF,yBAAsB;GAEtB,MAAM,UAAU,qBAAQ;;mBAEX,KAAK;;;;;;uBAMD,OAAO,OAAO,CACxB,MAAM,IAAI,CACV,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CACpB,KAAK,KAAK,CAAC;;;;;;;;;wBASA,KAAK;yBACJ,KAAK;0BACJ,MAAM;;;;;;;;;EAS9B;GAEI,MAAM,aAAa,qBAAQ;;;;;oBAKb,QAAQ;;;;;;;;;;;;;;;EAe1B;GAEI,MAAMC,WAAgC;IACpC,UACE;IACF,gBAAgB;IAChB,SAAS,EAAE,MAAM,EAAE,YAAY,WAAY,EAAE;IAC7C,QAAQ,CAAE;IACV,MAAM,CAAE;GACT;AAED,SAAM,iBAAiB,MAAM,SAAS;AAEtC,OAAI,aACF,OAAM,iBAAiB,kBAAK,KAAK,QAAQ,KAAK,EAAE,KAAK,CAAC;AAGxD,WAAQ,IAAI,YAAY;AACxB,WAAQ,IAAI,QAAQ,KAAK;AACzB,WAAQ,IAAI,kBAAkB;EAC/B;CACF;AACF,IAAG;AAEJ,eAAe,iBAAiBX,MAAcW,UAA+B;CAC3E,MAAM,cAAc;CACpB,MAAM,cAAc,UAAU,IAAI,YAAY,EAAE;AAEhD,KAAI,gBAAG,WAAW,YAAY,EAAE;EAC9B,MAAM,YAAY,MAAM,SAAS,KAAK,YAAY,YAAY;AAE9D,OAAK,UACH,iBAAgB;AAGlB,MAAI,gBAAgB,QAAQ,KAAK,EAC/B;OAAI,gBAAG,YAAY,YAAY,CAAC,WAAW,GAAG;IAC5C,MAAM,cAAc,MAAM,QACxB,oCACD;AACD,SAAK,YACH,iBAAgB;GAEnB;;AAGH,QAAM,KAAK,YAAY;CACxB;AAED,iBAAG,UAAU,aAAa,EAAE,WAAW,KAAM,EAAC;AAE9C,cAAa,UAAU,YAAY;AAEnC,SAAQ,KAAK,KAAK,YAAY,QAAQ;CAEtC,MAAM,CAAC,KAAKjB,OAAK,GAAG,cAAc,iBAAiB;AACnD,SAAQ,KAAK,iBAAiB,IAAI,GAAG,OAAK,KAAK,IAAI,CAAC,EAAE;AACtD,KAAI,KAAKA,QAAM,EACb,KAAK,YACN,EAAC;AACH;AAED,SAAS,iBAAiB;AACxB,SAAQ,IAAI,OAAO;AACnB,SAAQ,KAAK,EAAE;AAChB;AAED,SAAS,SAASkB,OAAe;AAC/B,QAAO,kBAAK,QAAQ,QAAQ,KAAK,EAAE,MAAM;AAC1C;AAMD,eAAe,QACbC,SACAC,SACA;AACA,QAAO,gBAAQ,OAAO,SAAS;EAC7B,MAAM;EACN,QAAQ;EACR,GAAG;CACJ,EAAC;AACH;AAED,eAAe,MACbD,SACAE,SACA;CACA,MAAM,SAAS,MAAM,gBAAQ,OAAO,SAAS;EAC3C,MAAM;EACN,QAAQ;EACR,GAAG;CACJ,EAAC;AACF,KAAI,SAAS,aAAa,OAAQ,QAAO,MAAM,SAAS,QAAQ;AAChE,QAAO;AACR;AAED,SAAS,aACPC,UAIAC,MACA;AACA,MAAK,MAAM,CAAC,MAAM,QAAQ,IAAI,OAAO,QAAQ,SAAS,CACpD,YAAW,YAAY,YAAY,YAAY,MAAM;EACnD,MAAM,WAAW,EAAE,KAAK,GAAG,KAAK;AAChC,OAAK,gBAAG,WAAW,QAAQ,CACzB,iBAAG,UAAU,SAAS,EAAE,WAAW,KAAM,EAAC;AAE5C,OAAK,MAAM,CAAC,SAAS,WAAW,IAAI,OAAO,QAAQ,QAAQ,CACzD,YAAW,eAAe,SACxB,cACE,YACA,kBAAK,KAAK,SAAS,QAAQ,CAC5B;MAED,iBAAG,eAAe,EAAE,QAAQ,GAAG,QAAQ,GAAG,WAAW;CAG1D,OAAM;EACL,MAAM,YAAY,EAAE,KAAK,GAAG,KAAK;EACjC,MAAM,UAAU,kBAAK,QAAQ,SAAS;AACtC,OAAK,gBAAG,WAAW,QAAQ,CACzB,iBAAG,UAAU,SAAS,EAAE,WAAW,KAAM,EAAC;AAE5C,kBAAG,cAAc,UAAU,QAAQ;CACpC;AAEJ"}
|
|
1
|
+
{"version":3,"file":"cli.cjs","names":["cmd: string","args: string[]","options: Parameters<typeof execFileSync>[2]","args","dir: string","err: any","packages: string[]","input: string","input","name: string","cwd?: string","updates: string[]","cwd: string","packages","confirm","cli","fileTree: Record<string, any>","_path: string","message: string","options?: OmitTypeWithRequired<{ initial?: boolean }>","options?: OmitTypeWithRequired<{ default?: string; placeholder?: string }>","fileTree: Record<\n string,\n string | Record<string, string | Record<string, string>>\n >","base: string"],"sources":["../package.json","../src/cli.ts"],"sourcesContent":["{\n \"name\": \"mioku\",\n \"type\": \"module\",\n \"version\": \"0.8.18\",\n \"packageManager\": \"bun@1.2.0\",\n \"description\": \"Mioku - Plugin framework extended from mioki for NapCat OneBot v11\",\n \"keywords\": [\n \"onebot\",\n \"framework\",\n \"bot\",\n \"mioki\",\n \"mioku\"\n ],\n \"bin\": {\n \"mioku\": \"./dist/cli.js\"\n },\n \"engines\": {\n \"node\": \">= 22.18.0\"\n },\n \"homepage\": \"https://github.com/jerryplusy/mioku#readme\",\n \"files\": [\n \"dist\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/jerryplusy/mioku/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/jerryplusy/mioku.git\",\n \"directory\": \"src/packages/mioku\"\n },\n \"scripts\": {\n \"dev\": \"tsdown -w\",\n \"build\": \"tsdown\"\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 \"mioki\": \"^0.16.0\",\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 \"openai\": \"^4.0.0\",\n \"puppeteer\": \"^23.10.0\",\n \"pretty-ms\": \"^9.3.0\",\n \"string2argv\": \"^1.0.2\",\n \"systeminformation\": \"^5.30.7\",\n \"lodash\": \"^4.17.21\"\n },\n \"devDependencies\": {\n \"@types/lodash\": \"^4.17.0\",\n \"@types/node\": \"^22.0.0\",\n \"@types/puppeteer\": \"^7.0.4\",\n \"tsdown\": \"^0.11.0\",\n \"typescript\": \"^5.8.0\"\n }\n}\n","#!/usr/bin/env node\n\nimport fs, { readFileSync } from \"node:fs\";\nimport { execFileSync } from \"node:child_process\";\nimport mri from \"mri\";\nimport path from \"node:path\";\nimport dedent from \"dedent\";\nimport consola from \"consola\";\nimport { version } from \"../package.json\";\nconst DEFAULT_PACKAGES = [\n \"mioku\",\n \"mioku-plugin-boot\",\n \"mioku-plugin-help\",\n \"mioku-plugin-chat\",\n \"mioku-service-config\",\n \"mioku-service-ai\",\n \"mioku-service-screenshot\",\n \"mioku-service-help\",\n];\n\nconst PLUGIN_PREFIX = \"mioku-plugin-\";\nconst SERVICE_PREFIX = \"mioku-service-\";\n\nconst args = process.argv.slice(2);\n\nfunction run(\n cmd: string,\n args: string[] = [],\n options: Parameters<typeof execFileSync>[2] = {},\n) {\n return execFileSync(cmd, args, {\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n ...options,\n });\n}\n\nasync 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\ninterface CliOptions {\n name?: string;\n protocol?: string;\n host?: string;\n port?: number;\n token?: string;\n prefix?: string;\n owners?: string;\n admins?: string;\n help?: boolean;\n version?: boolean;\n \"use-npm-mirror\"?: boolean;\n}\n\nfunction hasCommand(cmd: string): boolean {\n try {\n execFileSync(cmd, [\"--version\"], {\n stdio: \"ignore\",\n shell: process.platform === \"win32\",\n });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction findNpmPath(): string | null {\n if (process.platform !== \"win32\") {\n return \"npm\";\n }\n\n const candidates = [\n \"npm.cmd\",\n \"npm.exe\",\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 for (const candidate of candidates) {\n try {\n execFileSync(candidate, [\"--version\"], {\n stdio: \"ignore\",\n shell: true,\n });\n return candidate;\n } catch {}\n }\n\n try {\n const result = execFileSync(\"where\", [\"npm\"], {\n encoding: \"utf-8\",\n shell: true,\n });\n\n const lines = result\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean);\n\n const cmdPath = lines.find((line) => line.endsWith(\".cmd\"));\n return cmdPath || lines[0] || null;\n } catch {\n return null;\n }\n}\n\nfunction ensurePackageManager() {\n if (hasCommand(\"bun\")) return;\n\n console.log(\"安装 bun...\");\n\n const npmPath = findNpmPath();\n if (!npmPath) {\n consola.error(\"未找到 npm,请确保 Node.js 已安装并包含 npm\");\n process.exit(1);\n }\n\n run(npmPath, [\"install\", \"-g\", \"bun\"]);\n}\n\nfunction getAddCommand(packages: string[]): [string, string[]] {\n return [\"bun\", [\"add\", ...packages]];\n}\n\nfunction normalizePackageName(input: string): string {\n if (input.startsWith(PLUGIN_PREFIX) || input.startsWith(SERVICE_PREFIX)) {\n return input;\n }\n if (input.startsWith(\"mioku-\")) {\n // 已经是完整名称,如 mioku-plugin-xxx\n return input;\n }\n // 默认当作 plugin 处理\n return `${PLUGIN_PREFIX}${input}`;\n}\n\nfunction 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\nfunction execAdd(packages: string[], cwd?: string) {\n const [cmd, args] = getAddCommand(packages);\n\n console.log(`执行: ${cmd} ${args.join(\" \")}`);\n\n run(cmd, args, {\n cwd,\n });\n}\n\nasync function installPackage(name: string, cwd?: string) {\n const normalized = normalizePackageName(name);\n const type = detectType(normalized);\n if (type === \"unknown\") {\n consola.error(`无法识别的包类型: ${name}`);\n return false;\n }\n try {\n execAdd([normalized], cwd);\n consola.success(`已安装 ${normalized}`);\n return true;\n } catch {\n consola.error(`安装失败: ${normalized}`);\n return false;\n }\n}\n\nasync function updatePackage(name: string, cwd?: string) {\n try {\n console.log(`执行: bun update ${name}`);\n\n run(\"bun\", [\"update\", name], {\n cwd,\n });\n consola.success(`已更新 ${name}`);\n return true;\n } catch {\n consola.error(`更新失败: ${name}`);\n return false;\n }\n}\n\nasync function checkUpdates(packages: string[], cwd?: string) {\n try {\n const output = execFileSync(\"bun\", [\"pm\", \"outdated\", \"--json\"], {\n cwd,\n encoding: \"utf-8\",\n stdio: \"pipe\",\n shell: process.platform === \"win32\",\n });\n if (!output.trim()) {\n consola.info(\"所有依赖已是最新版本\");\n return [];\n }\n const outdated = JSON.parse(output);\n const updates: string[] = [];\n for (const pkg of packages) {\n if (outdated[pkg]) {\n updates.push(\n `${pkg}: ${outdated[pkg].current} → ${outdated[pkg].latest}`,\n );\n }\n }\n return updates;\n } catch {\n return [];\n }\n}\n\nasync function getInstalledPackages(cwd: string): Promise<string[]> {\n try {\n const pkgPath = path.join(cwd, \"package.json\");\n const content = readFileSync(pkgPath, \"utf-8\");\n const pkg = JSON.parse(content);\n const deps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n return Object.keys(deps).filter((k) => k.startsWith(\"mioku-\"));\n } catch {\n return [];\n }\n}\n\n(async () => {\n const cli = mri<CliOptions>(args, {\n alias: {\n v: \"version\",\n h: \"help\",\n },\n });\n\n const helpInfo = 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 const [cmd, ...cmdArgs] = args;\n\n switch (cmd) {\n case \"install\": {\n ensurePackageManager();\n const cwd = process.cwd();\n const type = cmdArgs[0];\n const name = cmdArgs[1];\n\n if (!type || !name) {\n consola.error(\n \"请指定类型和名称: mioku install plugin <名称> 或 mioku install service <名称>\",\n );\n console.log(helpInfo);\n process.exitCode = 1;\n return;\n }\n\n if (type !== \"plugin\" && type !== \"service\") {\n consola.error(`无效的类型 \"${type}\",请使用 plugin 或 service`);\n console.log(helpInfo);\n process.exitCode = 1;\n return;\n }\n\n const prefix = type === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const normalized = `${prefix}${name}`;\n const success = await installPackage(normalized, cwd);\n process.exitCode = success ? 0 : 1;\n return;\n }\n\n case \"update\": {\n ensurePackageManager();\n const cwd = process.cwd();\n\n if (!cmdArgs.length || cmdArgs[0] === \"check\") {\n // 检查更新\n const packages = await getInstalledPackages(cwd);\n const updates = await checkUpdates(packages, cwd);\n if (updates.length === 0) {\n consola.info(\"所有 mioku 依赖已是最新版本\");\n } else {\n console.log(\"\\n可用更新:\");\n updates.forEach((u) => consola.warn(` ${u}`));\n console.log(\"\\n运行 npx mioku update all 更新所有包\");\n }\n process.exitCode = 0;\n return;\n }\n\n const target = cmdArgs[0];\n\n if (target === \"all\") {\n // 先并发检查所有包的更新\n const packages = await getInstalledPackages(cwd);\n if (packages.length === 0) {\n consola.info(\"未找到 mioku 相关依赖\");\n process.exitCode = 0;\n return;\n }\n\n const updates = await checkUpdates(packages, cwd);\n if (updates.length === 0) {\n consola.info(\"所有 mioku 依赖已是最新版本\");\n process.exitCode = 0;\n return;\n }\n\n console.log(\"\\n可用更新:\");\n updates.forEach((u) => consola.warn(` ${u}`));\n\n const confirm = await confirm(`确认更新以上 ${updates.length} 个包?`);\n if (!confirm) {\n gracefullyExit();\n }\n\n // 并发更新所有包\n await Promise.all(\n packages.map((pkg) => updatePackage(pkg, cwd)),\n );\n process.exitCode = 0;\n return;\n }\n\n if (target === \"self\") {\n await updatePackage(\"mioku\", cwd);\n process.exitCode = 0;\n return;\n }\n\n if (target === \"plugin\" || target === \"service\") {\n // update plugin/service [name]\n const name = cmdArgs[1];\n if (!name) {\n // 更新所有指定类型的包\n const packages = await getInstalledPackages(cwd);\n const prefix = target === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const filtered = packages.filter((p) => p.startsWith(prefix));\n if (filtered.length === 0) {\n consola.info(`未找到 ${prefix}* 相关依赖`);\n process.exitCode = 0;\n return;\n }\n for (const pkg of filtered) {\n await updatePackage(pkg, cwd);\n }\n } else {\n const prefix = target === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const normalized = name.startsWith(prefix)\n ? name\n : `${prefix}${name}`;\n await updatePackage(normalized, cwd);\n }\n process.exitCode = 0;\n return;\n }\n\n // update xxx - 更新指定包,自动识别前缀\n const packages = await getInstalledPackages(cwd);\n if (packages.includes(target)) {\n await updatePackage(target, cwd);\n } else {\n const normalized = normalizePackageName(target);\n await updatePackage(normalized, cwd);\n }\n process.exitCode = 0;\n return;\n }\n\n default: {\n // 原始交互式项目创建\n const cli = mri<CliOptions>(args, {\n alias: {\n v: \"version\",\n h: \"help\",\n },\n });\n\n switch (true) {\n case cli.version:\n console.log(`v${version}`);\n process.exitCode = 0;\n return;\n // fall through\n\n case cli.help:\n console.log(helpInfo);\n process.exitCode = 0;\n return;\n // fall through\n\n default:\n break;\n }\n\n const name = await input(\"请输入项目名称\", {\n default: \"mioku-bot\",\n placeholder: \"mioku-bot\",\n required: true,\n });\n\n const owners = await input(\n \"请输入主人 QQ (最高权限,英文逗号分隔,必填)\",\n {\n placeholder: \"请输入\",\n default: \"\",\n required: true,\n },\n );\n\n const host = await input(\"请输入 NapCat WS 主机\", {\n default: \"localhost\",\n placeholder: \"localhost\",\n required: true,\n });\n\n const port = parseInt(\n await input(\"请输入 NapCat WS 端口\", {\n default: \"3001\",\n placeholder: \"3001\",\n required: true,\n }),\n );\n\n const token = await input(\"请输入 NapCat WS Token(如无则留空)\", {\n placeholder: \"请输入\",\n });\n\n ensurePackageManager();\n\n const pkgJson = dedent(`\n {\n \"name\": \"${name}\",\n \"private\": true,\n \"type\": \"module\",\n \"dependencies\": {},\n \"mioki\": {\n \"prefix\": \"#\",\n \"owners\": [${String(owners)\n .split(\",\")\n .map((o) => o.trim())\n .join(\", \")}],\n \"admins\": [],\n \"plugins\": [\"boot\", \"help\", \"chat\", \"demo\"],\n \"log_level\": \"info\",\n \"online_push\": false,\n \"error_push\": false,\n \"napcat\": [\n {\n \"protocol\": \"ws\",\n \"port\": ${port},\n \"host\": \"${host}\",\n \"token\": \"${token}\"\n }\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, any> = {\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 installWebui = await confirm(\"是否安装 WebUI 管理面板?(建议安装)\", {\n initial: true,\n });\n\n await createNewProject(name, fileTree, installWebui);\n\n console.log(\"\\n若需启动机器人,请运行:\");\n console.log(\" cd\", name);\n console.log(\" bun run start\");\n }\n }\n})();\n\nasync function createNewProject(name: string, fileTree: Record<string, any>, installWebui = false) {\n const projectName = name;\n const projectPath = withRoot(`./${projectName}`);\n\n if (fs.existsSync(projectPath)) {\n const overwrite = await confirm(`项目 ${projectName} 已存在,是否覆盖?`);\n\n if (!overwrite) {\n gracefullyExit();\n }\n\n if (projectPath === process.cwd()) {\n if (fs.readdirSync(projectPath).length !== 0) {\n const confirmOver = await confirm(\n \"项目路径与当前路径相同,将删除当前目录下所有内容再创建,是否继续?\",\n );\n if (!confirmOver) {\n gracefullyExit();\n }\n }\n }\n\n await rmrf(projectPath);\n }\n\n fs.mkdirSync(projectPath, { recursive: true });\n\n makeFileTree(fileTree, projectPath);\n\n console.log(`项目 ${projectName} 创建成功!`);\n\n const packages = installWebui ? DEFAULT_PACKAGES : DEFAULT_PACKAGES.filter(p => p !== \"mioku-service-webui\");\n const [cmd, args] = getAddCommand(packages);\n console.log(`正在安装 Mioku 依赖: ${cmd} ${args.join(\" \")}`);\n run(cmd, args, {\n cwd: projectPath,\n });\n}\n\nfunction gracefullyExit() {\n console.log(\"Bye!\");\n process.exit(0);\n}\n\nfunction withRoot(_path: string) {\n return path.resolve(process.cwd(), _path);\n}\n\ntype OmitTypeWithRequired<T> = Omit<T, \"type\" | \"required\"> & {\n required?: boolean;\n};\n\nasync function confirm(\n message: string,\n options?: OmitTypeWithRequired<{ initial?: boolean }>,\n) {\n return consola.prompt(message, {\n type: \"confirm\",\n cancel: \"reject\",\n ...options,\n });\n}\n\nasync function input(\n message: string,\n options?: OmitTypeWithRequired<{ default?: string; placeholder?: string }>,\n) {\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\nfunction makeFileTree(\n fileTree: Record<\n string,\n string | Record<string, string | Record<string, string>>\n >,\n base: string,\n) {\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)) {\n fs.mkdirSync(subPath, { recursive: true });\n }\n for (const [subName, subContent] of Object.entries(content)) {\n if (typeof subContent === \"object\") {\n makeFileTree(\n subContent as typeof fileTree,\n path.join(subPath, subName),\n );\n } else {\n fs.writeFileSync(`${subPath}/${subName}`, subContent);\n }\n }\n } else {\n const filePath = `${base}/${name}`;\n const dirname = path.dirname(filePath);\n if (!fs.existsSync(dirname)) {\n fs.mkdirSync(dirname, { recursive: true });\n }\n fs.writeFileSync(filePath, content);\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -3,13 +3,11 @@ import fs, { readFileSync } from "node:fs";
|
|
|
3
3
|
import { execFileSync } from "node:child_process";
|
|
4
4
|
import mri from "mri";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
import os from "node:os";
|
|
7
6
|
import dedent from "dedent";
|
|
8
7
|
import consola from "consola";
|
|
9
|
-
import AdmZip from "adm-zip";
|
|
10
8
|
|
|
11
9
|
//#region package.json
|
|
12
|
-
var version = "0.8.
|
|
10
|
+
var version = "0.8.18";
|
|
13
11
|
|
|
14
12
|
//#endregion
|
|
15
13
|
//#region src/cli.ts
|
|
@@ -113,87 +111,6 @@ function detectType(name) {
|
|
|
113
111
|
if (name.startsWith(SERVICE_PREFIX)) return "service";
|
|
114
112
|
return "unknown";
|
|
115
113
|
}
|
|
116
|
-
async function installWebUIDist(projectPath) {
|
|
117
|
-
consola.info("正在安装 WebUI...");
|
|
118
|
-
try {
|
|
119
|
-
run("bun", ["add", "mioku-service-webui"], { cwd: projectPath });
|
|
120
|
-
consola.success("mioku-service-webui 安装成功");
|
|
121
|
-
} catch (err) {
|
|
122
|
-
consola.error("安装 mioku-service-webui 失败");
|
|
123
|
-
console.error(err);
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
const nodeModulesWebui = path.join(projectPath, "node_modules", "mioku-service-webui");
|
|
127
|
-
const targetDist = path.join(nodeModulesWebui, "dist");
|
|
128
|
-
consola.info(`WebUI dist 目录: ${targetDist}`);
|
|
129
|
-
try {
|
|
130
|
-
consola.info("正在获取 WebUI Release 信息...");
|
|
131
|
-
const releaseRes = await fetch("https://api.github.com/repos/mioku-lab/mioku-webui/releases/latest", { headers: {
|
|
132
|
-
Accept: "application/vnd.github+json",
|
|
133
|
-
"User-Agent": "mioku-cli"
|
|
134
|
-
} });
|
|
135
|
-
if (!releaseRes.ok) {
|
|
136
|
-
consola.error(`GitHub API 请求失败: ${releaseRes.status}`);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
const release = await releaseRes.json();
|
|
140
|
-
consola.success(`获取 Release 成功: ${release.tag_name}`);
|
|
141
|
-
const distAsset = release.assets.find((a) => a.name.includes("dist") || a.name.endsWith(".zip"));
|
|
142
|
-
if (!distAsset) {
|
|
143
|
-
consola.error("未找到 dist zip 资源");
|
|
144
|
-
console.log("可用资源:", release.assets.map((a) => a.name));
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
consola.info(`下载资源: ${distAsset.name}`);
|
|
148
|
-
const zipRes = await fetch(distAsset.browser_download_url, { headers: { "User-Agent": "mioku-cli" } });
|
|
149
|
-
if (!zipRes.ok) {
|
|
150
|
-
consola.error(`下载失败: ${zipRes.status}`);
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
const buffer = Buffer.from(await zipRes.arrayBuffer());
|
|
154
|
-
const tmpZip = path.join(os.tmpdir(), `mioku-webui-${Date.now()}.zip`);
|
|
155
|
-
fs.writeFileSync(tmpZip, buffer);
|
|
156
|
-
consola.success(`ZIP 下载完成: ${tmpZip}`);
|
|
157
|
-
const tmpUnpack = path.join(os.tmpdir(), `mioku-webui-unpack-${Date.now()}`);
|
|
158
|
-
fs.mkdirSync(tmpUnpack, { recursive: true });
|
|
159
|
-
consola.info("正在解压 WebUI...");
|
|
160
|
-
const zip = new AdmZip(tmpZip);
|
|
161
|
-
zip.extractAllTo(tmpUnpack, true);
|
|
162
|
-
consola.success("解压完成");
|
|
163
|
-
const sourceDir = findDistSourceDir(tmpUnpack);
|
|
164
|
-
if (!sourceDir) {
|
|
165
|
-
consola.error("未找到 dist/index.html");
|
|
166
|
-
consola.info(`解压目录: ${tmpUnpack}`);
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
consola.success(`找到 dist: ${sourceDir}`);
|
|
170
|
-
fs.mkdirSync(targetDist, { recursive: true });
|
|
171
|
-
fs.cpSync(sourceDir, targetDist, {
|
|
172
|
-
recursive: true,
|
|
173
|
-
force: true
|
|
174
|
-
});
|
|
175
|
-
consola.success("WebUI dist 安装成功");
|
|
176
|
-
await rmrf(tmpZip);
|
|
177
|
-
await rmrf(tmpUnpack);
|
|
178
|
-
consola.success("临时文件清理完成");
|
|
179
|
-
} catch (err) {
|
|
180
|
-
consola.error("安装 WebUI dist 失败");
|
|
181
|
-
console.error(err);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
function findDistSourceDir(unpackDir) {
|
|
185
|
-
const directCandidates = [path.join(unpackDir, "dist"), unpackDir];
|
|
186
|
-
for (const candidate of directCandidates) if (fs.existsSync(path.join(candidate, "index.html"))) return candidate;
|
|
187
|
-
const children = fs.readdirSync(unpackDir);
|
|
188
|
-
for (const child of children) {
|
|
189
|
-
const childPath = path.join(unpackDir, child);
|
|
190
|
-
if (fs.statSync(childPath).isDirectory()) {
|
|
191
|
-
const subCandidate = path.join(childPath, "dist");
|
|
192
|
-
if (fs.existsSync(path.join(subCandidate, "index.html"))) return subCandidate;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
return null;
|
|
196
|
-
}
|
|
197
114
|
function execAdd(packages, cwd) {
|
|
198
115
|
const [cmd, args$1] = getAddCommand(packages);
|
|
199
116
|
console.log(`执行: ${cmd} ${args$1.join(" ")}`);
|
|
@@ -344,7 +261,17 @@ async function getInstalledPackages(cwd) {
|
|
|
344
261
|
process.exitCode = 0;
|
|
345
262
|
return;
|
|
346
263
|
}
|
|
347
|
-
|
|
264
|
+
const updates = await checkUpdates(packages$1, cwd);
|
|
265
|
+
if (updates.length === 0) {
|
|
266
|
+
consola.info("所有 mioku 依赖已是最新版本");
|
|
267
|
+
process.exitCode = 0;
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
console.log("\n可用更新:");
|
|
271
|
+
updates.forEach((u) => consola.warn(` ${u}`));
|
|
272
|
+
const confirm$1 = await confirm$1(`确认更新以上 ${updates.length} 个包?`);
|
|
273
|
+
if (!confirm$1) gracefullyExit();
|
|
274
|
+
await Promise.all(packages$1.map((pkg) => updatePackage(pkg, cwd)));
|
|
348
275
|
process.exitCode = 0;
|
|
349
276
|
return;
|
|
350
277
|
}
|
|
@@ -419,7 +346,6 @@ async function getInstalledPackages(cwd) {
|
|
|
419
346
|
required: true
|
|
420
347
|
}));
|
|
421
348
|
const token = await input("请输入 NapCat WS Token(如无则留空)", { placeholder: "请输入" });
|
|
422
|
-
const installWebui = await confirm("是否安装 WebUI?(建议安装)", { initial: true });
|
|
423
349
|
ensurePackageManager();
|
|
424
350
|
const pkgJson = dedent(`
|
|
425
351
|
{
|
|
@@ -478,15 +404,15 @@ async function getInstalledPackages(cwd) {
|
|
|
478
404
|
config: {},
|
|
479
405
|
data: {}
|
|
480
406
|
};
|
|
481
|
-
await
|
|
482
|
-
|
|
483
|
-
console.log("\n
|
|
407
|
+
const installWebui = await confirm("是否安装 WebUI 管理面板?(建议安装)", { initial: true });
|
|
408
|
+
await createNewProject(name, fileTree, installWebui);
|
|
409
|
+
console.log("\n若需启动机器人,请运行:");
|
|
484
410
|
console.log(" cd", name);
|
|
485
411
|
console.log(" bun run start");
|
|
486
412
|
}
|
|
487
413
|
}
|
|
488
414
|
})();
|
|
489
|
-
async function createNewProject(name, fileTree) {
|
|
415
|
+
async function createNewProject(name, fileTree, installWebui = false) {
|
|
490
416
|
const projectName = name;
|
|
491
417
|
const projectPath = withRoot(`./${projectName}`);
|
|
492
418
|
if (fs.existsSync(projectPath)) {
|
|
@@ -503,7 +429,8 @@ async function createNewProject(name, fileTree) {
|
|
|
503
429
|
fs.mkdirSync(projectPath, { recursive: true });
|
|
504
430
|
makeFileTree(fileTree, projectPath);
|
|
505
431
|
console.log(`项目 ${projectName} 创建成功!`);
|
|
506
|
-
const
|
|
432
|
+
const packages = installWebui ? DEFAULT_PACKAGES : DEFAULT_PACKAGES.filter((p) => p !== "mioku-service-webui");
|
|
433
|
+
const [cmd, args$1] = getAddCommand(packages);
|
|
507
434
|
console.log(`正在安装 Mioku 依赖: ${cmd} ${args$1.join(" ")}`);
|
|
508
435
|
run(cmd, args$1, { cwd: projectPath });
|
|
509
436
|
}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","names":["cmd: string","args: string[]","options: Parameters<typeof execFileSync>[2]","args","dir: string","err: any","packages: string[]","input: string","input","name: string","projectPath: string","a: { name: string; browser_download_url: string }","a: { name: string }","unpackDir: string","cwd?: string","updates: string[]","cwd: string","packages","cli","fileTree: Record<string, any>","_path: string","message: string","options?: OmitTypeWithRequired<{ initial?: boolean }>","options?: OmitTypeWithRequired<{ default?: string; placeholder?: string }>","fileTree: Record<\n string,\n string | Record<string, string | Record<string, string>>\n >","base: string"],"sources":["../package.json","../src/cli.ts"],"sourcesContent":["{\n \"name\": \"mioku\",\n \"type\": \"module\",\n \"version\": \"0.8.15\",\n \"packageManager\": \"bun@1.2.0\",\n \"description\": \"Mioku - Plugin framework extended from mioki for NapCat OneBot v11\",\n \"keywords\": [\n \"onebot\",\n \"framework\",\n \"bot\",\n \"mioki\",\n \"mioku\"\n ],\n \"bin\": {\n \"mioku\": \"./dist/cli.js\"\n },\n \"engines\": {\n \"node\": \">= 22.18.0\"\n },\n \"homepage\": \"https://github.com/jerryplusy/mioku#readme\",\n \"files\": [\n \"dist\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/jerryplusy/mioku/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/jerryplusy/mioku.git\",\n \"directory\": \"src/packages/mioku\"\n },\n \"scripts\": {\n \"dev\": \"tsdown -w\",\n \"build\": \"tsdown\"\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 \"mioki\": \"^0.16.0\",\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 \"openai\": \"^4.0.0\",\n \"puppeteer\": \"^23.10.0\",\n \"pretty-ms\": \"^9.3.0\",\n \"string2argv\": \"^1.0.2\",\n \"systeminformation\": \"^5.30.7\",\n \"lodash\": \"^4.17.21\",\n \"adm-zip\": \"^0.5.16\"\n },\n \"devDependencies\": {\n \"@types/lodash\": \"^4.17.0\",\n \"@types/node\": \"^22.0.0\",\n \"@types/puppeteer\": \"^7.0.4\",\n \"tsdown\": \"^0.11.0\",\n \"typescript\": \"^5.8.0\"\n }\n}\n","#!/usr/bin/env node\n\nimport fs from \"node:fs\";\nimport { execFileSync } from \"node:child_process\";\nimport mri from \"mri\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport dedent from \"dedent\";\nimport consola from \"consola\";\nimport { version } from \"../package.json\";\nimport { readFileSync } from \"node:fs\";\nimport AdmZip from \"adm-zip\";\n\nconst DEFAULT_PACKAGES = [\n \"mioku\",\n \"mioku-plugin-boot\",\n \"mioku-plugin-help\",\n \"mioku-plugin-chat\",\n \"mioku-service-config\",\n \"mioku-service-ai\",\n \"mioku-service-screenshot\",\n \"mioku-service-help\",\n];\n\nconst PLUGIN_PREFIX = \"mioku-plugin-\";\nconst SERVICE_PREFIX = \"mioku-service-\";\n\nconst args = process.argv.slice(2);\n\nfunction run(\n cmd: string,\n args: string[] = [],\n options: Parameters<typeof execFileSync>[2] = {},\n) {\n return execFileSync(cmd, args, {\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n ...options,\n });\n}\n\nasync 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\ninterface CliOptions {\n name?: string;\n protocol?: string;\n host?: string;\n port?: number;\n token?: string;\n prefix?: string;\n owners?: string;\n admins?: string;\n help?: boolean;\n version?: boolean;\n \"use-npm-mirror\"?: boolean;\n}\n\nfunction hasCommand(cmd: string): boolean {\n try {\n execFileSync(cmd, [\"--version\"], {\n stdio: \"ignore\",\n shell: process.platform === \"win32\",\n });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction findNpmPath(): string | null {\n if (process.platform !== \"win32\") {\n return \"npm\";\n }\n\n const candidates = [\n \"npm.cmd\",\n \"npm.exe\",\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 for (const candidate of candidates) {\n try {\n execFileSync(candidate, [\"--version\"], {\n stdio: \"ignore\",\n shell: true,\n });\n return candidate;\n } catch {}\n }\n\n try {\n const result = execFileSync(\"where\", [\"npm\"], {\n encoding: \"utf-8\",\n shell: true,\n });\n\n const lines = result\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean);\n\n const cmdPath = lines.find((line) => line.endsWith(\".cmd\"));\n return cmdPath || lines[0] || null;\n } catch {\n return null;\n }\n}\n\nfunction ensurePackageManager() {\n if (hasCommand(\"bun\")) return;\n\n console.log(\"安装 bun...\");\n\n const npmPath = findNpmPath();\n if (!npmPath) {\n consola.error(\"未找到 npm,请确保 Node.js 已安装并包含 npm\");\n process.exit(1);\n }\n\n run(npmPath, [\"install\", \"-g\", \"bun\"]);\n}\n\nfunction getAddCommand(packages: string[]): [string, string[]] {\n return [\"bun\", [\"add\", ...packages]];\n}\n\nfunction normalizePackageName(input: string): string {\n if (input.startsWith(PLUGIN_PREFIX) || input.startsWith(SERVICE_PREFIX)) {\n return input;\n }\n if (input.startsWith(\"mioku-\")) {\n // 已经是完整名称,如 mioku-plugin-xxx\n return input;\n }\n // 默认当作 plugin 处理\n return `${PLUGIN_PREFIX}${input}`;\n}\n\nfunction 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\nasync function installWebUIDist(projectPath: string) {\n consola.info(\"正在安装 WebUI...\");\n\n try {\n run(\"bun\", [\"add\", \"mioku-service-webui\"], {\n cwd: projectPath,\n });\n\n consola.success(\"mioku-service-webui 安装成功\");\n } catch (err) {\n consola.error(\"安装 mioku-service-webui 失败\");\n console.error(err);\n return;\n }\n\n const nodeModulesWebui = path.join(\n projectPath,\n \"node_modules\",\n \"mioku-service-webui\",\n );\n\n const targetDist = path.join(nodeModulesWebui, \"dist\");\n\n consola.info(`WebUI dist 目录: ${targetDist}`);\n\n try {\n consola.info(\"正在获取 WebUI Release 信息...\");\n\n const releaseRes = await fetch(\n \"https://api.github.com/repos/mioku-lab/mioku-webui/releases/latest\",\n {\n headers: {\n Accept: \"application/vnd.github+json\",\n \"User-Agent\": \"mioku-cli\",\n },\n },\n );\n\n if (!releaseRes.ok) {\n consola.error(`GitHub API 请求失败: ${releaseRes.status}`);\n return;\n }\n\n const release = (await releaseRes.json()) as {\n tag_name: string;\n assets: Array<{ name: string; browser_download_url: string }>;\n };\n\n consola.success(`获取 Release 成功: ${release.tag_name}`);\n const distAsset = release.assets.find(\n (a: { name: string; browser_download_url: string }) =>\n a.name.includes(\"dist\") || a.name.endsWith(\".zip\"),\n );\n\n if (!distAsset) {\n consola.error(\"未找到 dist zip 资源\");\n console.log(\n \"可用资源:\",\n release.assets.map((a: { name: string }) => a.name),\n );\n return;\n }\n\n consola.info(`下载资源: ${distAsset.name}`);\n\n const zipRes = await fetch(distAsset.browser_download_url, {\n headers: {\n \"User-Agent\": \"mioku-cli\",\n },\n });\n\n if (!zipRes.ok) {\n consola.error(`下载失败: ${zipRes.status}`);\n return;\n }\n\n const buffer = Buffer.from(await zipRes.arrayBuffer());\n\n const tmpZip = path.join(os.tmpdir(), `mioku-webui-${Date.now()}.zip`);\n\n fs.writeFileSync(tmpZip, buffer);\n\n consola.success(`ZIP 下载完成: ${tmpZip}`);\n\n const tmpUnpack = path.join(\n os.tmpdir(),\n `mioku-webui-unpack-${Date.now()}`,\n );\n\n fs.mkdirSync(tmpUnpack, {\n recursive: true,\n });\n\n consola.info(\"正在解压 WebUI...\");\n\n const zip = new AdmZip(tmpZip);\n zip.extractAllTo(tmpUnpack, true);\n\n consola.success(\"解压完成\");\n\n const sourceDir = findDistSourceDir(tmpUnpack);\n\n if (!sourceDir) {\n consola.error(\"未找到 dist/index.html\");\n consola.info(`解压目录: ${tmpUnpack}`);\n return;\n }\n\n consola.success(`找到 dist: ${sourceDir}`);\n\n fs.mkdirSync(targetDist, {\n recursive: true,\n });\n\n fs.cpSync(sourceDir, targetDist, {\n recursive: true,\n force: true,\n });\n\n consola.success(\"WebUI dist 安装成功\");\n\n await rmrf(tmpZip);\n await rmrf(tmpUnpack);\n\n consola.success(\"临时文件清理完成\");\n } catch (err) {\n consola.error(\"安装 WebUI dist 失败\");\n console.error(err);\n }\n}\n\nfunction findDistSourceDir(unpackDir: string): string | null {\n const directCandidates = [path.join(unpackDir, \"dist\"), unpackDir];\n for (const candidate of directCandidates) {\n if (fs.existsSync(path.join(candidate, \"index.html\"))) {\n return candidate;\n }\n }\n const children = fs.readdirSync(unpackDir);\n for (const child of children) {\n const childPath = path.join(unpackDir, child);\n if (fs.statSync(childPath).isDirectory()) {\n const subCandidate = path.join(childPath, \"dist\");\n if (fs.existsSync(path.join(subCandidate, \"index.html\"))) {\n return subCandidate;\n }\n }\n }\n return null;\n}\n\nfunction execAdd(packages: string[], cwd?: string) {\n const [cmd, args] = getAddCommand(packages);\n\n console.log(`执行: ${cmd} ${args.join(\" \")}`);\n\n run(cmd, args, {\n cwd,\n });\n}\n\nasync function installPackage(name: string, cwd?: string) {\n const normalized = normalizePackageName(name);\n const type = detectType(normalized);\n if (type === \"unknown\") {\n consola.error(`无法识别的包类型: ${name}`);\n return false;\n }\n try {\n execAdd([normalized], cwd);\n consola.success(`已安装 ${normalized}`);\n return true;\n } catch {\n consola.error(`安装失败: ${normalized}`);\n return false;\n }\n}\n\nasync function updatePackage(name: string, cwd?: string) {\n try {\n console.log(`执行: bun update ${name}`);\n\n run(\"bun\", [\"update\", name], {\n cwd,\n });\n consola.success(`已更新 ${name}`);\n return true;\n } catch {\n consola.error(`更新失败: ${name}`);\n return false;\n }\n}\n\nasync function checkUpdates(packages: string[], cwd?: string) {\n try {\n const output = execFileSync(\"bun\", [\"pm\", \"outdated\", \"--json\"], {\n cwd,\n encoding: \"utf-8\",\n stdio: \"pipe\",\n shell: process.platform === \"win32\",\n });\n if (!output.trim()) {\n consola.info(\"所有依赖已是最新版本\");\n return [];\n }\n const outdated = JSON.parse(output);\n const updates: string[] = [];\n for (const pkg of packages) {\n if (outdated[pkg]) {\n updates.push(\n `${pkg}: ${outdated[pkg].current} → ${outdated[pkg].latest}`,\n );\n }\n }\n return updates;\n } catch {\n return [];\n }\n}\n\nasync function getInstalledPackages(cwd: string): Promise<string[]> {\n try {\n const pkgPath = path.join(cwd, \"package.json\");\n const content = readFileSync(pkgPath, \"utf-8\");\n const pkg = JSON.parse(content);\n const deps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n return Object.keys(deps).filter((k) => k.startsWith(\"mioku-\"));\n } catch {\n return [];\n }\n}\n\n(async () => {\n const cli = mri<CliOptions>(args, {\n alias: {\n v: \"version\",\n h: \"help\",\n },\n });\n\n const helpInfo = 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 const [cmd, ...cmdArgs] = args;\n\n switch (cmd) {\n case \"install\": {\n ensurePackageManager();\n const cwd = process.cwd();\n const type = cmdArgs[0];\n const name = cmdArgs[1];\n\n if (!type || !name) {\n consola.error(\n \"请指定类型和名称: mioku install plugin <名称> 或 mioku install service <名称>\",\n );\n console.log(helpInfo);\n process.exitCode = 1;\n return;\n }\n\n if (type !== \"plugin\" && type !== \"service\") {\n consola.error(`无效的类型 \"${type}\",请使用 plugin 或 service`);\n console.log(helpInfo);\n process.exitCode = 1;\n return;\n }\n\n const prefix = type === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const normalized = `${prefix}${name}`;\n const success = await installPackage(normalized, cwd);\n process.exitCode = success ? 0 : 1;\n return;\n }\n\n case \"update\": {\n ensurePackageManager();\n const cwd = process.cwd();\n\n if (!cmdArgs.length || cmdArgs[0] === \"check\") {\n // 检查更新\n const packages = await getInstalledPackages(cwd);\n const updates = await checkUpdates(packages, cwd);\n if (updates.length === 0) {\n consola.info(\"所有 mioku 依赖已是最新版本\");\n } else {\n console.log(\"\\n可用更新:\");\n updates.forEach((u) => consola.warn(` ${u}`));\n console.log(\"\\n运行 npx mioku update all 更新所有包\");\n }\n process.exitCode = 0;\n return;\n }\n\n const target = cmdArgs[0];\n\n if (target === \"all\") {\n // 更新所有 mioku- 包\n const packages = await getInstalledPackages(cwd);\n if (packages.length === 0) {\n consola.info(\"未找到 mioku 相关依赖\");\n process.exitCode = 0;\n return;\n }\n for (const pkg of packages) {\n await updatePackage(pkg, cwd);\n }\n process.exitCode = 0;\n return;\n }\n\n if (target === \"self\") {\n await updatePackage(\"mioku\", cwd);\n process.exitCode = 0;\n return;\n }\n\n if (target === \"plugin\" || target === \"service\") {\n // update plugin/service [name]\n const name = cmdArgs[1];\n if (!name) {\n // 更新所有指定类型的包\n const packages = await getInstalledPackages(cwd);\n const prefix = target === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const filtered = packages.filter((p) => p.startsWith(prefix));\n if (filtered.length === 0) {\n consola.info(`未找到 ${prefix}* 相关依赖`);\n process.exitCode = 0;\n return;\n }\n for (const pkg of filtered) {\n await updatePackage(pkg, cwd);\n }\n } else {\n const prefix = target === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const normalized = name.startsWith(prefix)\n ? name\n : `${prefix}${name}`;\n await updatePackage(normalized, cwd);\n }\n process.exitCode = 0;\n return;\n }\n\n // update xxx - 更新指定包,自动识别前缀\n const packages = await getInstalledPackages(cwd);\n if (packages.includes(target)) {\n await updatePackage(target, cwd);\n } else {\n const normalized = normalizePackageName(target);\n await updatePackage(normalized, cwd);\n }\n process.exitCode = 0;\n return;\n }\n\n default: {\n // 原始交互式项目创建\n const cli = mri<CliOptions>(args, {\n alias: {\n v: \"version\",\n h: \"help\",\n },\n });\n\n switch (true) {\n case cli.version:\n console.log(`v${version}`);\n process.exitCode = 0;\n return;\n // fall through\n\n case cli.help:\n console.log(helpInfo);\n process.exitCode = 0;\n return;\n // fall through\n\n default:\n break;\n }\n\n const name = await input(\"请输入项目名称\", {\n default: \"mioku-bot\",\n placeholder: \"mioku-bot\",\n required: true,\n });\n\n const owners = await input(\n \"请输入主人 QQ (最高权限,英文逗号分隔,必填)\",\n {\n placeholder: \"请输入\",\n default: \"\",\n required: true,\n },\n );\n\n const host = await input(\"请输入 NapCat WS 主机\", {\n default: \"localhost\",\n placeholder: \"localhost\",\n required: true,\n });\n\n const port = parseInt(\n await input(\"请输入 NapCat WS 端口\", {\n default: \"3001\",\n placeholder: \"3001\",\n required: true,\n }),\n );\n\n const token = await input(\"请输入 NapCat WS Token(如无则留空)\", {\n placeholder: \"请输入\",\n });\n\n const installWebui = await confirm(\"是否安装 WebUI?(建议安装)\", {\n initial: true,\n });\n\n ensurePackageManager();\n\n const pkgJson = dedent(`\n {\n \"name\": \"${name}\",\n \"private\": true,\n \"type\": \"module\",\n \"dependencies\": {},\n \"mioki\": {\n \"prefix\": \"#\",\n \"owners\": [${String(owners)\n .split(\",\")\n .map((o) => o.trim())\n .join(\", \")}],\n \"admins\": [],\n \"plugins\": [\"boot\", \"help\", \"chat\", \"demo\"],\n \"log_level\": \"info\",\n \"online_push\": false,\n \"error_push\": false,\n \"napcat\": [\n {\n \"protocol\": \"ws\",\n \"port\": ${port},\n \"host\": \"${host}\",\n \"token\": \"${token}\"\n }\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, any> = {\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 await createNewProject(name, fileTree);\n\n if (installWebui) {\n await installWebUIDist(path.join(process.cwd(), name));\n }\n\n console.log(\"\\n接下来的操作:\");\n console.log(\" cd\", name);\n console.log(\" bun run start\");\n }\n }\n})();\n\nasync function createNewProject(name: string, fileTree: Record<string, any>) {\n const projectName = name;\n const projectPath = withRoot(`./${projectName}`);\n\n if (fs.existsSync(projectPath)) {\n const overwrite = await confirm(`项目 ${projectName} 已存在,是否覆盖?`);\n\n if (!overwrite) {\n gracefullyExit();\n }\n\n if (projectPath === process.cwd()) {\n if (fs.readdirSync(projectPath).length !== 0) {\n const confirmOver = await confirm(\n \"项目路径与当前路径相同,将删除当前目录下所有内容再创建,是否继续?\",\n );\n if (!confirmOver) {\n gracefullyExit();\n }\n }\n }\n\n await rmrf(projectPath);\n }\n\n fs.mkdirSync(projectPath, { recursive: true });\n\n makeFileTree(fileTree, projectPath);\n\n console.log(`项目 ${projectName} 创建成功!`);\n\n const [cmd, args] = getAddCommand(DEFAULT_PACKAGES);\n console.log(`正在安装 Mioku 依赖: ${cmd} ${args.join(\" \")}`);\n run(cmd, args, {\n cwd: projectPath,\n });\n}\n\nfunction gracefullyExit() {\n console.log(\"Bye!\");\n process.exit(0);\n}\n\nfunction withRoot(_path: string) {\n return path.resolve(process.cwd(), _path);\n}\n\ntype OmitTypeWithRequired<T> = Omit<T, \"type\" | \"required\"> & {\n required?: boolean;\n};\n\nasync function confirm(\n message: string,\n options?: OmitTypeWithRequired<{ initial?: boolean }>,\n) {\n return consola.prompt(message, {\n type: \"confirm\",\n cancel: \"reject\",\n ...options,\n });\n}\n\nasync function input(\n message: string,\n options?: OmitTypeWithRequired<{ default?: string; placeholder?: string }>,\n) {\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\nfunction makeFileTree(\n fileTree: Record<\n string,\n string | Record<string, string | Record<string, string>>\n >,\n base: string,\n) {\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)) {\n fs.mkdirSync(subPath, { recursive: true });\n }\n for (const [subName, subContent] of Object.entries(content)) {\n if (typeof subContent === \"object\") {\n makeFileTree(\n subContent as typeof fileTree,\n path.join(subPath, subName),\n );\n } else {\n fs.writeFileSync(`${subPath}/${subName}`, subContent);\n }\n }\n } else {\n const filePath = `${base}/${name}`;\n const dirname = path.dirname(filePath);\n if (!fs.existsSync(dirname)) {\n fs.mkdirSync(dirname, { recursive: true });\n }\n fs.writeFileSync(filePath, content);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","names":["cmd: string","args: string[]","options: Parameters<typeof execFileSync>[2]","args","dir: string","err: any","packages: string[]","input: string","input","name: string","cwd?: string","updates: string[]","cwd: string","packages","confirm","cli","fileTree: Record<string, any>","_path: string","message: string","options?: OmitTypeWithRequired<{ initial?: boolean }>","options?: OmitTypeWithRequired<{ default?: string; placeholder?: string }>","fileTree: Record<\n string,\n string | Record<string, string | Record<string, string>>\n >","base: string"],"sources":["../package.json","../src/cli.ts"],"sourcesContent":["{\n \"name\": \"mioku\",\n \"type\": \"module\",\n \"version\": \"0.8.18\",\n \"packageManager\": \"bun@1.2.0\",\n \"description\": \"Mioku - Plugin framework extended from mioki for NapCat OneBot v11\",\n \"keywords\": [\n \"onebot\",\n \"framework\",\n \"bot\",\n \"mioki\",\n \"mioku\"\n ],\n \"bin\": {\n \"mioku\": \"./dist/cli.js\"\n },\n \"engines\": {\n \"node\": \">= 22.18.0\"\n },\n \"homepage\": \"https://github.com/jerryplusy/mioku#readme\",\n \"files\": [\n \"dist\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/jerryplusy/mioku/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/jerryplusy/mioku.git\",\n \"directory\": \"src/packages/mioku\"\n },\n \"scripts\": {\n \"dev\": \"tsdown -w\",\n \"build\": \"tsdown\"\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 \"mioki\": \"^0.16.0\",\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 \"openai\": \"^4.0.0\",\n \"puppeteer\": \"^23.10.0\",\n \"pretty-ms\": \"^9.3.0\",\n \"string2argv\": \"^1.0.2\",\n \"systeminformation\": \"^5.30.7\",\n \"lodash\": \"^4.17.21\"\n },\n \"devDependencies\": {\n \"@types/lodash\": \"^4.17.0\",\n \"@types/node\": \"^22.0.0\",\n \"@types/puppeteer\": \"^7.0.4\",\n \"tsdown\": \"^0.11.0\",\n \"typescript\": \"^5.8.0\"\n }\n}\n","#!/usr/bin/env node\n\nimport fs, { readFileSync } from \"node:fs\";\nimport { execFileSync } from \"node:child_process\";\nimport mri from \"mri\";\nimport path from \"node:path\";\nimport dedent from \"dedent\";\nimport consola from \"consola\";\nimport { version } from \"../package.json\";\nconst DEFAULT_PACKAGES = [\n \"mioku\",\n \"mioku-plugin-boot\",\n \"mioku-plugin-help\",\n \"mioku-plugin-chat\",\n \"mioku-service-config\",\n \"mioku-service-ai\",\n \"mioku-service-screenshot\",\n \"mioku-service-help\",\n];\n\nconst PLUGIN_PREFIX = \"mioku-plugin-\";\nconst SERVICE_PREFIX = \"mioku-service-\";\n\nconst args = process.argv.slice(2);\n\nfunction run(\n cmd: string,\n args: string[] = [],\n options: Parameters<typeof execFileSync>[2] = {},\n) {\n return execFileSync(cmd, args, {\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n ...options,\n });\n}\n\nasync 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\ninterface CliOptions {\n name?: string;\n protocol?: string;\n host?: string;\n port?: number;\n token?: string;\n prefix?: string;\n owners?: string;\n admins?: string;\n help?: boolean;\n version?: boolean;\n \"use-npm-mirror\"?: boolean;\n}\n\nfunction hasCommand(cmd: string): boolean {\n try {\n execFileSync(cmd, [\"--version\"], {\n stdio: \"ignore\",\n shell: process.platform === \"win32\",\n });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction findNpmPath(): string | null {\n if (process.platform !== \"win32\") {\n return \"npm\";\n }\n\n const candidates = [\n \"npm.cmd\",\n \"npm.exe\",\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 for (const candidate of candidates) {\n try {\n execFileSync(candidate, [\"--version\"], {\n stdio: \"ignore\",\n shell: true,\n });\n return candidate;\n } catch {}\n }\n\n try {\n const result = execFileSync(\"where\", [\"npm\"], {\n encoding: \"utf-8\",\n shell: true,\n });\n\n const lines = result\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean);\n\n const cmdPath = lines.find((line) => line.endsWith(\".cmd\"));\n return cmdPath || lines[0] || null;\n } catch {\n return null;\n }\n}\n\nfunction ensurePackageManager() {\n if (hasCommand(\"bun\")) return;\n\n console.log(\"安装 bun...\");\n\n const npmPath = findNpmPath();\n if (!npmPath) {\n consola.error(\"未找到 npm,请确保 Node.js 已安装并包含 npm\");\n process.exit(1);\n }\n\n run(npmPath, [\"install\", \"-g\", \"bun\"]);\n}\n\nfunction getAddCommand(packages: string[]): [string, string[]] {\n return [\"bun\", [\"add\", ...packages]];\n}\n\nfunction normalizePackageName(input: string): string {\n if (input.startsWith(PLUGIN_PREFIX) || input.startsWith(SERVICE_PREFIX)) {\n return input;\n }\n if (input.startsWith(\"mioku-\")) {\n // 已经是完整名称,如 mioku-plugin-xxx\n return input;\n }\n // 默认当作 plugin 处理\n return `${PLUGIN_PREFIX}${input}`;\n}\n\nfunction 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\nfunction execAdd(packages: string[], cwd?: string) {\n const [cmd, args] = getAddCommand(packages);\n\n console.log(`执行: ${cmd} ${args.join(\" \")}`);\n\n run(cmd, args, {\n cwd,\n });\n}\n\nasync function installPackage(name: string, cwd?: string) {\n const normalized = normalizePackageName(name);\n const type = detectType(normalized);\n if (type === \"unknown\") {\n consola.error(`无法识别的包类型: ${name}`);\n return false;\n }\n try {\n execAdd([normalized], cwd);\n consola.success(`已安装 ${normalized}`);\n return true;\n } catch {\n consola.error(`安装失败: ${normalized}`);\n return false;\n }\n}\n\nasync function updatePackage(name: string, cwd?: string) {\n try {\n console.log(`执行: bun update ${name}`);\n\n run(\"bun\", [\"update\", name], {\n cwd,\n });\n consola.success(`已更新 ${name}`);\n return true;\n } catch {\n consola.error(`更新失败: ${name}`);\n return false;\n }\n}\n\nasync function checkUpdates(packages: string[], cwd?: string) {\n try {\n const output = execFileSync(\"bun\", [\"pm\", \"outdated\", \"--json\"], {\n cwd,\n encoding: \"utf-8\",\n stdio: \"pipe\",\n shell: process.platform === \"win32\",\n });\n if (!output.trim()) {\n consola.info(\"所有依赖已是最新版本\");\n return [];\n }\n const outdated = JSON.parse(output);\n const updates: string[] = [];\n for (const pkg of packages) {\n if (outdated[pkg]) {\n updates.push(\n `${pkg}: ${outdated[pkg].current} → ${outdated[pkg].latest}`,\n );\n }\n }\n return updates;\n } catch {\n return [];\n }\n}\n\nasync function getInstalledPackages(cwd: string): Promise<string[]> {\n try {\n const pkgPath = path.join(cwd, \"package.json\");\n const content = readFileSync(pkgPath, \"utf-8\");\n const pkg = JSON.parse(content);\n const deps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n return Object.keys(deps).filter((k) => k.startsWith(\"mioku-\"));\n } catch {\n return [];\n }\n}\n\n(async () => {\n const cli = mri<CliOptions>(args, {\n alias: {\n v: \"version\",\n h: \"help\",\n },\n });\n\n const helpInfo = 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 const [cmd, ...cmdArgs] = args;\n\n switch (cmd) {\n case \"install\": {\n ensurePackageManager();\n const cwd = process.cwd();\n const type = cmdArgs[0];\n const name = cmdArgs[1];\n\n if (!type || !name) {\n consola.error(\n \"请指定类型和名称: mioku install plugin <名称> 或 mioku install service <名称>\",\n );\n console.log(helpInfo);\n process.exitCode = 1;\n return;\n }\n\n if (type !== \"plugin\" && type !== \"service\") {\n consola.error(`无效的类型 \"${type}\",请使用 plugin 或 service`);\n console.log(helpInfo);\n process.exitCode = 1;\n return;\n }\n\n const prefix = type === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const normalized = `${prefix}${name}`;\n const success = await installPackage(normalized, cwd);\n process.exitCode = success ? 0 : 1;\n return;\n }\n\n case \"update\": {\n ensurePackageManager();\n const cwd = process.cwd();\n\n if (!cmdArgs.length || cmdArgs[0] === \"check\") {\n // 检查更新\n const packages = await getInstalledPackages(cwd);\n const updates = await checkUpdates(packages, cwd);\n if (updates.length === 0) {\n consola.info(\"所有 mioku 依赖已是最新版本\");\n } else {\n console.log(\"\\n可用更新:\");\n updates.forEach((u) => consola.warn(` ${u}`));\n console.log(\"\\n运行 npx mioku update all 更新所有包\");\n }\n process.exitCode = 0;\n return;\n }\n\n const target = cmdArgs[0];\n\n if (target === \"all\") {\n // 先并发检查所有包的更新\n const packages = await getInstalledPackages(cwd);\n if (packages.length === 0) {\n consola.info(\"未找到 mioku 相关依赖\");\n process.exitCode = 0;\n return;\n }\n\n const updates = await checkUpdates(packages, cwd);\n if (updates.length === 0) {\n consola.info(\"所有 mioku 依赖已是最新版本\");\n process.exitCode = 0;\n return;\n }\n\n console.log(\"\\n可用更新:\");\n updates.forEach((u) => consola.warn(` ${u}`));\n\n const confirm = await confirm(`确认更新以上 ${updates.length} 个包?`);\n if (!confirm) {\n gracefullyExit();\n }\n\n // 并发更新所有包\n await Promise.all(\n packages.map((pkg) => updatePackage(pkg, cwd)),\n );\n process.exitCode = 0;\n return;\n }\n\n if (target === \"self\") {\n await updatePackage(\"mioku\", cwd);\n process.exitCode = 0;\n return;\n }\n\n if (target === \"plugin\" || target === \"service\") {\n // update plugin/service [name]\n const name = cmdArgs[1];\n if (!name) {\n // 更新所有指定类型的包\n const packages = await getInstalledPackages(cwd);\n const prefix = target === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const filtered = packages.filter((p) => p.startsWith(prefix));\n if (filtered.length === 0) {\n consola.info(`未找到 ${prefix}* 相关依赖`);\n process.exitCode = 0;\n return;\n }\n for (const pkg of filtered) {\n await updatePackage(pkg, cwd);\n }\n } else {\n const prefix = target === \"plugin\" ? PLUGIN_PREFIX : SERVICE_PREFIX;\n const normalized = name.startsWith(prefix)\n ? name\n : `${prefix}${name}`;\n await updatePackage(normalized, cwd);\n }\n process.exitCode = 0;\n return;\n }\n\n // update xxx - 更新指定包,自动识别前缀\n const packages = await getInstalledPackages(cwd);\n if (packages.includes(target)) {\n await updatePackage(target, cwd);\n } else {\n const normalized = normalizePackageName(target);\n await updatePackage(normalized, cwd);\n }\n process.exitCode = 0;\n return;\n }\n\n default: {\n // 原始交互式项目创建\n const cli = mri<CliOptions>(args, {\n alias: {\n v: \"version\",\n h: \"help\",\n },\n });\n\n switch (true) {\n case cli.version:\n console.log(`v${version}`);\n process.exitCode = 0;\n return;\n // fall through\n\n case cli.help:\n console.log(helpInfo);\n process.exitCode = 0;\n return;\n // fall through\n\n default:\n break;\n }\n\n const name = await input(\"请输入项目名称\", {\n default: \"mioku-bot\",\n placeholder: \"mioku-bot\",\n required: true,\n });\n\n const owners = await input(\n \"请输入主人 QQ (最高权限,英文逗号分隔,必填)\",\n {\n placeholder: \"请输入\",\n default: \"\",\n required: true,\n },\n );\n\n const host = await input(\"请输入 NapCat WS 主机\", {\n default: \"localhost\",\n placeholder: \"localhost\",\n required: true,\n });\n\n const port = parseInt(\n await input(\"请输入 NapCat WS 端口\", {\n default: \"3001\",\n placeholder: \"3001\",\n required: true,\n }),\n );\n\n const token = await input(\"请输入 NapCat WS Token(如无则留空)\", {\n placeholder: \"请输入\",\n });\n\n ensurePackageManager();\n\n const pkgJson = dedent(`\n {\n \"name\": \"${name}\",\n \"private\": true,\n \"type\": \"module\",\n \"dependencies\": {},\n \"mioki\": {\n \"prefix\": \"#\",\n \"owners\": [${String(owners)\n .split(\",\")\n .map((o) => o.trim())\n .join(\", \")}],\n \"admins\": [],\n \"plugins\": [\"boot\", \"help\", \"chat\", \"demo\"],\n \"log_level\": \"info\",\n \"online_push\": false,\n \"error_push\": false,\n \"napcat\": [\n {\n \"protocol\": \"ws\",\n \"port\": ${port},\n \"host\": \"${host}\",\n \"token\": \"${token}\"\n }\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, any> = {\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 installWebui = await confirm(\"是否安装 WebUI 管理面板?(建议安装)\", {\n initial: true,\n });\n\n await createNewProject(name, fileTree, installWebui);\n\n console.log(\"\\n若需启动机器人,请运行:\");\n console.log(\" cd\", name);\n console.log(\" bun run start\");\n }\n }\n})();\n\nasync function createNewProject(name: string, fileTree: Record<string, any>, installWebui = false) {\n const projectName = name;\n const projectPath = withRoot(`./${projectName}`);\n\n if (fs.existsSync(projectPath)) {\n const overwrite = await confirm(`项目 ${projectName} 已存在,是否覆盖?`);\n\n if (!overwrite) {\n gracefullyExit();\n }\n\n if (projectPath === process.cwd()) {\n if (fs.readdirSync(projectPath).length !== 0) {\n const confirmOver = await confirm(\n \"项目路径与当前路径相同,将删除当前目录下所有内容再创建,是否继续?\",\n );\n if (!confirmOver) {\n gracefullyExit();\n }\n }\n }\n\n await rmrf(projectPath);\n }\n\n fs.mkdirSync(projectPath, { recursive: true });\n\n makeFileTree(fileTree, projectPath);\n\n console.log(`项目 ${projectName} 创建成功!`);\n\n const packages = installWebui ? DEFAULT_PACKAGES : DEFAULT_PACKAGES.filter(p => p !== \"mioku-service-webui\");\n const [cmd, args] = getAddCommand(packages);\n console.log(`正在安装 Mioku 依赖: ${cmd} ${args.join(\" \")}`);\n run(cmd, args, {\n cwd: projectPath,\n });\n}\n\nfunction gracefullyExit() {\n console.log(\"Bye!\");\n process.exit(0);\n}\n\nfunction withRoot(_path: string) {\n return path.resolve(process.cwd(), _path);\n}\n\ntype OmitTypeWithRequired<T> = Omit<T, \"type\" | \"required\"> & {\n required?: boolean;\n};\n\nasync function confirm(\n message: string,\n options?: OmitTypeWithRequired<{ initial?: boolean }>,\n) {\n return consola.prompt(message, {\n type: \"confirm\",\n cancel: \"reject\",\n ...options,\n });\n}\n\nasync function input(\n message: string,\n options?: OmitTypeWithRequired<{ default?: string; placeholder?: string }>,\n) {\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\nfunction makeFileTree(\n fileTree: Record<\n string,\n string | Record<string, string | Record<string, string>>\n >,\n base: string,\n) {\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)) {\n fs.mkdirSync(subPath, { recursive: true });\n }\n for (const [subName, subContent] of Object.entries(content)) {\n if (typeof subContent === \"object\") {\n makeFileTree(\n subContent as typeof fileTree,\n path.join(subPath, subName),\n );\n } else {\n fs.writeFileSync(`${subPath}/${subName}`, subContent);\n }\n }\n } else {\n const filePath = `${base}/${name}`;\n const dirname = path.dirname(filePath);\n if (!fs.existsSync(dirname)) {\n fs.mkdirSync(dirname, { recursive: true });\n }\n fs.writeFileSync(filePath, content);\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -82,7 +82,8 @@ async function ensurePluginLink(runtimePluginsDir, metadata) {
|
|
|
82
82
|
logger.warn(`[plugin-linker] Plugin target missing, skip linking ${metadata.name}: ${targetPath}`);
|
|
83
83
|
return false;
|
|
84
84
|
}
|
|
85
|
-
await fs_promises.symlink(
|
|
85
|
+
if (process.platform === "win32") await fs_promises.symlink(targetPath, linkPath, "junction");
|
|
86
|
+
else await fs_promises.symlink(relativeSymlinkTarget(linkPath, targetPath), linkPath, "dir");
|
|
86
87
|
return true;
|
|
87
88
|
}
|
|
88
89
|
async function prepareRuntimePluginLinks(plugins, runtimePluginsDir = path.resolve(process.cwd(), DEFAULT_RUNTIME_PLUGINS_DIR)) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["fallbackLogger: MiokuLogger","activeLogger: MiokuLogger","logger: MiokuLogger | undefined","logger","logger: MiokuLogger","pathExists","filePath: string","entryPath: string","linkPath: string","targetPath: string","runtimePluginsDir: string","metadata: PluginMetadata","plugins: PluginMetadata[]","linkedNames: string[]","pathExists","filePath: string","miokuConfig: any","discovered: PluginMetadata[]","pluginsDir: string","entryPath: string","name: string","pluginPath: string","packageJson: any","metadata: PluginMetadata","pathExists","filePath: string","miokuConfig: any","discovered: ServiceMetadata[]","servicesDir: string","name: string","servicePath: string","metadata: ServiceMetadata","error: any","requiredServices: Set<string>","missing: string[]","ctx: MiokiContext","service: MiokuService","filePath: string","value: any","moduleExports: any","pluginPath: string","ctx: MiokiContext","error: any","pluginName: string","serviceName: string","runtimeState: PluginRuntimeState","pluginName: string","state: Record<string, any>","plugin: T","options: MiokuStartOptions","logger","miokuConfig: any"],"sources":["../src/core/logger.ts","../src/core/plugin-linker.ts","../src/core/plugin-manager.ts","../src/core/service-manager.ts","../src/core/plugin-artifact-registry.ts","../src/service-types.ts","../src/core/data-paths.ts","../src/core/plugin-runtime-state.ts","../src/index.ts"],"sourcesContent":["type LogMethod = (...args: unknown[]) => void;\n\nexport interface MiokuLogger {\n error: LogMethod;\n warn: LogMethod;\n info: LogMethod;\n debug: LogMethod;\n trace?: LogMethod;\n}\n\nconst fallbackLogger: MiokuLogger = {\n error: (...args) => console.error(...args),\n warn: (...args) => console.warn(...args),\n info: (...args) => console.info(...args),\n debug: (...args) => console.debug(...args),\n trace: (...args) => console.debug(...args),\n};\n\nlet activeLogger: MiokuLogger = fallbackLogger;\n\nexport function setMiokuLogger(logger: MiokuLogger | undefined): void {\n activeLogger = logger || fallbackLogger;\n}\n\nexport function getMiokuLogger(): MiokuLogger {\n return activeLogger;\n}\n\nexport const logger: MiokuLogger = {\n error: (...args) => activeLogger.error(...args),\n warn: (...args) => activeLogger.warn(...args),\n info: (...args) => activeLogger.info(...args),\n debug: (...args) => activeLogger.debug(...args),\n trace: (...args) => activeLogger.trace?.(...args),\n};\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport type { PluginMetadata } from \"./types\";\nimport { logger } from \"./logger\";\n\nexport const DEFAULT_RUNTIME_PLUGINS_DIR = \".mioku/plugins\";\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function removeIfBrokenSymlink(entryPath: string): Promise<\"ok\" | \"blocked\" | \"removed\"> {\n let stat;\n try {\n stat = await fs.lstat(entryPath);\n } catch {\n return \"removed\";\n }\n\n if (!stat.isSymbolicLink()) {\n return \"blocked\";\n }\n\n try {\n await fs.realpath(entryPath);\n return \"ok\";\n } catch {\n await fs.rm(entryPath, { force: true });\n logger.warn(`[plugin-linker] Removed broken plugin link: ${entryPath}`);\n return \"removed\";\n }\n}\n\nfunction relativeSymlinkTarget(linkPath: string, targetPath: string): string {\n const relativePath = path.relative(path.dirname(linkPath), targetPath);\n return relativePath || \".\";\n}\n\nasync function ensurePluginLink(\n runtimePluginsDir: string,\n metadata: PluginMetadata,\n): Promise<boolean> {\n const linkPath = path.join(runtimePluginsDir, metadata.name);\n const targetPath = metadata.path;\n\n let stat;\n try {\n stat = await fs.lstat(linkPath);\n } catch {\n stat = null;\n }\n\n if (stat?.isSymbolicLink()) {\n try {\n const currentTarget = await fs.realpath(linkPath);\n const expectedTarget = await fs.realpath(targetPath);\n if (currentTarget === expectedTarget) {\n return true;\n }\n await fs.rm(linkPath, { force: true });\n logger.info(`[plugin-linker] Rebuilding plugin link: ${metadata.name}`);\n } catch {\n await fs.rm(linkPath, { force: true });\n logger.warn(`[plugin-linker] Removed broken plugin link: ${linkPath}`);\n }\n } else if (stat) {\n logger.warn(\n `[plugin-linker] ${linkPath} exists and is not a symlink, skip linking ${metadata.name}`,\n );\n return false;\n }\n\n if (!(await pathExists(targetPath))) {\n logger.warn(\n `[plugin-linker] Plugin target missing, skip linking ${metadata.name}: ${targetPath}`,\n );\n return false;\n }\n\n await fs.symlink(relativeSymlinkTarget(linkPath, targetPath), linkPath, \"dir\");\n return true;\n}\n\nexport async function prepareRuntimePluginLinks(\n plugins: PluginMetadata[],\n runtimePluginsDir = path.resolve(process.cwd(), DEFAULT_RUNTIME_PLUGINS_DIR),\n): Promise<string[]> {\n await fs.mkdir(runtimePluginsDir, { recursive: true });\n\n const discoveredNames = new Set(plugins.map((plugin) => plugin.name));\n const entries = await fs.readdir(runtimePluginsDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = path.join(runtimePluginsDir, entry.name);\n const symlinkState = await removeIfBrokenSymlink(entryPath);\n if (symlinkState !== \"ok\") {\n continue;\n }\n\n if (entry.isSymbolicLink() && !discoveredNames.has(entry.name)) {\n await fs.rm(entryPath, { force: true });\n logger.info(`[plugin-linker] Removed stale plugin link: ${entry.name}`);\n }\n }\n\n const linkedNames: string[] = [];\n for (const metadata of plugins) {\n if (await ensurePluginLink(runtimePluginsDir, metadata)) {\n linkedNames.push(metadata.name);\n }\n }\n\n return linkedNames;\n}\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport { mkdirSync } from \"fs\";\nimport type { PluginMetadata } from \"./types\";\nimport { DEFAULT_RUNTIME_PLUGINS_DIR } from \"./plugin-linker\";\nimport { logger } from \"./logger\";\n\nconst PLUGIN_MANAGER_SYMBOL = Symbol.for(\"mioku.plugin-manager\");\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * 插件管理器\n *\n * Discover and manage plugins from both local directories and node_modules.\n */\nexport class PluginManager {\n private pluginMetadata: Map<string, PluginMetadata> = new Map();\n\n public static getInstance(): PluginManager {\n const g = global as any;\n if (!g[PLUGIN_MANAGER_SYMBOL]) {\n g[PLUGIN_MANAGER_SYMBOL] = new PluginManager();\n }\n return g[PLUGIN_MANAGER_SYMBOL];\n }\n\n async discoverPlugins(miokuConfig: any = {}): Promise<PluginMetadata[]> {\n // Resolve pluginsDir dynamically so it uses the current cwd\n const configuredPluginsDir = miokuConfig.plugins_dir;\n const pluginsDir =\n configuredPluginsDir && configuredPluginsDir !== DEFAULT_RUNTIME_PLUGINS_DIR\n ? path.resolve(process.cwd(), configuredPluginsDir)\n : path.resolve(process.cwd(), \"plugins\");\n\n this.pluginMetadata.clear();\n\n // Ensure plugins directory exists\n if (!(await pathExists(pluginsDir))) {\n mkdirSync(pluginsDir, { recursive: true });\n }\n\n const discovered: PluginMetadata[] = [];\n\n // Discover from local plugins/ directory\n if (await pathExists(pluginsDir)) {\n const localPlugins = await this.discoverFromDir(pluginsDir);\n discovered.push(...localPlugins);\n }\n\n // Discover from node_modules (mioku-plugin-* prefix)\n const nodeModulesPlugins = await this.discoverFromNodeModules();\n discovered.push(...nodeModulesPlugins);\n\n logger.info(`O.o 发现了 ${this.pluginMetadata.size} 个插件`);\n return Array.from(this.pluginMetadata.values());\n }\n\n private async discoverFromDir(pluginsDir: string): Promise<PluginMetadata[]> {\n const discovered: PluginMetadata[] = [];\n\n try {\n const entries = await fs.readdir(pluginsDir, { withFileTypes: true });\n for (const entry of entries) {\n const pluginPath = path.join(pluginsDir, entry.name);\n const metadataPath = await this.resolveDirectoryPath(pluginPath);\n if (!metadataPath) continue;\n\n const metadata = await this.loadPluginMetadata(entry.name, pluginPath);\n if (metadata) {\n discovered.push(metadata);\n this.pluginMetadata.set(metadata.name, metadata);\n }\n }\n } catch (error) {\n logger.error(`扫描插件目录失败: ${error}`);\n }\n\n return discovered;\n }\n\n private async discoverFromNodeModules(): Promise<PluginMetadata[]> {\n const discovered: PluginMetadata[] = [];\n const nodeModulesPath = path.resolve(process.cwd(), \"node_modules\");\n\n if (!(await pathExists(nodeModulesPath))) {\n return discovered;\n }\n\n try {\n const entries = await fs.readdir(nodeModulesPath, { withFileTypes: true });\n for (const entry of entries) {\n // Check for mioku-plugin-* prefix (don't check isDirectory - symlinks return false)\n if (!entry.name.startsWith(\"mioku-plugin-\")) {\n continue;\n }\n\n const pluginName = entry.name.replace(/^mioku-plugin-/, \"\");\n const pluginPath = path.join(nodeModulesPath, entry.name);\n const metadata = await this.loadPluginMetadata(pluginName, pluginPath);\n if (metadata) {\n discovered.push(metadata);\n this.pluginMetadata.set(metadata.name, metadata);\n }\n }\n } catch (error) {\n logger.debug(`扫描 node_modules 插件失败: ${error}`);\n }\n\n return discovered;\n }\n\n private async resolveDirectoryPath(entryPath: string): Promise<string | null> {\n try {\n const stat = await fs.stat(entryPath);\n return stat.isDirectory() ? entryPath : null;\n } catch {\n return null;\n }\n }\n\n private async loadPluginMetadata(\n name: string,\n pluginPath: string,\n ): Promise<PluginMetadata | null> {\n // Resolve symlinks to get actual path\n let resolvedPath = pluginPath;\n try {\n resolvedPath = await fs.realpath(pluginPath);\n } catch {\n // Not a symlink or doesn't exist, use original path\n }\n\n const packageJsonPath = path.join(resolvedPath, \"package.json\");\n\n let packageJson: any = null;\n try {\n const content = await fs.readFile(packageJsonPath, \"utf-8\");\n packageJson = JSON.parse(content);\n } catch {\n // File doesn't exist or can't be read - plugin uses defaults\n }\n\n const metadata: PluginMetadata = {\n name,\n version: packageJson?.version || \"0.0.0\",\n description: packageJson?.description,\n path: resolvedPath,\n packageJson,\n config: packageJson?.mioku || {},\n };\n return metadata;\n }\n\n collectRequiredServices(): Set<string> {\n const services = new Set<string>();\n for (const metadata of this.pluginMetadata.values()) {\n if (metadata.config.services) {\n metadata.config.services.forEach((s) => services.add(s));\n }\n }\n return services;\n }\n\n getPluginMetadata(name: string): PluginMetadata | undefined {\n return this.pluginMetadata.get(name);\n }\n\n getAllMetadata(): PluginMetadata[] {\n return Array.from(this.pluginMetadata.values());\n }\n\n reset(): void {\n this.pluginMetadata.clear();\n }\n}\n\nexport default PluginManager.getInstance();\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport { existsSync, mkdirSync } from \"fs\";\nimport type { MiokiContext } from \"mioki\";\nimport type { ServiceMetadata, MiokuService } from \"./types\";\nimport { logger } from \"./logger\";\n\nconst SERVICE_MANAGER_SYMBOL = Symbol.for(\"mioku.service-manager\");\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * 服务管理器\n */\nexport class ServiceManager {\n private services: Map<string, MiokuService> = new Map();\n private serviceMetadata: Map<string, ServiceMetadata> = new Map();\n private servicesDir: string = \"services\";\n\n public static getInstance(): ServiceManager {\n const g = global as any;\n if (!g[SERVICE_MANAGER_SYMBOL]) {\n g[SERVICE_MANAGER_SYMBOL] = new ServiceManager();\n }\n return g[SERVICE_MANAGER_SYMBOL];\n }\n\n async discoverServices(miokuConfig: any = {}): Promise<ServiceMetadata[]> {\n // Use services_dir from mioku config if provided, otherwise default to \"services\" in project root\n if (miokuConfig.services_dir) {\n this.servicesDir = path.resolve(process.cwd(), miokuConfig.services_dir);\n } else {\n this.servicesDir = path.resolve(process.cwd(), \"services\");\n }\n\n const discovered: ServiceMetadata[] = [];\n this.serviceMetadata.clear();\n\n // Discover from local services/ directory\n if (existsSync(this.servicesDir)) {\n const localServices = await this.discoverFromDir(this.servicesDir);\n discovered.push(...localServices);\n } else {\n // Ensure the directory exists for user services\n mkdirSync(this.servicesDir, { recursive: true });\n }\n\n // Discover builtin services (config, ai, screenshot, webui)\n await this.loadBuiltinServices();\n\n logger.info(`o.O 发现了 ${this.serviceMetadata.size} 个服务`);\n return Array.from(this.serviceMetadata.values());\n }\n\n private async discoverFromDir(servicesDir: string): Promise<ServiceMetadata[]> {\n const discovered: ServiceMetadata[] = [];\n\n try {\n const entries = await fs.readdir(servicesDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const servicePath = path.join(servicesDir, entry.name);\n const metadata = await this.loadServiceMetadata(entry.name, servicePath);\n if (metadata) {\n discovered.push(metadata);\n this.serviceMetadata.set(entry.name, metadata);\n }\n }\n } catch (error) {\n logger.error(`扫描服务目录失败: ${error}`);\n }\n\n return discovered;\n }\n\n private async loadServiceMetadata(\n name: string,\n servicePath: string,\n ): Promise<ServiceMetadata | null> {\n // Resolve symlinks to get actual path\n let resolvedPath = servicePath;\n try {\n resolvedPath = await fs.realpath(servicePath);\n } catch {\n // Not a symlink or doesn't exist, use original path\n }\n\n const packageJsonPath = path.join(resolvedPath, \"package.json\");\n\n if (!(await pathExists(packageJsonPath))) {\n return null;\n }\n\n try {\n const packageJson = JSON.parse(\n await fs.readFile(packageJsonPath, \"utf-8\"),\n );\n const metadata: ServiceMetadata = {\n name,\n version: packageJson.version || \"0.0.0\",\n description: packageJson.description,\n path: resolvedPath,\n packageJson,\n };\n return metadata;\n } catch (error: any) {\n logger.error(`解析服务 ${name} 失败: ${error.message}`);\n return null;\n }\n }\n\n /**\n * Load built-in services from the package\n */\n private async loadBuiltinServices(): Promise<void> {\n // Discover from node_modules (mioku-service-* prefix)\n await this.discoverFromNodeModules();\n }\n\n private async discoverFromNodeModules(): Promise<void> {\n const nodeModulesPath = path.resolve(process.cwd(), \"node_modules\");\n\n if (!(await pathExists(nodeModulesPath))) {\n return;\n }\n\n try {\n const entries = await fs.readdir(nodeModulesPath, { withFileTypes: true });\n for (const entry of entries) {\n // Don't check isDirectory - symlinks return false\n if (!entry.name.startsWith(\"mioku-service-\")) {\n continue;\n }\n\n const serviceName = entry.name.replace(/^mioku-service-/, \"\");\n const servicePath = path.join(nodeModulesPath, entry.name);\n const metadata = await this.loadServiceMetadata(serviceName, servicePath);\n if (metadata) {\n this.serviceMetadata.set(serviceName, metadata);\n }\n }\n } catch (error) {\n logger.debug(`扫描 node_modules 服务失败: ${error}`);\n }\n }\n\n async checkMissingServices(requiredServices: Set<string>): Promise<string[]> {\n const missing: string[] = [];\n for (const serviceName of requiredServices) {\n if (!this.serviceMetadata.has(serviceName)) {\n missing.push(serviceName);\n }\n }\n return missing;\n }\n\n async loadAllServices(ctx: MiokiContext): Promise<void> {\n const allMetadata = Array.from(this.serviceMetadata.values());\n logger.info(`O.o 准备加载 ${allMetadata.length} 个服务...`);\n\n for (const metadata of allMetadata) {\n await this.loadService(metadata, ctx);\n }\n }\n\n private async loadService(\n metadata: ServiceMetadata,\n ctx: MiokiContext,\n ): Promise<boolean> {\n try {\n const indexPath = path.join(metadata.path, \"index.ts\");\n const indexJsPath = path.join(metadata.path, \"index.js\");\n const indexExists = await pathExists(indexPath);\n const indexJsExists = await pathExists(indexJsPath);\n const entryPoint = indexExists ? indexPath : indexJsPath;\n\n if (!entryPoint || (!indexExists && !indexJsExists)) {\n logger.error(`服务 ${metadata.name} 入口丢失`);\n return false;\n }\n\n let importPath = entryPoint;\n if (process.platform === \"win32\") {\n importPath = \"file:///\" + entryPoint.replace(/\\\\/g, \"/\");\n }\n\n const serviceModule = await import(importPath);\n const service: MiokuService = serviceModule.default || serviceModule;\n\n if (!service || typeof service.init !== \"function\") return false;\n\n await service.init();\n if (service.api) {\n if (!(ctx as any).services) (ctx as any).services = {};\n (ctx as any).services[metadata.name] = service.api;\n }\n\n this.services.set(metadata.name, service);\n return true;\n } catch (error: any) {\n logger.error(`加载服务 ${metadata.name} 失败: ${error.message}`);\n return false;\n }\n }\n\n /**\n * Register a builtin service directly\n */\n registerBuiltinService(name: string, service: MiokuService): void {\n this.services.set(name, service);\n }\n\n /**\n * Get a loaded service\n */\n getService(name: string): MiokuService | undefined {\n return this.services.get(name);\n }\n\n async disposeAll(): Promise<void> {\n for (const [name, service] of this.services) {\n if (service.dispose) await service.dispose();\n }\n this.services.clear();\n }\n\n reset(): void {\n this.services.clear();\n this.serviceMetadata.clear();\n }\n}\n\nexport default ServiceManager.getInstance();\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport type { MiokiContext } from \"mioki\";\nimport type { AIService } from \"../types\";\nimport type { HelpService } from \"../service-types\";\nimport type { AISkill } from \"./types\";\nimport pluginManager from \"./plugin-manager\";\nimport { logger } from \"./logger\";\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction toImportPath(filePath: string): string {\n if (process.platform === \"win32\") {\n return \"file:///\" + filePath.replace(/\\\\/g, \"/\");\n }\n return filePath;\n}\n\nfunction isAISkill(value: any): value is AISkill {\n return (\n value &&\n typeof value === \"object\" &&\n typeof value.name === \"string\" &&\n Array.isArray(value.tools)\n );\n}\n\nfunction extractSkills(moduleExports: any): AISkill[] {\n const candidates = [\n moduleExports?.default,\n moduleExports?.skills,\n moduleExports,\n ];\n\n for (const candidate of candidates) {\n if (Array.isArray(candidate)) {\n return candidate.filter(isAISkill);\n }\n if (isAISkill(candidate)) {\n return [candidate];\n }\n }\n\n return [];\n}\n\nasync function resolveSkillsEntry(pluginPath: string): Promise<string | null> {\n const tsPath = path.join(pluginPath, \"skills.ts\");\n if (await pathExists(tsPath)) {\n return tsPath;\n }\n\n const jsPath = path.join(pluginPath, \"skills.js\");\n if (await pathExists(jsPath)) {\n return jsPath;\n }\n\n return null;\n}\n\n/**\n * Auto-register plugin help manifests and AI skills\n */\nexport async function registerPluginArtifacts(\n ctx: MiokiContext,\n): Promise<void> {\n const enabledPlugins = new Set<string>(\n Array.isArray((ctx as any).botConfig?.plugins)\n ? (ctx as any).botConfig.plugins\n : [],\n );\n const pluginMetadata = pluginManager\n .getAllMetadata()\n .filter((metadata) =>\n enabledPlugins.size > 0 ? enabledPlugins.has(metadata.name) : true,\n );\n\n const helpService = ctx.services?.help as HelpService | undefined;\n const aiService = ctx.services?.ai as AIService | undefined;\n\n if (helpService) {\n let helpCount = 0;\n for (const metadata of pluginMetadata) {\n if (!metadata.config.help) {\n continue;\n }\n helpService.registerHelp(metadata.name, metadata.config.help);\n helpCount += 1;\n }\n logger.info(`[plugin-artifacts] Registered ${helpCount} help manifest(s)`);\n }\n\n if (!aiService) {\n return;\n }\n\n let skillCount = 0;\n for (const metadata of pluginMetadata) {\n const skillsEntry = await resolveSkillsEntry(metadata.path);\n if (!skillsEntry) {\n continue;\n }\n\n try {\n const moduleExports = await import(toImportPath(skillsEntry));\n const skills = extractSkills(moduleExports);\n\n if (skills.length === 0) {\n logger.warn(\n `[plugin-artifacts] Plugin ${metadata.name} has ${path.basename(skillsEntry)} but exported no valid skill`,\n );\n continue;\n }\n\n for (const skill of skills) {\n aiService.registerSkill(skill);\n skillCount += 1;\n }\n } catch (error: any) {\n logger.error(\n `[plugin-artifacts] Failed to load skills for plugin ${metadata.name}: ${error?.message || error}`,\n );\n }\n }\n\n logger.info(`[plugin-artifacts] Registered ${skillCount} skill(s)`);\n}\n","/**\n * Service interface definitions for built-in services\n * These are used for type annotations in plugins\n */\n\n// ============ Core Service Interfaces ============\n\n// Config Service\nexport interface ConfigService {\n registerConfig(pluginName: string, configName: string, initialConfig: any): Promise<boolean>;\n updateConfig(pluginName: string, configName: string, updates: any): Promise<boolean>;\n getConfig(pluginName: string, configName: string): Promise<any>;\n getPluginConfigs(pluginName: string): Promise<Record<string, any>>;\n onConfigChange(pluginName: string, configName: string, callback: (newConfig: any) => void): () => void;\n}\n\n// Screenshot Service\nexport interface ScreenshotService {\n screenshot(html: string, options?: any): Promise<string>;\n screenshotMarkdown(markdownContent: string, options?: any): Promise<string>;\n screenshotFromUrl(url: string, options?: any): Promise<string>;\n cleanupTemp(olderThanMs?: number): Promise<number>;\n}\n\n// Help Service\nexport interface HelpService {\n registerHelp(pluginName: string, help: any): void;\n getHelp(pluginName: string): any;\n getAllHelp(): Map<string, any>;\n unregisterHelp(pluginName: string): void;\n}\n\n// WebUI Service\nexport interface WebUIService {\n getSettings(): { port: number; host: string; packageManager: string };\n}\n\n// ============ AI Service Types ============\n\nexport interface AITool {\n name: string;\n description: string;\n parameters: {\n type: \"object\";\n properties: Record<string, any>;\n required?: string[];\n };\n handler: (args: any, event?: any) => Promise<any> | any;\n}\n\nexport interface AISkill {\n name: string;\n description: string;\n permission?: \"owner\" | \"admin\" | \"member\";\n tools: AITool[];\n}\n\nexport interface TextMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\nexport interface MultimodalMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string | MultimodalContentItem[];\n}\n\nexport interface ToolCallRecord {\n name: string;\n arguments: any;\n result: any;\n}\n\nexport interface SessionToolDefinition {\n name: string;\n tool: AITool;\n}\n\nexport interface CompleteOptions {\n model?: string;\n messages: any[];\n temperature?: number;\n max_tokens?: number;\n stream?: boolean;\n tools?: any[];\n executableTools?: SessionToolDefinition[];\n executableToolsProvider?: () => SessionToolDefinition[];\n maxIterations?: number;\n onTextDelta?: (delta: string) => void | Promise<void>;\n usageContext?: AIUsageContext;\n usageContextTokens?: number;\n usageBreakdown?: AIUsageFinalization[\"breakdown\"];\n}\n\nexport interface CompleteResponse {\n content: string | null;\n reasoning: string | null;\n toolCalls: Array<{ id: string; name: string; arguments: string }>;\n raw: any;\n turnMessages: any[];\n iterations?: number;\n allToolCalls?: ToolCallRecord[];\n}\n\nexport interface ChatRuntime {\n generateNotice(options: ChatRuntimeNoticeOptions): Promise<ChatRuntimeResult>;\n requestInformation(options: ChatRuntimeInformationRequestOptions): Promise<ChatRuntimeResult>;\n}\n\nexport const TOOL_RESULT_FOLLOWUP_KEY = \"__miokuFollowup\";\n\nexport interface ToolResultFollowup {\n text: string;\n images: Array<{\n url: string;\n detail?: \"auto\" | \"low\" | \"high\";\n }>;\n}\n\n// Permission role for skills\nexport type SkillPermissionRole = \"owner\" | \"admin\" | \"member\";\n\n// Multimodal content item\nexport interface MultimodalContentItem {\n type: \"text\" | \"image_url\";\n text?: string;\n image_url?: {\n url: string;\n detail?: \"auto\" | \"low\" | \"high\";\n };\n}\n\n// Chat runtime types\nexport interface ChatRuntimePromptInjection {\n content: string;\n title?: string;\n}\n\nexport interface ChatRuntimeGroupTarget {\n selfId: number;\n groupId: number;\n}\n\nexport interface ChatRuntimePrivateTarget {\n selfId: number;\n userId: number;\n}\n\nexport type ChatRuntimeSource =\n | { event: any }\n | ChatRuntimeGroupTarget\n | ChatRuntimePrivateTarget;\n\nexport type ChatRuntimeBaseOptions = ChatRuntimeSource & {\n targetMessage?: string;\n promptInjections?: ChatRuntimePromptInjection[];\n send?: boolean;\n};\n\nexport type ChatRuntimeNoticeOptions = ChatRuntimeBaseOptions & {\n instruction: string;\n};\n\nexport type ChatRuntimeInformationRequestOptions = ChatRuntimeBaseOptions & {\n task: string;\n schema: {\n type: \"object\";\n properties: Record<string, any>;\n required?: string[];\n };\n toolName?: string;\n toolDescription?: string;\n};\n\nexport interface ChatRuntimeCollectedInfo {\n data: any;\n isComplete?: boolean;\n confidence?: number;\n notes?: string;\n}\n\nexport type AIUsageRange = \"today\" | \"7d\" | \"30d\";\n\nexport interface AIUsageContext {\n usageId?: string;\n source?: string;\n botId?: number;\n groupId?: number;\n groupName?: string;\n userId?: number;\n userName?: string;\n sessionId?: string;\n}\n\nexport interface AIUsageBreakdown {\n systemPromptTokens?: number;\n chatHistoryTokens?: number;\n toolDefinitionTokens?: number;\n toolUseTokens?: number;\n otherContextTokens?: number;\n}\n\nexport interface AIUsageFinalization {\n sentUserMessages?: number;\n sentAssistantMessages?: number;\n breakdown?: AIUsageBreakdown;\n}\n\nexport interface AIUsageSummary {\n range: AIUsageRange;\n total: {\n requests: number;\n inputTokens: number;\n outputTokens: number;\n cacheWriteTokens: number;\n cacheReadTokens: number;\n totalTokens: number;\n };\n byBot: Array<{\n botId: number | null;\n requests: number;\n inputTokens: number;\n outputTokens: number;\n cacheWriteTokens: number;\n cacheReadTokens: number;\n totalTokens: number;\n }>;\n}\n\nexport interface ChatRuntimeResult {\n messages: string[];\n toolCalls: ToolCallRecord[];\n collectedInfo: ChatRuntimeCollectedInfo | null;\n pendingAt?: number[];\n pendingPoke?: number[];\n pendingQuote?: number;\n emojiPath?: string | null;\n protocolMessages?: any[];\n}\n\nexport interface LegacyChatRuntimeNoticeOptions {\n sessionId: string;\n groupId?: number;\n userId: number;\n message: string;\n replyContextType: string;\n}\n\nexport interface LegacyChatRuntimeInformationRequestOptions {\n sessionId: string;\n groupId?: number;\n userId: number;\n prompt: string;\n injectHistoryCount?: number;\n}\n\n// ============ AI Service Interfaces ============\n\nexport interface AIInstance {\n generateText(options: { prompt?: string; messages: TextMessage[]; model?: string; temperature?: number; max_tokens?: number }): Promise<string>;\n generateMultimodal(options: { prompt?: string; messages: MultimodalMessage[]; model?: string; temperature?: number; max_tokens?: number }): Promise<string>;\n complete(options: CompleteOptions): Promise<CompleteResponse>;\n generateWithTools(options: { prompt?: string; messages: TextMessage[] | MultimodalMessage[]; model?: string; temperature?: number; maxIterations?: number }): Promise<any>;\n setUsageContext?(context: AIUsageContext | undefined): void;\n withUsageContext?<T>(context: AIUsageContext | undefined, fn: () => Promise<T>): Promise<T>;\n registerPrompt(name: string, prompt: string): boolean;\n getPrompt(name: string): string | undefined;\n getAllPrompts(): Record<string, string>;\n removePrompt(name: string): boolean;\n}\n\nexport interface AIService {\n create(options: { name: string; apiUrl: string; apiKey: string; modelType: \"text\" | \"multimodal\"; model?: string }): Promise<AIInstance>;\n get(name: string): AIInstance | undefined;\n list(): string[];\n remove(name: string): boolean;\n setDefault(name: string): boolean;\n getDefault(): AIInstance | undefined;\n registerChatRuntime(runtime: any): boolean;\n getChatRuntime(): any;\n removeChatRuntime(): boolean;\n registerSkill(skill: AISkill): boolean;\n getSkill(skillName: string): AISkill | undefined;\n getAllSkills(): Map<string, AISkill>;\n removeSkill(skillName: string): boolean;\n getTool(toolName: string): AITool | undefined;\n getAllTools(): Map<string, AITool>;\n getUsageSummary?(options: { range: AIUsageRange; botId?: number }): AIUsageSummary;\n cleanupUsageStats?(retentionMs?: number): number;\n finalizeUsage?(usageId: string, finalization: AIUsageFinalization): boolean;\n}\n","/**\n * Data Directory Utilities for Mioku Plugins\n *\n * Provides consistent data path resolution that respects the project directory\n * (process.cwd()) rather than the package installation directory.\n */\n\nimport * as path from \"path\";\n\n/**\n * Get the data directory for a specific plugin\n * Returns: {cwd}/data/{pluginName}\n */\nexport function getPluginDataDir(pluginName: string): string {\n const dataDir = path.join(process.cwd(), \"data\", pluginName);\n return dataDir;\n}\n\n/**\n * Get the data directory for a service\n * Returns: {cwd}/data/{serviceName}\n */\nexport function getServiceDataDir(serviceName: string): string {\n const dataDir = path.join(process.cwd(), \"data\", serviceName);\n return dataDir;\n}\n\n/**\n * Get the main data directory\n * Returns: {cwd}/data\n */\nexport function getDataDir(): string {\n return path.join(process.cwd(), \"data\");\n}\n\n/**\n * Get the config directory for a plugin\n * Returns: {cwd}/config/{pluginName}\n */\nexport function getPluginConfigDir(pluginName: string): string {\n const configDir = path.join(process.cwd(), \"config\", pluginName);\n return configDir;\n}\n\n/**\n * Get the config directory for a service\n * Returns: {cwd}/config/{serviceName}\n */\nexport function getServiceConfigDir(serviceName: string): string {\n const configDir = path.join(process.cwd(), \"config\", serviceName);\n return configDir;\n}\n\n/**\n * Get the main config directory\n * Returns: {cwd}/config\n */\nexport function getConfigDir(): string {\n return path.join(process.cwd(), \"config\");\n}\n\n/**\n * Ensure a directory exists, creating it if necessary\n */\nexport function ensureDataDir(pluginName: string): string {\n const dir = getPluginDataDir(pluginName);\n const { existsSync, mkdirSync } = require(\"fs\");\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n return dir;\n}","/**\n * Plugin Runtime State Management\n *\n * Provides a way for plugins to store state that needs to persist\n * across the plugin lifecycle but should be isolated per plugin.\n */\n\ninterface PluginRuntimeState {\n [pluginName: string]: Record<string, any>;\n}\n\nconst runtimeState: PluginRuntimeState = {};\n\n/**\n * Get the runtime state for a plugin\n */\nexport function getPluginRuntimeState(pluginName: string): Record<string, any> {\n if (!runtimeState[pluginName]) {\n runtimeState[pluginName] = {};\n }\n return runtimeState[pluginName];\n}\n\n/**\n * Set/update the runtime state for a plugin\n */\nexport function setPluginRuntimeState(\n pluginName: string,\n state: Record<string, any>,\n): Record<string, any> {\n if (!runtimeState[pluginName]) {\n runtimeState[pluginName] = {};\n }\n Object.assign(runtimeState[pluginName], state);\n return runtimeState[pluginName];\n}\n\n/**\n * Reset the runtime state for a plugin\n */\nexport function resetPluginRuntimeState(pluginName: string): void {\n delete runtimeState[pluginName];\n}\n\n/**\n * Get all plugin runtime states (for debugging)\n */\nexport function getAllPluginRuntimeStates(): PluginRuntimeState {\n return { ...runtimeState };\n}","/**\n * Mioku - Plugin framework extended from mioki\n *\n * Main entry point for the mioku npm package\n */\n\nimport pluginManager from \"./core/plugin-manager\";\nimport serviceManager from \"./core/service-manager\";\nimport { registerPluginArtifacts } from \"./core/plugin-artifact-registry\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { existsSync, mkdirSync } from \"fs\";\nimport {\n DEFAULT_RUNTIME_PLUGINS_DIR,\n prepareRuntimePluginLinks,\n} from \"./core/plugin-linker\";\nimport { setMiokuLogger } from \"./core/logger\";\n\n// Re-export mioki types for convenience\nexport type { MiokiPlugin, MiokiContext } from \"mioki\";\n\nexport function definePlugin<T extends import(\"mioki\").MiokiPlugin>(\n plugin: T,\n): T {\n return plugin;\n}\n\n// Core functionality\nexport { default as pluginManager } from \"./core/plugin-manager\";\nexport { default as serviceManager } from \"./core/service-manager\";\nexport { registerPluginArtifacts } from \"./core/plugin-artifact-registry\";\n\n// Types from types.ts\nexport type {\n MiokuService,\n PluginMetadata,\n ServiceMetadata,\n PluginPackageConfig,\n PluginHelp,\n CommandRole,\n} from \"./types\";\n\n// Service types from service-types.ts\nexport type {\n ConfigService,\n ScreenshotService,\n HelpService,\n WebUIService,\n AITool,\n AISkill,\n AIInstance,\n AIService,\n ChatRuntime,\n TextMessage,\n MultimodalMessage,\n ToolCallRecord,\n CompleteOptions,\n CompleteResponse,\n SessionToolDefinition,\n SkillPermissionRole,\n MultimodalContentItem,\n ToolResultFollowup,\n ChatRuntimePromptInjection,\n ChatRuntimeGroupTarget,\n ChatRuntimePrivateTarget,\n ChatRuntimeSource,\n ChatRuntimeBaseOptions,\n ChatRuntimeNoticeOptions,\n ChatRuntimeInformationRequestOptions,\n ChatRuntimeCollectedInfo,\n ChatRuntimeResult,\n AIUsageRange,\n AIUsageContext,\n AIUsageBreakdown,\n AIUsageFinalization,\n AIUsageSummary,\n} from \"./service-types\";\n\nexport { TOOL_RESULT_FOLLOWUP_KEY } from \"./service-types\";\n\n/**\n * Start options for Mioku\n */\nexport interface MiokuStartOptions {\n cwd?: string;\n}\n\n/**\n * Start Mioku with plugin and service discovery\n */\nexport async function start(options: MiokuStartOptions = {}): Promise<void> {\n const { cwd = process.cwd() } = options;\n\n if (cwd) {\n process.chdir(cwd);\n }\n\n const { start: startMioki, logger, botConfig } = await import(\"mioki\");\n setMiokuLogger(logger);\n\n // Read mioku config from package.json (mioki field contains merged config)\n const packageJsonPath = path.join(process.cwd(), \"package.json\");\n let miokuConfig: any = {};\n if (fs.existsSync(packageJsonPath)) {\n const pkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n // mioku-specific config lives in the same mioki field\n miokuConfig = pkg.mioki || {};\n }\n\n logger.info(\"こんにちは..\");\n logger.info(\"---------------------------------------\");\n logger.info(\"---------- Mioku 正在启动 ------------\");\n logger.info(\"---------------------------------------\");\n\n // Ensure required directories exist\n const requiredDirs = [\"data\", \"config\", \"temp\"];\n for (const dir of requiredDirs) {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n logger.info(\"O.o Miku 正在翻找插件..\");\n const discoveredPlugins = await pluginManager.discoverPlugins(miokuConfig);\n logger.info(`O.o 共发现 ${discoveredPlugins.length} 个插件: ${discoveredPlugins.map(p => p.name).join(\", \")}`);\n\n const runtimePluginsDir = path.resolve(\n process.cwd(),\n DEFAULT_RUNTIME_PLUGINS_DIR,\n );\n const linkedPluginNames = await prepareRuntimePluginLinks(\n discoveredPlugins,\n runtimePluginsDir,\n );\n botConfig.plugins_dir = DEFAULT_RUNTIME_PLUGINS_DIR;\n\n logger.info(\"o.O Miku 正在翻找服务..\");\n await serviceManager.discoverServices(miokuConfig);\n\n const requiredServices = pluginManager.collectRequiredServices();\n const missingServices =\n await serviceManager.checkMissingServices(requiredServices);\n\n if (missingServices.length > 0) {\n logger.warn(`发现缺失服务: ${missingServices.join(\", \")}`);\n }\n\n // Only auto-load discovered plugins if the user has not specified a plugins list.\n // \"not specified\" means plugins key is undefined in mioki config.\n // If plugins is explicitly set (even to empty array []), only load what's in the list.\n const userSpecifiedPlugins = miokuConfig.plugins !== undefined;\n if (!userSpecifiedPlugins) {\n for (const name of linkedPluginNames) {\n if (!botConfig.plugins.includes(name)) {\n botConfig.plugins.push(name);\n }\n }\n }\n\n await startMioki({ cwd });\n}\n\n// Version\nexport const version = \"1.0.0\";\n\n// Data path utilities\nexport {\n getDataDir,\n getPluginDataDir,\n getServiceDataDir,\n getConfigDir,\n getPluginConfigDir,\n getServiceConfigDir,\n ensureDataDir,\n} from \"./core/data-paths\";\n\n// Plugin runtime state\nexport {\n getPluginRuntimeState,\n setPluginRuntimeState,\n resetPluginRuntimeState,\n} from \"./core/plugin-runtime-state\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["fallbackLogger: MiokuLogger","activeLogger: MiokuLogger","logger: MiokuLogger | undefined","logger","logger: MiokuLogger","pathExists","filePath: string","entryPath: string","linkPath: string","targetPath: string","runtimePluginsDir: string","metadata: PluginMetadata","plugins: PluginMetadata[]","linkedNames: string[]","pathExists","filePath: string","miokuConfig: any","discovered: PluginMetadata[]","pluginsDir: string","entryPath: string","name: string","pluginPath: string","packageJson: any","metadata: PluginMetadata","pathExists","filePath: string","miokuConfig: any","discovered: ServiceMetadata[]","servicesDir: string","name: string","servicePath: string","metadata: ServiceMetadata","error: any","requiredServices: Set<string>","missing: string[]","ctx: MiokiContext","service: MiokuService","filePath: string","value: any","moduleExports: any","pluginPath: string","ctx: MiokiContext","error: any","pluginName: string","serviceName: string","runtimeState: PluginRuntimeState","pluginName: string","state: Record<string, any>","plugin: T","options: MiokuStartOptions","logger","miokuConfig: any"],"sources":["../src/core/logger.ts","../src/core/plugin-linker.ts","../src/core/plugin-manager.ts","../src/core/service-manager.ts","../src/core/plugin-artifact-registry.ts","../src/service-types.ts","../src/core/data-paths.ts","../src/core/plugin-runtime-state.ts","../src/index.ts"],"sourcesContent":["type LogMethod = (...args: unknown[]) => void;\n\nexport interface MiokuLogger {\n error: LogMethod;\n warn: LogMethod;\n info: LogMethod;\n debug: LogMethod;\n trace?: LogMethod;\n}\n\nconst fallbackLogger: MiokuLogger = {\n error: (...args) => console.error(...args),\n warn: (...args) => console.warn(...args),\n info: (...args) => console.info(...args),\n debug: (...args) => console.debug(...args),\n trace: (...args) => console.debug(...args),\n};\n\nlet activeLogger: MiokuLogger = fallbackLogger;\n\nexport function setMiokuLogger(logger: MiokuLogger | undefined): void {\n activeLogger = logger || fallbackLogger;\n}\n\nexport function getMiokuLogger(): MiokuLogger {\n return activeLogger;\n}\n\nexport const logger: MiokuLogger = {\n error: (...args) => activeLogger.error(...args),\n warn: (...args) => activeLogger.warn(...args),\n info: (...args) => activeLogger.info(...args),\n debug: (...args) => activeLogger.debug(...args),\n trace: (...args) => activeLogger.trace?.(...args),\n};\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport type { PluginMetadata } from \"./types\";\nimport { logger } from \"./logger\";\n\nexport const DEFAULT_RUNTIME_PLUGINS_DIR = \".mioku/plugins\";\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function removeIfBrokenSymlink(entryPath: string): Promise<\"ok\" | \"blocked\" | \"removed\"> {\n let stat;\n try {\n stat = await fs.lstat(entryPath);\n } catch {\n return \"removed\";\n }\n\n if (!stat.isSymbolicLink()) {\n return \"blocked\";\n }\n\n try {\n await fs.realpath(entryPath);\n return \"ok\";\n } catch {\n await fs.rm(entryPath, { force: true });\n logger.warn(`[plugin-linker] Removed broken plugin link: ${entryPath}`);\n return \"removed\";\n }\n}\n\nfunction relativeSymlinkTarget(linkPath: string, targetPath: string): string {\n const relativePath = path.relative(path.dirname(linkPath), targetPath);\n return relativePath || \".\";\n}\n\nasync function ensurePluginLink(\n runtimePluginsDir: string,\n metadata: PluginMetadata,\n): Promise<boolean> {\n const linkPath = path.join(runtimePluginsDir, metadata.name);\n const targetPath = metadata.path;\n\n let stat;\n try {\n stat = await fs.lstat(linkPath);\n } catch {\n stat = null;\n }\n\n if (stat?.isSymbolicLink()) {\n try {\n const currentTarget = await fs.realpath(linkPath);\n const expectedTarget = await fs.realpath(targetPath);\n if (currentTarget === expectedTarget) {\n return true;\n }\n await fs.rm(linkPath, { force: true });\n logger.info(`[plugin-linker] Rebuilding plugin link: ${metadata.name}`);\n } catch {\n await fs.rm(linkPath, { force: true });\n logger.warn(`[plugin-linker] Removed broken plugin link: ${linkPath}`);\n }\n } else if (stat) {\n logger.warn(\n `[plugin-linker] ${linkPath} exists and is not a symlink, skip linking ${metadata.name}`,\n );\n return false;\n }\n\n if (!(await pathExists(targetPath))) {\n logger.warn(\n `[plugin-linker] Plugin target missing, skip linking ${metadata.name}: ${targetPath}`,\n );\n return false;\n }\n\n // Use junction on Windows (no admin needed), symlink on Unix\n if (process.platform === \"win32\") {\n // Junctions require absolute paths\n await fs.symlink(targetPath, linkPath, \"junction\");\n } else {\n await fs.symlink(relativeSymlinkTarget(linkPath, targetPath), linkPath, \"dir\");\n }\n return true;\n}\n\nexport async function prepareRuntimePluginLinks(\n plugins: PluginMetadata[],\n runtimePluginsDir = path.resolve(process.cwd(), DEFAULT_RUNTIME_PLUGINS_DIR),\n): Promise<string[]> {\n await fs.mkdir(runtimePluginsDir, { recursive: true });\n\n const discoveredNames = new Set(plugins.map((plugin) => plugin.name));\n const entries = await fs.readdir(runtimePluginsDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = path.join(runtimePluginsDir, entry.name);\n const symlinkState = await removeIfBrokenSymlink(entryPath);\n if (symlinkState !== \"ok\") {\n continue;\n }\n\n if (entry.isSymbolicLink() && !discoveredNames.has(entry.name)) {\n await fs.rm(entryPath, { force: true });\n logger.info(`[plugin-linker] Removed stale plugin link: ${entry.name}`);\n }\n }\n\n const linkedNames: string[] = [];\n for (const metadata of plugins) {\n if (await ensurePluginLink(runtimePluginsDir, metadata)) {\n linkedNames.push(metadata.name);\n }\n }\n\n return linkedNames;\n}\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport { mkdirSync } from \"fs\";\nimport type { PluginMetadata } from \"./types\";\nimport { DEFAULT_RUNTIME_PLUGINS_DIR } from \"./plugin-linker\";\nimport { logger } from \"./logger\";\n\nconst PLUGIN_MANAGER_SYMBOL = Symbol.for(\"mioku.plugin-manager\");\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * 插件管理器\n *\n * Discover and manage plugins from both local directories and node_modules.\n */\nexport class PluginManager {\n private pluginMetadata: Map<string, PluginMetadata> = new Map();\n\n public static getInstance(): PluginManager {\n const g = global as any;\n if (!g[PLUGIN_MANAGER_SYMBOL]) {\n g[PLUGIN_MANAGER_SYMBOL] = new PluginManager();\n }\n return g[PLUGIN_MANAGER_SYMBOL];\n }\n\n async discoverPlugins(miokuConfig: any = {}): Promise<PluginMetadata[]> {\n // Resolve pluginsDir dynamically so it uses the current cwd\n const configuredPluginsDir = miokuConfig.plugins_dir;\n const pluginsDir =\n configuredPluginsDir && configuredPluginsDir !== DEFAULT_RUNTIME_PLUGINS_DIR\n ? path.resolve(process.cwd(), configuredPluginsDir)\n : path.resolve(process.cwd(), \"plugins\");\n\n this.pluginMetadata.clear();\n\n // Ensure plugins directory exists\n if (!(await pathExists(pluginsDir))) {\n mkdirSync(pluginsDir, { recursive: true });\n }\n\n const discovered: PluginMetadata[] = [];\n\n // Discover from local plugins/ directory\n if (await pathExists(pluginsDir)) {\n const localPlugins = await this.discoverFromDir(pluginsDir);\n discovered.push(...localPlugins);\n }\n\n // Discover from node_modules (mioku-plugin-* prefix)\n const nodeModulesPlugins = await this.discoverFromNodeModules();\n discovered.push(...nodeModulesPlugins);\n\n logger.info(`O.o 发现了 ${this.pluginMetadata.size} 个插件`);\n return Array.from(this.pluginMetadata.values());\n }\n\n private async discoverFromDir(pluginsDir: string): Promise<PluginMetadata[]> {\n const discovered: PluginMetadata[] = [];\n\n try {\n const entries = await fs.readdir(pluginsDir, { withFileTypes: true });\n for (const entry of entries) {\n const pluginPath = path.join(pluginsDir, entry.name);\n const metadataPath = await this.resolveDirectoryPath(pluginPath);\n if (!metadataPath) continue;\n\n const metadata = await this.loadPluginMetadata(entry.name, pluginPath);\n if (metadata) {\n discovered.push(metadata);\n this.pluginMetadata.set(metadata.name, metadata);\n }\n }\n } catch (error) {\n logger.error(`扫描插件目录失败: ${error}`);\n }\n\n return discovered;\n }\n\n private async discoverFromNodeModules(): Promise<PluginMetadata[]> {\n const discovered: PluginMetadata[] = [];\n const nodeModulesPath = path.resolve(process.cwd(), \"node_modules\");\n\n if (!(await pathExists(nodeModulesPath))) {\n return discovered;\n }\n\n try {\n const entries = await fs.readdir(nodeModulesPath, { withFileTypes: true });\n for (const entry of entries) {\n // Check for mioku-plugin-* prefix (don't check isDirectory - symlinks return false)\n if (!entry.name.startsWith(\"mioku-plugin-\")) {\n continue;\n }\n\n const pluginName = entry.name.replace(/^mioku-plugin-/, \"\");\n const pluginPath = path.join(nodeModulesPath, entry.name);\n const metadata = await this.loadPluginMetadata(pluginName, pluginPath);\n if (metadata) {\n discovered.push(metadata);\n this.pluginMetadata.set(metadata.name, metadata);\n }\n }\n } catch (error) {\n logger.debug(`扫描 node_modules 插件失败: ${error}`);\n }\n\n return discovered;\n }\n\n private async resolveDirectoryPath(entryPath: string): Promise<string | null> {\n try {\n const stat = await fs.stat(entryPath);\n return stat.isDirectory() ? entryPath : null;\n } catch {\n return null;\n }\n }\n\n private async loadPluginMetadata(\n name: string,\n pluginPath: string,\n ): Promise<PluginMetadata | null> {\n // Resolve symlinks to get actual path\n let resolvedPath = pluginPath;\n try {\n resolvedPath = await fs.realpath(pluginPath);\n } catch {\n // Not a symlink or doesn't exist, use original path\n }\n\n const packageJsonPath = path.join(resolvedPath, \"package.json\");\n\n let packageJson: any = null;\n try {\n const content = await fs.readFile(packageJsonPath, \"utf-8\");\n packageJson = JSON.parse(content);\n } catch {\n // File doesn't exist or can't be read - plugin uses defaults\n }\n\n const metadata: PluginMetadata = {\n name,\n version: packageJson?.version || \"0.0.0\",\n description: packageJson?.description,\n path: resolvedPath,\n packageJson,\n config: packageJson?.mioku || {},\n };\n return metadata;\n }\n\n collectRequiredServices(): Set<string> {\n const services = new Set<string>();\n for (const metadata of this.pluginMetadata.values()) {\n if (metadata.config.services) {\n metadata.config.services.forEach((s) => services.add(s));\n }\n }\n return services;\n }\n\n getPluginMetadata(name: string): PluginMetadata | undefined {\n return this.pluginMetadata.get(name);\n }\n\n getAllMetadata(): PluginMetadata[] {\n return Array.from(this.pluginMetadata.values());\n }\n\n reset(): void {\n this.pluginMetadata.clear();\n }\n}\n\nexport default PluginManager.getInstance();\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport { existsSync, mkdirSync } from \"fs\";\nimport type { MiokiContext } from \"mioki\";\nimport type { ServiceMetadata, MiokuService } from \"./types\";\nimport { logger } from \"./logger\";\n\nconst SERVICE_MANAGER_SYMBOL = Symbol.for(\"mioku.service-manager\");\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * 服务管理器\n */\nexport class ServiceManager {\n private services: Map<string, MiokuService> = new Map();\n private serviceMetadata: Map<string, ServiceMetadata> = new Map();\n private servicesDir: string = \"services\";\n\n public static getInstance(): ServiceManager {\n const g = global as any;\n if (!g[SERVICE_MANAGER_SYMBOL]) {\n g[SERVICE_MANAGER_SYMBOL] = new ServiceManager();\n }\n return g[SERVICE_MANAGER_SYMBOL];\n }\n\n async discoverServices(miokuConfig: any = {}): Promise<ServiceMetadata[]> {\n // Use services_dir from mioku config if provided, otherwise default to \"services\" in project root\n if (miokuConfig.services_dir) {\n this.servicesDir = path.resolve(process.cwd(), miokuConfig.services_dir);\n } else {\n this.servicesDir = path.resolve(process.cwd(), \"services\");\n }\n\n const discovered: ServiceMetadata[] = [];\n this.serviceMetadata.clear();\n\n // Discover from local services/ directory\n if (existsSync(this.servicesDir)) {\n const localServices = await this.discoverFromDir(this.servicesDir);\n discovered.push(...localServices);\n } else {\n // Ensure the directory exists for user services\n mkdirSync(this.servicesDir, { recursive: true });\n }\n\n // Discover builtin services (config, ai, screenshot, webui)\n await this.loadBuiltinServices();\n\n logger.info(`o.O 发现了 ${this.serviceMetadata.size} 个服务`);\n return Array.from(this.serviceMetadata.values());\n }\n\n private async discoverFromDir(servicesDir: string): Promise<ServiceMetadata[]> {\n const discovered: ServiceMetadata[] = [];\n\n try {\n const entries = await fs.readdir(servicesDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const servicePath = path.join(servicesDir, entry.name);\n const metadata = await this.loadServiceMetadata(entry.name, servicePath);\n if (metadata) {\n discovered.push(metadata);\n this.serviceMetadata.set(entry.name, metadata);\n }\n }\n } catch (error) {\n logger.error(`扫描服务目录失败: ${error}`);\n }\n\n return discovered;\n }\n\n private async loadServiceMetadata(\n name: string,\n servicePath: string,\n ): Promise<ServiceMetadata | null> {\n // Resolve symlinks to get actual path\n let resolvedPath = servicePath;\n try {\n resolvedPath = await fs.realpath(servicePath);\n } catch {\n // Not a symlink or doesn't exist, use original path\n }\n\n const packageJsonPath = path.join(resolvedPath, \"package.json\");\n\n if (!(await pathExists(packageJsonPath))) {\n return null;\n }\n\n try {\n const packageJson = JSON.parse(\n await fs.readFile(packageJsonPath, \"utf-8\"),\n );\n const metadata: ServiceMetadata = {\n name,\n version: packageJson.version || \"0.0.0\",\n description: packageJson.description,\n path: resolvedPath,\n packageJson,\n };\n return metadata;\n } catch (error: any) {\n logger.error(`解析服务 ${name} 失败: ${error.message}`);\n return null;\n }\n }\n\n /**\n * Load built-in services from the package\n */\n private async loadBuiltinServices(): Promise<void> {\n // Discover from node_modules (mioku-service-* prefix)\n await this.discoverFromNodeModules();\n }\n\n private async discoverFromNodeModules(): Promise<void> {\n const nodeModulesPath = path.resolve(process.cwd(), \"node_modules\");\n\n if (!(await pathExists(nodeModulesPath))) {\n return;\n }\n\n try {\n const entries = await fs.readdir(nodeModulesPath, { withFileTypes: true });\n for (const entry of entries) {\n // Don't check isDirectory - symlinks return false\n if (!entry.name.startsWith(\"mioku-service-\")) {\n continue;\n }\n\n const serviceName = entry.name.replace(/^mioku-service-/, \"\");\n const servicePath = path.join(nodeModulesPath, entry.name);\n const metadata = await this.loadServiceMetadata(serviceName, servicePath);\n if (metadata) {\n this.serviceMetadata.set(serviceName, metadata);\n }\n }\n } catch (error) {\n logger.debug(`扫描 node_modules 服务失败: ${error}`);\n }\n }\n\n async checkMissingServices(requiredServices: Set<string>): Promise<string[]> {\n const missing: string[] = [];\n for (const serviceName of requiredServices) {\n if (!this.serviceMetadata.has(serviceName)) {\n missing.push(serviceName);\n }\n }\n return missing;\n }\n\n async loadAllServices(ctx: MiokiContext): Promise<void> {\n const allMetadata = Array.from(this.serviceMetadata.values());\n logger.info(`O.o 准备加载 ${allMetadata.length} 个服务...`);\n\n for (const metadata of allMetadata) {\n await this.loadService(metadata, ctx);\n }\n }\n\n private async loadService(\n metadata: ServiceMetadata,\n ctx: MiokiContext,\n ): Promise<boolean> {\n try {\n const indexPath = path.join(metadata.path, \"index.ts\");\n const indexJsPath = path.join(metadata.path, \"index.js\");\n const indexExists = await pathExists(indexPath);\n const indexJsExists = await pathExists(indexJsPath);\n const entryPoint = indexExists ? indexPath : indexJsPath;\n\n if (!entryPoint || (!indexExists && !indexJsExists)) {\n logger.error(`服务 ${metadata.name} 入口丢失`);\n return false;\n }\n\n let importPath = entryPoint;\n if (process.platform === \"win32\") {\n importPath = \"file:///\" + entryPoint.replace(/\\\\/g, \"/\");\n }\n\n const serviceModule = await import(importPath);\n const service: MiokuService = serviceModule.default || serviceModule;\n\n if (!service || typeof service.init !== \"function\") return false;\n\n await service.init();\n if (service.api) {\n if (!(ctx as any).services) (ctx as any).services = {};\n (ctx as any).services[metadata.name] = service.api;\n }\n\n this.services.set(metadata.name, service);\n return true;\n } catch (error: any) {\n logger.error(`加载服务 ${metadata.name} 失败: ${error.message}`);\n return false;\n }\n }\n\n /**\n * Register a builtin service directly\n */\n registerBuiltinService(name: string, service: MiokuService): void {\n this.services.set(name, service);\n }\n\n /**\n * Get a loaded service\n */\n getService(name: string): MiokuService | undefined {\n return this.services.get(name);\n }\n\n async disposeAll(): Promise<void> {\n for (const [name, service] of this.services) {\n if (service.dispose) await service.dispose();\n }\n this.services.clear();\n }\n\n reset(): void {\n this.services.clear();\n this.serviceMetadata.clear();\n }\n}\n\nexport default ServiceManager.getInstance();\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport type { MiokiContext } from \"mioki\";\nimport type { AIService } from \"../types\";\nimport type { HelpService } from \"../service-types\";\nimport type { AISkill } from \"./types\";\nimport pluginManager from \"./plugin-manager\";\nimport { logger } from \"./logger\";\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction toImportPath(filePath: string): string {\n if (process.platform === \"win32\") {\n return \"file:///\" + filePath.replace(/\\\\/g, \"/\");\n }\n return filePath;\n}\n\nfunction isAISkill(value: any): value is AISkill {\n return (\n value &&\n typeof value === \"object\" &&\n typeof value.name === \"string\" &&\n Array.isArray(value.tools)\n );\n}\n\nfunction extractSkills(moduleExports: any): AISkill[] {\n const candidates = [\n moduleExports?.default,\n moduleExports?.skills,\n moduleExports,\n ];\n\n for (const candidate of candidates) {\n if (Array.isArray(candidate)) {\n return candidate.filter(isAISkill);\n }\n if (isAISkill(candidate)) {\n return [candidate];\n }\n }\n\n return [];\n}\n\nasync function resolveSkillsEntry(pluginPath: string): Promise<string | null> {\n const tsPath = path.join(pluginPath, \"skills.ts\");\n if (await pathExists(tsPath)) {\n return tsPath;\n }\n\n const jsPath = path.join(pluginPath, \"skills.js\");\n if (await pathExists(jsPath)) {\n return jsPath;\n }\n\n return null;\n}\n\n/**\n * Auto-register plugin help manifests and AI skills\n */\nexport async function registerPluginArtifacts(\n ctx: MiokiContext,\n): Promise<void> {\n const enabledPlugins = new Set<string>(\n Array.isArray((ctx as any).botConfig?.plugins)\n ? (ctx as any).botConfig.plugins\n : [],\n );\n const pluginMetadata = pluginManager\n .getAllMetadata()\n .filter((metadata) =>\n enabledPlugins.size > 0 ? enabledPlugins.has(metadata.name) : true,\n );\n\n const helpService = ctx.services?.help as HelpService | undefined;\n const aiService = ctx.services?.ai as AIService | undefined;\n\n if (helpService) {\n let helpCount = 0;\n for (const metadata of pluginMetadata) {\n if (!metadata.config.help) {\n continue;\n }\n helpService.registerHelp(metadata.name, metadata.config.help);\n helpCount += 1;\n }\n logger.info(`[plugin-artifacts] Registered ${helpCount} help manifest(s)`);\n }\n\n if (!aiService) {\n return;\n }\n\n let skillCount = 0;\n for (const metadata of pluginMetadata) {\n const skillsEntry = await resolveSkillsEntry(metadata.path);\n if (!skillsEntry) {\n continue;\n }\n\n try {\n const moduleExports = await import(toImportPath(skillsEntry));\n const skills = extractSkills(moduleExports);\n\n if (skills.length === 0) {\n logger.warn(\n `[plugin-artifacts] Plugin ${metadata.name} has ${path.basename(skillsEntry)} but exported no valid skill`,\n );\n continue;\n }\n\n for (const skill of skills) {\n aiService.registerSkill(skill);\n skillCount += 1;\n }\n } catch (error: any) {\n logger.error(\n `[plugin-artifacts] Failed to load skills for plugin ${metadata.name}: ${error?.message || error}`,\n );\n }\n }\n\n logger.info(`[plugin-artifacts] Registered ${skillCount} skill(s)`);\n}\n","/**\n * Service interface definitions for built-in services\n * These are used for type annotations in plugins\n */\n\n// ============ Core Service Interfaces ============\n\n// Config Service\nexport interface ConfigService {\n registerConfig(pluginName: string, configName: string, initialConfig: any): Promise<boolean>;\n updateConfig(pluginName: string, configName: string, updates: any): Promise<boolean>;\n getConfig(pluginName: string, configName: string): Promise<any>;\n getPluginConfigs(pluginName: string): Promise<Record<string, any>>;\n onConfigChange(pluginName: string, configName: string, callback: (newConfig: any) => void): () => void;\n}\n\n// Screenshot Service\nexport interface ScreenshotService {\n screenshot(html: string, options?: any): Promise<string>;\n screenshotMarkdown(markdownContent: string, options?: any): Promise<string>;\n screenshotFromUrl(url: string, options?: any): Promise<string>;\n cleanupTemp(olderThanMs?: number): Promise<number>;\n}\n\n// Help Service\nexport interface HelpService {\n registerHelp(pluginName: string, help: any): void;\n getHelp(pluginName: string): any;\n getAllHelp(): Map<string, any>;\n unregisterHelp(pluginName: string): void;\n}\n\n// WebUI Service\nexport interface WebUIService {\n getSettings(): { port: number; host: string; packageManager: string };\n}\n\n// ============ AI Service Types ============\n\nexport interface AITool {\n name: string;\n description: string;\n parameters: {\n type: \"object\";\n properties: Record<string, any>;\n required?: string[];\n };\n handler: (args: any, event?: any) => Promise<any> | any;\n}\n\nexport interface AISkill {\n name: string;\n description: string;\n permission?: \"owner\" | \"admin\" | \"member\";\n tools: AITool[];\n}\n\nexport interface TextMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\nexport interface MultimodalMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string | MultimodalContentItem[];\n}\n\nexport interface ToolCallRecord {\n name: string;\n arguments: any;\n result: any;\n}\n\nexport interface SessionToolDefinition {\n name: string;\n tool: AITool;\n}\n\nexport interface CompleteOptions {\n model?: string;\n messages: any[];\n temperature?: number;\n max_tokens?: number;\n stream?: boolean;\n tools?: any[];\n executableTools?: SessionToolDefinition[];\n executableToolsProvider?: () => SessionToolDefinition[];\n maxIterations?: number;\n onTextDelta?: (delta: string) => void | Promise<void>;\n usageContext?: AIUsageContext;\n usageContextTokens?: number;\n usageBreakdown?: AIUsageFinalization[\"breakdown\"];\n}\n\nexport interface CompleteResponse {\n content: string | null;\n reasoning: string | null;\n toolCalls: Array<{ id: string; name: string; arguments: string }>;\n raw: any;\n turnMessages: any[];\n iterations?: number;\n allToolCalls?: ToolCallRecord[];\n}\n\nexport interface ChatRuntime {\n generateNotice(options: ChatRuntimeNoticeOptions): Promise<ChatRuntimeResult>;\n requestInformation(options: ChatRuntimeInformationRequestOptions): Promise<ChatRuntimeResult>;\n}\n\nexport const TOOL_RESULT_FOLLOWUP_KEY = \"__miokuFollowup\";\n\nexport interface ToolResultFollowup {\n text: string;\n images: Array<{\n url: string;\n detail?: \"auto\" | \"low\" | \"high\";\n }>;\n}\n\n// Permission role for skills\nexport type SkillPermissionRole = \"owner\" | \"admin\" | \"member\";\n\n// Multimodal content item\nexport interface MultimodalContentItem {\n type: \"text\" | \"image_url\";\n text?: string;\n image_url?: {\n url: string;\n detail?: \"auto\" | \"low\" | \"high\";\n };\n}\n\n// Chat runtime types\nexport interface ChatRuntimePromptInjection {\n content: string;\n title?: string;\n}\n\nexport interface ChatRuntimeGroupTarget {\n selfId: number;\n groupId: number;\n}\n\nexport interface ChatRuntimePrivateTarget {\n selfId: number;\n userId: number;\n}\n\nexport type ChatRuntimeSource =\n | { event: any }\n | ChatRuntimeGroupTarget\n | ChatRuntimePrivateTarget;\n\nexport type ChatRuntimeBaseOptions = ChatRuntimeSource & {\n targetMessage?: string;\n promptInjections?: ChatRuntimePromptInjection[];\n send?: boolean;\n};\n\nexport type ChatRuntimeNoticeOptions = ChatRuntimeBaseOptions & {\n instruction: string;\n};\n\nexport type ChatRuntimeInformationRequestOptions = ChatRuntimeBaseOptions & {\n task: string;\n schema: {\n type: \"object\";\n properties: Record<string, any>;\n required?: string[];\n };\n toolName?: string;\n toolDescription?: string;\n};\n\nexport interface ChatRuntimeCollectedInfo {\n data: any;\n isComplete?: boolean;\n confidence?: number;\n notes?: string;\n}\n\nexport type AIUsageRange = \"today\" | \"7d\" | \"30d\";\n\nexport interface AIUsageContext {\n usageId?: string;\n source?: string;\n botId?: number;\n groupId?: number;\n groupName?: string;\n userId?: number;\n userName?: string;\n sessionId?: string;\n}\n\nexport interface AIUsageBreakdown {\n systemPromptTokens?: number;\n chatHistoryTokens?: number;\n toolDefinitionTokens?: number;\n toolUseTokens?: number;\n otherContextTokens?: number;\n}\n\nexport interface AIUsageFinalization {\n sentUserMessages?: number;\n sentAssistantMessages?: number;\n breakdown?: AIUsageBreakdown;\n}\n\nexport interface AIUsageSummary {\n range: AIUsageRange;\n total: {\n requests: number;\n inputTokens: number;\n outputTokens: number;\n cacheWriteTokens: number;\n cacheReadTokens: number;\n totalTokens: number;\n };\n byBot: Array<{\n botId: number | null;\n requests: number;\n inputTokens: number;\n outputTokens: number;\n cacheWriteTokens: number;\n cacheReadTokens: number;\n totalTokens: number;\n }>;\n}\n\nexport interface ChatRuntimeResult {\n messages: string[];\n toolCalls: ToolCallRecord[];\n collectedInfo: ChatRuntimeCollectedInfo | null;\n pendingAt?: number[];\n pendingPoke?: number[];\n pendingQuote?: number;\n emojiPath?: string | null;\n protocolMessages?: any[];\n}\n\nexport interface LegacyChatRuntimeNoticeOptions {\n sessionId: string;\n groupId?: number;\n userId: number;\n message: string;\n replyContextType: string;\n}\n\nexport interface LegacyChatRuntimeInformationRequestOptions {\n sessionId: string;\n groupId?: number;\n userId: number;\n prompt: string;\n injectHistoryCount?: number;\n}\n\n// ============ AI Service Interfaces ============\n\nexport interface AIInstance {\n generateText(options: { prompt?: string; messages: TextMessage[]; model?: string; temperature?: number; max_tokens?: number }): Promise<string>;\n generateMultimodal(options: { prompt?: string; messages: MultimodalMessage[]; model?: string; temperature?: number; max_tokens?: number }): Promise<string>;\n complete(options: CompleteOptions): Promise<CompleteResponse>;\n generateWithTools(options: { prompt?: string; messages: TextMessage[] | MultimodalMessage[]; model?: string; temperature?: number; maxIterations?: number }): Promise<any>;\n setUsageContext?(context: AIUsageContext | undefined): void;\n withUsageContext?<T>(context: AIUsageContext | undefined, fn: () => Promise<T>): Promise<T>;\n registerPrompt(name: string, prompt: string): boolean;\n getPrompt(name: string): string | undefined;\n getAllPrompts(): Record<string, string>;\n removePrompt(name: string): boolean;\n}\n\nexport interface AIService {\n create(options: { name: string; apiUrl: string; apiKey: string; modelType: \"text\" | \"multimodal\"; model?: string }): Promise<AIInstance>;\n get(name: string): AIInstance | undefined;\n list(): string[];\n remove(name: string): boolean;\n setDefault(name: string): boolean;\n getDefault(): AIInstance | undefined;\n registerChatRuntime(runtime: any): boolean;\n getChatRuntime(): any;\n removeChatRuntime(): boolean;\n registerSkill(skill: AISkill): boolean;\n getSkill(skillName: string): AISkill | undefined;\n getAllSkills(): Map<string, AISkill>;\n removeSkill(skillName: string): boolean;\n getTool(toolName: string): AITool | undefined;\n getAllTools(): Map<string, AITool>;\n getUsageSummary?(options: { range: AIUsageRange; botId?: number }): AIUsageSummary;\n cleanupUsageStats?(retentionMs?: number): number;\n finalizeUsage?(usageId: string, finalization: AIUsageFinalization): boolean;\n}\n","/**\n * Data Directory Utilities for Mioku Plugins\n *\n * Provides consistent data path resolution that respects the project directory\n * (process.cwd()) rather than the package installation directory.\n */\n\nimport * as path from \"path\";\n\n/**\n * Get the data directory for a specific plugin\n * Returns: {cwd}/data/{pluginName}\n */\nexport function getPluginDataDir(pluginName: string): string {\n const dataDir = path.join(process.cwd(), \"data\", pluginName);\n return dataDir;\n}\n\n/**\n * Get the data directory for a service\n * Returns: {cwd}/data/{serviceName}\n */\nexport function getServiceDataDir(serviceName: string): string {\n const dataDir = path.join(process.cwd(), \"data\", serviceName);\n return dataDir;\n}\n\n/**\n * Get the main data directory\n * Returns: {cwd}/data\n */\nexport function getDataDir(): string {\n return path.join(process.cwd(), \"data\");\n}\n\n/**\n * Get the config directory for a plugin\n * Returns: {cwd}/config/{pluginName}\n */\nexport function getPluginConfigDir(pluginName: string): string {\n const configDir = path.join(process.cwd(), \"config\", pluginName);\n return configDir;\n}\n\n/**\n * Get the config directory for a service\n * Returns: {cwd}/config/{serviceName}\n */\nexport function getServiceConfigDir(serviceName: string): string {\n const configDir = path.join(process.cwd(), \"config\", serviceName);\n return configDir;\n}\n\n/**\n * Get the main config directory\n * Returns: {cwd}/config\n */\nexport function getConfigDir(): string {\n return path.join(process.cwd(), \"config\");\n}\n\n/**\n * Ensure a directory exists, creating it if necessary\n */\nexport function ensureDataDir(pluginName: string): string {\n const dir = getPluginDataDir(pluginName);\n const { existsSync, mkdirSync } = require(\"fs\");\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n return dir;\n}","/**\n * Plugin Runtime State Management\n *\n * Provides a way for plugins to store state that needs to persist\n * across the plugin lifecycle but should be isolated per plugin.\n */\n\ninterface PluginRuntimeState {\n [pluginName: string]: Record<string, any>;\n}\n\nconst runtimeState: PluginRuntimeState = {};\n\n/**\n * Get the runtime state for a plugin\n */\nexport function getPluginRuntimeState(pluginName: string): Record<string, any> {\n if (!runtimeState[pluginName]) {\n runtimeState[pluginName] = {};\n }\n return runtimeState[pluginName];\n}\n\n/**\n * Set/update the runtime state for a plugin\n */\nexport function setPluginRuntimeState(\n pluginName: string,\n state: Record<string, any>,\n): Record<string, any> {\n if (!runtimeState[pluginName]) {\n runtimeState[pluginName] = {};\n }\n Object.assign(runtimeState[pluginName], state);\n return runtimeState[pluginName];\n}\n\n/**\n * Reset the runtime state for a plugin\n */\nexport function resetPluginRuntimeState(pluginName: string): void {\n delete runtimeState[pluginName];\n}\n\n/**\n * Get all plugin runtime states (for debugging)\n */\nexport function getAllPluginRuntimeStates(): PluginRuntimeState {\n return { ...runtimeState };\n}","/**\n * Mioku - Plugin framework extended from mioki\n *\n * Main entry point for the mioku npm package\n */\n\nimport pluginManager from \"./core/plugin-manager\";\nimport serviceManager from \"./core/service-manager\";\nimport { registerPluginArtifacts } from \"./core/plugin-artifact-registry\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { existsSync, mkdirSync } from \"fs\";\nimport {\n DEFAULT_RUNTIME_PLUGINS_DIR,\n prepareRuntimePluginLinks,\n} from \"./core/plugin-linker\";\nimport { setMiokuLogger } from \"./core/logger\";\n\n// Re-export mioki types for convenience\nexport type { MiokiPlugin, MiokiContext } from \"mioki\";\n\nexport function definePlugin<T extends import(\"mioki\").MiokiPlugin>(\n plugin: T,\n): T {\n return plugin;\n}\n\n// Core functionality\nexport { default as pluginManager } from \"./core/plugin-manager\";\nexport { default as serviceManager } from \"./core/service-manager\";\nexport { registerPluginArtifacts } from \"./core/plugin-artifact-registry\";\n\n// Types from types.ts\nexport type {\n MiokuService,\n PluginMetadata,\n ServiceMetadata,\n PluginPackageConfig,\n PluginHelp,\n CommandRole,\n} from \"./types\";\n\n// Service types from service-types.ts\nexport type {\n ConfigService,\n ScreenshotService,\n HelpService,\n WebUIService,\n AITool,\n AISkill,\n AIInstance,\n AIService,\n ChatRuntime,\n TextMessage,\n MultimodalMessage,\n ToolCallRecord,\n CompleteOptions,\n CompleteResponse,\n SessionToolDefinition,\n SkillPermissionRole,\n MultimodalContentItem,\n ToolResultFollowup,\n ChatRuntimePromptInjection,\n ChatRuntimeGroupTarget,\n ChatRuntimePrivateTarget,\n ChatRuntimeSource,\n ChatRuntimeBaseOptions,\n ChatRuntimeNoticeOptions,\n ChatRuntimeInformationRequestOptions,\n ChatRuntimeCollectedInfo,\n ChatRuntimeResult,\n AIUsageRange,\n AIUsageContext,\n AIUsageBreakdown,\n AIUsageFinalization,\n AIUsageSummary,\n} from \"./service-types\";\n\nexport { TOOL_RESULT_FOLLOWUP_KEY } from \"./service-types\";\n\n/**\n * Start options for Mioku\n */\nexport interface MiokuStartOptions {\n cwd?: string;\n}\n\n/**\n * Start Mioku with plugin and service discovery\n */\nexport async function start(options: MiokuStartOptions = {}): Promise<void> {\n const { cwd = process.cwd() } = options;\n\n if (cwd) {\n process.chdir(cwd);\n }\n\n const { start: startMioki, logger, botConfig } = await import(\"mioki\");\n setMiokuLogger(logger);\n\n // Read mioku config from package.json (mioki field contains merged config)\n const packageJsonPath = path.join(process.cwd(), \"package.json\");\n let miokuConfig: any = {};\n if (fs.existsSync(packageJsonPath)) {\n const pkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n // mioku-specific config lives in the same mioki field\n miokuConfig = pkg.mioki || {};\n }\n\n logger.info(\"こんにちは..\");\n logger.info(\"---------------------------------------\");\n logger.info(\"---------- Mioku 正在启动 ------------\");\n logger.info(\"---------------------------------------\");\n\n // Ensure required directories exist\n const requiredDirs = [\"data\", \"config\", \"temp\"];\n for (const dir of requiredDirs) {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n logger.info(\"O.o Miku 正在翻找插件..\");\n const discoveredPlugins = await pluginManager.discoverPlugins(miokuConfig);\n logger.info(`O.o 共发现 ${discoveredPlugins.length} 个插件: ${discoveredPlugins.map(p => p.name).join(\", \")}`);\n\n const runtimePluginsDir = path.resolve(\n process.cwd(),\n DEFAULT_RUNTIME_PLUGINS_DIR,\n );\n const linkedPluginNames = await prepareRuntimePluginLinks(\n discoveredPlugins,\n runtimePluginsDir,\n );\n botConfig.plugins_dir = DEFAULT_RUNTIME_PLUGINS_DIR;\n\n logger.info(\"o.O Miku 正在翻找服务..\");\n await serviceManager.discoverServices(miokuConfig);\n\n const requiredServices = pluginManager.collectRequiredServices();\n const missingServices =\n await serviceManager.checkMissingServices(requiredServices);\n\n if (missingServices.length > 0) {\n logger.warn(`发现缺失服务: ${missingServices.join(\", \")}`);\n }\n\n // Only auto-load discovered plugins if the user has not specified a plugins list.\n // \"not specified\" means plugins key is undefined in mioki config.\n // If plugins is explicitly set (even to empty array []), only load what's in the list.\n const userSpecifiedPlugins = miokuConfig.plugins !== undefined;\n if (!userSpecifiedPlugins) {\n for (const name of linkedPluginNames) {\n if (!botConfig.plugins.includes(name)) {\n botConfig.plugins.push(name);\n }\n }\n }\n\n await startMioki({ cwd });\n}\n\n// Version\nexport const version = \"1.0.0\";\n\n// Data path utilities\nexport {\n getDataDir,\n getPluginDataDir,\n getServiceDataDir,\n getConfigDir,\n getPluginConfigDir,\n getServiceConfigDir,\n ensureDataDir,\n} from \"./core/data-paths\";\n\n// Plugin runtime state\nexport {\n getPluginRuntimeState,\n setPluginRuntimeState,\n resetPluginRuntimeState,\n} from \"./core/plugin-runtime-state\";\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -95,7 +95,8 @@ async function ensurePluginLink(runtimePluginsDir, metadata) {
|
|
|
95
95
|
logger.warn(`[plugin-linker] Plugin target missing, skip linking ${metadata.name}: ${targetPath}`);
|
|
96
96
|
return false;
|
|
97
97
|
}
|
|
98
|
-
await fs$4.symlink(
|
|
98
|
+
if (process.platform === "win32") await fs$4.symlink(targetPath, linkPath, "junction");
|
|
99
|
+
else await fs$4.symlink(relativeSymlinkTarget(linkPath, targetPath), linkPath, "dir");
|
|
99
100
|
return true;
|
|
100
101
|
}
|
|
101
102
|
async function prepareRuntimePluginLinks(plugins, runtimePluginsDir = path$5.resolve(process.cwd(), DEFAULT_RUNTIME_PLUGINS_DIR)) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["fallbackLogger: MiokuLogger","activeLogger: MiokuLogger","logger: MiokuLogger | undefined","logger","logger: MiokuLogger","pathExists","filePath: string","entryPath: string","linkPath: string","targetPath: string","runtimePluginsDir: string","metadata: PluginMetadata","plugins: PluginMetadata[]","linkedNames: string[]","pathExists","filePath: string","miokuConfig: any","discovered: PluginMetadata[]","pluginsDir: string","entryPath: string","name: string","pluginPath: string","packageJson: any","metadata: PluginMetadata","pathExists","filePath: string","miokuConfig: any","discovered: ServiceMetadata[]","servicesDir: string","name: string","servicePath: string","metadata: ServiceMetadata","error: any","requiredServices: Set<string>","missing: string[]","ctx: MiokiContext","service: MiokuService","filePath: string","value: any","moduleExports: any","pluginPath: string","ctx: MiokiContext","error: any","pluginName: string","serviceName: string","runtimeState: PluginRuntimeState","pluginName: string","state: Record<string, any>","plugin: T","options: MiokuStartOptions","logger","miokuConfig: any"],"sources":["../src/core/logger.ts","../src/core/plugin-linker.ts","../src/core/plugin-manager.ts","../src/core/service-manager.ts","../src/core/plugin-artifact-registry.ts","../src/service-types.ts","../src/core/data-paths.ts","../src/core/plugin-runtime-state.ts","../src/index.ts"],"sourcesContent":["type LogMethod = (...args: unknown[]) => void;\n\nexport interface MiokuLogger {\n error: LogMethod;\n warn: LogMethod;\n info: LogMethod;\n debug: LogMethod;\n trace?: LogMethod;\n}\n\nconst fallbackLogger: MiokuLogger = {\n error: (...args) => console.error(...args),\n warn: (...args) => console.warn(...args),\n info: (...args) => console.info(...args),\n debug: (...args) => console.debug(...args),\n trace: (...args) => console.debug(...args),\n};\n\nlet activeLogger: MiokuLogger = fallbackLogger;\n\nexport function setMiokuLogger(logger: MiokuLogger | undefined): void {\n activeLogger = logger || fallbackLogger;\n}\n\nexport function getMiokuLogger(): MiokuLogger {\n return activeLogger;\n}\n\nexport const logger: MiokuLogger = {\n error: (...args) => activeLogger.error(...args),\n warn: (...args) => activeLogger.warn(...args),\n info: (...args) => activeLogger.info(...args),\n debug: (...args) => activeLogger.debug(...args),\n trace: (...args) => activeLogger.trace?.(...args),\n};\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport type { PluginMetadata } from \"./types\";\nimport { logger } from \"./logger\";\n\nexport const DEFAULT_RUNTIME_PLUGINS_DIR = \".mioku/plugins\";\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function removeIfBrokenSymlink(entryPath: string): Promise<\"ok\" | \"blocked\" | \"removed\"> {\n let stat;\n try {\n stat = await fs.lstat(entryPath);\n } catch {\n return \"removed\";\n }\n\n if (!stat.isSymbolicLink()) {\n return \"blocked\";\n }\n\n try {\n await fs.realpath(entryPath);\n return \"ok\";\n } catch {\n await fs.rm(entryPath, { force: true });\n logger.warn(`[plugin-linker] Removed broken plugin link: ${entryPath}`);\n return \"removed\";\n }\n}\n\nfunction relativeSymlinkTarget(linkPath: string, targetPath: string): string {\n const relativePath = path.relative(path.dirname(linkPath), targetPath);\n return relativePath || \".\";\n}\n\nasync function ensurePluginLink(\n runtimePluginsDir: string,\n metadata: PluginMetadata,\n): Promise<boolean> {\n const linkPath = path.join(runtimePluginsDir, metadata.name);\n const targetPath = metadata.path;\n\n let stat;\n try {\n stat = await fs.lstat(linkPath);\n } catch {\n stat = null;\n }\n\n if (stat?.isSymbolicLink()) {\n try {\n const currentTarget = await fs.realpath(linkPath);\n const expectedTarget = await fs.realpath(targetPath);\n if (currentTarget === expectedTarget) {\n return true;\n }\n await fs.rm(linkPath, { force: true });\n logger.info(`[plugin-linker] Rebuilding plugin link: ${metadata.name}`);\n } catch {\n await fs.rm(linkPath, { force: true });\n logger.warn(`[plugin-linker] Removed broken plugin link: ${linkPath}`);\n }\n } else if (stat) {\n logger.warn(\n `[plugin-linker] ${linkPath} exists and is not a symlink, skip linking ${metadata.name}`,\n );\n return false;\n }\n\n if (!(await pathExists(targetPath))) {\n logger.warn(\n `[plugin-linker] Plugin target missing, skip linking ${metadata.name}: ${targetPath}`,\n );\n return false;\n }\n\n await fs.symlink(relativeSymlinkTarget(linkPath, targetPath), linkPath, \"dir\");\n return true;\n}\n\nexport async function prepareRuntimePluginLinks(\n plugins: PluginMetadata[],\n runtimePluginsDir = path.resolve(process.cwd(), DEFAULT_RUNTIME_PLUGINS_DIR),\n): Promise<string[]> {\n await fs.mkdir(runtimePluginsDir, { recursive: true });\n\n const discoveredNames = new Set(plugins.map((plugin) => plugin.name));\n const entries = await fs.readdir(runtimePluginsDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = path.join(runtimePluginsDir, entry.name);\n const symlinkState = await removeIfBrokenSymlink(entryPath);\n if (symlinkState !== \"ok\") {\n continue;\n }\n\n if (entry.isSymbolicLink() && !discoveredNames.has(entry.name)) {\n await fs.rm(entryPath, { force: true });\n logger.info(`[plugin-linker] Removed stale plugin link: ${entry.name}`);\n }\n }\n\n const linkedNames: string[] = [];\n for (const metadata of plugins) {\n if (await ensurePluginLink(runtimePluginsDir, metadata)) {\n linkedNames.push(metadata.name);\n }\n }\n\n return linkedNames;\n}\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport { mkdirSync } from \"fs\";\nimport type { PluginMetadata } from \"./types\";\nimport { DEFAULT_RUNTIME_PLUGINS_DIR } from \"./plugin-linker\";\nimport { logger } from \"./logger\";\n\nconst PLUGIN_MANAGER_SYMBOL = Symbol.for(\"mioku.plugin-manager\");\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * 插件管理器\n *\n * Discover and manage plugins from both local directories and node_modules.\n */\nexport class PluginManager {\n private pluginMetadata: Map<string, PluginMetadata> = new Map();\n\n public static getInstance(): PluginManager {\n const g = global as any;\n if (!g[PLUGIN_MANAGER_SYMBOL]) {\n g[PLUGIN_MANAGER_SYMBOL] = new PluginManager();\n }\n return g[PLUGIN_MANAGER_SYMBOL];\n }\n\n async discoverPlugins(miokuConfig: any = {}): Promise<PluginMetadata[]> {\n // Resolve pluginsDir dynamically so it uses the current cwd\n const configuredPluginsDir = miokuConfig.plugins_dir;\n const pluginsDir =\n configuredPluginsDir && configuredPluginsDir !== DEFAULT_RUNTIME_PLUGINS_DIR\n ? path.resolve(process.cwd(), configuredPluginsDir)\n : path.resolve(process.cwd(), \"plugins\");\n\n this.pluginMetadata.clear();\n\n // Ensure plugins directory exists\n if (!(await pathExists(pluginsDir))) {\n mkdirSync(pluginsDir, { recursive: true });\n }\n\n const discovered: PluginMetadata[] = [];\n\n // Discover from local plugins/ directory\n if (await pathExists(pluginsDir)) {\n const localPlugins = await this.discoverFromDir(pluginsDir);\n discovered.push(...localPlugins);\n }\n\n // Discover from node_modules (mioku-plugin-* prefix)\n const nodeModulesPlugins = await this.discoverFromNodeModules();\n discovered.push(...nodeModulesPlugins);\n\n logger.info(`O.o 发现了 ${this.pluginMetadata.size} 个插件`);\n return Array.from(this.pluginMetadata.values());\n }\n\n private async discoverFromDir(pluginsDir: string): Promise<PluginMetadata[]> {\n const discovered: PluginMetadata[] = [];\n\n try {\n const entries = await fs.readdir(pluginsDir, { withFileTypes: true });\n for (const entry of entries) {\n const pluginPath = path.join(pluginsDir, entry.name);\n const metadataPath = await this.resolveDirectoryPath(pluginPath);\n if (!metadataPath) continue;\n\n const metadata = await this.loadPluginMetadata(entry.name, pluginPath);\n if (metadata) {\n discovered.push(metadata);\n this.pluginMetadata.set(metadata.name, metadata);\n }\n }\n } catch (error) {\n logger.error(`扫描插件目录失败: ${error}`);\n }\n\n return discovered;\n }\n\n private async discoverFromNodeModules(): Promise<PluginMetadata[]> {\n const discovered: PluginMetadata[] = [];\n const nodeModulesPath = path.resolve(process.cwd(), \"node_modules\");\n\n if (!(await pathExists(nodeModulesPath))) {\n return discovered;\n }\n\n try {\n const entries = await fs.readdir(nodeModulesPath, { withFileTypes: true });\n for (const entry of entries) {\n // Check for mioku-plugin-* prefix (don't check isDirectory - symlinks return false)\n if (!entry.name.startsWith(\"mioku-plugin-\")) {\n continue;\n }\n\n const pluginName = entry.name.replace(/^mioku-plugin-/, \"\");\n const pluginPath = path.join(nodeModulesPath, entry.name);\n const metadata = await this.loadPluginMetadata(pluginName, pluginPath);\n if (metadata) {\n discovered.push(metadata);\n this.pluginMetadata.set(metadata.name, metadata);\n }\n }\n } catch (error) {\n logger.debug(`扫描 node_modules 插件失败: ${error}`);\n }\n\n return discovered;\n }\n\n private async resolveDirectoryPath(entryPath: string): Promise<string | null> {\n try {\n const stat = await fs.stat(entryPath);\n return stat.isDirectory() ? entryPath : null;\n } catch {\n return null;\n }\n }\n\n private async loadPluginMetadata(\n name: string,\n pluginPath: string,\n ): Promise<PluginMetadata | null> {\n // Resolve symlinks to get actual path\n let resolvedPath = pluginPath;\n try {\n resolvedPath = await fs.realpath(pluginPath);\n } catch {\n // Not a symlink or doesn't exist, use original path\n }\n\n const packageJsonPath = path.join(resolvedPath, \"package.json\");\n\n let packageJson: any = null;\n try {\n const content = await fs.readFile(packageJsonPath, \"utf-8\");\n packageJson = JSON.parse(content);\n } catch {\n // File doesn't exist or can't be read - plugin uses defaults\n }\n\n const metadata: PluginMetadata = {\n name,\n version: packageJson?.version || \"0.0.0\",\n description: packageJson?.description,\n path: resolvedPath,\n packageJson,\n config: packageJson?.mioku || {},\n };\n return metadata;\n }\n\n collectRequiredServices(): Set<string> {\n const services = new Set<string>();\n for (const metadata of this.pluginMetadata.values()) {\n if (metadata.config.services) {\n metadata.config.services.forEach((s) => services.add(s));\n }\n }\n return services;\n }\n\n getPluginMetadata(name: string): PluginMetadata | undefined {\n return this.pluginMetadata.get(name);\n }\n\n getAllMetadata(): PluginMetadata[] {\n return Array.from(this.pluginMetadata.values());\n }\n\n reset(): void {\n this.pluginMetadata.clear();\n }\n}\n\nexport default PluginManager.getInstance();\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport { existsSync, mkdirSync } from \"fs\";\nimport type { MiokiContext } from \"mioki\";\nimport type { ServiceMetadata, MiokuService } from \"./types\";\nimport { logger } from \"./logger\";\n\nconst SERVICE_MANAGER_SYMBOL = Symbol.for(\"mioku.service-manager\");\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * 服务管理器\n */\nexport class ServiceManager {\n private services: Map<string, MiokuService> = new Map();\n private serviceMetadata: Map<string, ServiceMetadata> = new Map();\n private servicesDir: string = \"services\";\n\n public static getInstance(): ServiceManager {\n const g = global as any;\n if (!g[SERVICE_MANAGER_SYMBOL]) {\n g[SERVICE_MANAGER_SYMBOL] = new ServiceManager();\n }\n return g[SERVICE_MANAGER_SYMBOL];\n }\n\n async discoverServices(miokuConfig: any = {}): Promise<ServiceMetadata[]> {\n // Use services_dir from mioku config if provided, otherwise default to \"services\" in project root\n if (miokuConfig.services_dir) {\n this.servicesDir = path.resolve(process.cwd(), miokuConfig.services_dir);\n } else {\n this.servicesDir = path.resolve(process.cwd(), \"services\");\n }\n\n const discovered: ServiceMetadata[] = [];\n this.serviceMetadata.clear();\n\n // Discover from local services/ directory\n if (existsSync(this.servicesDir)) {\n const localServices = await this.discoverFromDir(this.servicesDir);\n discovered.push(...localServices);\n } else {\n // Ensure the directory exists for user services\n mkdirSync(this.servicesDir, { recursive: true });\n }\n\n // Discover builtin services (config, ai, screenshot, webui)\n await this.loadBuiltinServices();\n\n logger.info(`o.O 发现了 ${this.serviceMetadata.size} 个服务`);\n return Array.from(this.serviceMetadata.values());\n }\n\n private async discoverFromDir(servicesDir: string): Promise<ServiceMetadata[]> {\n const discovered: ServiceMetadata[] = [];\n\n try {\n const entries = await fs.readdir(servicesDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const servicePath = path.join(servicesDir, entry.name);\n const metadata = await this.loadServiceMetadata(entry.name, servicePath);\n if (metadata) {\n discovered.push(metadata);\n this.serviceMetadata.set(entry.name, metadata);\n }\n }\n } catch (error) {\n logger.error(`扫描服务目录失败: ${error}`);\n }\n\n return discovered;\n }\n\n private async loadServiceMetadata(\n name: string,\n servicePath: string,\n ): Promise<ServiceMetadata | null> {\n // Resolve symlinks to get actual path\n let resolvedPath = servicePath;\n try {\n resolvedPath = await fs.realpath(servicePath);\n } catch {\n // Not a symlink or doesn't exist, use original path\n }\n\n const packageJsonPath = path.join(resolvedPath, \"package.json\");\n\n if (!(await pathExists(packageJsonPath))) {\n return null;\n }\n\n try {\n const packageJson = JSON.parse(\n await fs.readFile(packageJsonPath, \"utf-8\"),\n );\n const metadata: ServiceMetadata = {\n name,\n version: packageJson.version || \"0.0.0\",\n description: packageJson.description,\n path: resolvedPath,\n packageJson,\n };\n return metadata;\n } catch (error: any) {\n logger.error(`解析服务 ${name} 失败: ${error.message}`);\n return null;\n }\n }\n\n /**\n * Load built-in services from the package\n */\n private async loadBuiltinServices(): Promise<void> {\n // Discover from node_modules (mioku-service-* prefix)\n await this.discoverFromNodeModules();\n }\n\n private async discoverFromNodeModules(): Promise<void> {\n const nodeModulesPath = path.resolve(process.cwd(), \"node_modules\");\n\n if (!(await pathExists(nodeModulesPath))) {\n return;\n }\n\n try {\n const entries = await fs.readdir(nodeModulesPath, { withFileTypes: true });\n for (const entry of entries) {\n // Don't check isDirectory - symlinks return false\n if (!entry.name.startsWith(\"mioku-service-\")) {\n continue;\n }\n\n const serviceName = entry.name.replace(/^mioku-service-/, \"\");\n const servicePath = path.join(nodeModulesPath, entry.name);\n const metadata = await this.loadServiceMetadata(serviceName, servicePath);\n if (metadata) {\n this.serviceMetadata.set(serviceName, metadata);\n }\n }\n } catch (error) {\n logger.debug(`扫描 node_modules 服务失败: ${error}`);\n }\n }\n\n async checkMissingServices(requiredServices: Set<string>): Promise<string[]> {\n const missing: string[] = [];\n for (const serviceName of requiredServices) {\n if (!this.serviceMetadata.has(serviceName)) {\n missing.push(serviceName);\n }\n }\n return missing;\n }\n\n async loadAllServices(ctx: MiokiContext): Promise<void> {\n const allMetadata = Array.from(this.serviceMetadata.values());\n logger.info(`O.o 准备加载 ${allMetadata.length} 个服务...`);\n\n for (const metadata of allMetadata) {\n await this.loadService(metadata, ctx);\n }\n }\n\n private async loadService(\n metadata: ServiceMetadata,\n ctx: MiokiContext,\n ): Promise<boolean> {\n try {\n const indexPath = path.join(metadata.path, \"index.ts\");\n const indexJsPath = path.join(metadata.path, \"index.js\");\n const indexExists = await pathExists(indexPath);\n const indexJsExists = await pathExists(indexJsPath);\n const entryPoint = indexExists ? indexPath : indexJsPath;\n\n if (!entryPoint || (!indexExists && !indexJsExists)) {\n logger.error(`服务 ${metadata.name} 入口丢失`);\n return false;\n }\n\n let importPath = entryPoint;\n if (process.platform === \"win32\") {\n importPath = \"file:///\" + entryPoint.replace(/\\\\/g, \"/\");\n }\n\n const serviceModule = await import(importPath);\n const service: MiokuService = serviceModule.default || serviceModule;\n\n if (!service || typeof service.init !== \"function\") return false;\n\n await service.init();\n if (service.api) {\n if (!(ctx as any).services) (ctx as any).services = {};\n (ctx as any).services[metadata.name] = service.api;\n }\n\n this.services.set(metadata.name, service);\n return true;\n } catch (error: any) {\n logger.error(`加载服务 ${metadata.name} 失败: ${error.message}`);\n return false;\n }\n }\n\n /**\n * Register a builtin service directly\n */\n registerBuiltinService(name: string, service: MiokuService): void {\n this.services.set(name, service);\n }\n\n /**\n * Get a loaded service\n */\n getService(name: string): MiokuService | undefined {\n return this.services.get(name);\n }\n\n async disposeAll(): Promise<void> {\n for (const [name, service] of this.services) {\n if (service.dispose) await service.dispose();\n }\n this.services.clear();\n }\n\n reset(): void {\n this.services.clear();\n this.serviceMetadata.clear();\n }\n}\n\nexport default ServiceManager.getInstance();\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport type { MiokiContext } from \"mioki\";\nimport type { AIService } from \"../types\";\nimport type { HelpService } from \"../service-types\";\nimport type { AISkill } from \"./types\";\nimport pluginManager from \"./plugin-manager\";\nimport { logger } from \"./logger\";\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction toImportPath(filePath: string): string {\n if (process.platform === \"win32\") {\n return \"file:///\" + filePath.replace(/\\\\/g, \"/\");\n }\n return filePath;\n}\n\nfunction isAISkill(value: any): value is AISkill {\n return (\n value &&\n typeof value === \"object\" &&\n typeof value.name === \"string\" &&\n Array.isArray(value.tools)\n );\n}\n\nfunction extractSkills(moduleExports: any): AISkill[] {\n const candidates = [\n moduleExports?.default,\n moduleExports?.skills,\n moduleExports,\n ];\n\n for (const candidate of candidates) {\n if (Array.isArray(candidate)) {\n return candidate.filter(isAISkill);\n }\n if (isAISkill(candidate)) {\n return [candidate];\n }\n }\n\n return [];\n}\n\nasync function resolveSkillsEntry(pluginPath: string): Promise<string | null> {\n const tsPath = path.join(pluginPath, \"skills.ts\");\n if (await pathExists(tsPath)) {\n return tsPath;\n }\n\n const jsPath = path.join(pluginPath, \"skills.js\");\n if (await pathExists(jsPath)) {\n return jsPath;\n }\n\n return null;\n}\n\n/**\n * Auto-register plugin help manifests and AI skills\n */\nexport async function registerPluginArtifacts(\n ctx: MiokiContext,\n): Promise<void> {\n const enabledPlugins = new Set<string>(\n Array.isArray((ctx as any).botConfig?.plugins)\n ? (ctx as any).botConfig.plugins\n : [],\n );\n const pluginMetadata = pluginManager\n .getAllMetadata()\n .filter((metadata) =>\n enabledPlugins.size > 0 ? enabledPlugins.has(metadata.name) : true,\n );\n\n const helpService = ctx.services?.help as HelpService | undefined;\n const aiService = ctx.services?.ai as AIService | undefined;\n\n if (helpService) {\n let helpCount = 0;\n for (const metadata of pluginMetadata) {\n if (!metadata.config.help) {\n continue;\n }\n helpService.registerHelp(metadata.name, metadata.config.help);\n helpCount += 1;\n }\n logger.info(`[plugin-artifacts] Registered ${helpCount} help manifest(s)`);\n }\n\n if (!aiService) {\n return;\n }\n\n let skillCount = 0;\n for (const metadata of pluginMetadata) {\n const skillsEntry = await resolveSkillsEntry(metadata.path);\n if (!skillsEntry) {\n continue;\n }\n\n try {\n const moduleExports = await import(toImportPath(skillsEntry));\n const skills = extractSkills(moduleExports);\n\n if (skills.length === 0) {\n logger.warn(\n `[plugin-artifacts] Plugin ${metadata.name} has ${path.basename(skillsEntry)} but exported no valid skill`,\n );\n continue;\n }\n\n for (const skill of skills) {\n aiService.registerSkill(skill);\n skillCount += 1;\n }\n } catch (error: any) {\n logger.error(\n `[plugin-artifacts] Failed to load skills for plugin ${metadata.name}: ${error?.message || error}`,\n );\n }\n }\n\n logger.info(`[plugin-artifacts] Registered ${skillCount} skill(s)`);\n}\n","/**\n * Service interface definitions for built-in services\n * These are used for type annotations in plugins\n */\n\n// ============ Core Service Interfaces ============\n\n// Config Service\nexport interface ConfigService {\n registerConfig(pluginName: string, configName: string, initialConfig: any): Promise<boolean>;\n updateConfig(pluginName: string, configName: string, updates: any): Promise<boolean>;\n getConfig(pluginName: string, configName: string): Promise<any>;\n getPluginConfigs(pluginName: string): Promise<Record<string, any>>;\n onConfigChange(pluginName: string, configName: string, callback: (newConfig: any) => void): () => void;\n}\n\n// Screenshot Service\nexport interface ScreenshotService {\n screenshot(html: string, options?: any): Promise<string>;\n screenshotMarkdown(markdownContent: string, options?: any): Promise<string>;\n screenshotFromUrl(url: string, options?: any): Promise<string>;\n cleanupTemp(olderThanMs?: number): Promise<number>;\n}\n\n// Help Service\nexport interface HelpService {\n registerHelp(pluginName: string, help: any): void;\n getHelp(pluginName: string): any;\n getAllHelp(): Map<string, any>;\n unregisterHelp(pluginName: string): void;\n}\n\n// WebUI Service\nexport interface WebUIService {\n getSettings(): { port: number; host: string; packageManager: string };\n}\n\n// ============ AI Service Types ============\n\nexport interface AITool {\n name: string;\n description: string;\n parameters: {\n type: \"object\";\n properties: Record<string, any>;\n required?: string[];\n };\n handler: (args: any, event?: any) => Promise<any> | any;\n}\n\nexport interface AISkill {\n name: string;\n description: string;\n permission?: \"owner\" | \"admin\" | \"member\";\n tools: AITool[];\n}\n\nexport interface TextMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\nexport interface MultimodalMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string | MultimodalContentItem[];\n}\n\nexport interface ToolCallRecord {\n name: string;\n arguments: any;\n result: any;\n}\n\nexport interface SessionToolDefinition {\n name: string;\n tool: AITool;\n}\n\nexport interface CompleteOptions {\n model?: string;\n messages: any[];\n temperature?: number;\n max_tokens?: number;\n stream?: boolean;\n tools?: any[];\n executableTools?: SessionToolDefinition[];\n executableToolsProvider?: () => SessionToolDefinition[];\n maxIterations?: number;\n onTextDelta?: (delta: string) => void | Promise<void>;\n usageContext?: AIUsageContext;\n usageContextTokens?: number;\n usageBreakdown?: AIUsageFinalization[\"breakdown\"];\n}\n\nexport interface CompleteResponse {\n content: string | null;\n reasoning: string | null;\n toolCalls: Array<{ id: string; name: string; arguments: string }>;\n raw: any;\n turnMessages: any[];\n iterations?: number;\n allToolCalls?: ToolCallRecord[];\n}\n\nexport interface ChatRuntime {\n generateNotice(options: ChatRuntimeNoticeOptions): Promise<ChatRuntimeResult>;\n requestInformation(options: ChatRuntimeInformationRequestOptions): Promise<ChatRuntimeResult>;\n}\n\nexport const TOOL_RESULT_FOLLOWUP_KEY = \"__miokuFollowup\";\n\nexport interface ToolResultFollowup {\n text: string;\n images: Array<{\n url: string;\n detail?: \"auto\" | \"low\" | \"high\";\n }>;\n}\n\n// Permission role for skills\nexport type SkillPermissionRole = \"owner\" | \"admin\" | \"member\";\n\n// Multimodal content item\nexport interface MultimodalContentItem {\n type: \"text\" | \"image_url\";\n text?: string;\n image_url?: {\n url: string;\n detail?: \"auto\" | \"low\" | \"high\";\n };\n}\n\n// Chat runtime types\nexport interface ChatRuntimePromptInjection {\n content: string;\n title?: string;\n}\n\nexport interface ChatRuntimeGroupTarget {\n selfId: number;\n groupId: number;\n}\n\nexport interface ChatRuntimePrivateTarget {\n selfId: number;\n userId: number;\n}\n\nexport type ChatRuntimeSource =\n | { event: any }\n | ChatRuntimeGroupTarget\n | ChatRuntimePrivateTarget;\n\nexport type ChatRuntimeBaseOptions = ChatRuntimeSource & {\n targetMessage?: string;\n promptInjections?: ChatRuntimePromptInjection[];\n send?: boolean;\n};\n\nexport type ChatRuntimeNoticeOptions = ChatRuntimeBaseOptions & {\n instruction: string;\n};\n\nexport type ChatRuntimeInformationRequestOptions = ChatRuntimeBaseOptions & {\n task: string;\n schema: {\n type: \"object\";\n properties: Record<string, any>;\n required?: string[];\n };\n toolName?: string;\n toolDescription?: string;\n};\n\nexport interface ChatRuntimeCollectedInfo {\n data: any;\n isComplete?: boolean;\n confidence?: number;\n notes?: string;\n}\n\nexport type AIUsageRange = \"today\" | \"7d\" | \"30d\";\n\nexport interface AIUsageContext {\n usageId?: string;\n source?: string;\n botId?: number;\n groupId?: number;\n groupName?: string;\n userId?: number;\n userName?: string;\n sessionId?: string;\n}\n\nexport interface AIUsageBreakdown {\n systemPromptTokens?: number;\n chatHistoryTokens?: number;\n toolDefinitionTokens?: number;\n toolUseTokens?: number;\n otherContextTokens?: number;\n}\n\nexport interface AIUsageFinalization {\n sentUserMessages?: number;\n sentAssistantMessages?: number;\n breakdown?: AIUsageBreakdown;\n}\n\nexport interface AIUsageSummary {\n range: AIUsageRange;\n total: {\n requests: number;\n inputTokens: number;\n outputTokens: number;\n cacheWriteTokens: number;\n cacheReadTokens: number;\n totalTokens: number;\n };\n byBot: Array<{\n botId: number | null;\n requests: number;\n inputTokens: number;\n outputTokens: number;\n cacheWriteTokens: number;\n cacheReadTokens: number;\n totalTokens: number;\n }>;\n}\n\nexport interface ChatRuntimeResult {\n messages: string[];\n toolCalls: ToolCallRecord[];\n collectedInfo: ChatRuntimeCollectedInfo | null;\n pendingAt?: number[];\n pendingPoke?: number[];\n pendingQuote?: number;\n emojiPath?: string | null;\n protocolMessages?: any[];\n}\n\nexport interface LegacyChatRuntimeNoticeOptions {\n sessionId: string;\n groupId?: number;\n userId: number;\n message: string;\n replyContextType: string;\n}\n\nexport interface LegacyChatRuntimeInformationRequestOptions {\n sessionId: string;\n groupId?: number;\n userId: number;\n prompt: string;\n injectHistoryCount?: number;\n}\n\n// ============ AI Service Interfaces ============\n\nexport interface AIInstance {\n generateText(options: { prompt?: string; messages: TextMessage[]; model?: string; temperature?: number; max_tokens?: number }): Promise<string>;\n generateMultimodal(options: { prompt?: string; messages: MultimodalMessage[]; model?: string; temperature?: number; max_tokens?: number }): Promise<string>;\n complete(options: CompleteOptions): Promise<CompleteResponse>;\n generateWithTools(options: { prompt?: string; messages: TextMessage[] | MultimodalMessage[]; model?: string; temperature?: number; maxIterations?: number }): Promise<any>;\n setUsageContext?(context: AIUsageContext | undefined): void;\n withUsageContext?<T>(context: AIUsageContext | undefined, fn: () => Promise<T>): Promise<T>;\n registerPrompt(name: string, prompt: string): boolean;\n getPrompt(name: string): string | undefined;\n getAllPrompts(): Record<string, string>;\n removePrompt(name: string): boolean;\n}\n\nexport interface AIService {\n create(options: { name: string; apiUrl: string; apiKey: string; modelType: \"text\" | \"multimodal\"; model?: string }): Promise<AIInstance>;\n get(name: string): AIInstance | undefined;\n list(): string[];\n remove(name: string): boolean;\n setDefault(name: string): boolean;\n getDefault(): AIInstance | undefined;\n registerChatRuntime(runtime: any): boolean;\n getChatRuntime(): any;\n removeChatRuntime(): boolean;\n registerSkill(skill: AISkill): boolean;\n getSkill(skillName: string): AISkill | undefined;\n getAllSkills(): Map<string, AISkill>;\n removeSkill(skillName: string): boolean;\n getTool(toolName: string): AITool | undefined;\n getAllTools(): Map<string, AITool>;\n getUsageSummary?(options: { range: AIUsageRange; botId?: number }): AIUsageSummary;\n cleanupUsageStats?(retentionMs?: number): number;\n finalizeUsage?(usageId: string, finalization: AIUsageFinalization): boolean;\n}\n","/**\n * Data Directory Utilities for Mioku Plugins\n *\n * Provides consistent data path resolution that respects the project directory\n * (process.cwd()) rather than the package installation directory.\n */\n\nimport * as path from \"path\";\n\n/**\n * Get the data directory for a specific plugin\n * Returns: {cwd}/data/{pluginName}\n */\nexport function getPluginDataDir(pluginName: string): string {\n const dataDir = path.join(process.cwd(), \"data\", pluginName);\n return dataDir;\n}\n\n/**\n * Get the data directory for a service\n * Returns: {cwd}/data/{serviceName}\n */\nexport function getServiceDataDir(serviceName: string): string {\n const dataDir = path.join(process.cwd(), \"data\", serviceName);\n return dataDir;\n}\n\n/**\n * Get the main data directory\n * Returns: {cwd}/data\n */\nexport function getDataDir(): string {\n return path.join(process.cwd(), \"data\");\n}\n\n/**\n * Get the config directory for a plugin\n * Returns: {cwd}/config/{pluginName}\n */\nexport function getPluginConfigDir(pluginName: string): string {\n const configDir = path.join(process.cwd(), \"config\", pluginName);\n return configDir;\n}\n\n/**\n * Get the config directory for a service\n * Returns: {cwd}/config/{serviceName}\n */\nexport function getServiceConfigDir(serviceName: string): string {\n const configDir = path.join(process.cwd(), \"config\", serviceName);\n return configDir;\n}\n\n/**\n * Get the main config directory\n * Returns: {cwd}/config\n */\nexport function getConfigDir(): string {\n return path.join(process.cwd(), \"config\");\n}\n\n/**\n * Ensure a directory exists, creating it if necessary\n */\nexport function ensureDataDir(pluginName: string): string {\n const dir = getPluginDataDir(pluginName);\n const { existsSync, mkdirSync } = require(\"fs\");\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n return dir;\n}","/**\n * Plugin Runtime State Management\n *\n * Provides a way for plugins to store state that needs to persist\n * across the plugin lifecycle but should be isolated per plugin.\n */\n\ninterface PluginRuntimeState {\n [pluginName: string]: Record<string, any>;\n}\n\nconst runtimeState: PluginRuntimeState = {};\n\n/**\n * Get the runtime state for a plugin\n */\nexport function getPluginRuntimeState(pluginName: string): Record<string, any> {\n if (!runtimeState[pluginName]) {\n runtimeState[pluginName] = {};\n }\n return runtimeState[pluginName];\n}\n\n/**\n * Set/update the runtime state for a plugin\n */\nexport function setPluginRuntimeState(\n pluginName: string,\n state: Record<string, any>,\n): Record<string, any> {\n if (!runtimeState[pluginName]) {\n runtimeState[pluginName] = {};\n }\n Object.assign(runtimeState[pluginName], state);\n return runtimeState[pluginName];\n}\n\n/**\n * Reset the runtime state for a plugin\n */\nexport function resetPluginRuntimeState(pluginName: string): void {\n delete runtimeState[pluginName];\n}\n\n/**\n * Get all plugin runtime states (for debugging)\n */\nexport function getAllPluginRuntimeStates(): PluginRuntimeState {\n return { ...runtimeState };\n}","/**\n * Mioku - Plugin framework extended from mioki\n *\n * Main entry point for the mioku npm package\n */\n\nimport pluginManager from \"./core/plugin-manager\";\nimport serviceManager from \"./core/service-manager\";\nimport { registerPluginArtifacts } from \"./core/plugin-artifact-registry\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { existsSync, mkdirSync } from \"fs\";\nimport {\n DEFAULT_RUNTIME_PLUGINS_DIR,\n prepareRuntimePluginLinks,\n} from \"./core/plugin-linker\";\nimport { setMiokuLogger } from \"./core/logger\";\n\n// Re-export mioki types for convenience\nexport type { MiokiPlugin, MiokiContext } from \"mioki\";\n\nexport function definePlugin<T extends import(\"mioki\").MiokiPlugin>(\n plugin: T,\n): T {\n return plugin;\n}\n\n// Core functionality\nexport { default as pluginManager } from \"./core/plugin-manager\";\nexport { default as serviceManager } from \"./core/service-manager\";\nexport { registerPluginArtifacts } from \"./core/plugin-artifact-registry\";\n\n// Types from types.ts\nexport type {\n MiokuService,\n PluginMetadata,\n ServiceMetadata,\n PluginPackageConfig,\n PluginHelp,\n CommandRole,\n} from \"./types\";\n\n// Service types from service-types.ts\nexport type {\n ConfigService,\n ScreenshotService,\n HelpService,\n WebUIService,\n AITool,\n AISkill,\n AIInstance,\n AIService,\n ChatRuntime,\n TextMessage,\n MultimodalMessage,\n ToolCallRecord,\n CompleteOptions,\n CompleteResponse,\n SessionToolDefinition,\n SkillPermissionRole,\n MultimodalContentItem,\n ToolResultFollowup,\n ChatRuntimePromptInjection,\n ChatRuntimeGroupTarget,\n ChatRuntimePrivateTarget,\n ChatRuntimeSource,\n ChatRuntimeBaseOptions,\n ChatRuntimeNoticeOptions,\n ChatRuntimeInformationRequestOptions,\n ChatRuntimeCollectedInfo,\n ChatRuntimeResult,\n AIUsageRange,\n AIUsageContext,\n AIUsageBreakdown,\n AIUsageFinalization,\n AIUsageSummary,\n} from \"./service-types\";\n\nexport { TOOL_RESULT_FOLLOWUP_KEY } from \"./service-types\";\n\n/**\n * Start options for Mioku\n */\nexport interface MiokuStartOptions {\n cwd?: string;\n}\n\n/**\n * Start Mioku with plugin and service discovery\n */\nexport async function start(options: MiokuStartOptions = {}): Promise<void> {\n const { cwd = process.cwd() } = options;\n\n if (cwd) {\n process.chdir(cwd);\n }\n\n const { start: startMioki, logger, botConfig } = await import(\"mioki\");\n setMiokuLogger(logger);\n\n // Read mioku config from package.json (mioki field contains merged config)\n const packageJsonPath = path.join(process.cwd(), \"package.json\");\n let miokuConfig: any = {};\n if (fs.existsSync(packageJsonPath)) {\n const pkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n // mioku-specific config lives in the same mioki field\n miokuConfig = pkg.mioki || {};\n }\n\n logger.info(\"こんにちは..\");\n logger.info(\"---------------------------------------\");\n logger.info(\"---------- Mioku 正在启动 ------------\");\n logger.info(\"---------------------------------------\");\n\n // Ensure required directories exist\n const requiredDirs = [\"data\", \"config\", \"temp\"];\n for (const dir of requiredDirs) {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n logger.info(\"O.o Miku 正在翻找插件..\");\n const discoveredPlugins = await pluginManager.discoverPlugins(miokuConfig);\n logger.info(`O.o 共发现 ${discoveredPlugins.length} 个插件: ${discoveredPlugins.map(p => p.name).join(\", \")}`);\n\n const runtimePluginsDir = path.resolve(\n process.cwd(),\n DEFAULT_RUNTIME_PLUGINS_DIR,\n );\n const linkedPluginNames = await prepareRuntimePluginLinks(\n discoveredPlugins,\n runtimePluginsDir,\n );\n botConfig.plugins_dir = DEFAULT_RUNTIME_PLUGINS_DIR;\n\n logger.info(\"o.O Miku 正在翻找服务..\");\n await serviceManager.discoverServices(miokuConfig);\n\n const requiredServices = pluginManager.collectRequiredServices();\n const missingServices =\n await serviceManager.checkMissingServices(requiredServices);\n\n if (missingServices.length > 0) {\n logger.warn(`发现缺失服务: ${missingServices.join(\", \")}`);\n }\n\n // Only auto-load discovered plugins if the user has not specified a plugins list.\n // \"not specified\" means plugins key is undefined in mioki config.\n // If plugins is explicitly set (even to empty array []), only load what's in the list.\n const userSpecifiedPlugins = miokuConfig.plugins !== undefined;\n if (!userSpecifiedPlugins) {\n for (const name of linkedPluginNames) {\n if (!botConfig.plugins.includes(name)) {\n botConfig.plugins.push(name);\n }\n }\n }\n\n await startMioki({ cwd });\n}\n\n// Version\nexport const version = \"1.0.0\";\n\n// Data path utilities\nexport {\n getDataDir,\n getPluginDataDir,\n getServiceDataDir,\n getConfigDir,\n getPluginConfigDir,\n getServiceConfigDir,\n ensureDataDir,\n} from \"./core/data-paths\";\n\n// Plugin runtime state\nexport {\n getPluginRuntimeState,\n setPluginRuntimeState,\n resetPluginRuntimeState,\n} from \"./core/plugin-runtime-state\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["fallbackLogger: MiokuLogger","activeLogger: MiokuLogger","logger: MiokuLogger | undefined","logger","logger: MiokuLogger","pathExists","filePath: string","entryPath: string","linkPath: string","targetPath: string","runtimePluginsDir: string","metadata: PluginMetadata","plugins: PluginMetadata[]","linkedNames: string[]","pathExists","filePath: string","miokuConfig: any","discovered: PluginMetadata[]","pluginsDir: string","entryPath: string","name: string","pluginPath: string","packageJson: any","metadata: PluginMetadata","pathExists","filePath: string","miokuConfig: any","discovered: ServiceMetadata[]","servicesDir: string","name: string","servicePath: string","metadata: ServiceMetadata","error: any","requiredServices: Set<string>","missing: string[]","ctx: MiokiContext","service: MiokuService","filePath: string","value: any","moduleExports: any","pluginPath: string","ctx: MiokiContext","error: any","pluginName: string","serviceName: string","runtimeState: PluginRuntimeState","pluginName: string","state: Record<string, any>","plugin: T","options: MiokuStartOptions","logger","miokuConfig: any"],"sources":["../src/core/logger.ts","../src/core/plugin-linker.ts","../src/core/plugin-manager.ts","../src/core/service-manager.ts","../src/core/plugin-artifact-registry.ts","../src/service-types.ts","../src/core/data-paths.ts","../src/core/plugin-runtime-state.ts","../src/index.ts"],"sourcesContent":["type LogMethod = (...args: unknown[]) => void;\n\nexport interface MiokuLogger {\n error: LogMethod;\n warn: LogMethod;\n info: LogMethod;\n debug: LogMethod;\n trace?: LogMethod;\n}\n\nconst fallbackLogger: MiokuLogger = {\n error: (...args) => console.error(...args),\n warn: (...args) => console.warn(...args),\n info: (...args) => console.info(...args),\n debug: (...args) => console.debug(...args),\n trace: (...args) => console.debug(...args),\n};\n\nlet activeLogger: MiokuLogger = fallbackLogger;\n\nexport function setMiokuLogger(logger: MiokuLogger | undefined): void {\n activeLogger = logger || fallbackLogger;\n}\n\nexport function getMiokuLogger(): MiokuLogger {\n return activeLogger;\n}\n\nexport const logger: MiokuLogger = {\n error: (...args) => activeLogger.error(...args),\n warn: (...args) => activeLogger.warn(...args),\n info: (...args) => activeLogger.info(...args),\n debug: (...args) => activeLogger.debug(...args),\n trace: (...args) => activeLogger.trace?.(...args),\n};\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport type { PluginMetadata } from \"./types\";\nimport { logger } from \"./logger\";\n\nexport const DEFAULT_RUNTIME_PLUGINS_DIR = \".mioku/plugins\";\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function removeIfBrokenSymlink(entryPath: string): Promise<\"ok\" | \"blocked\" | \"removed\"> {\n let stat;\n try {\n stat = await fs.lstat(entryPath);\n } catch {\n return \"removed\";\n }\n\n if (!stat.isSymbolicLink()) {\n return \"blocked\";\n }\n\n try {\n await fs.realpath(entryPath);\n return \"ok\";\n } catch {\n await fs.rm(entryPath, { force: true });\n logger.warn(`[plugin-linker] Removed broken plugin link: ${entryPath}`);\n return \"removed\";\n }\n}\n\nfunction relativeSymlinkTarget(linkPath: string, targetPath: string): string {\n const relativePath = path.relative(path.dirname(linkPath), targetPath);\n return relativePath || \".\";\n}\n\nasync function ensurePluginLink(\n runtimePluginsDir: string,\n metadata: PluginMetadata,\n): Promise<boolean> {\n const linkPath = path.join(runtimePluginsDir, metadata.name);\n const targetPath = metadata.path;\n\n let stat;\n try {\n stat = await fs.lstat(linkPath);\n } catch {\n stat = null;\n }\n\n if (stat?.isSymbolicLink()) {\n try {\n const currentTarget = await fs.realpath(linkPath);\n const expectedTarget = await fs.realpath(targetPath);\n if (currentTarget === expectedTarget) {\n return true;\n }\n await fs.rm(linkPath, { force: true });\n logger.info(`[plugin-linker] Rebuilding plugin link: ${metadata.name}`);\n } catch {\n await fs.rm(linkPath, { force: true });\n logger.warn(`[plugin-linker] Removed broken plugin link: ${linkPath}`);\n }\n } else if (stat) {\n logger.warn(\n `[plugin-linker] ${linkPath} exists and is not a symlink, skip linking ${metadata.name}`,\n );\n return false;\n }\n\n if (!(await pathExists(targetPath))) {\n logger.warn(\n `[plugin-linker] Plugin target missing, skip linking ${metadata.name}: ${targetPath}`,\n );\n return false;\n }\n\n // Use junction on Windows (no admin needed), symlink on Unix\n if (process.platform === \"win32\") {\n // Junctions require absolute paths\n await fs.symlink(targetPath, linkPath, \"junction\");\n } else {\n await fs.symlink(relativeSymlinkTarget(linkPath, targetPath), linkPath, \"dir\");\n }\n return true;\n}\n\nexport async function prepareRuntimePluginLinks(\n plugins: PluginMetadata[],\n runtimePluginsDir = path.resolve(process.cwd(), DEFAULT_RUNTIME_PLUGINS_DIR),\n): Promise<string[]> {\n await fs.mkdir(runtimePluginsDir, { recursive: true });\n\n const discoveredNames = new Set(plugins.map((plugin) => plugin.name));\n const entries = await fs.readdir(runtimePluginsDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = path.join(runtimePluginsDir, entry.name);\n const symlinkState = await removeIfBrokenSymlink(entryPath);\n if (symlinkState !== \"ok\") {\n continue;\n }\n\n if (entry.isSymbolicLink() && !discoveredNames.has(entry.name)) {\n await fs.rm(entryPath, { force: true });\n logger.info(`[plugin-linker] Removed stale plugin link: ${entry.name}`);\n }\n }\n\n const linkedNames: string[] = [];\n for (const metadata of plugins) {\n if (await ensurePluginLink(runtimePluginsDir, metadata)) {\n linkedNames.push(metadata.name);\n }\n }\n\n return linkedNames;\n}\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport { mkdirSync } from \"fs\";\nimport type { PluginMetadata } from \"./types\";\nimport { DEFAULT_RUNTIME_PLUGINS_DIR } from \"./plugin-linker\";\nimport { logger } from \"./logger\";\n\nconst PLUGIN_MANAGER_SYMBOL = Symbol.for(\"mioku.plugin-manager\");\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * 插件管理器\n *\n * Discover and manage plugins from both local directories and node_modules.\n */\nexport class PluginManager {\n private pluginMetadata: Map<string, PluginMetadata> = new Map();\n\n public static getInstance(): PluginManager {\n const g = global as any;\n if (!g[PLUGIN_MANAGER_SYMBOL]) {\n g[PLUGIN_MANAGER_SYMBOL] = new PluginManager();\n }\n return g[PLUGIN_MANAGER_SYMBOL];\n }\n\n async discoverPlugins(miokuConfig: any = {}): Promise<PluginMetadata[]> {\n // Resolve pluginsDir dynamically so it uses the current cwd\n const configuredPluginsDir = miokuConfig.plugins_dir;\n const pluginsDir =\n configuredPluginsDir && configuredPluginsDir !== DEFAULT_RUNTIME_PLUGINS_DIR\n ? path.resolve(process.cwd(), configuredPluginsDir)\n : path.resolve(process.cwd(), \"plugins\");\n\n this.pluginMetadata.clear();\n\n // Ensure plugins directory exists\n if (!(await pathExists(pluginsDir))) {\n mkdirSync(pluginsDir, { recursive: true });\n }\n\n const discovered: PluginMetadata[] = [];\n\n // Discover from local plugins/ directory\n if (await pathExists(pluginsDir)) {\n const localPlugins = await this.discoverFromDir(pluginsDir);\n discovered.push(...localPlugins);\n }\n\n // Discover from node_modules (mioku-plugin-* prefix)\n const nodeModulesPlugins = await this.discoverFromNodeModules();\n discovered.push(...nodeModulesPlugins);\n\n logger.info(`O.o 发现了 ${this.pluginMetadata.size} 个插件`);\n return Array.from(this.pluginMetadata.values());\n }\n\n private async discoverFromDir(pluginsDir: string): Promise<PluginMetadata[]> {\n const discovered: PluginMetadata[] = [];\n\n try {\n const entries = await fs.readdir(pluginsDir, { withFileTypes: true });\n for (const entry of entries) {\n const pluginPath = path.join(pluginsDir, entry.name);\n const metadataPath = await this.resolveDirectoryPath(pluginPath);\n if (!metadataPath) continue;\n\n const metadata = await this.loadPluginMetadata(entry.name, pluginPath);\n if (metadata) {\n discovered.push(metadata);\n this.pluginMetadata.set(metadata.name, metadata);\n }\n }\n } catch (error) {\n logger.error(`扫描插件目录失败: ${error}`);\n }\n\n return discovered;\n }\n\n private async discoverFromNodeModules(): Promise<PluginMetadata[]> {\n const discovered: PluginMetadata[] = [];\n const nodeModulesPath = path.resolve(process.cwd(), \"node_modules\");\n\n if (!(await pathExists(nodeModulesPath))) {\n return discovered;\n }\n\n try {\n const entries = await fs.readdir(nodeModulesPath, { withFileTypes: true });\n for (const entry of entries) {\n // Check for mioku-plugin-* prefix (don't check isDirectory - symlinks return false)\n if (!entry.name.startsWith(\"mioku-plugin-\")) {\n continue;\n }\n\n const pluginName = entry.name.replace(/^mioku-plugin-/, \"\");\n const pluginPath = path.join(nodeModulesPath, entry.name);\n const metadata = await this.loadPluginMetadata(pluginName, pluginPath);\n if (metadata) {\n discovered.push(metadata);\n this.pluginMetadata.set(metadata.name, metadata);\n }\n }\n } catch (error) {\n logger.debug(`扫描 node_modules 插件失败: ${error}`);\n }\n\n return discovered;\n }\n\n private async resolveDirectoryPath(entryPath: string): Promise<string | null> {\n try {\n const stat = await fs.stat(entryPath);\n return stat.isDirectory() ? entryPath : null;\n } catch {\n return null;\n }\n }\n\n private async loadPluginMetadata(\n name: string,\n pluginPath: string,\n ): Promise<PluginMetadata | null> {\n // Resolve symlinks to get actual path\n let resolvedPath = pluginPath;\n try {\n resolvedPath = await fs.realpath(pluginPath);\n } catch {\n // Not a symlink or doesn't exist, use original path\n }\n\n const packageJsonPath = path.join(resolvedPath, \"package.json\");\n\n let packageJson: any = null;\n try {\n const content = await fs.readFile(packageJsonPath, \"utf-8\");\n packageJson = JSON.parse(content);\n } catch {\n // File doesn't exist or can't be read - plugin uses defaults\n }\n\n const metadata: PluginMetadata = {\n name,\n version: packageJson?.version || \"0.0.0\",\n description: packageJson?.description,\n path: resolvedPath,\n packageJson,\n config: packageJson?.mioku || {},\n };\n return metadata;\n }\n\n collectRequiredServices(): Set<string> {\n const services = new Set<string>();\n for (const metadata of this.pluginMetadata.values()) {\n if (metadata.config.services) {\n metadata.config.services.forEach((s) => services.add(s));\n }\n }\n return services;\n }\n\n getPluginMetadata(name: string): PluginMetadata | undefined {\n return this.pluginMetadata.get(name);\n }\n\n getAllMetadata(): PluginMetadata[] {\n return Array.from(this.pluginMetadata.values());\n }\n\n reset(): void {\n this.pluginMetadata.clear();\n }\n}\n\nexport default PluginManager.getInstance();\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport { existsSync, mkdirSync } from \"fs\";\nimport type { MiokiContext } from \"mioki\";\nimport type { ServiceMetadata, MiokuService } from \"./types\";\nimport { logger } from \"./logger\";\n\nconst SERVICE_MANAGER_SYMBOL = Symbol.for(\"mioku.service-manager\");\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * 服务管理器\n */\nexport class ServiceManager {\n private services: Map<string, MiokuService> = new Map();\n private serviceMetadata: Map<string, ServiceMetadata> = new Map();\n private servicesDir: string = \"services\";\n\n public static getInstance(): ServiceManager {\n const g = global as any;\n if (!g[SERVICE_MANAGER_SYMBOL]) {\n g[SERVICE_MANAGER_SYMBOL] = new ServiceManager();\n }\n return g[SERVICE_MANAGER_SYMBOL];\n }\n\n async discoverServices(miokuConfig: any = {}): Promise<ServiceMetadata[]> {\n // Use services_dir from mioku config if provided, otherwise default to \"services\" in project root\n if (miokuConfig.services_dir) {\n this.servicesDir = path.resolve(process.cwd(), miokuConfig.services_dir);\n } else {\n this.servicesDir = path.resolve(process.cwd(), \"services\");\n }\n\n const discovered: ServiceMetadata[] = [];\n this.serviceMetadata.clear();\n\n // Discover from local services/ directory\n if (existsSync(this.servicesDir)) {\n const localServices = await this.discoverFromDir(this.servicesDir);\n discovered.push(...localServices);\n } else {\n // Ensure the directory exists for user services\n mkdirSync(this.servicesDir, { recursive: true });\n }\n\n // Discover builtin services (config, ai, screenshot, webui)\n await this.loadBuiltinServices();\n\n logger.info(`o.O 发现了 ${this.serviceMetadata.size} 个服务`);\n return Array.from(this.serviceMetadata.values());\n }\n\n private async discoverFromDir(servicesDir: string): Promise<ServiceMetadata[]> {\n const discovered: ServiceMetadata[] = [];\n\n try {\n const entries = await fs.readdir(servicesDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const servicePath = path.join(servicesDir, entry.name);\n const metadata = await this.loadServiceMetadata(entry.name, servicePath);\n if (metadata) {\n discovered.push(metadata);\n this.serviceMetadata.set(entry.name, metadata);\n }\n }\n } catch (error) {\n logger.error(`扫描服务目录失败: ${error}`);\n }\n\n return discovered;\n }\n\n private async loadServiceMetadata(\n name: string,\n servicePath: string,\n ): Promise<ServiceMetadata | null> {\n // Resolve symlinks to get actual path\n let resolvedPath = servicePath;\n try {\n resolvedPath = await fs.realpath(servicePath);\n } catch {\n // Not a symlink or doesn't exist, use original path\n }\n\n const packageJsonPath = path.join(resolvedPath, \"package.json\");\n\n if (!(await pathExists(packageJsonPath))) {\n return null;\n }\n\n try {\n const packageJson = JSON.parse(\n await fs.readFile(packageJsonPath, \"utf-8\"),\n );\n const metadata: ServiceMetadata = {\n name,\n version: packageJson.version || \"0.0.0\",\n description: packageJson.description,\n path: resolvedPath,\n packageJson,\n };\n return metadata;\n } catch (error: any) {\n logger.error(`解析服务 ${name} 失败: ${error.message}`);\n return null;\n }\n }\n\n /**\n * Load built-in services from the package\n */\n private async loadBuiltinServices(): Promise<void> {\n // Discover from node_modules (mioku-service-* prefix)\n await this.discoverFromNodeModules();\n }\n\n private async discoverFromNodeModules(): Promise<void> {\n const nodeModulesPath = path.resolve(process.cwd(), \"node_modules\");\n\n if (!(await pathExists(nodeModulesPath))) {\n return;\n }\n\n try {\n const entries = await fs.readdir(nodeModulesPath, { withFileTypes: true });\n for (const entry of entries) {\n // Don't check isDirectory - symlinks return false\n if (!entry.name.startsWith(\"mioku-service-\")) {\n continue;\n }\n\n const serviceName = entry.name.replace(/^mioku-service-/, \"\");\n const servicePath = path.join(nodeModulesPath, entry.name);\n const metadata = await this.loadServiceMetadata(serviceName, servicePath);\n if (metadata) {\n this.serviceMetadata.set(serviceName, metadata);\n }\n }\n } catch (error) {\n logger.debug(`扫描 node_modules 服务失败: ${error}`);\n }\n }\n\n async checkMissingServices(requiredServices: Set<string>): Promise<string[]> {\n const missing: string[] = [];\n for (const serviceName of requiredServices) {\n if (!this.serviceMetadata.has(serviceName)) {\n missing.push(serviceName);\n }\n }\n return missing;\n }\n\n async loadAllServices(ctx: MiokiContext): Promise<void> {\n const allMetadata = Array.from(this.serviceMetadata.values());\n logger.info(`O.o 准备加载 ${allMetadata.length} 个服务...`);\n\n for (const metadata of allMetadata) {\n await this.loadService(metadata, ctx);\n }\n }\n\n private async loadService(\n metadata: ServiceMetadata,\n ctx: MiokiContext,\n ): Promise<boolean> {\n try {\n const indexPath = path.join(metadata.path, \"index.ts\");\n const indexJsPath = path.join(metadata.path, \"index.js\");\n const indexExists = await pathExists(indexPath);\n const indexJsExists = await pathExists(indexJsPath);\n const entryPoint = indexExists ? indexPath : indexJsPath;\n\n if (!entryPoint || (!indexExists && !indexJsExists)) {\n logger.error(`服务 ${metadata.name} 入口丢失`);\n return false;\n }\n\n let importPath = entryPoint;\n if (process.platform === \"win32\") {\n importPath = \"file:///\" + entryPoint.replace(/\\\\/g, \"/\");\n }\n\n const serviceModule = await import(importPath);\n const service: MiokuService = serviceModule.default || serviceModule;\n\n if (!service || typeof service.init !== \"function\") return false;\n\n await service.init();\n if (service.api) {\n if (!(ctx as any).services) (ctx as any).services = {};\n (ctx as any).services[metadata.name] = service.api;\n }\n\n this.services.set(metadata.name, service);\n return true;\n } catch (error: any) {\n logger.error(`加载服务 ${metadata.name} 失败: ${error.message}`);\n return false;\n }\n }\n\n /**\n * Register a builtin service directly\n */\n registerBuiltinService(name: string, service: MiokuService): void {\n this.services.set(name, service);\n }\n\n /**\n * Get a loaded service\n */\n getService(name: string): MiokuService | undefined {\n return this.services.get(name);\n }\n\n async disposeAll(): Promise<void> {\n for (const [name, service] of this.services) {\n if (service.dispose) await service.dispose();\n }\n this.services.clear();\n }\n\n reset(): void {\n this.services.clear();\n this.serviceMetadata.clear();\n }\n}\n\nexport default ServiceManager.getInstance();\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport type { MiokiContext } from \"mioki\";\nimport type { AIService } from \"../types\";\nimport type { HelpService } from \"../service-types\";\nimport type { AISkill } from \"./types\";\nimport pluginManager from \"./plugin-manager\";\nimport { logger } from \"./logger\";\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction toImportPath(filePath: string): string {\n if (process.platform === \"win32\") {\n return \"file:///\" + filePath.replace(/\\\\/g, \"/\");\n }\n return filePath;\n}\n\nfunction isAISkill(value: any): value is AISkill {\n return (\n value &&\n typeof value === \"object\" &&\n typeof value.name === \"string\" &&\n Array.isArray(value.tools)\n );\n}\n\nfunction extractSkills(moduleExports: any): AISkill[] {\n const candidates = [\n moduleExports?.default,\n moduleExports?.skills,\n moduleExports,\n ];\n\n for (const candidate of candidates) {\n if (Array.isArray(candidate)) {\n return candidate.filter(isAISkill);\n }\n if (isAISkill(candidate)) {\n return [candidate];\n }\n }\n\n return [];\n}\n\nasync function resolveSkillsEntry(pluginPath: string): Promise<string | null> {\n const tsPath = path.join(pluginPath, \"skills.ts\");\n if (await pathExists(tsPath)) {\n return tsPath;\n }\n\n const jsPath = path.join(pluginPath, \"skills.js\");\n if (await pathExists(jsPath)) {\n return jsPath;\n }\n\n return null;\n}\n\n/**\n * Auto-register plugin help manifests and AI skills\n */\nexport async function registerPluginArtifacts(\n ctx: MiokiContext,\n): Promise<void> {\n const enabledPlugins = new Set<string>(\n Array.isArray((ctx as any).botConfig?.plugins)\n ? (ctx as any).botConfig.plugins\n : [],\n );\n const pluginMetadata = pluginManager\n .getAllMetadata()\n .filter((metadata) =>\n enabledPlugins.size > 0 ? enabledPlugins.has(metadata.name) : true,\n );\n\n const helpService = ctx.services?.help as HelpService | undefined;\n const aiService = ctx.services?.ai as AIService | undefined;\n\n if (helpService) {\n let helpCount = 0;\n for (const metadata of pluginMetadata) {\n if (!metadata.config.help) {\n continue;\n }\n helpService.registerHelp(metadata.name, metadata.config.help);\n helpCount += 1;\n }\n logger.info(`[plugin-artifacts] Registered ${helpCount} help manifest(s)`);\n }\n\n if (!aiService) {\n return;\n }\n\n let skillCount = 0;\n for (const metadata of pluginMetadata) {\n const skillsEntry = await resolveSkillsEntry(metadata.path);\n if (!skillsEntry) {\n continue;\n }\n\n try {\n const moduleExports = await import(toImportPath(skillsEntry));\n const skills = extractSkills(moduleExports);\n\n if (skills.length === 0) {\n logger.warn(\n `[plugin-artifacts] Plugin ${metadata.name} has ${path.basename(skillsEntry)} but exported no valid skill`,\n );\n continue;\n }\n\n for (const skill of skills) {\n aiService.registerSkill(skill);\n skillCount += 1;\n }\n } catch (error: any) {\n logger.error(\n `[plugin-artifacts] Failed to load skills for plugin ${metadata.name}: ${error?.message || error}`,\n );\n }\n }\n\n logger.info(`[plugin-artifacts] Registered ${skillCount} skill(s)`);\n}\n","/**\n * Service interface definitions for built-in services\n * These are used for type annotations in plugins\n */\n\n// ============ Core Service Interfaces ============\n\n// Config Service\nexport interface ConfigService {\n registerConfig(pluginName: string, configName: string, initialConfig: any): Promise<boolean>;\n updateConfig(pluginName: string, configName: string, updates: any): Promise<boolean>;\n getConfig(pluginName: string, configName: string): Promise<any>;\n getPluginConfigs(pluginName: string): Promise<Record<string, any>>;\n onConfigChange(pluginName: string, configName: string, callback: (newConfig: any) => void): () => void;\n}\n\n// Screenshot Service\nexport interface ScreenshotService {\n screenshot(html: string, options?: any): Promise<string>;\n screenshotMarkdown(markdownContent: string, options?: any): Promise<string>;\n screenshotFromUrl(url: string, options?: any): Promise<string>;\n cleanupTemp(olderThanMs?: number): Promise<number>;\n}\n\n// Help Service\nexport interface HelpService {\n registerHelp(pluginName: string, help: any): void;\n getHelp(pluginName: string): any;\n getAllHelp(): Map<string, any>;\n unregisterHelp(pluginName: string): void;\n}\n\n// WebUI Service\nexport interface WebUIService {\n getSettings(): { port: number; host: string; packageManager: string };\n}\n\n// ============ AI Service Types ============\n\nexport interface AITool {\n name: string;\n description: string;\n parameters: {\n type: \"object\";\n properties: Record<string, any>;\n required?: string[];\n };\n handler: (args: any, event?: any) => Promise<any> | any;\n}\n\nexport interface AISkill {\n name: string;\n description: string;\n permission?: \"owner\" | \"admin\" | \"member\";\n tools: AITool[];\n}\n\nexport interface TextMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\nexport interface MultimodalMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string | MultimodalContentItem[];\n}\n\nexport interface ToolCallRecord {\n name: string;\n arguments: any;\n result: any;\n}\n\nexport interface SessionToolDefinition {\n name: string;\n tool: AITool;\n}\n\nexport interface CompleteOptions {\n model?: string;\n messages: any[];\n temperature?: number;\n max_tokens?: number;\n stream?: boolean;\n tools?: any[];\n executableTools?: SessionToolDefinition[];\n executableToolsProvider?: () => SessionToolDefinition[];\n maxIterations?: number;\n onTextDelta?: (delta: string) => void | Promise<void>;\n usageContext?: AIUsageContext;\n usageContextTokens?: number;\n usageBreakdown?: AIUsageFinalization[\"breakdown\"];\n}\n\nexport interface CompleteResponse {\n content: string | null;\n reasoning: string | null;\n toolCalls: Array<{ id: string; name: string; arguments: string }>;\n raw: any;\n turnMessages: any[];\n iterations?: number;\n allToolCalls?: ToolCallRecord[];\n}\n\nexport interface ChatRuntime {\n generateNotice(options: ChatRuntimeNoticeOptions): Promise<ChatRuntimeResult>;\n requestInformation(options: ChatRuntimeInformationRequestOptions): Promise<ChatRuntimeResult>;\n}\n\nexport const TOOL_RESULT_FOLLOWUP_KEY = \"__miokuFollowup\";\n\nexport interface ToolResultFollowup {\n text: string;\n images: Array<{\n url: string;\n detail?: \"auto\" | \"low\" | \"high\";\n }>;\n}\n\n// Permission role for skills\nexport type SkillPermissionRole = \"owner\" | \"admin\" | \"member\";\n\n// Multimodal content item\nexport interface MultimodalContentItem {\n type: \"text\" | \"image_url\";\n text?: string;\n image_url?: {\n url: string;\n detail?: \"auto\" | \"low\" | \"high\";\n };\n}\n\n// Chat runtime types\nexport interface ChatRuntimePromptInjection {\n content: string;\n title?: string;\n}\n\nexport interface ChatRuntimeGroupTarget {\n selfId: number;\n groupId: number;\n}\n\nexport interface ChatRuntimePrivateTarget {\n selfId: number;\n userId: number;\n}\n\nexport type ChatRuntimeSource =\n | { event: any }\n | ChatRuntimeGroupTarget\n | ChatRuntimePrivateTarget;\n\nexport type ChatRuntimeBaseOptions = ChatRuntimeSource & {\n targetMessage?: string;\n promptInjections?: ChatRuntimePromptInjection[];\n send?: boolean;\n};\n\nexport type ChatRuntimeNoticeOptions = ChatRuntimeBaseOptions & {\n instruction: string;\n};\n\nexport type ChatRuntimeInformationRequestOptions = ChatRuntimeBaseOptions & {\n task: string;\n schema: {\n type: \"object\";\n properties: Record<string, any>;\n required?: string[];\n };\n toolName?: string;\n toolDescription?: string;\n};\n\nexport interface ChatRuntimeCollectedInfo {\n data: any;\n isComplete?: boolean;\n confidence?: number;\n notes?: string;\n}\n\nexport type AIUsageRange = \"today\" | \"7d\" | \"30d\";\n\nexport interface AIUsageContext {\n usageId?: string;\n source?: string;\n botId?: number;\n groupId?: number;\n groupName?: string;\n userId?: number;\n userName?: string;\n sessionId?: string;\n}\n\nexport interface AIUsageBreakdown {\n systemPromptTokens?: number;\n chatHistoryTokens?: number;\n toolDefinitionTokens?: number;\n toolUseTokens?: number;\n otherContextTokens?: number;\n}\n\nexport interface AIUsageFinalization {\n sentUserMessages?: number;\n sentAssistantMessages?: number;\n breakdown?: AIUsageBreakdown;\n}\n\nexport interface AIUsageSummary {\n range: AIUsageRange;\n total: {\n requests: number;\n inputTokens: number;\n outputTokens: number;\n cacheWriteTokens: number;\n cacheReadTokens: number;\n totalTokens: number;\n };\n byBot: Array<{\n botId: number | null;\n requests: number;\n inputTokens: number;\n outputTokens: number;\n cacheWriteTokens: number;\n cacheReadTokens: number;\n totalTokens: number;\n }>;\n}\n\nexport interface ChatRuntimeResult {\n messages: string[];\n toolCalls: ToolCallRecord[];\n collectedInfo: ChatRuntimeCollectedInfo | null;\n pendingAt?: number[];\n pendingPoke?: number[];\n pendingQuote?: number;\n emojiPath?: string | null;\n protocolMessages?: any[];\n}\n\nexport interface LegacyChatRuntimeNoticeOptions {\n sessionId: string;\n groupId?: number;\n userId: number;\n message: string;\n replyContextType: string;\n}\n\nexport interface LegacyChatRuntimeInformationRequestOptions {\n sessionId: string;\n groupId?: number;\n userId: number;\n prompt: string;\n injectHistoryCount?: number;\n}\n\n// ============ AI Service Interfaces ============\n\nexport interface AIInstance {\n generateText(options: { prompt?: string; messages: TextMessage[]; model?: string; temperature?: number; max_tokens?: number }): Promise<string>;\n generateMultimodal(options: { prompt?: string; messages: MultimodalMessage[]; model?: string; temperature?: number; max_tokens?: number }): Promise<string>;\n complete(options: CompleteOptions): Promise<CompleteResponse>;\n generateWithTools(options: { prompt?: string; messages: TextMessage[] | MultimodalMessage[]; model?: string; temperature?: number; maxIterations?: number }): Promise<any>;\n setUsageContext?(context: AIUsageContext | undefined): void;\n withUsageContext?<T>(context: AIUsageContext | undefined, fn: () => Promise<T>): Promise<T>;\n registerPrompt(name: string, prompt: string): boolean;\n getPrompt(name: string): string | undefined;\n getAllPrompts(): Record<string, string>;\n removePrompt(name: string): boolean;\n}\n\nexport interface AIService {\n create(options: { name: string; apiUrl: string; apiKey: string; modelType: \"text\" | \"multimodal\"; model?: string }): Promise<AIInstance>;\n get(name: string): AIInstance | undefined;\n list(): string[];\n remove(name: string): boolean;\n setDefault(name: string): boolean;\n getDefault(): AIInstance | undefined;\n registerChatRuntime(runtime: any): boolean;\n getChatRuntime(): any;\n removeChatRuntime(): boolean;\n registerSkill(skill: AISkill): boolean;\n getSkill(skillName: string): AISkill | undefined;\n getAllSkills(): Map<string, AISkill>;\n removeSkill(skillName: string): boolean;\n getTool(toolName: string): AITool | undefined;\n getAllTools(): Map<string, AITool>;\n getUsageSummary?(options: { range: AIUsageRange; botId?: number }): AIUsageSummary;\n cleanupUsageStats?(retentionMs?: number): number;\n finalizeUsage?(usageId: string, finalization: AIUsageFinalization): boolean;\n}\n","/**\n * Data Directory Utilities for Mioku Plugins\n *\n * Provides consistent data path resolution that respects the project directory\n * (process.cwd()) rather than the package installation directory.\n */\n\nimport * as path from \"path\";\n\n/**\n * Get the data directory for a specific plugin\n * Returns: {cwd}/data/{pluginName}\n */\nexport function getPluginDataDir(pluginName: string): string {\n const dataDir = path.join(process.cwd(), \"data\", pluginName);\n return dataDir;\n}\n\n/**\n * Get the data directory for a service\n * Returns: {cwd}/data/{serviceName}\n */\nexport function getServiceDataDir(serviceName: string): string {\n const dataDir = path.join(process.cwd(), \"data\", serviceName);\n return dataDir;\n}\n\n/**\n * Get the main data directory\n * Returns: {cwd}/data\n */\nexport function getDataDir(): string {\n return path.join(process.cwd(), \"data\");\n}\n\n/**\n * Get the config directory for a plugin\n * Returns: {cwd}/config/{pluginName}\n */\nexport function getPluginConfigDir(pluginName: string): string {\n const configDir = path.join(process.cwd(), \"config\", pluginName);\n return configDir;\n}\n\n/**\n * Get the config directory for a service\n * Returns: {cwd}/config/{serviceName}\n */\nexport function getServiceConfigDir(serviceName: string): string {\n const configDir = path.join(process.cwd(), \"config\", serviceName);\n return configDir;\n}\n\n/**\n * Get the main config directory\n * Returns: {cwd}/config\n */\nexport function getConfigDir(): string {\n return path.join(process.cwd(), \"config\");\n}\n\n/**\n * Ensure a directory exists, creating it if necessary\n */\nexport function ensureDataDir(pluginName: string): string {\n const dir = getPluginDataDir(pluginName);\n const { existsSync, mkdirSync } = require(\"fs\");\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n return dir;\n}","/**\n * Plugin Runtime State Management\n *\n * Provides a way for plugins to store state that needs to persist\n * across the plugin lifecycle but should be isolated per plugin.\n */\n\ninterface PluginRuntimeState {\n [pluginName: string]: Record<string, any>;\n}\n\nconst runtimeState: PluginRuntimeState = {};\n\n/**\n * Get the runtime state for a plugin\n */\nexport function getPluginRuntimeState(pluginName: string): Record<string, any> {\n if (!runtimeState[pluginName]) {\n runtimeState[pluginName] = {};\n }\n return runtimeState[pluginName];\n}\n\n/**\n * Set/update the runtime state for a plugin\n */\nexport function setPluginRuntimeState(\n pluginName: string,\n state: Record<string, any>,\n): Record<string, any> {\n if (!runtimeState[pluginName]) {\n runtimeState[pluginName] = {};\n }\n Object.assign(runtimeState[pluginName], state);\n return runtimeState[pluginName];\n}\n\n/**\n * Reset the runtime state for a plugin\n */\nexport function resetPluginRuntimeState(pluginName: string): void {\n delete runtimeState[pluginName];\n}\n\n/**\n * Get all plugin runtime states (for debugging)\n */\nexport function getAllPluginRuntimeStates(): PluginRuntimeState {\n return { ...runtimeState };\n}","/**\n * Mioku - Plugin framework extended from mioki\n *\n * Main entry point for the mioku npm package\n */\n\nimport pluginManager from \"./core/plugin-manager\";\nimport serviceManager from \"./core/service-manager\";\nimport { registerPluginArtifacts } from \"./core/plugin-artifact-registry\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { existsSync, mkdirSync } from \"fs\";\nimport {\n DEFAULT_RUNTIME_PLUGINS_DIR,\n prepareRuntimePluginLinks,\n} from \"./core/plugin-linker\";\nimport { setMiokuLogger } from \"./core/logger\";\n\n// Re-export mioki types for convenience\nexport type { MiokiPlugin, MiokiContext } from \"mioki\";\n\nexport function definePlugin<T extends import(\"mioki\").MiokiPlugin>(\n plugin: T,\n): T {\n return plugin;\n}\n\n// Core functionality\nexport { default as pluginManager } from \"./core/plugin-manager\";\nexport { default as serviceManager } from \"./core/service-manager\";\nexport { registerPluginArtifacts } from \"./core/plugin-artifact-registry\";\n\n// Types from types.ts\nexport type {\n MiokuService,\n PluginMetadata,\n ServiceMetadata,\n PluginPackageConfig,\n PluginHelp,\n CommandRole,\n} from \"./types\";\n\n// Service types from service-types.ts\nexport type {\n ConfigService,\n ScreenshotService,\n HelpService,\n WebUIService,\n AITool,\n AISkill,\n AIInstance,\n AIService,\n ChatRuntime,\n TextMessage,\n MultimodalMessage,\n ToolCallRecord,\n CompleteOptions,\n CompleteResponse,\n SessionToolDefinition,\n SkillPermissionRole,\n MultimodalContentItem,\n ToolResultFollowup,\n ChatRuntimePromptInjection,\n ChatRuntimeGroupTarget,\n ChatRuntimePrivateTarget,\n ChatRuntimeSource,\n ChatRuntimeBaseOptions,\n ChatRuntimeNoticeOptions,\n ChatRuntimeInformationRequestOptions,\n ChatRuntimeCollectedInfo,\n ChatRuntimeResult,\n AIUsageRange,\n AIUsageContext,\n AIUsageBreakdown,\n AIUsageFinalization,\n AIUsageSummary,\n} from \"./service-types\";\n\nexport { TOOL_RESULT_FOLLOWUP_KEY } from \"./service-types\";\n\n/**\n * Start options for Mioku\n */\nexport interface MiokuStartOptions {\n cwd?: string;\n}\n\n/**\n * Start Mioku with plugin and service discovery\n */\nexport async function start(options: MiokuStartOptions = {}): Promise<void> {\n const { cwd = process.cwd() } = options;\n\n if (cwd) {\n process.chdir(cwd);\n }\n\n const { start: startMioki, logger, botConfig } = await import(\"mioki\");\n setMiokuLogger(logger);\n\n // Read mioku config from package.json (mioki field contains merged config)\n const packageJsonPath = path.join(process.cwd(), \"package.json\");\n let miokuConfig: any = {};\n if (fs.existsSync(packageJsonPath)) {\n const pkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n // mioku-specific config lives in the same mioki field\n miokuConfig = pkg.mioki || {};\n }\n\n logger.info(\"こんにちは..\");\n logger.info(\"---------------------------------------\");\n logger.info(\"---------- Mioku 正在启动 ------------\");\n logger.info(\"---------------------------------------\");\n\n // Ensure required directories exist\n const requiredDirs = [\"data\", \"config\", \"temp\"];\n for (const dir of requiredDirs) {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n logger.info(\"O.o Miku 正在翻找插件..\");\n const discoveredPlugins = await pluginManager.discoverPlugins(miokuConfig);\n logger.info(`O.o 共发现 ${discoveredPlugins.length} 个插件: ${discoveredPlugins.map(p => p.name).join(\", \")}`);\n\n const runtimePluginsDir = path.resolve(\n process.cwd(),\n DEFAULT_RUNTIME_PLUGINS_DIR,\n );\n const linkedPluginNames = await prepareRuntimePluginLinks(\n discoveredPlugins,\n runtimePluginsDir,\n );\n botConfig.plugins_dir = DEFAULT_RUNTIME_PLUGINS_DIR;\n\n logger.info(\"o.O Miku 正在翻找服务..\");\n await serviceManager.discoverServices(miokuConfig);\n\n const requiredServices = pluginManager.collectRequiredServices();\n const missingServices =\n await serviceManager.checkMissingServices(requiredServices);\n\n if (missingServices.length > 0) {\n logger.warn(`发现缺失服务: ${missingServices.join(\", \")}`);\n }\n\n // Only auto-load discovered plugins if the user has not specified a plugins list.\n // \"not specified\" means plugins key is undefined in mioki config.\n // If plugins is explicitly set (even to empty array []), only load what's in the list.\n const userSpecifiedPlugins = miokuConfig.plugins !== undefined;\n if (!userSpecifiedPlugins) {\n for (const name of linkedPluginNames) {\n if (!botConfig.plugins.includes(name)) {\n botConfig.plugins.push(name);\n }\n }\n }\n\n await startMioki({ cwd });\n}\n\n// Version\nexport const version = \"1.0.0\";\n\n// Data path utilities\nexport {\n getDataDir,\n getPluginDataDir,\n getServiceDataDir,\n getConfigDir,\n getPluginConfigDir,\n getServiceConfigDir,\n ensureDataDir,\n} from \"./core/data-paths\";\n\n// Plugin runtime state\nexport {\n getPluginRuntimeState,\n setPluginRuntimeState,\n resetPluginRuntimeState,\n} from \"./core/plugin-runtime-state\";\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mioku",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.18",
|
|
5
5
|
"packageManager": "bun@1.2.0",
|
|
6
6
|
"description": "Mioku - Plugin framework extended from mioki for NapCat OneBot v11",
|
|
7
7
|
"keywords": [
|
|
@@ -59,8 +59,7 @@
|
|
|
59
59
|
"pretty-ms": "^9.3.0",
|
|
60
60
|
"string2argv": "^1.0.2",
|
|
61
61
|
"systeminformation": "^5.30.7",
|
|
62
|
-
"lodash": "^4.17.21"
|
|
63
|
-
"adm-zip": "^0.5.16"
|
|
62
|
+
"lodash": "^4.17.21"
|
|
64
63
|
},
|
|
65
64
|
"devDependencies": {
|
|
66
65
|
"@types/lodash": "^4.17.0",
|