@yunzai-ng/core 0.1.0

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.
Files changed (357) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +51 -0
  3. package/dist/adapter/accounts.d.ts +174 -0
  4. package/dist/adapter/accounts.d.ts.map +1 -0
  5. package/dist/adapter/accounts.js +653 -0
  6. package/dist/adapter/accounts.js.map +1 -0
  7. package/dist/adapter/bots.d.ts +142 -0
  8. package/dist/adapter/bots.d.ts.map +1 -0
  9. package/dist/adapter/bots.js +454 -0
  10. package/dist/adapter/bots.js.map +1 -0
  11. package/dist/adapter/host.d.ts +114 -0
  12. package/dist/adapter/host.d.ts.map +1 -0
  13. package/dist/adapter/host.js +90 -0
  14. package/dist/adapter/host.js.map +1 -0
  15. package/dist/adapter/login.d.ts +174 -0
  16. package/dist/adapter/login.d.ts.map +1 -0
  17. package/dist/adapter/login.js +345 -0
  18. package/dist/adapter/login.js.map +1 -0
  19. package/dist/adapter/registry.d.ts +102 -0
  20. package/dist/adapter/registry.d.ts.map +1 -0
  21. package/dist/adapter/registry.js +150 -0
  22. package/dist/adapter/registry.js.map +1 -0
  23. package/dist/config/core-config.d.ts +151 -0
  24. package/dist/config/core-config.d.ts.map +1 -0
  25. package/dist/config/core-config.js +338 -0
  26. package/dist/config/core-config.js.map +1 -0
  27. package/dist/config/schema.d.ts +449 -0
  28. package/dist/config/schema.d.ts.map +1 -0
  29. package/dist/config/schema.js +871 -0
  30. package/dist/config/schema.js.map +1 -0
  31. package/dist/config/store.d.ts +184 -0
  32. package/dist/config/store.d.ts.map +1 -0
  33. package/dist/config/store.js +428 -0
  34. package/dist/config/store.js.map +1 -0
  35. package/dist/config/yaml.d.ts +23 -0
  36. package/dist/config/yaml.d.ts.map +1 -0
  37. package/dist/config/yaml.js +108 -0
  38. package/dist/config/yaml.js.map +1 -0
  39. package/dist/http/client.d.ts +82 -0
  40. package/dist/http/client.d.ts.map +1 -0
  41. package/dist/http/client.js +658 -0
  42. package/dist/http/client.js.map +1 -0
  43. package/dist/index.d.ts +77 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +94 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/kernel/app.d.ts +244 -0
  48. package/dist/kernel/app.d.ts.map +1 -0
  49. package/dist/kernel/app.js +654 -0
  50. package/dist/kernel/app.js.map +1 -0
  51. package/dist/kernel/kv-sink.d.ts +34 -0
  52. package/dist/kernel/kv-sink.d.ts.map +1 -0
  53. package/dist/kernel/kv-sink.js +25 -0
  54. package/dist/kernel/kv-sink.js.map +1 -0
  55. package/dist/kernel/policy.d.ts +77 -0
  56. package/dist/kernel/policy.d.ts.map +1 -0
  57. package/dist/kernel/policy.js +99 -0
  58. package/dist/kernel/policy.js.map +1 -0
  59. package/dist/kernel/runtime.d.ts +117 -0
  60. package/dist/kernel/runtime.d.ts.map +1 -0
  61. package/dist/kernel/runtime.js +197 -0
  62. package/dist/kernel/runtime.js.map +1 -0
  63. package/dist/kernel/sql-sink.d.ts +36 -0
  64. package/dist/kernel/sql-sink.d.ts.map +1 -0
  65. package/dist/kernel/sql-sink.js +114 -0
  66. package/dist/kernel/sql-sink.js.map +1 -0
  67. package/dist/logger/format.d.ts +67 -0
  68. package/dist/logger/format.d.ts.map +1 -0
  69. package/dist/logger/format.js +218 -0
  70. package/dist/logger/format.js.map +1 -0
  71. package/dist/logger/index.d.ts +97 -0
  72. package/dist/logger/index.d.ts.map +1 -0
  73. package/dist/logger/index.js +363 -0
  74. package/dist/logger/index.js.map +1 -0
  75. package/dist/logger/rotate.d.ts +47 -0
  76. package/dist/logger/rotate.d.ts.map +1 -0
  77. package/dist/logger/rotate.js +242 -0
  78. package/dist/logger/rotate.js.map +1 -0
  79. package/dist/message/segment.d.ts +255 -0
  80. package/dist/message/segment.d.ts.map +1 -0
  81. package/dist/message/segment.js +510 -0
  82. package/dist/message/segment.js.map +1 -0
  83. package/dist/message/split.d.ts +34 -0
  84. package/dist/message/split.d.ts.map +1 -0
  85. package/dist/message/split.js +79 -0
  86. package/dist/message/split.js.map +1 -0
  87. package/dist/message/target.d.ts +29 -0
  88. package/dist/message/target.d.ts.map +1 -0
  89. package/dist/message/target.js +34 -0
  90. package/dist/message/target.js.map +1 -0
  91. package/dist/pipeline/cooldown.d.ts +84 -0
  92. package/dist/pipeline/cooldown.d.ts.map +1 -0
  93. package/dist/pipeline/cooldown.js +94 -0
  94. package/dist/pipeline/cooldown.js.map +1 -0
  95. package/dist/pipeline/dispatch.d.ts +98 -0
  96. package/dist/pipeline/dispatch.d.ts.map +1 -0
  97. package/dist/pipeline/dispatch.js +323 -0
  98. package/dist/pipeline/dispatch.js.map +1 -0
  99. package/dist/pipeline/event.d.ts +130 -0
  100. package/dist/pipeline/event.d.ts.map +1 -0
  101. package/dist/pipeline/event.js +538 -0
  102. package/dist/pipeline/event.js.map +1 -0
  103. package/dist/pipeline/middleware.d.ts +63 -0
  104. package/dist/pipeline/middleware.d.ts.map +1 -0
  105. package/dist/pipeline/middleware.js +174 -0
  106. package/dist/pipeline/middleware.js.map +1 -0
  107. package/dist/pipeline/prompt.d.ts +80 -0
  108. package/dist/pipeline/prompt.d.ts.map +1 -0
  109. package/dist/pipeline/prompt.js +155 -0
  110. package/dist/pipeline/prompt.js.map +1 -0
  111. package/dist/pipeline/router.d.ts +98 -0
  112. package/dist/pipeline/router.d.ts.map +1 -0
  113. package/dist/pipeline/router.js +489 -0
  114. package/dist/pipeline/router.js.map +1 -0
  115. package/dist/platform/detect.d.ts +24 -0
  116. package/dist/platform/detect.d.ts.map +1 -0
  117. package/dist/platform/detect.js +178 -0
  118. package/dist/platform/detect.js.map +1 -0
  119. package/dist/platform/paths.d.ts +38 -0
  120. package/dist/platform/paths.d.ts.map +1 -0
  121. package/dist/platform/paths.js +129 -0
  122. package/dist/platform/paths.js.map +1 -0
  123. package/dist/platform/system.d.ts +71 -0
  124. package/dist/platform/system.d.ts.map +1 -0
  125. package/dist/platform/system.js +242 -0
  126. package/dist/platform/system.js.map +1 -0
  127. package/dist/plugin/context.d.ts +92 -0
  128. package/dist/plugin/context.d.ts.map +1 -0
  129. package/dist/plugin/context.js +573 -0
  130. package/dist/plugin/context.js.map +1 -0
  131. package/dist/plugin/define.d.ts +92 -0
  132. package/dist/plugin/define.d.ts.map +1 -0
  133. package/dist/plugin/define.js +82 -0
  134. package/dist/plugin/define.js.map +1 -0
  135. package/dist/plugin/discover.d.ts +106 -0
  136. package/dist/plugin/discover.d.ts.map +1 -0
  137. package/dist/plugin/discover.js +254 -0
  138. package/dist/plugin/discover.js.map +1 -0
  139. package/dist/plugin/events.d.ts +109 -0
  140. package/dist/plugin/events.d.ts.map +1 -0
  141. package/dist/plugin/events.js +209 -0
  142. package/dist/plugin/events.js.map +1 -0
  143. package/dist/plugin/hooks.d.ts +266 -0
  144. package/dist/plugin/hooks.d.ts.map +1 -0
  145. package/dist/plugin/hooks.js +84 -0
  146. package/dist/plugin/hooks.js.map +1 -0
  147. package/dist/plugin/host.d.ts +160 -0
  148. package/dist/plugin/host.d.ts.map +1 -0
  149. package/dist/plugin/host.js +546 -0
  150. package/dist/plugin/host.js.map +1 -0
  151. package/dist/plugin/market.d.ts +264 -0
  152. package/dist/plugin/market.d.ts.map +1 -0
  153. package/dist/plugin/market.js +700 -0
  154. package/dist/plugin/market.js.map +1 -0
  155. package/dist/plugin/services.d.ts +116 -0
  156. package/dist/plugin/services.d.ts.map +1 -0
  157. package/dist/plugin/services.js +213 -0
  158. package/dist/plugin/services.js.map +1 -0
  159. package/dist/plugin/tar.d.ts +65 -0
  160. package/dist/plugin/tar.d.ts.map +1 -0
  161. package/dist/plugin/tar.js +277 -0
  162. package/dist/plugin/tar.js.map +1 -0
  163. package/dist/render/registry.d.ts +127 -0
  164. package/dist/render/registry.d.ts.map +1 -0
  165. package/dist/render/registry.js +306 -0
  166. package/dist/render/registry.js.map +1 -0
  167. package/dist/scheduler/index.d.ts +67 -0
  168. package/dist/scheduler/index.d.ts.map +1 -0
  169. package/dist/scheduler/index.js +279 -0
  170. package/dist/scheduler/index.js.map +1 -0
  171. package/dist/server/api.d.ts +179 -0
  172. package/dist/server/api.d.ts.map +1 -0
  173. package/dist/server/api.js +602 -0
  174. package/dist/server/api.js.map +1 -0
  175. package/dist/server/auth.d.ts +83 -0
  176. package/dist/server/auth.d.ts.map +1 -0
  177. package/dist/server/auth.js +178 -0
  178. package/dist/server/auth.js.map +1 -0
  179. package/dist/server/browse.d.ts +60 -0
  180. package/dist/server/browse.d.ts.map +1 -0
  181. package/dist/server/browse.js +187 -0
  182. package/dist/server/browse.js.map +1 -0
  183. package/dist/server/files.d.ts +27 -0
  184. package/dist/server/files.d.ts.map +1 -0
  185. package/dist/server/files.js +76 -0
  186. package/dist/server/files.js.map +1 -0
  187. package/dist/server/index.d.ts +189 -0
  188. package/dist/server/index.d.ts.map +1 -0
  189. package/dist/server/index.js +1123 -0
  190. package/dist/server/index.js.map +1 -0
  191. package/dist/server/table.d.ts +105 -0
  192. package/dist/server/table.d.ts.map +1 -0
  193. package/dist/server/table.js +289 -0
  194. package/dist/server/table.js.map +1 -0
  195. package/dist/store/index.d.ts +50 -0
  196. package/dist/store/index.d.ts.map +1 -0
  197. package/dist/store/index.js +120 -0
  198. package/dist/store/index.js.map +1 -0
  199. package/dist/store/json.d.ts +73 -0
  200. package/dist/store/json.d.ts.map +1 -0
  201. package/dist/store/json.js +174 -0
  202. package/dist/store/json.js.map +1 -0
  203. package/dist/store/kv.d.ts +126 -0
  204. package/dist/store/kv.d.ts.map +1 -0
  205. package/dist/store/kv.js +232 -0
  206. package/dist/store/kv.js.map +1 -0
  207. package/dist/store/level.d.ts +103 -0
  208. package/dist/store/level.d.ts.map +1 -0
  209. package/dist/store/level.js +119 -0
  210. package/dist/store/level.js.map +1 -0
  211. package/dist/store/memory.d.ts +61 -0
  212. package/dist/store/memory.d.ts.map +1 -0
  213. package/dist/store/memory.js +94 -0
  214. package/dist/store/memory.js.map +1 -0
  215. package/dist/store/sql.d.ts +142 -0
  216. package/dist/store/sql.d.ts.map +1 -0
  217. package/dist/store/sql.js +246 -0
  218. package/dist/store/sql.js.map +1 -0
  219. package/dist/testing/fake.d.ts +109 -0
  220. package/dist/testing/fake.d.ts.map +1 -0
  221. package/dist/testing/fake.js +196 -0
  222. package/dist/testing/fake.js.map +1 -0
  223. package/dist/testing/index.d.ts +16 -0
  224. package/dist/testing/index.d.ts.map +1 -0
  225. package/dist/testing/index.js +16 -0
  226. package/dist/testing/index.js.map +1 -0
  227. package/dist/testing/mock-adapter.d.ts +205 -0
  228. package/dist/testing/mock-adapter.d.ts.map +1 -0
  229. package/dist/testing/mock-adapter.js +309 -0
  230. package/dist/testing/mock-adapter.js.map +1 -0
  231. package/dist/util/deep.d.ts +108 -0
  232. package/dist/util/deep.d.ts.map +1 -0
  233. package/dist/util/deep.js +275 -0
  234. package/dist/util/deep.js.map +1 -0
  235. package/dist/util/defer.d.ts +107 -0
  236. package/dist/util/defer.d.ts.map +1 -0
  237. package/dist/util/defer.js +163 -0
  238. package/dist/util/defer.js.map +1 -0
  239. package/dist/util/dispose.d.ts +88 -0
  240. package/dist/util/dispose.d.ts.map +1 -0
  241. package/dist/util/dispose.js +143 -0
  242. package/dist/util/dispose.js.map +1 -0
  243. package/dist/util/duration.d.ts +28 -0
  244. package/dist/util/duration.d.ts.map +1 -0
  245. package/dist/util/duration.js +77 -0
  246. package/dist/util/duration.js.map +1 -0
  247. package/dist/util/fs.d.ts +110 -0
  248. package/dist/util/fs.d.ts.map +1 -0
  249. package/dist/util/fs.js +269 -0
  250. package/dist/util/fs.js.map +1 -0
  251. package/dist/util/id.d.ts +49 -0
  252. package/dist/util/id.d.ts.map +1 -0
  253. package/dist/util/id.js +87 -0
  254. package/dist/util/id.js.map +1 -0
  255. package/dist/util/lru.d.ts +74 -0
  256. package/dist/util/lru.d.ts.map +1 -0
  257. package/dist/util/lru.js +156 -0
  258. package/dist/util/lru.js.map +1 -0
  259. package/dist/util/queue.d.ts +64 -0
  260. package/dist/util/queue.d.ts.map +1 -0
  261. package/dist/util/queue.js +147 -0
  262. package/dist/util/queue.js.map +1 -0
  263. package/dist/util/text.d.ts +86 -0
  264. package/dist/util/text.d.ts.map +1 -0
  265. package/dist/util/text.js +182 -0
  266. package/dist/util/text.js.map +1 -0
  267. package/package.json +44 -0
  268. package/src/adapter/accounts.ts +758 -0
  269. package/src/adapter/bots.ts +582 -0
  270. package/src/adapter/host.ts +224 -0
  271. package/src/adapter/login.ts +481 -0
  272. package/src/adapter/registry.ts +202 -0
  273. package/src/config/core-config.test.ts +60 -0
  274. package/src/config/core-config.ts +401 -0
  275. package/src/config/schema.test.ts +179 -0
  276. package/src/config/schema.ts +1036 -0
  277. package/src/config/store.test.ts +245 -0
  278. package/src/config/store.ts +506 -0
  279. package/src/config/yaml.ts +119 -0
  280. package/src/http/client.test.ts +568 -0
  281. package/src/http/client.ts +777 -0
  282. package/src/index.ts +106 -0
  283. package/src/kernel/app.test.ts +267 -0
  284. package/src/kernel/app.ts +843 -0
  285. package/src/kernel/kv-sink.ts +58 -0
  286. package/src/kernel/policy.ts +120 -0
  287. package/src/kernel/runtime.test.ts +542 -0
  288. package/src/kernel/runtime.ts +307 -0
  289. package/src/kernel/sql-sink.ts +154 -0
  290. package/src/logger/format.ts +259 -0
  291. package/src/logger/index.ts +427 -0
  292. package/src/logger/rotate.ts +265 -0
  293. package/src/message/segment.test.ts +335 -0
  294. package/src/message/segment.ts +569 -0
  295. package/src/message/split.ts +97 -0
  296. package/src/message/target.ts +48 -0
  297. package/src/pipeline/cooldown.ts +136 -0
  298. package/src/pipeline/dispatch.ts +419 -0
  299. package/src/pipeline/event.ts +735 -0
  300. package/src/pipeline/middleware.test.ts +426 -0
  301. package/src/pipeline/middleware.ts +199 -0
  302. package/src/pipeline/prompt.ts +212 -0
  303. package/src/pipeline/router.test.ts +432 -0
  304. package/src/pipeline/router.ts +575 -0
  305. package/src/platform/detect.ts +178 -0
  306. package/src/platform/paths.ts +147 -0
  307. package/src/platform/system.test.ts +102 -0
  308. package/src/platform/system.ts +289 -0
  309. package/src/plugin/context.test.ts +459 -0
  310. package/src/plugin/context.ts +757 -0
  311. package/src/plugin/define.test.ts +120 -0
  312. package/src/plugin/define.ts +142 -0
  313. package/src/plugin/discover.test.ts +253 -0
  314. package/src/plugin/discover.ts +353 -0
  315. package/src/plugin/events.test.ts +162 -0
  316. package/src/plugin/events.ts +266 -0
  317. package/src/plugin/hooks.ts +373 -0
  318. package/src/plugin/host.test.ts +696 -0
  319. package/src/plugin/host.ts +738 -0
  320. package/src/plugin/market.test.ts +781 -0
  321. package/src/plugin/market.ts +870 -0
  322. package/src/plugin/services.test.ts +135 -0
  323. package/src/plugin/services.ts +261 -0
  324. package/src/plugin/tar.test.ts +158 -0
  325. package/src/plugin/tar.ts +309 -0
  326. package/src/render/registry.test.ts +127 -0
  327. package/src/render/registry.ts +439 -0
  328. package/src/scheduler/index.ts +357 -0
  329. package/src/server/api.test.ts +802 -0
  330. package/src/server/api.ts +869 -0
  331. package/src/server/auth.ts +201 -0
  332. package/src/server/browse.test.ts +193 -0
  333. package/src/server/browse.ts +240 -0
  334. package/src/server/files.ts +97 -0
  335. package/src/server/index.test.ts +566 -0
  336. package/src/server/index.ts +1386 -0
  337. package/src/server/table.ts +351 -0
  338. package/src/store/index.ts +156 -0
  339. package/src/store/json.ts +198 -0
  340. package/src/store/kv.test.ts +307 -0
  341. package/src/store/kv.ts +256 -0
  342. package/src/store/level.ts +167 -0
  343. package/src/store/memory.ts +109 -0
  344. package/src/store/sql.test.ts +204 -0
  345. package/src/store/sql.ts +324 -0
  346. package/src/testing/fake.ts +297 -0
  347. package/src/testing/index.ts +15 -0
  348. package/src/testing/mock-adapter.ts +588 -0
  349. package/src/util/deep.ts +272 -0
  350. package/src/util/defer.ts +211 -0
  351. package/src/util/dispose.ts +169 -0
  352. package/src/util/duration.ts +82 -0
  353. package/src/util/fs.ts +279 -0
  354. package/src/util/id.ts +94 -0
  355. package/src/util/lru.ts +185 -0
  356. package/src/util/queue.ts +167 -0
  357. package/src/util/text.ts +189 -0
