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

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,7 +1831,6 @@ var TOOL_NAME_ALIASES = {
1831
1831
  finish_task: "FinishTask",
1832
1832
  glob: "Glob",
1833
1833
  grep: "Grep",
1834
- kb_search: "KbSearch",
1835
1834
  ls: "Ls",
1836
1835
  multi_edit: "MultiEdit",
1837
1836
  read: "Read",
@@ -1850,7 +1849,6 @@ var TOOL_DISPLAY_LABELS = {
1850
1849
  Ls: "\u5217\u51FA\u76EE\u5F55",
1851
1850
  Glob: "\u5339\u914D\u6587\u4EF6",
1852
1851
  Grep: "\u641C\u7D22\u6587\u672C",
1853
- KbSearch: "\u68C0\u7D22\u77E5\u8BC6\u5E93",
1854
1852
  WebSearch: "\u641C\u7D22\u7F51\u9875",
1855
1853
  WebFetch: "\u6574\u7406\u7F51\u9875\u5185\u5BB9",
1856
1854
  Agent: "\u6D3E\u751F\u5B50\u667A\u80FD\u4F53",
@@ -2690,6 +2688,7 @@ function buildAskUserPayload(argumentsJson) {
2690
2688
  import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2691
2689
  function ThinkingBlock({ reasoning, isStreaming }) {
2692
2690
  const [open, setOpen] = useState10(false);
2691
+ if (!isStreaming) return null;
2693
2692
  return /* @__PURE__ */ jsxs9("div", { className: "blade-chat-thinking text-xs", children: [
2694
2693
  /* @__PURE__ */ jsxs9(
2695
2694
  "button",
@@ -2699,7 +2698,7 @@ function ThinkingBlock({ reasoning, isStreaming }) {
2699
2698
  "aria-expanded": open,
2700
2699
  className: "group/thinking inline-flex items-center gap-1 text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
2701
2700
  children: [
2702
- isStreaming ? /* @__PURE__ */ jsx11(Shimmer, { className: "text-xs", children: "\u6B63\u5728\u601D\u8003" }) : /* @__PURE__ */ jsx11("span", { children: "\u5DF2\u601D\u8003" }),
2701
+ /* @__PURE__ */ jsx11(Shimmer, { className: "text-xs", children: "\u6B63\u5728\u601D\u8003" }),
2703
2702
  /* @__PURE__ */ jsx11(
2704
2703
  ChevronRight,
2705
2704
  {
@@ -2713,7 +2712,7 @@ function ThinkingBlock({ reasoning, isStreaming }) {
2713
2712
  ]
2714
2713
  }
2715
2714
  ),
2716
- open && /* @__PURE__ */ jsx11("div", { className: "mt-1.5 whitespace-pre-wrap text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", children: reasoning })
2715
+ open ? /* @__PURE__ */ jsx11("div", { className: "mt-1.5 whitespace-pre-wrap text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", children: reasoning }) : null
2717
2716
  ] });
2718
2717
  }
2719
2718
  function getMessageText(message) {
@@ -2811,63 +2810,8 @@ function executionSummaryLabel({
2811
2810
  }
2812
2811
  return completedLabel;
2813
2812
  }
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
- }
2866
2813
  function ExecutionToolRow({ toolCall }) {
2867
2814
  const normalizedName = formatToolName(toolCall.name);
2868
- const typeLabel = executionToolTypeLabel(toolCall);
2869
- const intent = executionToolIntent(toolCall);
2870
- const label = intent ? `${typeLabel}\uFF1A${intent}` : typeLabel;
2871
2815
  const failed = toolCall.status === "error" || toolCall.status === "cancelled";
2872
2816
  const filePath = toolCall.status === "done" && (normalizedName === "Write" || normalizedName === "Edit" || normalizedName === "MultiEdit") ? extractToolFilePath(toolCall) : null;
2873
2817
  const [fileOpen, setFileOpen] = useState10(false);
@@ -2875,16 +2819,13 @@ function ExecutionToolRow({ toolCall }) {
2875
2819
  "size-3.5 shrink-0",
2876
2820
  failed ? "text-red-500" : "text-[hsl(var(--muted-foreground))]"
2877
2821
  );
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" });
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" });
2879
2823
  const rowClassName = cn(
2880
2824
  "flex min-w-0 items-center gap-1 py-1.5 text-xs leading-[22px]",
2881
2825
  failed ? "text-red-500" : "text-[hsl(var(--muted-foreground))]"
2882
2826
  );
2883
2827
  if (!filePath) {
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
- ] });
2828
+ return /* @__PURE__ */ jsx11("div", { "data-testid": "execution-tool-intent", className: rowClassName, children: icon });
2888
2829
  }
2889
2830
  return /* @__PURE__ */ jsxs9("div", { className: "min-w-0", children: [
2890
2831
  /* @__PURE__ */ jsxs9(
@@ -2893,34 +2834,15 @@ function ExecutionToolRow({ toolCall }) {
2893
2834
  type: "button",
2894
2835
  "data-testid": "execution-tool-intent",
2895
2836
  className: cn(rowClassName, "w-full text-left"),
2896
- title: label,
2897
2837
  "aria-expanded": fileOpen,
2898
2838
  onClick: () => setFileOpen((open) => !open),
2899
2839
  children: [
2900
2840
  icon,
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
- )
2841
+ /* @__PURE__ */ jsx11(ChevronRight, { size: 14, className: cn("shrink-0 transition-transform", fileOpen && "rotate-90"), "aria-hidden": "true" })
2910
2842
  ]
2911
2843
  }
2912
2844
  ),
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
2845
+ fileOpen ? /* @__PURE__ */ jsx11("div", { className: "ml-[18px] truncate text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", title: filePath, children: filePath }) : null
2924
2846
  ] });
2925
2847
  }
2926
2848
  function AssistantTurnBlock({
@@ -2975,132 +2897,145 @@ function AssistantTurnBlock({
2975
2897
  }, [hasLiveStartTime, isStreaming]);
2976
2898
  const liveExecutionDurationMs = isStreaming ? getExecutionDurationMs({ messages, isStreaming, now: clock }) : executionDurationMs;
2977
2899
  if (!hasExecutionProcess) {
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,
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",
2988
2911
  {
2989
- message,
2990
- sessionId,
2991
- streaming: isStreaming && index === messages.length - 1
2992
- }
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
- ] });
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
+ );
3000
2928
  }
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",
3016
- {
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
- ]
3046
- }
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,
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",
3067
2949
  {
3068
- message,
3069
- sessionId,
3070
- streaming: streamingThis,
3071
- compact: true
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
+ ]
3072
2979
  }
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
- ] });
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,
3018
+ {
3019
+ message: finalMessage,
3020
+ sessionId,
3021
+ streaming: isStreaming && finalMessage === messages[messages.length - 1]
3022
+ }
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
+ );
3104
3039
  }
3105
3040
  function AssistantMessageContent({
3106
3041
  message,
@@ -3829,101 +3764,104 @@ function MessageList({
3829
3764
  }
3830
3765
  return blocks;
3831
3766
  }, [messages, isStreaming]);
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
- ) });
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
+ ] });
3927
3865
  }
3928
3866
  function PinLatestUserMessage({
3929
3867
  userMessageCount,
@@ -4554,6 +4492,48 @@ function ChatView(props) {
4554
4492
  return /* @__PURE__ */ jsx21(AgentChat, { ...rest });
4555
4493
  }
4556
4494
 
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
+
4557
4537
  // src/index.ts
4558
4538
  export * from "@blade-hq/agent-client";
4559
4539
  export {
@@ -4565,6 +4545,9 @@ export {
4565
4545
  MarkdownContent,
4566
4546
  ReplayBar,
4567
4547
  ReplayMismatchPrompt,
4548
+ classifyAgentComputerLaunchOutcome,
4549
+ isAgentComputerCommand,
4550
+ isAgentComputerToolCall,
4568
4551
  useAgentSession,
4569
4552
  useBladeClient,
4570
4553
  useLlmChat,