@blade-hq/agent-client 2610.0.0-beta.29 → 2610.0.0-beta.30

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/README.md CHANGED
@@ -518,6 +518,9 @@ groupMessagesByLoop(messages) // 按主/子智能体分组(智能体
518
518
  contentPreview(message.content, 80) // 截断预览
519
519
  ```
520
520
 
521
+ 错误消息在普通聊天界面展示前用 `chatErrorForDisplay(message)` 转成稳定的业务文案,
522
+ 避免把内部路径或传输诊断暴露给用户;仅开发者界面显式传入第二个参数 `true` 保留原文。
523
+
521
524
  一个完整的渲染示例:
522
525
 
523
526
  ```tsx
package/dist/index.d.ts CHANGED
@@ -28,7 +28,7 @@ export type { ModelCatalog, ModelOption } from "./resources/models";
28
28
  export type { SessionsResource } from "./resources/sessions";
29
29
  export type { CreateSessionRequest, AppCliAttachment, AppCliDefinition, FileEntry, ImportSessionOptions, PaginatedSessionsResult, GlobalSearchConversationResult, GlobalSearchFileResult, GlobalSearchResult, GlobalSearchResultItem, ResultFeedback, ResultFeedbackReason, SessionContextStats, SessionHistory, ShareLinkResult, UploadFileEntry, UploadFilesOptions, } from "./resources/sessions";
30
30
  export type { ArchivedFileInfo, ArchivedToolCallInfo, ChatMessage, CompactionInfo, FileContentPart, ImageUrlContentPart, MemoryRefInfo, MessageContent, MessageContentPart, TextContentPart, ToolBridgeContent, ToolCallInfo, } from "./schemas/message";
31
- export { buildMessageContent, contentPreview, extractTextAttachments, getFileParts, getImageParts, getTextContent, groupMessagesByLoop, isHiddenInternalMessage, normalizeMessageContent, transformSlashCommand, } from "./schemas/message-utils";
31
+ export { buildMessageContent, chatErrorForDisplay, contentPreview, extractTextAttachments, getFileParts, getImageParts, getTextContent, groupMessagesByLoop, isHiddenInternalMessage, normalizeMessageContent, transformSlashCommand, } from "./schemas/message-utils";
32
32
  export { contextProjectionData, getContextDisplayState, } from "./schemas/context";
33
33
  export type { ContextAction, ContextDisplayState, ContextProjectionData, ContextProjectionFields, ContextSourceInfo, } from "./schemas/context";
34
34
  export type { ParsedTextAttachment, ParsedTextContext, SkillMentionAvailability, } from "./schemas/message-utils";
package/dist/index.js CHANGED
@@ -1187,7 +1187,8 @@ function completedResponseText(content) {
1187
1187
  ).filter((part) => part.type === "text").map((part) => String(part.text ?? "")).join("");
1188
1188
  }
1189
1189
  function replaceTextContent(state, content) {
1190
- if (state.blocks.some((block) => block.type === "text")) return;
1190
+ const currentContent = state.blocks.filter((block) => block.type === "text").map((block) => String(block.content ?? "")).join("");
1191
+ if (currentContent === content) return;
1191
1192
  const replacement = { type: "text", content };
1192
1193
  const blocks = [];
1193
1194
  let inserted = false;
@@ -1207,6 +1208,31 @@ function replaceTextContent(state, content) {
1207
1208
  }
1208
1209
  state.blocks = blocks;
1209
1210
  }
