@blueking/chat-helper 0.0.12-beta.27 → 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.
@@ -58,6 +58,8 @@ export interface IAgentCommandComponentApi {
58
58
  }
59
59
  export interface IAgentInfo {
60
60
  agentName?: string;
61
+ /** Agent 类型:single 为普通智能体,claw 为 Claw 智能体 */
62
+ agentType?: 'claw' | 'single' | string;
61
63
  relatedSkills?: IRelatedSkill[];
62
64
  resources?: IAgentResourceItem[];
63
65
  saasUrl?: string;
@@ -79,6 +81,8 @@ export interface IAgentInfo {
79
81
  }
80
82
  export interface IAgentInfoApi {
81
83
  agent_name: string;
84
+ /** Agent 类型:single 为普通智能体,claw 为 Claw 智能体 */
85
+ agent_type?: 'claw' | 'single' | string;
82
86
  related_skills?: IRelatedSkillApi[];
83
87
  resources?: IAgentResourceItem[];
84
88
  saas_url?: string;
@@ -195,3 +199,9 @@ export interface ILlmItemApi {
195
199
  tag_names?: string[];
196
200
  user_auth_mode?: string;
197
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 - 配置选项
@@ -12,6 +12,7 @@ import type { IAgentInfo, ILlmItem, ILlmListQuery } from './type';
12
12
  export declare const useAgent: (mediator: IMediatorModule, protocol: ISSEProtocol) => {
13
13
  info: import("vue").Ref<{
14
14
  agentName?: string;
15
+ agentType?: "claw" | "single" | string;
15
16
  relatedSkills?: {
16
17
  description: string;
17
18
  icon: string;
@@ -1022,6 +1023,7 @@ export declare const useAgent: (mediator: IMediatorModule, protocol: ISSEProtoco
1022
1023
  };
1023
1024
  }, IAgentInfo | {
1024
1025
  agentName?: string;
1026
+ agentType?: "claw" | "single" | string;
1025
1027
  relatedSkills?: {
1026
1028
  description: string;
1027
1029
  icon: string;
@@ -2097,7 +2099,7 @@ export declare const useAgent: (mediator: IMediatorModule, protocol: ISSEProtoco
2097
2099
  pollResumeSession: (sessionCode: string, model?: string) => void;
2098
2100
  clearLongPollTimer: () => void;
2099
2101
  userOperationStreamRequest: (sessionCode: string, operation: UserOperation, payload: IUserOperationPayload, config?: IRequestConfig, model?: string) => Promise<void>;
2100
- streamRequest: ({ sessionCode, model, url, config, resume, input, lastMessageId, isReconnect, }: {
2102
+ streamRequest: ({ sessionCode, model, url, config, resume, input, lastMessageId, isReconnect, streamMode, }: {
2101
2103
  sessionCode: string;
2102
2104
  model?: string;
2103
2105
  url?: string;
@@ -2107,6 +2109,7 @@ export declare const useAgent: (mediator: IMediatorModule, protocol: ISSEProtoco
2107
2109
  lastMessageId?: string;
2108
2110
  /** 内部静默重连,不重置重连计数 */
2109
2111
  isReconnect?: boolean;
2112
+ streamMode?: StreamMode;
2110
2113
  }) => Promise<void>;
2111
2114
  };
2112
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
  };
@@ -0,0 +1 @@
1
+ export {};
@@ -63,6 +63,7 @@
63
63
  supportUpload: data.prompt_setting.support_upload
64
64
  } : undefined,
65
65
  agentName: data === null || data === void 0 ? void 0 : data.agent_name,
66
+ agentType: data === null || data === void 0 ? void 0 : data.agent_type,
66
67
  relatedSkills: data === null || data === void 0 ? void 0 : (_data_related_skills = data.related_skills) === null || _data_related_skills === void 0 ? void 0 : _data_related_skills.map((skill)=>({
67
68
  id: skill.id,
68
69
  skill_name: skill.skill_name,
package/dist/index.d.ts CHANGED
@@ -14,6 +14,7 @@ export declare const useChatHelper: (options: IUseChatHelperOptions) => {
14
14
  agent: {
15
15
  info: import("vue").Ref<{
16
16
  agentName?: string;
17
+ agentType?: "claw" | "single" | string;
17
18
  relatedSkills?: {
18
19
  description: string;
19
20
  icon: string;
@@ -1024,6 +1025,7 @@ export declare const useChatHelper: (options: IUseChatHelperOptions) => {
1024
1025
  };
1025
1026
  }, import("./agent").IAgentInfo | {
1026
1027
  agentName?: string;
1028
+ agentType?: "claw" | "single" | string;
1027
1029
  relatedSkills?: {
1028
1030
  description: string;
1029
1031
  icon: string;
@@ -2099,7 +2101,7 @@ export declare const useChatHelper: (options: IUseChatHelperOptions) => {
2099
2101
  pollResumeSession: (sessionCode: string, model?: string) => void;
2100
2102
  clearLongPollTimer: () => void;
2101
2103
  userOperationStreamRequest: (sessionCode: string, operation: import("./message").UserOperation, payload: import("./message").IUserOperationPayload, config?: import("./http").IRequestConfig, model?: string) => Promise<void>;
2102
- streamRequest: ({ sessionCode, model, url, config, resume, input, lastMessageId, isReconnect, }: {
2104
+ streamRequest: ({ sessionCode, model, url, config, resume, input, lastMessageId, isReconnect, streamMode, }: {
2103
2105
  sessionCode: string;
2104
2106
  model?: string;
2105
2107
  url?: string;
@@ -2108,6 +2110,7 @@ export declare const useChatHelper: (options: IUseChatHelperOptions) => {
2108
2110
  input?: string;
2109
2111
  lastMessageId?: string;
2110
2112
  isReconnect?: boolean;
2113
+ streamMode?: import("./agent").StreamMode;
2111
2114
  }) => Promise<void>;
2112
2115
  };
2113
2116
  session: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blueking/chat-helper",
3
- "version": "0.0.12-beta.27",
3
+ "version": "0.0.12-beta.29",
4
4
  "description": "",
5
5
  "main": "./dist/index.ts.js",
6
6
  "types": "./dist/index.d.ts",
@@ -24,12 +24,14 @@
24
24
  "@blueking/cli-service": "0.1.0-beta.31",
25
25
  "eslint-plugin-simple-import-sort": "^10.0.0",
26
26
  "typescript": "^5.5.4",
27
+ "vitest": "^4.0.18",
27
28
  "vue-tsc": "^3.1.4"
28
29
  },
29
30
  "dependencies": {
30
31
  "@types/json-schema": "^7.0.15"
31
32
  },
32
33
  "scripts": {
33
- "build": "bk-cli-service build && vue-tsc --emitDeclarationOnly"
34
+ "build": "bk-cli-service build && vue-tsc --emitDeclarationOnly",
35
+ "test": "vitest run"
34
36
  }
35
37
  }