@planet-matrix/mobius-model 0.5.0 → 0.9.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 (379) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +123 -36
  3. package/dist/index.js +715 -4
  4. package/dist/index.js.map +981 -13
  5. package/oxlint.config.ts +6 -0
  6. package/package.json +36 -18
  7. package/src/abort/README.md +92 -0
  8. package/src/abort/abort-manager.ts +278 -0
  9. package/src/abort/abort-signal-listener-manager.ts +81 -0
  10. package/src/abort/index.ts +2 -0
  11. package/src/ai/README.md +1 -0
  12. package/src/ai/ai.ts +107 -0
  13. package/src/ai/chat-completion-ai/aihubmix-chat-completion.ts +78 -0
  14. package/src/ai/chat-completion-ai/chat-completion-ai.ts +270 -0
  15. package/src/ai/chat-completion-ai/chat-completion.ts +189 -0
  16. package/src/ai/chat-completion-ai/index.ts +7 -0
  17. package/src/ai/chat-completion-ai/lingyiwanwu-chat-completion.ts +78 -0
  18. package/src/ai/chat-completion-ai/ohmygpt-chat-completion.ts +78 -0
  19. package/src/ai/chat-completion-ai/openai-next-chat-completion.ts +78 -0
  20. package/src/ai/embedding-ai/embedding-ai.ts +63 -0
  21. package/src/ai/embedding-ai/embedding.ts +50 -0
  22. package/src/ai/embedding-ai/index.ts +4 -0
  23. package/src/ai/embedding-ai/openai-next-embedding.ts +23 -0
  24. package/src/ai/index.ts +4 -0
  25. package/src/aio/README.md +100 -0
  26. package/src/aio/content.ts +141 -0
  27. package/src/aio/index.ts +3 -0
  28. package/src/aio/json.ts +127 -0
  29. package/src/aio/prompt.ts +246 -0
  30. package/src/basic/README.md +72 -116
  31. package/src/basic/error.ts +19 -5
  32. package/src/basic/function.ts +83 -64
  33. package/src/basic/index.ts +1 -0
  34. package/src/basic/is.ts +152 -71
  35. package/src/basic/promise.ts +29 -8
  36. package/src/basic/schedule.ts +111 -0
  37. package/src/basic/stream.ts +135 -25
  38. package/src/basic/string.ts +2 -33
  39. package/src/color/README.md +105 -0
  40. package/src/color/index.ts +3 -0
  41. package/src/color/internal.ts +42 -0
  42. package/src/color/rgb/analyze.ts +236 -0
  43. package/src/color/rgb/construct.ts +130 -0
  44. package/src/color/rgb/convert.ts +227 -0
  45. package/src/color/rgb/derive.ts +303 -0
  46. package/src/color/rgb/index.ts +6 -0
  47. package/src/color/rgb/internal.ts +208 -0
  48. package/src/color/rgb/parse.ts +302 -0
  49. package/src/color/rgb/serialize.ts +144 -0
  50. package/src/color/types.ts +57 -0
  51. package/src/color/xyz/analyze.ts +80 -0
  52. package/src/color/xyz/construct.ts +19 -0
  53. package/src/color/xyz/convert.ts +71 -0
  54. package/src/color/xyz/index.ts +3 -0
  55. package/src/color/xyz/internal.ts +23 -0
  56. package/src/credential/README.md +107 -0
  57. package/src/credential/api-key.ts +158 -0
  58. package/src/credential/bearer.ts +73 -0
  59. package/src/credential/index.ts +4 -0
  60. package/src/credential/json-web-token.ts +96 -0
  61. package/src/credential/password.ts +170 -0
  62. package/src/cron/README.md +86 -0
  63. package/src/cron/cron.ts +87 -0
  64. package/src/cron/index.ts +1 -0
  65. package/src/css/README.md +93 -0
  66. package/src/css/class.ts +559 -0
  67. package/src/css/index.ts +1 -0
  68. package/src/drizzle/README.md +1 -0
  69. package/src/drizzle/drizzle.ts +1 -0
  70. package/src/drizzle/helper.ts +47 -0
  71. package/src/drizzle/index.ts +5 -0
  72. package/src/drizzle/infer.ts +52 -0
  73. package/src/drizzle/kysely.ts +8 -0
  74. package/src/drizzle/pagination.ts +200 -0
  75. package/src/email/README.md +1 -0
  76. package/src/email/index.ts +1 -0
  77. package/src/email/resend.ts +25 -0
  78. package/src/encoding/README.md +66 -79
  79. package/src/encoding/base64.ts +13 -4
  80. package/src/environment/README.md +97 -0
  81. package/src/environment/basic.ts +26 -0
  82. package/src/environment/device.ts +311 -0
  83. package/src/environment/feature.ts +285 -0
  84. package/src/environment/geo.ts +337 -0
  85. package/src/environment/index.ts +7 -0
  86. package/src/environment/runtime.ts +400 -0
  87. package/src/environment/snapshot.ts +60 -0
  88. package/src/environment/variable.ts +239 -0
  89. package/src/event/README.md +90 -0
  90. package/src/event/class-event-proxy.ts +229 -0
  91. package/src/event/common.ts +29 -0
  92. package/src/event/event-manager.ts +203 -0
  93. package/src/event/index.ts +4 -0
  94. package/src/event/instance-event-proxy.ts +187 -0
  95. package/src/event/internal.ts +24 -0
  96. package/src/exception/README.md +96 -0
  97. package/src/exception/browser.ts +219 -0
  98. package/src/exception/index.ts +4 -0
  99. package/src/exception/nodejs.ts +169 -0
  100. package/src/exception/normalize.ts +106 -0
  101. package/src/exception/types.ts +99 -0
  102. package/src/form/README.md +25 -0
  103. package/src/form/index.ts +1 -0
  104. package/src/form/inputor-controller/base.ts +874 -0
  105. package/src/form/inputor-controller/boolean.ts +39 -0
  106. package/src/form/inputor-controller/file.ts +39 -0
  107. package/src/form/inputor-controller/form.ts +181 -0
  108. package/src/form/inputor-controller/helper.ts +117 -0
  109. package/src/form/inputor-controller/index.ts +17 -0
  110. package/src/form/inputor-controller/multi-select.ts +99 -0
  111. package/src/form/inputor-controller/number.ts +116 -0
  112. package/src/form/inputor-controller/select.ts +109 -0
  113. package/src/form/inputor-controller/text.ts +82 -0
  114. package/src/http/READMD.md +1 -0
  115. package/src/http/api/api-core.ts +84 -0
  116. package/src/http/api/api-handler.ts +79 -0
  117. package/src/http/api/api-host.ts +47 -0
  118. package/src/http/api/api-result.ts +56 -0
  119. package/src/http/api/api-schema.ts +154 -0
  120. package/src/http/api/api-server.ts +130 -0
  121. package/src/http/api/api-test.ts +142 -0
  122. package/src/http/api/api-type.ts +37 -0
  123. package/src/http/api/api.ts +81 -0
  124. package/src/http/api/index.ts +11 -0
  125. package/src/http/api-adapter/api-core-node-http.ts +260 -0
  126. package/src/http/api-adapter/api-host-node-http.ts +156 -0
  127. package/src/http/api-adapter/api-result-arktype.ts +297 -0
  128. package/src/http/api-adapter/api-result-zod.ts +286 -0
  129. package/src/http/api-adapter/index.ts +5 -0
  130. package/src/http/bin/gen-api-list/gen-api-list.ts +126 -0
  131. package/src/http/bin/gen-api-list/index.ts +1 -0
  132. package/src/http/bin/gen-api-test/gen-api-test.ts +136 -0
  133. package/src/http/bin/gen-api-test/index.ts +1 -0
  134. package/src/http/bin/gen-api-type/calc-code.ts +25 -0
  135. package/src/http/bin/gen-api-type/gen-api-type.ts +127 -0
  136. package/src/http/bin/gen-api-type/index.ts +2 -0
  137. package/src/http/bin/index.ts +2 -0
  138. package/src/http/index.ts +3 -0
  139. package/src/huawei/README.md +1 -0
  140. package/src/huawei/index.ts +2 -0
  141. package/src/huawei/moderation/index.ts +1 -0
  142. package/src/huawei/moderation/moderation.ts +355 -0
  143. package/src/huawei/obs/esdk-obs-nodejs.d.ts +87 -0
  144. package/src/huawei/obs/index.ts +1 -0
  145. package/src/huawei/obs/obs.ts +42 -0
  146. package/src/identifier/README.md +92 -0
  147. package/src/identifier/id.ts +119 -0
  148. package/src/identifier/index.ts +2 -0
  149. package/src/identifier/uuid.ts +187 -0
  150. package/src/index.ts +33 -1
  151. package/src/json/README.md +92 -0
  152. package/src/json/index.ts +1 -0
  153. package/src/json/repair.ts +18 -0
  154. package/src/log/README.md +79 -0
  155. package/src/log/index.ts +5 -0
  156. package/src/log/log-emitter.ts +72 -0
  157. package/src/log/log-record.ts +10 -0
  158. package/src/log/log-scheduler.ts +74 -0
  159. package/src/log/log-type.ts +8 -0
  160. package/src/log/logger.ts +554 -0
  161. package/src/openai/README.md +1 -0
  162. package/src/openai/index.ts +1 -0
  163. package/src/openai/openai.ts +510 -0
  164. package/src/orchestration/README.md +91 -0
  165. package/src/orchestration/coordination/barrier.ts +214 -0
  166. package/src/orchestration/coordination/count-down-latch.ts +215 -0
  167. package/src/orchestration/coordination/errors.ts +98 -0
  168. package/src/orchestration/coordination/index.ts +16 -0
  169. package/src/orchestration/coordination/internal/wait-constraints.ts +95 -0
  170. package/src/orchestration/coordination/internal/wait-queue.ts +109 -0
  171. package/src/orchestration/coordination/keyed-lock.ts +168 -0
  172. package/src/orchestration/coordination/mutex.ts +257 -0
  173. package/src/orchestration/coordination/permit.ts +127 -0
  174. package/src/orchestration/coordination/read-write-lock.ts +444 -0
  175. package/src/orchestration/coordination/semaphore.ts +280 -0
  176. package/src/orchestration/dispatching/dispatcher.ts +83 -0
  177. package/src/orchestration/dispatching/index.ts +2 -0
  178. package/src/orchestration/dispatching/selector/base-selector.ts +39 -0
  179. package/src/orchestration/dispatching/selector/down-count-selector.ts +119 -0
  180. package/src/orchestration/dispatching/selector/index.ts +2 -0
  181. package/src/orchestration/index.ts +3 -0
  182. package/src/orchestration/scheduling/index.ts +2 -0
  183. package/src/orchestration/scheduling/scheduler.ts +103 -0
  184. package/src/orchestration/scheduling/task.ts +32 -0
  185. package/src/random/README.md +56 -86
  186. package/src/random/base.ts +66 -0
  187. package/src/random/index.ts +5 -1
  188. package/src/random/random-boolean.ts +40 -0
  189. package/src/random/random-integer.ts +60 -0
  190. package/src/random/random-number.ts +72 -0
  191. package/src/random/random-string.ts +66 -0
  192. package/src/reactor/README.md +4 -0
  193. package/src/reactor/reactor-core/primitive.ts +9 -9
  194. package/src/reactor/reactor-core/reactive-system.ts +5 -5
  195. package/src/request/README.md +108 -0
  196. package/src/request/fetch/base.ts +108 -0
  197. package/src/request/fetch/browser.ts +285 -0
  198. package/src/request/fetch/general.ts +20 -0
  199. package/src/request/fetch/index.ts +4 -0
  200. package/src/request/fetch/nodejs.ts +285 -0
  201. package/src/request/index.ts +2 -0
  202. package/src/request/request/base.ts +250 -0
  203. package/src/request/request/general.ts +64 -0
  204. package/src/request/request/index.ts +3 -0
  205. package/src/request/request/resource.ts +68 -0
  206. package/src/result/README.md +4 -0
  207. package/src/result/controller.ts +54 -0
  208. package/src/result/either.ts +193 -0
  209. package/src/result/index.ts +2 -0
  210. package/src/route/README.md +105 -0
  211. package/src/route/adapter/browser.ts +122 -0
  212. package/src/route/adapter/driver.ts +56 -0
  213. package/src/route/adapter/index.ts +2 -0
  214. package/src/route/index.ts +3 -0
  215. package/src/route/router/index.ts +2 -0
  216. package/src/route/router/route.ts +630 -0
  217. package/src/route/router/router.ts +1642 -0
  218. package/src/route/uri/hash.ts +308 -0
  219. package/src/route/uri/index.ts +7 -0
  220. package/src/route/uri/pathname.ts +376 -0
  221. package/src/route/uri/search.ts +413 -0
  222. package/src/singleton/README.md +79 -0
  223. package/src/singleton/factory.ts +55 -0
  224. package/src/singleton/index.ts +2 -0
  225. package/src/singleton/manager.ts +204 -0
  226. package/src/socket/README.md +105 -0
  227. package/src/socket/client/index.ts +2 -0
  228. package/src/socket/client/socket-unit.ts +660 -0
  229. package/src/socket/client/socket.ts +203 -0
  230. package/src/socket/common/index.ts +2 -0
  231. package/src/socket/common/socket-unit-common.ts +23 -0
  232. package/src/socket/common/socket-unit-heartbeat.ts +427 -0
  233. package/src/socket/index.ts +3 -0
  234. package/src/socket/server/index.ts +3 -0
  235. package/src/socket/server/server.ts +183 -0
  236. package/src/socket/server/socket-unit.ts +449 -0
  237. package/src/socket/server/socket.ts +264 -0
  238. package/src/storage/README.md +107 -0
  239. package/src/storage/index.ts +1 -0
  240. package/src/storage/table.ts +449 -0
  241. package/src/timer/README.md +86 -0
  242. package/src/timer/expiration/expiration-manager.ts +594 -0
  243. package/src/timer/expiration/index.ts +3 -0
  244. package/src/timer/expiration/min-heap.ts +208 -0
  245. package/src/timer/expiration/remaining-manager.ts +241 -0
  246. package/src/timer/index.ts +1 -0
  247. package/src/tube/README.md +99 -0
  248. package/src/tube/helper.ts +138 -0
  249. package/src/tube/index.ts +2 -0
  250. package/src/tube/tube.ts +880 -0
  251. package/src/type/README.md +54 -307
  252. package/src/type/class.ts +2 -2
  253. package/src/type/index.ts +14 -14
  254. package/src/type/is.ts +265 -2
  255. package/src/type/object.ts +37 -0
  256. package/src/type/string.ts +7 -2
  257. package/src/type/tuple.ts +6 -6
  258. package/src/type/union.ts +16 -0
  259. package/src/web/README.md +77 -0
  260. package/src/web/capture.ts +35 -0
  261. package/src/web/clipboard.ts +97 -0
  262. package/src/web/dom.ts +117 -0
  263. package/src/web/download.ts +16 -0
  264. package/src/web/event.ts +46 -0
  265. package/src/web/index.ts +10 -0
  266. package/src/web/local-storage.ts +113 -0
  267. package/src/web/location.ts +28 -0
  268. package/src/web/permission.ts +172 -0
  269. package/src/web/script-loader.ts +432 -0
  270. package/src/weixin/README.md +1 -0
  271. package/src/weixin/index.ts +2 -0
  272. package/src/weixin/official-account/authorization.ts +159 -0
  273. package/src/weixin/official-account/index.ts +2 -0
  274. package/src/weixin/official-account/js-api.ts +134 -0
  275. package/src/weixin/open/index.ts +1 -0
  276. package/src/weixin/open/oauth2.ts +133 -0
  277. package/tests/unit/abort/abort-manager.spec.ts +225 -0
  278. package/tests/unit/abort/abort-signal-listener-manager.spec.ts +62 -0
  279. package/tests/unit/ai/ai.spec.ts +85 -0
  280. package/tests/unit/aio/content.spec.ts +105 -0
  281. package/tests/unit/aio/json.spec.ts +147 -0
  282. package/tests/unit/aio/prompt.spec.ts +111 -0
  283. package/tests/unit/basic/array.spec.ts +1 -1
  284. package/tests/unit/basic/error.spec.ts +16 -4
  285. package/tests/unit/basic/schedule.spec.ts +74 -0
  286. package/tests/unit/basic/stream.spec.ts +91 -38
  287. package/tests/unit/basic/string.spec.ts +0 -9
  288. package/tests/unit/color/rgb/analyze.spec.ts +110 -0
  289. package/tests/unit/color/rgb/construct.spec.ts +56 -0
  290. package/tests/unit/color/rgb/convert.spec.ts +60 -0
  291. package/tests/unit/color/rgb/derive.spec.ts +103 -0
  292. package/tests/unit/color/rgb/parse.spec.ts +66 -0
  293. package/tests/unit/color/rgb/serialize.spec.ts +46 -0
  294. package/tests/unit/color/xyz/analyze.spec.ts +33 -0
  295. package/tests/unit/color/xyz/construct.spec.ts +10 -0
  296. package/tests/unit/color/xyz/convert.spec.ts +18 -0
  297. package/tests/unit/credential/api-key.spec.ts +37 -0
  298. package/tests/unit/credential/bearer.spec.ts +23 -0
  299. package/tests/unit/credential/json-web-token.spec.ts +23 -0
  300. package/tests/unit/credential/password.spec.ts +41 -0
  301. package/tests/unit/cron/cron.spec.ts +84 -0
  302. package/tests/unit/css/class.spec.ts +157 -0
  303. package/tests/unit/environment/basic.spec.ts +20 -0
  304. package/tests/unit/environment/device.spec.ts +146 -0
  305. package/tests/unit/environment/feature.spec.ts +388 -0
  306. package/tests/unit/environment/geo.spec.ts +111 -0
  307. package/tests/unit/environment/runtime.spec.ts +364 -0
  308. package/tests/unit/environment/snapshot.spec.ts +4 -0
  309. package/tests/unit/environment/variable.spec.ts +190 -0
  310. package/tests/unit/event/class-event-proxy.spec.ts +225 -0
  311. package/tests/unit/event/event-manager.spec.ts +246 -0
  312. package/tests/unit/event/instance-event-proxy.spec.ts +187 -0
  313. package/tests/unit/exception/browser.spec.ts +213 -0
  314. package/tests/unit/exception/nodejs.spec.ts +144 -0
  315. package/tests/unit/exception/normalize.spec.ts +57 -0
  316. package/tests/unit/form/inputor-controller/base.spec.ts +458 -0
  317. package/tests/unit/form/inputor-controller/boolean.spec.ts +30 -0
  318. package/tests/unit/form/inputor-controller/file.spec.ts +27 -0
  319. package/tests/unit/form/inputor-controller/form.spec.ts +120 -0
  320. package/tests/unit/form/inputor-controller/helper.spec.ts +67 -0
  321. package/tests/unit/form/inputor-controller/multi-select.spec.ts +34 -0
  322. package/tests/unit/form/inputor-controller/number.spec.ts +36 -0
  323. package/tests/unit/form/inputor-controller/select.spec.ts +49 -0
  324. package/tests/unit/form/inputor-controller/text.spec.ts +34 -0
  325. package/tests/unit/http/api/api-core-host.spec.ts +207 -0
  326. package/tests/unit/http/api/api-schema.spec.ts +120 -0
  327. package/tests/unit/http/api/api-server.spec.ts +363 -0
  328. package/tests/unit/http/api/api-test.spec.ts +117 -0
  329. package/tests/unit/http/api/api.spec.ts +121 -0
  330. package/tests/unit/http/api-adapter/node-http.spec.ts +191 -0
  331. package/tests/unit/identifier/id.spec.ts +71 -0
  332. package/tests/unit/identifier/uuid.spec.ts +85 -0
  333. package/tests/unit/json/repair.spec.ts +11 -0
  334. package/tests/unit/log/log-emitter.spec.ts +33 -0
  335. package/tests/unit/log/log-scheduler.spec.ts +40 -0
  336. package/tests/unit/log/log-type.spec.ts +7 -0
  337. package/tests/unit/log/logger.spec.ts +237 -0
  338. package/tests/unit/openai/openai.spec.ts +64 -0
  339. package/tests/unit/orchestration/coordination/barrier.spec.ts +96 -0
  340. package/tests/unit/orchestration/coordination/count-down-latch.spec.ts +63 -0
  341. package/tests/unit/orchestration/coordination/errors.spec.ts +29 -0
  342. package/tests/unit/orchestration/coordination/keyed-lock.spec.ts +109 -0
  343. package/tests/unit/orchestration/coordination/mutex.spec.ts +132 -0
  344. package/tests/unit/orchestration/coordination/permit.spec.ts +43 -0
  345. package/tests/unit/orchestration/coordination/read-write-lock.spec.ts +154 -0
  346. package/tests/unit/orchestration/coordination/semaphore.spec.ts +135 -0
  347. package/tests/unit/orchestration/dispatching/dispatcher.spec.ts +41 -0
  348. package/tests/unit/orchestration/dispatching/selector/down-count-selector.spec.ts +81 -0
  349. package/tests/unit/orchestration/scheduling/scheduler.spec.ts +103 -0
  350. package/tests/unit/random/base.spec.ts +58 -0
  351. package/tests/unit/random/random-boolean.spec.ts +25 -0
  352. package/tests/unit/random/random-integer.spec.ts +32 -0
  353. package/tests/unit/random/random-number.spec.ts +33 -0
  354. package/tests/unit/random/random-string.spec.ts +22 -0
  355. package/tests/unit/reactor/alien-signals-effect.spec.ts +11 -10
  356. package/tests/unit/reactor/preact-signal.spec.ts +1 -2
  357. package/tests/unit/request/fetch/browser.spec.ts +222 -0
  358. package/tests/unit/request/fetch/general.spec.ts +43 -0
  359. package/tests/unit/request/fetch/nodejs.spec.ts +225 -0
  360. package/tests/unit/request/request/base.spec.ts +385 -0
  361. package/tests/unit/request/request/general.spec.ts +161 -0
  362. package/tests/unit/route/router/route.spec.ts +431 -0
  363. package/tests/unit/route/router/router.spec.ts +407 -0
  364. package/tests/unit/route/uri/hash.spec.ts +72 -0
  365. package/tests/unit/route/uri/pathname.spec.ts +147 -0
  366. package/tests/unit/route/uri/search.spec.ts +107 -0
  367. package/tests/unit/singleton/singleton.spec.ts +49 -0
  368. package/tests/unit/socket/client.spec.ts +208 -0
  369. package/tests/unit/socket/server.spec.ts +135 -0
  370. package/tests/unit/socket/socket-unit-heartbeat.spec.ts +214 -0
  371. package/tests/unit/storage/table.spec.ts +620 -0
  372. package/tests/unit/timer/expiration/expiration-manager.spec.ts +464 -0
  373. package/tests/unit/timer/expiration/min-heap.spec.ts +71 -0
  374. package/tests/unit/timer/expiration/remaining-manager.spec.ts +234 -0
  375. package/tests/unit/tube/helper.spec.ts +139 -0
  376. package/tests/unit/tube/tube.spec.ts +501 -0
  377. package/.oxlintrc.json +0 -5
  378. package/src/random/uuid.ts +0 -103
  379. package/tests/unit/random/uuid.spec.ts +0 -37