1211
+ function applyResponseBlockOrder(state, value) {
1212
+ if (!Array.isArray(value)) return false;
1213
+ const ordered = [];
1214
+ for (const item of value) {
1215
+ if (typeof item !== "object" || item === null || Array.isArray(item)) continue;
1216
+ const block = item;
1217
+ if (block.type === "text" || block.type === "thinking") {
1218
+ const content = String(block[block.type] ?? "");
1219
+ if (content) ordered.push({ type: block.type, content });
1220
+ continue;
1221
+ }
1222
+ if (block.type !== "tool_call") continue;
1223
+ const toolCallId = String(block.id ?? "");
1224
+ const toolBlock = state.blocks.find(
1225
+ (candidate) => candidate.type === "tool_use" && candidate.tool_call_id === toolCallId
1226
+ );
1227
+ if (toolBlock) ordered.push(toolBlock);
1228
+ }
1229
+ if (ordered.length === 0 && value.length > 0) return false;
1230
+ const unrelatedBlocks = state.blocks.filter(
1231
+ (block) => block.type !== "text" && block.type !== "thinking" && block.type !== "tool_use"
1232
+ );
1233
+ state.blocks = [...ordered, ...unrelatedBlocks];
1234
+ return true;
1235
+ }
1210
1236
  var ClientProjectionBuilder = class {
1211
1237
  activeTurns = /* @__PURE__ */ new Map();
1212
1238
  lastTurnIds = /* @__PURE__ */ new Map();
@@ -1591,9 +1617,6 @@ var ClientProjectionBuilder = class {
1591
1617
  if (typeof payload.usage === "object" && payload.usage !== null) {
1592
1618
  state.usage = { ...payload.usage };
1593
1619
  }
1594
- if ("content" in payload) {
1595
- replaceTextContent(state, completedResponseText(payload.content));
1596
- }
1597
1620
  const toolCalls = payload.tool_calls;
1598
1621
  if (Array.isArray(toolCalls)) {
1599
1622
  for (const raw of toolCalls) {
@@ -1611,6 +1634,9 @@ var ClientProjectionBuilder = class {
1611
1634
  );
1612
1635
  }
1613
1636
  }
1637
+ if (!applyResponseBlockOrder(state, payload.response_blocks) && "content" in payload) {
1638
+ replaceTextContent(state, completedResponseText(payload.content));
1639
+ }
1614
1640
  const isNativeProviderResponse = typeof payload.provider === "string" && payload.provider !== "";
1615
1641
  if (state.toolCalls.length === 0 || isNativeProviderResponse && state.toolCalls.every(
1616
1642
  (toolCall) => toolCall.status !== "pending" && toolCall.status !== "awaiting_answer"
@@ -2210,6 +2236,7 @@ function buildBlocks(message, toolCalls) {
2210
2236
  const displayContent = message.role === "user" ? message._display_content : void 0;
2211
2237
  const stored = message._blocks;
2212
2238
  const blocks = [];
2239
+ const storedToolCallIds = /* @__PURE__ */ new Set();
2213
2240
  if (displayContent !== void 0) {
2214
2241
  blocks.push({ type: "text", content: displayContent });
2215
2242
  } else if (Array.isArray(stored)) {
@@ -2218,15 +2245,31 @@ function buildBlocks(message, toolCalls) {
2218
2245
  const type3 = String(raw.type ?? "");
2219
2246
  if (type3 === "thinking") blocks.push({ type: type3, content: raw.thinking ?? raw.content ?? "" });
2220
2247
  if (type3 === "text") blocks.push({ type: type3, content: raw.text ?? raw.content ?? "" });
2248
+ if (type3 === "tool_call") {
2249
+ const toolCallId = String(raw.id ?? "");
2250
+ const toolCall = toolCalls.find((candidate) => candidate.id === toolCallId);
2251
+ if (!toolCall) continue;
2252
+ storedToolCallIds.add(toolCallId);
2253
+ blocks.push({
2254
+ type: "tool_use",
2255
+ content: toolCall.arguments,
2256
+ tool_call_id: toolCall.id,
2257
+ tool_name: toolCall.tool_name,
2258
+ display_name: toolCall.display_name
2259
+ });
2260
+ }
2221
2261
  }
2222
2262
  } else if (message.content !== void 0 && message.content !== "") {
2223
2263
  blocks.push({ type: "text", content: message.content });
2224
2264
  }
2225
2265
  for (const toolCall of toolCalls) {
2266
+ if (storedToolCallIds.has(toolCall.id)) continue;
2226
2267
  blocks.push({
2227
2268
  type: "tool_use",
2228
- content: { name: toolCall.tool_name, arguments: toolCall.arguments },
2229
- tool_call_id: toolCall.id
2269
+ content: toolCall.arguments,
2270
+ tool_call_id: toolCall.id,
2271
+ tool_name: toolCall.tool_name,
2272
+ display_name: toolCall.display_name
2230
2273
  });
2231
2274
  }
2232
2275
  return blocks;
@@ -2898,6 +2941,36 @@ var LEGACY_FORK_CONTEXT_MARKERS = [
2898
2941
  "\u53EF\u901A\u8FC7 `read_file` \u8BFB\u53D6\u3002",
2899
2942
  "# \u4F60\u7684\u4EFB\u52A1"
2900
2943
  ];
2944
+ var INTERNAL_CHAT_ERROR_PATTERNS = [
2945
+ /\b(?:ENOENT|EACCES|EPERM)\b/i,
2946
+ /\[(?:Errno -?\d+|WinError \d+)\]/i,
2947
+ /\b(?:ECONNRESET|ECONNREFUSED|ETIMEDOUT|EHOSTUNREACH|ENETUNREACH|ENOTFOUND|EAI_AGAIN)\b/i,
2948
+ /\b(?:Connection refused|Connection reset by peer|All connection attempts failed|getaddrinfo failed)\b/i,
2949
+ /(?:^|[\s("'`])\/(?:root|home|Users|tmp|var|opt|etc)\//,
2950
+ /[A-Za-z]:\\(?:Users|Windows|Program Files|AppData)\\/i,
2951
+ /(?:^|\n)Traceback \(most recent call last\):/,
2952
+ /(?:^|\n)\s*at\s+\S+(?:\s+\(|:\d+:\d+)/,
2953
+ /(?:^|\n)File "[^"]+", line \d+/
2954
+ ];
2955
+ var SAFE_CHAT_ERROR_PREFIXES = [
2956
+ "\u6C99\u76D2\u8FD0\u884C\u73AF\u5883\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",
2957
+ "\u6A21\u578B\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u68C0\u67E5\u6A21\u578B\u914D\u7F6E\u540E\u91CD\u8BD5\u3002"
2958
+ ];
2959
+ var GENERIC_CHAT_ERROR = "\u6D88\u606F\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002";
2960
+ function chatErrorForDisplay(message, developer = false) {
2961
+ const normalized = message.trim();
2962
+ if (!developer) {
2963
+ const safePrefix = SAFE_CHAT_ERROR_PREFIXES.find((prefix) => normalized.startsWith(prefix));
2964
+ if (safePrefix) return safePrefix;
2965
+ }
2966
+ if (!developer && /no source matches this model/i.test(normalized)) {
2967
+ return "\u5F53\u524D\u6A21\u578B\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u6216\u91CD\u65B0\u9009\u62E9\u6A21\u578B\u3002";
2968
+ }
2969
+ if (!developer && INTERNAL_CHAT_ERROR_PATTERNS.some((pattern) => pattern.test(normalized))) {
2970
+ return GENERIC_CHAT_ERROR;
2971
+ }
2972
+ return normalized || GENERIC_CHAT_ERROR;
2973
+ }
2901
2974
  function normalizeMessageContent(content) {
2902
2975
  if (typeof content === "string") return content;
2903
2976
  if (Array.isArray(content)) return content;
@@ -4745,7 +4818,7 @@ function resolveAuthToken(options) {
4745
4818
 
4746
4819
  // src/version.ts
4747
4820
  var SDK_NAME = "agent-client";
4748
- var SDK_VERSION = true ? "2610.0.0-beta.29" : "1.1.1";
4821
+ var SDK_VERSION = true ? "2610.0.0-beta.30" : "1.1.1";
4749
4822
 
4750
4823
  // src/socket.ts
4751
4824
  function withSdkIdentity(auth) {
@@ -5342,6 +5415,7 @@ export {
5342
5415
  acceptedPostChatFollowupCompletesLatestRun,
5343
5416
  buildMessageContent,
5344
5417
  canToggleComputer,
5418
+ chatErrorForDisplay,
5345
5419
  computerState,
5346
5420
  connectEmbedded,
5347
5421
  contentPreview,