mioku-service-webui 4.8.0 → 4.8.1

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/index.ts CHANGED
@@ -247,8 +247,6 @@ const runtime = new WebUIRuntime();
247
247
 
248
248
  const webUIService: MiokuService = {
249
249
  name: "webui",
250
- version: "4.2.0",
251
- description: "Mioku WebUI 管理服务",
252
250
  api: {
253
251
  getSettings: () => getWebUISettings(),
254
252
  } as WebUIServiceAPI,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mioku-service-webui",
3
- "version": "4.8.0",
3
+ "version": "4.8.1",
4
4
  "description": "Mioku WebUI 服务",
5
5
  "main": "index.ts",
6
6
  "type": "module",
@@ -1,8 +1,8 @@
1
1
  import { Hono } from "hono";
2
2
  import * as fs from "node:fs";
3
3
  import * as path from "node:path";
4
- import { logger } from "mioku";
5
- import { readJsonFile, writeJsonFile, NODE_MODULES_DIR } from "../utils";
4
+ import { getActiveCommandManager, logger } from "mioku";
5
+ import { isPackageDir, readJsonFile, writeJsonFile, NODE_MODULES_DIR } from "../utils";
6
6
 
7
7
  const ACCESS_CONFIG_PATH = path.resolve(
8
8
  process.cwd(),
@@ -38,24 +38,37 @@ interface AccessItem {
38
38
  desc?: string;
39
39
  match?: string;
40
40
  event?: string;
41
+ permission?: string;
42
+ priority?: number;
41
43
  fromHook: boolean;
42
44
  }
43
45
 
44
46
  function readAccessCatalog(): AccessItem[] {
47
+ const manager = getActiveCommandManager();
48
+ if (manager) {
49
+ return manager.catalog().map((item) => ({
50
+ kind: item.kind,
51
+ plugin: item.plugin,
52
+ id: item.id,
53
+ label: item.label,
54
+ desc: item.desc,
55
+ match: item.match,
56
+ event: item.event,
57
+ permission: item.permission,
58
+ priority: item.priority,
59
+ fromHook:
60
+ item.source === "manifest" && Boolean(item.match || item.event),
61
+ }));
62
+ }
45
63
  if (!fs.existsSync(NODE_MODULES_DIR)) return [];
46
64
  const entries = fs.readdirSync(NODE_MODULES_DIR, { withFileTypes: true });
47
65
  const items: AccessItem[] = [];
48
66
 
49
67
  for (const entry of entries) {
50
- if (!entry.name.startsWith("mioku-plugin-")) continue;
68
+ if (!entry.name.toLowerCase().startsWith("mioku-plugin-")) continue;
51
69
  const fullPath = path.join(NODE_MODULES_DIR, entry.name);
52
- let stat: fs.Stats;
53
- try {
54
- stat = fs.lstatSync(fullPath);
55
- } catch {
56
- continue;
57
- }
58
- if (!stat.isDirectory() && !stat.isSymbolicLink()) continue;
70
+ // Windows 上 pnpm/bun workspace 会用 NTFS junction,旧 lstat 检查会误判
71
+ if (!isPackageDir(fullPath)) continue;
59
72
 
60
73
  const pkgPath = path.join(fullPath, "package.json");
61
74
  if (!fs.existsSync(pkgPath)) continue;
@@ -66,7 +79,7 @@ function readAccessCatalog(): AccessItem[] {
66
79
  continue;
67
80
  }
68
81
 
69
- const name = entry.name.replace(/^mioku-plugin-/, "");
82
+ const name = entry.name.replace(/^mioku-plugin-/i, "");
70
83
  const mioku = pkg.mioku || {};
71
84
  const help = mioku.help || { title: name, description: "", commands: [] };
72
85
  const hooks: Array<{ id: string; match?: string; event?: string; description?: string }> =
@@ -3,23 +3,25 @@ import * as fs from "node:fs";
3
3
  import * as path from "node:path";
4
4
  import { loadAdapterConfigPage } from "../config-page-loader";
5
5
  import { getAdapterConfigs, updateAdapterConfig } from "../system";
6
+ import { isPackageDir } from "../utils";
6
7
 
7
8
  function listAdaptersFromNodeModules(): string[] {
8
9
  const modulesPath = path.join(process.cwd(), "node_modules");
9
- if (!fs.existsSync(modulesPath)) return [];
10
10
  const adapters: string[] = [];
11
- const entries = fs.readdirSync(modulesPath, { withFileTypes: true });
11
+ if (!fs.existsSync(modulesPath)) return adapters;
12
+
13
+ let entries: import("fs").Dirent[];
14
+ try {
15
+ entries = fs.readdirSync(modulesPath, { withFileTypes: true });
16
+ } catch {
17
+ return adapters;
18
+ }
19
+
12
20
  for (const entry of entries) {
13
- if (!entry.name.startsWith("mioku-adapter-")) continue;
21
+ if (!entry.name.toLowerCase().startsWith("mioku-adapter-")) continue;
14
22
  const fullPath = path.join(modulesPath, entry.name);
15
- let stat: fs.Stats;
16
- try {
17
- stat = fs.lstatSync(fullPath);
18
- } catch {
19
- continue;
20
- }
21
- if (!stat.isDirectory() && !stat.isSymbolicLink()) continue;
22
- adapters.push(entry.name.replace(/^mioku-adapter-/, ""));
23
+ if (!isPackageDir(fullPath)) continue;
24
+ adapters.push(entry.name.replace(/^mioku-adapter-/i, ""));
23
25
  }
24
26
  return adapters.sort((a, b) => a.localeCompare(b));
25
27
  }
package/system.ts CHANGED
@@ -21,6 +21,7 @@ import {
21
21
  ensureDir,
22
22
  getInstallCommand,
23
23
  isNpmPackageName,
24
+ isPackageDir,
24
25
  isValidRepoUrl,
25
26
  LOCAL_CONFIG_PATH,
26
27
  NODE_MODULES_DIR,
@@ -887,11 +888,11 @@ function listPluginsFromNodeModules(): Array<Record<string, any>> {
887
888
 
888
889
  const entries = fs.readdirSync(modulesPath, { withFileTypes: true });
889
890
  for (const entry of entries) {
890
- if (!entry.name.startsWith("mioku-plugin-")) continue;
891
+ if (!entry.name.toLowerCase().startsWith("mioku-plugin-")) continue;
891
892
  const fullPath = path.join(modulesPath, entry.name);
892
- const stat = fs.lstatSync(fullPath);
893
- if (!stat.isDirectory() && !stat.isSymbolicLink()) continue;
894
- const name = entry.name.replace(/^mioku-plugin-/, "");
893
+ // Windows 上 pnpm/bun workspace 会用 NTFS junction,旧 lstat 检查会误判
894
+ if (!isPackageDir(fullPath)) continue;
895
+ const name = entry.name.replace(/^mioku-plugin-/i, "");
895
896
  const pkg = readPackageJson(fullPath);
896
897
  plugins.push({
897
898
  name,
@@ -915,11 +916,11 @@ function listServicesFromNodeModules(): Array<Record<string, any>> {
915
916
 
916
917
  const entries = fs.readdirSync(modulesPath, { withFileTypes: true });
917
918
  for (const entry of entries) {
918
- if (!entry.name.startsWith("mioku-service-")) continue;
919
+ if (!entry.name.toLowerCase().startsWith("mioku-service-")) continue;
919
920
  const fullPath = path.join(modulesPath, entry.name);
920
- const stat = fs.lstatSync(fullPath);
921
- if (!stat.isDirectory() && !stat.isSymbolicLink()) continue;
922
- const name = entry.name.replace(/^mioku-service-/, "");
921
+ // Windows 上 pnpm/bun workspace 会用 NTFS junction,旧 lstat 检查会误判
922
+ if (!isPackageDir(fullPath)) continue;
923
+ const name = entry.name.replace(/^mioku-service-/i, "");
923
924
  const pkg = readPackageJson(fullPath);
924
925
  services.push({
925
926
  name,
@@ -943,11 +944,11 @@ function listAdaptersFromNodeModules(): Array<Record<string, any>> {
943
944
 
944
945
  const entries = fs.readdirSync(modulesPath, { withFileTypes: true });
945
946
  for (const entry of entries) {
946
- if (!entry.name.startsWith("mioku-adapter-")) continue;
947
+ if (!entry.name.toLowerCase().startsWith("mioku-adapter-")) continue;
947
948
  const fullPath = path.join(modulesPath, entry.name);
948
- const stat = fs.lstatSync(fullPath);
949
- if (!stat.isDirectory() && !stat.isSymbolicLink()) continue;
950
- const name = entry.name.replace(/^mioku-adapter-/, "");
949
+ // Windows 上 pnpm/bun workspace 会用 NTFS junction,旧 lstat 检查会误判
950
+ if (!isPackageDir(fullPath)) continue;
951
+ const name = entry.name.replace(/^mioku-adapter-/i, "");
951
952
  const pkg = readPackageJson(fullPath);
952
953
  adapters.push({
953
954
  name,
@@ -2401,11 +2402,11 @@ export function getAvailablePlugins(): string[] {
2401
2402
  const plugins: string[] = [];
2402
2403
  const entries = fs.readdirSync(modulesPath, { withFileTypes: true });
2403
2404
  for (const entry of entries) {
2404
- if (!entry.name.startsWith("mioku-plugin-")) continue;
2405
+ if (!entry.name.toLowerCase().startsWith("mioku-plugin-")) continue;
2405
2406
  const fullPath = path.join(modulesPath, entry.name);
2406
- const stat = fs.lstatSync(fullPath);
2407
- if (!stat.isDirectory() && !stat.isSymbolicLink()) continue;
2408
- plugins.push(entry.name.replace(/^mioku-plugin-/, ""));
2407
+ // Windows 上 pnpm/bun workspace 会用 NTFS junction,旧 lstat 检查会误判
2408
+ if (!isPackageDir(fullPath)) continue;
2409
+ plugins.push(entry.name.replace(/^mioku-plugin-/i, ""));
2409
2410
  }
2410
2411
  return plugins.sort((a, b) => a.localeCompare(b));
2411
2412
  }
package/utils.ts CHANGED
@@ -97,6 +97,11 @@ export function normalizePackageManager(): PackageManager {
97
97
  return "bun";
98
98
  }
99
99
 
100
+ export function isPackageDir(fullPath: string | null | undefined): boolean {
101
+ if (!fullPath) return false;
102
+ return fs.existsSync(path.join(fullPath, "package.json"));
103
+ }
104
+
100
105
  export function isValidRepoUrl(url: string): boolean {
101
106
  const trimmed = url.trim();
102
107
  // 拒绝空白字符:堵 `ssh://host -o ProxyCommand=...` 之类参数注入