@@ -0,0 +1,62 @@
1
+ import { expect, test } from "vitest"
2
+
3
+ import {
4
+ AbortSignalListenerManager,
5
+ getGlobalAbortSignalListenerManager,
6
+ } from "#Source/abort/index.ts"
7
+
8
+ test("AbortSignalListenerManager.hasEventListener checks managed listener state", () => {
9
+ const manager = new AbortSignalListenerManager()
10
+ const abortController = new AbortController()
11
+ const listener = (): void => {
12
+ void abortController
13
+ }
14
+
15
+ expect(manager.hasEventListener(abortController.signal, listener)).toBe(false)
16
+
17
+ manager.addEventListener(abortController.signal, listener)
18
+
19
+ expect(manager.hasEventListener(abortController.signal, listener)).toBe(true)
20
+
21
+ manager.removeEventListener(abortController.signal, listener)
22
+
23
+ expect(manager.hasEventListener(abortController.signal, listener)).toBe(false)
24
+ })
25
+
26
+ test("AbortSignalListenerManager.addEventListener registers listener for abort events", () => {
27
+ const manager = new AbortSignalListenerManager()
28
+ const abortController = new AbortController()
29
+ let count = 0
30
+ const listener = (): void => {
31
+ count = count + 1
32
+ }
33
+
34
+ manager.addEventListener(abortController.signal, listener)
35
+
36
+ abortController.abort("stop")
37
+
38
+ expect(count).toBe(1)
39
+ })
40
+
41
+ test("AbortSignalListenerManager.removeEventListener unregisters listener", () => {
42
+ const manager = new AbortSignalListenerManager()
43
+ const abortController = new AbortController()
44
+ let count = 0
45
+ const listener = (): void => {
46
+ count = count + 1
47
+ }
48
+
49
+ manager.addEventListener(abortController.signal, listener)
50
+ manager.removeEventListener(abortController.signal, listener)
51
+
52
+ abortController.abort("stop")
53
+
54
+ expect(count).toBe(0)
55
+ })
56
+
57
+ test("getGlobalAbortSignalListenerManager returns singleton instance", () => {
58
+ const first = getGlobalAbortSignalListenerManager()
59
+ const second = getGlobalAbortSignalListenerManager()
60
+
61
+ expect(first).toBe(second)
62
+ })
@@ -0,0 +1,85 @@
1
+ import * as Ai from "#Source/ai/index.ts"
2
+ import { Openai } from "#Source/openai/index.ts"
3
+ import { eitherToTuple } from "#Source/result/index.ts"
4
+ import { tubeToReadableStream } from "#Source/tube/index.ts"
5
+ import { test } from "vitest"
6
+
7
+ const testApiKey = "sk-DLj8aHvKjvHfZ7IHA2F07c968c3d4aE491C1525e40E24932"
8
+ const testBaseUrl = "https://cn.api.openai-next.com/v1/"
9
+ const ai = new Ai.Ai({
10
+ chatCompletionAiOptions: {
11
+ chatCompletionInstanceList: [
12
+ new Ai.ChatCompletionAi.OpenaiNextChatCompletion.OpenaiNextChatCompletion({
13
+ openai: new Openai({
14
+ apiKey: testApiKey,
15
+ baseUrl: testBaseUrl,
16
+ }),
17
+ }),
18
+ ],
19
+ },
20
+ embeddingAiOptions: {
21
+ embeddingInstanceList: [
22
+ new Ai.EmbeddingAi.OpenaiNextEmbedding.OpenaiNextEmbedding({
23
+ openai: new Openai({
24
+ apiKey: testApiKey,
25
+ baseUrl: testBaseUrl,
26
+ }),
27
+ }),
28
+ ],
29
+ },
30
+ instancePool: [
31
+ new Openai({
32
+ apiKey: testApiKey,
33
+ baseUrl: testBaseUrl,
34
+ }),
35
+ ],
36
+ indexChangeMode: "poll",
37
+ })
38
+
39
+ test("ai", { timeout: 60_000 }, async () => {
40
+ const 请求开始时间 = Date.now()
41
+ let 第一个字返回时间: number | null = null
42
+ let 累积文本 = ""
43
+
44
+ const [leftResult, rightResult] = eitherToTuple(await ai.chatCompletionAi.chatCompletion({
45
+ model: "gpt-4o-mini",
46
+ messages: [
47
+ {
48
+ role: "system",
49
+ content:
50
+ "你是一个返回JSON格式的AI助手, 预期的格式是: {\"回复内容\": string}. 你是小学生,有“雌小鬼”的性格。你瞧不起用户,经常称呼用户为“杂鱼”、“杂鱼大哥哥”等,表现出一种轻蔑和挑衅的态度。",
51
+ },
52
+ { role: "user", content: "你好" },
53
+ ],
54
+ responseFormat: { type: "json_object" },
55
+ }))
56
+ if (leftResult !== undefined) {
57
+ throw new Error(`请求失败: ${JSON.stringify(leftResult)}`)
58
+ }
59
+ const { completionTube: completionData } = rightResult
60
+ const stream = tubeToReadableStream(completionData)
61
+
62
+ try {
63
+ for await (const completion of stream) {
64
+ if (第一个字返回时间 === null) {
65
+ 第一个字返回时间 = Date.now()
66
+ }
67
+ 累积文本 = completion.content.total
68
+ }
69
+ }
70
+ catch (exception) {
71
+ throw new Error(`请求失败: ${String(exception)}`, { cause: exception })
72
+ }
73
+
74
+ if (第一个字返回时间 === null) { throw new Error("第一个字返回时间 为 null") }
75
+
76
+ const 请求结束时间 = Date.now()
77
+
78
+ const 第一个字时间 = 第一个字返回时间 - 请求开始时间
79
+ const 平均字返回时间 = (请求结束时间 - 请求开始时间) / 累积文本.length
80
+
81
+ console.log(`总返回时间: ${(请求结束时间 - 请求开始时间).toFixed(2)}ms`)
82
+ console.log(`第一个字返回时间: ${第一个字时间}ms`)
83
+ console.log(`平均每个字返回时间: ${平均字返回时间.toFixed(2)}ms`)
84
+ console.log(`返回的内容: %O`, 累积文本)
85
+ })
@@ -0,0 +1,105 @@
1
+ import { expect, test } from "vitest"
2
+
3
+ import {
4
+ applyDeltaToNumberContent,
5
+ applyDeltaToTextContent,
6
+ } from "#Source/aio/index.ts"
7
+
8
+ test("applyDeltaToTextContent appends, conditionally removes, resets and keeps prior snapshots immutable", () => {
9
+ const initial = {
10
+ deltaList: [],
11
+ total: "",
12
+ }
13
+
14
+ const appended = applyDeltaToTextContent(initial, {
15
+ type: "append",
16
+ text: "mobius",
17
+ })
18
+ const removed = applyDeltaToTextContent(appended, {
19
+ type: "remove",
20
+ text: "ius",
21
+ })
22
+ const unchangedRemove = applyDeltaToTextContent(removed, {
23
+ type: "remove",
24
+ text: "xyz",
25
+ })
26
+ const reset = applyDeltaToTextContent(unchangedRemove, {
27
+ type: "reset",
28
+ })
29
+
30
+ expect(initial).toEqual({
31
+ deltaList: [],
32
+ total: "",
33
+ })
34
+ expect(appended).toEqual({
35
+ deltaList: [{ type: "append", text: "mobius" }],
36
+ total: "mobius",
37
+ })
38
+ expect(removed).toEqual({
39
+ deltaList: [
40
+ { type: "append", text: "mobius" },
41
+ { type: "remove", text: "ius" },
42
+ ],
43
+ total: "mob",
44
+ })
45
+ expect(unchangedRemove).toEqual({
46
+ deltaList: [
47
+ { type: "append", text: "mobius" },
48
+ { type: "remove", text: "ius" },
49
+ { type: "remove", text: "xyz" },
50
+ ],
51
+ total: "mob",
52
+ })
53
+ expect(reset).toEqual({
54
+ deltaList: [
55
+ { type: "append", text: "mobius" },
56
+ { type: "remove", text: "ius" },
57
+ { type: "remove", text: "xyz" },
58
+ { type: "reset" },
59
+ ],
60
+ total: "",
61
+ })
62
+ })
63
+
64
+ test("applyDeltaToNumberContent accumulates, subtracts, resets and keeps prior snapshots immutable", () => {
65
+ const initial = {
66
+ deltaList: [],
67
+ total: 0,
68
+ }
69
+
70
+ const appended = applyDeltaToNumberContent(initial, {
71
+ type: "append",
72
+ value: 10,
73
+ })
74
+ const removed = applyDeltaToNumberContent(appended, {
75
+ type: "remove",
76
+ value: 3,
77
+ })
78
+ const reset = applyDeltaToNumberContent(removed, {
79
+ type: "reset",
80
+ })
81
+
82
+ expect(initial).toEqual({
83
+ deltaList: [],
84
+ total: 0,
85
+ })
86
+ expect(appended).toEqual({
87
+ deltaList: [{ type: "append", value: 10 }],
88
+ total: 10,
89
+ })
90
+ expect(removed).toEqual({
91
+ deltaList: [
92
+ { type: "append", value: 10 },
93
+ { type: "remove", value: 3 },
94
+ ],
95
+ total: 7,
96
+ })
97
+ expect(reset).toEqual({
98
+ deltaList: [
99
+ { type: "append", value: 10 },
100
+ { type: "remove", value: 3 },
101
+ { type: "reset" },
102
+ ],
103
+ total: 0,
104
+ })
105
+ })
@@ -0,0 +1,147 @@
1
+ import { expect, test, vi } from "vitest"
2
+
3
+ import type { StandardSchemaV1 } from "@standard-schema/spec"
4
+ import { Logger } from "#Source/log/index.ts"
5
+ import {
6
+ JsonModeResponseParser,
7
+ extractJsonBlock,
8
+ } from "#Source/aio/index.ts"
9
+
10
+ interface TestJsonOutput {
11
+ value: number
12
+ label?: string | undefined
13
+ }
14
+
15
+ const createSyncSchema = (
16
+ options: { validateCount?: { current: number } | undefined } = {}
17
+ ): StandardSchemaV1<unknown, TestJsonOutput> => {
18
+ const validateCount = options.validateCount
19
+
20
+ return {
21
+ "~standard": {
22
+ version: 1 as const,
23
+ vendor: "mobius-aio-json-sync-spec",
24
+ validate: (value: unknown): StandardSchemaV1.Result<TestJsonOutput> => {
25
+ if (validateCount !== undefined) {
26
+ validateCount.current = validateCount.current + 1
27
+ }
28
+
29
+ if (typeof value !== "object" || value === null) {
30
+ return {
31
+ issues: [{ message: "value must be an object" }],
32
+ }
33
+ }
34
+
35
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion
36
+ const record = value as Record<string, unknown>
37
+ if (typeof record["value"] !== "number") {
38
+ return {
39
+ issues: [{ message: "value must be a number" }],
40
+ }
41
+ }
42
+
43
+ const output: TestJsonOutput = {
44
+ value: record["value"],
45
+ }
46
+
47
+ if (typeof record["label"] === "string") {
48
+ output.label = record["label"]
49
+ }
50
+
51
+ return {
52
+ value: output,
53
+ }
54
+ },
55
+ },
56
+ }
57
+ }
58
+
59
+ const createAsyncSchema = (): StandardSchemaV1<unknown, TestJsonOutput> => {
60
+ return {
61
+ "~standard": {
62
+ version: 1 as const,
63
+ vendor: "mobius-aio-json-async-spec",
64
+ validate: async (_value: unknown): Promise<StandardSchemaV1.Result<TestJsonOutput>> => {
65
+ await Promise.resolve()
66
+
67
+ return {
68
+ value: {
69
+ value: 1,
70
+ },
71
+ }
72
+ },
73
+ },
74
+ }
75
+ }
76
+
77
+ test("extractJsonBlock returns the first fenced json block and throws when none exists", () => {
78
+ const response = [
79
+ "before",
80
+ "```json",
81
+ "{\"value\":1}",
82
+ "```",
83
+ "```json",
84
+ "{\"value\":2}",
85
+ "```",
86
+ ].join("\n")
87
+
88
+ expect(extractJsonBlock(response)).toBe(["```json", "{\"value\":1}", "```"].join("\n"))
89
+ expect(() => extractJsonBlock("plain text only")).toThrow("Failed to extract json block from response")
90
+ })
91
+
92
+ test("JsonModeResponseParser.extractJsonContent strips fences, repairs json-like content and falls back to raw text", () => {
93
+ const parser = new JsonModeResponseParser({
94
+ outputSchema: createSyncSchema(),
95
+ })
96
+
97
+ const repairedFromFence = parser.extractJsonContent(["header", "```json", "{value:1,}", "```"].join("\n"))
98
+ const repairedFromRawText = parser.extractJsonContent("{label:'mobius',value:2,}")
99
+
100
+ expect(repairedFromFence).toBe('\n{"value":1}\n')
101
+ expect(repairedFromRawText).toBe('{"label":"mobius","value":2}')
102
+ })
103
+
104
+ test("JsonModeResponseParser.parse validates sync output, caches by source text and throws for invalid or async schemas", () => {
105
+ const validateCount = { current: 0 }
106
+ const parser = new JsonModeResponseParser({
107
+ outputSchema: createSyncSchema({ validateCount }),
108
+ })
109
+
110
+ const first = parser.parse('{"value":1,"label":"ok"}')
111
+ const second = parser.parse('{"value":1,"label":"ok"}')
112
+
113
+ expect(first).toEqual({ value: 1, label: "ok" })
114
+ expect(second).toBe(first)
115
+ expect(validateCount.current).toBe(1)
116
+
117
+ const invalidParser = new JsonModeResponseParser({
118
+ outputSchema: createSyncSchema(),
119
+ })
120
+ expect(() => invalidParser.parse('{"label":"missing-value"}')).toThrow("Variable validation failed")
121
+
122
+ const asyncParser = new JsonModeResponseParser({
123
+ outputSchema: createAsyncSchema(),
124
+ })
125
+ expect(() => asyncParser.parse('{"value":1}')).toThrow("Validation result is a promise")
126
+ })
127
+
128
+ test("JsonModeResponseParser.check returns false and logs the failure context when parsing fails", () => {
129
+ const logger = new Logger({
130
+ name: "AioJsonTest",
131
+ configs: {
132
+ enabled: false,
133
+ },
134
+ })
135
+ const logSpy = vi.spyOn(logger, "log")
136
+ const parser = new JsonModeResponseParser({
137
+ logger,
138
+ outputSchema: createSyncSchema(),
139
+ })
140
+
141
+ expect(parser.check('{"value":3}')).toBe(true)
142
+ expect(parser.check('{"label":"missing-value"}')).toBe(false)
143
+
144
+ expect(logSpy).toHaveBeenCalledTimes(2)
145
+ expect(logSpy.mock.calls[0]?.[0]).toBe("check error:")
146
+ expect(logSpy.mock.calls[1]).toEqual(["error response:", '{"label":"missing-value"}'])
147
+ })
@@ -0,0 +1,111 @@
1
+ import { expect, test } from "vitest"
2
+
3
+ import {
4
+ Prompt,
5
+ emptyLine,
6
+ orderedListItem,
7
+ scopeContent,
8
+ text,
9
+ unorderedListItem,
10
+ } from "#Source/aio/index.ts"
11
+
12
+ test("text creates a plain text prompt block", () => {
13
+ expect(text("hello")).toEqual({
14
+ type: "text",
15
+ content: "hello",
16
+ })
17
+ })
18
+
19
+ test("emptyLine creates an empty-line prompt block", () => {
20
+ expect(emptyLine()).toEqual({
21
+ type: "empty-line",
22
+ })
23
+ })
24
+
25
+ test("scopeContent wraps content with triple-quote boundaries", () => {
26
+ expect(scopeContent("context")).toEqual({
27
+ type: "scope-content",
28
+ content: '"""\ncontext\n"""',
29
+ })
30
+ })
31
+
32
+ test("orderedListItem creates an ordered-list prompt block", () => {
33
+ expect(orderedListItem("first")).toEqual({
34
+ type: "ordered-list-item",
35
+ content: "first",
36
+ })
37
+ })
38
+
39
+ test("unorderedListItem creates an unordered-list prompt block", () => {
40
+ expect(unorderedListItem("first")).toEqual({
41
+ type: "unordered-list-item",
42
+ content: "first",
43
+ })
44
+ })
45
+
46
+ test("Prompt.addBlock appends a block produced by helpers and returns the same instance", async () => {
47
+ const prompt = new Prompt({})
48
+
49
+ expect(prompt.addBlock(helpers => helpers.text("from-helper"))).toBe(prompt)
50
+ await expect(prompt.getPromptInString()).resolves.toBe("from-helper")
51
+ })
52
+
53
+ test("Prompt.addText appends a text block", async () => {
54
+ const prompt = new Prompt({})
55
+
56
+ expect(prompt.addText("alpha")).toBe(prompt)
57
+ await expect(prompt.getPromptInString()).resolves.toBe("alpha")
58
+ })
59
+
60
+ test("Prompt.addEmptyLine appends an empty line block", async () => {
61
+ const prompt = new Prompt({})
62
+
63
+ expect(prompt.addEmptyLine()).toBe(prompt)
64
+ await expect(prompt.getPromptInString()).resolves.toBe("\r\n")
65
+ })
66
+
67
+ test("Prompt.addScopeContent appends a scoped content block", async () => {
68
+ const prompt = new Prompt({})
69
+
70
+ expect(prompt.addScopeContent("body")).toBe(prompt)
71
+ await expect(prompt.getPromptInString()).resolves.toBe('"""\nbody\n"""')
72
+ })
73
+
74
+ test("Prompt.addOrderedListItem appends an ordered list block", async () => {
75
+ const prompt = new Prompt({})
76
+
77
+ expect(prompt.addOrderedListItem("step")).toBe(prompt)
78
+ await expect(prompt.getPromptInString()).resolves.toBe("1. step")
79
+ })
80
+
81
+ test("Prompt.addUnorderedListItem appends an unordered list block", async () => {
82
+ const prompt = new Prompt({})
83
+
84
+ expect(prompt.addUnorderedListItem("item")).toBe(prompt)
85
+ await expect(prompt.getPromptInString()).resolves.toBe("- item")
86
+ })
87
+
88
+ test("Prompt.getPromptInString renders prompt blocks with list numbering and resets between block groups", async () => {
89
+ const prompt = new Prompt({})
90
+
91
+ prompt
92
+ .addText("Intro")
93
+ .addOrderedListItem("First")
94
+ .addOrderedListItem("Second")
95
+ .addText("Break")
96
+ .addOrderedListItem("Reset")
97
+ .addUnorderedListItem("One")
98
+ .addUnorderedListItem("Two")
99
+ .addScopeContent("body")
100
+
101
+ await expect(prompt.getPromptInString()).resolves.toBe([
102
+ "Intro",
103
+ "1. First",
104
+ "2. Second",
105
+ "Break",
106
+ "1. Reset",
107
+ "- One",
108
+ "- Two",
109
+ '"""\nbody\n"""',
110
+ ].join("\r\n"))
111
+ })
@@ -192,7 +192,7 @@ test("arrayAny aliases arraySome", () => {
192
192
 
193
193
  test("arrayForEach applies the callback", () => {
194
194
  const target: number[] = []
195
- arrayForEach((item) => target.push(item * 2), [1, 2, 3])
195
+ arrayForEach((item) => { target.push(item * 2) }, [1, 2, 3])
196
196
  expect(target).toEqual([2, 4, 6])
197
197
  })
198
198
 
@@ -2,7 +2,8 @@ import { expect, test } from "vitest"
2
2
 
3
3
  import {
4
4
  errorIsNetworkError,
5
- errorStringifyException,
5
+ errorStringify,
6
+ toError,
6
7
  } from "#Source/basic/index.ts"
7
8
 
8
9
  test("errorIsNetworkError returns expected values", () => {
@@ -26,7 +27,18 @@ test("errorIsNetworkError returns expected values", () => {
26
27
  expect(errorIsNetworkError(safariWithStack)).toBe(false)
27
28
  })
28
29
 
29
- test("errorStringifyException returns readable output", () => {
30
- expect(errorStringifyException(new Error("boom"))).toBe("Error: boom")
31
- expect(errorStringifyException(123)).toBe("123")
30
+ test("errorStringify returns readable output", () => {
31
+ expect(errorStringify(new Error("boom"))).toBe("Error: boom")
32
+ expect(errorStringify(123)).toBe("123")
33
+ })
34
+
35
+ test("toError returns expected values", () => {
36
+ const error = new Error("boom")
37
+
38
+ expect(toError(error)).toBe(error)
39
+
40
+ const wrappedError = toError(123)
41
+
42
+ expect(wrappedError).toBeInstanceOf(Error)
43
+ expect(wrappedError.message).toBe("123")
32
44
  })
@@ -0,0 +1,74 @@
1
+ import { expect, test, vi } from "vitest"
2
+
3
+ import {
4
+ scheduleMacroTask,
5
+ scheduleMacroTaskSimple,
6
+ scheduleMicroTask,
7
+ scheduleMicroTaskSimple,
8
+ } from "#Source/basic/index.ts"
9
+
10
+ test("scheduleMicroTaskSimple schedules a task in the microtask queue", async () => {
11
+ const values: string[] = []
12
+
13
+ scheduleMicroTaskSimple(() => {
14
+ values.push("micro")
15
+ })
16
+
17
+ expect(values).toEqual([])
18
+
19
+ await Promise.resolve()
20
+
21
+ expect(values).toEqual(["micro"])
22
+ })
23
+
24
+ test("scheduleMacroTaskSimple schedules a task in the macrotask queue", async () => {
25
+ vi.useFakeTimers()
26
+ const values: string[] = []
27
+
28
+ scheduleMacroTaskSimple(() => {
29
+ values.push("macro")
30
+ })
31
+
32
+ expect(values).toEqual([])
33
+
34
+ await vi.runAllTimersAsync()
35
+
36
+ expect(values).toEqual(["macro"])
37
+ vi.useRealTimers()
38
+ })
39
+
40
+ test("scheduleMicroTask schedules async-capable tasks in the microtask queue", async () => {
41
+ const values: string[] = []
42
+
43
+ scheduleMicroTask({
44
+ task: () => {
45
+ values.push("micro")
46
+ },
47
+ })
48
+
49
+ expect(values).toEqual([])
50
+
51
+ await Promise.resolve()
52
+ await Promise.resolve()
53
+
54
+ expect(values).toEqual(["micro"])
55
+ })
56
+
57
+ test("scheduleMacroTask schedules async-capable tasks with timeout", async () => {
58
+ vi.useFakeTimers()
59
+ const values: string[] = []
60
+
61
+ scheduleMacroTask({
62
+ timeout: 25,
63
+ task: () => {
64
+ values.push("macro")
65
+ },
66
+ })
67
+
68
+ await vi.advanceTimersByTimeAsync(24)
69
+ expect(values).toEqual([])
70
+
71
+ await vi.advanceTimersByTimeAsync(1)
72
+ expect(values).toEqual(["macro"])
73
+ vi.useRealTimers()
74
+ })