@blade-hq/agent-react 2610.0.0-beta.25 → 2610.0.0-beta.26

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/dist/index.js CHANGED
@@ -1831,6 +1831,7 @@ var TOOL_NAME_ALIASES = {
1831
1831
  finish_task: "FinishTask",
1832
1832
  glob: "Glob",
1833
1833
  grep: "Grep",
1834
+ kb_search: "KbSearch",
1834
1835
  ls: "Ls",
1835
1836
  multi_edit: "MultiEdit",
1836
1837
  read: "Read",
@@ -1849,6 +1850,7 @@ var TOOL_DISPLAY_LABELS = {
1849
1850
  Ls: "\u5217\u51FA\u76EE\u5F55",
1850
1851
  Glob: "\u5339\u914D\u6587\u4EF6",
1851
1852
  Grep: "\u641C\u7D22\u6587\u672C",
1853
+ KbSearch: "\u68C0\u7D22\u77E5\u8BC6\u5E93",
1852
1854
  WebSearch: "\u641C\u7D22\u7F51\u9875",
1853
1855
  WebFetch: "\u6574\u7406\u7F51\u9875\u5185\u5BB9",
1854
1856
  Agent: "\u6D3E\u751F\u5B50\u667A\u80FD\u4F53",
@@ -2688,7 +2690,6 @@ function buildAskUserPayload(argumentsJson) {
2688
2690
  import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2689
2691
  function ThinkingBlock({ reasoning, isStreaming }) {
2690
2692
  const [open, setOpen] = useState10(false);
2691
- if (!isStreaming) return null;
2692
2693
  return /* @__PURE__ */ jsxs9("div", { className: "blade-chat-thinking text-xs", children: [
2693
2694
  /* @__PURE__ */ jsxs9(
2694
2695
  "button",
@@ -2698,7 +2699,7 @@ function ThinkingBlock({ reasoning, isStreaming }) {
2698
2699
  "aria-expanded": open,
2699
2700
  className: "group/thinking inline-flex items-center gap-1 text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
2700
2701
  children: [
2701
- /* @__PURE__ */ jsx11(Shimmer, { className: "text-xs", children: "\u6B63\u5728\u601D\u8003" }),
2702
+ isStreaming ? /* @__PURE__ */ jsx11(Shimmer, { className: "text-xs", children: "\u6B63\u5728\u601D\u8003" }) : /* @__PURE__ */ jsx11("span", { children: "\u5DF2\u601D\u8003" }),
2702
2703
  /* @__PURE__ */ jsx11(
2703
2704
  ChevronRight,
2704
2705
  {
@@ -2712,7 +2713,7 @@ function ThinkingBlock({ reasoning, isStreaming }) {
2712
2713
  ]
2713
2714
  }
2714
2715
  ),
2715
- open ? /* @__PURE__ */ jsx11("div", { className: "mt-1.5 whitespace-pre-wrap text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", children: reasoning }) : null
2716
+ open && /* @__PURE__ */ jsx11("div", { className: "mt-1.5 whitespace-pre-wrap text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", children: reasoning })
2716
2717
  ] });
2717
2718
  }
2718
2719
  function getMessageText(message) {
@@ -2810,8 +2811,63 @@ function executionSummaryLabel({
2810
2811
  }
2811
2812
  return completedLabel;
2812
2813
  }
2814
+ function executionToolTypeLabel(toolCall) {
2815
+ switch (formatToolName(toolCall.name)) {
2816
+ case "WebSearch":
2817
+ case "WebFetch":
2818
+ return "\u7F51\u7EDC\u68C0\u7D22";
2819
+ case "Bash":
2820
+ case "BgBash":
2821
+ return "\u547D\u4EE4\u6267\u884C";
2822
+ case "Read":
2823
+ case "ReadSkill":
2824
+ return "\u5185\u5BB9\u8BFB\u53D6";
2825
+ case "Write":
2826
+ case "Edit":
2827
+ case "MultiEdit":
2828
+ return "\u6587\u4EF6\u5904\u7406";
2829
+ case "Grep":
2830
+ case "Glob":
2831
+ return "\u5185\u5BB9\u641C\u7D22";
2832
+ case "Agent":
2833
+ return "\u5B50\u4EFB\u52A1";
2834
+ case "search_skills":
2835
+ return "\u6280\u80FD\u68C0\u7D22";
2836
+ case "get_skill_content":
2837
+ return "\u8BFB\u53D6\u6280\u80FD";
2838
+ case "run_skill_tool":
2839
+ return "\u6267\u884C\u6280\u80FD";
2840
+ default:
2841
+ return toolCall.display_name?.trim() || "\u6267\u884C\u6B65\u9AA4";
2842
+ }
2843
+ }
2844
+ function executionToolIntent(toolCall) {
2845
+ const normalizedName = formatToolName(toolCall.name);
2846
+ let args = null;
2847
+ try {
2848
+ const parsed = JSON.parse(toolCall.arguments);
2849
+ args = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
2850
+ } catch {
2851
+ args = null;
2852
+ }
2853
+ const getString = (key) => {
2854
+ const value = args?.[key];
2855
+ return typeof value === "string" ? value.trim() : "";
2856
+ };
2857
+ const explicitIntent = getString("description") || getString("_meta_display_name") || getString("display_name") || toolCall.display_name?.trim() || "";
2858
+ if (explicitIntent) return explicitIntent;
2859
+ if (normalizedName === "search_skills") return getString("query");
2860
+ if (normalizedName === "get_skill_content" || normalizedName === "ReadSkill") {
2861
+ return getString("skill_name") || getString("skill");
2862
+ }
2863
+ if (normalizedName === "FinishTask") return getString("title");
2864
+ return "";
2865
+ }
2813
2866
  function ExecutionToolRow({ toolCall }) {
2814
2867
  const normalizedName = formatToolName(toolCall.name);
2868
+ const typeLabel = executionToolTypeLabel(toolCall);
2869
+ const intent = executionToolIntent(toolCall);
2870
+ const label = intent ? `${typeLabel}\uFF1A${intent}` : typeLabel;
2815
2871
  const failed = toolCall.status === "error" || toolCall.status === "cancelled";
2816
2872
  const filePath = toolCall.status === "done" && (normalizedName === "Write" || normalizedName === "Edit" || normalizedName === "MultiEdit") ? extractToolFilePath(toolCall) : null;
2817
2873
  const [fileOpen, setFileOpen] = useState10(false);
@@ -2819,13 +2875,16 @@ function ExecutionToolRow({ toolCall }) {
2819
2875
  "size-3.5 shrink-0",
2820
2876
  failed ? "text-red-500" : "text-[hsl(var(--muted-foreground))]"
2821
2877
  );
2822
- const icon = toolCall.status === "pending" ? /* @__PURE__ */ jsx11(LoaderCircle, { className: cn(iconClass, "animate-spin"), "aria-hidden": "true" }) : toolCall.status === "error" ? /* @__PURE__ */ jsx11(CircleAlert, { className: iconClass, "aria-hidden": "true" }) : toolCall.status === "cancelled" ? /* @__PURE__ */ jsx11(X, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "WebSearch" || normalizedName === "WebFetch" ? /* @__PURE__ */ jsx11(Earth, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Bash" || normalizedName === "BgBash" ? /* @__PURE__ */ jsx11(Terminal, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Write" || normalizedName === "Edit" || normalizedName === "MultiEdit" ? /* @__PURE__ */ jsx11(FilePenLine, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Read" || normalizedName === "ReadSkill" || normalizedName === "get_skill_content" ? /* @__PURE__ */ jsx11(BookOpen, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Grep" || normalizedName === "Glob" || normalizedName === "search_skills" ? /* @__PURE__ */ jsx11(Search, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Agent" ? /* @__PURE__ */ jsx11(Bot, { className: iconClass, "aria-hidden": "true" }) : /* @__PURE__ */ jsx11(Wrench, { className: iconClass, "aria-hidden": "true" });
2878
+ const icon = toolCall.status === "pending" ? /* @__PURE__ */ jsx11(LoaderCircle, { className: cn(iconClass, "animate-spin"), "aria-hidden": "true" }) : toolCall.status === "error" ? /* @__PURE__ */ jsx11(CircleAlert, { className: iconClass, "aria-hidden": "true" }) : toolCall.status === "cancelled" ? /* @__PURE__ */ jsx11(X, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "WebSearch" || normalizedName === "WebFetch" ? /* @__PURE__ */ jsx11(Earth, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Bash" || normalizedName === "BgBash" ? /* @__PURE__ */ jsx11(Terminal, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Write" || normalizedName === "Edit" || normalizedName === "MultiEdit" ? /* @__PURE__ */ jsx11(FilePenLine, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Read" || normalizedName === "ReadSkill" ? /* @__PURE__ */ jsx11(BookOpen, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Grep" || normalizedName === "Glob" || normalizedName === "search_skills" ? /* @__PURE__ */ jsx11(Search, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "get_skill_content" ? /* @__PURE__ */ jsx11(BookOpen, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Agent" ? /* @__PURE__ */ jsx11(Bot, { className: iconClass, "aria-hidden": "true" }) : /* @__PURE__ */ jsx11(Wrench, { className: iconClass, "aria-hidden": "true" });
2823
2879
  const rowClassName = cn(
2824
2880
  "flex min-w-0 items-center gap-1 py-1.5 text-xs leading-[22px]",
2825
2881
  failed ? "text-red-500" : "text-[hsl(var(--muted-foreground))]"
2826
2882
  );
2827
2883
  if (!filePath) {
2828
- return /* @__PURE__ */ jsx11("div", { "data-testid": "execution-tool-intent", className: rowClassName, children: icon });
2884
+ return /* @__PURE__ */ jsxs9("div", { "data-testid": "execution-tool-intent", className: rowClassName, title: label, children: [
2885
+ icon,
2886
+ /* @__PURE__ */ jsx11("span", { className: "min-w-0 truncate", children: label })
2887
+ ] });
2829
2888
  }
2830
2889
  return /* @__PURE__ */ jsxs9("div", { className: "min-w-0", children: [
2831
2890
  /* @__PURE__ */ jsxs9(
@@ -2834,15 +2893,34 @@ function ExecutionToolRow({ toolCall }) {
2834
2893
  type: "button",
2835
2894
  "data-testid": "execution-tool-intent",
2836
2895
  className: cn(rowClassName, "w-full text-left"),
2896
+ title: label,
2837
2897
  "aria-expanded": fileOpen,
2838
2898
  onClick: () => setFileOpen((open) => !open),
2839
2899
  children: [
2840
2900
  icon,
2841
- /* @__PURE__ */ jsx11(ChevronRight, { size: 14, className: cn("shrink-0 transition-transform", fileOpen && "rotate-90"), "aria-hidden": "true" })
2901
+ /* @__PURE__ */ jsx11("span", { className: "min-w-0 truncate", children: label }),
2902
+ /* @__PURE__ */ jsx11(
2903
+ ChevronRight,
2904
+ {
2905
+ size: 14,
2906
+ className: cn("shrink-0 transition-transform", fileOpen && "rotate-90"),
2907
+ "aria-hidden": "true"
2908
+ }
2909
+ )
2842
2910
  ]
2843
2911
  }
2844
2912
  ),
2845
- fileOpen ? /* @__PURE__ */ jsx11("div", { className: "ml-[18px] truncate text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", title: filePath, children: filePath }) : null
2913
+ fileOpen ? /* @__PURE__ */ jsxs9(
2914
+ "div",
2915
+ {
2916
+ className: "ml-[18px] truncate text-xs leading-[22px] text-[hsl(var(--muted-foreground))]",
2917
+ title: filePath,
2918
+ children: [
2919
+ "\u6587\u4EF6\uFF1A",
2920
+ filePath
2921
+ ]
2922
+ }
2923
+ ) : null
2846
2924
  ] });
2847
2925
  }
2848
2926
  function AssistantTurnBlock({
@@ -2897,145 +2975,132 @@ function AssistantTurnBlock({
2897
2975
  }, [hasLiveStartTime, isStreaming]);
2898
2976
  const liveExecutionDurationMs = isStreaming ? getExecutionDurationMs({ messages, isStreaming, now: clock }) : executionDurationMs;
2899
2977
  if (!hasExecutionProcess) {
2900
- return /* @__PURE__ */ jsxs9(
2901
- "div",
2902
- {
2903
- "aria-busy": isStreaming || void 0,
2904
- className: "blade-chat-assistant-turn flex flex-col gap-3",
2905
- children: [
2906
- hasInterrupted && /* @__PURE__ */ jsx11("div", { className: "ml-4 w-fit rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300", children: "\u5DF2\u4E2D\u65AD" }),
2907
- hasFailedWithoutContent && /* @__PURE__ */ jsx11("div", { className: "ml-4 w-fit rounded-full border border-red-500/30 bg-red-500/10 px-2.5 py-1 text-[10px] font-medium text-red-400", children: "\u751F\u6210\u5931\u8D25" }),
2908
- messages.map((message, index) => {
2909
- return hasRenderableMessageContent(message) ? /* @__PURE__ */ jsx11(
2910
- "div",
2911
- {
2912
- className: "flex flex-col gap-3",
2913
- children: /* @__PURE__ */ jsx11(
2914
- AssistantMessageContent,
2915
- {
2916
- message,
2917
- sessionId,
2918
- streaming: isStreaming && index === messages.length - 1
2919
- }
2920
- )
2921
- },
2922
- message.entry_id ?? `${message.timestamp ?? "assistant"}-${index}`
2923
- ) : null;
2924
- })
2925
- ]
2926
- }
2927
- );
2928
- }
2929
- return /* @__PURE__ */ jsxs9(
2930
- "div",
2931
- {
2932
- "aria-busy": isStreaming || void 0,
2933
- className: "blade-chat-assistant-turn flex flex-col gap-3",
2934
- children: [
2935
- hasInterrupted && /* @__PURE__ */ jsx11("div", { className: "ml-4 w-fit rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300", children: "\u5DF2\u4E2D\u65AD" }),
2936
- hasFailedWithoutContent && /* @__PURE__ */ jsx11("div", { className: "ml-4 w-fit rounded-full border border-red-500/30 bg-red-500/10 px-2.5 py-1 text-[10px] font-medium text-red-400", children: "\u751F\u6210\u5931\u8D25" }),
2937
- /* @__PURE__ */ jsxs9("div", { className: "flex w-full items-start gap-2.5", children: [
2938
- /* @__PURE__ */ jsx11(
2939
- "span",
2940
- {
2941
- className: "grid size-[30px] shrink-0 place-items-center rounded-full bg-[hsl(var(--muted)/0.55)] text-[hsl(var(--foreground))]",
2942
- "aria-hidden": "true",
2943
- children: /* @__PURE__ */ jsx11(Bot, { size: 16 })
2944
- }
2945
- ),
2946
- /* @__PURE__ */ jsxs9("div", { className: "min-w-0 flex-1 pt-0.5", children: [
2947
- /* @__PURE__ */ jsxs9(
2948
- "button",
2978
+ return /* @__PURE__ */ jsxs9("div", { className: "blade-chat-assistant-turn flex flex-col gap-3", children: [
2979
+ hasInterrupted && /* @__PURE__ */ jsx11("div", { className: "ml-4 w-fit rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300", children: "\u5DF2\u4E2D\u65AD" }),
2980
+ hasFailedWithoutContent && /* @__PURE__ */ jsx11("div", { className: "ml-4 w-fit rounded-full border border-red-500/30 bg-red-500/10 px-2.5 py-1 text-[10px] font-medium text-red-400", children: "\u751F\u6210\u5931\u8D25" }),
2981
+ messages.map((message, index) => {
2982
+ return hasRenderableMessageContent(message) ? /* @__PURE__ */ jsx11(
2983
+ "div",
2984
+ {
2985
+ className: "flex flex-col gap-3",
2986
+ children: /* @__PURE__ */ jsx11(
2987
+ AssistantMessageContent,
2949
2988
  {
2950
- type: "button",
2951
- onClick: () => {
2952
- userSelectedDisplayModeRef.current = true;
2953
- setDisplayMode(displayMode === "detail" ? "compact" : "detail");
2954
- },
2955
- "aria-expanded": effectiveMode === "detail",
2956
- "aria-label": effectiveMode === "detail" ? "\u6536\u8D77\u6267\u884C\u8FC7\u7A0B" : "\u5C55\u5F00\u6267\u884C\u8FC7\u7A0B",
2957
- "data-testid": "assistant-execution-summary",
2958
- className: "inline-flex min-w-0 max-w-full select-none items-center gap-1 bg-transparent p-0 text-left text-xs leading-[22px] text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
2959
- children: [
2960
- /* @__PURE__ */ jsx11("span", { className: "min-w-0 truncate", children: executionSummaryLabel({
2961
- messages,
2962
- isStreaming,
2963
- durationMs: liveExecutionDurationMs,
2964
- sessionStatus,
2965
- askAnswers
2966
- }) }),
2967
- /* @__PURE__ */ jsx11(
2968
- ChevronRight,
2969
- {
2970
- size: 14,
2971
- className: cn(
2972
- "shrink-0 transition-transform duration-300",
2973
- effectiveMode === "detail" && "rotate-90"
2974
- ),
2975
- "aria-hidden": "true"
2976
- }
2977
- )
2978
- ]
2989
+ message,
2990
+ sessionId,
2991
+ streaming: isStreaming && index === messages.length - 1
2979
2992
  }
2980
- ),
2981
- /* @__PURE__ */ jsx11("div", { className: "mt-3 h-px w-full bg-[hsl(var(--border)/0.75)]" })
2982
- ] })
2983
- ] }),
2984
- effectiveMode === "detail" ? /* @__PURE__ */ jsx11("div", { className: "ml-10 flex flex-col gap-3 pt-1", children: messages.map((message, index) => {
2985
- const isLast = index === messages.length - 1;
2986
- const streamingThis = isStreaming && isLast;
2987
- const text = getMessageText(message);
2988
- const toolCalls = (message.tool_calls ?? []).filter(
2989
- (toolCall) => formatToolName(toolCall.name) !== "AskUserQuestion"
2990
- );
2991
- const showReasoning = !!message.reasoning && isStreaming && index === latestReasoningIndex;
2992
- return /* @__PURE__ */ jsxs9(
2993
- "div",
2994
- {
2995
- className: "flex flex-col gap-3",
2996
- children: [
2997
- showReasoning && message.reasoning ? /* @__PURE__ */ jsx11(ThinkingBlock, { reasoning: message.reasoning, isStreaming: streamingThis && !text }) : null,
2998
- hasRenderableMessageContent(message) && message !== finalMessage ? /* @__PURE__ */ jsx11(
2999
- AssistantMessageContent,
3000
- {
3001
- message,
3002
- sessionId,
3003
- streaming: streamingThis,
3004
- compact: true
3005
- }
3006
- ) : null,
3007
- toolCalls.length > 0 ? /* @__PURE__ */ jsx11("div", { className: "flex flex-col gap-0.5", children: toolCalls.map((toolCall) => {
3008
- const custom = toolCallRenderer?.(toolCall);
3009
- return custom !== null && custom !== void 0 ? /* @__PURE__ */ jsx11("div", { children: custom }, toolCall.id) : formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx11(AgentLoopBlock, { toolCall }, toolCall.id) : /* @__PURE__ */ jsx11(ExecutionToolRow, { toolCall }, toolCall.id);
3010
- }) }) : null
3011
- ]
3012
- },
3013
- message.entry_id ?? `${message.timestamp ?? "assistant"}-${index}`
3014
- );
3015
- }) }) : null,
3016
- finalMessage ? /* @__PURE__ */ jsx11("div", { className: "ml-10", children: /* @__PURE__ */ jsx11(
3017
- AssistantMessageContent,
2993
+ )
2994
+ },
2995
+ message.entry_id ?? `${message.timestamp ?? "assistant"}-${index}`
2996
+ ) : null;
2997
+ }),
2998
+ isStreaming && !finalMessage ? /* @__PURE__ */ jsx11(Shimmer, { className: "ml-4", children: "\u6B63\u5728\u751F\u6210..." }) : null
2999
+ ] });
3000
+ }
3001
+ return /* @__PURE__ */ jsxs9("div", { className: "blade-chat-assistant-turn flex flex-col gap-3", children: [
3002
+ hasInterrupted && /* @__PURE__ */ jsx11("div", { className: "ml-4 w-fit rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300", children: "\u5DF2\u4E2D\u65AD" }),
3003
+ hasFailedWithoutContent && /* @__PURE__ */ jsx11("div", { className: "ml-4 w-fit rounded-full border border-red-500/30 bg-red-500/10 px-2.5 py-1 text-[10px] font-medium text-red-400", children: "\u751F\u6210\u5931\u8D25" }),
3004
+ /* @__PURE__ */ jsxs9("div", { className: "flex w-full items-start gap-2.5", children: [
3005
+ /* @__PURE__ */ jsx11(
3006
+ "span",
3007
+ {
3008
+ className: "grid size-[30px] shrink-0 place-items-center rounded-full bg-[hsl(var(--muted)/0.55)] text-[hsl(var(--foreground))]",
3009
+ "aria-hidden": "true",
3010
+ children: /* @__PURE__ */ jsx11(Bot, { size: 16 })
3011
+ }
3012
+ ),
3013
+ /* @__PURE__ */ jsxs9("div", { className: "min-w-0 flex-1 pt-0.5", children: [
3014
+ /* @__PURE__ */ jsxs9(
3015
+ "button",
3018
3016
  {
3019
- message: finalMessage,
3020
- sessionId,
3021
- streaming: isStreaming && finalMessage === messages[messages.length - 1]
3017
+ type: "button",
3018
+ onClick: () => {
3019
+ userSelectedDisplayModeRef.current = true;
3020
+ setDisplayMode(displayMode === "detail" ? "compact" : "detail");
3021
+ },
3022
+ "aria-expanded": effectiveMode === "detail",
3023
+ "aria-label": effectiveMode === "detail" ? "\u6536\u8D77\u6267\u884C\u8FC7\u7A0B" : "\u5C55\u5F00\u6267\u884C\u8FC7\u7A0B",
3024
+ "data-testid": "assistant-execution-summary",
3025
+ className: "inline-flex min-w-0 max-w-full select-none items-center gap-1 bg-transparent p-0 text-left text-xs leading-[22px] text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
3026
+ children: [
3027
+ /* @__PURE__ */ jsx11("span", { className: "min-w-0 truncate", children: executionSummaryLabel({
3028
+ messages,
3029
+ isStreaming,
3030
+ durationMs: liveExecutionDurationMs,
3031
+ sessionStatus,
3032
+ askAnswers
3033
+ }) }),
3034
+ /* @__PURE__ */ jsx11(
3035
+ ChevronRight,
3036
+ {
3037
+ size: 14,
3038
+ className: cn(
3039
+ "shrink-0 transition-transform duration-300",
3040
+ effectiveMode === "detail" && "rotate-90"
3041
+ ),
3042
+ "aria-hidden": "true"
3043
+ }
3044
+ )
3045
+ ]
3022
3046
  }
3023
- ) }) : null,
3024
- questionToolCalls.map((toolCall) => /* @__PURE__ */ jsx11(
3025
- ToolCallBlock,
3026
- {
3027
- toolCall,
3028
- answerData: askAnswers?.[toolCall.id],
3029
- onAnswer,
3030
- answered: sessionStatus !== "waiting_for_input",
3031
- sessionStatus,
3032
- renderer: toolCallRenderer
3033
- },
3034
- toolCall.id
3035
- ))
3036
- ]
3037
- }
3038
- );
3047
+ ),
3048
+ /* @__PURE__ */ jsx11("div", { className: "mt-3 h-px w-full bg-[hsl(var(--border)/0.75)]" })
3049
+ ] })
3050
+ ] }),
3051
+ effectiveMode === "detail" ? /* @__PURE__ */ jsx11("div", { className: "ml-10 flex flex-col gap-3 pt-1", children: messages.map((message, index) => {
3052
+ const isLast = index === messages.length - 1;
3053
+ const streamingThis = isStreaming && isLast;
3054
+ const text = getMessageText(message);
3055
+ const toolCalls = (message.tool_calls ?? []).filter(
3056
+ (toolCall) => formatToolName(toolCall.name) !== "AskUserQuestion"
3057
+ );
3058
+ const showReasoning = !!message.reasoning && (!isStreaming || index === latestReasoningIndex);
3059
+ return /* @__PURE__ */ jsxs9(
3060
+ "div",
3061
+ {
3062
+ className: "flex flex-col gap-3",
3063
+ children: [
3064
+ showReasoning && message.reasoning ? /* @__PURE__ */ jsx11(ThinkingBlock, { reasoning: message.reasoning, isStreaming: streamingThis && !text }) : null,
3065
+ hasRenderableMessageContent(message) && message !== finalMessage ? /* @__PURE__ */ jsx11(
3066
+ AssistantMessageContent,
3067
+ {
3068
+ message,
3069
+ sessionId,
3070
+ streaming: streamingThis,
3071
+ compact: true
3072
+ }
3073
+ ) : null,
3074
+ toolCalls.length > 0 ? /* @__PURE__ */ jsx11("div", { className: "flex flex-col gap-0.5", children: toolCalls.map((toolCall) => {
3075
+ const custom = toolCallRenderer?.(toolCall);
3076
+ return custom !== null && custom !== void 0 ? /* @__PURE__ */ jsx11("div", { children: custom }, toolCall.id) : formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx11(AgentLoopBlock, { toolCall }, toolCall.id) : /* @__PURE__ */ jsx11(ExecutionToolRow, { toolCall }, toolCall.id);
3077
+ }) }) : null
3078
+ ]
3079
+ },
3080
+ message.entry_id ?? `${message.timestamp ?? "assistant"}-${index}`
3081
+ );
3082
+ }) }) : null,
3083
+ finalMessage ? /* @__PURE__ */ jsx11("div", { className: "ml-10", children: /* @__PURE__ */ jsx11(
3084
+ AssistantMessageContent,
3085
+ {
3086
+ message: finalMessage,
3087
+ sessionId,
3088
+ streaming: isStreaming && finalMessage === messages[messages.length - 1]
3089
+ }
3090
+ ) }) : null,
3091
+ questionToolCalls.map((toolCall) => /* @__PURE__ */ jsx11(
3092
+ ToolCallBlock,
3093
+ {
3094
+ toolCall,
3095
+ answerData: askAnswers?.[toolCall.id],
3096
+ onAnswer,
3097
+ answered: sessionStatus !== "waiting_for_input",
3098
+ sessionStatus,
3099
+ renderer: toolCallRenderer
3100
+ },
3101
+ toolCall.id
3102
+ ))
3103
+ ] });
3039
3104
  }
3040
3105
  function AssistantMessageContent({
3041
3106
  message,
@@ -3764,104 +3829,101 @@ function MessageList({
3764
3829
  }
3765
3830
  return blocks;
3766
3831
  }, [messages, isStreaming]);
3767
- return /* @__PURE__ */ jsxs14("div", { className: cn("blade-chat-messages relative min-h-0 flex-1", className), children: [
3768
- isStreaming ? /* @__PURE__ */ jsx16("output", { className: "sr-only", children: "\u6B63\u5728\u751F\u6210\u56DE\u590D" }) : null,
3769
- /* @__PURE__ */ jsxs14(
3770
- StickToBottom,
3771
- {
3772
- className: "h-full overflow-y-hidden",
3773
- initial: "instant",
3774
- resize: "instant",
3775
- children: [
3776
- /* @__PURE__ */ jsx16(StickToBottom.Content, { className: "blade-chat-messages-scroll", children: /* @__PURE__ */ jsx16("div", { className: "blade-chat-messages-content mx-auto max-w-[748px]", children: /* @__PURE__ */ jsxs14("div", { className: "flex min-w-0 flex-col", children: [
3777
- renderBlocks.length === 0 ? emptyState ?? /* @__PURE__ */ jsxs14("div", { className: "blade-chat-empty", children: [
3778
- /* @__PURE__ */ jsx16(MessageSquare, { size: 40, strokeWidth: 1.5 }),
3779
- /* @__PURE__ */ jsx16("span", { className: "text-base font-medium", children: "\u5F00\u59CB\u5BF9\u8BDD" }),
3780
- /* @__PURE__ */ jsx16("span", { className: "text-sm opacity-60", children: "\u5728\u4E0B\u65B9\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u804A\u5929" })
3781
- ] }) : renderBlocks.map((block) => {
3782
- if (block.type === "message") {
3783
- return /* @__PURE__ */ jsx16("div", { "data-entry-id": block.message.entry_id, children: isUserMessage(block.message) ? /* @__PURE__ */ jsx16(UserMessageBubble, { message: block.message }) : isErrorMessage(block.message) ? /* @__PURE__ */ jsx16(ErrorMessageBlock, { message: block.message }) : null }, block.key);
3784
- }
3785
- if (block.type === "assistant_turn") {
3786
- const blockFeedback = block.messages.map(
3787
- (message) => message.entry_id ? resultFeedbackByEntry.get(message.entry_id) : void 0
3788
- ).find((feedback) => feedback != null);
3789
- const hasActiveFollowup = Boolean(
3790
- postChatFollowup && block.messages.some(
3791
- (message) => message.entry_id === postChatFollowup.assistant_entry_id
3792
- )
3793
- );
3794
- return /* @__PURE__ */ jsx16("div", { "data-entry-id": block.messages[0]?.entry_id, children: /* @__PURE__ */ jsxs14(
3795
- RenderErrorBoundary,
3796
- {
3797
- label: "\u52A9\u624B\u6D88\u606F",
3798
- details: block.key,
3799
- resetKey: getMessageResetSignature(block.messages),
3800
- children: [
3801
- /* @__PURE__ */ jsx16(
3802
- AssistantTurnBlock,
3803
- {
3804
- messages: block.messages,
3805
- isStreaming: block.isStreaming,
3806
- askAnswers,
3807
- onAnswer,
3808
- sessionStatus,
3809
- toolCallRenderer,
3810
- sessionId
3811
- }
3812
- ),
3813
- blockFeedback && !hasActiveFollowup ? /* @__PURE__ */ jsx16(HistoricalResultFeedback, { feedback: blockFeedback }) : null,
3814
- hasActiveFollowup && postChatFollowup ? /* @__PURE__ */ jsx16(
3815
- PostChatFollowupBlock,
3816
- {
3817
- followup: postChatFollowup,
3818
- sessionId,
3819
- onSuggestion,
3820
- isViewer,
3821
- onInteraction: onFollowupInteraction,
3822
- savedFeedback: blockFeedback,
3823
- onFeedbackSaved: onResultFeedbackSaved
3824
- }
3825
- ) : null
3826
- ]
3827
- }
3828
- ) }, block.key);
3829
- }
3830
- if (block.type === "context") {
3831
- return /* @__PURE__ */ jsx16("div", { "data-entry-id": block.message.entry_id, children: /* @__PURE__ */ jsx16(ContextCard, { context: block.message.context }) }, block.key);
3832
- }
3833
- if (block.type === "compaction") {
3834
- return /* @__PURE__ */ jsxs14(
3835
- "div",
3836
- {
3837
- className: "flex items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]",
3838
- children: [
3839
- /* @__PURE__ */ jsx16(Layers, { size: 12 }),
3840
- /* @__PURE__ */ jsx16("span", { children: "\u4E0A\u4E0B\u6587\u5DF2\u538B\u7F29" })
3841
- ]
3842
- },
3843
- block.key
3844
- );
3845
- }
3846
- return /* @__PURE__ */ jsx16(PlanningDivider, { kind: block.kind }, block.key);
3847
- }),
3848
- sessionStatus === "interrupted" && !isStreaming ? /* @__PURE__ */ jsx16("div", { className: "flex", children: /* @__PURE__ */ jsx16("div", { className: "rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300", children: "\u5DF2\u4E2D\u65AD" }) }) : null
3849
- ] }) }) }),
3850
- /* @__PURE__ */ jsx16(
3851
- PinLatestUserMessage,
3852
- {
3853
- userMessageCount: userMessages.length,
3854
- shouldPinLatestUser,
3855
- targetKey: latestUserMessage?.render_id ?? latestUserMessage?.entry_id ?? (latestUserMessage ? `user:${userMessages.length}` : null)
3856
- },
3857
- sessionId ?? "no-session"
3858
- ),
3859
- /* @__PURE__ */ jsx16(ScrollToBottomButton, {})
3860
- ]
3861
- },
3862
- sessionId ?? "no-session"
3863
- )
3864
- ] });
3832
+ return /* @__PURE__ */ jsx16("div", { className: cn("blade-chat-messages relative min-h-0 flex-1", className), children: /* @__PURE__ */ jsxs14(
3833
+ StickToBottom,
3834
+ {
3835
+ className: "h-full overflow-y-hidden",
3836
+ initial: "instant",
3837
+ resize: "instant",
3838
+ children: [
3839
+ /* @__PURE__ */ jsx16(StickToBottom.Content, { className: "blade-chat-messages-scroll", children: /* @__PURE__ */ jsx16("div", { className: "blade-chat-messages-content mx-auto max-w-[748px]", children: /* @__PURE__ */ jsxs14("div", { className: "flex min-w-0 flex-col", children: [
3840
+ renderBlocks.length === 0 ? emptyState ?? /* @__PURE__ */ jsxs14("div", { className: "blade-chat-empty", children: [
3841
+ /* @__PURE__ */ jsx16(MessageSquare, { size: 40, strokeWidth: 1.5 }),
3842
+ /* @__PURE__ */ jsx16("span", { className: "text-base font-medium", children: "\u5F00\u59CB\u5BF9\u8BDD" }),
3843
+ /* @__PURE__ */ jsx16("span", { className: "text-sm opacity-60", children: "\u5728\u4E0B\u65B9\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u804A\u5929" })
3844
+ ] }) : renderBlocks.map((block) => {
3845
+ if (block.type === "message") {
3846
+ return /* @__PURE__ */ jsx16("div", { "data-entry-id": block.message.entry_id, children: isUserMessage(block.message) ? /* @__PURE__ */ jsx16(UserMessageBubble, { message: block.message }) : isErrorMessage(block.message) ? /* @__PURE__ */ jsx16(ErrorMessageBlock, { message: block.message }) : null }, block.key);
3847
+ }
3848
+ if (block.type === "assistant_turn") {
3849
+ const blockFeedback = block.messages.map(
3850
+ (message) => message.entry_id ? resultFeedbackByEntry.get(message.entry_id) : void 0
3851
+ ).find((feedback) => feedback != null);
3852
+ const hasActiveFollowup = Boolean(
3853
+ postChatFollowup && block.messages.some(
3854
+ (message) => message.entry_id === postChatFollowup.assistant_entry_id
3855
+ )
3856
+ );
3857
+ return /* @__PURE__ */ jsx16("div", { "data-entry-id": block.messages[0]?.entry_id, children: /* @__PURE__ */ jsxs14(
3858
+ RenderErrorBoundary,
3859
+ {
3860
+ label: "\u52A9\u624B\u6D88\u606F",
3861
+ details: block.key,
3862
+ resetKey: getMessageResetSignature(block.messages),
3863
+ children: [
3864
+ /* @__PURE__ */ jsx16(
3865
+ AssistantTurnBlock,
3866
+ {
3867
+ messages: block.messages,
3868
+ isStreaming: block.isStreaming,
3869
+ askAnswers,
3870
+ onAnswer,
3871
+ sessionStatus,
3872
+ toolCallRenderer,
3873
+ sessionId
3874
+ }
3875
+ ),
3876
+ blockFeedback && !hasActiveFollowup ? /* @__PURE__ */ jsx16(HistoricalResultFeedback, { feedback: blockFeedback }) : null,
3877
+ hasActiveFollowup && postChatFollowup ? /* @__PURE__ */ jsx16(
3878
+ PostChatFollowupBlock,
3879
+ {
3880
+ followup: postChatFollowup,
3881
+ sessionId,
3882
+ onSuggestion,
3883
+ isViewer,
3884
+ onInteraction: onFollowupInteraction,
3885
+ savedFeedback: blockFeedback,
3886
+ onFeedbackSaved: onResultFeedbackSaved
3887
+ }
3888
+ ) : null
3889
+ ]
3890
+ }
3891
+ ) }, block.key);
3892
+ }
3893
+ if (block.type === "context") {
3894
+ return /* @__PURE__ */ jsx16("div", { "data-entry-id": block.message.entry_id, children: /* @__PURE__ */ jsx16(ContextCard, { context: block.message.context }) }, block.key);
3895
+ }
3896
+ if (block.type === "compaction") {
3897
+ return /* @__PURE__ */ jsxs14(
3898
+ "div",
3899
+ {
3900
+ className: "flex items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]",
3901
+ children: [
3902
+ /* @__PURE__ */ jsx16(Layers, { size: 12 }),
3903
+ /* @__PURE__ */ jsx16("span", { children: "\u4E0A\u4E0B\u6587\u5DF2\u538B\u7F29" })
3904
+ ]
3905
+ },
3906
+ block.key
3907
+ );
3908
+ }
3909
+ return /* @__PURE__ */ jsx16(PlanningDivider, { kind: block.kind }, block.key);
3910
+ }),
3911
+ sessionStatus === "interrupted" && !isStreaming ? /* @__PURE__ */ jsx16("div", { className: "flex", children: /* @__PURE__ */ jsx16("div", { className: "rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300", children: "\u5DF2\u4E2D\u65AD" }) }) : null
3912
+ ] }) }) }),
3913
+ /* @__PURE__ */ jsx16(
3914
+ PinLatestUserMessage,
3915
+ {
3916
+ userMessageCount: userMessages.length,
3917
+ shouldPinLatestUser,
3918
+ targetKey: latestUserMessage?.render_id ?? latestUserMessage?.entry_id ?? (latestUserMessage ? `user:${userMessages.length}` : null)
3919
+ },
3920
+ sessionId ?? "no-session"
3921
+ ),
3922
+ /* @__PURE__ */ jsx16(ScrollToBottomButton, {})
3923
+ ]
3924
+ },
3925
+ sessionId ?? "no-session"
3926
+ ) });
3865
3927
  }
3866
3928
  function PinLatestUserMessage({
3867
3929
  userMessageCount,
@@ -4492,48 +4554,6 @@ function ChatView(props) {
4492
4554
  return /* @__PURE__ */ jsx21(AgentChat, { ...rest });
4493
4555
  }
4494
4556
 
4495
- // src/lib/agent-computer-command.ts
4496
- var COMPUTER_LAUNCH_COMMAND_PATTERN = /(?:^|[\n;&|(]\s*)computer\s+launch(?:\s|$)/;
4497
- function isAgentComputerCommand(command) {
4498
- return COMPUTER_LAUNCH_COMMAND_PATTERN.test(command);
4499
- }
4500
- function isAgentComputerToolCall(argumentsJson) {
4501
- if (!argumentsJson) return false;
4502
- let command;
4503
- try {
4504
- const parsed = JSON.parse(argumentsJson);
4505
- if (typeof parsed !== "object" || parsed === null) return false;
4506
- command = parsed.command;
4507
- } catch {
4508
- return false;
4509
- }
4510
- return typeof command === "string" && isAgentComputerCommand(command);
4511
- }
4512
- var LAUNCH_SUCCESS_MARKER = "\u5DF2\u542F\u52A8 ";
4513
- function resultContainsLaunchSuccessMarker(result, depth = 0) {
4514
- if (depth > 2) return false;
4515
- if (typeof result === "string") {
4516
- if (result.includes(LAUNCH_SUCCESS_MARKER)) return true;
4517
- try {
4518
- return resultContainsLaunchSuccessMarker(JSON.parse(result), depth + 1);
4519
- } catch {
4520
- return false;
4521
- }
4522
- }
4523
- if (typeof result === "object" && result !== null) {
4524
- for (const value of Object.values(result)) {
4525
- if (typeof value === "string" && value.includes(LAUNCH_SUCCESS_MARKER)) return true;
4526
- }
4527
- }
4528
- return false;
4529
- }
4530
- function classifyAgentComputerLaunchOutcome(toolCall) {
4531
- if (toolCall.status === "error" || toolCall.status === "cancelled") return "failed";
4532
- if (toolCall.status !== "done") return "pending";
4533
- if (toolCall.result === void 0 || toolCall.result === null) return "unknown";
4534
- return resultContainsLaunchSuccessMarker(toolCall.result) ? "succeeded" : "failed";
4535
- }
4536
-
4537
4557
  // src/index.ts
4538
4558
  export * from "@blade-hq/agent-client";
4539
4559
  export {
@@ -4545,9 +4565,6 @@ export {
4545
4565
  MarkdownContent,
4546
4566
  ReplayBar,
4547
4567
  ReplayMismatchPrompt,
4548
- classifyAgentComputerLaunchOutcome,
4549
- isAgentComputerCommand,
4550
- isAgentComputerToolCall,
4551
4568
  useAgentSession,
4552
4569
  useBladeClient,
4553
4570
  useLlmChat,