@blueking/chat-helper 0.0.12-beta.28 → 0.0.12-beta.29

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.
@@ -199,3 +199,9 @@ export interface ILlmItemApi {
199
199
  tag_names?: string[];
200
200
  user_auth_mode?: string;
201
201
  }
202
+ /**
203
+ * chat_completion execute_kwargs.stream_mode
204
+ * - start: 可创建生产者,开新一轮执行(默认)
205
+ * - attach: 仅接管/回放已有流,不允许新建生产者
206
+ */
207
+ export type StreamMode = 'start' | 'attach';
@@ -22,4 +22,8 @@
22
22
  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23
23
  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24
24
  * IN THE SOFTWARE.
25
- */ /** 后端 llms/ 原始响应项(字段可能缺省) */ export { };
25
+ */ /**
26
+ * chat_completion execute_kwargs.stream_mode
27
+ * - start: 可创建生产者,开新一轮执行(默认)
28
+ * - attach: 仅接管/回放已有流,不允许新建生产者
29
+ */ export { };
@@ -3,7 +3,7 @@ import { MessageRole, MessageStatus, UserOperation } from '../message';
3
3
  import type { IRequestConfig, ISSEProtocol } from '../http';
4
4
  import type { IMediatorModule } from '../mediator';
5
5
  import type { IMessageProperty, IUserMessage, IUserOperationPayload } from '../message/type';
6
- import type { IAgentInfo, ILlmItem, ILlmListQuery } from './type';
6
+ import type { IAgentInfo, ILlmItem, ILlmListQuery, StreamMode } from './type';
7
7
  /**
8
8
  * Agent 模块
9
9
  * @param options - 配置选项
@@ -2099,7 +2099,7 @@ export declare const useAgent: (mediator: IMediatorModule, protocol: ISSEProtoco
2099
2099
  pollResumeSession: (sessionCode: string, model?: string) => void;
2100
2100
  clearLongPollTimer: () => void;
2101
2101
  userOperationStreamRequest: (sessionCode: string, operation: UserOperation, payload: IUserOperationPayload, config?: IRequestConfig, model?: string) => Promise<void>;
2102
- streamRequest: ({ sessionCode, model, url, config, resume, input, lastMessageId, isReconnect, }: {
2102
+ streamRequest: ({ sessionCode, model, url, config, resume, input, lastMessageId, isReconnect, streamMode, }: {
2103
2103
  sessionCode: string;
2104
2104
  model?: string;
2105
2105
  url?: string;
@@ -2109,6 +2109,7 @@ export declare const useAgent: (mediator: IMediatorModule, protocol: ISSEProtoco
2109
2109
  lastMessageId?: string;
2110
2110
  /** 内部静默重连,不重置重连计数 */
2111
2111
  isReconnect?: boolean;
2112
+ streamMode?: StreamMode;
2112
2113
  }) => Promise<void>;
2113
2114
  };
2114
2115
  export type IAgentModule = ReturnType<typeof useAgent>;
@@ -111,14 +111,18 @@ import { SessionStatus } from '../session/type.ts.js';
111
111
  const RECONNECT_BASE_DELAY_MS = 1000;
112
112
  const RECONNECT_MAX_DELAY_MS = 8000;
113
113
  const getReconnectDelayMs = (attempt)=>Math.min(RECONNECT_BASE_DELAY_MS * Math.pow(2, attempt - 1), RECONNECT_MAX_DELAY_MS);
114
+ /** 后端 attach_only 且无可接管流时抛出(见 StreamAttachUnavailableError) */ const isStreamAttachUnavailableError = (error)=>/No active or replayable stream/i.test(error.message);
114
115
  /**
115
116
  * 判断流式错误是否可静默重连。
116
- * 不重试:Abort、401/403 等业务 4xx(408/429 除外);可重试:网络错误、5xx、无状态码的中断。
117
+ * 不重试:Abort、attach 无流、401/403 等业务 4xx(408/429 除外);可重试:网络错误、5xx、无状态码的中断。
117
118
  */ const isRecoverableStreamError = (error)=>{
118
119
  var _requestError_response;
119
120
  if (error.name === 'AbortError') {
120
121
  return false;
121
122
  }
123
+ if (isStreamAttachUnavailableError(error)) {
124
+ return false;
125
+ }
122
126
  const requestError = error;
123
127
  const statusFromResponse = (_requestError_response = requestError.response) === null || _requestError_response === void 0 ? void 0 : _requestError_response.status;
124
128
  const statusFromMessage = error.message.match(/status code (\d+)/i);
@@ -318,7 +322,8 @@ const getReconnectDelayMs = (attempt)=>Math.min(RECONNECT_BASE_DELAY_MS * Math.p
318
322
  url: ctx === null || ctx === void 0 ? void 0 : ctx.url,
319
323
  config: ctx === null || ctx === void 0 ? void 0 : ctx.config,
320
324
  lastMessageId: lastMessageId !== undefined ? String(lastMessageId) : undefined,
321
- isReconnect: true
325
+ isReconnect: true,
326
+ /** 静默重连:仅接管已有流,禁止后端新建 producer */ streamMode: 'attach'
322
327
  });
323
328
  return 'reconnected';
