@planet-matrix/mobius-model 0.6.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/CHANGELOG.md +50 -0
- package/oxlint.config.ts +1 -2
- package/package.json +29 -17
- package/scripts/build.ts +2 -52
- package/src/ai/README.md +1 -0
- package/src/ai/ai.ts +107 -0
- package/src/ai/chat-completion-ai/aihubmix-chat-completion.ts +78 -0
- package/src/ai/chat-completion-ai/chat-completion-ai.ts +270 -0
- package/src/ai/chat-completion-ai/chat-completion.ts +189 -0
- package/src/ai/chat-completion-ai/index.ts +7 -0
- package/src/ai/chat-completion-ai/lingyiwanwu-chat-completion.ts +78 -0
- package/src/ai/chat-completion-ai/ohmygpt-chat-completion.ts +78 -0
- package/src/ai/chat-completion-ai/openai-next-chat-completion.ts +78 -0
- package/src/ai/embedding-ai/embedding-ai.ts +63 -0
- package/src/ai/embedding-ai/embedding.ts +50 -0
- package/src/ai/embedding-ai/index.ts +4 -0
- package/src/ai/embedding-ai/openai-next-embedding.ts +23 -0
- package/src/ai/index.ts +4 -0
- package/src/aio/README.md +100 -0
- package/src/aio/content.ts +141 -0
- package/src/aio/index.ts +3 -0
- package/src/aio/json.ts +127 -0
- package/src/aio/prompt.ts +246 -0
- package/src/basic/README.md +20 -15
- package/src/basic/error.ts +19 -5
- package/src/basic/function.ts +2 -2
- package/src/basic/index.ts +1 -0
- package/src/basic/promise.ts +141 -71
- package/src/basic/schedule.ts +111 -0
- package/src/basic/stream.ts +135 -25
- package/src/credential/README.md +107 -0
- package/src/credential/api-key.ts +158 -0
- package/src/credential/bearer.ts +73 -0
- package/src/credential/index.ts +4 -0
- package/src/credential/json-web-token.ts +96 -0
- package/src/credential/password.ts +170 -0
- package/src/cron/README.md +86 -0
- package/src/cron/cron.ts +87 -0
- package/src/cron/index.ts +1 -0
- package/src/drizzle/README.md +1 -0
- package/src/drizzle/drizzle.ts +1 -0
- package/src/drizzle/helper.ts +47 -0
- package/src/drizzle/index.ts +5 -0
- package/src/drizzle/infer.ts +52 -0
- package/src/drizzle/kysely.ts +8 -0
- package/src/drizzle/pagination.ts +198 -0
- package/src/email/README.md +1 -0
- package/src/email/index.ts +1 -0
- package/src/email/resend.ts +25 -0
- package/src/event/class-event-proxy.ts +5 -6
- package/src/event/common.ts +13 -3
- package/src/event/event-manager.ts +3 -3
- package/src/event/instance-event-proxy.ts +5 -6
- package/src/event/internal.ts +4 -4
- package/src/exception/README.md +28 -19
- package/src/exception/error/error.ts +123 -0
- package/src/exception/error/index.ts +2 -0
- package/src/exception/error/match.ts +38 -0
- package/src/exception/error/must-fix.ts +17 -0
- package/src/exception/index.ts +2 -0
- package/src/file-system/find.ts +53 -0
- package/src/file-system/index.ts +2 -0
- package/src/file-system/path.ts +76 -0
- package/src/file-system/resolve.ts +22 -0
- package/src/form/README.md +25 -0
- package/src/form/index.ts +1 -0
- package/src/form/inputor-controller/base.ts +861 -0
- package/src/form/inputor-controller/boolean.ts +39 -0
- package/src/form/inputor-controller/file.ts +39 -0
- package/src/form/inputor-controller/form.ts +179 -0
- package/src/form/inputor-controller/helper.ts +117 -0
- package/src/form/inputor-controller/index.ts +17 -0
- package/src/form/inputor-controller/multi-select.ts +99 -0
- package/src/form/inputor-controller/number.ts +116 -0
- package/src/form/inputor-controller/select.ts +109 -0
- package/src/form/inputor-controller/text.ts +82 -0
- package/src/http/READMD.md +1 -0
- package/src/http/api/api-core.ts +84 -0
- package/src/http/api/api-handler.ts +79 -0
- package/src/http/api/api-host.ts +47 -0
- package/src/http/api/api-result.ts +56 -0
- package/src/http/api/api-schema.ts +154 -0
- package/src/http/api/api-server.ts +130 -0
- package/src/http/api/api-test.ts +142 -0
- package/src/http/api/api-type.ts +34 -0
- package/src/http/api/api.ts +81 -0
- package/src/http/api/index.ts +11 -0
- package/src/http/api-adapter/api-core-node-http.ts +260 -0
- package/src/http/api-adapter/api-host-node-http.ts +156 -0
- package/src/http/api-adapter/api-result-arktype.ts +294 -0
- package/src/http/api-adapter/api-result-zod.ts +286 -0
- package/src/http/api-adapter/index.ts +5 -0
- package/src/http/bin/gen-api-list/gen-api-list.ts +126 -0
- package/src/http/bin/gen-api-list/index.ts +1 -0
- package/src/http/bin/gen-api-test/gen-api-test.ts +136 -0
- package/src/http/bin/gen-api-test/index.ts +1 -0
- package/src/http/bin/gen-api-type/calc-code.ts +25 -0
- package/src/http/bin/gen-api-type/gen-api-type.ts +127 -0
- package/src/http/bin/gen-api-type/index.ts +2 -0
- package/src/http/bin/index.ts +2 -0
- package/src/http/index.ts +3 -0
- package/src/huawei/README.md +1 -0
- package/src/huawei/index.ts +2 -0
- package/src/huawei/moderation/index.ts +1 -0
- package/src/huawei/moderation/moderation.ts +355 -0
- package/src/huawei/obs/esdk-obs-nodejs.d.ts +87 -0
- package/src/huawei/obs/index.ts +1 -0
- package/src/huawei/obs/obs.ts +42 -0
- package/src/index.ts +21 -2
- package/src/json/README.md +92 -0
- package/src/json/index.ts +1 -0
- package/src/json/repair.ts +18 -0
- package/src/log/logger.ts +15 -4
- package/src/openai/README.md +1 -0
- package/src/openai/index.ts +1 -0
- package/src/openai/openai.ts +509 -0
- package/src/orchestration/README.md +9 -7
- package/src/orchestration/dispatching/dispatcher.ts +83 -0
- package/src/orchestration/dispatching/index.ts +2 -0
- package/src/orchestration/dispatching/selector/base-selector.ts +39 -0
- package/src/orchestration/dispatching/selector/down-count-selector.ts +119 -0
- package/src/orchestration/dispatching/selector/index.ts +2 -0
- package/src/orchestration/index.ts +2 -0
- package/src/orchestration/scheduling/index.ts +2 -0
- package/src/orchestration/scheduling/scheduler.ts +103 -0
- package/src/orchestration/scheduling/task.ts +32 -0
- package/src/random/README.md +8 -7
- package/src/random/base.ts +66 -0
- package/src/random/index.ts +5 -1
- package/src/random/random-boolean.ts +40 -0
- package/src/random/random-integer.ts +60 -0
- package/src/random/random-number.ts +72 -0
- package/src/random/random-string.ts +66 -0
- package/src/request/README.md +108 -0
- package/src/request/fetch/base.ts +108 -0
- package/src/request/fetch/browser.ts +280 -0
- package/src/request/fetch/general.ts +20 -0
- package/src/request/fetch/index.ts +4 -0
- package/src/request/fetch/nodejs.ts +280 -0
- package/src/request/index.ts +2 -0
- package/src/request/request/base.ts +246 -0
- package/src/request/request/general.ts +63 -0
- package/src/request/request/index.ts +3 -0
- package/src/request/request/resource.ts +68 -0
- package/src/result/README.md +4 -0
- package/src/result/controller.ts +58 -0
- package/src/result/either.ts +363 -0
- package/src/result/generator.ts +168 -0
- package/src/result/index.ts +3 -0
- package/src/route/README.md +105 -0
- package/src/route/adapter/browser.ts +122 -0
- package/src/route/adapter/driver.ts +56 -0
- package/src/route/adapter/index.ts +2 -0
- package/src/route/index.ts +3 -0
- package/src/route/router/index.ts +2 -0
- package/src/route/router/route.ts +630 -0
- package/src/route/router/router.ts +1641 -0
- package/src/route/uri/hash.ts +307 -0
- package/src/route/uri/index.ts +7 -0
- package/src/route/uri/pathname.ts +376 -0
- package/src/route/uri/search.ts +412 -0
- package/src/service/README.md +1 -0
- package/src/service/index.ts +1 -0
- package/src/service/service.ts +110 -0
- package/src/socket/README.md +105 -0
- package/src/socket/client/index.ts +2 -0
- package/src/socket/client/socket-unit.ts +658 -0
- package/src/socket/client/socket.ts +203 -0
- package/src/socket/common/index.ts +2 -0
- package/src/socket/common/socket-unit-common.ts +23 -0
- package/src/socket/common/socket-unit-heartbeat.ts +427 -0
- package/src/socket/index.ts +3 -0
- package/src/socket/server/index.ts +3 -0
- package/src/socket/server/server.ts +183 -0
- package/src/socket/server/socket-unit.ts +448 -0
- package/src/socket/server/socket.ts +264 -0
- package/src/storage/table.ts +3 -3
- package/src/timer/expiration/expiration-manager.ts +3 -3
- package/src/timer/expiration/remaining-manager.ts +3 -3
- package/src/tube/README.md +99 -0
- package/src/tube/helper.ts +137 -0
- package/src/tube/index.ts +2 -0
- package/src/tube/tube.ts +880 -0
- package/src/weixin/README.md +1 -0
- package/src/weixin/index.ts +2 -0
- package/src/weixin/official-account/authorization.ts +157 -0
- package/src/weixin/official-account/index.ts +2 -0
- package/src/weixin/official-account/js-api.ts +132 -0
- package/src/weixin/open/index.ts +1 -0
- package/src/weixin/open/oauth2.ts +131 -0
- package/tests/unit/ai/ai.spec.ts +85 -0
- package/tests/unit/aio/content.spec.ts +105 -0
- package/tests/unit/aio/json.spec.ts +146 -0
- package/tests/unit/aio/prompt.spec.ts +111 -0
- package/tests/unit/basic/error.spec.ts +16 -4
- package/tests/unit/basic/promise.spec.ts +158 -50
- package/tests/unit/basic/schedule.spec.ts +74 -0
- package/tests/unit/basic/stream.spec.ts +90 -37
- package/tests/unit/credential/api-key.spec.ts +36 -0
- package/tests/unit/credential/bearer.spec.ts +23 -0
- package/tests/unit/credential/json-web-token.spec.ts +23 -0
- package/tests/unit/credential/password.spec.ts +40 -0
- package/tests/unit/cron/cron.spec.ts +84 -0
- package/tests/unit/event/class-event-proxy.spec.ts +3 -3
- package/tests/unit/event/event-manager.spec.ts +3 -3
- package/tests/unit/event/instance-event-proxy.spec.ts +3 -3
- package/tests/unit/exception/error/error.spec.ts +83 -0
- package/tests/unit/exception/error/match.spec.ts +81 -0
- package/tests/unit/form/inputor-controller/base.spec.ts +458 -0
- package/tests/unit/form/inputor-controller/boolean.spec.ts +30 -0
- package/tests/unit/form/inputor-controller/file.spec.ts +27 -0
- package/tests/unit/form/inputor-controller/form.spec.ts +120 -0
- package/tests/unit/form/inputor-controller/helper.spec.ts +67 -0
- package/tests/unit/form/inputor-controller/multi-select.spec.ts +34 -0
- package/tests/unit/form/inputor-controller/number.spec.ts +36 -0
- package/tests/unit/form/inputor-controller/select.spec.ts +49 -0
- package/tests/unit/form/inputor-controller/text.spec.ts +34 -0
- package/tests/unit/http/api/api-core-host.spec.ts +207 -0
- package/tests/unit/http/api/api-schema.spec.ts +120 -0
- package/tests/unit/http/api/api-server.spec.ts +363 -0
- package/tests/unit/http/api/api-test.spec.ts +117 -0
- package/tests/unit/http/api/api.spec.ts +121 -0
- package/tests/unit/http/api-adapter/node-http.spec.ts +187 -0
- package/tests/unit/identifier/uuid.spec.ts +0 -1
- package/tests/unit/json/repair.spec.ts +11 -0
- package/tests/unit/log/logger.spec.ts +19 -4
- package/tests/unit/openai/openai.spec.ts +64 -0
- package/tests/unit/orchestration/dispatching/dispatcher.spec.ts +41 -0
- package/tests/unit/orchestration/dispatching/selector/down-count-selector.spec.ts +81 -0
- package/tests/unit/orchestration/scheduling/scheduler.spec.ts +103 -0
- package/tests/unit/random/base.spec.ts +58 -0
- package/tests/unit/random/random-boolean.spec.ts +25 -0
- package/tests/unit/random/random-integer.spec.ts +32 -0
- package/tests/unit/random/random-number.spec.ts +33 -0
- package/tests/unit/random/random-string.spec.ts +22 -0
- package/tests/unit/request/fetch/browser.spec.ts +222 -0
- package/tests/unit/request/fetch/general.spec.ts +43 -0
- package/tests/unit/request/fetch/nodejs.spec.ts +225 -0
- package/tests/unit/request/request/base.spec.ts +382 -0
- package/tests/unit/request/request/general.spec.ts +160 -0
- package/tests/unit/result/controller.spec.ts +82 -0
- package/tests/unit/result/either.spec.ts +377 -0
- package/tests/unit/result/generator.spec.ts +273 -0
- package/tests/unit/route/router/route.spec.ts +430 -0
- package/tests/unit/route/router/router.spec.ts +407 -0
- package/tests/unit/route/uri/hash.spec.ts +72 -0
- package/tests/unit/route/uri/pathname.spec.ts +146 -0
- package/tests/unit/route/uri/search.spec.ts +107 -0
- package/tests/unit/socket/client.spec.ts +208 -0
- package/tests/unit/socket/server.spec.ts +133 -0
- package/tests/unit/socket/socket-unit-heartbeat.spec.ts +214 -0
- package/tests/unit/tube/helper.spec.ts +139 -0
- package/tests/unit/tube/tube.spec.ts +501 -0
- package/vite.config.ts +2 -1
- package/dist/index.js +0 -50
- package/dist/index.js.map +0 -209
- package/src/random/string.ts +0 -35
- package/tests/unit/random/string.spec.ts +0 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
# @planet-matrix/mobius-model
|
|
2
2
|
|
|
3
|
+
## 0.10.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- d7c33d7: Add `dist` to `.npmignore`.
|
|
8
|
+
|
|
9
|
+
## 0.10.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 6f99535: Add service model.
|
|
14
|
+
- 9520154: Add tagged error capabilities to exception model.
|
|
15
|
+
|
|
16
|
+
## 0.9.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- f5cd790: Add weixin model.
|
|
21
|
+
- fae630f: Add ai model.
|
|
22
|
+
- 6e132e6: Add openai model.
|
|
23
|
+
|
|
24
|
+
## 0.8.0
|
|
25
|
+
|
|
26
|
+
### Minor Changes
|
|
27
|
+
|
|
28
|
+
- 3c736c0: Add http model.
|
|
29
|
+
- 5036bdb: Add drizzle model.
|
|
30
|
+
- fefbfef: 优化 basic steam,新增 basic schedule。
|
|
31
|
+
- 5a9fb9d: Add cron model.
|
|
32
|
+
- f101d98: Add http model.
|
|
33
|
+
- de21d1f: Add email model.
|
|
34
|
+
- 84e76bc: Enhance logger functionality with default names for various components.
|
|
35
|
+
- 8146954: Implement Scheduler and Task classes with logging functionality and tests.
|
|
36
|
+
- faa0f2d: Add huawei model, include moderation and obs functionalities.
|
|
37
|
+
- 8421836: Add tube model.
|
|
38
|
+
|
|
39
|
+
## 0.7.0
|
|
40
|
+
|
|
41
|
+
### Minor Changes
|
|
42
|
+
|
|
43
|
+
- cbe190c: Add request model.
|
|
44
|
+
- 730cb8b: Add socket model.
|
|
45
|
+
- 7511df7: Add result model.
|
|
46
|
+
- a97b489: Add form model.
|
|
47
|
+
- 44cbf55: Add aio model.
|
|
48
|
+
- 8ec2d59: Add route model.
|
|
49
|
+
- 73cb3ea: Implement dispatcher and down-count selector for orchestration model.
|
|
50
|
+
- 5452bbe: Add json model.
|
|
51
|
+
- c1afa6e: Add credential model.
|
|
52
|
+
|
|
3
53
|
## 0.6.0
|
|
4
54
|
|
|
5
55
|
### Minor Changes
|
package/oxlint.config.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planet-matrix/mobius-model",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Mobius model.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mobius",
|
|
@@ -32,19 +32,19 @@
|
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
"imports": {
|
|
35
|
-
"#Project/*": {
|
|
36
|
-
"import": {
|
|
37
|
-
"@planet-matrix/mobius-mono": "./*",
|
|
38
|
-
"bun": "./*",
|
|
39
|
-
"default": "./*"
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
35
|
"#Source/*": {
|
|
43
36
|
"import": {
|
|
44
37
|
"@planet-matrix/mobius-mono": "./src/*",
|
|
45
38
|
"bun": "./src/*",
|
|
46
39
|
"default": "./src/*"
|
|
47
40
|
}
|
|
41
|
+
},
|
|
42
|
+
"#Project/*": {
|
|
43
|
+
"import": {
|
|
44
|
+
"@planet-matrix/mobius-mono": "./*",
|
|
45
|
+
"bun": "./*",
|
|
46
|
+
"default": "./*"
|
|
47
|
+
}
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
"repository": {
|
|
@@ -59,21 +59,33 @@
|
|
|
59
59
|
"prepublishOnly": "bun run build"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
+
"typescript": "^6.0.2",
|
|
62
63
|
"ua-parser-js": "^2.0.9",
|
|
63
64
|
"html-to-image": "^1.11.13",
|
|
65
|
+
"undici": "^7.24.6",
|
|
66
|
+
"ws": "^8.20.0",
|
|
67
|
+
"@types/ws": "^8.18.1",
|
|
64
68
|
"@standard-schema/spec": "^v1.1.0",
|
|
65
69
|
"arktype": "^2.2.0",
|
|
66
|
-
"
|
|
70
|
+
"zod": "^4.3.6",
|
|
71
|
+
"@dotenvx/dotenvx": "^1.59.1",
|
|
72
|
+
"jsonrepair": "^3.13.3",
|
|
73
|
+
"jose": "^6.2.2",
|
|
74
|
+
"croner": "^10.0.1",
|
|
75
|
+
"drizzle-orm": "^0.45.2",
|
|
76
|
+
"resend": "^6.9.4",
|
|
77
|
+
"esdk-obs-nodejs": "^3.26.2",
|
|
78
|
+
"openai": "^6.33.0"
|
|
67
79
|
},
|
|
68
80
|
"devDependencies": {
|
|
69
|
-
"@planet-matrix/mobius-mono": "0.
|
|
70
|
-
"@types/bun": "^1.3.
|
|
71
|
-
"
|
|
72
|
-
"oxlint
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"vite": "^8.0.
|
|
76
|
-
"
|
|
81
|
+
"@planet-matrix/mobius-mono": "0.10.1",
|
|
82
|
+
"@types/bun": "^1.3.11",
|
|
83
|
+
"@typescript/native-preview": "^7.0.0-dev.20260329.1",
|
|
84
|
+
"oxlint": "^1.57.0",
|
|
85
|
+
"oxlint-tsgolint": "^0.18.1",
|
|
86
|
+
"vitest": "^4.1.2",
|
|
87
|
+
"vite": "^8.0.3",
|
|
88
|
+
"drizzle-kit": "^0.31.10"
|
|
77
89
|
},
|
|
78
90
|
"peerDependencies": {},
|
|
79
91
|
"peerDependenciesMeta": {},
|
package/scripts/build.ts
CHANGED
|
@@ -1,53 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Build } from "@planet-matrix/mobius-mono"
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
console.log("Cleaning and preparing ./dist directory...")
|
|
5
|
-
await $`rm -rf dist`
|
|
6
|
-
|
|
7
|
-
// console.log("Building TypeScript declarations...")
|
|
8
|
-
// await $`bun run tsgo --noEmit false`
|
|
9
|
-
|
|
10
|
-
console.log("Building the library with Bun...")
|
|
11
|
-
const builtOutput = await build({
|
|
12
|
-
banner: "// Enjoy using Example Library!",
|
|
13
|
-
bytecode: false,
|
|
14
|
-
conditions: [],
|
|
15
|
-
define: {},
|
|
16
|
-
drop: [],
|
|
17
|
-
emitDCEAnnotations: false,
|
|
18
|
-
entrypoints: ["./src/index.ts"],
|
|
19
|
-
env: "PUBLIC_*",
|
|
20
|
-
external: [],
|
|
21
|
-
footer: "// Made with ♥ by the Planet Matrix team!",
|
|
22
|
-
format: "esm",
|
|
23
|
-
ignoreDCEAnnotations: false,
|
|
24
|
-
loader: {},
|
|
25
|
-
minify: {
|
|
26
|
-
identifiers: true,
|
|
27
|
-
keepNames: false,
|
|
28
|
-
syntax: true,
|
|
29
|
-
whitespace: true,
|
|
30
|
-
},
|
|
31
|
-
naming: {
|
|
32
|
-
entry: '[dir]/[name].[ext]',
|
|
33
|
-
chunk: '[name]-[hash].[ext]',
|
|
34
|
-
asset: '[name]-[hash].[ext]',
|
|
35
|
-
},
|
|
36
|
-
outdir: "./dist",
|
|
37
|
-
packages: "bundle",
|
|
38
|
-
plugins: [],
|
|
39
|
-
// publicPath: undefined,
|
|
40
|
-
// root: undefined,
|
|
41
|
-
sourcemap: "linked",
|
|
42
|
-
splitting: true,
|
|
43
|
-
target: "bun",
|
|
44
|
-
throw: false,
|
|
45
|
-
tsconfig: "./tsconfig.json",
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
if (builtOutput.success === false) {
|
|
49
|
-
console.error('Build failed:', builtOutput.logs);
|
|
50
|
-
throw new Error('Build process failed.');
|
|
51
|
-
} else {
|
|
52
|
-
console.log("Build completed successfully.");
|
|
53
|
-
}
|
|
3
|
+
await Build.Library.build({})
|
package/src/ai/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Ai
|
package/src/ai/ai.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type * as Openai from "#Source/openai/index.ts"
|
|
2
|
+
import type { LoggerFriendly, LoggerFriendlyOptions } from "#Source/log/index.ts"
|
|
3
|
+
import { Logger } from "#Source/log/index.ts"
|
|
4
|
+
import { randomIntBetween } from "#Source/basic/index.ts"
|
|
5
|
+
|
|
6
|
+
import * as ChatCompletionAi from "./chat-completion-ai/index.ts"
|
|
7
|
+
import * as EmbeddingAi from "./embedding-ai/index.ts"
|
|
8
|
+
|
|
9
|
+
export type ChatCompletionOptions = Openai.OriginalChatCompletionOptions
|
|
10
|
+
export type EmbeddingOptions = Openai.CustomEmbeddingOptions
|
|
11
|
+
|
|
12
|
+
export interface WithAi {
|
|
13
|
+
ai: Ai
|
|
14
|
+
}
|
|
15
|
+
export interface AiOptions extends LoggerFriendlyOptions {
|
|
16
|
+
chatCompletionAiOptions?: ChatCompletionAi.ChatCompletionAi.ChatCompletionAiOptions | undefined
|
|
17
|
+
embeddingAiOptions?: EmbeddingAi.EmbeddingAi.EmbeddingAiOptions | undefined
|
|
18
|
+
/**
|
|
19
|
+
* @deprecated
|
|
20
|
+
*/
|
|
21
|
+
instancePool: Openai.Openai[]
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated
|
|
24
|
+
*/
|
|
25
|
+
indexChangeMode?: "random" | "poll"
|
|
26
|
+
}
|
|
27
|
+
export class Ai implements LoggerFriendly {
|
|
28
|
+
readonly logger: Logger
|
|
29
|
+
|
|
30
|
+
readonly chatCompletionAi: ChatCompletionAi.ChatCompletionAi.ChatCompletionAi
|
|
31
|
+
readonly embeddingAi: EmbeddingAi.EmbeddingAi.EmbeddingAi
|
|
32
|
+
|
|
33
|
+
protected instancePool: Openai.Openai[]
|
|
34
|
+
protected indexChangeMode: "random" | "poll"
|
|
35
|
+
protected index = 0
|
|
36
|
+
|
|
37
|
+
constructor(options: AiOptions) {
|
|
38
|
+
this.logger = Logger.fromOptions(options).setDefaultName("Ai")
|
|
39
|
+
|
|
40
|
+
this.chatCompletionAi = new ChatCompletionAi.ChatCompletionAi.ChatCompletionAi(options.chatCompletionAiOptions ?? {
|
|
41
|
+
chatCompletionInstanceList: [],
|
|
42
|
+
})
|
|
43
|
+
this.embeddingAi = new EmbeddingAi.EmbeddingAi.EmbeddingAi(options.embeddingAiOptions ?? {
|
|
44
|
+
embeddingInstanceList: [],
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
this.instancePool = options.instancePool
|
|
48
|
+
this.indexChangeMode = options.indexChangeMode ?? "random"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
protected changeIndex(): void {
|
|
52
|
+
this.logger.info(`chang instance index, mode: ${this.indexChangeMode}`)
|
|
53
|
+
|
|
54
|
+
switch (this.indexChangeMode) {
|
|
55
|
+
case "random": {
|
|
56
|
+
this.index = randomIntBetween(0, this.instancePool.length - 1)
|
|
57
|
+
break
|
|
58
|
+
}
|
|
59
|
+
case "poll": {
|
|
60
|
+
this.index = this.index + 1
|
|
61
|
+
if (this.index >= this.instancePool.length - 1) {
|
|
62
|
+
this.index = 0
|
|
63
|
+
}
|
|
64
|
+
break
|
|
65
|
+
}
|
|
66
|
+
default: {
|
|
67
|
+
throw new Error(`unknown indexChangeMode: ${String(this.indexChangeMode)}`)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
this.logger.info(`change instance index success: ${this.index}`)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
protected async getInstance(): Promise<Openai.Openai> {
|
|
75
|
+
this.logger.info(`get instance index: ${this.index}`)
|
|
76
|
+
|
|
77
|
+
const instance = this.instancePool[this.index]
|
|
78
|
+
if (instance === undefined) {
|
|
79
|
+
throw new Error("can not find instance")
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
this.logger.info(`get instance success, index: ${this.index}`)
|
|
83
|
+
this.logger.info(`get instance success, baseUrl: ${instance.getBaseUrl()}`)
|
|
84
|
+
return await Promise.resolve(instance)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
protected async changeIndexAndGetInstance(): Promise<Openai.Openai> {
|
|
88
|
+
this.changeIndex()
|
|
89
|
+
return await this.getInstance()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @deprecated
|
|
94
|
+
*/
|
|
95
|
+
async originalChatCompletionNoStreaming(options: ChatCompletionOptions): Promise<Openai.OriginalChatCompletionResult> {
|
|
96
|
+
const instance = await this.changeIndexAndGetInstance()
|
|
97
|
+
return await instance.originalChatCompletionNonStreaming(options)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @deprecated
|
|
102
|
+
*/
|
|
103
|
+
async originalChatCompletionStreaming(options: ChatCompletionOptions): Promise<Openai.Stream<Openai.OriginalChatCompletionChunkResult>> {
|
|
104
|
+
const instance = await this.changeIndexAndGetInstance()
|
|
105
|
+
return await instance.originalChatCompletionStreaming(options)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type * as Openai from "#Source/openai/index.ts"
|
|
2
|
+
|
|
3
|
+
import type { BaseChatCompletionOptions, ChatCompletionOptions, ChatCompletionResult } from "./chat-completion.ts"
|
|
4
|
+
import { BaseChatCompletion } from "./chat-completion.ts"
|
|
5
|
+
|
|
6
|
+
export interface AihubmixChatCompletionOptions extends BaseChatCompletionOptions {
|
|
7
|
+
openai: Openai.Openai
|
|
8
|
+
}
|
|
9
|
+
export class AihubmixChatCompletion extends BaseChatCompletion {
|
|
10
|
+
protected readonly openai: Openai.Openai
|
|
11
|
+
|
|
12
|
+
constructor(options: AihubmixChatCompletionOptions) {
|
|
13
|
+
super(options)
|
|
14
|
+
this.logger.setDefaultName("AihubmixChatCompletion")
|
|
15
|
+
|
|
16
|
+
this.openai = options.openai
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
protected transformOptions(options: ChatCompletionOptions): Openai.CustomChatCompletionOptions {
|
|
20
|
+
const transformedOptions: Openai.CustomChatCompletionOptions = {
|
|
21
|
+
messages: options.messages.map((message) => {
|
|
22
|
+
const { role, content } = message
|
|
23
|
+
if (role === "system") {
|
|
24
|
+
return message
|
|
25
|
+
}
|
|
26
|
+
if (role === "user") {
|
|
27
|
+
if (typeof content === "string") {
|
|
28
|
+
return {
|
|
29
|
+
role,
|
|
30
|
+
content,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (Array.isArray(content)) {
|
|
34
|
+
return {
|
|
35
|
+
role,
|
|
36
|
+
content: content.map((item) => {
|
|
37
|
+
if (item.type === "image_url") {
|
|
38
|
+
return {
|
|
39
|
+
type: item.type,
|
|
40
|
+
image_url: item.imageUrl,
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
return item
|
|
45
|
+
}
|
|
46
|
+
}),
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
throw new Error("Invalid content")
|
|
50
|
+
}
|
|
51
|
+
if (role === "assistant") {
|
|
52
|
+
return message
|
|
53
|
+
}
|
|
54
|
+
throw new Error("Invalid role")
|
|
55
|
+
}),
|
|
56
|
+
model: options.model,
|
|
57
|
+
...(options.frequencyPenalty !== undefined ? { frequency_penalty: options.frequencyPenalty } : {}),
|
|
58
|
+
...(options.logitBias !== undefined ? { logit_bias: options.logitBias } : {}),
|
|
59
|
+
...(options.logprobs !== undefined ? { logprobs: options.logprobs } : {}),
|
|
60
|
+
...(options.maxCompletionTokens !== undefined ? { max_completion_tokens: options.maxCompletionTokens } : {}),
|
|
61
|
+
...(options.maxTokens !== undefined ? { max_tokens: options.maxTokens } : {}),
|
|
62
|
+
...(options.presencePenalty !== undefined ? { presence_penalty: options.presencePenalty } : {}),
|
|
63
|
+
...(options.responseFormat !== undefined ? { response_format: options.responseFormat } : {}),
|
|
64
|
+
...(options.temperature !== undefined ? { temperature: options.temperature } : {}),
|
|
65
|
+
...(options.topLogprobs !== undefined ? { top_logprobs: options.topLogprobs } : {}),
|
|
66
|
+
...(options.topP !== undefined ? { top_p: options.topP } : {}),
|
|
67
|
+
timeout: options.timeoutFirstChunk ?? undefined,
|
|
68
|
+
abortSignal: options.abortSignal,
|
|
69
|
+
}
|
|
70
|
+
return transformedOptions
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async chatCompletion(options: ChatCompletionOptions): Promise<ChatCompletionResult> {
|
|
74
|
+
const transformedOptions = this.transformOptions(options)
|
|
75
|
+
const result = await this.openai.customChatCompletionStreaming(transformedOptions)
|
|
76
|
+
return result
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import type { LoggerFriendly, LoggerFriendlyOptions } from "#Source/log/index.ts"
|
|
2
|
+
import type { AbortManager } from "#Source/abort/index.ts"
|
|
3
|
+
|
|
4
|
+
import { Logger } from "#Source/log/index.ts"
|
|
5
|
+
import { Dispatcher } from "#Source/orchestration/index.ts"
|
|
6
|
+
import { fromWithAbortSignal } from "#Source/abort/index.ts"
|
|
7
|
+
import { controllerFromEitherType, eitherToTuple } from "#Source/result/index.ts"
|
|
8
|
+
import { scheduleMacroTask } from "#Source/basic/index.ts"
|
|
9
|
+
import { connectTube, Tube } from "#Source/tube/index.ts"
|
|
10
|
+
import * as Aio from "#Source/aio/index.ts"
|
|
11
|
+
|
|
12
|
+
import type { BaseChatCompletion, ChatCompletionOptions, ChatCompletionResult, Completion } from "./chat-completion.ts"
|
|
13
|
+
|
|
14
|
+
export interface ChatCompletionAiOptions extends LoggerFriendlyOptions {
|
|
15
|
+
chatCompletionInstanceList: BaseChatCompletion[]
|
|
16
|
+
/**
|
|
17
|
+
* The timeout for the first chunk of data to be received, in milliseconds.
|
|
18
|
+
*
|
|
19
|
+
* @default timeoutPerChunk | 30_000
|
|
20
|
+
*/
|
|
21
|
+
timeoutFirstChunk?: number | undefined
|
|
22
|
+
/**
|
|
23
|
+
* The timeout for each chunk of data to be received, in milliseconds.
|
|
24
|
+
*
|
|
25
|
+
* @default 30_000
|
|
26
|
+
*/
|
|
27
|
+
timeoutPerChunk?: number | undefined
|
|
28
|
+
/**
|
|
29
|
+
* The maximum number of tries for the request.
|
|
30
|
+
*
|
|
31
|
+
* @default 3
|
|
32
|
+
*/
|
|
33
|
+
maxTries?: number | undefined
|
|
34
|
+
}
|
|
35
|
+
interface ResolvedChatCompletionAiOptions {
|
|
36
|
+
chatCompletionInstanceList: BaseChatCompletion[]
|
|
37
|
+
timeoutFirstChunk: number
|
|
38
|
+
timeoutPerChunk: number
|
|
39
|
+
maxTries: number
|
|
40
|
+
}
|
|
41
|
+
export class ChatCompletionAi implements LoggerFriendly {
|
|
42
|
+
protected readonly options: ResolvedChatCompletionAiOptions
|
|
43
|
+
|
|
44
|
+
readonly logger: Logger
|
|
45
|
+
private dispatcher: Dispatcher<BaseChatCompletion>
|
|
46
|
+
|
|
47
|
+
constructor(options: ChatCompletionAiOptions) {
|
|
48
|
+
this.options = {
|
|
49
|
+
chatCompletionInstanceList: options.chatCompletionInstanceList,
|
|
50
|
+
timeoutFirstChunk: options.timeoutFirstChunk ?? options.timeoutPerChunk ?? 30_000,
|
|
51
|
+
timeoutPerChunk: options.timeoutPerChunk ?? 30_000,
|
|
52
|
+
maxTries: options.maxTries ?? 3,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this.logger = Logger.fromOptions(options).setDefaultName("ChatCompletionAi")
|
|
56
|
+
|
|
57
|
+
this.dispatcher = new Dispatcher({
|
|
58
|
+
itemList: this.options.chatCompletionInstanceList,
|
|
59
|
+
logger: this.logger,
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async chatCompletion(
|
|
64
|
+
options: ChatCompletionOptions
|
|
65
|
+
): Promise<ChatCompletionResult> {
|
|
66
|
+
const controller = controllerFromEitherType<ChatCompletionResult>()
|
|
67
|
+
|
|
68
|
+
const completionTube = new Tube<Completion>({
|
|
69
|
+
historyCount: Infinity,
|
|
70
|
+
replayHistory: true
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
scheduleMacroTask({
|
|
74
|
+
task: async () => {
|
|
75
|
+
await this.request(options, completionTube)
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
return await controller.returnRight({
|
|
80
|
+
completionTube,
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private async request(
|
|
85
|
+
options: ChatCompletionOptions,
|
|
86
|
+
targetCompletionTube: Tube<Completion>,
|
|
87
|
+
): Promise<void> {
|
|
88
|
+
const { selector, destroy } = this.dispatcher.getSelector({
|
|
89
|
+
filter: (item) => {
|
|
90
|
+
return item.isSupportModel(options.model) === true
|
|
91
|
+
},
|
|
92
|
+
})
|
|
93
|
+
targetCompletionTube.subscribeEndEvent({
|
|
94
|
+
subscriber: () => {
|
|
95
|
+
destroy()
|
|
96
|
+
},
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
const latestCompletion: Completion = {
|
|
100
|
+
content: {
|
|
101
|
+
deltaList: [],
|
|
102
|
+
total: "",
|
|
103
|
+
},
|
|
104
|
+
token: {
|
|
105
|
+
deltaList: [],
|
|
106
|
+
total: 0,
|
|
107
|
+
},
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const maxTries = options.maxTries ?? this.options.maxTries
|
|
111
|
+
|
|
112
|
+
interface HandleTryErrorOptions {
|
|
113
|
+
tryIndex: number
|
|
114
|
+
abortManager: AbortManager
|
|
115
|
+
}
|
|
116
|
+
const handleTryError = async (options: HandleTryErrorOptions): Promise<void> => {
|
|
117
|
+
const { tryIndex, abortManager } = options
|
|
118
|
+
|
|
119
|
+
this.logger.log(`Handle try error, current failure count: ${tryIndex + 1}, max tries: ${maxTries}`)
|
|
120
|
+
|
|
121
|
+
if (abortManager.isAborted()) {
|
|
122
|
+
this.logger.log("Chat completion aborted by invoker.")
|
|
123
|
+
await targetCompletionTube.pushError(new Error("Chat completion aborted by invoker."))
|
|
124
|
+
abortManager.abort("Chat completion aborted by invoker.")
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
this.logger.log("Chat completion not aborted by invoker.")
|
|
129
|
+
}
|
|
130
|
+
// 清理资源
|
|
131
|
+
abortManager.abort("Failed request")
|
|
132
|
+
|
|
133
|
+
// 重置数据
|
|
134
|
+
latestCompletion.content = Aio.applyDeltaToTextContent(latestCompletion.content, {
|
|
135
|
+
type: "reset",
|
|
136
|
+
})
|
|
137
|
+
latestCompletion.token = Aio.applyDeltaToNumberContent(latestCompletion.token, {
|
|
138
|
+
type: "reset",
|
|
139
|
+
})
|
|
140
|
+
await targetCompletionTube.pushData(structuredClone(latestCompletion))
|
|
141
|
+
|
|
142
|
+
// 如果尝试次数未达到上限,则继续尝试
|
|
143
|
+
const nextTryIndex = tryIndex + 1
|
|
144
|
+
if (nextTryIndex < maxTries) {
|
|
145
|
+
this.logger.log(`Not exceed maximum tries (${maxTries}) for chat completion, try again`)
|
|
146
|
+
scheduleMacroTask({
|
|
147
|
+
task: async () => {
|
|
148
|
+
await startTry(nextTryIndex)
|
|
149
|
+
},
|
|
150
|
+
timeout: 500,
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
this.logger.log(`Exceeded maximum tries (${maxTries}) for chat completion`)
|
|
155
|
+
await targetCompletionTube.pushError(new Error("Exceeded maximum tries."))
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const startTry = async (tryIndex: number): Promise<void> => {
|
|
159
|
+
this.logger.log(`Start try, tries ${tryIndex + 1} of ${maxTries}`)
|
|
160
|
+
|
|
161
|
+
const abortManager = fromWithAbortSignal(options)
|
|
162
|
+
const [getItemLeft, getItemRight] = eitherToTuple(await selector.getItem())
|
|
163
|
+
if (getItemLeft !== undefined) {
|
|
164
|
+
await handleTryError({ tryIndex, abortManager })
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
const { item, markUnavailable } = getItemRight
|
|
168
|
+
this.logger.log(`${item.logger.getName()} is selected from pool`)
|
|
169
|
+
const [leftResult, rightResult] = eitherToTuple(await this.requestAndConstrainSpeed(
|
|
170
|
+
{
|
|
171
|
+
...options,
|
|
172
|
+
abortSignal: abortManager.abortSignal,
|
|
173
|
+
},
|
|
174
|
+
item,
|
|
175
|
+
))
|
|
176
|
+
if (leftResult !== undefined) {
|
|
177
|
+
await handleTryError({ tryIndex, abortManager })
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
const { completionTube: sourceCompletionTube } = rightResult
|
|
181
|
+
sourceCompletionTube.subscribeEndEvent({
|
|
182
|
+
subscriber: async (): Promise<void> => {
|
|
183
|
+
if (sourceCompletionTube.isError()) {
|
|
184
|
+
this.logger.log("Source completion tube ended with error")
|
|
185
|
+
markUnavailable()
|
|
186
|
+
await handleTryError({ tryIndex, abortManager })
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
this.logger.log("Source completion tube ended normally")
|
|
190
|
+
await targetCompletionTube.end()
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
})
|
|
194
|
+
sourceCompletionTube.subscribeData({
|
|
195
|
+
subscriber: async (data: Completion): Promise<void> => {
|
|
196
|
+
await targetCompletionTube.pushData(data)
|
|
197
|
+
},
|
|
198
|
+
})
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
await startTry(0)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* 发起请求并对返回结果施加时间约束,当发生以下情况时,将被视为请求失败:
|
|
206
|
+
* 1. 首个数据块超时;
|
|
207
|
+
* 2. 相邻数据块超时;
|
|
208
|
+
*/
|
|
209
|
+
private async requestAndConstrainSpeed(
|
|
210
|
+
options: ChatCompletionOptions,
|
|
211
|
+
instance: BaseChatCompletion,
|
|
212
|
+
): Promise<ChatCompletionResult> {
|
|
213
|
+
const controller = controllerFromEitherType<ChatCompletionResult>()
|
|
214
|
+
|
|
215
|
+
const [chatCompletionLeft, chatCompletionRight] = eitherToTuple(await instance.chatCompletion(options))
|
|
216
|
+
if (chatCompletionLeft !== undefined) {
|
|
217
|
+
return await controller.returnLeft(chatCompletionLeft)
|
|
218
|
+
}
|
|
219
|
+
const { completionTube } = chatCompletionRight
|
|
220
|
+
|
|
221
|
+
const newCompletionTube = new Tube<Completion>({ historyCount: Infinity, replayHistory: true })
|
|
222
|
+
// 无异常的情况下,上游数据直接传递给下游即可
|
|
223
|
+
connectTube(completionTube, newCompletionTube)
|
|
224
|
+
|
|
225
|
+
const timeoutFirstChunk = options.timeoutFirstChunk ?? this.options.timeoutFirstChunk
|
|
226
|
+
const timeoutPerChunk = options.timeoutPerChunk ?? this.options.timeoutPerChunk
|
|
227
|
+
|
|
228
|
+
// 定义首个数据块超时的处理逻辑
|
|
229
|
+
let hasReceivedFirstChunk = false
|
|
230
|
+
const firstChunkTimeoutTimer: NodeJS.Timeout = setTimeout(() => {
|
|
231
|
+
if (hasReceivedFirstChunk === false) {
|
|
232
|
+
this.logger.addOnceTags(["ConstrainSpeed"]).log("First chunk timeout")
|
|
233
|
+
void newCompletionTube.pushError(new Error("FirstChunkTimeout"))
|
|
234
|
+
}
|
|
235
|
+
}, timeoutFirstChunk)
|
|
236
|
+
|
|
237
|
+
// 定义相邻数据块超时的处理逻辑
|
|
238
|
+
let perChunkTimeoutTimer: NodeJS.Timeout | undefined
|
|
239
|
+
completionTube.subscribeData({
|
|
240
|
+
subscriber: () => {
|
|
241
|
+
if (hasReceivedFirstChunk === false) {
|
|
242
|
+
this.logger.addOnceTags(["ConstrainSpeed"]).log("Received first chunk, clear first chunk timeout timer")
|
|
243
|
+
hasReceivedFirstChunk = true
|
|
244
|
+
// Clear the timeout timer for the first chunk
|
|
245
|
+
clearTimeout(firstChunkTimeoutTimer)
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
// Reset the timeout timer for each chunk
|
|
249
|
+
clearTimeout(perChunkTimeoutTimer)
|
|
250
|
+
}
|
|
251
|
+
// Set a new timeout timer for the next chunk
|
|
252
|
+
perChunkTimeoutTimer = setTimeout(() => {
|
|
253
|
+
this.logger.addOnceTags(["ConstrainSpeed"]).log("Per chunk timeout")
|
|
254
|
+
void newCompletionTube.pushError(new Error("PerChunkTimeout"))
|
|
255
|
+
}, timeoutPerChunk)
|
|
256
|
+
},
|
|
257
|
+
})
|
|
258
|
+
completionTube.subscribeEndEvent({
|
|
259
|
+
subscriber: () => {
|
|
260
|
+
this.logger.addOnceTags(["ConstrainSpeed"]).log("Source completion tube ended")
|
|
261
|
+
clearTimeout(firstChunkTimeoutTimer)
|
|
262
|
+
clearTimeout(perChunkTimeoutTimer)
|
|
263
|
+
},
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
return await controller.returnRight({
|
|
267
|
+
completionTube: newCompletionTube,
|
|
268
|
+
})
|
|
269
|
+
}
|
|
270
|
+
}
|