@antdv-next/x-sdk 0.0.1 → 0.0.3
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/LICENSE +21 -0
- package/dist/_util/resolveMaybeRef.d.ts +2 -0
- package/dist/_util/resolveMaybeRef.js +7 -0
- package/dist/_util/types.js +0 -0
- package/dist/chat-providers/AbstractChatProvider.d.ts +2 -2
- package/dist/chat-providers/AbstractChatProvider.js +42 -0
- package/dist/chat-providers/DeepSeekChatProvider.d.ts +2 -2
- package/dist/chat-providers/DeepSeekChatProvider.js +59 -0
- package/dist/chat-providers/DefaultChatProvider.d.ts +2 -2
- package/dist/chat-providers/DefaultChatProvider.js +26 -0
- package/dist/chat-providers/OpenAIChatProvider.d.ts +2 -2
- package/dist/chat-providers/OpenAIChatProvider.js +49 -0
- package/dist/chat-providers/index.js +4 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -3
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/expect/index.js +1467 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/pretty-format/index.js +884 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js +1513 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/snapshot/index.js +661 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/spy/index.js +384 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/utils/chunk-pathe.M-eThtNZ.js +80 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/utils/diff.js +1304 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/utils/display.js +556 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/utils/error.js +27 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/utils/helpers.js +179 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/utils/offset.js +25 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/utils/serialize.js +75 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/utils/source-map.js +371 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/utils/timers.js +35 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/chunks/_commonjsHelpers.D26ty3Ew.js +4 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/chunks/rpc.MzXet3jl.js +50 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/chunks/test.CBQUpOM3.js +2645 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/chunks/utils.BX5Fg8C4.js +42 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/vendor/chai.js +2872 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/vendor/magic-string.js +1009 -0
- package/dist/node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/vendor/tinyrainbow.js +84 -0
- package/dist/x-chat/__tests__/index.test.d.ts +1 -0
- package/dist/x-chat/__tests__/index.test.js +258 -0
- package/dist/x-chat/index.d.ts +14 -23
- package/dist/x-chat/index.js +85 -67
- package/dist/x-chat/store.d.ts +2 -0
- package/dist/{store-C1diHqNH.js → x-chat/store.js} +15 -9
- package/dist/x-conversations/__tests__/index.test.d.ts +1 -0
- package/dist/x-conversations/__tests__/index.test.js +36 -0
- package/dist/x-conversations/index.d.ts +4 -4
- package/dist/x-conversations/index.js +37 -1
- package/dist/{x-conversations-BrKWhj5r.js → x-conversations/store.js} +2 -31
- package/dist/x-request/__tests__/index.test.d.ts +1 -0
- package/dist/x-request/__tests__/index.test.js +90 -0
- package/dist/x-request/index.d.ts +36 -11
- package/dist/x-request/index.js +246 -1
- package/dist/x-request/x-fetch.js +18 -0
- package/dist/x-stream/__tests__/index.test.d.ts +1 -0
- package/dist/x-stream/__tests__/index.test.js +62 -0
- package/dist/x-stream/index.js +16 -5
- package/package.json +2 -1
- package/dist/chat-providers-5x9Va7p5.js +0 -167
- package/dist/x-request-BSFGaKND.js +0 -234
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MaybeRef } from 'vue';
|
|
1
2
|
import { AnyObject } from '../_util/types';
|
|
2
3
|
import { MessageInfo, SimpleType } from '../x-chat';
|
|
3
4
|
import { SSEOutput, XStreamOptions } from '../x-stream';
|
|
@@ -23,30 +24,49 @@ export interface XRequestOptions<Input = AnyObject, Output = SSEOutput, ChatMess
|
|
|
23
24
|
retryInterval?: number;
|
|
24
25
|
retryTimes?: number;
|
|
25
26
|
}
|
|
26
|
-
export type
|
|
27
|
-
|
|
27
|
+
export type XRequestConfigOptions<Input = AnyObject, Output = SSEOutput, ChatMessage extends SimpleType = any> = Omit<XRequestOptions<Input, Output, ChatMessage>, "callbacks" | "params" | "headers" | "timeout" | "streamTimeout" | "fetch" | "middlewares" | "transformStream" | "streamSeparator" | "partSeparator" | "kvSeparator" | "manual" | "retryInterval" | "retryTimes"> & {
|
|
28
|
+
callbacks?: XRequestCallbacks<Output, ChatMessage>;
|
|
29
|
+
params?: MaybeRef<Partial<Input>>;
|
|
30
|
+
headers?: MaybeRef<Record<string, string>>;
|
|
31
|
+
timeout?: MaybeRef<number>;
|
|
32
|
+
streamTimeout?: MaybeRef<number>;
|
|
33
|
+
fetch?: (baseURL: Parameters<typeof fetch>[0], options: XRequestOptions<Input, Output>) => Promise<Response>;
|
|
34
|
+
middlewares?: XFetchMiddlewares<Input, Output>;
|
|
35
|
+
transformStream?: XStreamOptions<Output>["transformStream"] | ((baseURL: string, responseHeaders: Headers) => XStreamOptions<Output>["transformStream"]);
|
|
36
|
+
streamSeparator?: MaybeRef<string>;
|
|
37
|
+
partSeparator?: MaybeRef<string>;
|
|
38
|
+
kvSeparator?: MaybeRef<string>;
|
|
39
|
+
manual?: MaybeRef<boolean>;
|
|
40
|
+
retryInterval?: MaybeRef<number>;
|
|
41
|
+
retryTimes?: MaybeRef<number>;
|
|
42
|
+
};
|
|
43
|
+
export type XRequestGlobalOptions<Input, Output> = Pick<XRequestConfigOptions<Input, Output>, "headers" | "timeout" | "streamTimeout" | "middlewares" | "fetch" | "transformStream" | "manual">;
|
|
44
|
+
export type XRequestFunction<Input = AnyObject, Output = SSEOutput> = (baseURL: MaybeRef<string>, options?: XRequestConfigOptions<Input, Output>) => XRequestClass<Input, Output>;
|
|
45
|
+
export interface XRequestReactiveState {
|
|
46
|
+
isTimeout: boolean;
|
|
47
|
+
isStreamTimeout: boolean;
|
|
48
|
+
isRequesting: boolean;
|
|
49
|
+
}
|
|
28
50
|
export declare function setXRequestGlobalOptions<Input, Output>(options: XRequestGlobalOptions<Input, Output>): void;
|
|
29
51
|
export declare abstract class AbstractXRequestClass<Input, Output, ChatMessage extends SimpleType = any> {
|
|
30
|
-
baseURL: string
|
|
31
|
-
options:
|
|
32
|
-
constructor(baseURL: string
|
|
52
|
+
baseURL: MaybeRef<string>;
|
|
53
|
+
options: XRequestConfigOptions<Input, Output, ChatMessage>;
|
|
54
|
+
constructor(baseURL: MaybeRef<string>, options?: XRequestConfigOptions<Input, Output, ChatMessage>);
|
|
33
55
|
abstract get asyncHandler(): Promise<any>;
|
|
34
56
|
abstract get isTimeout(): boolean;
|
|
35
57
|
abstract get isStreamTimeout(): boolean;
|
|
36
58
|
abstract get isRequesting(): boolean;
|
|
37
59
|
abstract get manual(): boolean;
|
|
60
|
+
abstract get state(): Readonly<XRequestReactiveState>;
|
|
38
61
|
abstract run(params?: Input): void;
|
|
39
62
|
abstract abort(): void;
|
|
40
63
|
}
|
|
41
64
|
export declare class XRequestClass<Input = AnyObject, Output = SSEOutput, ChatMessage extends SimpleType = any> extends AbstractXRequestClass<Input, Output, ChatMessage> {
|
|
42
65
|
private _asyncHandler;
|
|
43
66
|
private timeoutHandler;
|
|
44
|
-
private _isTimeout;
|
|
45
67
|
private streamTimeoutHandler;
|
|
46
|
-
private _isStreamTimeout;
|
|
47
68
|
private abortController;
|
|
48
|
-
private
|
|
49
|
-
private _manual;
|
|
69
|
+
private _state;
|
|
50
70
|
private lastManualParams?;
|
|
51
71
|
private retryTimes;
|
|
52
72
|
private retryTimer;
|
|
@@ -58,7 +78,12 @@ export declare class XRequestClass<Input = AnyObject, Output = SSEOutput, ChatMe
|
|
|
58
78
|
private set isStreamTimeout(value);
|
|
59
79
|
get isRequesting(): boolean;
|
|
60
80
|
get manual(): boolean;
|
|
61
|
-
|
|
81
|
+
get state(): {
|
|
82
|
+
readonly isTimeout: boolean;
|
|
83
|
+
readonly isStreamTimeout: boolean;
|
|
84
|
+
readonly isRequesting: boolean;
|
|
85
|
+
};
|
|
86
|
+
constructor(baseURL: MaybeRef<string>, options?: XRequestConfigOptions<Input, Output, ChatMessage>);
|
|
62
87
|
run(params?: Input): boolean;
|
|
63
88
|
abort(): void;
|
|
64
89
|
private init;
|
|
@@ -70,5 +95,5 @@ export declare class XRequestClass<Input = AnyObject, Output = SSEOutput, ChatMe
|
|
|
70
95
|
private jsonResponseHandler;
|
|
71
96
|
private resetRetry;
|
|
72
97
|
}
|
|
73
|
-
declare function XRequest<Input = AnyObject, Output = SSEOutput, ChatMessage extends SimpleType = any>(baseURL: string
|
|
98
|
+
declare function XRequest<Input = AnyObject, Output = SSEOutput, ChatMessage extends SimpleType = any>(baseURL: MaybeRef<string>, options?: XRequestConfigOptions<Input, Output, ChatMessage>): AbstractXRequestClass<Input, Output, ChatMessage>;
|
|
74
99
|
export default XRequest;
|
package/dist/x-request/index.js
CHANGED
|
@@ -1,2 +1,247 @@
|
|
|
1
|
-
import
|
|
1
|
+
import resolveMaybeRef from "../_util/resolveMaybeRef.js";
|
|
2
|
+
import XStream from "../x-stream/index.js";
|
|
3
|
+
import XFetch from "./x-fetch.js";
|
|
4
|
+
import { reactive, readonly } from "vue";
|
|
5
|
+
//#region src/x-request/index.ts
|
|
6
|
+
var globalOptions = {
|
|
7
|
+
manual: false,
|
|
8
|
+
headers: { "Content-Type": "application/json" }
|
|
9
|
+
};
|
|
10
|
+
function setXRequestGlobalOptions(options) {
|
|
11
|
+
Object.assign(globalOptions, options);
|
|
12
|
+
}
|
|
13
|
+
var LastEventId = "Last-Event-ID";
|
|
14
|
+
var AbstractXRequestClass = class {
|
|
15
|
+
baseURL;
|
|
16
|
+
options;
|
|
17
|
+
constructor(baseURL, options) {
|
|
18
|
+
const resolvedBaseURL = resolveMaybeRef(baseURL);
|
|
19
|
+
if (!resolvedBaseURL || typeof resolvedBaseURL !== "string") throw new Error("The baseURL is not valid!");
|
|
20
|
+
this.baseURL = baseURL;
|
|
21
|
+
this.options = options || {};
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
var XRequestClass = class extends AbstractXRequestClass {
|
|
25
|
+
_asyncHandler;
|
|
26
|
+
timeoutHandler;
|
|
27
|
+
streamTimeoutHandler;
|
|
28
|
+
abortController;
|
|
29
|
+
_state = reactive({
|
|
30
|
+
isTimeout: false,
|
|
31
|
+
isStreamTimeout: false,
|
|
32
|
+
isRequesting: false
|
|
33
|
+
});
|
|
34
|
+
lastManualParams;
|
|
35
|
+
retryTimes = 0;
|
|
36
|
+
retryTimer;
|
|
37
|
+
lastEventId = void 0;
|
|
38
|
+
get asyncHandler() {
|
|
39
|
+
return this._asyncHandler;
|
|
40
|
+
}
|
|
41
|
+
get isTimeout() {
|
|
42
|
+
return this._state.isTimeout;
|
|
43
|
+
}
|
|
44
|
+
set isTimeout(value) {
|
|
45
|
+
this._state.isTimeout = value;
|
|
46
|
+
}
|
|
47
|
+
get isStreamTimeout() {
|
|
48
|
+
return this._state.isStreamTimeout;
|
|
49
|
+
}
|
|
50
|
+
set isStreamTimeout(value) {
|
|
51
|
+
this._state.isStreamTimeout = value;
|
|
52
|
+
}
|
|
53
|
+
get isRequesting() {
|
|
54
|
+
return this._state.isRequesting;
|
|
55
|
+
}
|
|
56
|
+
get manual() {
|
|
57
|
+
const localManual = resolveMaybeRef(this.options.manual);
|
|
58
|
+
if (typeof localManual === "boolean") return localManual;
|
|
59
|
+
const globalManual = resolveMaybeRef(globalOptions.manual);
|
|
60
|
+
if (typeof globalManual === "boolean") return globalManual;
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
get state() {
|
|
64
|
+
return readonly(this._state);
|
|
65
|
+
}
|
|
66
|
+
constructor(baseURL, options) {
|
|
67
|
+
super(baseURL, options);
|
|
68
|
+
if (!this.manual) this.init();
|
|
69
|
+
}
|
|
70
|
+
run(params) {
|
|
71
|
+
if (this.manual) {
|
|
72
|
+
this.resetRetry();
|
|
73
|
+
this.lastManualParams = params;
|
|
74
|
+
this.init(params);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
console.warn("The request is not manual, so it cannot be run!");
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
abort() {
|
|
81
|
+
clearTimeout(this.timeoutHandler);
|
|
82
|
+
clearTimeout(this.streamTimeoutHandler);
|
|
83
|
+
this.abortController.abort();
|
|
84
|
+
}
|
|
85
|
+
init(extraParams, extraHeaders) {
|
|
86
|
+
const currentBaseURL = resolveMaybeRef(this.baseURL);
|
|
87
|
+
if (!currentBaseURL || typeof currentBaseURL !== "string") throw new Error("The baseURL is not valid!");
|
|
88
|
+
this.abortController = new AbortController();
|
|
89
|
+
this.isTimeout = false;
|
|
90
|
+
this.isStreamTimeout = false;
|
|
91
|
+
const { callbacks: sourceCallbacks, params: sourceParams, headers: sourceHeaders, transformStream: sourceTransformStream, fetch: sourceFetch, timeout: sourceTimeout, streamTimeout: sourceStreamTimeout, middlewares: sourceMiddlewares, streamSeparator: sourceStreamSeparator, partSeparator: sourcePartSeparator, kvSeparator: sourceKvSeparator, manual: _sourceManual, retryInterval: sourceRetryInterval, retryTimes: sourceRetryTimes, ...otherOptions } = this.options;
|
|
92
|
+
const callbacks = sourceCallbacks;
|
|
93
|
+
const params = resolveMaybeRef(sourceParams);
|
|
94
|
+
const headers = resolveMaybeRef(sourceHeaders) || {};
|
|
95
|
+
const transformStream = sourceTransformStream;
|
|
96
|
+
const fetch = sourceFetch;
|
|
97
|
+
const timeout = resolveMaybeRef(sourceTimeout);
|
|
98
|
+
const streamTimeout = resolveMaybeRef(sourceStreamTimeout);
|
|
99
|
+
const middlewares = sourceMiddlewares;
|
|
100
|
+
const streamSeparator = resolveMaybeRef(sourceStreamSeparator);
|
|
101
|
+
const partSeparator = resolveMaybeRef(sourcePartSeparator);
|
|
102
|
+
const kvSeparator = resolveMaybeRef(sourceKvSeparator);
|
|
103
|
+
const retryInterval = resolveMaybeRef(sourceRetryInterval);
|
|
104
|
+
const retryTimes = resolveMaybeRef(sourceRetryTimes);
|
|
105
|
+
const globalHeaders = resolveMaybeRef(globalOptions.headers) || {};
|
|
106
|
+
const margeHeaders = Object.assign({}, globalHeaders, headers, extraHeaders || {});
|
|
107
|
+
const requestInit = {
|
|
108
|
+
...otherOptions,
|
|
109
|
+
method: "POST",
|
|
110
|
+
body: JSON.stringify({
|
|
111
|
+
...params,
|
|
112
|
+
...extraParams
|
|
113
|
+
}),
|
|
114
|
+
params: {
|
|
115
|
+
...params,
|
|
116
|
+
...extraParams
|
|
117
|
+
},
|
|
118
|
+
headers: margeHeaders,
|
|
119
|
+
signal: this.abortController.signal,
|
|
120
|
+
middlewares
|
|
121
|
+
};
|
|
122
|
+
if (timeout && timeout > 0) this.timeoutHandler = setTimeout(() => {
|
|
123
|
+
this.isTimeout = true;
|
|
124
|
+
this.finishRequest();
|
|
125
|
+
callbacks?.onError?.(/* @__PURE__ */ new Error("TimeoutError"));
|
|
126
|
+
}, timeout);
|
|
127
|
+
this.startRequest();
|
|
128
|
+
this._asyncHandler = XFetch(currentBaseURL, {
|
|
129
|
+
fetch,
|
|
130
|
+
...requestInit
|
|
131
|
+
}).then(async (response) => {
|
|
132
|
+
clearTimeout(this.timeoutHandler);
|
|
133
|
+
if (this.isTimeout) return;
|
|
134
|
+
if (transformStream) {
|
|
135
|
+
let transformer = transformStream;
|
|
136
|
+
if (typeof transformStream === "function") transformer = transformStream(currentBaseURL, response.headers);
|
|
137
|
+
await this.customResponseHandler(response, callbacks, transformer, streamTimeout, streamSeparator, partSeparator, kvSeparator);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const contentType = response.headers.get("content-type") || "";
|
|
141
|
+
switch (contentType.split(";")[0].trim()) {
|
|
142
|
+
case "text/event-stream":
|
|
143
|
+
await this.sseResponseHandler(response, callbacks, streamTimeout, streamSeparator, partSeparator, kvSeparator);
|
|
144
|
+
break;
|
|
145
|
+
case "application/json":
|
|
146
|
+
await this.jsonResponseHandler(response, callbacks);
|
|
147
|
+
break;
|
|
148
|
+
default: throw new Error(`The response content-type: ${contentType} is not support!`);
|
|
149
|
+
}
|
|
150
|
+
}).catch((error) => {
|
|
151
|
+
clearTimeout(this.timeoutHandler);
|
|
152
|
+
this.finishRequest();
|
|
153
|
+
const err = error instanceof Error || error instanceof DOMException ? error : /* @__PURE__ */ new Error("Unknown error!");
|
|
154
|
+
const returnOfOnError = callbacks?.onError?.(err);
|
|
155
|
+
if (err.name !== "AbortError") {
|
|
156
|
+
const actualRetryInterval = typeof returnOfOnError === "number" ? returnOfOnError : retryInterval;
|
|
157
|
+
if (actualRetryInterval && actualRetryInterval > 0) {
|
|
158
|
+
if (typeof retryTimes === "number" && this.retryTimes >= retryTimes) return;
|
|
159
|
+
clearTimeout(this.retryTimer);
|
|
160
|
+
this.retryTimer = setTimeout(() => {
|
|
161
|
+
const extraHeaders = {};
|
|
162
|
+
if (typeof this.lastEventId !== "undefined") extraHeaders[LastEventId] = this.lastEventId;
|
|
163
|
+
this.init(this.lastManualParams, extraHeaders);
|
|
164
|
+
}, actualRetryInterval);
|
|
165
|
+
this.retryTimes = this.retryTimes + 1;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
startRequest() {
|
|
171
|
+
this._state.isRequesting = true;
|
|
172
|
+
}
|
|
173
|
+
finishRequest() {
|
|
174
|
+
this._state.isRequesting = false;
|
|
175
|
+
}
|
|
176
|
+
customResponseHandler = async (response, callbacks, transformStream, streamTimeout, streamSeparator, partSeparator, kvSeparator) => {
|
|
177
|
+
const stream = XStream({
|
|
178
|
+
readableStream: response.body,
|
|
179
|
+
transformStream,
|
|
180
|
+
streamSeparator,
|
|
181
|
+
partSeparator,
|
|
182
|
+
kvSeparator
|
|
183
|
+
});
|
|
184
|
+
await this.processStream(stream, response, callbacks, streamTimeout);
|
|
185
|
+
};
|
|
186
|
+
sseResponseHandler = async (response, callbacks, streamTimeout, streamSeparator, partSeparator, kvSeparator) => {
|
|
187
|
+
const stream = XStream({
|
|
188
|
+
readableStream: response.body,
|
|
189
|
+
streamSeparator,
|
|
190
|
+
partSeparator,
|
|
191
|
+
kvSeparator
|
|
192
|
+
});
|
|
193
|
+
await this.processStream(stream, response, callbacks, streamTimeout);
|
|
194
|
+
};
|
|
195
|
+
async processStream(stream, response, callbacks, streamTimeout) {
|
|
196
|
+
const chunks = [];
|
|
197
|
+
const iterator = stream[Symbol.asyncIterator]();
|
|
198
|
+
let result;
|
|
199
|
+
do {
|
|
200
|
+
if (streamTimeout) this.streamTimeoutHandler = setTimeout(() => {
|
|
201
|
+
this.isStreamTimeout = true;
|
|
202
|
+
this.finishRequest();
|
|
203
|
+
callbacks?.onError?.(/* @__PURE__ */ new Error("StreamTimeoutError"), void 0, response.headers);
|
|
204
|
+
}, streamTimeout);
|
|
205
|
+
result = await iterator.next();
|
|
206
|
+
clearTimeout(this.streamTimeoutHandler);
|
|
207
|
+
if (this.isStreamTimeout) break;
|
|
208
|
+
if (result.value) {
|
|
209
|
+
chunks.push(result.value);
|
|
210
|
+
callbacks?.onUpdate?.(result.value, response.headers);
|
|
211
|
+
if (typeof result?.value?.id !== "undefined") this.lastEventId = result.value.id;
|
|
212
|
+
}
|
|
213
|
+
} while (!result.done);
|
|
214
|
+
if (streamTimeout) {
|
|
215
|
+
clearTimeout(this.streamTimeoutHandler);
|
|
216
|
+
if (this.isStreamTimeout) {
|
|
217
|
+
this.finishRequest();
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
this.finishRequest();
|
|
222
|
+
callbacks?.onSuccess?.(chunks, response.headers);
|
|
223
|
+
}
|
|
224
|
+
jsonResponseHandler = async (response, callbacks) => {
|
|
225
|
+
const chunk = await response.json();
|
|
226
|
+
if (chunk?.success === false) {
|
|
227
|
+
this.finishRequest();
|
|
228
|
+
const error = new Error(chunk.message || "System error");
|
|
229
|
+
error.name = chunk.name || "SystemError";
|
|
230
|
+
callbacks?.onError?.(error, chunk, response.headers);
|
|
231
|
+
} else {
|
|
232
|
+
callbacks?.onUpdate?.(chunk, response.headers);
|
|
233
|
+
this.finishRequest();
|
|
234
|
+
callbacks?.onSuccess?.([chunk], response.headers);
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
resetRetry() {
|
|
238
|
+
clearTimeout(this.retryTimer);
|
|
239
|
+
this.retryTimes = 0;
|
|
240
|
+
this.lastEventId = void 0;
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
function XRequest(baseURL, options) {
|
|
244
|
+
return new XRequestClass(baseURL, options);
|
|
245
|
+
}
|
|
246
|
+
//#endregion
|
|
2
247
|
export { AbstractXRequestClass, XRequestClass, XRequest as default, setXRequestGlobalOptions };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/x-request/x-fetch.ts
|
|
2
|
+
var XFetch = async (baseURL, options) => {
|
|
3
|
+
const { fetch: fetchFn = globalThis.fetch, middlewares = {}, ...requestInit } = options;
|
|
4
|
+
if (typeof fetchFn !== "function") throw new Error("The options.fetch must be a typeof fetch function!");
|
|
5
|
+
let fetchArgs = [baseURL, requestInit];
|
|
6
|
+
if (typeof middlewares.onRequest === "function") fetchArgs = await middlewares.onRequest(...fetchArgs);
|
|
7
|
+
let response = await fetchFn(...fetchArgs);
|
|
8
|
+
if (typeof middlewares.onResponse === "function") {
|
|
9
|
+
const modifiedResponse = await middlewares.onResponse(response);
|
|
10
|
+
if (!(modifiedResponse instanceof Response)) throw new Error("The options.onResponse must return a Response instance!");
|
|
11
|
+
response = modifiedResponse;
|
|
12
|
+
}
|
|
13
|
+
if (!response.ok) throw new Error(`Fetch failed with status ${response.status}`);
|
|
14
|
+
if (!response.body) throw new Error("The response body is empty.");
|
|
15
|
+
return response;
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { XFetch as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import XStream from "../index.js";
|
|
2
|
+
import { h as describe, m as it } from "../../node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/@vitest/runner/chunk-artifact.js";
|
|
3
|
+
import { g as globalExpect, v as vi } from "../../node_modules/.pnpm/@voidzero-dev_vite-plus-test@0.1.14_@types_node@24.12.0_@voidzero-dev_vite-plus-core@0._0c620f79340a656256b2ffe23b3e6dd1/node_modules/@voidzero-dev/vite-plus-test/dist/chunks/test.CBQUpOM3.js";
|
|
4
|
+
//#region src/x-stream/__tests__/index.test.ts
|
|
5
|
+
var encoder = new TextEncoder();
|
|
6
|
+
describe("XStream", () => {
|
|
7
|
+
it("cancels the source and releases the reader lock on early exit", async () => {
|
|
8
|
+
const cancel = vi.fn();
|
|
9
|
+
const stream = XStream({ readableStream: new ReadableStream({
|
|
10
|
+
start(controller) {
|
|
11
|
+
controller.enqueue(encoder.encode("data: first\n\n"));
|
|
12
|
+
},
|
|
13
|
+
cancel
|
|
14
|
+
}) });
|
|
15
|
+
for await (const value of stream) {
|
|
16
|
+
globalExpect(value).toEqual({ data: "first" });
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
globalExpect(stream.locked).toBe(false);
|
|
20
|
+
await vi.waitFor(() => globalExpect(cancel).toHaveBeenCalledOnce());
|
|
21
|
+
const reader = stream.getReader();
|
|
22
|
+
await globalExpect(reader.read()).resolves.toEqual({
|
|
23
|
+
done: true,
|
|
24
|
+
value: void 0
|
|
25
|
+
});
|
|
26
|
+
reader.releaseLock();
|
|
27
|
+
});
|
|
28
|
+
it("preserves the consumer error when cancellation fails", async () => {
|
|
29
|
+
const consumerError = /* @__PURE__ */ new Error("consumer failed");
|
|
30
|
+
const cancelError = /* @__PURE__ */ new Error("cancel failed");
|
|
31
|
+
const cancel = vi.fn(() => Promise.reject(cancelError));
|
|
32
|
+
const stream = XStream({ readableStream: new ReadableStream({
|
|
33
|
+
start(controller) {
|
|
34
|
+
controller.enqueue(encoder.encode("data: first\n\n"));
|
|
35
|
+
},
|
|
36
|
+
cancel
|
|
37
|
+
}) });
|
|
38
|
+
const consume = async () => {
|
|
39
|
+
for await (const _value of stream) throw consumerError;
|
|
40
|
+
};
|
|
41
|
+
await globalExpect(consume()).rejects.toBe(consumerError);
|
|
42
|
+
globalExpect(cancel).toHaveBeenCalledOnce();
|
|
43
|
+
globalExpect(stream.locked).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
it("releases the reader lock without cancellation after normal completion", async () => {
|
|
46
|
+
const cancel = vi.fn();
|
|
47
|
+
const stream = XStream({ readableStream: new ReadableStream({
|
|
48
|
+
start(controller) {
|
|
49
|
+
controller.enqueue(encoder.encode("data: first\n\n"));
|
|
50
|
+
controller.enqueue(encoder.encode("data: second\n\n"));
|
|
51
|
+
controller.close();
|
|
52
|
+
},
|
|
53
|
+
cancel
|
|
54
|
+
}) });
|
|
55
|
+
const values = [];
|
|
56
|
+
for await (const value of stream) values.push(value);
|
|
57
|
+
globalExpect(values).toEqual([{ data: "first" }, { data: "second" }]);
|
|
58
|
+
globalExpect(cancel).not.toHaveBeenCalled();
|
|
59
|
+
globalExpect(stream.locked).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
//#endregion
|
package/dist/x-stream/index.js
CHANGED
|
@@ -101,11 +101,22 @@ function XStream(options) {
|
|
|
101
101
|
/** support async iterator */
|
|
102
102
|
stream[Symbol.asyncIterator] = async function* () {
|
|
103
103
|
const reader = this.getReader();
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
let completed = false;
|
|
105
|
+
try {
|
|
106
|
+
while (true) {
|
|
107
|
+
const { done, value } = await reader.read();
|
|
108
|
+
if (done) {
|
|
109
|
+
completed = true;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
if (!value) continue;
|
|
113
|
+
yield value;
|
|
114
|
+
}
|
|
115
|
+
} finally {
|
|
116
|
+
if (!completed) try {
|
|
117
|
+
await reader.cancel();
|
|
118
|
+
} catch {}
|
|
119
|
+
reader.releaseLock();
|
|
109
120
|
}
|
|
110
121
|
};
|
|
111
122
|
return stream;
|
package/package.json
CHANGED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
//#region src/chat-providers/AbstractChatProvider.ts
|
|
2
|
-
var AbstractChatProvider = class {
|
|
3
|
-
_request;
|
|
4
|
-
_getMessagesFn;
|
|
5
|
-
_originalCallbacks;
|
|
6
|
-
get request() {
|
|
7
|
-
return this._request;
|
|
8
|
-
}
|
|
9
|
-
constructor(config) {
|
|
10
|
-
const request = typeof config.request === "function" ? config.request() : config.request;
|
|
11
|
-
if (!request.manual) throw new Error("request must be manual");
|
|
12
|
-
this._request = request;
|
|
13
|
-
this._originalCallbacks = this._request.options?.callbacks;
|
|
14
|
-
}
|
|
15
|
-
getMessages() {
|
|
16
|
-
return this?._getMessagesFn();
|
|
17
|
-
}
|
|
18
|
-
injectGetMessages(getMessages) {
|
|
19
|
-
this._getMessagesFn = getMessages;
|
|
20
|
-
}
|
|
21
|
-
injectRequest({ onUpdate, onSuccess, onError }) {
|
|
22
|
-
const originalOnUpdate = this._originalCallbacks?.onUpdate;
|
|
23
|
-
const originalOnSuccess = this._originalCallbacks?.onSuccess;
|
|
24
|
-
const originalOnError = this._originalCallbacks?.onError;
|
|
25
|
-
this._request.options.callbacks = {
|
|
26
|
-
onUpdate: (data, responseHeaders) => {
|
|
27
|
-
const msg = onUpdate(data, responseHeaders);
|
|
28
|
-
if (originalOnUpdate) originalOnUpdate(data, responseHeaders, msg);
|
|
29
|
-
},
|
|
30
|
-
onSuccess: (data, responseHeaders) => {
|
|
31
|
-
const msg = onSuccess(data, responseHeaders);
|
|
32
|
-
if (originalOnSuccess) originalOnSuccess(data, responseHeaders, msg);
|
|
33
|
-
},
|
|
34
|
-
onError: (error, errorInfo, responseHeaders) => {
|
|
35
|
-
const fallbackMsg = onError(error, errorInfo);
|
|
36
|
-
if (originalOnError) originalOnError(error, errorInfo, responseHeaders, fallbackMsg);
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
//#endregion
|
|
42
|
-
//#region src/chat-providers/DeepSeekChatProvider.ts
|
|
43
|
-
/**
|
|
44
|
-
* DeepSeek Chat Provider
|
|
45
|
-
* @template ChatMessage 消息类型
|
|
46
|
-
* @template Input 请求参数类型
|
|
47
|
-
* @template Output 响应数据类型
|
|
48
|
-
*/
|
|
49
|
-
var DeepSeekChatProvider = class extends AbstractChatProvider {
|
|
50
|
-
transformParams(requestParams, options) {
|
|
51
|
-
return {
|
|
52
|
-
...options?.params,
|
|
53
|
-
...requestParams,
|
|
54
|
-
messages: this.getMessages()
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
transformLocalMessage(requestParams) {
|
|
58
|
-
return requestParams?.messages || [];
|
|
59
|
-
}
|
|
60
|
-
transformMessage(info) {
|
|
61
|
-
const { originMessage, chunk, responseHeaders } = info;
|
|
62
|
-
let currentContent = "";
|
|
63
|
-
let currentThink = "";
|
|
64
|
-
let role = "assistant";
|
|
65
|
-
try {
|
|
66
|
-
let message;
|
|
67
|
-
if (responseHeaders.get("content-type")?.includes("text/event-stream")) {
|
|
68
|
-
if (chunk && chunk.data?.trim() !== "[DONE]") message = JSON.parse(chunk.data);
|
|
69
|
-
} else message = chunk;
|
|
70
|
-
if (message) message?.choices?.forEach((choice) => {
|
|
71
|
-
if (choice?.delta) {
|
|
72
|
-
currentThink = choice.delta.reasoning_content || "";
|
|
73
|
-
currentContent += choice.delta.content || "";
|
|
74
|
-
role = choice.delta.role;
|
|
75
|
-
} else if (choice?.message) {
|
|
76
|
-
currentThink = choice.message.reasoning_content || "";
|
|
77
|
-
currentContent += choice.message.content || "";
|
|
78
|
-
role = choice.message.role;
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
} catch (error) {
|
|
82
|
-
console.error("transformMessage error", error);
|
|
83
|
-
}
|
|
84
|
-
let content = "";
|
|
85
|
-
let originMessageContent = typeof originMessage?.content === "string" ? originMessage?.content : originMessage?.content.text || "";
|
|
86
|
-
if (!originMessageContent && currentThink) content = `\n\n<think>\n\n${currentThink?.replace?.(/^\n{0,2}/, "")}`;
|
|
87
|
-
else if (originMessageContent.includes("<think>") && !originMessageContent.includes("</think>") && currentContent) {
|
|
88
|
-
originMessageContent = originMessageContent.replace("<think>", "<think status=\"done\">");
|
|
89
|
-
content = `${originMessageContent?.replace?.(/[\s\n]{0,2}$/, "")}\n\n</think>\n\n${currentContent}`;
|
|
90
|
-
} else content = `${originMessageContent || ""}${currentThink}${currentContent}`;
|
|
91
|
-
return {
|
|
92
|
-
content,
|
|
93
|
-
role: role || "assistant"
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
//#endregion
|
|
98
|
-
//#region src/chat-providers/DefaultChatProvider.ts
|
|
99
|
-
var DefaultChatProvider = class extends AbstractChatProvider {
|
|
100
|
-
transformParams(requestParams, options) {
|
|
101
|
-
if (typeof requestParams !== "object") throw new Error("requestParams must be an object");
|
|
102
|
-
return {
|
|
103
|
-
...options?.params,
|
|
104
|
-
...requestParams
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
transformLocalMessage(requestParams) {
|
|
108
|
-
return requestParams;
|
|
109
|
-
}
|
|
110
|
-
transformMessage(info) {
|
|
111
|
-
const { chunk, chunks, originMessage } = info;
|
|
112
|
-
if (chunk) return chunk;
|
|
113
|
-
if (Array.isArray(chunks)) {
|
|
114
|
-
const chunk = chunks?.length > 0 ? chunks?.[chunks?.length - 1] : void 0;
|
|
115
|
-
return originMessage ? originMessage : chunk;
|
|
116
|
-
}
|
|
117
|
-
return chunks;
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
//#endregion
|
|
121
|
-
//#region src/chat-providers/OpenAIChatProvider.ts
|
|
122
|
-
/**
|
|
123
|
-
* LLM OpenAI Compatible Chat Provider
|
|
124
|
-
* @template ChatMessage 消息类型
|
|
125
|
-
* @template Input 请求参数类型
|
|
126
|
-
* @template Output 响应数据类型
|
|
127
|
-
*/
|
|
128
|
-
var OpenAIChatProvider = class extends AbstractChatProvider {
|
|
129
|
-
transformParams(requestParams, options) {
|
|
130
|
-
return {
|
|
131
|
-
...options?.params,
|
|
132
|
-
...requestParams,
|
|
133
|
-
messages: this.getMessages()
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
transformLocalMessage(requestParams) {
|
|
137
|
-
return requestParams?.messages || [];
|
|
138
|
-
}
|
|
139
|
-
transformMessage(info) {
|
|
140
|
-
const { originMessage, chunk, responseHeaders } = info;
|
|
141
|
-
let currentContent = "";
|
|
142
|
-
let role = "assistant";
|
|
143
|
-
try {
|
|
144
|
-
let message;
|
|
145
|
-
if (responseHeaders.get("content-type")?.includes("text/event-stream")) {
|
|
146
|
-
if (chunk && chunk.data?.trim() !== "[DONE]") message = JSON.parse(chunk.data);
|
|
147
|
-
} else message = chunk;
|
|
148
|
-
if (message) message?.choices?.forEach((choice) => {
|
|
149
|
-
if (choice?.delta) {
|
|
150
|
-
currentContent += choice.delta.content || "";
|
|
151
|
-
role = choice.delta.role || "assistant";
|
|
152
|
-
} else if (choice?.message) {
|
|
153
|
-
currentContent += choice.message.content || "";
|
|
154
|
-
role = choice.message.role || "assistant";
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
} catch (error) {
|
|
158
|
-
console.error("transformMessage error", error);
|
|
159
|
-
}
|
|
160
|
-
return {
|
|
161
|
-
content: `${originMessage?.content || ""}${currentContent || ""}`,
|
|
162
|
-
role
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
//#endregion
|
|
167
|
-
export { AbstractChatProvider as i, DefaultChatProvider as n, DeepSeekChatProvider as r, OpenAIChatProvider as t };
|