324
329
  });
@@ -327,16 +332,17 @@ const getReconnectDelayMs = (attempt)=>Math.min(RECONNECT_BASE_DELAY_MS * Math.p
327
332
  };
328
333
  }();
329
334
  const streamRequest = function() {
330
- var _ref = _async_to_generator(function*({ sessionCode, model, url, config, resume, input, lastMessageId, isReconnect = false }) {
335
+ var _ref = _async_to_generator(function*({ sessionCode, model, url, config, resume, input, lastMessageId, isReconnect = false, /** start 可启动新一轮执行;attach 仅接管/回放已有流 */ streamMode = 'start' }) {
331
336
  var _previousController_abort, _mediator_http;
332
337
  if (!isReconnect) {
333
338
  resetStreamReconnectState();
334
339
  }
335
340
  activeStreamContext = {
336
341
  sessionCode,
337
- model: model,
342
+ model,
338
343
  url,
339
- config
344
+ config,
345
+ streamMode
340
346
  };
341
347
  // 先递增世代再 abort 旧连接,避免旧流 onDone 误触发二次重连
342
348
  const streamId = ++activeStreamId;
@@ -426,6 +432,31 @@ const getReconnectDelayMs = (attempt)=>Math.min(RECONNECT_BASE_DELAY_MS * Math.p
426
432
  if (!isActiveStream() || manualAbort) {
427
433
  return;
428
434
  }
435
+ // attach 时后端无可接管流:视为本轮已结束,勿静默重连空转
436
+ if (streamMode === 'attach' && isStreamAttachUnavailableError(error)) {
437
+ var _mediator_session;
438
+ const settleAttachUnavailable = ()=>{
439
+ var _mediator_session_current_value, _mediator_session;
440
+ if (!isActiveStream() || manualAbort || !isSameActiveSession(sessionCode)) {
441
+ if (isActiveStream()) {
442
+ isChatting.value = false;
443
+ }
444
+ return;
445
+ }
446
+ if (((_mediator_session = mediator.session) === null || _mediator_session === void 0 ? void 0 : (_mediator_session_current_value = _mediator_session.current.value) === null || _mediator_session_current_value === void 0 ? void 0 : _mediator_session_current_value.status) !== SessionStatus.Running) {
447
+ finishSuccessfully();
448
+ return;
449
+ }
450
+ isChatting.value = false;
451
+ };
452
+ const refresh = (_mediator_session = mediator.session) === null || _mediator_session === void 0 ? void 0 : _mediator_session.getSession(sessionCode);
453
+ if (refresh) {
454
+ void refresh.catch(()=>undefined).then(settleAttachUnavailable);
455
+ } else {
456
+ settleAttachUnavailable();
457
+ }
458
+ return;
459
+ }
429
460
  if (!isRecoverableStreamError(error)) {
430
461
  failWithError(error);
431
462
  return;
@@ -479,6 +510,7 @@ const getReconnectDelayMs = (attempt)=>Math.min(RECONNECT_BASE_DELAY_MS * Math.p
479
510
  input,
480
511
  execute_kwargs: {
481
512
  stream: true,
513
+ stream_mode: streamMode,
482
514
  persist_input: !!input,
483
515
  last_message_id: lastMessageId,
484
516
  resume
@@ -547,7 +579,8 @@ const getReconnectDelayMs = (attempt)=>Math.min(RECONNECT_BASE_DELAY_MS * Math.p
547
579
  model,
548
580
  url,
549
581
  config,
550
- lastMessageId
582
+ lastMessageId,
583
+ /** 切会话/刷新恢复:仅接管已有流 */ streamMode: 'attach'
551
584
  });
552
585
  }
553
586
  };
package/dist/index.d.ts CHANGED
@@ -2101,7 +2101,7 @@ export declare const useChatHelper: (options: IUseChatHelperOptions) => {
2101
2101
  pollResumeSession: (sessionCode: string, model?: string) => void;
2102
2102
  clearLongPollTimer: () => void;
2103
2103
  userOperationStreamRequest: (sessionCode: string, operation: import("./message").UserOperation, payload: import("./message").IUserOperationPayload, config?: import("./http").IRequestConfig, model?: string) => Promise<void>;
2104
- streamRequest: ({ sessionCode, model, url, config, resume, input, lastMessageId, isReconnect, }: {
2104
+ streamRequest: ({ sessionCode, model, url, config, resume, input, lastMessageId, isReconnect, streamMode, }: {
2105
2105
  sessionCode: string;
2106
2106
  model?: string;
2107
2107
  url?: string;
@@ -2110,6 +2110,7 @@ export declare const useChatHelper: (options: IUseChatHelperOptions) => {
2110
2110
  input?: string;
2111
2111
  lastMessageId?: string;
2112
2112
  isReconnect?: boolean;
2113
+ streamMode?: import("./agent").StreamMode;
2113
2114
  }) => Promise<void>;
2114
2115
  };
2115
2116
  session: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blueking/chat-helper",
3
- "version": "0.0.12-beta.28",
3
+ "version": "0.0.12-beta.29",
4
4
  "description": "",
5
5
  "main": "./dist/index.ts.js",
6
6
  "types": "./dist/index.d.ts",