@blade-hq/agent-react 2610.0.0 → 2610.0.1

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.
@@ -1,5 +1,5 @@
1
1
  import type { AskUserAnswerData, ToolCallInfo } from "@blade-hq/agent-client";
2
- import { type ReactNode } from "react";
2
+ import type { ReactNode } from "react";
3
3
  import type { ChatViewClassNames, ChatViewRenderers } from "./ChatSurface";
4
4
  /** 接入方自定义渲染器:返回 null 时回落到默认渲染。 */
5
5
  export type ToolCallRenderer = (info: ToolCallInfo) => ReactNode | null;
@@ -37,5 +37,5 @@ export declare function resolveAskQuestionState({ toolStatus, hasAnswerData, fal
37
37
  * 极简工具调用块:状态 + 展示名一行,点开后是参数/结果的 <pre> 折叠展示。
38
38
  * AskUserQuestion 特殊处理为提问选项卡片。
39
39
  */
40
- export declare function ToolCallBlock({ toolCall, onAnswer, answered, answerData, sessionStatus, isActiveQuestion, classNames, renderers, }: Props): import("react/jsx-runtime").JSX.Element;
40
+ export declare function ToolCallBlock({ toolCall, onAnswer, answered, answerData, sessionStatus, isActiveQuestion, classNames, renderers, }: Props): import("react/jsx-runtime").JSX.Element | undefined;
41
41
  export {};
@@ -1,26 +1,4 @@
1
- import type { ToolCallInfo } from "@blade-hq/agent-client";
2
- export type ToolTone = "emerald" | "blue" | "amber" | "red";
3
- /**
4
- * 技能入口文件的所在目录就是技能名(`.agent/skills/<技能名>/SKILL.md`)。
5
- * 只显示 "SKILL.md" 用户看不出读的是哪个技能。
6
- *
7
- * 改这里必须同步 apps/web/src/agent/components/chat/display-utils.ts 的同名函数。
8
- */
9
- export declare function getSkillNameFromFilePath(filePath: string | null | undefined): string | null;
10
1
  /** 归一化工具名:去掉命名空间前缀并映射到别名表(如 "fork:Agent" → "Agent")。 */
11
2
  export declare function formatToolName(name: string): string;
12
- export declare function extractToolFilePath(toolCall: ToolCallInfo): string | null;
13
- /** 从文件类工具参数中提取全部可定位的文件路径(按出现顺序去重)。 */
14
- export declare function extractToolFilePaths(toolCall: ToolCallInfo): string[];
15
- /**
16
- * 返回工具调用的中文展示标签:优先取参数里的 description,
17
- * 其次取后端下发的 display_name / 系统工具中文名。
18
- */
19
- export declare function getToolDisplayLabel(toolCall: ToolCallInfo): string;
20
- export declare function getToolTone(status?: ToolCallInfo["status"]): ToolTone;
21
- export declare function getToolStatusLabel(status?: ToolCallInfo["status"]): string;
22
- export declare function formatToolDuration(ms: number): string;
23
- /** 参数 JSON 美化:无法解析时按原文展示。 */
24
- export declare function formatToolArgs(args: string): string;
25
3
  /** 工具结果的文本化 + 截断:长结果只在折叠面板里展示前若干字符。 */
26
4
  export declare function formatToolResult(result: unknown): string;
package/dist/index.js CHANGED
@@ -3412,7 +3412,7 @@ var X = createLucideIcon("X", [
3412
3412
  ]);
3413
3413
 
3414
3414
  // src/components/AgentChat.tsx
3415
- import { useCallback as useCallback30, useEffect as useEffect26, useMemo as useMemo18, useRef as useRef28, useState as useState36 } from "react";
3415
+ import { useCallback as useCallback30, useEffect as useEffect26, useMemo as useMemo18, useRef as useRef28, useState as useState35 } from "react";
3416
3416
 
3417
3417
  // src/components/SessionPluginSelector.tsx
3418
3418
  import { useEffect as useEffect14, useState as useState19 } from "react";
@@ -20758,50 +20758,6 @@ var TOOL_NAME_ALIASES = {
20758
20758
  web_search: "WebSearch",
20759
20759
  write: "Write"
20760
20760
  };
20761
- var TOOL_DISPLAY_LABELS = {
20762
- Bash: "\u6267\u884C\u547D\u4EE4",
20763
- BgBash: "\u540E\u53F0\u6267\u884C\u547D\u4EE4",
20764
- Read: "\u8BFB\u53D6\u6587\u4EF6",
20765
- Write: "\u5199\u5165\u6587\u4EF6",
20766
- Edit: "\u7F16\u8F91\u6587\u4EF6",
20767
- MultiEdit: "\u7F16\u8F91\u6587\u4EF6",
20768
- Ls: "\u5217\u51FA\u76EE\u5F55",
20769
- Glob: "\u5339\u914D\u6587\u4EF6",
20770
- Grep: "\u641C\u7D22\u6587\u672C",
20771
- KbSearch: "\u68C0\u7D22\u77E5\u8BC6\u5E93",
20772
- WebSearch: "\u641C\u7D22\u7F51\u9875",
20773
- WebFetch: "\u6574\u7406\u7F51\u9875\u5185\u5BB9",
20774
- Agent: "\u6D3E\u751F\u5B50\u667A\u80FD\u4F53",
20775
- AskUserQuestion: "\u5411\u7528\u6237\u63D0\u95EE",
20776
- ReadSkill: "\u8BFB\u53D6\u6280\u80FD",
20777
- FinishTask: "\u4EFB\u52A1\u5B8C\u6210",
20778
- ExitPlanMode: "\u63D0\u4EA4\u8BA1\u5212",
20779
- ListSessions: "\u5217\u51FA\u5386\u53F2\u4F1A\u8BDD",
20780
- GetSessionHistory: "\u8BFB\u53D6\u4F1A\u8BDD\u5386\u53F2"
20781
- };
20782
- function safeParseJson(value) {
20783
- if (!value) return null;
20784
- try {
20785
- return JSON.parse(value);
20786
- } catch {
20787
- return null;
20788
- }
20789
- }
20790
- function getStringArgValue(args, key) {
20791
- const value = args?.[key];
20792
- return typeof value === "string" ? value.trim() : "";
20793
- }
20794
- var SKILL_ENTRY_FILE_NAMES = /* @__PURE__ */ new Set(["skill.md", "command.md"]);
20795
- var NON_SKILL_DIR_NAMES = /* @__PURE__ */ new Set([".", "..", ".agent", ".agents", ".claude", "skill_data", "skills"]);
20796
- function getSkillNameFromFilePath(filePath) {
20797
- if (!filePath) return null;
20798
- const segments = filePath.split(/[\\/]+/).filter(Boolean);
20799
- const fileName = segments.pop();
20800
- if (!fileName || !SKILL_ENTRY_FILE_NAMES.has(fileName.toLowerCase())) return null;
20801
- const dirName = segments.pop();
20802
- if (!dirName || NON_SKILL_DIR_NAMES.has(dirName.toLowerCase())) return null;
20803
- return dirName;
20804
- }
20805
20761
  function formatToolName(name) {
20806
20762
  const trimmed = name.trim();
20807
20763
  if (!trimmed) return name;
@@ -20809,63 +20765,6 @@ function formatToolName(name) {
20809
20765
  const normalized = stripped.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toLowerCase();
20810
20766
  return TOOL_NAME_ALIASES[normalized] ?? stripped;
20811
20767
  }
20812
- function getToolDisplayLabel(toolCall) {
20813
- const normalized = formatToolName(toolCall.name);
20814
- const args = safeParseJson(toolCall.arguments);
20815
- const displayName = toolCall.display_name?.trim() ?? "";
20816
- const baseLabel = displayName || TOOL_DISPLAY_LABELS[normalized] || normalized;
20817
- const metaDisplayName = getStringArgValue(args, "_meta_display_name");
20818
- if (metaDisplayName) {
20819
- return metaDisplayName;
20820
- }
20821
- const description = getStringArgValue(args, "description");
20822
- if (normalized === "BgBash") {
20823
- return description ? `\u540E\u53F0\u6267\u884C\uFF1A${description}` : "\u540E\u53F0\u6267\u884C\u547D\u4EE4";
20824
- }
20825
- if (normalized === "ReadSkill") {
20826
- const skillName = getStringArgValue(args, "skill") || getStringArgValue(args, "skill_name");
20827
- return skillName ? `${baseLabel}\u300C${skillName}\u300D` : baseLabel;
20828
- }
20829
- if (normalized === "Read") {
20830
- const skillName = getSkillNameFromFilePath(
20831
- getStringArgValue(args, "file_path") || getStringArgValue(args, "path")
20832
- );
20833
- if (skillName) return `\u8BFB\u53D6\u6280\u80FD\u300C${skillName}\u300D`;
20834
- }
20835
- if (normalized === "FinishTask") {
20836
- const title = getStringArgValue(args, "title");
20837
- return title ? `${baseLabel}\uFF1A${title}` : baseLabel;
20838
- }
20839
- return description || baseLabel;
20840
- }
20841
- function getToolTone(status) {
20842
- if (status === "error" || status === "cancelled") return "red";
20843
- if (status === "awaiting_answer") return "amber";
20844
- if (status === "pending") return "blue";
20845
- return "emerald";
20846
- }
20847
- function getToolStatusLabel(status) {
20848
- if (status === "pending") return "\u8FD0\u884C\u4E2D";
20849
- if (status === "awaiting_answer") return "\u7B49\u5F85\u56DE\u7B54";
20850
- if (status === "error") return "\u9519\u8BEF";
20851
- if (status === "cancelled") return "\u5DF2\u53D6\u6D88";
20852
- return "\u5B8C\u6210";
20853
- }
20854
- function formatToolDuration(ms) {
20855
- if (ms < 1e3) return `${Math.round(ms)}ms`;
20856
- const seconds = ms / 1e3;
20857
- if (seconds < 60) return `${seconds.toFixed(1)}s`;
20858
- const minutes = Math.floor(seconds / 60);
20859
- const remainingSeconds = Math.round(seconds % 60);
20860
- return remainingSeconds > 0 ? `${minutes}m${remainingSeconds}s` : `${minutes}m`;
20861
- }
20862
- function formatToolArgs(args) {
20863
- try {
20864
- return JSON.stringify(JSON.parse(args), null, 2);
20865
- } catch {
20866
- return args;
20867
- }
20868
- }
20869
20768
  var RESULT_PREVIEW_LIMIT = 4e3;
20870
20769
  function formatToolResult(result) {
20871
20770
  const text4 = typeof result === "string" ? result : JSON.stringify(result, null, 2);
@@ -21072,7 +20971,7 @@ function CurrentPlanPanel({
21072
20971
 
21073
20972
  // src/components/ChatSurface.tsx
21074
20973
  import { chatErrorForDisplay as chatErrorForDisplay2 } from "@blade-hq/agent-client";
21075
- import { useMemo as useMemo17, useState as useState35 } from "react";
20974
+ import { useMemo as useMemo17, useState as useState34 } from "react";
21076
20975
 
21077
20976
  // src/lib/random-id.ts
21078
20977
  function randomId() {
@@ -46431,7 +46330,7 @@ import {
46431
46330
  useEffect as useEffect25,
46432
46331
  useMemo as useMemo16,
46433
46332
  useRef as useRef27,
46434
- useState as useState34
46333
+ useState as useState33
46435
46334
  } from "react";
46436
46335
 
46437
46336
  // ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/useStickToBottom.js
@@ -46931,7 +46830,7 @@ import {
46931
46830
  getTextContent as getTextContent2,
46932
46831
  normalizeMessageContent as normalizeMessageContent2
46933
46832
  } from "@blade-hq/agent-client";
46934
- import { useEffect as useEffect23, useRef as useRef25, useState as useState32 } from "react";
46833
+ import { useEffect as useEffect23, useRef as useRef25, useState as useState31 } from "react";
46935
46834
 
46936
46835
  // src/components/AgentTaskCard.tsx
46937
46836
  import { useEffect as useEffect20, useState as useState27 } from "react";
@@ -56044,9 +55943,6 @@ function Shimmer({ children = "\u6B63\u5728\u601D\u8003...", className }) {
56044
55943
  return /* @__PURE__ */ jsx20("span", { className: cn("blade-shimmer-text text-sm font-medium", className), children });
56045
55944
  }
56046
55945
 
56047
- // src/components/ToolCallBlock.tsx
56048
- import { useState as useState30 } from "react";
56049
-
56050
55946
  // src/components/AskUserQuestionBlock.tsx
56051
55947
  import { useEffect as useEffect21, useMemo as useMemo15, useRef as useRef24, useState as useState29 } from "react";
56052
55948
  import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
@@ -56512,7 +56408,6 @@ function ToolCallBlock({
56512
56408
  classNames,
56513
56409
  renderers
56514
56410
  }) {
56515
- const [expanded, setExpanded] = useState30(false);
56516
56411
  const normalizedName = formatToolName(toolCall.name);
56517
56412
  const customQuestion = normalizedName === "AskUserQuestion" ? renderers?.askUserQuestion : void 0;
56518
56413
  const customToolCall = normalizedName === "AskUserQuestion" && customQuestion ? null : renderers?.toolCall?.(toolCall);
@@ -56588,52 +56483,6 @@ function ToolCallBlock({
56588
56483
  }
56589
56484
  );
56590
56485
  }
56591
- const tone = getToolTone(toolCall.status);
56592
- const displayName = getToolDisplayLabel(toolCall);
56593
- const toneClass = tone === "red" ? "border-l-[hsl(var(--muted-foreground)/0.5)]" : tone === "amber" ? "border-l-amber-400" : tone === "blue" ? "border-l-blue-500" : "border-l-[hsl(var(--primary))]";
56594
- const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx22(LoaderCircle, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx22(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx22(X, { size: 11 }) : /* @__PURE__ */ jsx22(Check, { size: 11 });
56595
- const statusTextClass = tone === "red" ? "text-[hsl(var(--muted-foreground))]" : tone === "amber" ? "text-amber-300" : tone === "blue" ? "text-blue-300" : "text-[hsl(var(--primary))]";
56596
- return /* @__PURE__ */ jsxs17("div", { className: "ml-4 text-xs", children: [
56597
- /* @__PURE__ */ jsxs17("div", { className: cn("border-l-[3px] flex items-center gap-2 min-h-7 px-3 leading-5", toneClass), children: [
56598
- /* @__PURE__ */ jsxs17(
56599
- "button",
56600
- {
56601
- type: "button",
56602
- onClick: () => setExpanded(!expanded),
56603
- className: "flex min-h-7 min-w-0 flex-1 items-center gap-2 text-left transition-colors hover:bg-white/3 focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
56604
- "aria-expanded": expanded,
56605
- children: [
56606
- /* @__PURE__ */ jsx22(
56607
- ChevronRight,
56608
- {
56609
- size: 11,
56610
- className: cn(
56611
- "shrink-0 text-[hsl(var(--muted-foreground))] transition-transform",
56612
- expanded && "rotate-90"
56613
- )
56614
- }
56615
- ),
56616
- /* @__PURE__ */ jsxs17("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
56617
- statusIcon,
56618
- /* @__PURE__ */ jsx22("span", { children: getToolStatusLabel(toolCall.status) })
56619
- ] }),
56620
- /* @__PURE__ */ jsx22("span", { className: "min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]", children: displayName })
56621
- ]
56622
- }
56623
- ),
56624
- typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */ jsx22("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration(toolCall.duration_ms) })
56625
- ] }),
56626
- expanded && /* @__PURE__ */ jsxs17("div", { className: "ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3", children: [
56627
- /* @__PURE__ */ jsx22("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u5DE5\u5177" }),
56628
- /* @__PURE__ */ jsx22("div", { className: "mb-3 font-mono text-[11px] text-[hsl(var(--foreground))]", children: normalizedName }),
56629
- /* @__PURE__ */ jsx22("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u53C2\u6570" }),
56630
- /* @__PURE__ */ jsx22("pre", { className: "overflow-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatToolArgs(toolCall.arguments) }),
56631
- toolCall.result != null && /* @__PURE__ */ jsxs17(Fragment7, { children: [
56632
- /* @__PURE__ */ jsx22("div", { className: "mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u7ED3\u679C" }),
56633
- /* @__PURE__ */ jsx22("pre", { className: "max-h-[400px] overflow-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatToolResult(toolCall.result) })
56634
- ] })
56635
- ] })
56636
- ] });
56637
56486
  }
56638
56487
  function buildAskUserPayload(argumentsJson) {
56639
56488
  try {
@@ -56649,7 +56498,7 @@ function buildAskUserPayload(argumentsJson) {
56649
56498
 
56650
56499
  // src/components/ToolUiCardView.tsx
56651
56500
  import { resolveToolUiCardContent } from "@blade-hq/agent-client";
56652
- import { useEffect as useEffect22, useState as useState31 } from "react";
56501
+ import { useEffect as useEffect22, useState as useState30 } from "react";
56653
56502
  import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
56654
56503
  function ToolUiCardView({ card, sessionId }) {
56655
56504
  if (card.mcpApp) return sessionId ? /* @__PURE__ */ jsx23(McpAppCard, { sessionId, sourceId: card.mcpApp.sourceId }) : null;
@@ -56676,9 +56525,9 @@ function ToolUiCardView({ card, sessionId }) {
56676
56525
  }
56677
56526
  function FileCard({ card, sessionId, path: path2 }) {
56678
56527
  const client = useBladeClient();
56679
- const [html, setHtml] = useState31(null);
56680
- const [failed, setFailed] = useState31(false);
56681
- const [refreshVersion, setRefreshVersion] = useState31(0);
56528
+ const [html, setHtml] = useState30(null);
56529
+ const [failed, setFailed] = useState30(false);
56530
+ const [refreshVersion, setRefreshVersion] = useState30(0);
56682
56531
  useEffect22(() => {
56683
56532
  const abort = new AbortController();
56684
56533
  setHtml(null);
@@ -56745,7 +56594,7 @@ function ThinkingBlock({
56745
56594
  isStreaming,
56746
56595
  className
56747
56596
  }) {
56748
- const [open2, setOpen] = useState32(false);
56597
+ const [open2, setOpen] = useState31(false);
56749
56598
  if (!isStreaming) return null;
56750
56599
  return /* @__PURE__ */ jsxs19("div", { part: "thinking", className: cn("blade-chat-thinking ml-4 text-xs", className), children: [
56751
56600
  /* @__PURE__ */ jsxs19(
@@ -57025,7 +56874,7 @@ function AssistantTurnBlock({
57025
56874
  )
57026
56875
  );
57027
56876
  const activeQuestionId = questionToolCalls.filter((toolCall) => toolCall.status === "pending").at(-1)?.id;
57028
- const [displayMode, setDisplayMode] = useState32(
56877
+ const [displayMode, setDisplayMode] = useState31(
57029
56878
  () => isStreaming || hasActionableToolCall ? "detail" : "compact"
57030
56879
  );
57031
56880
  const userSelectedDisplayModeRef = useRef25(false);
@@ -57038,7 +56887,7 @@ function AssistantTurnBlock({
57038
56887
  }, [hasActionableToolCall, isStreaming]);
57039
56888
  const effectiveMode = resolveTurnDisplayMode({ isStreaming, displayMode });
57040
56889
  const executionDurationMs = getExecutionDurationMs({ messages, isStreaming });
57041
- const [clock, setClock] = useState32(() => Date.now());
56890
+ const [clock, setClock] = useState31(() => Date.now());
57042
56891
  const hasLiveStartTime = messages.some(
57043
56892
  (message) => message.timestamp != null && Number.isFinite(Date.parse(message.timestamp))
57044
56893
  );
@@ -57254,7 +57103,7 @@ function collectMemoryRefs(messages) {
57254
57103
  return [...refs.values()];
57255
57104
  }
57256
57105
  function MemoryRefsHint({ refs, className }) {
57257
- const [expanded, setExpanded] = useState32(false);
57106
+ const [expanded, setExpanded] = useState31(false);
57258
57107
  const label = refs.some((ref) => ref.skill_name) ? "\u53C2\u8003\u4E86\u8BE5\u6280\u80FD\u7684\u5386\u53F2\u7ECF\u9A8C" : "\u53C2\u8003\u4E86\u5386\u53F2\u7ECF\u9A8C";
57259
57108
  return /* @__PURE__ */ jsxs19("div", { part: "memory-refs", className: cn("blade-chat-memory-refs ml-1 w-full max-w-[680px]", className), children: [
57260
57109
  /* @__PURE__ */ jsxs19("button", { type: "button", onClick: () => setExpanded((value) => !value), className: "inline-flex h-8 items-center gap-1.5 rounded-lg border border-[hsl(var(--primary)/0.22)] bg-[hsl(var(--primary)/0.07)] px-3 text-xs font-medium text-[hsl(var(--primary))]", children: [
@@ -57400,7 +57249,7 @@ var RenderErrorBoundary = class extends Component2 {
57400
57249
  };
57401
57250
 
57402
57251
  // src/components/PostChatFollowupBlock.tsx
57403
- import { useCallback as useCallback28, useEffect as useEffect24, useRef as useRef26, useState as useState33 } from "react";
57252
+ import { useCallback as useCallback28, useEffect as useEffect24, useRef as useRef26, useState as useState32 } from "react";
57404
57253
  import { Fragment as Fragment8, jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
57405
57254
  function emitInteraction(callback, event) {
57406
57255
  try {
@@ -57420,7 +57269,7 @@ function ArtifactCard({
57420
57269
  onArtifactOpened
57421
57270
  }) {
57422
57271
  const client = useBladeClient();
57423
- const [downloading, setDownloading] = useState33(false);
57272
+ const [downloading, setDownloading] = useState32(false);
57424
57273
  const name = artifact.label || basename(artifact.target);
57425
57274
  if (artifact.kind === "link") {
57426
57275
  return /* @__PURE__ */ jsxs21(
@@ -57526,11 +57375,11 @@ function ResultFeedback({
57526
57375
  onFeedbackSaved
57527
57376
  }) {
57528
57377
  const client = useBladeClient();
57529
- const [saved, setSaved] = useState33(savedFeedback ?? null);
57530
- const [helpful, setHelpful] = useState33(savedFeedback?.helpful ?? null);
57531
- const [reason, setReason] = useState33(savedFeedback?.reason ?? null);
57532
- const [saving, setSaving] = useState33(false);
57533
- const [saveError, setSaveError] = useState33(false);
57378
+ const [saved, setSaved] = useState32(savedFeedback ?? null);
57379
+ const [helpful, setHelpful] = useState32(savedFeedback?.helpful ?? null);
57380
+ const [reason, setReason] = useState32(savedFeedback?.reason ?? null);
57381
+ const [saving, setSaving] = useState32(false);
57382
+ const [saveError, setSaveError] = useState32(false);
57534
57383
  const reportedShown = useRef26(false);
57535
57384
  const latestChoice = useRef26(null);
57536
57385
  const eligible = followup.feedback_eligible === true && Boolean(sessionId) && !isViewer;
@@ -57657,7 +57506,7 @@ function PostChatFollowupBlock({
57657
57506
  className,
57658
57507
  suggestionClassName
57659
57508
  }) {
57660
- const [expanded, setExpanded] = useState33(false);
57509
+ const [expanded, setExpanded] = useState32(false);
57661
57510
  const adopted = useRef26(/* @__PURE__ */ new Set());
57662
57511
  const reportedSuggestions = useRef26(false);
57663
57512
  const reportedArtifacts = useRef26(/* @__PURE__ */ new Set());
@@ -58152,7 +58001,7 @@ function MessageList({
58152
58001
  isEntryLoaded: (entryId) => findEntryRow(rootRef.current, entryId) !== null,
58153
58002
  beforeSeek: () => stopAutoScrollRef.current?.()
58154
58003
  });
58155
- const [viewportNavTurnId, setViewportNavTurnId] = useState34(null);
58004
+ const [viewportNavTurnId, setViewportNavTurnId] = useState33(null);
58156
58005
  const latestNavTurnId = turnNavItems.at(-1)?.id ?? null;
58157
58006
  return /* @__PURE__ */ jsxs24(
58158
58007
  "div",
@@ -58430,7 +58279,7 @@ function PinLatestUserMessage({
58430
58279
  }
58431
58280
  function ScrollToBottomButton({ className }) {
58432
58281
  const { isAtBottom, scrollToBottom } = useStickToBottomContext();
58433
- const [visible, setVisible] = useState34(false);
58282
+ const [visible, setVisible] = useState33(false);
58434
58283
  const hideTimerRef = useRef27(null);
58435
58284
  useEffect25(() => {
58436
58285
  if (isAtBottom) {
@@ -58604,7 +58453,7 @@ function ChatSurface({
58604
58453
  onRevealingChange,
58605
58454
  isReplay
58606
58455
  }) {
58607
- const [pending, setPending] = useState35([]);
58456
+ const [pending, setPending] = useState34([]);
58608
58457
  const currentPending = pending.filter((item) => item.sessionId === sessionId);
58609
58458
  const sendWithApps = async (text4) => {
58610
58459
  const content3 = [...currentPending.map((item) => `[${item.label}]
@@ -58726,8 +58575,8 @@ function isUnauthorizedError(error61) {
58726
58575
  return error61 instanceof BladeApiError2 && error61.status === 401;
58727
58576
  }
58728
58577
  function LoginCard({ client, onLoggedIn }) {
58729
- const [loggingIn, setLoggingIn] = useState36(false);
58730
- const [loginError, setLoginError] = useState36(null);
58578
+ const [loggingIn, setLoggingIn] = useState35(false);
58579
+ const [loginError, setLoginError] = useState35(null);
58731
58580
  const handleLogin = async () => {
58732
58581
  setLoggingIn(true);
58733
58582
  setLoginError(null);
@@ -58759,8 +58608,8 @@ function LoginCard({ client, onLoggedIn }) {
58759
58608
  }
58760
58609
  function AgentChat(props) {
58761
58610
  const client = useBladeClient();
58762
- const [attempt, setAttempt] = useState36(0);
58763
- const [needLogin, setNeedLogin] = useState36(() => !client.hasToken());
58611
+ const [attempt, setAttempt] = useState35(0);
58612
+ const [needLogin, setNeedLogin] = useState35(() => !client.hasToken());
58764
58613
  if (needLogin) {
58765
58614
  return /* @__PURE__ */ jsx31(
58766
58615
  "div",
@@ -58799,7 +58648,7 @@ function ChatSessionView({
58799
58648
  onUnauthorized
58800
58649
  }) {
58801
58650
  const client = useBladeClient();
58802
- const [planRevealRevisions, setPlanRevealRevisions] = useState36(
58651
+ const [planRevealRevisions, setPlanRevealRevisions] = useState35(
58803
58652
  () => /* @__PURE__ */ new Map()
58804
58653
  );
58805
58654
  const handleSessionConnected = useCallback30((connectedSession) => {
@@ -58820,14 +58669,14 @@ function ChatSessionView({
58820
58669
  onSessionConnected: handleSessionConnected
58821
58670
  });
58822
58671
  const replay = useReplay(session);
58823
- const [stopRequested, setStopRequested] = useState36(false);
58824
- const [isRevealing, setIsRevealing] = useState36(false);
58825
- const [inputText, setInputText] = useState36("");
58826
- const [queueNotice, setQueueNotice] = useState36(null);
58827
- const [queuePendingItemId, setQueuePendingItemId] = useState36(null);
58828
- const [queuePanelVisible, setQueuePanelVisible] = useState36(false);
58829
- const [resultFeedback, setResultFeedback] = useState36([]);
58830
- const [timelineRewrite, setTimelineRewrite] = useState36(0);
58672
+ const [stopRequested, setStopRequested] = useState35(false);
58673
+ const [isRevealing, setIsRevealing] = useState35(false);
58674
+ const [inputText, setInputText] = useState35("");
58675
+ const [queueNotice, setQueueNotice] = useState35(null);
58676
+ const [queuePendingItemId, setQueuePendingItemId] = useState35(null);
58677
+ const [queuePanelVisible, setQueuePanelVisible] = useState35(false);
58678
+ const [resultFeedback, setResultFeedback] = useState35([]);
58679
+ const [timelineRewrite, setTimelineRewrite] = useState35(0);
58831
58680
  const resolvedSessionId = session?.sessionId;
58832
58681
  const isViewer = state?.viewerRole === "viewer";
58833
58682
  const canUseQueue = !isViewer;
@@ -59075,10 +58924,10 @@ ${content3}`);
59075
58924
  }
59076
58925
 
59077
58926
  // src/components/LlmChat.tsx
59078
- import { useEffect as useEffect27, useMemo as useMemo19, useState as useState38 } from "react";
58927
+ import { useEffect as useEffect27, useMemo as useMemo19, useState as useState37 } from "react";
59079
58928
 
59080
58929
  // src/components/LlmAdvancedSettings.tsx
59081
- import { useState as useState37 } from "react";
58930
+ import { useState as useState36 } from "react";
59082
58931
  import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
59083
58932
  var FIELDS = [
59084
58933
  { id: "baseURL", label: "\u6A21\u578B\u670D\u52A1\u5730\u5740", placeholder: "http://\u5185\u7F51\u5730\u5740/v1" },
@@ -59125,8 +58974,8 @@ function writeOverride(settings, baseURL, override) {
59125
58974
  }
59126
58975
  function LlmAdvancedSettingsBar({ settings, defaults: defaults2, override, onChange }) {
59127
58976
  const normalized = normalizeAdvanced(settings);
59128
- const [open2, setOpen] = useState37(false);
59129
- const [draft, setDraft] = useState37(override);
58977
+ const [open2, setOpen] = useState36(false);
58978
+ const [draft, setDraft] = useState36(override);
59130
58979
  if (!normalized) return null;
59131
58980
  const fields2 = FIELDS.filter((field) => normalized[field.id]);
59132
58981
  const dirty = Object.keys(override).length > 0;
@@ -59209,12 +59058,12 @@ function LlmChat({
59209
59058
  onOverrideChange,
59210
59059
  ...options
59211
59060
  }) {
59212
- const [override, setOverride] = useState38(() => readOverride(advanced, options.baseURL));
59061
+ const [override, setOverride] = useState37(() => readOverride(advanced, options.baseURL));
59213
59062
  const effective = { ...options, ...override };
59214
59063
  const { messages, isStreaming, error: error61, send, stop, reset } = useLlmChat(effective);
59215
- const [inputText, setInputText] = useState38("");
59216
- const [stopRequested, setStopRequested] = useState38(false);
59217
- const [isRevealing, setIsRevealing] = useState38(false);
59064
+ const [inputText, setInputText] = useState37("");
59065
+ const [stopRequested, setStopRequested] = useState37(false);
59066
+ const [isRevealing, setIsRevealing] = useState37(false);
59218
59067
  const isStreamingDisplay = isStreaming || isRevealing;
59219
59068
  const handle = useMemo19(
59220
59069
  () => ({
@@ -59296,7 +59145,7 @@ function ChatView(props) {
59296
59145
  }
59297
59146
 
59298
59147
  // src/components/ConnectorPanel.tsx
59299
- import { useCallback as useCallback31, useEffect as useEffect28, useMemo as useMemo20, useRef as useRef29, useState as useState39 } from "react";
59148
+ import { useCallback as useCallback31, useEffect as useEffect28, useMemo as useMemo20, useRef as useRef29, useState as useState38 } from "react";
59300
59149
 
59301
59150
  // src/components/connector-panel-types.ts
59302
59151
  function selectionFromItem(item) {
@@ -59338,10 +59187,10 @@ function ConnectorPanel({
59338
59187
  renderFooterActions,
59339
59188
  className
59340
59189
  }) {
59341
- const [query, setQuery] = useState39("");
59342
- const [pendingCatalog, setPendingCatalog] = useState39(null);
59343
- const [pendingLoading, setPendingLoading] = useState39(false);
59344
- const [pendingError, setPendingError] = useState39(false);
59190
+ const [query, setQuery] = useState38("");
59191
+ const [pendingCatalog, setPendingCatalog] = useState38(null);
59192
+ const [pendingLoading, setPendingLoading] = useState38(false);
59193
+ const [pendingError, setPendingError] = useState38(false);
59345
59194
  const activation = useSessionPluginActivation({
59346
59195
  client,
59347
59196
  // 首页不会走这个分支:待选在下面自己处理开关,不碰会话接口。
@@ -59615,7 +59464,7 @@ function ContextGroupCard({ contexts, className }) {
59615
59464
  }
59616
59465
 
59617
59466
  // src/components/SessionMemoryToggle.tsx
59618
- import { useCallback as useCallback32, useEffect as useEffect29, useRef as useRef30, useState as useState40, useSyncExternalStore as useSyncExternalStore2 } from "react";
59467
+ import { useCallback as useCallback32, useEffect as useEffect29, useRef as useRef30, useState as useState39, useSyncExternalStore as useSyncExternalStore2 } from "react";
59619
59468
  import { jsx as jsx38, jsxs as jsxs31 } from "react/jsx-runtime";
59620
59469
  var saveStates = /* @__PURE__ */ new WeakMap();
59621
59470
  function getSaveState(client, sessionId) {
@@ -59673,7 +59522,7 @@ function SessionMemoryToggle({
59673
59522
  getSaving,
59674
59523
  getSaving
59675
59524
  );
59676
- const [draftEnabled, setDraftEnabled] = useState40(enabled);
59525
+ const [draftEnabled, setDraftEnabled] = useState39(enabled);
59677
59526
  const activeSessionIdRef = useRef30(sessionId);
59678
59527
  activeSessionIdRef.current = sessionId;
59679
59528
  useEffect29(() => {
@@ -63245,7 +63094,7 @@ var Portal2 = TooltipPortal;
63245
63094
  var Content2 = TooltipContent;
63246
63095
 
63247
63096
  // src/components/SessionBranchPicker.tsx
63248
- import { useMemo as useMemo26, useState as useState50 } from "react";
63097
+ import { useMemo as useMemo26, useState as useState49 } from "react";
63249
63098
  import { jsx as jsx48, jsxs as jsxs33 } from "react/jsx-runtime";
63250
63099
  var ROW_HEIGHT = 32;
63251
63100
  var SVG_WIDTH = 44;
@@ -63254,8 +63103,8 @@ function SessionBranchPicker({
63254
63103
  disabled = false,
63255
63104
  onCheckout
63256
63105
  }) {
63257
- const [checkoutError, setCheckoutError] = useState50(null);
63258
- const [pendingNodeId, setPendingNodeId] = useState50(null);
63106
+ const [checkoutError, setCheckoutError] = useState49(null);
63107
+ const [pendingNodeId, setPendingNodeId] = useState49(null);
63259
63108
  const hasHistory = tree.nodes.length > 0;
63260
63109
  const layout = useMemo26(() => buildLayoutNodes(tree), [tree]);
63261
63110
  const nodeMap = useMemo26(() => new Map(tree.nodes.map((node3) => [node3.id, node3])), [tree]);