@aalis/plugin-webui-server 0.9.0 → 0.10.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/dist/auth.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { IncomingMessage } from 'node:http';
2
+ import type { UserIdentity } from '@aalis/api-authority';
3
+ import type { ProcessService } from '@aalis/api-process';
2
4
  import type { Logger } from '@aalis/core';
3
- import type { UserIdentity } from '@aalis/plugin-authority-api';
4
- import type { ProcessService } from '@aalis/plugin-process-api';
5
5
  import type { RequestHandler } from 'express';
6
6
  export interface AuthSystem {
7
7
  /** Express 中间件:处理 ?token= 重定向、登录端点、未认证拦截、登录页 */
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AA0E9C,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,UAAU,EAAE,cAAc,CAAC;IAC3B,wCAAwC;IACxC,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;IAC9C,0EAA0E;IAC1E,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,YAAY,GAAG,SAAS,CAAC;CAC3E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CA+E3E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAenE"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AA0E9C,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,UAAU,EAAE,cAAc,CAAC;IAC3B,wCAAwC;IACxC,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;IAC9C,0EAA0E;IAC1E,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,YAAY,GAAG,SAAS,CAAC;CAC3E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CA+E3E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAwBnE"}
package/dist/auth.js CHANGED
@@ -149,7 +149,16 @@ export function createAuthSystem(token, _logger) {
149
149
  export function openBrowser(url, proc) {
150
150
  try {
151
151
  const spawnDetached = (cmd, args) => {
152
- proc.spawn(cmd, args, { detached: true, stdio: 'ignore' }).unref();
152
+ const handle = proc.spawn(cmd, args, { detached: true, stdio: 'ignore' });
153
+ // **必须 await wait()**:`child.on('error')` 只在 wait() 内注册,而 `stdio:'ignore'`
154
+ // 让 stdin 为 null、那条 handler 也挂不上——于是 handle 上零 error 监听。
155
+ // spawn 失败(headless Linux/Docker 无 xdg-open 是常态)是**异步 emit**,
156
+ // 外层 try/catch 接不住,直达 uncaughtException → runtime 的 process.exit(1),
157
+ // 把整个 bot 打死。而这只是个「顺手开浏览器」的便利功能。
158
+ void handle.wait().catch(() => {
159
+ /* 打不开浏览器不影响服务;这里只是给 handle 挂上 error 监听 */
160
+ });
161
+ handle.unref();
153
162
  };
154
163
  if (process.platform === 'darwin') {
155
164
  spawnDetached('open', [url]);
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -20,13 +20,35 @@ export interface DiscoveryEnv {
20
20
  * 默认活跃前端由调用方按 config 或「排序后第一个」决定——本函数不做偏好判断、不认任何具体名字。
21
21
  */
22
22
  export declare function discoverClients(scanDirs: string[], depIds: string[], env: DiscoveryEnv): ClientCandidate[];
23
+ /** 本地扫到的一个包:它自身的元数据 + 它依赖了谁。 */
24
+ export interface LocalScanEntry {
25
+ /** 该包 package.json 的 version。缺字段则 undefined。 */
26
+ version?: string;
27
+ /** 该包的 keywords。离线降级路径靠它筛出 aalis 组件——缺了这些包就整批看不见。 */
28
+ keywords?: string[];
29
+ description?: string;
30
+ /** `dependencies/peer/optional` 的并集**包名**(不含版本区间)。 */
31
+ deps: string[];
32
+ }
23
33
  /**
24
- * 扫描本地物理存在的包 → `name → 依赖名[]`(与 discoverClients 共用 scanDirs/env)。
25
- * 两用,一次扫盘:① keys 即「本地已装包名」,补市场已装判定(require.resolve 在 pnpm 工作区
26
- * 从仓库根解析不到未提升的工作区包);② values 即各包 `dependencies/peer/optional` 的并集名单,
27
- * 供依赖图(谁依赖谁)。**只取依赖名、不看版本区间**(`workspace:^`/`^1.0.0` 一律按名),故无需 semver
34
+ * 扫描本地物理存在的包 → `name → {version, deps}`(与 discoverClients 共用 scanDirs/env)。
35
+ * 三用,一次扫盘:① keys 即「本地已装包名」,补市场已装判定(require.resolve 在 pnpm 工作区
36
+ * 从仓库根解析不到未提升的工作区包);② `deps` 供依赖图(谁依赖谁)——**只取依赖名、不看版本
37
+ * 区间**(`workspace:^`/`^1.0.0` 一律按名),故无需 semver;③ `version`/`keywords`/`description` 供市场卡片:
38
+ * 工作区包这条路径 require.resolve 走不通,不带 version 就只能退回显示 npm latest;不带
39
+ * keywords 则**离线降级列表整批看不见它们**(toLocalPackages 按 keywords 筛 aalis 组件)。
28
40
  * scope 无关(不挑 @aalis)。纯函数便于单测。
29
41
  */
30
- export declare function collectLocalPackageDeps(scanDirs: string[], env: Pick<DiscoveryEnv, 'existsSync' | 'readdirSync' | 'readJson' | 'join'>): Map<string, string[]>;
42
+ export declare function collectLocalPackageDeps(scanDirs: string[], env: Pick<DiscoveryEnv, 'existsSync' | 'readdirSync' | 'readJson' | 'join'>): Map<string, LocalScanEntry>;
43
+ /**
44
+ * 从本轮发现结果里挑出**尚未登记**的候选。
45
+ *
46
+ * 前端发现要能重复跑(装完一个 `aalis-interface` 包后立刻重跑,否则它不出现在服务页的
47
+ * 下拉里、必须重启才看得见)。而重复 `fork().provide('webui-client', …)` 会在服务容器里
48
+ * 堆同名重复项 —— 所以幂等是硬要求,不是优化。纯函数,便于单测。
49
+ */
50
+ export declare function pickFreshClients<T extends {
51
+ id: string;
52
+ }>(known: Iterable<string>, discovered: readonly T[]): T[];
31
53
  export {};
32
54
  //# sourceMappingURL=client-discovery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client-discovery.d.ts","sourceRoot":"","sources":["../src/client-discovery.ts"],"names":[],"mappings":"AAMA,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,qBAAqB;IACrB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IACrC,oCAAoC;IACpC,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IACjC,IAAI,EAAE,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC;IACrC,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,mDAAmD;IACnD,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CACpD;AASD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,YAAY,GAAG,eAAe,EAAE,CA2B1G;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAAE,EAClB,GAAG,EAAE,IAAI,CAAC,YAAY,EAAE,YAAY,GAAG,aAAa,GAAG,UAAU,GAAG,MAAM,CAAC,GAC1E,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAuBvB"}
1
+ {"version":3,"file":"client-discovery.d.ts","sourceRoot":"","sources":["../src/client-discovery.ts"],"names":[],"mappings":"AAMA,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,qBAAqB;IACrB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IACrC,oCAAoC;IACpC,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IACjC,IAAI,EAAE,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC;IACrC,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,mDAAmD;IACnD,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CACpD;AASD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,YAAY,GAAG,eAAe,EAAE,CA2B1G;AAED,gCAAgC;AAChC,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAAE,EAClB,GAAG,EAAE,IAAI,CAAC,YAAY,EAAE,YAAY,GAAG,aAAa,GAAG,UAAU,GAAG,MAAM,CAAC,GAC1E,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAiC7B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,EAAE,CAGjH"}
@@ -39,10 +39,12 @@ export function discoverClients(scanDirs, depIds, env) {
39
39
  return out.sort((a, b) => a.id.localeCompare(b.id));
40
40
  }
41
41
  /**
42
- * 扫描本地物理存在的包 → `name → 依赖名[]`(与 discoverClients 共用 scanDirs/env)。
43
- * 两用,一次扫盘:① keys 即「本地已装包名」,补市场已装判定(require.resolve 在 pnpm 工作区
44
- * 从仓库根解析不到未提升的工作区包);② values 即各包 `dependencies/peer/optional` 的并集名单,
45
- * 供依赖图(谁依赖谁)。**只取依赖名、不看版本区间**(`workspace:^`/`^1.0.0` 一律按名),故无需 semver
42
+ * 扫描本地物理存在的包 → `name → {version, deps}`(与 discoverClients 共用 scanDirs/env)。
43
+ * 三用,一次扫盘:① keys 即「本地已装包名」,补市场已装判定(require.resolve 在 pnpm 工作区
44
+ * 从仓库根解析不到未提升的工作区包);② `deps` 供依赖图(谁依赖谁)——**只取依赖名、不看版本
45
+ * 区间**(`workspace:^`/`^1.0.0` 一律按名),故无需 semver;③ `version`/`keywords`/`description` 供市场卡片:
46
+ * 工作区包这条路径 require.resolve 走不通,不带 version 就只能退回显示 npm latest;不带
47
+ * keywords 则**离线降级列表整批看不见它们**(toLocalPackages 按 keywords 筛 aalis 组件)。
46
48
  * scope 无关(不挑 @aalis)。纯函数便于单测。
47
49
  */
48
50
  export function collectLocalPackageDeps(scanDirs, env) {
@@ -59,9 +61,27 @@ export function collectLocalPackageDeps(scanDirs, env) {
59
61
  ...Object.keys(pkg.peerDependencies ?? {}),
60
62
  ...Object.keys(pkg.optionalDependencies ?? {}),
61
63
  ]);
62
- out.set(pkg.name, [...deps]);
64
+ out.set(pkg.name, {
65
+ version: typeof pkg.version === 'string' ? pkg.version : undefined,
66
+ keywords: Array.isArray(pkg.keywords)
67
+ ? pkg.keywords.filter((k) => typeof k === 'string')
68
+ : undefined,
69
+ description: typeof pkg.description === 'string' ? pkg.description : undefined,
70
+ deps: [...deps],
71
+ });
63
72
  }
64
73
  }
65
74
  return out;
66
75
  }
76
+ /**
77
+ * 从本轮发现结果里挑出**尚未登记**的候选。
78
+ *
79
+ * 前端发现要能重复跑(装完一个 `aalis-interface` 包后立刻重跑,否则它不出现在服务页的
80
+ * 下拉里、必须重启才看得见)。而重复 `fork().provide('webui-client', …)` 会在服务容器里
81
+ * 堆同名重复项 —— 所以幂等是硬要求,不是优化。纯函数,便于单测。
82
+ */
83
+ export function pickFreshClients(known, discovered) {
84
+ const seen = new Set(known);
85
+ return discovered.filter(c => !seen.has(c.id));
86
+ }
67
87
  //# sourceMappingURL=client-discovery.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client-discovery.js","sourceRoot":"","sources":["../src/client-discovery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client-discovery.js","sourceRoot":"","sources":["../src/client-discovery.ts"],"names":[],"mappings":"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"}
package/dist/gate.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { UserIdentity } from '@aalis/plugin-authority-api';
1
+ import type { UserIdentity } from '@aalis/api-authority';
2
2
  /** 从请求解析调用者身份(auth.ts 的 AuthSystem.identify) */
3
3
  type IdentifyFn = (req: {
4
4
  headers: {
@@ -1 +1 @@
1
- {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,gDAAgD;AAChD,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE;IAAE,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,KAAK,YAAY,GAAG,SAAS,CAAC;AAKtF,UAAU,WAAW;IACnB,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9B;AACD,UAAU,YAAY;IACpB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;KAAE,CAAC;CACxD;AACD,KAAK,cAAc,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;AAEtF;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,UAAU,SACvC,cAAc,CAO1B;AAED,kDAAkD;AAClD,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC"}
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,gDAAgD;AAChD,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE;IAAE,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,KAAK,YAAY,GAAG,SAAS,CAAC;AAKtF,UAAU,WAAW;IACnB,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9B;AACD,UAAU,YAAY;IACpB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;KAAE,CAAC;CACxD;AACD,KAAK,cAAc,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;AAEtF;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,UAAU,SACvC,cAAc,CAO1B;AAED,kDAAkD;AAClD,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Context } from '@aalis/core';
2
- import type { ConfigSchema } from '@aalis/plugin-config-api';
2
+ import type { ConfigSchema } from '@aalis/schema-config';
3
3
  export declare const name = "@aalis/plugin-webui-server";
4
4
  export declare const displayName = "WebUI \u670D\u52A1\u7AEF";
5
5
  export declare const subsystem = "platform";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAc,OAAO,EAAkC,MAAM,aAAa,CAAC;AAKvF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AA+C7D,eAAO,MAAM,IAAI,+BAA+B,CAAC;AACjD,eAAO,MAAM,WAAW,6BAAc,CAAC;AACvC,eAAO,MAAM,SAAS,aAAa,CAAC;AACpC,eAAO,MAAM,QAAQ,UAA+B,CAAC;AACrD,eAAO,MAAM,MAAM;;CAMlB,CAAC;AAWF,eAAO,MAAM,YAAY,EAAE,YAiD1B,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;CASzB,CAAC;AAoBF,OAAO,EAAE,KAAK,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAsIlE,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA4yCxF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAc,OAAO,EAAkC,MAAM,aAAa,CAAC;AAGvF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AA0BzD,eAAO,MAAM,IAAI,+BAA+B,CAAC;AACjD,eAAO,MAAM,WAAW,6BAAc,CAAC;AACvC,eAAO,MAAM,SAAS,aAAa,CAAC;AACpC,eAAO,MAAM,QAAQ,UAA+B,CAAC;AACrD,eAAO,MAAM,MAAM;;CAMlB,CAAC;AAWF,eAAO,MAAM,YAAY,EAAE,YAiD1B,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;CASzB,CAAC;AAoBF,OAAO,EAAE,KAAK,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAmJlE,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAi3CxF"}
package/dist/index.js CHANGED
@@ -5,17 +5,17 @@ import { existsSync, readdirSync, readFileSync } from 'node:fs';
5
5
  import { createServer } from 'node:http';
6
6
  import { createRequire } from 'node:module';
7
7
  import { dirname, resolve } from 'node:path';
8
- import { fileURLToPath, pathToFileURL } from 'node:url';
8
+ import { pathToFileURL } from 'node:url';
9
+ import { listLLMModels } from '@aalis/api-llm';
10
+ import { aggregatePlatformDetails, getPlatformAdapters, getPlatformNames, } from '@aalis/api-platform';
11
+ import { createProcessGateway } from '@aalis/api-process';
12
+ import { createStorageGateway, readTailLines } from '@aalis/api-storage';
13
+ import { DEFAULT_SUBSYSTEM_METADATA } from '@aalis/api-webui';
9
14
  import { LogHub, parseLogLine } from '@aalis/core';
10
- import { listLLMModels } from '@aalis/plugin-llm-api';
11
- import { aggregatePlatformDetails, getPlatformAdapters, getPlatformNames, } from '@aalis/plugin-platform-api';
12
- import { createProcessGateway } from '@aalis/plugin-process-api';
13
- import { createStorageGateway, readTailLines } from '@aalis/plugin-storage-api';
14
- import { DEFAULT_SUBSYSTEM_METADATA } from '@aalis/plugin-webui-api';
15
15
  import express from 'express';
16
16
  import { WebSocket, WebSocketServer } from 'ws';
17
17
  import { createAuthSystem, openBrowser } from './auth.js';
18
- import { collectLocalPackageDeps, discoverClients } from './client-discovery.js';
18
+ import { collectLocalPackageDeps, discoverClients, pickFreshClients } from './client-discovery.js';
19
19
  import { renderClientSwitchPage } from './client-switch-page.js';
20
20
  import { createRouteGate } from './gate.js';
21
21
  import { registerFileRoutes } from './routes/files.js';
@@ -141,6 +141,18 @@ async function readLogFileBefore(storage, beforeSeq, limit) {
141
141
  return lines.map(parseLogLine).filter((e) => e !== null && e.seq < beforeSeq);
142
142
  }
143
143
  // ===== 插件入口 =====
144
+ /**
145
+ * 本地包扫描目录:项目根的 `packages/` 与 `node_modules/@aalis`。
146
+ *
147
+ * 两者都以 **cwd(项目根)** 为基准——与 `projectRoot()`、node_modules 加载器的默认值同源。
148
+ *
149
+ * **不可按本文件位置推算**(如 `resolve(dirname(import.meta.url), '../../')`):那是个位置
150
+ * 假设,只在 webui-server 恰好躺在 `<根>/packages/<包>/dist` 时成立。装进用户项目后它解析成
151
+ * `<proj>/node_modules/@aalis`,与第二条重合、退化成同一目录扫两遍,而**用户自己的
152
+ * `packages/` 从来不在范围内** —— 「私有插件放 packages/、第三方插件从 npm 装」这种混合
153
+ * 形态下,本地插件在市场里将不可见。
154
+ */
155
+ const LOCAL_SCAN_DIRS = [resolve(process.cwd(), 'packages'), resolve(process.cwd(), 'node_modules/@aalis')];
144
156
  export async function apply(ctx, config) {
145
157
  const uiConfig = {
146
158
  port: config.port ?? 3000,
@@ -264,6 +276,14 @@ export async function apply(ctx, config) {
264
276
  }
265
277
  // 已发现的前端候选(ready 时填充,逐个注册为 webui-client 服务 provider)。
266
278
  const clientCandidates = [];
279
+ /**
280
+ * 候选 id → 它那条 webui-client provider 的注销句柄。
281
+ *
282
+ * 单独一张表而不是往 ClientCandidate 上加字段:那个类型是 client-discovery 的产出契约,
283
+ * 「怎么注销」是本文件的注册细节,不该反向污染它。对账时只从数组里删掉候选是不够的——
284
+ * 服务池里那条 provider 还在,仍可能被解析到一个已删除的目录。
285
+ */
286
+ const clientProviderDisposers = new Map();
267
287
  /** 当前活跃前端目录 = 解析后的 webui-client 服务(servicePreferences 偏好 > 优先级 > 注册顺序)。 */
268
288
  function currentClientDir() {
269
289
  return ctx.getService('webui-client')?.getClientDir?.();
@@ -355,14 +375,10 @@ export async function apply(ctx, config) {
355
375
  join: (...parts) => resolve(...parts),
356
376
  };
357
377
  registerPluginRoutes(expressApp, ctx, getApp, getPluginMgr, auth.identify, gate);
358
- // 市场「已装」判定 + 依赖图都吃这一份本地扫描(pnpm 工作区下 require.resolve 从仓库根解析不到工作区包):
359
- // 与 discoverClients 同套 scanDirs(monorepo packages/ 同级 + node_modules/@aalis),每请求懒扫(量小)。
360
- // 返回 name→依赖名[]:keys=已装包名,values=依赖图边。
361
- const localScanDirs = [
362
- resolve(dirname(fileURLToPath(import.meta.url)), '../../'),
363
- resolve(process.cwd(), 'node_modules/@aalis'),
364
- ];
365
- registerMarketplaceRoutes(expressApp, ctx, getPluginMgr, gate, uiConfig.marketplaceRegistry, () => collectLocalPackageDeps(localScanDirs, fsScanEnv));
378
+ // 市场「已装」判定、依赖图、前端候选发现共用这一份扫描目录(pnpm 工作区下 require.resolve
379
+ // 从仓库根解析不到工作区包,只能扫盘)。每请求懒扫,量小。
380
+ const localScanDirs = LOCAL_SCAN_DIRS;
381
+ registerMarketplaceRoutes(expressApp, ctx, getPluginMgr, gate, uiConfig.marketplaceRegistry, () => collectLocalPackageDeps(localScanDirs, fsScanEnv), () => discoverAndProvideClients());
366
382
  // 获取历史日志:从 data/latest.log 读尾部 N 条(lazy load)。
367
383
  // 单进程内 LogHub 不再缓存 buffer——历史以文件为单一数据源。
368
384
  expressApp.get('/api/logs', gate(), async (_req, res) => {
@@ -503,7 +519,7 @@ export async function apply(ctx, config) {
503
519
  const pluginMgr = getPluginMgr();
504
520
  const pluginStatus = pluginMgr ? pluginMgr.getStatus() : [];
505
521
  // 按插件 subsystem 归组(未声明 → 'external')。subsystem 是 WebUI 展示概念、
506
- // 由 @aalis/plugin-webui-api 声明合并到 PluginModule,core 状态契约不含——从 module 直接读。
522
+ // 由 @aalis/api-webui 声明合并到 PluginModule,core 状态契约不含——从 module 直接读。
507
523
  const groupsMap = new Map();
508
524
  for (const p of pluginStatus) {
509
525
  const sub = pluginMgr?.getPlugin(p.instanceId)?.module?.subsystem ?? 'external';
@@ -1194,12 +1210,21 @@ export async function apply(ctx, config) {
1194
1210
  res.status(404).json({ error: '前端未就绪,请安装 webui-client 插件 (如 @aalis/plugin-webui-client)' });
1195
1211
  }
1196
1212
  });
1197
- // 启动服务器
1198
- ctx.on('ready', () => {
1199
- // 全动态发现前端:按 `aalis.client:true` 标记扫描,**不硬编码任何前端包名**
1200
- // (与 runtime 加载器的 marker 驱动一致;忒修斯之船——任意第三方前端带标记+dist 即被发现)。
1201
- // 覆盖三种拓扑:monorepo(扫 packages 同级目录)/ 独立项目(扫 node_modules/@aalis + 根 deps)。
1202
- const here = dirname(fileURLToPath(import.meta.url));
1213
+ /**
1214
+ * 全动态发现前端:按 `aalis.client:true` 标记扫描,**不硬编码任何前端包名**
1215
+ * (与 runtime 加载器的 marker 驱动一致;忒修斯之船——任意第三方前端带标记+dist 即被发现)。
1216
+ * 覆盖三种拓扑:monorepo(扫 packages 同级目录)/ 独立项目(扫 node_modules/@aalis + 根 deps)。
1217
+ *
1218
+ * **幂等**,可重复调用:装完一个 `aalis-interface` 包后要立刻重跑,否则它不会出现在服务页
1219
+ * 的下拉里、必须重启才看得见。幂等是硬要求而非优化——重复 `fork().provide()` 会在服务
1220
+ * 容器里堆同名重复项。已登记过的 id 直接跳过。
1221
+ *
1222
+ * 只登记新候选,**不切换活跃前端**:换前端是用户在服务页的显式选择,装了个新的不该把
1223
+ * 他正在用的顶掉。
1224
+ *
1225
+ * @returns 本次新发现的候选数
1226
+ */
1227
+ function discoverAndProvideClients() {
1203
1228
  const projectRequire = createRequire(pathToFileURL(resolve(process.cwd(), 'package.json')));
1204
1229
  const env = {
1205
1230
  ...fsScanEnv,
@@ -1213,23 +1238,52 @@ export async function apply(ctx, config) {
1213
1238
  }
1214
1239
  },
1215
1240
  };
1216
- // here = <pkg>/dist;其上两级即 monorepo 的 packages 目录。再加项目 node_modules/@aalis 作用域。
1217
- const scanDirs = [resolve(here, '../../'), resolve(process.cwd(), 'node_modules/@aalis')];
1241
+ const scanDirs = LOCAL_SCAN_DIRS;
1218
1242
  let depIds = [];
1219
1243
  try {
1244
+ // 每次重读:装完新包后根 dependencies 已变,缓存会让新前端发现不到。
1220
1245
  const rootPkg = JSON.parse(readFileSync(resolve(process.cwd(), 'package.json'), 'utf-8'));
1221
1246
  depIds = Object.keys({ ...rootPkg.dependencies, ...rootPkg.optionalDependencies });
1222
1247
  }
1223
1248
  catch {
1224
1249
  /* 无项目根 package.json(如 monorepo 直跑),跳过 deps 扫描 */
1225
1250
  }
1226
- clientCandidates.push(...discoverClients(scanDirs, depIds, env));
1227
- // 把每个发现到的前端注册为 webui-client 服务的一个 provider(带 label,供「服务」页下拉切换)。
1251
+ const scanned = discoverClients(scanDirs, depIds, env);
1252
+ // 对账:本轮扫不到的候选要摘掉,不能只增不删。卸载现在会真删 node_modules,
1253
+ // 留着的候选指向一个已不存在的目录——它仍在服务池里,被解析到就是整站 404。
1254
+ const scannedIds = new Set(scanned.map(c => c.id));
1255
+ let removed = 0;
1256
+ for (let i = clientCandidates.length - 1; i >= 0; i--) {
1257
+ const stale = clientCandidates[i];
1258
+ if (scannedIds.has(stale.id))
1259
+ continue;
1260
+ clientProviderDisposers.get(stale.id)?.();
1261
+ clientProviderDisposers.delete(stale.id);
1262
+ clientCandidates.splice(i, 1);
1263
+ removed++;
1264
+ ctx.logger.info(`前端已消失,摘除候选: ${stale.label} (${stale.dir})`);
1265
+ }
1266
+ // 摘掉 provider 只改了「服务解析结果」,**真正服务 HTTP 的是 clientDist / staticMiddleware**,
1267
+ // 它们在 ready 时绑定、之后只由 remountActiveClient 更新。不重挂的话,被摘掉的正好是当前
1268
+ // 活跃前端时,express.static 仍指向已删目录 —— 请求落到 SPA 兜底、`index.html` 不存在
1269
+ // → 整站 404,而服务池里明明还有别的可用前端。切换偏好那条路径早就这么做了,这里对齐。
1270
+ if (removed > 0)
1271
+ remountActiveClient();
1272
+ const fresh = pickFreshClients(clientCandidates.map(c => c.id), scanned);
1273
+ clientCandidates.push(...fresh);
1274
+ // 把每个新发现的前端注册为 webui-client 服务的一个 provider(带 label,供「服务」页下拉切换)。
1228
1275
  // 外部插件在 apply 里主动 provide('webui-client') 的也已在服务池中(注册更早 → 默认胜出,仍可被偏好切换)。
1229
- for (const candidate of clientCandidates) {
1230
- ctx.fork(candidate.id).provide('webui-client', { getClientDir: () => candidate.dir }, { label: candidate.label });
1276
+ for (const candidate of fresh) {
1277
+ clientProviderDisposers.set(candidate.id, ctx
1278
+ .fork(candidate.id)
1279
+ .provide('webui-client', { getClientDir: () => candidate.dir }, { label: candidate.label }));
1231
1280
  ctx.logger.info(`发现前端: ${candidate.label} (${candidate.dir})`);
1232
1281
  }
1282
+ return fresh.length;
1283
+ }
1284
+ // 启动服务器
1285
+ ctx.on('ready', () => {
1286
+ discoverAndProvideClients();
1233
1287
  // 活跃前端 = 解析后的 webui-client 服务(servicePreferences 偏好 > 优先级 > 注册顺序);零前端则 404。
1234
1288
  const activeDir = currentClientDir();
1235
1289
  if (activeDir) {
@@ -1240,6 +1294,18 @@ export async function apply(ctx, config) {
1240
1294
  else {
1241
1295
  ctx.logger.warn('未发现任何前端(webui-client provider);前端路由将 404,请安装一个 aalis.client 包');
1242
1296
  }
1297
+ // 监听失败(典型 EADDRINUSE:3000 被别的 dev server 占了)是 bind 之后**异步 emit** 的,
1298
+ // 不在任何调用栈内,外层 try/catch 接不住 —— 无人处理即 uncaughtException →
1299
+ // runtime 的 process.exit(1),把聊天适配器、定时任务连同整个 bot 一起打死。
1300
+ // 契约本该是「WebUI 起不来、其余照跑」(plugin-activation 的插件失败隔离)。
1301
+ //
1302
+ // **必须挂在 wss 上,挂 server 上是死代码。** `new WebSocketServer({ server })` 构造时
1303
+ // 已给 http server 挂了一条 'error' 监听(内容是 `this.emit.bind(this, 'error')`,转发给
1304
+ // wss)并排在最前;EventEmitter 按注册顺序调用,它 emit 到无监听器的 wss 上会同步抛出、
1305
+ // 中断 emit 循环,后注册在 server 上的 handler 因此永远轮不到。
1306
+ wss.on('error', (err) => {
1307
+ ctx.logger.error(`WebUI 监听 ${uiConfig.host}:${uiConfig.port} 失败: ${err.message};WebUI 不可用,其余功能照常运行`);
1308
+ });
1243
1309
  server.listen(uiConfig.port, uiConfig.host, () => {
1244
1310
  const url = `http://${uiConfig.host}:${uiConfig.port}/`;
1245
1311
  const accessUrl = `${url}?token=${authToken}`;