@@ -0,0 +1,345 @@
1
+ import { parseDuration } from "../util/duration.js";
2
+ import { createEventId } from "../util/id.js";
3
+ /** 单次提问的缺省超时(毫秒),与 `LoginPrompt.timeout` 文档一致 */
4
+ export const DEFAULT_LOGIN_PROMPT_TIMEOUT = 180_000;
5
+ /** 整个登录会话的硬上限(毫秒):扫码最多两三分钟,十分钟足够宽裕 */
6
+ export const DEFAULT_LOGIN_TTL = 600_000;
7
+ /** 已结束的会话保留多久供前端读取结果(毫秒) */
8
+ const RESULT_TTL = 120_000;
9
+ /** 步骤数组上限:`progress` 刷屏或反复刷新二维码时不能无限增长 */
10
+ const MAX_STEPS = 40;
11
+ /**
12
+ * 取错误的可读描述
13
+ * @param err 任意抛出物
14
+ * @returns 描述文本
15
+ */
16
+ function errText(err) {
17
+ return err instanceof Error ? err.message : String(err);
18
+ }
19
+ /**
20
+ * 交互式登录会话管理器
21
+ *
22
+ * WebUI 侧的用法:`start()` 拿到 id → 轮询/订阅 `snapshot(id)` → 遇到
23
+ * `pending` 就渲染输入框,用户提交后 `answer(id, seq, value)` → 直到
24
+ * `status` 不再是 `running`。
25
+ */
26
+ export class LoginManager {
27
+ /** 日志器 */
28
+ #logger;
29
+ /** 适配器注册表 */
30
+ #adapters;
31
+ /** 账号创建回调 */
32
+ #createAccount;
33
+ /** 会话硬上限 */
34
+ #ttl;
35
+ /** 会话 id → 状态 */
36
+ #sessions = new Map();
37
+ /**
38
+ * @param opts 构造参数
39
+ */
40
+ constructor(opts) {
41
+ this.#logger = opts.logger.child({ scope: "login" });
42
+ this.#adapters = opts.adapters;
43
+ this.#createAccount = opts.createAccount;
44
+ this.#ttl = opts.ttl ?? DEFAULT_LOGIN_TTL;
45
+ }
46
+ /** 进行中的会话数 */
47
+ get running() {
48
+ let n = 0;
49
+ for (const s of this.#sessions.values())
50
+ if (s.status === "running")
51
+ n++;
52
+ return n;
53
+ }
54
+ /**
55
+ * 开始一次交互式登录
56
+ *
57
+ * **同步返回**,登录流程在后台跑,见文件头第 1 点。
58
+ * @param adapterId 适配器 id
59
+ * @param mode 登录方式 id
60
+ * @param label 账号备注名
61
+ * @returns 初始快照
62
+ * @throws 适配器不存在、不支持交互式登录、或方式 id 无效时
63
+ */
64
+ start(adapterId, mode, label) {
65
+ const provider = this.#adapters.get(adapterId);
66
+ if (provider === undefined)
67
+ throw new Error(`适配器 ${adapterId} 未注册:请先安装并启用对应的适配器插件`);
68
+ const login = provider.login;
69
+ if (login === undefined) {
70
+ throw new Error(`适配器 ${provider.name} 不支持交互式登录,请在"添加账号"里直接填写配置`);
71
+ }
72
+ const modes = provider.loginModes ?? [];
73
+ if (modes.length > 0 && !modes.some(m => m.id === mode)) {
74
+ const names = modes.map(m => `${m.id}(${m.name})`).join("、");
75
+ throw new Error(`适配器 ${provider.name} 没有名为 ${mode} 的登录方式,可用:${names}`);
76
+ }
77
+ const id = createEventId("login");
78
+ const now = Date.now();
79
+ const state = {
80
+ id,
81
+ adapterId,
82
+ mode,
83
+ label,
84
+ controller: new AbortController(),
85
+ steps: [],
86
+ status: "running",
87
+ pending: undefined,
88
+ resolveAsk: undefined,
89
+ rejectAsk: undefined,
90
+ ttlTimer: undefined,
91
+ reapTimer: undefined,
92
+ seq: 0,
93
+ error: undefined,
94
+ accountId: undefined,
95
+ startedAt: now,
96
+ updatedAt: now
97
+ };
98
+ this.#sessions.set(id, state);
99
+ state.ttlTimer = setTimeout(() => {
100
+ this.#abort(state, `登录超时(超过 ${Math.round(this.#ttl / 1000)} 秒未完成)`, "failed");
101
+ }, this.#ttl);
102
+ state.ttlTimer.unref?.();
103
+ const session = this.#createSession(state);
104
+ this.#logger.info(`开始登录:适配器 ${adapterId},方式 ${mode},会话 ${id}`);
105
+ // 后台跑:不 await,也不让它的 rejection 冒成 unhandledRejection
106
+ void login(session, mode).then(config => void this.#succeed(state, config), (err) => this.#fail(state, err));
107
+ return this.snapshotOf(state);
108
+ }
109
+ /**
110
+ * 读一个会话的快照
111
+ * @param id 会话 id
112
+ * @returns 快照;会话不存在(或已自毁)时 undefined
113
+ */
114
+ snapshot(id) {
115
+ const state = this.#sessions.get(id);
116
+ return state === undefined ? undefined : this.snapshotOf(state);
117
+ }
118
+ /**
119
+ * 列出全部会话
120
+ * @returns 快照数组,按开始时间
121
+ */
122
+ list() {
123
+ return [...this.#sessions.values()].map(s => this.snapshotOf(s));
124
+ }
125
+ /**
126
+ * 提交用户的答复
127
+ * @param id 会话 id
128
+ * @param seq 提问序号,必须与 `pending.seq` 一致
129
+ * @param value 用户输入
130
+ * @returns 是否被接受
131
+ */
132
+ answer(id, seq, value) {
133
+ const state = this.#sessions.get(id);
134
+ if (state === undefined || state.status !== "running")
135
+ return false;
136
+ const pending = state.pending;
137
+ if (pending === undefined)
138
+ return false;
139
+ // 序号不符即丢弃:见文件头第 2 点
140
+ if (pending.seq !== seq) {
141
+ this.#logger.debug(`会话 ${id} 收到过期答复(seq ${seq},当前 ${pending.seq}),已忽略`);
142
+ return false;
143
+ }
144
+ state.resolveAsk?.(value);
145
+ return true;
146
+ }
147
+ /**
148
+ * 取消一个会话
149
+ * @param id 会话 id
150
+ * @returns 是否取消成功(会话不存在或已结束时 false)
151
+ */
152
+ cancel(id) {
153
+ const state = this.#sessions.get(id);
154
+ if (state === undefined || state.status !== "running")
155
+ return false;
156
+ this.#abort(state, "用户取消了登录", "cancelled");
157
+ return true;
158
+ }
159
+ /** 取消全部会话并清理(停机时调用) */
160
+ stop() {
161
+ for (const state of [...this.#sessions.values()]) {
162
+ if (state.status === "running")
163
+ this.#abort(state, "内核正在停止", "cancelled");
164
+ if (state.ttlTimer !== undefined)
165
+ clearTimeout(state.ttlTimer);
166
+ if (state.reapTimer !== undefined)
167
+ clearTimeout(state.reapTimer);
168
+ }
169
+ this.#sessions.clear();
170
+ }
171
+ /**
172
+ * 生成快照
173
+ * @param state 会话状态
174
+ * @returns 快照
175
+ */
176
+ snapshotOf(state) {
177
+ return {
178
+ id: state.id,
179
+ adapterId: state.adapterId,
180
+ mode: state.mode,
181
+ status: state.status,
182
+ // 复制数组:前端持有的快照不该跟着后续 push 变化,否则"这一帧看到了什么"
183
+ // 就说不清了。步骤有上限,复制成本可控。
184
+ steps: [...state.steps],
185
+ pending: state.pending,
186
+ error: state.error,
187
+ accountId: state.accountId,
188
+ startedAt: state.startedAt,
189
+ updatedAt: state.updatedAt
190
+ };
191
+ }
192
+ /**
193
+ * 造出交给适配器的 `LoginSession`
194
+ * @param state 会话状态
195
+ * @returns 登录会话
196
+ */
197
+ #createSession(state) {
198
+ const logger = this.#logger.child({ session: state.id });
199
+ return {
200
+ id: state.id,
201
+ logger,
202
+ signal: state.controller.signal,
203
+ push: (step) => {
204
+ if (state.status !== "running")
205
+ return;
206
+ const steps = state.steps;
207
+ const last = steps[steps.length - 1];
208
+ // 进度覆盖上一条进度:否则一个每秒 push 一次的适配器将累积出数百条
209
+ // 只有最后一条有意义的记录
210
+ if (step.type === "progress" && last?.type === "progress")
211
+ steps[steps.length - 1] = step;
212
+ else
213
+ steps.push(step);
214
+ // 超出上限丢最旧的:二维码可能是几十 KB 的 base64,不能无限累积
215
+ while (steps.length > MAX_STEPS)
216
+ steps.shift();
217
+ state.updatedAt = Date.now();
218
+ },
219
+ ask: (prompt) => this.#ask(state, prompt)
220
+ };
221
+ }
222
+ /**
223
+ * 等待一次用户输入
224
+ *
225
+ * 与 `pipeline/prompt.ts` 同构:超时、会话取消、用户答复三个终止条件
226
+ * 都汇到一个只许生效一次的 `settle` 上。
227
+ * @param state 会话状态
228
+ * @param prompt 提问内容
229
+ * @returns 用户输入
230
+ * @throws 超时、被取消、或适配器并发提问时
231
+ */
232
+ #ask(state, prompt) {
233
+ if (state.status !== "running")
234
+ return Promise.reject(new Error("登录会话已结束,不能再提问"));
235
+ if (state.pending !== undefined) {
236
+ // 前端一次只渲染一个输入框,同时问两个问题必然有一个永远收不到答复
237
+ return Promise.reject(new Error("上一次提问还没得到答复:登录流程必须串行提问"));
238
+ }
239
+ const ms = parseDuration(prompt.timeout, DEFAULT_LOGIN_PROMPT_TIMEOUT);
240
+ const seq = ++state.seq;
241
+ return new Promise((resolve, reject) => {
242
+ let done = false;
243
+ let timer;
244
+ /** 统一收尾 */
245
+ const settle = (fn) => {
246
+ if (done)
247
+ return;
248
+ done = true;
249
+ if (timer !== undefined)
250
+ clearTimeout(timer);
251
+ state.pending = undefined;
252
+ state.resolveAsk = undefined;
253
+ state.rejectAsk = undefined;
254
+ state.updatedAt = Date.now();
255
+ fn();
256
+ };
257
+ state.pending = { seq, prompt, deadline: Date.now() + ms };
258
+ state.resolveAsk = (value) => settle(() => resolve(value));
259
+ state.rejectAsk = (err) => settle(() => reject(err));
260
+ state.updatedAt = Date.now();
261
+ if (ms > 0) {
262
+ timer = setTimeout(() => {
263
+ settle(() => reject(new Error(`等待"${prompt.label}"超时`)));
264
+ }, ms);
265
+ timer.unref?.();
266
+ }
267
+ });
268
+ }
269
+ /**
270
+ * 中止一个会话
271
+ * @param state 会话状态
272
+ * @param reason 原因
273
+ * @param status 终态
274
+ */
275
+ #abort(state, reason, status) {
276
+ if (state.status !== "running")
277
+ return;
278
+ // 先落终态再 abort:适配器的 catch 里可能回读 snapshot,看到的应该是终态
279
+ state.status = status;
280
+ state.error = reason;
281
+ state.updatedAt = Date.now();
282
+ state.rejectAsk?.(new Error(reason));
283
+ state.controller.abort();
284
+ this.#finish(state);
285
+ this.#logger.info(`登录会话 ${state.id} 结束:${reason}`);
286
+ }
287
+ /**
288
+ * 登录成功:落账号
289
+ * @param state 会话状态
290
+ * @param config 登录产出的账号配置
291
+ */
292
+ async #succeed(state, config) {
293
+ if (state.status !== "running")
294
+ return;
295
+ try {
296
+ const record = await this.#createAccount(state.adapterId, config, state.label);
297
+ state.accountId = record.id;
298
+ state.status = "done";
299
+ state.updatedAt = Date.now();
300
+ this.#finish(state);
301
+ this.#logger.info(`登录成功:会话 ${state.id} → 账号 ${record.id}`);
302
+ }
303
+ catch (err) {
304
+ // 登录本身成功了但存不下来(磁盘满、配置校验不过),这仍然是失败:
305
+ // 让用户看到原因,而不是一个"成功了但列表里没有"的账号
306
+ this.#fail(state, err);
307
+ }
308
+ }
309
+ /**
310
+ * 登录失败
311
+ * @param state 会话状态
312
+ * @param err 错误
313
+ */
314
+ #fail(state, err) {
315
+ // 已被取消/超时的会话不要把状态改成 failed —— 用户点了取消,
316
+ // 适配器随后抛出的 AbortError 只是取消的回声
317
+ if (state.status !== "running")
318
+ return;
319
+ state.status = "failed";
320
+ state.error = errText(err);
321
+ state.updatedAt = Date.now();
322
+ state.controller.abort();
323
+ this.#finish(state);
324
+ this.#logger.warn(`登录失败:会话 ${state.id}:${state.error}`);
325
+ }
326
+ /**
327
+ * 结束善后:停 TTL、安排自毁
328
+ * @param state 会话状态
329
+ */
330
+ #finish(state) {
331
+ if (state.ttlTimer !== undefined) {
332
+ clearTimeout(state.ttlTimer);
333
+ state.ttlTimer = undefined;
334
+ }
335
+ if (state.reapTimer !== undefined)
336
+ return;
337
+ // 保留一段时间供前端读取结果,之后自毁 —— 否则一个长期运行的实例将累积
338
+ // 无数条历史登录记录(每条都可能挂着一张二维码)
339
+ state.reapTimer = setTimeout(() => {
340
+ this.#sessions.delete(state.id);
341
+ }, RESULT_TTL);
342
+ state.reapTimer.unref?.();
343
+ }
344
+ }
345
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/adapter/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * 模块职责:适配器注册表(实现 `AdapterSink` 与 `AdapterRegistryView`)
3
+ * 依赖方向:仅依赖类型包与 plugin/hooks 的接缝定义;**不认识账号管理器**
4
+ * 生命周期:随内核创建;每条注册随提供方插件卸载而摘除
5
+ * 注意事项:这是"账号登录也是插件"的登记处 —— 内核对 QQ 协议零认知,只知道
6
+ * "某个插件声称能把一份账号配置变成一个能收发消息的 BotDriver"。
7
+ *
8
+ * 摘除一条适配器时必须先断开它名下的全部账号,但 `Disposer` 是**同步**的
9
+ * (见 util/dispose.ts:插件卸载走 `DisposalRegistry.dispose()`,不 await)。
10
+ * 于是这里只做同步通知:`onUnregister` 的监听者(账号管理器)必须在回调里
11
+ * **同步**把账号标成下线、让 `AdapterHost.submit()` 立刻开始丢弃事件,
12
+ * 真正的 socket 关闭再异步收尾。否则会出现"插件已卸载但事件还在往管线里灌",
13
+ * 症状是热重载后收到重复回复。
14
+ */
15
+ import type { AdapterProvider, AdapterRegistryView, Disposer, Logger } from "@yunzai-ng/types";
16
+ import type { AdapterSink } from "../plugin/hooks.js";
17
+ /** 适配器描述(`list()` 的元素类型,WebUI 的"添加账号"页面据此渲染) */
18
+ export type AdapterSummary = Pick<AdapterProvider, "id" | "name" | "description" | "platform" | "accountSchema" | "loginModes">;
19
+ /** 注册表内部条目 */
20
+ export interface AdapterEntry {
21
+ /** 适配器实现 */
22
+ readonly provider: AdapterProvider;
23
+ /** 提供方插件名 */
24
+ readonly owner: string;
25
+ }
26
+ /** 摘除通知监听器 */
27
+ export type AdapterUnregisterListener = (id: string, entry: AdapterEntry) => void;
28
+ /** 注册通知监听器 */
29
+ export type AdapterRegisterListener = (id: string, entry: AdapterEntry) => void;
30
+ /** 适配器注册表构造参数 */
31
+ export interface AdapterRegistryOptions {
32
+ /** 日志器 */
33
+ readonly logger: Logger;
34
+ }
35
+ /**
36
+ * 适配器注册表
37
+ *
38
+ * 既是 `ctx.registerAdapter()` 的落点(`AdapterSink`),也是 WebUI 与账号管理器
39
+ * 的查询入口(`AdapterRegistryView`)。
40
+ */
41
+ export declare class AdapterRegistry implements AdapterSink, AdapterRegistryView {
42
+ #private;
43
+ /**
44
+ * @param opts 构造参数
45
+ */
46
+ constructor(opts: AdapterRegistryOptions);
47
+ /** 已注册的适配器数量 */
48
+ get size(): number;
49
+ /**
50
+ * 注册一个适配器
51
+ * @param provider 适配器实现
52
+ * @param owner 提供方插件名
53
+ * @returns 注销句柄
54
+ * @throws 该 id 已被别的插件占用时
55
+ */
56
+ register(provider: AdapterProvider, owner: string): Disposer;
57
+ /**
58
+ * 按 id 取适配器
59
+ * @param id 适配器 id
60
+ * @returns 适配器实现;未注册时 undefined
61
+ */
62
+ get(id: string): AdapterProvider | undefined;
63
+ /**
64
+ * 按 id 取条目(含提供方插件名)
65
+ * @param id 适配器 id
66
+ * @returns 条目;未注册时 undefined
67
+ */
68
+ entry(id: string): AdapterEntry | undefined;
69
+ /**
70
+ * 列出已注册的适配器
71
+ * @returns 适配器描述数组,按注册顺序
72
+ */
73
+ list(): AdapterSummary[];
74
+ /**
75
+ * 登记注册通知
76
+ *
77
+ * 为热重载而存在:适配器插件重新加载后,其名下账号须自行重连,
78
+ * 否则用户须在面板中逐个点击连接。
79
+ * @param listener 监听器
80
+ * @returns 取消登记
81
+ */
82
+ onRegister(listener: AdapterRegisterListener): Disposer;
83
+ /**
84
+ * 登记摘除通知
85
+ *
86
+ * 回调在 `Disposer` 里**同步**执行,因此实现方不能在里面 await 网络操作,
87
+ * 只能做"立刻停止投递事件"这类同步动作,见文件头。
88
+ * @param listener 监听器
89
+ * @returns 取消登记
90
+ */
91
+ onUnregister(listener: AdapterUnregisterListener): Disposer;
92
+ /**
93
+ * 摘除某插件注册的全部适配器
94
+ *
95
+ * 兜底路径:插件上下文正常会逐条调 Disposer,但插件 setup 抛在半路时
96
+ * 可能有登记没走 ctx。
97
+ * @param owner 插件名
98
+ * @returns 摘除的条数
99
+ */
100
+ removePlugin(owner: string): number;
101
+ }
102
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/adapter/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD,gDAAgD;AAChD,MAAM,MAAM,cAAc,GAAG,IAAI,CAC/B,eAAe,EACf,IAAI,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,eAAe,GAAG,YAAY,CAC5E,CAAA;AAED,cAAc;AACd,MAAM,WAAW,YAAY;IAC3B,YAAY;IACZ,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAA;IAClC,aAAa;IACb,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,cAAc;AACd,MAAM,MAAM,yBAAyB,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;AAEjF,cAAc;AACd,MAAM,MAAM,uBAAuB,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;AAE/E,iBAAiB;AACjB,MAAM,WAAW,sBAAsB;IACrC,UAAU;IACV,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,WAAW,EAAE,mBAAmB;;IAUtE;;OAEG;gBACS,IAAI,EAAE,sBAAsB;IAIxC,gBAAgB;IAChB,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ;IAwB5D;;;;OAIG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAI5C;;;;OAIG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI3C;;;OAGG;IACH,IAAI,IAAI,cAAc,EAAE;IAWxB;;;;;;;OAOG;IACH,UAAU,CAAC,QAAQ,EAAE,uBAAuB,GAAG,QAAQ;IAKvD;;;;;;;OAOG;IACH,YAAY,CAAC,QAAQ,EAAE,yBAAyB,GAAG,QAAQ;IAK3D;;;;;;;OAOG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAgCpC"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * 适配器注册表
3
+ *
4
+ * 既是 `ctx.registerAdapter()` 的落点(`AdapterSink`),也是 WebUI 与账号管理器
5
+ * 的查询入口(`AdapterRegistryView`)。
6
+ */
7
+ export class AdapterRegistry {
8
+ /** 日志器 */
9
+ #logger;
10
+ /** 适配器 id → 条目 */
11
+ #entries = new Map();
12
+ /** 摘除通知监听器 */
13
+ #listeners = new Set();
14
+ /** 注册通知监听器 */
15
+ #onRegister = new Set();
16
+ /**
17
+ * @param opts 构造参数
18
+ */
19
+ constructor(opts) {
20
+ this.#logger = opts.logger.child({ scope: "adapter" });
21
+ }
22
+ /** 已注册的适配器数量 */
23
+ get size() {
24
+ return this.#entries.size;
25
+ }
26
+ /**
27
+ * 注册一个适配器
28
+ * @param provider 适配器实现
29
+ * @param owner 提供方插件名
30
+ * @returns 注销句柄
31
+ * @throws 该 id 已被别的插件占用时
32
+ */
33
+ register(provider, owner) {
34
+ const existing = this.#entries.get(provider.id);
35
+ if (existing !== undefined) {
36
+ // 不做"后来者覆盖":id 是账号记录里引用适配器的唯一凭据,
37
+ // 悄悄换掉实现会让已存的账号连到另一套协议上去
38
+ throw new Error(`适配器 id ${provider.id} 已被插件 ${existing.owner} 注册,插件 ${owner} 不能重复注册;` +
39
+ `请改用不同的 id(账号记录靠它定位适配器实现)`);
40
+ }
41
+ const entry = { provider, owner };
42
+ this.#entries.set(provider.id, entry);
43
+ this.#logger.info(`适配器就绪:${provider.name}(${provider.id},平台 ${provider.platform},来自插件 ${owner})`);
44
+ for (const listener of [...this.#onRegister]) {
45
+ try {
46
+ listener(provider.id, entry);
47
+ }
48
+ catch (err) {
49
+ this.#logger.error(`处理适配器 ${provider.id} 的注册通知时出错`, err);
50
+ }
51
+ }
52
+ return () => this.#remove(provider.id, entry);
53
+ }
54
+ /**
55
+ * 按 id 取适配器
56
+ * @param id 适配器 id
57
+ * @returns 适配器实现;未注册时 undefined
58
+ */
59
+ get(id) {
60
+ return this.#entries.get(id)?.provider;
61
+ }
62
+ /**
63
+ * 按 id 取条目(含提供方插件名)
64
+ * @param id 适配器 id
65
+ * @returns 条目;未注册时 undefined
66
+ */
67
+ entry(id) {
68
+ return this.#entries.get(id);
69
+ }
70
+ /**
71
+ * 列出已注册的适配器
72
+ * @returns 适配器描述数组,按注册顺序
73
+ */
74
+ list() {
75
+ return [...this.#entries.values()].map(({ provider }) => ({
76
+ id: provider.id,
77
+ name: provider.name,
78
+ description: provider.description,
79
+ platform: provider.platform,
80
+ accountSchema: provider.accountSchema,
81
+ loginModes: provider.loginModes
82
+ }));
83
+ }
84
+ /**
85
+ * 登记注册通知
86
+ *
87
+ * 为热重载而存在:适配器插件重新加载后,其名下账号须自行重连,
88
+ * 否则用户须在面板中逐个点击连接。
89
+ * @param listener 监听器
90
+ * @returns 取消登记
91
+ */
92
+ onRegister(listener) {
93
+ this.#onRegister.add(listener);
94
+ return () => void this.#onRegister.delete(listener);
95
+ }
96
+ /**
97
+ * 登记摘除通知
98
+ *
99
+ * 回调在 `Disposer` 里**同步**执行,因此实现方不能在里面 await 网络操作,
100
+ * 只能做"立刻停止投递事件"这类同步动作,见文件头。
101
+ * @param listener 监听器
102
+ * @returns 取消登记
103
+ */
104
+ onUnregister(listener) {
105
+ this.#listeners.add(listener);
106
+ return () => void this.#listeners.delete(listener);
107
+ }
108
+ /**
109
+ * 摘除某插件注册的全部适配器
110
+ *
111
+ * 兜底路径:插件上下文正常会逐条调 Disposer,但插件 setup 抛在半路时
112
+ * 可能有登记没走 ctx。
113
+ * @param owner 插件名
114
+ * @returns 摘除的条数
115
+ */
116
+ removePlugin(owner) {
117
+ let n = 0;
118
+ for (const [id, entry] of [...this.#entries]) {
119
+ if (entry.owner === owner) {
120
+ this.#remove(id, entry);
121
+ n++;
122
+ }
123
+ }
124
+ return n;
125
+ }
126
+ /**
127
+ * 摘除一条注册
128
+ *
129
+ * 比对 entry 而不是只看 id:插件 A 卸载得晚、插件 B 已经用同一个 id 注册了
130
+ * 新实现时,A 的 Disposer 不应将 B 的实现摘除。
131
+ * @param id 适配器 id
132
+ * @param entry 注册时的条目
133
+ */
134
+ #remove(id, entry) {
135
+ if (this.#entries.get(id) !== entry)
136
+ return;
137
+ // 先通知再删:监听者要能通过 entry 拿到 provider 做收尾
138
+ for (const listener of [...this.#listeners]) {
139
+ try {
140
+ listener(id, entry);
141
+ }
142
+ catch (err) {
143
+ this.#logger.error(`处理适配器 ${id} 的摘除通知时出错`, err);
144
+ }
145
+ }
146
+ this.#entries.delete(id);
147
+ this.#logger.info(`适配器 ${id} 已摘除(插件 ${entry.owner})`);
148
+ }
149
+ }
150
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/adapter/registry.ts"],"names":[],"mappings":"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"}