dsh-qqbot-buddy 1.0.0-alpha.2 → 1.0.0-alpha.4

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.
@@ -34,6 +34,32 @@ function collect(ctx) {
34
34
  return { bots, profiles, bindings, activeProfiles, runtime };
35
35
  }
36
36
 
37
+ /**
38
+ * dsh Web 入口:优先用启动时缓存,为空时向插件根 ctx 现算一次(解决 web-app/connection 就绪时序问题)。
39
+ * @param {object} ctx 控制台请求上下文
40
+ * @returns {{url:string, ready:boolean, error:string, hasWebApp:boolean, hasConnection:boolean}|null}
41
+ */
42
+ function readDshWeb(ctx) {
43
+ const cached = ctx.deps && ctx.deps.dshWeb ? ctx.deps.dshWeb : null;
44
+ let info = cached
45
+ ? {
46
+ url: typeof cached.url === 'string' ? cached.url : '',
47
+ ready: cached.ready === true,
48
+ error: typeof cached.error === 'string' ? cached.error : '',
49
+ hasWebApp: cached.hasWebApp === true,
50
+ hasConnection: cached.hasConnection === true,
51
+ }
52
+ : null;
53
+ if ((!info || info.url === '') && ctx.deps && typeof ctx.deps.resolveDshWeb === 'function') {
54
+ try {
55
+ const live = ctx.deps.resolveDshWeb();
56
+ if (live && !info) info = live;
57
+ else if (live && live.url !== '') info = live;
58
+ } catch { /* 保持 cached */ }
59
+ }
60
+ return info;
61
+ }
62
+
37
63
  export const routes = [
38
64
  {
39
65
  method: 'GET',
@@ -59,13 +85,7 @@ export const routes = [
59
85
  uptimeMs,
60
86
  },
61
87
  runtime: { online: runtime.online, bots: runtime.bots },
62
- dshWeb: ctx.deps && ctx.deps.dshWeb
63
- ? {
64
- url: typeof ctx.deps.dshWeb.url === 'string' ? ctx.deps.dshWeb.url : '',
65
- ready: ctx.deps.dshWeb.ready === true,
66
- error: typeof ctx.deps.dshWeb.error === 'string' ? ctx.deps.dshWeb.error : '',
67
- }
68
- : null,
88
+ dshWeb: readDshWeb(ctx),
69
89
  };
70
90
  },
71
91
  },
package/lib/index.js CHANGED
@@ -11,6 +11,40 @@ import path from 'node:path';
11
11
  import { fileURLToPath } from 'node:url';
12
12
 
13
13
  import { ConfigSchema } from './config-schema.js';
14
+
15
+ /**
16
+ * 解析当前 dsh Web 的带鉴权入口 URL(控制台「dsh Web ↗」按钮用)。
17
+ * 为什么不用一次性 ctx.inject:web-app/connection 的就绪时机在不同 profile/启动参数下
18
+ * 并不稳定(实测 qqbot profile 下 inject 回调可能一直不触发),这里做成可重复调用的惰性解析,
19
+ * 由 console 的 /api/state 在需要时现算,避免按钮因启动时序问题消失。
20
+ * @param {object} scope 任意能 get 服务的 cordis 上下文(插件根 ctx / 请求 ctx)
21
+ * @returns {{url:string, ready:boolean, error:string, hasWebApp:boolean, hasConnection:boolean}}
22
+ */
23
+ function resolveDshWeb(scope) {
24
+ const get = (name) => {
25
+ try {
26
+ if (!scope) return undefined;
27
+ if (typeof scope.get === 'function') return scope.get(name);
28
+ return scope[name];
29
+ } catch { return undefined; }
30
+ };
31
+ const webApp = get('webApp');
32
+ const connection = get('connection');
33
+ const hasWebApp = Boolean(webApp);
34
+ const hasConnection = Boolean(connection);
35
+ if (!hasWebApp || !hasConnection) {
36
+ return { url: '', ready: false, error: '', hasWebApp, hasConnection };
37
+ }
38
+ try {
39
+ const root = typeof webApp.getAdvertisedUrl === 'function' ? webApp.getAdvertisedUrl() : '';
40
+ const url = root !== '' && typeof connection.authenticatedUrl === 'function'
41
+ ? connection.authenticatedUrl(root)
42
+ : root;
43
+ return { url: typeof url === 'string' ? url : '', ready: true, error: '', hasWebApp, hasConnection };
44
+ } catch (err) {
45
+ return { url: '', ready: true, error: errText(err), hasWebApp, hasConnection };
46
+ }
47
+ }
14
48
  import { createLogger } from './logger.js';
15
49
  import { openDb, closeDb } from './core/db.js';
16
50
  import { createConfigStore } from './core/config/store.js';
@@ -110,23 +144,16 @@ export async function apply(ctx, config) {
110
144
 
111
145
  // dsh Web 入口(带鉴权 token 的 URL):控制台顶栏「dsh Web」按钮用。
112
146
  // web-app/connection 服务可能晚于本插件就绪,用 ctx.inject 等待后回填。
113
- runtime.dshWeb = { url: '', ready: false, error: '' };
147
+ runtime.dshWeb = { url: '', ready: false, error: '', hasWebApp: false, hasConnection: false };
148
+ runtime.rootCtx = ctx;
149
+ runtime.resolveDshWeb = () => resolveDshWeb(ctx);
114
150
  try {
115
- ctx.inject(['webApp', 'connection'], (wctx) => {
116
- try {
117
- const root = wctx.webApp && typeof wctx.webApp.getAdvertisedUrl === 'function' ? wctx.webApp.getAdvertisedUrl() : '';
118
- const connection = wctx.connection;
119
- const url = root !== '' && connection && typeof connection.authenticatedUrl === 'function'
120
- ? connection.authenticatedUrl(root)
121
- : root;
122
- runtime.dshWeb = { url: typeof url === 'string' ? url : '', ready: true, error: '' };
123
- } catch (err) {
124
- runtime.dshWeb = { url: '', ready: true, error: errText(err) };
125
- logger.warn('dsh Web 入口获取失败: ' + errText(err));
126
- }
127
- });
151
+ // 服务先就绪时立即算一次;没就绪时保留惰性解析(state API 每次请求会再试)
152
+ const initial = resolveDshWeb(ctx);
153
+ if (initial.url !== '') runtime.dshWeb = initial;
154
+ else logger.info('dsh Web 入口暂未就绪(等待 web-app/connection,按钮会在可用后自动出现)');
128
155
  } catch (err) {
129
- logger.warn('dsh Web 入口注入失败: ' + errText(err));
156
+ logger.warn('dsh Web 入口解析失败: ' + errText(err));
130
157
  }
131
158
 
132
159
  // 技能 provider(v1 的 lib/skills/provider.js 等价物):
@@ -214,6 +241,8 @@ export async function apply(ctx, config) {
214
241
  logger,
215
242
  toolsDiscover: discovery || undefined,
216
243
  dshWeb: runtime.dshWeb,
244
+ resolveDshWeb: runtime.resolveDshWeb,
245
+ rootCtx: ctx,
217
246
  getHost: () => runtime.host,
218
247
  actions: {
219
248
  async run(name, body = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-qqbot-buddy",
3
- "version": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.4",
4
4
  "description": "DSH QQ 机器人插件 v2:自包含管理控制台、配置档/会话级配置、可管理的工具与技能、SQLite+FTS5 记忆与知识库",
5
5
  "type": "module",
6
6
  "license": "MIT",