@blade-hq/agent-react 2610.0.0-beta.53 → 2610.0.0-beta.55

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
@@ -1554,7 +1554,7 @@ var require_react_is_development = __commonJS({
1554
1554
  var ContextProvider = REACT_PROVIDER_TYPE;
1555
1555
  var Element = REACT_ELEMENT_TYPE;
1556
1556
  var ForwardRef = REACT_FORWARD_REF_TYPE;
1557
- var Fragment9 = REACT_FRAGMENT_TYPE;
1557
+ var Fragment10 = REACT_FRAGMENT_TYPE;
1558
1558
  var Lazy = REACT_LAZY_TYPE;
1559
1559
  var Memo = REACT_MEMO_TYPE;
1560
1560
  var Portal = REACT_PORTAL_TYPE;
@@ -1622,7 +1622,7 @@ var require_react_is_development = __commonJS({
1622
1622
  exports.ContextProvider = ContextProvider;
1623
1623
  exports.Element = Element;
1624
1624
  exports.ForwardRef = ForwardRef;
1625
- exports.Fragment = Fragment9;
1625
+ exports.Fragment = Fragment10;
1626
1626
  exports.Lazy = Lazy;
1627
1627
  exports.Memo = Memo;
1628
1628
  exports.Portal = Portal;
@@ -2888,10 +2888,10 @@ var X = createLucideIcon("X", [
2888
2888
  ]);
2889
2889
 
2890
2890
  // src/components/AgentChat.tsx
2891
- import { useCallback as useCallback26, useEffect as useEffect20, useMemo as useMemo16, useRef as useRef23, useState as useState30 } from "react";
2891
+ import { useCallback as useCallback27, useEffect as useEffect21, useMemo as useMemo17, useRef as useRef23, useState as useState31 } from "react";
2892
2892
 
2893
2893
  // src/components/SessionPluginSelector.tsx
2894
- import { useEffect as useEffect10, useRef as useRef10, useState as useState15 } from "react";
2894
+ import { useEffect as useEffect11, useState as useState16 } from "react";
2895
2895
 
2896
2896
  // src/components/SessionPluginConfigDialog.tsx
2897
2897
  import { useEffect as useEffect9, useRef as useRef9, useState as useState14 } from "react";
@@ -15469,6 +15469,13 @@ function presentationSchema(schema) {
15469
15469
  }
15470
15470
  return result;
15471
15471
  }
15472
+ function ConfigMultiSchemaField(props) {
15473
+ return /* @__PURE__ */ jsxs("div", { className: "rjsf-field", children: [
15474
+ /* @__PURE__ */ jsx2("label", { htmlFor: isValidElement(props.selector) ? props.selector.props.id : void 0, children: "\u914D\u7F6E\u65B9\u5F0F" }),
15475
+ props.selector,
15476
+ props.optionSchemaField
15477
+ ] });
15478
+ }
15472
15479
  function ConfigSchemaField(inputProps) {
15473
15480
  const path = inputProps.name === "" && inputProps.onKeyRename ? [...inputProps.fieldPathId.path, ""] : inputProps.fieldPathId.path;
15474
15481
  const props = {
@@ -15658,17 +15665,7 @@ function SessionPluginConfigForm({
15658
15665
  templates: {
15659
15666
  FieldTemplate: ConfigFieldTemplate,
15660
15667
  ArrayFieldItemTemplate: ConfigArrayItem,
15661
- MultiSchemaFieldTemplate: (props) => /* @__PURE__ */ jsxs("div", { className: "rjsf-field", children: [
15662
- /* @__PURE__ */ jsx2(
15663
- "label",
15664
- {
15665
- htmlFor: isValidElement(props.selector) ? props.selector.props.id : void 0,
15666
- children: "\u914D\u7F6E\u65B9\u5F0F"
15667
- }
15668
- ),
15669
- props.selector,
15670
- props.optionSchemaField
15671
- ] }),
15668
+ MultiSchemaFieldTemplate: ConfigMultiSchemaField,
15672
15669
  ButtonTemplates: {
15673
15670
  ...defaults.templates.ButtonTemplates,
15674
15671
  AddButton: (props) => /* @__PURE__ */ jsx2(
@@ -15744,10 +15741,10 @@ function iconBlob(client, sessionId, name, token) {
15744
15741
  blobCache = /* @__PURE__ */ new Map();
15745
15742
  clientCaches.set(client, blobCache);
15746
15743
  }
15747
- const key = `${sessionId}:${name}:${token}`;
15744
+ const key = sessionId ? `${sessionId}:${name}:${token}` : `account:${name}:${token}`;
15748
15745
  const cached2 = blobCache.get(key);
15749
15746
  if (cached2) return cached2;
15750
- const pending = client.sessions.fetchSessionPluginIcon(sessionId, name).catch(() => {
15747
+ const pending = (sessionId ? client.sessions.fetchSessionPluginIcon(sessionId, name) : client.plugins.fetchIcon(name)).catch(() => {
15751
15748
  blobCache?.delete(key);
15752
15749
  return null;
15753
15750
  });
@@ -15760,7 +15757,7 @@ function SessionPluginIcon({ client, sessionId, plugin, className }) {
15760
15757
  const token = plugin.icon;
15761
15758
  useEffect8(() => {
15762
15759
  setUrl(null);
15763
- if (!token || !sessionId) return;
15760
+ if (!token) return;
15764
15761
  let alive = true;
15765
15762
  let objectUrl = null;
15766
15763
  void iconBlob(client, sessionId, plugin.name, token).then((blob) => {
@@ -15914,6 +15911,12 @@ function ConfigDialogState({
15914
15911
  event.preventDefault();
15915
15912
  onClose();
15916
15913
  },
15914
+ onKeyDown: (event) => {
15915
+ if (event.key !== "Escape") return;
15916
+ event.preventDefault();
15917
+ event.stopPropagation();
15918
+ onClose();
15919
+ },
15917
15920
  style: {
15918
15921
  position: "fixed",
15919
15922
  inset: 0,
@@ -15975,40 +15978,256 @@ function ConfigDialogState({
15975
15978
  ] });
15976
15979
  }
15977
15980
 
15978
- // src/components/SessionPluginSelector.tsx
15981
+ // src/components/plugin-connector.ts
15982
+ function catalogToConnectorItems(catalog) {
15983
+ return catalog.map((entry) => ({
15984
+ name: entry.name,
15985
+ display_name: entry.display_name,
15986
+ icon: entry.icon,
15987
+ iconSource: "account",
15988
+ installed: entry.installed,
15989
+ active: false,
15990
+ status: "not_prepared",
15991
+ projected: false
15992
+ }));
15993
+ }
15994
+ function mergeConnectorItems(sessionPlugins, catalog) {
15995
+ const byName = new Map((catalog ?? []).map((entry) => [entry.name, entry]));
15996
+ return sessionPlugins.map((plugin) => {
15997
+ const entry = byName.get(plugin.name);
15998
+ if (!entry) {
15999
+ return {
16000
+ name: plugin.name,
16001
+ display_name: plugin.display_name ?? null,
16002
+ icon: plugin.icon ?? null,
16003
+ iconSource: "session",
16004
+ installed: plugin.installed,
16005
+ active: plugin.active,
16006
+ status: plugin.status,
16007
+ reason: plugin.reason,
16008
+ config: plugin.config,
16009
+ projected: plugin.projected
16010
+ };
16011
+ }
16012
+ return {
16013
+ name: plugin.name,
16014
+ display_name: entry.display_name ?? plugin.display_name ?? null,
16015
+ icon: entry.icon,
16016
+ iconSource: "account",
16017
+ installed: entry.installed,
16018
+ active: plugin.active,
16019
+ status: plugin.status,
16020
+ reason: plugin.reason,
16021
+ config: plugin.config,
16022
+ projected: plugin.projected
16023
+ };
16024
+ });
16025
+ }
16026
+ function pluginConnectorSummary(state) {
16027
+ if (state === "configured") return "\u914D\u7F6E\u5DF2\u4FDD\u5B58";
16028
+ if (state === "required") return "\u8FD8\u9700\u8981\u586B\u5199\u914D\u7F6E";
16029
+ if (state === "error") return "\u914D\u7F6E\u58F0\u660E\u6709\u95EE\u9898";
16030
+ return null;
16031
+ }
16032
+ function filterConnectorItems(items, query) {
16033
+ const needle = query.trim().toLowerCase();
16034
+ if (!needle) return items;
16035
+ return items.filter(
16036
+ (item) => `${item.display_name ?? ""} ${item.name}`.toLowerCase().includes(needle)
16037
+ );
16038
+ }
16039
+
16040
+ // src/components/PluginConnectorList.tsx
15979
16041
  import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
15980
- function SessionPluginSelector(props) {
15981
- return /* @__PURE__ */ jsx5(PluginSelectorState, { ...props }, props.sessionId);
16042
+ function PluginSwitch({
16043
+ label,
16044
+ checked,
16045
+ pending,
16046
+ disabled,
16047
+ /** 首页的开关只是"这次输入的待选",不是"已经启用",措辞必须跟着分。 */
16048
+ draft = false,
16049
+ onToggle
16050
+ }) {
16051
+ return /* @__PURE__ */ jsx5(
16052
+ "button",
16053
+ {
16054
+ type: "button",
16055
+ role: "switch",
16056
+ "aria-checked": checked,
16057
+ "aria-label": draft ? `${label} \u5F85\u9009` : `${label} \u542F\u7528`,
16058
+ disabled,
16059
+ onClick: () => onToggle(!checked),
16060
+ className: `relative inline-flex h-[18px] w-8 shrink-0 cursor-pointer items-center rounded-full border transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${checked ? "border-transparent bg-[hsl(213_94%_55%)]" : "border-[hsl(var(--border))] bg-[hsl(var(--muted))]"}`,
16061
+ children: /* @__PURE__ */ jsx5(
16062
+ "span",
16063
+ {
16064
+ "aria-hidden": "true",
16065
+ className: `pointer-events-none flex h-3.5 w-3.5 items-center justify-center rounded-full bg-white shadow transition-transform ${checked ? "translate-x-[16px]" : "translate-x-[2px]"}`,
16066
+ children: pending ? /* @__PURE__ */ jsx5(LoaderCircle, { size: 9, className: "animate-spin text-[hsl(var(--muted-foreground))]" }) : null
16067
+ }
16068
+ )
16069
+ }
16070
+ );
15982
16071
  }
15983
- function PluginSelectorState({ client, sessionId, className, side = "bottom", onChange }) {
15984
- const [open2, setOpen] = useState15(false);
16072
+ function PluginConnectorList({
16073
+ client,
16074
+ sessionId,
16075
+ items,
16076
+ inFlight,
16077
+ busy,
16078
+ mutationError,
16079
+ onToggle,
16080
+ onRetry,
16081
+ onEditConfig,
16082
+ configuring,
16083
+ onConfigSaved,
16084
+ onConfigClose,
16085
+ disabledReason,
16086
+ unavailableText,
16087
+ emptyText,
16088
+ draft = false
16089
+ }) {
16090
+ const configuringItem = configuring ? items.find((item) => item.name === configuring.name) ?? null : null;
16091
+ return /* @__PURE__ */ jsxs3("div", { className: "py-0.5", children: [
16092
+ disabledReason ? /* @__PURE__ */ jsx5("div", { className: "px-3 py-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: disabledReason }) : null,
16093
+ items.length === 0 ? /* @__PURE__ */ jsx5("div", { className: "px-3 py-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: unavailableText ?? emptyText }) : null,
16094
+ items.map((item) => {
16095
+ const label = sessionPluginLabel(item);
16096
+ const summary = pluginConnectorSummary(item.config);
16097
+ const actionable = !disabledReason && item.installed !== false || item.active;
16098
+ const pending = Boolean(inFlight[item.name]);
16099
+ const checked = item.active;
16100
+ return /* @__PURE__ */ jsxs3("div", { className: "px-3 py-1", children: [
16101
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
16102
+ /* @__PURE__ */ jsx5(
16103
+ SessionPluginIcon,
16104
+ {
16105
+ client,
16106
+ sessionId: item.iconSource === "account" ? null : sessionId,
16107
+ plugin: item
16108
+ }
16109
+ ),
16110
+ /* @__PURE__ */ jsx5("span", { className: "min-w-0 flex-1 truncate text-[11px]", title: label, children: label }),
16111
+ /* @__PURE__ */ jsx5(
16112
+ PluginSwitch,
16113
+ {
16114
+ label,
16115
+ checked,
16116
+ pending,
16117
+ draft,
16118
+ disabled: !actionable,
16119
+ onToggle: (next) => onToggle(item, next)
16120
+ }
16121
+ )
16122
+ ] }),
16123
+ !draft && summary && item.config !== "not_required" ? /* @__PURE__ */ jsxs3("div", { className: "mt-0.5 flex items-center gap-2 pl-7 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
16124
+ /* @__PURE__ */ jsx5("span", { children: summary }),
16125
+ item.config === "configured" ? /* @__PURE__ */ jsx5(
16126
+ "button",
16127
+ {
16128
+ type: "button",
16129
+ disabled: busy || !sessionId,
16130
+ onClick: () => onEditConfig(item),
16131
+ className: "underline disabled:cursor-not-allowed disabled:opacity-50",
16132
+ children: "\u914D\u7F6E"
16133
+ }
16134
+ ) : null
16135
+ ] }) : null,
16136
+ !draft && item.active && item.status !== "valid" && item.status !== "required" ? /* @__PURE__ */ jsxs3("div", { className: "mt-0.5 flex items-center gap-2 pl-7 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
16137
+ /* @__PURE__ */ jsx5("span", { children: item.reason || "\u63D2\u4EF6\u6682\u4E0D\u53EF\u7528" }),
16138
+ /* @__PURE__ */ jsx5(
16139
+ "button",
16140
+ {
16141
+ type: "button",
16142
+ disabled: busy,
16143
+ onClick: () => onRetry(item),
16144
+ className: "underline disabled:cursor-not-allowed disabled:opacity-50",
16145
+ children: "\u91CD\u8BD5"
16146
+ }
16147
+ )
16148
+ ] }) : null
16149
+ ] }, item.name);
16150
+ }),
16151
+ mutationError ? /* @__PURE__ */ jsx5("div", { className: "px-3 pt-1 text-[10px] text-[hsl(var(--destructive))]", children: "\u64CD\u4F5C\u672A\u5B8C\u6210\uFF0C\u8BF7\u91CD\u8BD5" }) : null,
16152
+ configuring && configuringItem && sessionId ? /* @__PURE__ */ jsx5(
16153
+ SessionPluginConfigDialog,
16154
+ {
16155
+ client,
16156
+ sessionId,
16157
+ plugin: configuringItem,
16158
+ onSaved: onConfigSaved,
16159
+ onClose: onConfigClose
16160
+ }
16161
+ ) : null
16162
+ ] });
16163
+ }
16164
+
16165
+ // src/components/use-session-plugin-activation.ts
16166
+ import { useCallback as useCallback22, useEffect as useEffect10, useMemo as useMemo11, useRef as useRef10, useState as useState15 } from "react";
16167
+ function useSessionPluginActivation({
16168
+ client,
16169
+ sessionId,
16170
+ onChange
16171
+ }) {
15985
16172
  const [plugins, setPlugins] = useState15([]);
16173
+ const [catalog, setCatalog] = useState15(null);
15986
16174
  const [loading, setLoading] = useState15(false);
15987
- const [busy, setBusy] = useState15(false);
15988
16175
  const [listError, setListError] = useState15(false);
15989
16176
  const [mutationError, setMutationError] = useState15(false);
16177
+ const [inFlight, setInFlight] = useState15({});
15990
16178
  const [configuring, setConfiguring] = useState15(null);
15991
- const latestPlugins = useRef10(plugins);
15992
- latestPlugins.current = plugins;
15993
16179
  const alive = useRef10(true);
15994
16180
  const generation = useRef10(0);
15995
16181
  const mutationGenerations = useRef10(/* @__PURE__ */ new Map());
15996
16182
  const desiredActivations = useRef10(/* @__PURE__ */ new Map());
15997
16183
  const pendingMutations = useRef10(/* @__PURE__ */ new Map());
16184
+ const submittedActivations = useRef10(/* @__PURE__ */ new Set());
16185
+ const serverActive = useRef10(/* @__PURE__ */ new Set());
15998
16186
  const lifetime = useRef10(0);
15999
16187
  const request = useRef10(null);
16188
+ const [desiredVersion, setDesiredVersion] = useState15(0);
16189
+ const setDesired = useCallback22((name, value) => {
16190
+ if (value === null) {
16191
+ if (!desiredActivations.current.delete(name)) return;
16192
+ } else {
16193
+ if (desiredActivations.current.get(name) === value) return;
16194
+ desiredActivations.current.set(name, value);
16195
+ }
16196
+ setDesiredVersion((version2) => version2 + 1);
16197
+ }, []);
16198
+ const items = useMemo11(() => {
16199
+ void desiredVersion;
16200
+ const merged = mergeConnectorItems(plugins, catalog);
16201
+ return merged.map((item) => {
16202
+ if (configuring?.name === item.name && configuring.pendingActivation) {
16203
+ return { ...item, active: false };
16204
+ }
16205
+ const desired = desiredActivations.current.get(item.name);
16206
+ return desired === void 0 ? item : { ...item, active: desired };
16207
+ });
16208
+ }, [catalog, configuring, desiredVersion, plugins]);
16209
+ const markInFlight = useCallback22((name, on) => {
16210
+ setInFlight((current) => {
16211
+ if (on) return current[name] ? current : { ...current, [name]: true };
16212
+ if (!current[name]) return current;
16213
+ const { [name]: removed, ...rest } = current;
16214
+ void removed;
16215
+ return rest;
16216
+ });
16217
+ }, []);
16000
16218
  useEffect10(() => {
16001
16219
  alive.current = true;
16002
16220
  setPlugins([]);
16003
- setOpen(false);
16221
+ setCatalog(null);
16004
16222
  setLoading(false);
16005
- setBusy(false);
16006
16223
  setListError(false);
16007
16224
  setMutationError(false);
16225
+ setInFlight({});
16008
16226
  setConfiguring(null);
16009
16227
  desiredActivations.current.clear();
16010
16228
  mutationGenerations.current.clear();
16011
16229
  pendingMutations.current.clear();
16230
+ submittedActivations.current.clear();
16012
16231
  return () => {
16013
16232
  alive.current = false;
16014
16233
  lifetime.current++;
@@ -16016,7 +16235,7 @@ function PluginSelectorState({ client, sessionId, className, side = "bottom", on
16016
16235
  request.current?.abort();
16017
16236
  };
16018
16237
  }, [client]);
16019
- const load = async () => {
16238
+ const load = useCallback22(async () => {
16020
16239
  if (!alive.current) return;
16021
16240
  request.current?.abort();
16022
16241
  const controller = new AbortController();
@@ -16027,136 +16246,245 @@ function PluginSelectorState({ client, sessionId, className, side = "bottom", on
16027
16246
  try {
16028
16247
  const result = await client.sessions.listSessionPlugins(sessionId, { signal: controller.signal });
16029
16248
  if (alive.current && current === generation.current) {
16249
+ serverActive.current = new Set(result.plugins.filter((item) => item.active).map((item) => item.name));
16030
16250
  setPlugins(result.plugins.map((item) => {
16031
- const pending = pendingMutations.current.has(item.name);
16032
16251
  const desired = desiredActivations.current.get(item.name);
16033
- return pending && desired !== void 0 ? { ...item, active: desired } : item;
16252
+ return desired === void 0 ? item : { ...item, active: desired };
16034
16253
  }));
16035
- setConfiguring((current2) => {
16036
- const fresh = result.plugins.find((item) => item.name === current2?.name);
16037
- return current2 && fresh ? { ...current2, display_name: fresh.display_name, icon: fresh.icon } : current2;
16038
- });
16039
16254
  }
16040
16255
  } catch {
16041
16256
  if (alive.current && current === generation.current && !controller.signal.aborted) setListError(true);
16042
16257
  } finally {
16043
16258
  if (alive.current && current === generation.current) setLoading(false);
16044
16259
  }
16045
- };
16046
- const select = async (name, active) => {
16047
- desiredActivations.current.set(name, active);
16048
- const currentLifetime = lifetime.current;
16049
- const currentMutation = (mutationGenerations.current.get(name) ?? 0) + 1;
16050
- mutationGenerations.current.set(name, currentMutation);
16051
- pendingMutations.current.set(name, currentMutation);
16260
+ }, [client, sessionId]);
16261
+ const loadCatalog = useCallback22(async () => {
16262
+ try {
16263
+ const { plugins: entries } = await client.plugins.catalog();
16264
+ if (alive.current) setCatalog(entries);
16265
+ } catch {
16266
+ }
16267
+ }, [client]);
16268
+ const reload = useCallback22(() => {
16269
+ void load();
16270
+ void loadCatalog();
16271
+ }, [load, loadCatalog]);
16272
+ const abandon = useCallback22((name) => {
16273
+ setDesired(name, null);
16274
+ pendingMutations.current.delete(name);
16275
+ mutationGenerations.current.set(name, (mutationGenerations.current.get(name) ?? 0) + 1);
16276
+ markInFlight(name, false);
16277
+ void load();
16278
+ }, [load, markInFlight, setDesired]);
16279
+ const finish = useCallback22((name, mutation) => {
16280
+ pendingMutations.current.delete(name);
16281
+ setDesired(name, null);
16282
+ if (mutation === mutationGenerations.current.get(name)) markInFlight(name, false);
16283
+ }, [markInFlight, setDesired]);
16284
+ const commitActivation = useCallback22(
16285
+ async (name, active, mutation, startedAt) => {
16286
+ submittedActivations.current.add(name);
16287
+ try {
16288
+ const { plugin } = await client.sessions.setSessionPluginActivation(sessionId, name, active);
16289
+ if (!alive.current || startedAt !== lifetime.current) return;
16290
+ if (mutation !== mutationGenerations.current.get(name)) {
16291
+ const desired = desiredActivations.current.get(name);
16292
+ if (desired !== void 0 && desired !== plugin.active) {
16293
+ const next = (mutationGenerations.current.get(name) ?? 0) + 1;
16294
+ mutationGenerations.current.set(name, next);
16295
+ pendingMutations.current.set(name, next);
16296
+ markInFlight(name, true);
16297
+ await commitActivation(name, desired, next, startedAt);
16298
+ }
16299
+ return;
16300
+ }
16301
+ if (active) serverActive.current.add(name);
16302
+ else serverActive.current.delete(name);
16303
+ finish(name, mutation);
16304
+ setPlugins((current) => current.map((item) => item.name === plugin.name ? { ...item, ...plugin } : item));
16305
+ onChange?.(plugin);
16306
+ if (plugin.active && plugin.status === "required") {
16307
+ setConfiguring({ name: plugin.name, pendingActivation: true });
16308
+ }
16309
+ await load();
16310
+ } catch {
16311
+ if (alive.current && startedAt === lifetime.current && mutation === mutationGenerations.current.get(name)) {
16312
+ pendingMutations.current.delete(name);
16313
+ submittedActivations.current.delete(name);
16314
+ setDesired(name, null);
16315
+ markInFlight(name, false);
16316
+ setMutationError(true);
16317
+ void load();
16318
+ }
16319
+ }
16320
+ },
16321
+ [client, finish, load, markInFlight, onChange, sessionId, setDesired]
16322
+ );
16323
+ const enable = useCallback22(async (name) => {
16324
+ if (!alive.current) return;
16325
+ const startedAt = lifetime.current;
16326
+ const mutation = (mutationGenerations.current.get(name) ?? 0) + 1;
16327
+ mutationGenerations.current.set(name, mutation);
16328
+ pendingMutations.current.set(name, mutation);
16329
+ setDesired(name, true);
16330
+ setMutationError(false);
16331
+ markInFlight(name, true);
16052
16332
  request.current?.abort();
16053
16333
  generation.current++;
16054
16334
  setLoading(false);
16055
- setBusy(true);
16056
- setMutationError(false);
16057
- setPlugins((current) => current.map((item) => item.name === name ? { ...item, active } : item));
16335
+ let state;
16058
16336
  try {
16059
- const { plugin } = await client.sessions.setSessionPluginActivation(sessionId, name, active);
16060
- if (!alive.current || currentLifetime !== lifetime.current) return;
16061
- if (currentMutation !== mutationGenerations.current.get(name)) {
16062
- const desired = desiredActivations.current.get(name);
16063
- if (desired !== void 0 && desired !== plugin.active) void select(name, desired);
16064
- return;
16065
- }
16066
- pendingMutations.current.delete(name);
16067
- setBusy(pendingMutations.current.size > 0);
16068
- setPlugins((current) => current.map((item) => item.name === plugin.name ? { ...item, ...plugin } : item));
16069
- onChange?.(plugin);
16070
- if (plugin.active && plugin.status === "required") {
16071
- const row = latestPlugins.current.find((item) => item.name === plugin.name);
16072
- if (row) setConfiguring({ ...row, ...plugin });
16073
- }
16074
- await load();
16337
+ const result = await client.sessions.prepareSessionPluginConfig(sessionId, name);
16338
+ if (!alive.current || startedAt !== lifetime.current || mutation !== mutationGenerations.current.get(name)) return;
16339
+ state = result.config;
16075
16340
  } catch {
16076
- if (alive.current && currentLifetime === lifetime.current && currentMutation === mutationGenerations.current.get(name)) {
16077
- pendingMutations.current.delete(name);
16078
- setBusy(pendingMutations.current.size > 0);
16079
- setMutationError(true);
16080
- void load();
16081
- }
16341
+ if (!alive.current || startedAt !== lifetime.current || mutation !== mutationGenerations.current.get(name)) return;
16342
+ abandon(name);
16343
+ setMutationError(true);
16344
+ return;
16345
+ }
16346
+ if (state.state === "required") {
16347
+ pendingMutations.current.delete(name);
16348
+ markInFlight(name, false);
16349
+ setConfiguring({ name, pendingActivation: true });
16350
+ return;
16351
+ }
16352
+ if (state.state !== "configured" && state.state !== "not_required") {
16353
+ abandon(name);
16354
+ setMutationError(true);
16355
+ return;
16082
16356
  }
16083
- };
16084
- const finishPreparation = async (name, state) => {
16085
16357
  setPlugins((current) => current.map((item) => item.name === name ? { ...item, config: state.state } : item));
16086
- const row = latestPlugins.current.find((item) => item.name === name);
16087
- if (row?.active && row.status === "required" && state.state === "configured") {
16088
- await select(name, true);
16358
+ await commitActivation(name, true, mutation, startedAt);
16359
+ }, [abandon, client, commitActivation, markInFlight, sessionId, setDesired]);
16360
+ const disable = useCallback22((name) => {
16361
+ const startedAt = lifetime.current;
16362
+ request.current?.abort();
16363
+ generation.current++;
16364
+ setLoading(false);
16365
+ if (!submittedActivations.current.has(name) && !serverActive.current.has(name)) {
16366
+ abandon(name);
16367
+ return;
16368
+ }
16369
+ const mutation = (mutationGenerations.current.get(name) ?? 0) + 1;
16370
+ mutationGenerations.current.set(name, mutation);
16371
+ pendingMutations.current.set(name, mutation);
16372
+ setDesired(name, false);
16373
+ setMutationError(false);
16374
+ markInFlight(name, true);
16375
+ void commitActivation(name, false, mutation, startedAt);
16376
+ }, [abandon, commitActivation, markInFlight, setDesired]);
16377
+ const toggle = useCallback22((item, next) => {
16378
+ if (next) void enable(item.name);
16379
+ else disable(item.name);
16380
+ }, [disable, enable]);
16381
+ const retry = useCallback22((item) => {
16382
+ void enable(item.name);
16383
+ }, [enable]);
16384
+ const editConfig = useCallback22((item) => {
16385
+ setConfiguring({ name: item.name, pendingActivation: false });
16386
+ }, []);
16387
+ const onConfigSaved = useCallback22((state) => {
16388
+ const target = configuring;
16389
+ if (!target) return;
16390
+ setConfiguring(null);
16391
+ setPlugins((current) => current.map((item) => item.name === target.name ? { ...item, config: state.state } : item));
16392
+ if (!target.pendingActivation || state.state !== "configured") {
16393
+ void load();
16089
16394
  return;
16090
16395
  }
16091
- await load();
16396
+ const startedAt = lifetime.current;
16397
+ const mutation = (mutationGenerations.current.get(target.name) ?? 0) + 1;
16398
+ mutationGenerations.current.set(target.name, mutation);
16399
+ pendingMutations.current.set(target.name, mutation);
16400
+ setDesired(target.name, true);
16401
+ markInFlight(target.name, true);
16402
+ void commitActivation(target.name, true, mutation, startedAt);
16403
+ }, [commitActivation, configuring, load, markInFlight, setDesired]);
16404
+ const onConfigClose = useCallback22(() => {
16405
+ const target = configuring;
16406
+ if (!target) return;
16407
+ setConfiguring(null);
16408
+ if (target.pendingActivation) abandon(target.name);
16409
+ else void load();
16410
+ }, [abandon, configuring, load]);
16411
+ return {
16412
+ items,
16413
+ loading,
16414
+ listError,
16415
+ mutationError,
16416
+ inFlight,
16417
+ busy: Object.keys(inFlight).length > 0,
16418
+ configuring,
16419
+ reload,
16420
+ toggle,
16421
+ retry,
16422
+ editConfig,
16423
+ onConfigSaved,
16424
+ onConfigClose
16092
16425
  };
16093
- return /* @__PURE__ */ jsxs3("div", { className: `relative text-xs ${className ?? ""}`, children: [
16094
- /* @__PURE__ */ jsx5(
16426
+ }
16427
+
16428
+ // src/components/SessionPluginSelector.tsx
16429
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
16430
+ function SessionPluginSelector(props) {
16431
+ return /* @__PURE__ */ jsx6(PluginSelectorState, { ...props }, props.sessionId);
16432
+ }
16433
+ function PluginSelectorState({ client, sessionId, className, side = "bottom", onChange }) {
16434
+ const [open2, setOpen] = useState16(false);
16435
+ return /* @__PURE__ */ jsxs4("div", { className: `relative text-xs ${className ?? ""}`, children: [
16436
+ /* @__PURE__ */ jsx6(
16095
16437
  "button",
16096
16438
  {
16097
16439
  type: "button",
16098
16440
  disabled: !sessionId,
16099
16441
  "aria-expanded": open2,
16100
- onClick: () => {
16101
- setOpen(!open2);
16102
- if (!open2) void load();
16103
- },
16442
+ onClick: () => setOpen(!open2),
16104
16443
  className: "rounded-full border border-[hsl(var(--border))] px-2.5 py-1",
16105
16444
  children: "\u4F1A\u8BDD\u63D2\u4EF6"
16106
16445
  }
16107
16446
  ),
16108
- open2 ? /* @__PURE__ */ jsxs3("div", { className: `absolute left-0 z-40 my-2 max-h-72 w-72 max-w-[calc(100vw-2rem)] overflow-y-auto rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-3 text-[hsl(var(--popover-foreground))] shadow-lg ${side === "top" ? "bottom-full" : "top-full"}`, children: [
16109
- loading ? /* @__PURE__ */ jsx5("div", { children: "\u6B63\u5728\u83B7\u53D6\u63D2\u4EF6\u2026" }) : null,
16110
- listError ? /* @__PURE__ */ jsx5("button", { type: "button", onClick: () => void load(), children: "\u63D2\u4EF6\u5217\u8868\u6682\u4E0D\u53EF\u7528\uFF0C\u70B9\u51FB\u91CD\u8BD5" }) : null,
16111
- !loading && !listError && !plugins.length ? /* @__PURE__ */ jsx5("div", { children: "\u5C1A\u672A\u5B89\u88C5\u63D2\u4EF6" }) : null,
16112
- plugins.map((plugin) => /* @__PURE__ */ jsxs3("div", { className: "py-1", children: [
16113
- /* @__PURE__ */ jsxs3("label", { className: "flex items-center justify-between gap-2", children: [
16114
- /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-center gap-2", children: [
16115
- /* @__PURE__ */ jsx5(SessionPluginIcon, { client, sessionId, plugin }),
16116
- /* @__PURE__ */ jsx5("span", { className: "min-w-0 truncate", title: sessionPluginLabel(plugin), children: sessionPluginLabel(plugin) })
16117
- ] }),
16118
- /* @__PURE__ */ jsx5(
16119
- "input",
16120
- {
16121
- type: "checkbox",
16122
- className: "shrink-0",
16123
- checked: plugin.active,
16124
- disabled: busy && !plugin.active || !plugin.installed && !plugin.active,
16125
- onChange: (event) => void select(plugin.name, event.target.checked),
16126
- "aria-label": `${plugin.name} \u4F1A\u8BDD\u6FC0\u6D3B`
16127
- }
16128
- )
16129
- ] }),
16130
- plugin.status === "required" ? /* @__PURE__ */ jsxs3("div", { className: "text-[hsl(var(--muted-foreground))]", children: [
16131
- plugin.reason || "\u8FD8\u9700\u8981\u586B\u5199\u914D\u7F6E",
16132
- /* @__PURE__ */ jsx5("button", { type: "button", disabled: busy, onClick: () => setConfiguring(plugin), className: "ml-2 underline", children: "\u586B\u5199\u914D\u7F6E" })
16133
- ] }) : plugin.active && plugin.status !== "valid" ? /* @__PURE__ */ jsxs3("div", { className: "text-[hsl(var(--muted-foreground))]", children: [
16134
- plugin.reason || "\u63D2\u4EF6\u6682\u4E0D\u53EF\u7528",
16135
- /* @__PURE__ */ jsx5("button", { type: "button", disabled: busy, onClick: () => void select(plugin.name, true), className: "ml-2 underline", children: "\u91CD\u8BD5" })
16136
- ] }) : plugin.config && plugin.config !== "not_required" ? /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 text-[hsl(var(--muted-foreground))]", children: [
16137
- configSummary(plugin.config) ? /* @__PURE__ */ jsx5("span", { children: configSummary(plugin.config) }) : null,
16138
- /* @__PURE__ */ jsx5("button", { type: "button", disabled: !sessionId, onClick: () => setConfiguring(plugin), className: "underline", children: "\u914D\u7F6E" })
16139
- ] }) : null
16140
- ] }, plugin.name)),
16141
- mutationError ? /* @__PURE__ */ jsx5("div", { children: "\u64CD\u4F5C\u672A\u5B8C\u6210\uFF0C\u8BF7\u91CD\u8BD5" }) : null
16142
- ] }) : null,
16143
- configuring ? /* @__PURE__ */ jsx5(
16144
- SessionPluginConfigDialog,
16145
- {
16146
- client,
16147
- sessionId,
16148
- plugin: configuring,
16149
- onSaved: (state) => void finishPreparation(configuring.name, state),
16150
- onClose: () => setConfiguring(null)
16151
- }
16152
- ) : null
16447
+ open2 ? /* @__PURE__ */ jsx6(PluginSelectorList, { client, sessionId, side, onChange }) : null
16153
16448
  ] });
16154
16449
  }
16155
- function configSummary(state) {
16156
- if (state === "configured") return "\u914D\u7F6E\u5DF2\u4FDD\u5B58";
16157
- if (state === "required") return "\u8FD8\u9700\u8981\u586B\u5199\u914D\u7F6E";
16158
- if (state === "error") return "\u914D\u7F6E\u58F0\u660E\u6709\u95EE\u9898";
16159
- return null;
16450
+ function PluginSelectorList({
16451
+ client,
16452
+ sessionId,
16453
+ side,
16454
+ onChange
16455
+ }) {
16456
+ const controller = useSessionPluginActivation({ client, sessionId, onChange });
16457
+ const { reload } = controller;
16458
+ useEffect11(() => {
16459
+ reload();
16460
+ }, [reload]);
16461
+ return /* @__PURE__ */ jsxs4(
16462
+ "div",
16463
+ {
16464
+ className: `absolute left-0 z-40 my-2 max-h-72 w-72 max-w-[calc(100vw-2rem)] overflow-y-auto rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-3 text-[hsl(var(--popover-foreground))] shadow-lg ${side === "top" ? "bottom-full" : "top-full"}`,
16465
+ children: [
16466
+ controller.listError ? /* @__PURE__ */ jsx6("button", { type: "button", onClick: reload, children: "\u63D2\u4EF6\u5217\u8868\u6682\u4E0D\u53EF\u7528\uFF0C\u70B9\u51FB\u91CD\u8BD5" }) : null,
16467
+ /* @__PURE__ */ jsx6(
16468
+ PluginConnectorList,
16469
+ {
16470
+ client,
16471
+ sessionId,
16472
+ items: controller.items,
16473
+ inFlight: controller.inFlight,
16474
+ busy: controller.busy,
16475
+ mutationError: controller.mutationError,
16476
+ onToggle: controller.toggle,
16477
+ onRetry: controller.retry,
16478
+ onEditConfig: controller.editConfig,
16479
+ configuring: controller.configuring,
16480
+ onConfigSaved: controller.onConfigSaved,
16481
+ onConfigClose: controller.onConfigClose,
16482
+ emptyText: "\u5C1A\u672A\u5B89\u88C5\u63D2\u4EF6"
16483
+ }
16484
+ )
16485
+ ]
16486
+ }
16487
+ );
16160
16488
  }
16161
16489
 
16162
16490
  // src/components/SessionQueuePanel.tsx
@@ -16167,7 +16495,7 @@ import {
16167
16495
  queuePauseReasonLabel,
16168
16496
  queuedMessageStatusLabel
16169
16497
  } from "@blade-hq/agent-client";
16170
- import { useRef as useRef11, useState as useState16 } from "react";
16498
+ import { useRef as useRef11, useState as useState17 } from "react";
16171
16499
 
16172
16500
  // src/lib/utils.ts
16173
16501
  function cn(...inputs) {
@@ -16199,7 +16527,7 @@ async function copyToClipboard(text) {
16199
16527
  }
16200
16528
 
16201
16529
  // src/components/SessionQueuePanel.tsx
16202
- import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
16530
+ import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
16203
16531
  var ACTION_BUTTON = "flex h-6 w-6 items-center justify-center rounded text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent";
16204
16532
  function SessionQueuePanel({
16205
16533
  snapshot,
@@ -16214,13 +16542,13 @@ function SessionQueuePanel({
16214
16542
  onReorder,
16215
16543
  onDeliver
16216
16544
  }) {
16217
- const [collapsed, setCollapsed] = useState16(false);
16218
- const [editing, setEditing] = useState16(
16545
+ const [collapsed, setCollapsed] = useState17(false);
16546
+ const [editing, setEditing] = useState17(
16219
16547
  null
16220
16548
  );
16221
- const [draggingId, setDraggingId] = useState16(null);
16549
+ const [draggingId, setDraggingId] = useState17(null);
16222
16550
  const requeuePending = useRef11(false);
16223
- const [requeueing, setRequeueing] = useState16(false);
16551
+ const [requeueing, setRequeueing] = useState17(false);
16224
16552
  const items = snapshot.items;
16225
16553
  if (items.length === 0 && !snapshot.paused && !notice && !editing) return null;
16226
16554
  const pendingIds = items.filter(canEditQueuedMessage).map((item) => item.id);
@@ -16259,23 +16587,23 @@ function SessionQueuePanel({
16259
16587
  next.splice(to, 0, sourceId);
16260
16588
  onReorder(next);
16261
16589
  };
16262
- return /* @__PURE__ */ jsx6(
16590
+ return /* @__PURE__ */ jsx7(
16263
16591
  "section",
16264
16592
  {
16265
16593
  className: "blade-chat-queue shrink-0 border-t border-[hsl(var(--border))] px-4 pt-3",
16266
16594
  "aria-label": "\u5F85\u6267\u884C\u6D88\u606F",
16267
- children: /* @__PURE__ */ jsxs4("div", { className: "mx-auto max-w-[748px]", children: [
16268
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
16269
- /* @__PURE__ */ jsxs4("span", { className: "font-medium text-[hsl(var(--foreground))]", children: [
16595
+ children: /* @__PURE__ */ jsxs5("div", { className: "mx-auto max-w-[748px]", children: [
16596
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
16597
+ /* @__PURE__ */ jsxs5("span", { className: "font-medium text-[hsl(var(--foreground))]", children: [
16270
16598
  "\u5F85\u6267\u884C \xB7 ",
16271
16599
  items.length
16272
16600
  ] }),
16273
- snapshot.paused && /* @__PURE__ */ jsxs4(Fragment4, { children: [
16274
- /* @__PURE__ */ jsxs4("span", { className: "inline-flex items-center gap-1 text-[hsl(var(--destructive))]", children: [
16275
- /* @__PURE__ */ jsx6(CirclePause, { size: 12 }),
16601
+ snapshot.paused && /* @__PURE__ */ jsxs5(Fragment4, { children: [
16602
+ /* @__PURE__ */ jsxs5("span", { className: "inline-flex items-center gap-1 text-[hsl(var(--destructive))]", children: [
16603
+ /* @__PURE__ */ jsx7(CirclePause, { size: 12 }),
16276
16604
  pauseLabel
16277
16605
  ] }),
16278
- /* @__PURE__ */ jsx6(
16606
+ /* @__PURE__ */ jsx7(
16279
16607
  "button",
16280
16608
  {
16281
16609
  type: "button",
@@ -16285,7 +16613,7 @@ function SessionQueuePanel({
16285
16613
  }
16286
16614
  )
16287
16615
  ] }),
16288
- collapsible && /* @__PURE__ */ jsxs4(
16616
+ collapsible && /* @__PURE__ */ jsxs5(
16289
16617
  "button",
16290
16618
  {
16291
16619
  type: "button",
@@ -16294,18 +16622,18 @@ function SessionQueuePanel({
16294
16622
  className: "ml-auto inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
16295
16623
  children: [
16296
16624
  collapsed ? "\u5C55\u5F00" : "\u6298\u53E0",
16297
- /* @__PURE__ */ jsx6(ChevronDown, { size: 12, className: cn(!collapsed && "rotate-180") })
16625
+ /* @__PURE__ */ jsx7(ChevronDown, { size: 12, className: cn(!collapsed && "rotate-180") })
16298
16626
  ]
16299
16627
  }
16300
16628
  )
16301
16629
  ] }),
16302
- notice && /* @__PURE__ */ jsxs4("div", { className: "blade-chat-queue-notice mt-2 flex items-start gap-1.5 text-xs text-[hsl(var(--destructive))]", children: [
16303
- /* @__PURE__ */ jsx6(CircleAlert, { size: 13, className: "mt-0.5 shrink-0" }),
16304
- /* @__PURE__ */ jsx6("span", { className: "min-w-0 whitespace-pre-wrap break-words [overflow-wrap:anywhere]", children: notice })
16630
+ notice && /* @__PURE__ */ jsxs5("div", { className: "blade-chat-queue-notice mt-2 flex items-start gap-1.5 text-xs text-[hsl(var(--destructive))]", children: [
16631
+ /* @__PURE__ */ jsx7(CircleAlert, { size: 13, className: "mt-0.5 shrink-0" }),
16632
+ /* @__PURE__ */ jsx7("span", { className: "min-w-0 whitespace-pre-wrap break-words [overflow-wrap:anywhere]", children: notice })
16305
16633
  ] }),
16306
- detachedEdit && /* @__PURE__ */ jsxs4("div", { className: "mt-2 flex flex-col gap-2 text-xs", children: [
16307
- /* @__PURE__ */ jsx6("span", { children: "\u539F\u6D88\u606F\u5DF2\u53D8\u5316\uFF0C\u4FEE\u6539\u5185\u5BB9\u5DF2\u4FDD\u7559" }),
16308
- /* @__PURE__ */ jsx6(
16634
+ detachedEdit && /* @__PURE__ */ jsxs5("div", { className: "mt-2 flex flex-col gap-2 text-xs", children: [
16635
+ /* @__PURE__ */ jsx7("span", { children: "\u539F\u6D88\u606F\u5DF2\u53D8\u5316\uFF0C\u4FEE\u6539\u5185\u5BB9\u5DF2\u4FDD\u7559" }),
16636
+ /* @__PURE__ */ jsx7(
16309
16637
  "textarea",
16310
16638
  {
16311
16639
  "aria-label": "\u4FDD\u7559\u7684\u4FEE\u6539\u5185\u5BB9",
@@ -16315,9 +16643,9 @@ function SessionQueuePanel({
16315
16643
  className: "w-full rounded border border-[hsl(var(--border))] bg-transparent p-2"
16316
16644
  }
16317
16645
  ),
16318
- /* @__PURE__ */ jsxs4("div", { className: "flex justify-end gap-2", children: [
16319
- /* @__PURE__ */ jsx6("button", { type: "button", className: "rounded border border-[hsl(var(--border))] px-2 py-1", disabled: requeueing, onClick: stopEdit, children: "\u653E\u5F03\u4FEE\u6539" }),
16320
- onRequeue && /* @__PURE__ */ jsx6("button", { type: "button", className: "rounded bg-[hsl(var(--primary))] px-2 py-1 text-[hsl(var(--primary-foreground))] disabled:opacity-40", disabled: requeueing || !detachedEdit.text.trim(), onClick: async () => {
16646
+ /* @__PURE__ */ jsxs5("div", { className: "flex justify-end gap-2", children: [
16647
+ /* @__PURE__ */ jsx7("button", { type: "button", className: "rounded border border-[hsl(var(--border))] px-2 py-1", disabled: requeueing, onClick: stopEdit, children: "\u653E\u5F03\u4FEE\u6539" }),
16648
+ onRequeue && /* @__PURE__ */ jsx7("button", { type: "button", className: "rounded bg-[hsl(var(--primary))] px-2 py-1 text-[hsl(var(--primary-foreground))] disabled:opacity-40", disabled: requeueing || !detachedEdit.text.trim(), onClick: async () => {
16321
16649
  if (requeuePending.current) return;
16322
16650
  requeuePending.current = true;
16323
16651
  setRequeueing(true);
@@ -16333,7 +16661,7 @@ function SessionQueuePanel({
16333
16661
  }, children: "\u4F5C\u4E3A\u65B0\u6D88\u606F\u6392\u961F" })
16334
16662
  ] })
16335
16663
  ] }),
16336
- /* @__PURE__ */ jsx6("ul", { className: "mt-2 flex max-h-56 flex-col gap-1.5 overflow-y-auto", children: visibleItems.map((item) => {
16664
+ /* @__PURE__ */ jsx7("ul", { className: "mt-2 flex max-h-56 flex-col gap-1.5 overflow-y-auto", children: visibleItems.map((item) => {
16337
16665
  const position = items.indexOf(item) + 1;
16338
16666
  const pending = canEditQueuedMessage(item);
16339
16667
  const busy = pendingItemId === item.id;
@@ -16341,7 +16669,7 @@ function SessionQueuePanel({
16341
16669
  const pendingIndex = pendingIds.indexOf(item.id);
16342
16670
  const statusLabel = queuedMessageStatusLabel(item.status);
16343
16671
  const deliverable = canDeliver && canDeliverQueuedMessage(item);
16344
- return /* @__PURE__ */ jsxs4(
16672
+ return /* @__PURE__ */ jsxs5(
16345
16673
  "li",
16346
16674
  {
16347
16675
  draggable: pending && !busy,
@@ -16360,9 +16688,9 @@ function SessionQueuePanel({
16360
16688
  draggingId === item.id && "opacity-40"
16361
16689
  ),
16362
16690
  children: [
16363
- /* @__PURE__ */ jsx6("span", { className: "mt-0.5 w-4 shrink-0 text-right tabular-nums text-[hsl(var(--muted-foreground))]", children: position }),
16364
- /* @__PURE__ */ jsx6("div", { className: "min-w-0 flex-1", children: isEditing ? /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-1.5", children: [
16365
- /* @__PURE__ */ jsx6(
16691
+ /* @__PURE__ */ jsx7("span", { className: "mt-0.5 w-4 shrink-0 text-right tabular-nums text-[hsl(var(--muted-foreground))]", children: position }),
16692
+ /* @__PURE__ */ jsx7("div", { className: "min-w-0 flex-1", children: isEditing ? /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-1.5", children: [
16693
+ /* @__PURE__ */ jsx7(
16366
16694
  "textarea",
16367
16695
  {
16368
16696
  value: activeEdit?.text ?? "",
@@ -16374,8 +16702,8 @@ function SessionQueuePanel({
16374
16702
  className: "w-full resize-none rounded border border-[hsl(var(--border))] bg-transparent px-1.5 py-1 text-xs leading-5 text-[hsl(var(--foreground))] outline-none"
16375
16703
  }
16376
16704
  ),
16377
- /* @__PURE__ */ jsxs4("div", { className: "flex justify-end gap-1.5", children: [
16378
- /* @__PURE__ */ jsx6(
16705
+ /* @__PURE__ */ jsxs5("div", { className: "flex justify-end gap-1.5", children: [
16706
+ /* @__PURE__ */ jsx7(
16379
16707
  "button",
16380
16708
  {
16381
16709
  type: "button",
@@ -16384,7 +16712,7 @@ function SessionQueuePanel({
16384
16712
  children: "\u53D6\u6D88"
16385
16713
  }
16386
16714
  ),
16387
- /* @__PURE__ */ jsx6(
16715
+ /* @__PURE__ */ jsx7(
16388
16716
  "button",
16389
16717
  {
16390
16718
  type: "button",
@@ -16395,19 +16723,19 @@ function SessionQueuePanel({
16395
16723
  }
16396
16724
  )
16397
16725
  ] })
16398
- ] }) : /* @__PURE__ */ jsxs4(Fragment4, { children: [
16399
- /* @__PURE__ */ jsx6("div", { className: "line-clamp-2 whitespace-pre-wrap break-words text-[hsl(var(--foreground))]", children: item.content }),
16400
- /* @__PURE__ */ jsxs4("div", { className: "mt-0.5 flex items-center gap-2 text-[hsl(var(--muted-foreground))]", children: [
16401
- statusLabel && /* @__PURE__ */ jsx6("span", { children: statusLabel }),
16402
- busy && /* @__PURE__ */ jsxs4("span", { className: "inline-flex items-center gap-1", children: [
16403
- /* @__PURE__ */ jsx6(LoaderCircle, { size: 11, className: "animate-spin" }),
16726
+ ] }) : /* @__PURE__ */ jsxs5(Fragment4, { children: [
16727
+ /* @__PURE__ */ jsx7("div", { className: "line-clamp-2 whitespace-pre-wrap break-words text-[hsl(var(--foreground))]", children: item.content }),
16728
+ /* @__PURE__ */ jsxs5("div", { className: "mt-0.5 flex items-center gap-2 text-[hsl(var(--muted-foreground))]", children: [
16729
+ statusLabel && /* @__PURE__ */ jsx7("span", { children: statusLabel }),
16730
+ busy && /* @__PURE__ */ jsxs5("span", { className: "inline-flex items-center gap-1", children: [
16731
+ /* @__PURE__ */ jsx7(LoaderCircle, { size: 11, className: "animate-spin" }),
16404
16732
  "\u5904\u7406\u4E2D"
16405
16733
  ] }),
16406
- item.error && /* @__PURE__ */ jsx6("span", { className: "text-[hsl(var(--destructive))]", children: item.error })
16734
+ item.error && /* @__PURE__ */ jsx7("span", { className: "text-[hsl(var(--destructive))]", children: item.error })
16407
16735
  ] })
16408
16736
  ] }) }),
16409
- /* @__PURE__ */ jsxs4("div", { className: "flex shrink-0 items-center gap-0.5", children: [
16410
- /* @__PURE__ */ jsx6(
16737
+ /* @__PURE__ */ jsxs5("div", { className: "flex shrink-0 items-center gap-0.5", children: [
16738
+ /* @__PURE__ */ jsx7(
16411
16739
  "button",
16412
16740
  {
16413
16741
  type: "button",
@@ -16416,10 +16744,10 @@ function SessionQueuePanel({
16416
16744
  disabled: busy || pendingIndex <= 0,
16417
16745
  onClick: () => onMove(item, -1),
16418
16746
  className: ACTION_BUTTON,
16419
- children: /* @__PURE__ */ jsx6(ChevronUp, { size: 13 })
16747
+ children: /* @__PURE__ */ jsx7(ChevronUp, { size: 13 })
16420
16748
  }
16421
16749
  ),
16422
- /* @__PURE__ */ jsx6(
16750
+ /* @__PURE__ */ jsx7(
16423
16751
  "button",
16424
16752
  {
16425
16753
  type: "button",
@@ -16428,10 +16756,10 @@ function SessionQueuePanel({
16428
16756
  disabled: busy || pendingIndex < 0 || pendingIndex >= pendingIds.length - 1,
16429
16757
  onClick: () => onMove(item, 1),
16430
16758
  className: ACTION_BUTTON,
16431
- children: /* @__PURE__ */ jsx6(ChevronDown, { size: 13 })
16759
+ children: /* @__PURE__ */ jsx7(ChevronDown, { size: 13 })
16432
16760
  }
16433
16761
  ),
16434
- /* @__PURE__ */ jsx6(
16762
+ /* @__PURE__ */ jsx7(
16435
16763
  "button",
16436
16764
  {
16437
16765
  type: "button",
@@ -16440,10 +16768,10 @@ function SessionQueuePanel({
16440
16768
  disabled: busy || !canEditQueuedMessage(item),
16441
16769
  onClick: () => startEdit(item),
16442
16770
  className: ACTION_BUTTON,
16443
- children: /* @__PURE__ */ jsx6(Pencil, { size: 12 })
16771
+ children: /* @__PURE__ */ jsx7(Pencil, { size: 12 })
16444
16772
  }
16445
16773
  ),
16446
- /* @__PURE__ */ jsx6(
16774
+ /* @__PURE__ */ jsx7(
16447
16775
  "button",
16448
16776
  {
16449
16777
  type: "button",
@@ -16452,10 +16780,10 @@ function SessionQueuePanel({
16452
16780
  disabled: busy || !canCancelQueuedMessage(item),
16453
16781
  onClick: () => onCancel(item),
16454
16782
  className: ACTION_BUTTON,
16455
- children: /* @__PURE__ */ jsx6(Trash2, { size: 12 })
16783
+ children: /* @__PURE__ */ jsx7(Trash2, { size: 12 })
16456
16784
  }
16457
16785
  ),
16458
- /* @__PURE__ */ jsx6(
16786
+ /* @__PURE__ */ jsx7(
16459
16787
  "button",
16460
16788
  {
16461
16789
  type: "button",
@@ -16464,7 +16792,7 @@ function SessionQueuePanel({
16464
16792
  disabled: busy || !deliverable,
16465
16793
  onClick: () => onDeliver(item),
16466
16794
  className: ACTION_BUTTON,
16467
- children: /* @__PURE__ */ jsx6(Send, { size: 12 })
16795
+ children: /* @__PURE__ */ jsx7(Send, { size: 12 })
16468
16796
  }
16469
16797
  )
16470
16798
  ] })
@@ -16479,7 +16807,7 @@ function SessionQueuePanel({
16479
16807
  }
16480
16808
 
16481
16809
  // src/components/ReplayBar.tsx
16482
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
16810
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
16483
16811
  var SPEED_OPTIONS = [1, 2, 5];
16484
16812
  function ReplayBar({
16485
16813
  isReplay,
@@ -16490,7 +16818,7 @@ function ReplayBar({
16490
16818
  className
16491
16819
  }) {
16492
16820
  if (!isReplay) return null;
16493
- return /* @__PURE__ */ jsxs5(
16821
+ return /* @__PURE__ */ jsxs6(
16494
16822
  "div",
16495
16823
  {
16496
16824
  className: cn(
@@ -16498,13 +16826,13 @@ function ReplayBar({
16498
16826
  className
16499
16827
  ),
16500
16828
  children: [
16501
- /* @__PURE__ */ jsxs5("span", { className: "inline-flex items-center gap-1.5 font-medium text-[hsl(var(--foreground))]", children: [
16502
- /* @__PURE__ */ jsx7(Play, { size: 13 }),
16829
+ /* @__PURE__ */ jsxs6("span", { className: "inline-flex items-center gap-1.5 font-medium text-[hsl(var(--foreground))]", children: [
16830
+ /* @__PURE__ */ jsx8(Play, { size: 13 }),
16503
16831
  "\u56DE\u653E\u6A21\u5F0F"
16504
16832
  ] }),
16505
- /* @__PURE__ */ jsx7("span", { className: "text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u91CD\u73B0\u4E4B\u524D\u7684\u5BF9\u8BDD" }),
16506
- /* @__PURE__ */ jsxs5("div", { className: "ml-auto flex items-center gap-2", children: [
16507
- /* @__PURE__ */ jsx7("div", { className: "flex items-center gap-0.5 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-0.5", children: SPEED_OPTIONS.map((option) => /* @__PURE__ */ jsxs5(
16833
+ /* @__PURE__ */ jsx8("span", { className: "text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u91CD\u73B0\u4E4B\u524D\u7684\u5BF9\u8BDD" }),
16834
+ /* @__PURE__ */ jsxs6("div", { className: "ml-auto flex items-center gap-2", children: [
16835
+ /* @__PURE__ */ jsx8("div", { className: "flex items-center gap-0.5 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-0.5", children: SPEED_OPTIONS.map((option) => /* @__PURE__ */ jsxs6(
16508
16836
  "button",
16509
16837
  {
16510
16838
  type: "button",
@@ -16523,7 +16851,7 @@ function ReplayBar({
16523
16851
  },
16524
16852
  option
16525
16853
  )) }),
16526
- /* @__PURE__ */ jsx7(
16854
+ /* @__PURE__ */ jsx8(
16527
16855
  "button",
16528
16856
  {
16529
16857
  type: "button",
@@ -16543,10 +16871,10 @@ function ReplayBar({
16543
16871
  }
16544
16872
 
16545
16873
  // src/components/ReplayMismatchPrompt.tsx
16546
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
16874
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
16547
16875
  function ReplayMismatchPrompt({ mismatch, className }) {
16548
16876
  if (!mismatch) return null;
16549
- return /* @__PURE__ */ jsxs6(
16877
+ return /* @__PURE__ */ jsxs7(
16550
16878
  "div",
16551
16879
  {
16552
16880
  className: cn(
@@ -16554,19 +16882,19 @@ function ReplayMismatchPrompt({ mismatch, className }) {
16554
16882
  className
16555
16883
  ),
16556
16884
  children: [
16557
- /* @__PURE__ */ jsx8("div", { className: "font-medium text-[hsl(var(--foreground))]", children: "\u8FD9\u53E5\u8BDD\u548C\u4E4B\u524D\u5F55\u5236\u7684\u4E0D\u4E00\u6837" }),
16558
- /* @__PURE__ */ jsxs6("dl", { className: "mt-2 space-y-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
16559
- /* @__PURE__ */ jsxs6("div", { className: "flex gap-2", children: [
16560
- /* @__PURE__ */ jsx8("dt", { className: "shrink-0", children: "\u5F55\u5236\u7684\u662F" }),
16561
- /* @__PURE__ */ jsx8("dd", { className: "min-w-0 break-words text-[hsl(var(--foreground))]", children: mismatch.expectedMessage || "\uFF08\u7A7A\uFF09" })
16885
+ /* @__PURE__ */ jsx9("div", { className: "font-medium text-[hsl(var(--foreground))]", children: "\u8FD9\u53E5\u8BDD\u548C\u4E4B\u524D\u5F55\u5236\u7684\u4E0D\u4E00\u6837" }),
16886
+ /* @__PURE__ */ jsxs7("dl", { className: "mt-2 space-y-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
16887
+ /* @__PURE__ */ jsxs7("div", { className: "flex gap-2", children: [
16888
+ /* @__PURE__ */ jsx9("dt", { className: "shrink-0", children: "\u5F55\u5236\u7684\u662F" }),
16889
+ /* @__PURE__ */ jsx9("dd", { className: "min-w-0 break-words text-[hsl(var(--foreground))]", children: mismatch.expectedMessage || "\uFF08\u7A7A\uFF09" })
16562
16890
  ] }),
16563
- /* @__PURE__ */ jsxs6("div", { className: "flex gap-2", children: [
16564
- /* @__PURE__ */ jsx8("dt", { className: "shrink-0", children: "\u4F60\u8F93\u5165\u7684" }),
16565
- /* @__PURE__ */ jsx8("dd", { className: "min-w-0 break-words text-[hsl(var(--foreground))]", children: mismatch.actualMessage || "\uFF08\u7A7A\uFF09" })
16891
+ /* @__PURE__ */ jsxs7("div", { className: "flex gap-2", children: [
16892
+ /* @__PURE__ */ jsx9("dt", { className: "shrink-0", children: "\u4F60\u8F93\u5165\u7684" }),
16893
+ /* @__PURE__ */ jsx9("dd", { className: "min-w-0 break-words text-[hsl(var(--foreground))]", children: mismatch.actualMessage || "\uFF08\u7A7A\uFF09" })
16566
16894
  ] })
16567
16895
  ] }),
16568
- /* @__PURE__ */ jsxs6("div", { className: "mt-3 flex flex-wrap gap-2", children: [
16569
- /* @__PURE__ */ jsx8(
16896
+ /* @__PURE__ */ jsxs7("div", { className: "mt-3 flex flex-wrap gap-2", children: [
16897
+ /* @__PURE__ */ jsx9(
16570
16898
  "button",
16571
16899
  {
16572
16900
  type: "button",
@@ -16575,7 +16903,7 @@ function ReplayMismatchPrompt({ mismatch, className }) {
16575
16903
  children: "\u6309\u5F55\u5236\u5185\u5BB9\u7EE7\u7EED"
16576
16904
  }
16577
16905
  ),
16578
- /* @__PURE__ */ jsx8(
16906
+ /* @__PURE__ */ jsx9(
16579
16907
  "button",
16580
16908
  {
16581
16909
  type: "button",
@@ -16591,7 +16919,7 @@ function ReplayMismatchPrompt({ mismatch, className }) {
16591
16919
  }
16592
16920
 
16593
16921
  // src/components/PlanUpdateBlock.tsx
16594
- import { useEffect as useEffect11, useRef as useRef12, useState as useState17 } from "react";
16922
+ import { useEffect as useEffect12, useRef as useRef12, useState as useState18 } from "react";
16595
16923
 
16596
16924
  // src/components/display-utils.ts
16597
16925
  var TOOL_NAME_ALIASES = {
@@ -16735,7 +17063,7 @@ function formatToolResult(result) {
16735
17063
  }
16736
17064
 
16737
17065
  // src/components/PlanUpdateBlock.tsx
16738
- import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
17066
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
16739
17067
  var PLAN_STEP_STATUSES = /* @__PURE__ */ new Set(["pending", "in_progress", "completed"]);
16740
17068
  var PLAN_AUTO_COLLAPSE_MS = 5e3;
16741
17069
  function isPlanUpdateTool(toolCall) {
@@ -16790,12 +17118,12 @@ function PlanStepIcon({
16790
17118
  running = false
16791
17119
  }) {
16792
17120
  if (status === "completed") {
16793
- return /* @__PURE__ */ jsx9(Check, { size, strokeWidth: 2, className: "shrink-0 text-emerald-500" });
17121
+ return /* @__PURE__ */ jsx10(Check, { size, strokeWidth: 2, className: "shrink-0 text-emerald-500" });
16794
17122
  }
16795
17123
  if (status === "in_progress") {
16796
- return running ? /* @__PURE__ */ jsx9(LoaderCircle, { size, className: "shrink-0 animate-spin text-[hsl(var(--muted-foreground))]" }) : /* @__PURE__ */ jsx9(CircleDot, { size, className: "shrink-0 text-amber-500" });
17124
+ return running ? /* @__PURE__ */ jsx10(LoaderCircle, { size, className: "shrink-0 animate-spin text-[hsl(var(--muted-foreground))]" }) : /* @__PURE__ */ jsx10(CircleDot, { size, className: "shrink-0 text-amber-500" });
16797
17125
  }
16798
- return /* @__PURE__ */ jsx9(Circle, { size, className: "shrink-0 text-[hsl(var(--muted-foreground))]/60" });
17126
+ return /* @__PURE__ */ jsx10(Circle, { size, className: "shrink-0 text-[hsl(var(--muted-foreground))]/60" });
16799
17127
  }
16800
17128
  function PlanUpdateBlock({
16801
17129
  toolCall,
@@ -16804,10 +17132,10 @@ function PlanUpdateBlock({
16804
17132
  }) {
16805
17133
  const updateKey = `${toolCall.id}:${toolCall.arguments}`;
16806
17134
  const revealKey = autoReveal ? updateKey : null;
16807
- const [collapsed, setCollapsed] = useState17(!autoReveal);
17135
+ const [collapsed, setCollapsed] = useState18(!autoReveal);
16808
17136
  const collapseTimerRef = useRef12(null);
16809
17137
  const data = parsePlanUpdate(toolCall.arguments);
16810
- useEffect11(() => {
17138
+ useEffect12(() => {
16811
17139
  if (!revealKey) return;
16812
17140
  if (collapseTimerRef.current) clearTimeout(collapseTimerRef.current);
16813
17141
  setCollapsed(false);
@@ -16816,7 +17144,7 @@ function PlanUpdateBlock({
16816
17144
  collapseTimerRef.current = null;
16817
17145
  }, PLAN_AUTO_COLLAPSE_MS);
16818
17146
  }, [revealKey]);
16819
- useEffect11(
17147
+ useEffect12(
16820
17148
  () => () => {
16821
17149
  if (collapseTimerRef.current) clearTimeout(collapseTimerRef.current);
16822
17150
  },
@@ -16826,8 +17154,8 @@ function PlanUpdateBlock({
16826
17154
  const completed = data.plan.filter((item) => item.status === "completed").length;
16827
17155
  const currentStep = pickCurrentPlanStep(data.plan);
16828
17156
  const pausedAtCurrentStep = !running && currentStep?.status === "in_progress";
16829
- return /* @__PURE__ */ jsxs7("section", { className: "overflow-hidden", children: [
16830
- /* @__PURE__ */ jsxs7(
17157
+ return /* @__PURE__ */ jsxs8("section", { className: "overflow-hidden", children: [
17158
+ /* @__PURE__ */ jsxs8(
16831
17159
  "button",
16832
17160
  {
16833
17161
  type: "button",
@@ -16844,21 +17172,21 @@ function PlanUpdateBlock({
16844
17172
  !collapsed && "border-b border-[hsl(var(--border))]"
16845
17173
  ),
16846
17174
  children: [
16847
- collapsed && currentStep ? /* @__PURE__ */ jsxs7("span", { className: "flex min-w-0 flex-1 items-center gap-1.5 text-xs text-[hsl(var(--foreground))]", children: [
16848
- /* @__PURE__ */ jsx9(PlanStepIcon, { status: currentStep.status, size: 14, running }),
16849
- /* @__PURE__ */ jsx9("span", { className: "truncate", children: currentStep.step }),
16850
- pausedAtCurrentStep ? /* @__PURE__ */ jsx9("span", { className: "shrink-0 text-[11px] text-amber-500", children: "\u5DF2\u6682\u505C" }) : null
16851
- ] }) : /* @__PURE__ */ jsxs7("span", { className: "flex min-w-0 flex-1 items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
16852
- /* @__PURE__ */ jsx9(ListChecks, { size: 14, className: "shrink-0", "aria-hidden": "true" }),
16853
- /* @__PURE__ */ jsx9("span", { className: "truncate", children: "\u4EFB\u52A1\u8FDB\u5EA6" }),
16854
- pausedAtCurrentStep ? /* @__PURE__ */ jsx9("span", { className: "shrink-0 text-amber-500", children: "\u5DF2\u6682\u505C" }) : null
17175
+ collapsed && currentStep ? /* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-1 items-center gap-1.5 text-xs text-[hsl(var(--foreground))]", children: [
17176
+ /* @__PURE__ */ jsx10(PlanStepIcon, { status: currentStep.status, size: 14, running }),
17177
+ /* @__PURE__ */ jsx10("span", { className: "truncate", children: currentStep.step }),
17178
+ pausedAtCurrentStep ? /* @__PURE__ */ jsx10("span", { className: "shrink-0 text-[11px] text-amber-500", children: "\u5DF2\u6682\u505C" }) : null
17179
+ ] }) : /* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-1 items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
17180
+ /* @__PURE__ */ jsx10(ListChecks, { size: 14, className: "shrink-0", "aria-hidden": "true" }),
17181
+ /* @__PURE__ */ jsx10("span", { className: "truncate", children: "\u4EFB\u52A1\u8FDB\u5EA6" }),
17182
+ pausedAtCurrentStep ? /* @__PURE__ */ jsx10("span", { className: "shrink-0 text-amber-500", children: "\u5DF2\u6682\u505C" }) : null
16855
17183
  ] }),
16856
- /* @__PURE__ */ jsxs7("span", { className: "shrink-0 text-[11px] tabular-nums text-[hsl(var(--muted-foreground))]", children: [
17184
+ /* @__PURE__ */ jsxs8("span", { className: "shrink-0 text-[11px] tabular-nums text-[hsl(var(--muted-foreground))]", children: [
16857
17185
  completed,
16858
17186
  "/",
16859
17187
  data.plan.length
16860
17188
  ] }),
16861
- /* @__PURE__ */ jsx9(
17189
+ /* @__PURE__ */ jsx10(
16862
17190
  ChevronDown,
16863
17191
  {
16864
17192
  size: 14,
@@ -16871,7 +17199,7 @@ function PlanUpdateBlock({
16871
17199
  ]
16872
17200
  }
16873
17201
  ),
16874
- /* @__PURE__ */ jsx9(
17202
+ /* @__PURE__ */ jsx10(
16875
17203
  "div",
16876
17204
  {
16877
17205
  "aria-hidden": collapsed,
@@ -16879,9 +17207,9 @@ function PlanUpdateBlock({
16879
17207
  "grid transition-[grid-template-rows,opacity] duration-300 ease-out motion-reduce:transition-none",
16880
17208
  collapsed ? "grid-rows-[0fr] opacity-0" : "grid-rows-[1fr] opacity-100"
16881
17209
  ),
16882
- children: /* @__PURE__ */ jsx9("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ jsx9("div", { className: "flex max-h-40 flex-col gap-0.5 overflow-y-auto px-3 py-2", children: data.plan.length === 0 ? /* @__PURE__ */ jsx9("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u4EFB\u52A1\u6B65\u9AA4" }) : data.plan.map((item, index) => /* @__PURE__ */ jsxs7("div", { className: "flex items-start gap-2 py-0.5", children: [
16883
- /* @__PURE__ */ jsx9("span", { className: "mt-[3px] flex shrink-0", children: /* @__PURE__ */ jsx9(PlanStepIcon, { status: item.status, size: 14, running }) }),
16884
- /* @__PURE__ */ jsx9(
17210
+ children: /* @__PURE__ */ jsx10("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ jsx10("div", { className: "flex max-h-40 flex-col gap-0.5 overflow-y-auto px-3 py-2", children: data.plan.length === 0 ? /* @__PURE__ */ jsx10("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u4EFB\u52A1\u6B65\u9AA4" }) : data.plan.map((item, index) => /* @__PURE__ */ jsxs8("div", { className: "flex items-start gap-2 py-0.5", children: [
17211
+ /* @__PURE__ */ jsx10("span", { className: "mt-[3px] flex shrink-0", children: /* @__PURE__ */ jsx10(PlanStepIcon, { status: item.status, size: 14, running }) }),
17212
+ /* @__PURE__ */ jsx10(
16885
17213
  "span",
16886
17214
  {
16887
17215
  className: cn(
@@ -16906,17 +17234,17 @@ function CurrentPlanPanel({
16906
17234
  const { current, updating } = getPlanUpdateDisplayState(messages);
16907
17235
  const revealBaselinesRef = useRef12(/* @__PURE__ */ new Map([[sessionId, revealRevision]]));
16908
17236
  const autoReveal = (revealBaselinesRef.current.get(sessionId) ?? 0) !== revealRevision;
16909
- useEffect11(() => {
17237
+ useEffect12(() => {
16910
17238
  if (!current) return;
16911
17239
  revealBaselinesRef.current.set(sessionId, revealRevision);
16912
17240
  }, [current, revealRevision, sessionId]);
16913
17241
  if (!current && !updating) return null;
16914
- return /* @__PURE__ */ jsxs7("div", { className: cn("blade-chat-plan mx-auto w-full max-w-[748px] px-4", className), children: [
16915
- updating ? /* @__PURE__ */ jsxs7("div", { className: "mb-2 flex items-center gap-2 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
16916
- /* @__PURE__ */ jsx9(LoaderCircle, { size: 14, className: "shrink-0 animate-spin" }),
16917
- /* @__PURE__ */ jsx9("span", { children: "\u6B63\u5728\u66F4\u65B0\u4EFB\u52A1\u8FDB\u5EA6\u2026" })
17242
+ return /* @__PURE__ */ jsxs8("div", { className: cn("blade-chat-plan mx-auto w-full max-w-[748px] px-4", className), children: [
17243
+ updating ? /* @__PURE__ */ jsxs8("div", { className: "mb-2 flex items-center gap-2 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
17244
+ /* @__PURE__ */ jsx10(LoaderCircle, { size: 14, className: "shrink-0 animate-spin" }),
17245
+ /* @__PURE__ */ jsx10("span", { children: "\u6B63\u5728\u66F4\u65B0\u4EFB\u52A1\u8FDB\u5EA6\u2026" })
16918
17246
  ] }) : null,
16919
- current ? /* @__PURE__ */ jsx9(
17247
+ current ? /* @__PURE__ */ jsx10(
16920
17248
  PlanUpdateBlock,
16921
17249
  {
16922
17250
  toolCall: current,
@@ -16930,7 +17258,7 @@ function CurrentPlanPanel({
16930
17258
 
16931
17259
  // src/components/ChatSurface.tsx
16932
17260
  import { chatErrorForDisplay as chatErrorForDisplay2 } from "@blade-hq/agent-client";
16933
- import { useState as useState29 } from "react";
17261
+ import { useState as useState30 } from "react";
16934
17262
 
16935
17263
  // src/components/McpAppCard.tsx
16936
17264
  import { BladeApiError } from "@blade-hq/agent-client";
@@ -41782,8 +42110,8 @@ function SF(G, Q2) {
41782
42110
  }
41783
42111
 
41784
42112
  // src/components/McpAppCard.tsx
41785
- import { createContext as createContext3, useContext as useContext3, useEffect as useEffect12, useLayoutEffect, useRef as useRef13, useState as useState18 } from "react";
41786
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
42113
+ import { createContext as createContext3, useContext as useContext3, useEffect as useEffect13, useLayoutEffect, useRef as useRef13, useState as useState19 } from "react";
42114
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
41787
42115
  var McpAppMessageContext = createContext3(null);
41788
42116
  function securedHtml(archive) {
41789
42117
  const ui = archive.resourceMeta.ui;
@@ -41829,12 +42157,12 @@ function McpAppCard({ sessionId, sourceId, client: suppliedClient, onMessage: su
41829
42157
  const frame = useRef13(null);
41830
42158
  const panel = useRef13(null);
41831
42159
  const bridgeRef = useRef13(null);
41832
- const [html, setHtml] = useState18();
41833
- const [title, setTitle] = useState18("\u5DE5\u5177\u754C\u9762");
41834
- const [error61, setError] = useState18(null);
41835
- const [ready, setReady] = useState18(false);
41836
- const [expanded, setExpanded] = useState18(false);
41837
- const [height, setHeight] = useState18(360);
42160
+ const [html, setHtml] = useState19();
42161
+ const [title, setTitle] = useState19("\u5DE5\u5177\u754C\u9762");
42162
+ const [error61, setError] = useState19(null);
42163
+ const [ready, setReady] = useState19(false);
42164
+ const [expanded, setExpanded] = useState19(false);
42165
+ const [height, setHeight] = useState19(360);
41838
42166
  useLayoutEffect(() => {
41839
42167
  const dialog = panel.current;
41840
42168
  if (!dialog) return;
@@ -41842,7 +42170,7 @@ function McpAppCard({ sessionId, sourceId, client: suppliedClient, onMessage: su
41842
42170
  if (expanded) dialog.showModal();
41843
42171
  else dialog.show();
41844
42172
  }, [expanded]);
41845
- useEffect12(() => {
42173
+ useEffect13(() => {
41846
42174
  const controller = new AbortController();
41847
42175
  let bridge;
41848
42176
  let disposed = false;
@@ -41998,7 +42326,7 @@ function McpAppCard({ sessionId, sourceId, client: suppliedClient, onMessage: su
41998
42326
  setExpanded(!expanded);
41999
42327
  bridgeRef.current?.setHostContext({ displayMode: expanded ? "inline" : "fullscreen" });
42000
42328
  };
42001
- return /* @__PURE__ */ jsxs8("dialog", { ref: panel, onCancel: () => {
42329
+ return /* @__PURE__ */ jsxs9("dialog", { ref: panel, onCancel: () => {
42002
42330
  setExpanded(false);
42003
42331
  bridgeRef.current?.setHostContext({ displayMode: "inline" });
42004
42332
  }, className: "blade-mcp-app", style: expanded ? {
@@ -42020,12 +42348,12 @@ function McpAppCard({ sessionId, sourceId, client: suppliedClient, onMessage: su
42020
42348
  display: "flex",
42021
42349
  flexDirection: "column"
42022
42350
  } : { position: "relative", margin: 0, padding: 0, width: "100%", maxWidth: "none", maxHeight: "none", border: "1px solid #d4d4d8", borderRadius: 6, overflow: "hidden", background: "white" }, children: [
42023
- /* @__PURE__ */ jsxs8("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "8px 12px", color: "#27272a" }, children: [
42024
- /* @__PURE__ */ jsx10("span", { children: title }),
42025
- /* @__PURE__ */ jsx10("button", { type: "button", onClick: toggle, title: expanded ? "\u6536\u8D77" : "\u5C55\u5F00", "aria-label": expanded ? "\u6536\u8D77" : "\u5C55\u5F00", style: { width: 32, height: 32, display: "grid", placeItems: "center", background: "transparent", border: 0, padding: 0 }, children: expanded ? /* @__PURE__ */ jsx10(Minimize2, { size: 16 }) : /* @__PURE__ */ jsx10(Maximize2, { size: 16 }) })
42351
+ /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "8px 12px", color: "#27272a" }, children: [
42352
+ /* @__PURE__ */ jsx11("span", { children: title }),
42353
+ /* @__PURE__ */ jsx11("button", { type: "button", onClick: toggle, title: expanded ? "\u6536\u8D77" : "\u5C55\u5F00", "aria-label": expanded ? "\u6536\u8D77" : "\u5C55\u5F00", style: { width: 32, height: 32, display: "grid", placeItems: "center", background: "transparent", border: 0, padding: 0 }, children: expanded ? /* @__PURE__ */ jsx11(Minimize2, { size: 16 }) : /* @__PURE__ */ jsx11(Maximize2, { size: 16 }) })
42026
42354
  ] }),
42027
- error61 ? /* @__PURE__ */ jsx10("p", { role: "alert", style: { padding: 12, color: "#b91c1c" }, children: error61 }) : !ready ? /* @__PURE__ */ jsx10("output", { style: { padding: 12 }, children: "\u6B63\u5728\u52A0\u8F7D" }) : null,
42028
- /* @__PURE__ */ jsx10(
42355
+ error61 ? /* @__PURE__ */ jsx11("p", { role: "alert", style: { padding: 12, color: "#b91c1c" }, children: error61 }) : !ready ? /* @__PURE__ */ jsx11("output", { style: { padding: 12 }, children: "\u6B63\u5728\u52A0\u8F7D" }) : null,
42356
+ /* @__PURE__ */ jsx11(
42029
42357
  "iframe",
42030
42358
  {
42031
42359
  ref: frame,
@@ -42040,8 +42368,8 @@ function McpAppCard({ sessionId, sourceId, client: suppliedClient, onMessage: su
42040
42368
  }
42041
42369
 
42042
42370
  // src/components/ChatInput.tsx
42043
- import { useRef as useRef14, useState as useState19 } from "react";
42044
- import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
42371
+ import { useRef as useRef14, useState as useState20 } from "react";
42372
+ import { Fragment as Fragment5, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
42045
42373
  function isImeCompositionKey(event) {
42046
42374
  return event.isComposing || event.keyCode === 229;
42047
42375
  }
@@ -42065,7 +42393,7 @@ function ChatInput({
42065
42393
  const latestValue = useRef14(value);
42066
42394
  latestValue.current = value;
42067
42395
  const sending = useRef14(false);
42068
- const [isSending2, setIsSending] = useState19(false);
42396
+ const [isSending2, setIsSending] = useState20(false);
42069
42397
  void queueKey;
42070
42398
  const canSend = !isSending2 && (trimmed.length > 0 || hasAttachments) && (!isStreaming || !hasAttachments && !isStopping && !!onAppend);
42071
42399
  const handleSend = async () => {
@@ -42093,8 +42421,8 @@ function ChatInput({
42093
42421
  void handleSend();
42094
42422
  }
42095
42423
  };
42096
- return /* @__PURE__ */ jsx11("div", { className: cn("blade-chat-input border-t border-[hsl(var(--border))] py-3", className), children: /* @__PURE__ */ jsxs9("div", { className: "blade-chat-input-inner mx-auto flex max-w-[748px] items-end gap-2 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-2", children: [
42097
- /* @__PURE__ */ jsx11(
42424
+ return /* @__PURE__ */ jsx12("div", { className: cn("blade-chat-input border-t border-[hsl(var(--border))] py-3", className), children: /* @__PURE__ */ jsxs10("div", { className: "blade-chat-input-inner mx-auto flex max-w-[748px] items-end gap-2 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-2", children: [
42425
+ /* @__PURE__ */ jsx12(
42098
42426
  "textarea",
42099
42427
  {
42100
42428
  value,
@@ -42111,10 +42439,10 @@ function ChatInput({
42111
42439
  className: "blade-chat-textarea max-h-48 min-h-[28px] flex-1 resize-none bg-transparent py-1 text-sm leading-6 text-[hsl(var(--foreground))] outline-none placeholder:text-[hsl(var(--muted-foreground)/0.6)]"
42112
42440
  }
42113
42441
  ),
42114
- isStreaming ? /* @__PURE__ */ jsxs9(Fragment5, { children: [
42115
- /* @__PURE__ */ jsx11("button", { type: "button", onClick: handleSend, disabled: !canSend, "aria-label": "\u52A0\u5165\u6392\u961F", title: "\u52A0\u5165\u6392\u961F", className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] disabled:opacity-40", children: /* @__PURE__ */ jsx11(ArrowUp, { size: 15 }) }),
42116
- /* @__PURE__ */ jsx11("button", { type: "button", onClick: onStop, disabled: isStopping, "aria-label": isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u56DE\u590D", title: isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u56DE\u590D", className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[hsl(var(--muted))] text-[hsl(var(--foreground))] transition-opacity hover:opacity-90 disabled:opacity-60", children: isStopping ? /* @__PURE__ */ jsx11(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx11(Square, { size: 12, fill: "currentColor" }) })
42117
- ] }) : /* @__PURE__ */ jsx11(
42442
+ isStreaming ? /* @__PURE__ */ jsxs10(Fragment5, { children: [
42443
+ /* @__PURE__ */ jsx12("button", { type: "button", onClick: handleSend, disabled: !canSend, "aria-label": "\u52A0\u5165\u6392\u961F", title: "\u52A0\u5165\u6392\u961F", className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] disabled:opacity-40", children: /* @__PURE__ */ jsx12(ArrowUp, { size: 15 }) }),
42444
+ /* @__PURE__ */ jsx12("button", { type: "button", onClick: onStop, disabled: isStopping, "aria-label": isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u56DE\u590D", title: isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u56DE\u590D", className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[hsl(var(--muted))] text-[hsl(var(--foreground))] transition-opacity hover:opacity-90 disabled:opacity-60", children: isStopping ? /* @__PURE__ */ jsx12(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx12(Square, { size: 12, fill: "currentColor" }) })
42445
+ ] }) : /* @__PURE__ */ jsx12(
42118
42446
  "button",
42119
42447
  {
42120
42448
  type: "button",
@@ -42123,23 +42451,23 @@ function ChatInput({
42123
42451
  "aria-label": "\u53D1\u9001\u6D88\u606F",
42124
42452
  title: "\u53D1\u9001\u6D88\u606F",
42125
42453
  className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-40",
42126
- children: /* @__PURE__ */ jsx11(ArrowUp, { size: 15 })
42454
+ children: /* @__PURE__ */ jsx12(ArrowUp, { size: 15 })
42127
42455
  }
42128
42456
  )
42129
42457
  ] }) });
42130
42458
  }
42131
42459
 
42132
42460
  // src/components/ConnectionBanner.tsx
42133
- import { useEffect as useEffect13, useRef as useRef15, useState as useState20 } from "react";
42134
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
42461
+ import { useEffect as useEffect14, useRef as useRef15, useState as useState21 } from "react";
42462
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
42135
42463
  var CONNECTION_NOTICE_DELAY_MS = 3e3;
42136
42464
  var CONNECTION_ERROR_DELAY_MS = 15e3;
42137
42465
  function useConnectionNoticePhase(connected) {
42138
- const [phase, setPhase] = useState20("hidden");
42466
+ const [phase, setPhase] = useState21("hidden");
42139
42467
  const connectedRef = useRef15(connected);
42140
42468
  const timersRef = useRef15([]);
42141
42469
  connectedRef.current = connected;
42142
- useEffect13(() => {
42470
+ useEffect14(() => {
42143
42471
  const clearTimers = () => {
42144
42472
  for (const timer of timersRef.current) clearTimeout(timer);
42145
42473
  timersRef.current = [];
@@ -42186,7 +42514,7 @@ function ConnectionBanner({ connection, className }) {
42186
42514
  if (connected || phase === "hidden") return null;
42187
42515
  const recovering = phase === "recovering";
42188
42516
  const firstConnection = !hasConnectedRef.current;
42189
- return /* @__PURE__ */ jsx12("div", { className: cn("blade-chat-banner bg-[hsl(var(--background))] px-5 pt-3", className), children: /* @__PURE__ */ jsxs10(
42517
+ return /* @__PURE__ */ jsx13("div", { className: cn("blade-chat-banner bg-[hsl(var(--background))] px-5 pt-3", className), children: /* @__PURE__ */ jsxs11(
42190
42518
  "div",
42191
42519
  {
42192
42520
  className: cn(
@@ -42194,10 +42522,10 @@ function ConnectionBanner({ connection, className }) {
42194
42522
  recovering ? "border-amber-500/25 bg-amber-500/10 text-amber-100" : "border-rose-500/25 bg-rose-500/10 text-rose-100"
42195
42523
  ),
42196
42524
  children: [
42197
- /* @__PURE__ */ jsx12("span", { className: "mt-0.5 shrink-0", children: recovering ? /* @__PURE__ */ jsx12(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx12(TriangleAlert, { size: 14 }) }),
42198
- /* @__PURE__ */ jsxs10("div", { className: "min-w-0", children: [
42199
- /* @__PURE__ */ jsx12("div", { className: "text-sm font-medium", children: recovering ? firstConnection ? "\u6B63\u5728\u8FDE\u63A5\u2026" : "\u6B63\u5728\u6062\u590D\u8FDE\u63A5\u2026" : "\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5" }),
42200
- /* @__PURE__ */ jsx12("div", { className: "text-xs opacity-80", children: recovering ? "\u6062\u590D\u540E\u4F1A\u81EA\u52A8\u540C\u6B65\u6700\u65B0\u6D88\u606F\uFF0C\u8BF7\u7A0D\u5019" : "\u8BF7\u68C0\u67E5\u7F51\u7EDC\u6216\u670D\u52A1\u72B6\u6001\uFF0C\u7CFB\u7EDF\u4F1A\u7EE7\u7EED\u81EA\u52A8\u91CD\u8BD5" })
42525
+ /* @__PURE__ */ jsx13("span", { className: "mt-0.5 shrink-0", children: recovering ? /* @__PURE__ */ jsx13(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx13(TriangleAlert, { size: 14 }) }),
42526
+ /* @__PURE__ */ jsxs11("div", { className: "min-w-0", children: [
42527
+ /* @__PURE__ */ jsx13("div", { className: "text-sm font-medium", children: recovering ? firstConnection ? "\u6B63\u5728\u8FDE\u63A5\u2026" : "\u6B63\u5728\u6062\u590D\u8FDE\u63A5\u2026" : "\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5" }),
42528
+ /* @__PURE__ */ jsx13("div", { className: "text-xs opacity-80", children: recovering ? "\u6062\u590D\u540E\u4F1A\u81EA\u52A8\u540C\u6B65\u6700\u65B0\u6D88\u606F\uFF0C\u8BF7\u7A0D\u5019" : "\u8BF7\u68C0\u67E5\u7F51\u7EDC\u6216\u670D\u52A1\u72B6\u6001\uFF0C\u7CFB\u7EDF\u4F1A\u7EE7\u7EED\u81EA\u52A8\u91CD\u8BD5" })
42201
42529
  ] })
42202
42530
  ]
42203
42531
  }
@@ -42206,10 +42534,10 @@ function ConnectionBanner({ connection, className }) {
42206
42534
 
42207
42535
  // src/components/MessageList.tsx
42208
42536
  import { isHiddenInternalMessage } from "@blade-hq/agent-client";
42209
- import { useCallback as useCallback25, useEffect as useEffect19, useMemo as useMemo15, useRef as useRef22, useState as useState28 } from "react";
42537
+ import { useCallback as useCallback26, useEffect as useEffect20, useMemo as useMemo16, useRef as useRef22, useState as useState29 } from "react";
42210
42538
 
42211
42539
  // ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/useStickToBottom.js
42212
- import { useCallback as useCallback22, useMemo as useMemo11, useRef as useRef16, useState as useState21 } from "react";
42540
+ import { useCallback as useCallback23, useMemo as useMemo12, useRef as useRef16, useState as useState22 } from "react";
42213
42541
  var DEFAULT_SPRING_ANIMATION = {
42214
42542
  /**
42215
42543
  * A value from 0 to 1, on how much to damp the animation.
@@ -42246,12 +42574,12 @@ globalThis.document?.addEventListener("click", () => {
42246
42574
  mouseDown = false;
42247
42575
  });
42248
42576
  var useStickToBottom = (options = {}) => {
42249
- const [escapedFromLock, updateEscapedFromLock] = useState21(false);
42250
- const [isAtBottom, updateIsAtBottom] = useState21(options.initial !== false);
42251
- const [isNearBottom, setIsNearBottom] = useState21(false);
42577
+ const [escapedFromLock, updateEscapedFromLock] = useState22(false);
42578
+ const [isAtBottom, updateIsAtBottom] = useState22(options.initial !== false);
42579
+ const [isNearBottom, setIsNearBottom] = useState22(false);
42252
42580
  const optionsRef = useRef16(null);
42253
42581
  optionsRef.current = options;
42254
- const isSelecting = useCallback22(() => {
42582
+ const isSelecting = useCallback23(() => {
42255
42583
  if (!mouseDown) {
42256
42584
  return false;
42257
42585
  }
@@ -42262,15 +42590,15 @@ var useStickToBottom = (options = {}) => {
42262
42590
  const range = selection.getRangeAt(0);
42263
42591
  return range.commonAncestorContainer.contains(scrollRef.current) || scrollRef.current?.contains(range.commonAncestorContainer);
42264
42592
  }, []);
42265
- const setIsAtBottom = useCallback22((isAtBottom2) => {
42593
+ const setIsAtBottom = useCallback23((isAtBottom2) => {
42266
42594
  state.isAtBottom = isAtBottom2;
42267
42595
  updateIsAtBottom(isAtBottom2);
42268
42596
  }, []);
42269
- const setEscapedFromLock = useCallback22((escapedFromLock2) => {
42597
+ const setEscapedFromLock = useCallback23((escapedFromLock2) => {
42270
42598
  state.escapedFromLock = escapedFromLock2;
42271
42599
  updateEscapedFromLock(escapedFromLock2);
42272
42600
  }, []);
42273
- const state = useMemo11(() => {
42601
+ const state = useMemo12(() => {
42274
42602
  let lastCalculation;
42275
42603
  return {
42276
42604
  escapedFromLock,
@@ -42323,7 +42651,7 @@ var useStickToBottom = (options = {}) => {
42323
42651
  }
42324
42652
  };
42325
42653
  }, []);
42326
- const scrollToBottom = useCallback22((scrollOptions = {}) => {
42654
+ const scrollToBottom = useCallback23((scrollOptions = {}) => {
42327
42655
  if (typeof scrollOptions === "string") {
42328
42656
  scrollOptions = { animation: scrollOptions };
42329
42657
  }
@@ -42408,11 +42736,11 @@ var useStickToBottom = (options = {}) => {
42408
42736
  }
42409
42737
  return next();
42410
42738
  }, [setIsAtBottom, isSelecting, state]);
42411
- const stopScroll = useCallback22(() => {
42739
+ const stopScroll = useCallback23(() => {
42412
42740
  setEscapedFromLock(true);
42413
42741
  setIsAtBottom(false);
42414
42742
  }, [setEscapedFromLock, setIsAtBottom]);
42415
- const handleScroll = useCallback22(({ target }) => {
42743
+ const handleScroll = useCallback23(({ target }) => {
42416
42744
  if (target !== scrollRef.current) {
42417
42745
  return;
42418
42746
  }
@@ -42451,7 +42779,7 @@ var useStickToBottom = (options = {}) => {
42451
42779
  }
42452
42780
  }, 1);
42453
42781
  }, [setEscapedFromLock, setIsAtBottom, isSelecting, state]);
42454
- const handleWheel = useCallback22(({ target, deltaY }) => {
42782
+ const handleWheel = useCallback23(({ target, deltaY }) => {
42455
42783
  let element = target;
42456
42784
  while (!["scroll", "auto"].includes(getComputedStyle(element).overflow)) {
42457
42785
  if (!element.parentElement) {
@@ -42521,7 +42849,7 @@ var useStickToBottom = (options = {}) => {
42521
42849
  };
42522
42850
  };
42523
42851
  function useRefCallback(callback, deps) {
42524
- const result = useCallback22((ref) => {
42852
+ const result = useCallback23((ref) => {
42525
42853
  result.current = ref;
42526
42854
  return callback(ref);
42527
42855
  }, deps);
@@ -42553,9 +42881,9 @@ function mergeAnimations(...animations) {
42553
42881
 
42554
42882
  // ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/StickToBottom.js
42555
42883
  import * as React from "react";
42556
- import { createContext as createContext4, useContext as useContext4, useEffect as useEffect14, useImperativeHandle, useLayoutEffect as useLayoutEffect2, useMemo as useMemo12, useRef as useRef17 } from "react";
42884
+ import { createContext as createContext4, useContext as useContext4, useEffect as useEffect15, useImperativeHandle, useLayoutEffect as useLayoutEffect2, useMemo as useMemo13, useRef as useRef17 } from "react";
42557
42885
  var StickToBottomContext = createContext4(null);
42558
- var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect2 : useEffect14;
42886
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect2 : useEffect15;
42559
42887
  function StickToBottom({ instance, children, resize, initial, mass, damping, stiffness, targetScrollTop: currentTargetScrollTop, contextRef, ...props }) {
42560
42888
  const customTargetScrollTop = useRef17(null);
42561
42889
  const targetScrollTop = React.useCallback((target, elements) => {
@@ -42571,7 +42899,7 @@ function StickToBottom({ instance, children, resize, initial, mass, damping, sti
42571
42899
  targetScrollTop
42572
42900
  });
42573
42901
  const { scrollRef, contentRef, scrollToBottom, stopScroll, isAtBottom, escapedFromLock, state } = instance ?? defaultInstance;
42574
- const context = useMemo12(() => ({
42902
+ const context = useMemo13(() => ({
42575
42903
  scrollToBottom,
42576
42904
  stopScroll,
42577
42905
  scrollRef,
@@ -42640,11 +42968,11 @@ import {
42640
42968
  getTextContent,
42641
42969
  normalizeMessageContent
42642
42970
  } from "@blade-hq/agent-client";
42643
- import { useEffect as useEffect17, useRef as useRef20, useState as useState26 } from "react";
42971
+ import { useEffect as useEffect18, useRef as useRef20, useState as useState27 } from "react";
42644
42972
 
42645
42973
  // src/components/AgentLoopBlock.tsx
42646
- import { useState as useState22 } from "react";
42647
- import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
42974
+ import { useState as useState23 } from "react";
42975
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
42648
42976
  function parseAgentDescription(argumentsJson) {
42649
42977
  try {
42650
42978
  const parsed = JSON.parse(argumentsJson);
@@ -42654,7 +42982,7 @@ function parseAgentDescription(argumentsJson) {
42654
42982
  }
42655
42983
  }
42656
42984
  function AgentLoopBlock({ toolCall }) {
42657
- const [expanded, setExpanded] = useState22(false);
42985
+ const [expanded, setExpanded] = useState23(false);
42658
42986
  const description = parseAgentDescription(toolCall.arguments);
42659
42987
  const running = toolCall.status === "pending" || toolCall.status === "awaiting_answer";
42660
42988
  const failed = toolCall.status === "error" || toolCall.status === "cancelled";
@@ -42663,8 +42991,8 @@ function AgentLoopBlock({ toolCall }) {
42663
42991
  "size-3.5 shrink-0",
42664
42992
  failed ? "text-red-500" : "text-[hsl(var(--muted-foreground))]"
42665
42993
  );
42666
- return /* @__PURE__ */ jsxs11("div", { className: "blade-chat-agent-loop text-xs leading-[22px]", children: [
42667
- /* @__PURE__ */ jsxs11(
42994
+ return /* @__PURE__ */ jsxs12("div", { className: "blade-chat-agent-loop text-xs leading-[22px]", children: [
42995
+ /* @__PURE__ */ jsxs12(
42668
42996
  "button",
42669
42997
  {
42670
42998
  type: "button",
@@ -42679,12 +43007,12 @@ function AgentLoopBlock({ toolCall }) {
42679
43007
  ),
42680
43008
  title: `\u5B50\u4EFB\u52A1\uFF1A${description}`,
42681
43009
  children: [
42682
- running ? /* @__PURE__ */ jsx13(LoaderCircle, { className: cn(iconClass, "animate-spin"), "aria-hidden": "true" }) : toolCall.status === "error" ? /* @__PURE__ */ jsx13(CircleAlert, { className: iconClass, "aria-hidden": "true" }) : toolCall.status === "cancelled" ? /* @__PURE__ */ jsx13(X, { className: iconClass, "aria-hidden": "true" }) : /* @__PURE__ */ jsx13(Bot, { className: iconClass, "aria-hidden": "true" }),
42683
- /* @__PURE__ */ jsxs11("span", { className: "min-w-0 truncate", children: [
43010
+ running ? /* @__PURE__ */ jsx14(LoaderCircle, { className: cn(iconClass, "animate-spin"), "aria-hidden": "true" }) : toolCall.status === "error" ? /* @__PURE__ */ jsx14(CircleAlert, { className: iconClass, "aria-hidden": "true" }) : toolCall.status === "cancelled" ? /* @__PURE__ */ jsx14(X, { className: iconClass, "aria-hidden": "true" }) : /* @__PURE__ */ jsx14(Bot, { className: iconClass, "aria-hidden": "true" }),
43011
+ /* @__PURE__ */ jsxs12("span", { className: "min-w-0 truncate", children: [
42684
43012
  "\u5B50\u4EFB\u52A1\uFF1A",
42685
43013
  description
42686
43014
  ] }),
42687
- hasResult ? /* @__PURE__ */ jsx13(
43015
+ hasResult ? /* @__PURE__ */ jsx14(
42688
43016
  ChevronRight,
42689
43017
  {
42690
43018
  size: 14,
@@ -42699,18 +43027,18 @@ function AgentLoopBlock({ toolCall }) {
42699
43027
  ]
42700
43028
  }
42701
43029
  ),
42702
- expanded && hasResult ? /* @__PURE__ */ jsx13("div", { className: "ml-[18px] mt-1.5 max-h-[400px] overflow-auto whitespace-pre-wrap text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", children: formatToolResult(toolCall.result) }) : null
43030
+ expanded && hasResult ? /* @__PURE__ */ jsx14("div", { className: "ml-[18px] mt-1.5 max-h-[400px] overflow-auto whitespace-pre-wrap text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", children: formatToolResult(toolCall.result) }) : null
42703
43031
  ] });
42704
43032
  }
42705
43033
 
42706
43034
  // src/components/MarkdownContent.tsx
42707
43035
  import {
42708
- useEffect as useEffect15,
42709
- useMemo as useMemo13,
43036
+ useEffect as useEffect16,
43037
+ useMemo as useMemo14,
42710
43038
  useRef as useRef18,
42711
- useState as useState23
43039
+ useState as useState24
42712
43040
  } from "react";
42713
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
43041
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
42714
43042
  var SYSTEM_REMINDER_RE = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
42715
43043
  function normalizeAdjacentUrlFormatting(value) {
42716
43044
  const protectedSegments = [];
@@ -42726,9 +43054,9 @@ function normalizeAdjacentUrlFormatting(value) {
42726
43054
  }
42727
43055
  function CodeBlockPre({ children, node: _node, ...props }) {
42728
43056
  const preRef = useRef18(null);
42729
- const [copied, setCopied] = useState23(false);
42730
- const [language, setLanguage] = useState23("");
42731
- useEffect15(() => {
43057
+ const [copied, setCopied] = useState24(false);
43058
+ const [language, setLanguage] = useState24("");
43059
+ useEffect16(() => {
42732
43060
  const codeEl = preRef.current?.querySelector("code");
42733
43061
  setLanguage(codeEl?.className.match(/language-(\S+)/)?.[1] ?? "");
42734
43062
  }, []);
@@ -42739,10 +43067,10 @@ function CodeBlockPre({ children, node: _node, ...props }) {
42739
43067
  setTimeout(() => setCopied(false), 2e3);
42740
43068
  }
42741
43069
  };
42742
- return /* @__PURE__ */ jsxs12("div", { className: "blade-chat-codeblock not-prose my-3 overflow-hidden rounded-xl border border-[hsl(var(--border))]", children: [
42743
- /* @__PURE__ */ jsxs12("div", { className: "blade-chat-codeblock-header flex h-[34px] items-center justify-between border-b border-[hsl(var(--border))] bg-[hsl(var(--muted))/0.5] pl-3.5 pr-1.5", children: [
42744
- /* @__PURE__ */ jsx14("span", { className: "font-mono text-[12px] text-[hsl(var(--muted-foreground))]", children: language || "code" }),
42745
- /* @__PURE__ */ jsxs12(
43070
+ return /* @__PURE__ */ jsxs13("div", { className: "blade-chat-codeblock not-prose my-3 overflow-hidden rounded-xl border border-[hsl(var(--border))]", children: [
43071
+ /* @__PURE__ */ jsxs13("div", { className: "blade-chat-codeblock-header flex h-[34px] items-center justify-between border-b border-[hsl(var(--border))] bg-[hsl(var(--muted))/0.5] pl-3.5 pr-1.5", children: [
43072
+ /* @__PURE__ */ jsx15("span", { className: "font-mono text-[12px] text-[hsl(var(--muted-foreground))]", children: language || "code" }),
43073
+ /* @__PURE__ */ jsxs13(
42746
43074
  "button",
42747
43075
  {
42748
43076
  type: "button",
@@ -42752,13 +43080,13 @@ function CodeBlockPre({ children, node: _node, ...props }) {
42752
43080
  copied ? "text-[hsl(var(--primary))]" : "text-[hsl(var(--muted-foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]"
42753
43081
  ),
42754
43082
  children: [
42755
- copied ? /* @__PURE__ */ jsx14(Check, { size: 12 }) : /* @__PURE__ */ jsx14(Copy, { size: 12 }),
42756
- /* @__PURE__ */ jsx14("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
43083
+ copied ? /* @__PURE__ */ jsx15(Check, { size: 12 }) : /* @__PURE__ */ jsx15(Copy, { size: 12 }),
43084
+ /* @__PURE__ */ jsx15("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
42757
43085
  ]
42758
43086
  }
42759
43087
  )
42760
43088
  ] }),
42761
- /* @__PURE__ */ jsx14(
43089
+ /* @__PURE__ */ jsx15(
42762
43090
  "pre",
42763
43091
  {
42764
43092
  ref: preRef,
@@ -42770,17 +43098,17 @@ function CodeBlockPre({ children, node: _node, ...props }) {
42770
43098
  ] });
42771
43099
  }
42772
43100
  function ExternalAnchor({ node: _node, children, ...props }) {
42773
- return /* @__PURE__ */ jsx14("a", { ...props, target: "_blank", rel: "noopener noreferrer", children });
43101
+ return /* @__PURE__ */ jsx15("a", { ...props, target: "_blank", rel: "noopener noreferrer", children });
42774
43102
  }
42775
43103
  var MARKDOWN_COMPONENTS = {
42776
43104
  pre: CodeBlockPre,
42777
43105
  a: ExternalAnchor
42778
43106
  };
42779
43107
  function MarkdownContent({ children, className, mode, sessionId }) {
42780
- const resolvedChildren = useMemo13(() => {
43108
+ const resolvedChildren = useMemo14(() => {
42781
43109
  return normalizeAdjacentUrlFormatting(children.replace(SYSTEM_REMINDER_RE, ""));
42782
43110
  }, [children]);
42783
- return /* @__PURE__ */ jsx14(
43111
+ return /* @__PURE__ */ jsx15(
42784
43112
  _r,
42785
43113
  {
42786
43114
  className: cn("blade-chat-markdown break-words", className),
@@ -42793,17 +43121,17 @@ function MarkdownContent({ children, className, mode, sessionId }) {
42793
43121
  }
42794
43122
 
42795
43123
  // src/components/Shimmer.tsx
42796
- import { jsx as jsx15 } from "react/jsx-runtime";
43124
+ import { jsx as jsx16 } from "react/jsx-runtime";
42797
43125
  function Shimmer({ children = "\u6B63\u5728\u601D\u8003...", className }) {
42798
- return /* @__PURE__ */ jsx15("span", { className: cn("blade-shimmer-text text-sm font-medium", className), children });
43126
+ return /* @__PURE__ */ jsx16("span", { className: cn("blade-shimmer-text text-sm font-medium", className), children });
42799
43127
  }
42800
43128
 
42801
43129
  // src/components/ToolCallBlock.tsx
42802
- import { useState as useState25 } from "react";
43130
+ import { useState as useState26 } from "react";
42803
43131
 
42804
43132
  // src/components/AskUserQuestionBlock.tsx
42805
- import { useEffect as useEffect16, useMemo as useMemo14, useRef as useRef19, useState as useState24 } from "react";
42806
- import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
43133
+ import { useEffect as useEffect17, useMemo as useMemo15, useRef as useRef19, useState as useState25 } from "react";
43134
+ import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
42807
43135
  var CUSTOM_TEXTAREA_MAX_HEIGHT = 160;
42808
43136
  function resizeCustomTextarea(textarea) {
42809
43137
  textarea.style.height = "auto";
@@ -42812,11 +43140,11 @@ function resizeCustomTextarea(textarea) {
42812
43140
  }
42813
43141
  function useAutoResizeTextarea(value) {
42814
43142
  const textareaRef = useRef19(null);
42815
- useEffect16(() => {
43143
+ useEffect17(() => {
42816
43144
  const textarea = textareaRef.current;
42817
43145
  if (textarea?.value === value) resizeCustomTextarea(textarea);
42818
43146
  }, [value]);
42819
- useEffect16(() => {
43147
+ useEffect17(() => {
42820
43148
  const textarea = textareaRef.current;
42821
43149
  if (!textarea || typeof ResizeObserver === "undefined") return;
42822
43150
  let previousWidth = textarea.clientWidth;
@@ -42841,17 +43169,17 @@ function AskUserQuestionBlock({
42841
43169
  answerData,
42842
43170
  onAnswer
42843
43171
  }) {
42844
- const [selections, setSelections] = useState24(/* @__PURE__ */ new Map());
42845
- const [customTexts, setCustomTexts] = useState24(/* @__PURE__ */ new Map());
42846
- const [usingCustom, setUsingCustom] = useState24(/* @__PURE__ */ new Set());
42847
- const [note, setNote] = useState24("");
42848
- const [submitted, setSubmitted] = useState24(false);
42849
- useEffect16(() => {
43172
+ const [selections, setSelections] = useState25(/* @__PURE__ */ new Map());
43173
+ const [customTexts, setCustomTexts] = useState25(/* @__PURE__ */ new Map());
43174
+ const [usingCustom, setUsingCustom] = useState25(/* @__PURE__ */ new Set());
43175
+ const [note, setNote] = useState25("");
43176
+ const [submitted, setSubmitted] = useState25(false);
43177
+ useEffect17(() => {
42850
43178
  if (sessionStatus === "failed" || sessionStatus === "interrupted") {
42851
43179
  setSubmitted(false);
42852
43180
  }
42853
43181
  }, [sessionStatus]);
42854
- const displayAnswerState = useMemo14(() => {
43182
+ const displayAnswerState = useMemo15(() => {
42855
43183
  if (!(answered && answerData)) {
42856
43184
  return { selections, customTexts, usingCustom, note };
42857
43185
  }
@@ -42944,7 +43272,7 @@ ${parts.join("\n")}`,
42944
43272
  setSubmitted(true);
42945
43273
  onAnswer(text, toolCallId, nextAnswerData);
42946
43274
  };
42947
- return /* @__PURE__ */ jsxs13(
43275
+ return /* @__PURE__ */ jsxs14(
42948
43276
  "div",
42949
43277
  {
42950
43278
  className: cn(
@@ -42952,12 +43280,12 @@ ${parts.join("\n")}`,
42952
43280
  answered ? "max-w-2xl space-y-3 p-3 text-xs text-[hsl(var(--muted-foreground))] opacity-80" : "max-w-lg space-y-5 p-4 text-sm"
42953
43281
  ),
42954
43282
  children: [
42955
- data.source_loop?.description && /* @__PURE__ */ jsxs13("div", { className: "rounded-lg bg-[hsl(var(--muted)/0.35)] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
43283
+ data.source_loop?.description && /* @__PURE__ */ jsxs14("div", { className: "rounded-lg bg-[hsl(var(--muted)/0.35)] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
42956
43284
  "\u5B50\u667A\u80FD\u4F53\u300C",
42957
43285
  data.source_loop.description,
42958
43286
  "\u300D\u5728\u7B49\u5F85\u4F60\u7684\u56DE\u7B54"
42959
43287
  ] }),
42960
- data.questions.map((q2, qIdx) => /* @__PURE__ */ jsx16(
43288
+ data.questions.map((q2, qIdx) => /* @__PURE__ */ jsx17(
42961
43289
  QuestionCard,
42962
43290
  {
42963
43291
  question: q2,
@@ -42972,7 +43300,7 @@ ${parts.join("\n")}`,
42972
43300
  },
42973
43301
  q2.question
42974
43302
  )),
42975
- /* @__PURE__ */ jsx16(
43303
+ /* @__PURE__ */ jsx17(
42976
43304
  NoteField,
42977
43305
  {
42978
43306
  answered,
@@ -42981,7 +43309,7 @@ ${parts.join("\n")}`,
42981
43309
  onChange: setNote
42982
43310
  }
42983
43311
  ),
42984
- !answered && !submitted && onAnswer && /* @__PURE__ */ jsx16(
43312
+ !answered && !submitted && onAnswer && /* @__PURE__ */ jsx17(
42985
43313
  "button",
42986
43314
  {
42987
43315
  type: "button",
@@ -42991,14 +43319,14 @@ ${parts.join("\n")}`,
42991
43319
  children: allAnswered ? "\u786E\u8BA4" : "\u8BF7\u5148\u9009\u62E9\u4E00\u4E2A\u9009\u9879"
42992
43320
  }
42993
43321
  ),
42994
- submitted && !answered && /* @__PURE__ */ jsxs13(
43322
+ submitted && !answered && /* @__PURE__ */ jsxs14(
42995
43323
  "button",
42996
43324
  {
42997
43325
  type: "button",
42998
43326
  disabled: true,
42999
43327
  className: "flex w-full items-center justify-center gap-2 rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-xs font-semibold text-[hsl(var(--primary-foreground))] opacity-80",
43000
43328
  children: [
43001
- /* @__PURE__ */ jsx16(LoaderCircle, { size: 14, className: "animate-spin" }),
43329
+ /* @__PURE__ */ jsx17(LoaderCircle, { size: 14, className: "animate-spin" }),
43002
43330
  "\u786E\u8BA4\u4E2D"
43003
43331
  ]
43004
43332
  }
@@ -43020,30 +43348,30 @@ function QuestionCard({
43020
43348
  }) {
43021
43349
  const multi = question.multiSelect ?? false;
43022
43350
  const customTextareaRef = useAutoResizeTextarea(customText);
43023
- return /* @__PURE__ */ jsxs13("div", { children: [
43024
- /* @__PURE__ */ jsxs13("div", { className: cn("flex items-start gap-2", answered ? "mb-2" : "mb-3"), children: [
43025
- /* @__PURE__ */ jsx16(
43351
+ return /* @__PURE__ */ jsxs14("div", { children: [
43352
+ /* @__PURE__ */ jsxs14("div", { className: cn("flex items-start gap-2", answered ? "mb-2" : "mb-3"), children: [
43353
+ /* @__PURE__ */ jsx17(
43026
43354
  MessageSquareMore,
43027
43355
  {
43028
43356
  size: answered ? 12 : 13,
43029
43357
  className: "mt-0.5 shrink-0 text-[hsl(var(--primary))]"
43030
43358
  }
43031
43359
  ),
43032
- /* @__PURE__ */ jsx16(
43360
+ /* @__PURE__ */ jsx17(
43033
43361
  "div",
43034
43362
  {
43035
43363
  className: cn(
43036
43364
  "min-w-0 flex-1 font-medium text-[hsl(var(--foreground))]",
43037
43365
  answered ? "text-xs" : "text-sm"
43038
43366
  ),
43039
- children: /* @__PURE__ */ jsx16(MarkdownContent, { className: "blade-chat-prose", children: question.question })
43367
+ children: /* @__PURE__ */ jsx17(MarkdownContent, { className: "blade-chat-prose", children: question.question })
43040
43368
  }
43041
43369
  )
43042
43370
  ] }),
43043
- /* @__PURE__ */ jsxs13("div", { className: cn("flex flex-col pl-5", answered ? "gap-1" : "gap-1.5"), children: [
43371
+ /* @__PURE__ */ jsxs14("div", { className: cn("flex flex-col pl-5", answered ? "gap-1" : "gap-1.5"), children: [
43044
43372
  question.options.map((opt, optIdx) => {
43045
43373
  const isSel = selected.has(optIdx);
43046
- return /* @__PURE__ */ jsxs13(
43374
+ return /* @__PURE__ */ jsxs14(
43047
43375
  "button",
43048
43376
  {
43049
43377
  type: "button",
@@ -43057,14 +43385,14 @@ function QuestionCard({
43057
43385
  answered && "cursor-default opacity-70"
43058
43386
  ),
43059
43387
  children: [
43060
- multi && /* @__PURE__ */ jsx16(
43388
+ multi && /* @__PURE__ */ jsx17(
43061
43389
  "div",
43062
43390
  {
43063
43391
  className: cn(
43064
43392
  "mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors",
43065
43393
  isSel && !answered ? "border-[hsl(var(--primary-foreground)/0.6)] bg-[hsl(var(--primary-foreground)/0.2)]" : isSel ? "border-[hsl(var(--primary)/0.45)] bg-[hsl(var(--primary)/0.12)]" : "border-[hsl(var(--border))]"
43066
43394
  ),
43067
- children: isSel && /* @__PURE__ */ jsx16(
43395
+ children: isSel && /* @__PURE__ */ jsx17(
43068
43396
  Check,
43069
43397
  {
43070
43398
  size: 9,
@@ -43073,9 +43401,9 @@ function QuestionCard({
43073
43401
  )
43074
43402
  }
43075
43403
  ),
43076
- /* @__PURE__ */ jsxs13("div", { className: "min-w-0", children: [
43077
- /* @__PURE__ */ jsx16("div", { className: cn("font-medium", answered ? "text-xs" : "text-[13px]"), children: opt.label }),
43078
- opt.description && /* @__PURE__ */ jsx16(
43404
+ /* @__PURE__ */ jsxs14("div", { className: "min-w-0", children: [
43405
+ /* @__PURE__ */ jsx17("div", { className: cn("font-medium", answered ? "text-xs" : "text-[13px]"), children: opt.label }),
43406
+ opt.description && /* @__PURE__ */ jsx17(
43079
43407
  "div",
43080
43408
  {
43081
43409
  className: cn(
@@ -43092,7 +43420,7 @@ function QuestionCard({
43092
43420
  opt.label
43093
43421
  );
43094
43422
  }),
43095
- answered && !isCustom ? null : /* @__PURE__ */ jsxs13(
43423
+ answered && !isCustom ? null : /* @__PURE__ */ jsxs14(
43096
43424
  "div",
43097
43425
  {
43098
43426
  className: cn(
@@ -43102,8 +43430,8 @@ function QuestionCard({
43102
43430
  answered && "cursor-default opacity-70"
43103
43431
  ),
43104
43432
  children: [
43105
- /* @__PURE__ */ jsx16("span", { className: "shrink-0 pt-1 text-xs text-[hsl(var(--muted-foreground))]", children: "\u5176\u4ED6\uFF1A" }),
43106
- /* @__PURE__ */ jsx16(
43433
+ /* @__PURE__ */ jsx17("span", { className: "shrink-0 pt-1 text-xs text-[hsl(var(--muted-foreground))]", children: "\u5176\u4ED6\uFF1A" }),
43434
+ /* @__PURE__ */ jsx17(
43107
43435
  "textarea",
43108
43436
  {
43109
43437
  ref: customTextareaRef,
@@ -43135,7 +43463,7 @@ function NoteField({
43135
43463
  const textareaRef = useAutoResizeTextarea(note);
43136
43464
  const readOnly = answered || submitted;
43137
43465
  if (answered && !note.trim()) return null;
43138
- return /* @__PURE__ */ jsxs13(
43466
+ return /* @__PURE__ */ jsxs14(
43139
43467
  "label",
43140
43468
  {
43141
43469
  className: cn(
@@ -43145,8 +43473,8 @@ function NoteField({
43145
43473
  readOnly && "cursor-default opacity-70"
43146
43474
  ),
43147
43475
  children: [
43148
- /* @__PURE__ */ jsx16("span", { className: "mb-1.5 block text-xs text-[hsl(var(--muted-foreground))]", children: "\u8865\u5145\u8BF4\u660E\uFF08\u53EF\u9009\uFF09" }),
43149
- /* @__PURE__ */ jsx16(
43476
+ /* @__PURE__ */ jsx17("span", { className: "mb-1.5 block text-xs text-[hsl(var(--muted-foreground))]", children: "\u8865\u5145\u8BF4\u660E\uFF08\u53EF\u9009\uFF09" }),
43477
+ /* @__PURE__ */ jsx17(
43150
43478
  "textarea",
43151
43479
  {
43152
43480
  ref: textareaRef,
@@ -43235,7 +43563,7 @@ function normalizeOptionItem(value) {
43235
43563
  }
43236
43564
 
43237
43565
  // src/components/ToolCallBlock.tsx
43238
- import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
43566
+ import { Fragment as Fragment6, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
43239
43567
  function resolveAskQuestionState({
43240
43568
  toolStatus,
43241
43569
  hasAnswerData,
@@ -43257,12 +43585,12 @@ function ToolCallBlock({
43257
43585
  isActiveQuestion,
43258
43586
  renderer
43259
43587
  }) {
43260
- const [expanded, setExpanded] = useState25(false);
43588
+ const [expanded, setExpanded] = useState26(false);
43261
43589
  const normalizedName = formatToolName(toolCall.name);
43262
43590
  if (renderer) {
43263
43591
  const custom2 = renderer(toolCall);
43264
43592
  if (custom2 !== null && custom2 !== void 0) {
43265
- return /* @__PURE__ */ jsx17(Fragment6, { children: custom2 });
43593
+ return /* @__PURE__ */ jsx18(Fragment6, { children: custom2 });
43266
43594
  }
43267
43595
  }
43268
43596
  if (normalizedName === "AskUserQuestion") {
@@ -43275,7 +43603,7 @@ function ToolCallBlock({
43275
43603
  });
43276
43604
  const canAnswer = questionState.awaitingAnswer && Boolean(onAnswer);
43277
43605
  if (askData) {
43278
- return /* @__PURE__ */ jsx17(
43606
+ return /* @__PURE__ */ jsx18(
43279
43607
  AskUserQuestionBlock,
43280
43608
  {
43281
43609
  data: askData,
@@ -43288,31 +43616,31 @@ function ToolCallBlock({
43288
43616
  );
43289
43617
  }
43290
43618
  if (toolCall.status === "pending") {
43291
- return /* @__PURE__ */ jsxs14("div", { className: "ml-4 flex max-w-lg items-center gap-2 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-4 text-sm text-[hsl(var(--muted-foreground))]", children: [
43292
- /* @__PURE__ */ jsx17(LoaderCircle, { size: 14, className: "animate-spin" }),
43293
- /* @__PURE__ */ jsx17("span", { children: "\u6B63\u5728\u51C6\u5907\u95EE\u9898\u2026" })
43619
+ return /* @__PURE__ */ jsxs15("div", { className: "ml-4 flex max-w-lg items-center gap-2 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-4 text-sm text-[hsl(var(--muted-foreground))]", children: [
43620
+ /* @__PURE__ */ jsx18(LoaderCircle, { size: 14, className: "animate-spin" }),
43621
+ /* @__PURE__ */ jsx18("span", { children: "\u6B63\u5728\u51C6\u5907\u95EE\u9898\u2026" })
43294
43622
  ] });
43295
43623
  }
43296
43624
  const errorDetail = parseAskUserQuestionError(
43297
43625
  typeof toolCall.result === "string" ? toolCall.result : null
43298
43626
  );
43299
- return /* @__PURE__ */ jsxs14("div", { className: "ml-4 max-w-lg rounded-xl border border-amber-500/35 bg-amber-500/10 p-4 text-sm text-[hsl(var(--foreground))]", children: [
43300
- /* @__PURE__ */ jsx17("div", { className: "font-semibold", children: "\u9009\u62E9\u9898\u5185\u5BB9\u6682\u65F6\u65E0\u6CD5\u663E\u793A" }),
43301
- /* @__PURE__ */ jsx17("div", { className: "mt-1 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: errorDetail?.message ?? "\u6536\u5230\u7684\u4EA4\u4E92\u6570\u636E\u4E0D\u5B8C\u6574\u3002\u8BF7\u8BA9\u667A\u80FD\u4F53\u91CD\u65B0\u63D0\u95EE\u3002" }),
43302
- errorDetail?.detail ? /* @__PURE__ */ jsxs14("details", { className: "mt-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
43303
- /* @__PURE__ */ jsx17("summary", { className: "cursor-pointer", children: "\u67E5\u770B\u5177\u4F53\u539F\u56E0" }),
43304
- /* @__PURE__ */ jsx17("div", { className: "mt-1 break-words font-mono", children: errorDetail.detail })
43627
+ return /* @__PURE__ */ jsxs15("div", { className: "ml-4 max-w-lg rounded-xl border border-amber-500/35 bg-amber-500/10 p-4 text-sm text-[hsl(var(--foreground))]", children: [
43628
+ /* @__PURE__ */ jsx18("div", { className: "font-semibold", children: "\u9009\u62E9\u9898\u5185\u5BB9\u6682\u65F6\u65E0\u6CD5\u663E\u793A" }),
43629
+ /* @__PURE__ */ jsx18("div", { className: "mt-1 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: errorDetail?.message ?? "\u6536\u5230\u7684\u4EA4\u4E92\u6570\u636E\u4E0D\u5B8C\u6574\u3002\u8BF7\u8BA9\u667A\u80FD\u4F53\u91CD\u65B0\u63D0\u95EE\u3002" }),
43630
+ errorDetail?.detail ? /* @__PURE__ */ jsxs15("details", { className: "mt-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
43631
+ /* @__PURE__ */ jsx18("summary", { className: "cursor-pointer", children: "\u67E5\u770B\u5177\u4F53\u539F\u56E0" }),
43632
+ /* @__PURE__ */ jsx18("div", { className: "mt-1 break-words font-mono", children: errorDetail.detail })
43305
43633
  ] }) : null
43306
43634
  ] });
43307
43635
  }
43308
43636
  const tone = getToolTone(toolCall.status);
43309
43637
  const displayName = getToolDisplayLabel(toolCall);
43310
43638
  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))]";
43311
- const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx17(LoaderCircle, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx17(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx17(X, { size: 11 }) : /* @__PURE__ */ jsx17(Check, { size: 11 });
43639
+ const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx18(LoaderCircle, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx18(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx18(X, { size: 11 }) : /* @__PURE__ */ jsx18(Check, { size: 11 });
43312
43640
  const statusTextClass = tone === "red" ? "text-[hsl(var(--muted-foreground))]" : tone === "amber" ? "text-amber-300" : tone === "blue" ? "text-blue-300" : "text-[hsl(var(--primary))]";
43313
- return /* @__PURE__ */ jsxs14("div", { className: "blade-chat-tool ml-4 text-xs", children: [
43314
- /* @__PURE__ */ jsxs14("div", { className: cn("border-l-[3px] flex items-center gap-2 px-3 py-2", toneClass), children: [
43315
- /* @__PURE__ */ jsxs14(
43641
+ return /* @__PURE__ */ jsxs15("div", { className: "blade-chat-tool ml-4 text-xs", children: [
43642
+ /* @__PURE__ */ jsxs15("div", { className: cn("border-l-[3px] flex items-center gap-2 px-3 py-2", toneClass), children: [
43643
+ /* @__PURE__ */ jsxs15(
43316
43644
  "button",
43317
43645
  {
43318
43646
  type: "button",
@@ -43320,7 +43648,7 @@ function ToolCallBlock({
43320
43648
  className: "flex 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",
43321
43649
  "aria-expanded": expanded,
43322
43650
  children: [
43323
- /* @__PURE__ */ jsx17(
43651
+ /* @__PURE__ */ jsx18(
43324
43652
  ChevronRight,
43325
43653
  {
43326
43654
  size: 11,
@@ -43330,24 +43658,24 @@ function ToolCallBlock({
43330
43658
  )
43331
43659
  }
43332
43660
  ),
43333
- /* @__PURE__ */ jsxs14("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
43661
+ /* @__PURE__ */ jsxs15("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
43334
43662
  statusIcon,
43335
- /* @__PURE__ */ jsx17("span", { children: getToolStatusLabel(toolCall.status) })
43663
+ /* @__PURE__ */ jsx18("span", { children: getToolStatusLabel(toolCall.status) })
43336
43664
  ] }),
43337
- /* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]", children: displayName })
43665
+ /* @__PURE__ */ jsx18("span", { className: "min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]", children: displayName })
43338
43666
  ]
43339
43667
  }
43340
43668
  ),
43341
- typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */ jsx17("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration(toolCall.duration_ms) })
43669
+ typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */ jsx18("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration(toolCall.duration_ms) })
43342
43670
  ] }),
43343
- expanded && /* @__PURE__ */ jsxs14("div", { className: "blade-chat-tool-detail ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3", children: [
43344
- /* @__PURE__ */ jsx17("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u5DE5\u5177" }),
43345
- /* @__PURE__ */ jsx17("div", { className: "mb-3 font-mono text-[11px] text-[hsl(var(--foreground))]", children: normalizedName }),
43346
- /* @__PURE__ */ jsx17("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u53C2\u6570" }),
43347
- /* @__PURE__ */ jsx17("pre", { className: "overflow-x-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatToolArgs(toolCall.arguments) }),
43348
- toolCall.result != null && /* @__PURE__ */ jsxs14(Fragment6, { children: [
43349
- /* @__PURE__ */ jsx17("div", { className: "mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u7ED3\u679C" }),
43350
- /* @__PURE__ */ jsx17("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) })
43671
+ expanded && /* @__PURE__ */ jsxs15("div", { className: "blade-chat-tool-detail ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3", children: [
43672
+ /* @__PURE__ */ jsx18("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u5DE5\u5177" }),
43673
+ /* @__PURE__ */ jsx18("div", { className: "mb-3 font-mono text-[11px] text-[hsl(var(--foreground))]", children: normalizedName }),
43674
+ /* @__PURE__ */ jsx18("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u53C2\u6570" }),
43675
+ /* @__PURE__ */ jsx18("pre", { className: "overflow-x-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatToolArgs(toolCall.arguments) }),
43676
+ toolCall.result != null && /* @__PURE__ */ jsxs15(Fragment6, { children: [
43677
+ /* @__PURE__ */ jsx18("div", { className: "mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u7ED3\u679C" }),
43678
+ /* @__PURE__ */ jsx18("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) })
43351
43679
  ] })
43352
43680
  ] })
43353
43681
  ] });
@@ -43366,13 +43694,13 @@ function buildAskUserPayload(argumentsJson) {
43366
43694
 
43367
43695
  // src/components/ToolUiCardView.tsx
43368
43696
  import { resolveToolUiCardContent } from "@blade-hq/agent-client";
43369
- import { jsx as jsx18 } from "react/jsx-runtime";
43697
+ import { jsx as jsx19 } from "react/jsx-runtime";
43370
43698
  function ToolUiCardView({ card, sessionId }) {
43371
- if (card.mcpApp) return sessionId ? /* @__PURE__ */ jsx18(McpAppCard, { sessionId, sourceId: card.mcpApp.sourceId }) : null;
43699
+ if (card.mcpApp) return sessionId ? /* @__PURE__ */ jsx19(McpAppCard, { sessionId, sourceId: card.mcpApp.sourceId }) : null;
43372
43700
  const resolved = resolveToolUiCardContent(card);
43373
43701
  if (!resolved) return null;
43374
43702
  const sandbox = resolved.type === "resource-uri" ? "allow-scripts allow-same-origin" : "allow-scripts";
43375
- return /* @__PURE__ */ jsx18(
43703
+ return /* @__PURE__ */ jsx19(
43376
43704
  "iframe",
43377
43705
  {
43378
43706
  title: card.title ?? "\u5DE5\u5177\u754C\u9762",
@@ -43403,12 +43731,12 @@ ${html}`;
43403
43731
  }
43404
43732
 
43405
43733
  // src/components/AssistantTurnBlock.tsx
43406
- import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
43734
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
43407
43735
  function ThinkingBlock({ reasoning, isStreaming }) {
43408
- const [open2, setOpen] = useState26(false);
43736
+ const [open2, setOpen] = useState27(false);
43409
43737
  if (!isStreaming) return null;
43410
- return /* @__PURE__ */ jsxs15("div", { className: "blade-chat-thinking text-xs", children: [
43411
- /* @__PURE__ */ jsxs15(
43738
+ return /* @__PURE__ */ jsxs16("div", { className: "blade-chat-thinking text-xs", children: [
43739
+ /* @__PURE__ */ jsxs16(
43412
43740
  "button",
43413
43741
  {
43414
43742
  type: "button",
@@ -43416,8 +43744,8 @@ function ThinkingBlock({ reasoning, isStreaming }) {
43416
43744
  "aria-expanded": open2,
43417
43745
  className: "group/thinking inline-flex items-center gap-1 text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
43418
43746
  children: [
43419
- /* @__PURE__ */ jsx19(Shimmer, { className: "text-xs", children: "\u6B63\u5728\u601D\u8003" }),
43420
- /* @__PURE__ */ jsx19(
43747
+ /* @__PURE__ */ jsx20(Shimmer, { className: "text-xs", children: "\u6B63\u5728\u601D\u8003" }),
43748
+ /* @__PURE__ */ jsx20(
43421
43749
  ChevronRight,
43422
43750
  {
43423
43751
  size: 14,
@@ -43430,7 +43758,7 @@ function ThinkingBlock({ reasoning, isStreaming }) {
43430
43758
  ]
43431
43759
  }
43432
43760
  ),
43433
- open2 ? /* @__PURE__ */ jsx19("div", { className: "mt-1.5 whitespace-pre-wrap text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", children: reasoning }) : null
43761
+ open2 ? /* @__PURE__ */ jsx20("div", { className: "mt-1.5 whitespace-pre-wrap text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", children: reasoning }) : null
43434
43762
  ] });
43435
43763
  }
43436
43764
  function getMessageText(message) {
@@ -43622,14 +43950,14 @@ function ExecutionToolRow({ toolCall }) {
43622
43950
  "size-3.5 shrink-0",
43623
43951
  failed ? "text-red-500" : "text-[hsl(var(--muted-foreground))]"
43624
43952
  );
43625
- const icon = toolCall.status === "pending" ? /* @__PURE__ */ jsx19(LoaderCircle, { className: cn(iconClass, "animate-spin"), "aria-hidden": "true" }) : toolCall.status === "error" ? /* @__PURE__ */ jsx19(CircleAlert, { className: iconClass, "aria-hidden": "true" }) : toolCall.status === "cancelled" ? /* @__PURE__ */ jsx19(X, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "WebSearch" || normalizedName === "WebFetch" ? /* @__PURE__ */ jsx19(Earth, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Bash" || normalizedName === "BgBash" ? /* @__PURE__ */ jsx19(Terminal, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Write" || normalizedName === "Edit" || normalizedName === "MultiEdit" ? /* @__PURE__ */ jsx19(FilePenLine, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Read" || normalizedName === "ReadSkill" || normalizedName === "get_skill_content" ? /* @__PURE__ */ jsx19(BookOpen, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Grep" || normalizedName === "Glob" || normalizedName === "search_skills" ? /* @__PURE__ */ jsx19(Search, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Agent" ? /* @__PURE__ */ jsx19(Bot, { className: iconClass, "aria-hidden": "true" }) : /* @__PURE__ */ jsx19(Wrench, { className: iconClass, "aria-hidden": "true" });
43953
+ const icon = toolCall.status === "pending" ? /* @__PURE__ */ jsx20(LoaderCircle, { className: cn(iconClass, "animate-spin"), "aria-hidden": "true" }) : toolCall.status === "error" ? /* @__PURE__ */ jsx20(CircleAlert, { className: iconClass, "aria-hidden": "true" }) : toolCall.status === "cancelled" ? /* @__PURE__ */ jsx20(X, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "WebSearch" || normalizedName === "WebFetch" ? /* @__PURE__ */ jsx20(Earth, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Bash" || normalizedName === "BgBash" ? /* @__PURE__ */ jsx20(Terminal, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Write" || normalizedName === "Edit" || normalizedName === "MultiEdit" ? /* @__PURE__ */ jsx20(FilePenLine, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Read" || normalizedName === "ReadSkill" || normalizedName === "get_skill_content" ? /* @__PURE__ */ jsx20(BookOpen, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Grep" || normalizedName === "Glob" || normalizedName === "search_skills" ? /* @__PURE__ */ jsx20(Search, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Agent" ? /* @__PURE__ */ jsx20(Bot, { className: iconClass, "aria-hidden": "true" }) : /* @__PURE__ */ jsx20(Wrench, { className: iconClass, "aria-hidden": "true" });
43626
43954
  const rowClassName = cn(
43627
43955
  "flex min-w-0 items-center gap-1 py-1.5 text-xs leading-[22px]",
43628
43956
  failed ? "text-red-500" : "text-[hsl(var(--muted-foreground))]"
43629
43957
  );
43630
- return /* @__PURE__ */ jsxs15("div", { "data-testid": "execution-tool-intent", className: rowClassName, title: label, children: [
43958
+ return /* @__PURE__ */ jsxs16("div", { "data-testid": "execution-tool-intent", className: rowClassName, title: label, children: [
43631
43959
  icon,
43632
- /* @__PURE__ */ jsx19("span", { className: "min-w-0 truncate", children: label })
43960
+ /* @__PURE__ */ jsx20("span", { className: "min-w-0 truncate", children: label })
43633
43961
  ] });
43634
43962
  }
43635
43963
  function AssistantTurnBlock({
@@ -43675,12 +44003,12 @@ function AssistantTurnBlock({
43675
44003
  )
43676
44004
  );
43677
44005
  const activeQuestionId = questionToolCalls.filter((toolCall) => toolCall.status === "pending").at(-1)?.id;
43678
- const [displayMode, setDisplayMode] = useState26(
44006
+ const [displayMode, setDisplayMode] = useState27(
43679
44007
  () => isStreaming || hasActionableToolCall ? "detail" : "compact"
43680
44008
  );
43681
44009
  const userSelectedDisplayModeRef = useRef20(false);
43682
44010
  const wasStreamingRef = useRef20(isStreaming);
43683
- useEffect17(() => {
44011
+ useEffect18(() => {
43684
44012
  if (wasStreamingRef.current && !isStreaming && !userSelectedDisplayModeRef.current) {
43685
44013
  setDisplayMode(hasActionableToolCall ? "detail" : "compact");
43686
44014
  }
@@ -43688,11 +44016,11 @@ function AssistantTurnBlock({
43688
44016
  }, [hasActionableToolCall, isStreaming]);
43689
44017
  const effectiveMode = resolveTurnDisplayMode({ isStreaming, displayMode });
43690
44018
  const executionDurationMs = getExecutionDurationMs({ messages, isStreaming });
43691
- const [clock, setClock] = useState26(() => Date.now());
44019
+ const [clock, setClock] = useState27(() => Date.now());
43692
44020
  const hasLiveStartTime = messages.some(
43693
44021
  (message) => message.timestamp != null && Number.isFinite(Date.parse(message.timestamp))
43694
44022
  );
43695
- useEffect17(() => {
44023
+ useEffect18(() => {
43696
44024
  if (!isStreaming || !hasLiveStartTime) return;
43697
44025
  const timer = window.setInterval(() => setClock(Date.now()), 1e3);
43698
44026
  return () => window.clearInterval(timer);
@@ -43701,21 +44029,21 @@ function AssistantTurnBlock({
43701
44029
  const memoryRefs = collectMemoryRefs(messages);
43702
44030
  const inlineToolUiCards = collectInlineToolUiCards(messages);
43703
44031
  if (!hasExecutionProcess) {
43704
- return /* @__PURE__ */ jsxs15(
44032
+ return /* @__PURE__ */ jsxs16(
43705
44033
  "div",
43706
44034
  {
43707
44035
  "aria-busy": isStreaming || void 0,
43708
44036
  className: "blade-chat-assistant-turn flex flex-col gap-3",
43709
44037
  children: [
43710
- memoryRefs.length > 0 ? /* @__PURE__ */ jsx19(MemoryRefsHint, { refs: memoryRefs }) : null,
43711
- hasInterrupted && /* @__PURE__ */ jsx19("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" }),
43712
- hasFailedWithoutContent && /* @__PURE__ */ jsx19("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" }),
44038
+ memoryRefs.length > 0 ? /* @__PURE__ */ jsx20(MemoryRefsHint, { refs: memoryRefs }) : null,
44039
+ hasInterrupted && /* @__PURE__ */ jsx20("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" }),
44040
+ hasFailedWithoutContent && /* @__PURE__ */ jsx20("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" }),
43713
44041
  messages.map((message, index) => {
43714
- return hasRenderableMessageContent(message) ? /* @__PURE__ */ jsx19(
44042
+ return hasRenderableMessageContent(message) ? /* @__PURE__ */ jsx20(
43715
44043
  "div",
43716
44044
  {
43717
44045
  className: "flex flex-col gap-3",
43718
- children: /* @__PURE__ */ jsx19(
44046
+ children: /* @__PURE__ */ jsx20(
43719
44047
  AssistantMessageContent,
43720
44048
  {
43721
44049
  message,
@@ -43727,31 +44055,31 @@ function AssistantTurnBlock({
43727
44055
  message.entry_id ?? `${message.timestamp ?? "assistant"}-${index}`
43728
44056
  ) : null;
43729
44057
  }),
43730
- inlineToolUiCards.length > 0 ? /* @__PURE__ */ jsx19("div", { className: "flex flex-col gap-3", children: inlineToolUiCards.map((entry) => /* @__PURE__ */ jsx19(ToolUiCardView, { card: entry.card, sessionId }, entry.key)) }) : null
44058
+ inlineToolUiCards.length > 0 ? /* @__PURE__ */ jsx20("div", { className: "flex flex-col gap-3", children: inlineToolUiCards.map((entry) => /* @__PURE__ */ jsx20(ToolUiCardView, { card: entry.card, sessionId }, entry.key)) }) : null
43731
44059
  ]
43732
44060
  }
43733
44061
  );
43734
44062
  }
43735
- return /* @__PURE__ */ jsxs15(
44063
+ return /* @__PURE__ */ jsxs16(
43736
44064
  "div",
43737
44065
  {
43738
44066
  "aria-busy": isStreaming || void 0,
43739
44067
  className: "blade-chat-assistant-turn flex flex-col gap-3",
43740
44068
  children: [
43741
- memoryRefs.length > 0 ? /* @__PURE__ */ jsx19(MemoryRefsHint, { refs: memoryRefs }) : null,
43742
- hasInterrupted && /* @__PURE__ */ jsx19("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" }),
43743
- hasFailedWithoutContent && /* @__PURE__ */ jsx19("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" }),
43744
- /* @__PURE__ */ jsxs15("div", { className: "flex w-full items-start gap-2.5", children: [
43745
- /* @__PURE__ */ jsx19(
44069
+ memoryRefs.length > 0 ? /* @__PURE__ */ jsx20(MemoryRefsHint, { refs: memoryRefs }) : null,
44070
+ hasInterrupted && /* @__PURE__ */ jsx20("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" }),
44071
+ hasFailedWithoutContent && /* @__PURE__ */ jsx20("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" }),
44072
+ /* @__PURE__ */ jsxs16("div", { className: "flex w-full items-start gap-2.5", children: [
44073
+ /* @__PURE__ */ jsx20(
43746
44074
  "span",
43747
44075
  {
43748
44076
  className: "grid size-[30px] shrink-0 place-items-center rounded-full bg-[hsl(var(--muted)/0.55)] text-[hsl(var(--foreground))]",
43749
44077
  "aria-hidden": "true",
43750
- children: /* @__PURE__ */ jsx19(Bot, { size: 16 })
44078
+ children: /* @__PURE__ */ jsx20(Bot, { size: 16 })
43751
44079
  }
43752
44080
  ),
43753
- /* @__PURE__ */ jsxs15("div", { className: "min-w-0 flex-1 pt-0.5", children: [
43754
- /* @__PURE__ */ jsxs15(
44081
+ /* @__PURE__ */ jsxs16("div", { className: "min-w-0 flex-1 pt-0.5", children: [
44082
+ /* @__PURE__ */ jsxs16(
43755
44083
  "button",
43756
44084
  {
43757
44085
  type: "button",
@@ -43764,14 +44092,14 @@ function AssistantTurnBlock({
43764
44092
  "data-testid": "assistant-execution-summary",
43765
44093
  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",
43766
44094
  children: [
43767
- /* @__PURE__ */ jsx19("span", { className: "min-w-0 truncate", children: executionSummaryLabel({
44095
+ /* @__PURE__ */ jsx20("span", { className: "min-w-0 truncate", children: executionSummaryLabel({
43768
44096
  messages,
43769
44097
  isStreaming,
43770
44098
  durationMs: liveExecutionDurationMs,
43771
44099
  sessionStatus,
43772
44100
  askAnswers
43773
44101
  }) }),
43774
- /* @__PURE__ */ jsx19(
44102
+ /* @__PURE__ */ jsx20(
43775
44103
  ChevronRight,
43776
44104
  {
43777
44105
  size: 14,
@@ -43786,10 +44114,10 @@ function AssistantTurnBlock({
43786
44114
  ]
43787
44115
  }
43788
44116
  ),
43789
- /* @__PURE__ */ jsx19("div", { className: "mt-3 h-px w-full bg-[hsl(var(--border)/0.75)]" })
44117
+ /* @__PURE__ */ jsx20("div", { className: "mt-3 h-px w-full bg-[hsl(var(--border)/0.75)]" })
43790
44118
  ] })
43791
44119
  ] }),
43792
- effectiveMode === "detail" ? /* @__PURE__ */ jsx19("div", { className: "ml-10 flex flex-col gap-3 pt-1", children: messages.map((message, index) => {
44120
+ effectiveMode === "detail" ? /* @__PURE__ */ jsx20("div", { className: "ml-10 flex flex-col gap-3 pt-1", children: messages.map((message, index) => {
43793
44121
  const isLast = index === messages.length - 1;
43794
44122
  const streamingThis = isStreaming && isLast;
43795
44123
  const text = getMessageText(message);
@@ -43799,14 +44127,14 @@ function AssistantTurnBlock({
43799
44127
  const orderedParts = getOrderedMessageParts(message, toolCalls);
43800
44128
  const showReasoning = !!message.reasoning && isStreaming && index === latestReasoningIndex;
43801
44129
  const messageToolUiCards = collectInlineToolUiCards([message]);
43802
- return /* @__PURE__ */ jsxs15(
44130
+ return /* @__PURE__ */ jsxs16(
43803
44131
  "div",
43804
44132
  {
43805
44133
  className: "flex flex-col gap-3",
43806
44134
  children: [
43807
- showReasoning && message.reasoning ? /* @__PURE__ */ jsx19(ThinkingBlock, { reasoning: message.reasoning, isStreaming: streamingThis && !text }) : null,
44135
+ showReasoning && message.reasoning ? /* @__PURE__ */ jsx20(ThinkingBlock, { reasoning: message.reasoning, isStreaming: streamingThis && !text }) : null,
43808
44136
  orderedParts.length > 0 ? orderedParts.map(
43809
- (part) => part.type === "text" ? /* @__PURE__ */ jsx19(
44137
+ (part) => part.type === "text" ? /* @__PURE__ */ jsx20(
43810
44138
  AssistantMessageContent,
43811
44139
  {
43812
44140
  message: { ...message, content: part.content, tool_calls: turnToolCalls },
@@ -43815,11 +44143,11 @@ function AssistantTurnBlock({
43815
44143
  compact: true
43816
44144
  },
43817
44145
  part.key
43818
- ) : /* @__PURE__ */ jsx19("div", { className: "flex flex-col gap-0.5", children: part.toolCalls.map((toolCall) => {
44146
+ ) : /* @__PURE__ */ jsx20("div", { className: "flex flex-col gap-0.5", children: part.toolCalls.map((toolCall) => {
43819
44147
  const custom2 = toolCallRenderer?.(toolCall);
43820
- return custom2 !== null && custom2 !== void 0 ? /* @__PURE__ */ jsx19("div", { children: custom2 }, toolCall.id) : formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx19(AgentLoopBlock, { toolCall }, toolCall.id) : /* @__PURE__ */ jsx19(ExecutionToolRow, { toolCall }, toolCall.id);
44148
+ return custom2 !== null && custom2 !== void 0 ? /* @__PURE__ */ jsx20("div", { children: custom2 }, toolCall.id) : formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx20(AgentLoopBlock, { toolCall }, toolCall.id) : /* @__PURE__ */ jsx20(ExecutionToolRow, { toolCall }, toolCall.id);
43821
44149
  }) }, part.key)
43822
- ) : hasRenderableMessageContent(message) && message !== finalMessage ? /* @__PURE__ */ jsx19(
44150
+ ) : hasRenderableMessageContent(message) && message !== finalMessage ? /* @__PURE__ */ jsx20(
43823
44151
  AssistantMessageContent,
43824
44152
  {
43825
44153
  message,
@@ -43828,18 +44156,18 @@ function AssistantTurnBlock({
43828
44156
  compact: true
43829
44157
  }
43830
44158
  ) : null,
43831
- orderedParts.length === 0 && toolCalls.length > 0 ? /* @__PURE__ */ jsx19("div", { className: "flex flex-col gap-0.5", children: toolCalls.map((toolCall) => {
44159
+ orderedParts.length === 0 && toolCalls.length > 0 ? /* @__PURE__ */ jsx20("div", { className: "flex flex-col gap-0.5", children: toolCalls.map((toolCall) => {
43832
44160
  const custom2 = toolCallRenderer?.(toolCall);
43833
- return custom2 !== null && custom2 !== void 0 ? /* @__PURE__ */ jsx19("div", { children: custom2 }, toolCall.id) : formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx19(AgentLoopBlock, { toolCall }, toolCall.id) : /* @__PURE__ */ jsx19(ExecutionToolRow, { toolCall }, toolCall.id);
44161
+ return custom2 !== null && custom2 !== void 0 ? /* @__PURE__ */ jsx20("div", { children: custom2 }, toolCall.id) : formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx20(AgentLoopBlock, { toolCall }, toolCall.id) : /* @__PURE__ */ jsx20(ExecutionToolRow, { toolCall }, toolCall.id);
43834
44162
  }) }) : null,
43835
- messageToolUiCards.map((entry) => /* @__PURE__ */ jsx19(ToolUiCardView, { card: entry.card, sessionId }, entry.key))
44163
+ messageToolUiCards.map((entry) => /* @__PURE__ */ jsx20(ToolUiCardView, { card: entry.card, sessionId }, entry.key))
43836
44164
  ]
43837
44165
  },
43838
44166
  message.entry_id ?? `${message.timestamp ?? "assistant"}-${index}`
43839
44167
  );
43840
44168
  }) }) : null,
43841
- effectiveMode === "compact" && inlineToolUiCards.length > 0 ? /* @__PURE__ */ jsx19("div", { className: "ml-10 flex flex-col gap-3", children: inlineToolUiCards.map((entry) => /* @__PURE__ */ jsx19(ToolUiCardView, { card: entry.card, sessionId }, entry.key)) }) : null,
43842
- finalMessage && (effectiveMode === "compact" || finalOrderedParts.length === 0) ? /* @__PURE__ */ jsx19("div", { className: "ml-10", children: /* @__PURE__ */ jsx19(
44169
+ effectiveMode === "compact" && inlineToolUiCards.length > 0 ? /* @__PURE__ */ jsx20("div", { className: "ml-10 flex flex-col gap-3", children: inlineToolUiCards.map((entry) => /* @__PURE__ */ jsx20(ToolUiCardView, { card: entry.card, sessionId }, entry.key)) }) : null,
44170
+ finalMessage && (effectiveMode === "compact" || finalOrderedParts.length === 0) ? /* @__PURE__ */ jsx20("div", { className: "ml-10", children: /* @__PURE__ */ jsx20(
43843
44171
  AssistantMessageContent,
43844
44172
  {
43845
44173
  message: finalMessage,
@@ -43847,7 +44175,7 @@ function AssistantTurnBlock({
43847
44175
  streaming: isStreaming && finalMessage === messages[messages.length - 1]
43848
44176
  }
43849
44177
  ) }) : null,
43850
- questionToolCalls.map((toolCall) => /* @__PURE__ */ jsx19(
44178
+ questionToolCalls.map((toolCall) => /* @__PURE__ */ jsx20(
43851
44179
  ToolCallBlock,
43852
44180
  {
43853
44181
  toolCall,
@@ -43872,22 +44200,22 @@ function collectMemoryRefs(messages) {
43872
44200
  return [...refs.values()];
43873
44201
  }
43874
44202
  function MemoryRefsHint({ refs }) {
43875
- const [expanded, setExpanded] = useState26(false);
44203
+ const [expanded, setExpanded] = useState27(false);
43876
44204
  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";
43877
- return /* @__PURE__ */ jsxs15("div", { className: "blade-chat-memory-refs ml-1 w-full max-w-[680px]", children: [
43878
- /* @__PURE__ */ jsxs15("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: [
43879
- /* @__PURE__ */ jsx19(BookOpen, { size: 12 }),
43880
- /* @__PURE__ */ jsxs15("span", { children: [
44205
+ return /* @__PURE__ */ jsxs16("div", { className: "blade-chat-memory-refs ml-1 w-full max-w-[680px]", children: [
44206
+ /* @__PURE__ */ jsxs16("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: [
44207
+ /* @__PURE__ */ jsx20(BookOpen, { size: 12 }),
44208
+ /* @__PURE__ */ jsxs16("span", { children: [
43881
44209
  label,
43882
44210
  "\uFF08",
43883
44211
  refs.length,
43884
44212
  "\uFF09"
43885
44213
  ] }),
43886
- /* @__PURE__ */ jsx19(ChevronRight, { size: 10, className: cn("transition-transform", expanded && "rotate-90") })
44214
+ /* @__PURE__ */ jsx20(ChevronRight, { size: 10, className: cn("transition-transform", expanded && "rotate-90") })
43887
44215
  ] }),
43888
- expanded ? /* @__PURE__ */ jsx19("div", { className: "mt-2 flex flex-col gap-2 rounded-xl border border-[hsl(var(--border)/0.8)] bg-[hsl(var(--muted)/0.28)] p-2.5", children: refs.map((ref) => /* @__PURE__ */ jsxs15("div", { className: "rounded-lg border border-[hsl(var(--border)/0.55)] bg-[hsl(var(--background)/0.72)] px-3 py-2.5 text-xs", children: [
43889
- /* @__PURE__ */ jsx19("p", { className: "line-clamp-2 break-words leading-5", children: ref.content_preview }),
43890
- ref.skill_name ? /* @__PURE__ */ jsx19("span", { className: "mt-1 inline-flex text-[10px] text-[hsl(var(--primary))]", children: ref.skill_name }) : null
44216
+ expanded ? /* @__PURE__ */ jsx20("div", { className: "mt-2 flex flex-col gap-2 rounded-xl border border-[hsl(var(--border)/0.8)] bg-[hsl(var(--muted)/0.28)] p-2.5", children: refs.map((ref) => /* @__PURE__ */ jsxs16("div", { className: "rounded-lg border border-[hsl(var(--border)/0.55)] bg-[hsl(var(--background)/0.72)] px-3 py-2.5 text-xs", children: [
44217
+ /* @__PURE__ */ jsx20("p", { className: "line-clamp-2 break-words leading-5", children: ref.content_preview }),
44218
+ ref.skill_name ? /* @__PURE__ */ jsx20("span", { className: "mt-1 inline-flex text-[10px] text-[hsl(var(--primary))]", children: ref.skill_name }) : null
43891
44219
  ] }, ref.id)) }) : null
43892
44220
  ] });
43893
44221
  }
@@ -43901,15 +44229,15 @@ function AssistantMessageContent({
43901
44229
  const imageParts = getImageParts(message.content);
43902
44230
  const fileParts = getFileParts(message.content);
43903
44231
  const failed = message.status === "failed";
43904
- const failedBadge = failed ? /* @__PURE__ */ jsx19("div", { className: "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" }) : null;
43905
- const textContent = text ? /* @__PURE__ */ jsx19(
44232
+ const failedBadge = failed ? /* @__PURE__ */ jsx20("div", { className: "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" }) : null;
44233
+ const textContent = text ? /* @__PURE__ */ jsx20(
43906
44234
  "div",
43907
44235
  {
43908
44236
  className: cn(
43909
44237
  "blade-chat-assistant-text",
43910
44238
  compact ? "text-xs leading-[22px] text-[hsl(var(--foreground))]" : "text-[15px] leading-8 text-[hsl(var(--foreground))]"
43911
44239
  ),
43912
- children: /* @__PURE__ */ jsx19(
44240
+ children: /* @__PURE__ */ jsx20(
43913
44241
  MarkdownContent,
43914
44242
  {
43915
44243
  mode: streaming ? "streaming" : "static",
@@ -43922,14 +44250,14 @@ function AssistantMessageContent({
43922
44250
  ) : null;
43923
44251
  if (imageParts.length === 0 && fileParts.length === 0) {
43924
44252
  if (!failed) return textContent;
43925
- return failedBadge || textContent ? /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-2", children: [
44253
+ return failedBadge || textContent ? /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-2", children: [
43926
44254
  failedBadge,
43927
44255
  textContent
43928
44256
  ] }) : null;
43929
44257
  }
43930
- return /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-3", children: [
44258
+ return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-3", children: [
43931
44259
  failedBadge,
43932
- imageParts.length > 0 ? /* @__PURE__ */ jsx19("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx19(
44260
+ imageParts.length > 0 ? /* @__PURE__ */ jsx20("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx20(
43933
44261
  "img",
43934
44262
  {
43935
44263
  src: part.image_url.url,
@@ -43938,14 +44266,14 @@ function AssistantMessageContent({
43938
44266
  },
43939
44267
  part.image_url.url
43940
44268
  )) }) : null,
43941
- fileParts.length > 0 ? /* @__PURE__ */ jsx19("div", { className: "flex flex-wrap gap-1.5", children: fileParts.map((part) => /* @__PURE__ */ jsxs15(
44269
+ fileParts.length > 0 ? /* @__PURE__ */ jsx20("div", { className: "flex flex-wrap gap-1.5", children: fileParts.map((part) => /* @__PURE__ */ jsxs16(
43942
44270
  "div",
43943
44271
  {
43944
44272
  className: "flex min-w-0 items-center gap-1.5 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.3)] px-2.5 py-1.5 text-xs text-[hsl(var(--muted-foreground))]",
43945
44273
  title: part.name,
43946
44274
  children: [
43947
- /* @__PURE__ */ jsx19(FileText, { size: 12, className: "shrink-0" }),
43948
- /* @__PURE__ */ jsx19("span", { className: "max-w-56 truncate", children: part.name })
44275
+ /* @__PURE__ */ jsx20(FileText, { size: 12, className: "shrink-0" }),
44276
+ /* @__PURE__ */ jsx20("span", { className: "max-w-56 truncate", children: part.name })
43949
44277
  ]
43950
44278
  },
43951
44279
  `${part.name}-${part.data.slice(0, 32)}`
@@ -43956,7 +44284,7 @@ function AssistantMessageContent({
43956
44284
 
43957
44285
  // src/components/RenderErrorBoundary.tsx
43958
44286
  import { Component as Component2 } from "react";
43959
- import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
44287
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
43960
44288
  function getFirstComponentName(componentStack) {
43961
44289
  const match = componentStack.match(/\n\s+at\s+([^\s(]+)/);
43962
44290
  return match?.[1] ?? null;
@@ -43989,26 +44317,26 @@ var RenderErrorBoundary = class extends Component2 {
43989
44317
  return children;
43990
44318
  }
43991
44319
  const componentName = getFirstComponentName(componentStack);
43992
- return /* @__PURE__ */ jsx20("div", { className: "blade-chat-render-error rounded-xl border border-amber-500/30 bg-amber-500/8 px-4 py-3 text-sm text-amber-100", children: /* @__PURE__ */ jsxs16("div", { className: "flex items-start gap-2", children: [
43993
- /* @__PURE__ */ jsx20(TriangleAlert, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
43994
- /* @__PURE__ */ jsxs16("div", { className: "min-w-0 flex-1", children: [
43995
- /* @__PURE__ */ jsxs16("div", { className: "font-medium", children: [
44320
+ return /* @__PURE__ */ jsx21("div", { className: "blade-chat-render-error rounded-xl border border-amber-500/30 bg-amber-500/8 px-4 py-3 text-sm text-amber-100", children: /* @__PURE__ */ jsxs17("div", { className: "flex items-start gap-2", children: [
44321
+ /* @__PURE__ */ jsx21(TriangleAlert, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
44322
+ /* @__PURE__ */ jsxs17("div", { className: "min-w-0 flex-1", children: [
44323
+ /* @__PURE__ */ jsxs17("div", { className: "font-medium", children: [
43996
44324
  label,
43997
44325
  "\u6E32\u67D3\u5931\u8D25"
43998
44326
  ] }),
43999
- /* @__PURE__ */ jsxs16("div", { className: "mt-1 break-words text-xs leading-5 text-amber-100/75", children: [
44327
+ /* @__PURE__ */ jsxs17("div", { className: "mt-1 break-words text-xs leading-5 text-amber-100/75", children: [
44000
44328
  componentName ? `\u7EC4\u4EF6\uFF1A${componentName}\u3002` : null,
44001
44329
  error61.message || "\u53D1\u751F\u4E86\u672A\u9884\u671F\u7684\u6E32\u67D3\u9519\u8BEF\u3002"
44002
44330
  ] }),
44003
- details ? /* @__PURE__ */ jsx20("div", { className: "mt-1 truncate text-xs text-amber-100/55", children: details }) : null
44331
+ details ? /* @__PURE__ */ jsx21("div", { className: "mt-1 truncate text-xs text-amber-100/55", children: details }) : null
44004
44332
  ] })
44005
44333
  ] }) });
44006
44334
  }
44007
44335
  };
44008
44336
 
44009
44337
  // src/components/PostChatFollowupBlock.tsx
44010
- import { useCallback as useCallback24, useEffect as useEffect18, useRef as useRef21, useState as useState27 } from "react";
44011
- import { Fragment as Fragment7, jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
44338
+ import { useCallback as useCallback25, useEffect as useEffect19, useRef as useRef21, useState as useState28 } from "react";
44339
+ import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
44012
44340
  function emitInteraction(callback, event) {
44013
44341
  try {
44014
44342
  callback?.(event);
@@ -44027,10 +44355,10 @@ function ArtifactCard({
44027
44355
  onArtifactOpened
44028
44356
  }) {
44029
44357
  const client = useBladeClient();
44030
- const [downloading, setDownloading] = useState27(false);
44358
+ const [downloading, setDownloading] = useState28(false);
44031
44359
  const name = artifact.label || basename(artifact.target);
44032
44360
  if (artifact.kind === "link") {
44033
- return /* @__PURE__ */ jsxs17(
44361
+ return /* @__PURE__ */ jsxs18(
44034
44362
  "a",
44035
44363
  {
44036
44364
  href: artifact.target,
@@ -44041,9 +44369,9 @@ function ArtifactCard({
44041
44369
  ${artifact.target}`,
44042
44370
  className: "group relative flex min-w-0 items-center gap-1.5 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2 py-1.5 text-xs text-[hsl(var(--card-foreground))] hover:bg-[hsl(var(--accent))]",
44043
44371
  children: [
44044
- /* @__PURE__ */ jsx21(Globe, { size: 15, className: "shrink-0 text-[hsl(var(--primary))]" }),
44045
- /* @__PURE__ */ jsx21("span", { className: "min-w-0 flex-1 truncate font-medium", children: name }),
44046
- /* @__PURE__ */ jsx21(ArrowUpRight, { size: 13, className: "absolute right-2 opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100" })
44372
+ /* @__PURE__ */ jsx22(Globe, { size: 15, className: "shrink-0 text-[hsl(var(--primary))]" }),
44373
+ /* @__PURE__ */ jsx22("span", { className: "min-w-0 flex-1 truncate font-medium", children: name }),
44374
+ /* @__PURE__ */ jsx22(ArrowUpRight, { size: 13, className: "absolute right-2 opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100" })
44047
44375
  ]
44048
44376
  }
44049
44377
  );
@@ -44078,7 +44406,7 @@ ${artifact.target}`,
44078
44406
  setDownloading(false);
44079
44407
  }
44080
44408
  };
44081
- return /* @__PURE__ */ jsx21(
44409
+ return /* @__PURE__ */ jsx22(
44082
44410
  "a",
44083
44411
  {
44084
44412
  href: downloadUrl,
@@ -44106,17 +44434,17 @@ function feedbackReasonLabel(reason) {
44106
44434
  }
44107
44435
  function HistoricalResultFeedback({ feedback }) {
44108
44436
  const label = feedbackReasonLabel(feedback.reason);
44109
- return /* @__PURE__ */ jsxs17(
44437
+ return /* @__PURE__ */ jsxs18(
44110
44438
  "section",
44111
44439
  {
44112
44440
  "aria-label": "\u5386\u53F2\u7ED3\u679C\u53CD\u9988",
44113
44441
  className: "mt-3 w-fit max-w-full rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.2)] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]",
44114
44442
  children: [
44115
- /* @__PURE__ */ jsxs17("span", { children: [
44443
+ /* @__PURE__ */ jsxs18("span", { children: [
44116
44444
  "\u4F60\u5BF9\u6B64\u8F6E\u7ED3\u679C\u7684\u8BC4\u4EF7\uFF1A",
44117
44445
  feedback.helpful ? "\u6709\u5E2E\u52A9" : "\u6CA1\u5E2E\u52A9"
44118
44446
  ] }),
44119
- label ? /* @__PURE__ */ jsxs17("span", { children: [
44447
+ label ? /* @__PURE__ */ jsxs18("span", { children: [
44120
44448
  " \xB7 ",
44121
44449
  label
44122
44450
  ] }) : null
@@ -44133,15 +44461,15 @@ function ResultFeedback({
44133
44461
  onFeedbackSaved
44134
44462
  }) {
44135
44463
  const client = useBladeClient();
44136
- const [saved, setSaved] = useState27(savedFeedback ?? null);
44137
- const [helpful, setHelpful] = useState27(savedFeedback?.helpful ?? null);
44138
- const [reason, setReason] = useState27(savedFeedback?.reason ?? null);
44139
- const [saving, setSaving] = useState27(false);
44140
- const [saveError, setSaveError] = useState27(false);
44464
+ const [saved, setSaved] = useState28(savedFeedback ?? null);
44465
+ const [helpful, setHelpful] = useState28(savedFeedback?.helpful ?? null);
44466
+ const [reason, setReason] = useState28(savedFeedback?.reason ?? null);
44467
+ const [saving, setSaving] = useState28(false);
44468
+ const [saveError, setSaveError] = useState28(false);
44141
44469
  const reportedShown = useRef21(false);
44142
44470
  const latestChoice = useRef21(null);
44143
44471
  const eligible = followup.feedback_eligible === true && Boolean(sessionId) && !isViewer;
44144
- useEffect18(() => {
44472
+ useEffect19(() => {
44145
44473
  if (!eligible || reportedShown.current) return;
44146
44474
  reportedShown.current = true;
44147
44475
  emitInteraction(onInteraction, {
@@ -44150,13 +44478,13 @@ function ResultFeedback({
44150
44478
  assistantEntryId: followup.assistant_entry_id
44151
44479
  });
44152
44480
  }, [eligible, followup.assistant_entry_id, onInteraction, sessionId]);
44153
- useEffect18(() => {
44481
+ useEffect19(() => {
44154
44482
  if (!savedFeedback || latestChoice.current) return;
44155
44483
  setSaved(savedFeedback);
44156
44484
  setHelpful(savedFeedback.helpful);
44157
44485
  setReason(savedFeedback.reason);
44158
44486
  }, [savedFeedback]);
44159
- const submit = useCallback24(
44487
+ const submit = useCallback25(
44160
44488
  async (nextHelpful, nextReason) => {
44161
44489
  if (!sessionId) return;
44162
44490
  const choice = { helpful: nextHelpful, reason: nextReason };
@@ -44191,15 +44519,15 @@ function ResultFeedback({
44191
44519
  [client, followup.assistant_entry_id, onFeedbackSaved, onInteraction, sessionId]
44192
44520
  );
44193
44521
  if (!eligible) return null;
44194
- return /* @__PURE__ */ jsxs17(
44522
+ return /* @__PURE__ */ jsxs18(
44195
44523
  "section",
44196
44524
  {
44197
44525
  "aria-label": "\u7ED3\u679C\u53CD\u9988",
44198
44526
  className: "flex flex-col gap-2 border-t border-[hsl(var(--border))] pt-3",
44199
44527
  children: [
44200
- /* @__PURE__ */ jsx21("div", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u76EE\u524D\u7684\u6574\u4F53\u7ED3\u679C\u6709\u5E2E\u52A9\u5417\uFF1F" }),
44201
- /* @__PURE__ */ jsxs17("div", { className: "flex flex-wrap gap-1.5", children: [
44202
- /* @__PURE__ */ jsx21(
44528
+ /* @__PURE__ */ jsx22("div", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u76EE\u524D\u7684\u6574\u4F53\u7ED3\u679C\u6709\u5E2E\u52A9\u5417\uFF1F" }),
44529
+ /* @__PURE__ */ jsxs18("div", { className: "flex flex-wrap gap-1.5", children: [
44530
+ /* @__PURE__ */ jsx22(
44203
44531
  "button",
44204
44532
  {
44205
44533
  type: "button",
@@ -44210,7 +44538,7 @@ function ResultFeedback({
44210
44538
  children: "\u6709\u5E2E\u52A9"
44211
44539
  }
44212
44540
  ),
44213
- /* @__PURE__ */ jsx21(
44541
+ /* @__PURE__ */ jsx22(
44214
44542
  "button",
44215
44543
  {
44216
44544
  type: "button",
@@ -44222,7 +44550,7 @@ function ResultFeedback({
44222
44550
  }
44223
44551
  )
44224
44552
  ] }),
44225
- helpful === false ? /* @__PURE__ */ jsx21("div", { className: "flex flex-wrap gap-1.5", "aria-label": "\u6CA1\u5E2E\u52A9\u7684\u4E3B\u8981\u539F\u56E0", children: FEEDBACK_REASONS.map((item) => /* @__PURE__ */ jsx21(
44553
+ helpful === false ? /* @__PURE__ */ jsx22("div", { className: "flex flex-wrap gap-1.5", "aria-label": "\u6CA1\u5E2E\u52A9\u7684\u4E3B\u8981\u539F\u56E0", children: FEEDBACK_REASONS.map((item) => /* @__PURE__ */ jsx22(
44226
44554
  "button",
44227
44555
  {
44228
44556
  type: "button",
@@ -44234,9 +44562,9 @@ function ResultFeedback({
44234
44562
  },
44235
44563
  item.value
44236
44564
  )) }) : null,
44237
- saveError ? /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2 text-xs text-[hsl(var(--destructive))]", children: [
44238
- /* @__PURE__ */ jsx21("span", { children: "\u53CD\u9988\u6682\u672A\u4FDD\u5B58\uFF0C\u53EF\u91CD\u8BD5" }),
44239
- /* @__PURE__ */ jsx21(
44565
+ saveError ? /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2 text-xs text-[hsl(var(--destructive))]", children: [
44566
+ /* @__PURE__ */ jsx22("span", { children: "\u53CD\u9988\u6682\u672A\u4FDD\u5B58\uFF0C\u53EF\u91CD\u8BD5" }),
44567
+ /* @__PURE__ */ jsx22(
44240
44568
  "button",
44241
44569
  {
44242
44570
  type: "button",
@@ -44248,7 +44576,7 @@ function ResultFeedback({
44248
44576
  children: "\u91CD\u8BD5"
44249
44577
  }
44250
44578
  )
44251
- ] }) : saved ? /* @__PURE__ */ jsx21("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: "\u5DF2\u4FDD\u5B58\uFF0C\u53EF\u968F\u65F6\u4FEE\u6539" }) : null
44579
+ ] }) : saved ? /* @__PURE__ */ jsx22("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: "\u5DF2\u4FDD\u5B58\uFF0C\u53EF\u968F\u65F6\u4FEE\u6539" }) : null
44252
44580
  ]
44253
44581
  }
44254
44582
  );
@@ -44262,14 +44590,14 @@ function PostChatFollowupBlock({
44262
44590
  savedFeedback,
44263
44591
  onFeedbackSaved
44264
44592
  }) {
44265
- const [expanded, setExpanded] = useState27(false);
44593
+ const [expanded, setExpanded] = useState28(false);
44266
44594
  const adopted = useRef21(/* @__PURE__ */ new Set());
44267
44595
  const reportedSuggestions = useRef21(false);
44268
44596
  const reportedArtifacts = useRef21(/* @__PURE__ */ new Set());
44269
44597
  const openedArtifacts = useRef21(/* @__PURE__ */ new Set());
44270
44598
  const artifacts = followup.final_artifacts ?? [];
44271
44599
  const visibleArtifacts = expanded ? artifacts : artifacts.slice(0, 3);
44272
- useEffect18(() => {
44600
+ useEffect19(() => {
44273
44601
  if (!reportedSuggestions.current && followup.suggestions.length > 0) {
44274
44602
  reportedSuggestions.current = true;
44275
44603
  emitInteraction(onInteraction, {
@@ -44299,7 +44627,7 @@ function PostChatFollowupBlock({
44299
44627
  sessionId,
44300
44628
  visibleArtifacts
44301
44629
  ]);
44302
- const reportArtifactOpened = useCallback24(
44630
+ const reportArtifactOpened = useCallback25(
44303
44631
  (artifactIndex, artifactKind) => {
44304
44632
  if (openedArtifacts.current.has(artifactIndex)) return;
44305
44633
  openedArtifacts.current.add(artifactIndex);
@@ -44315,15 +44643,15 @@ function PostChatFollowupBlock({
44315
44643
  );
44316
44644
  if (!followup.recaption && artifacts.length === 0 && followup.suggestions.length === 0 && !followup.feedback_eligible)
44317
44645
  return null;
44318
- return /* @__PURE__ */ jsxs17("div", { className: "mt-3 flex w-fit max-w-full flex-col gap-3 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.28)] p-3 sm:max-w-[680px]", children: [
44319
- followup.recaption || artifacts.length > 0 ? /* @__PURE__ */ jsxs17("section", { "aria-label": "\u672C\u8F6E\u5C0F\u7ED3", className: "flex flex-col gap-2", children: [
44320
- /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-1.5 text-xs font-medium text-[hsl(var(--muted-foreground))]", children: [
44321
- /* @__PURE__ */ jsx21(Sparkles, { size: 14 }),
44646
+ return /* @__PURE__ */ jsxs18("div", { className: "mt-3 flex w-fit max-w-full flex-col gap-3 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.28)] p-3 sm:max-w-[680px]", children: [
44647
+ followup.recaption || artifacts.length > 0 ? /* @__PURE__ */ jsxs18("section", { "aria-label": "\u672C\u8F6E\u5C0F\u7ED3", className: "flex flex-col gap-2", children: [
44648
+ /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-1.5 text-xs font-medium text-[hsl(var(--muted-foreground))]", children: [
44649
+ /* @__PURE__ */ jsx22(Sparkles, { size: 14 }),
44322
44650
  "\u672C\u8F6E\u5C0F\u7ED3"
44323
44651
  ] }),
44324
- followup.recaption ? /* @__PURE__ */ jsx21("p", { className: "text-[13px] leading-5", children: followup.recaption }) : null,
44325
- artifacts.length > 0 ? /* @__PURE__ */ jsxs17(Fragment7, { children: [
44326
- /* @__PURE__ */ jsx21("div", { className: "grid max-w-full grid-cols-3 gap-1.5", children: visibleArtifacts.map((artifact, artifactIndex) => /* @__PURE__ */ jsx21(
44652
+ followup.recaption ? /* @__PURE__ */ jsx22("p", { className: "text-[13px] leading-5", children: followup.recaption }) : null,
44653
+ artifacts.length > 0 ? /* @__PURE__ */ jsxs18(Fragment7, { children: [
44654
+ /* @__PURE__ */ jsx22("div", { className: "grid max-w-full grid-cols-3 gap-1.5", children: visibleArtifacts.map((artifact, artifactIndex) => /* @__PURE__ */ jsx22(
44327
44655
  ArtifactCard,
44328
44656
  {
44329
44657
  artifact,
@@ -44335,7 +44663,7 @@ function PostChatFollowupBlock({
44335
44663
  },
44336
44664
  `${artifact.kind}:${artifactIndex}`
44337
44665
  )) }),
44338
- artifacts.length > 3 ? /* @__PURE__ */ jsxs17(
44666
+ artifacts.length > 3 ? /* @__PURE__ */ jsxs18(
44339
44667
  "button",
44340
44668
  {
44341
44669
  type: "button",
@@ -44344,15 +44672,15 @@ function PostChatFollowupBlock({
44344
44672
  className: "flex w-fit items-center gap-0.5 text-[11px] text-[hsl(var(--muted-foreground))]",
44345
44673
  children: [
44346
44674
  expanded ? "\u6536\u8D77" : `\u5C55\u5F00 ${artifacts.length - 3} \u4E2A`,
44347
- /* @__PURE__ */ jsx21(ChevronDown, { size: 13, className: expanded ? "rotate-180" : void 0 })
44675
+ /* @__PURE__ */ jsx22(ChevronDown, { size: 13, className: expanded ? "rotate-180" : void 0 })
44348
44676
  ]
44349
44677
  }
44350
44678
  ) : null
44351
44679
  ] }) : null
44352
44680
  ] }) : null,
44353
- followup.suggestions.length > 0 ? /* @__PURE__ */ jsxs17("section", { "aria-label": "\u4E0B\u4E00\u6B65\u5EFA\u8BAE", className: "flex flex-col gap-1.5", children: [
44354
- /* @__PURE__ */ jsx21("div", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u4E0B\u4E00\u6B65\u53EF\u4EE5" }),
44355
- followup.suggestions.map((suggestion, suggestionIndex) => /* @__PURE__ */ jsxs17(
44681
+ followup.suggestions.length > 0 ? /* @__PURE__ */ jsxs18("section", { "aria-label": "\u4E0B\u4E00\u6B65\u5EFA\u8BAE", className: "flex flex-col gap-1.5", children: [
44682
+ /* @__PURE__ */ jsx22("div", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u4E0B\u4E00\u6B65\u53EF\u4EE5" }),
44683
+ followup.suggestions.map((suggestion, suggestionIndex) => /* @__PURE__ */ jsxs18(
44356
44684
  "button",
44357
44685
  {
44358
44686
  type: "button",
@@ -44371,14 +44699,14 @@ function PostChatFollowupBlock({
44371
44699
  },
44372
44700
  className: "group flex items-center gap-2 rounded-xl bg-[hsl(var(--muted)/0.62)] px-3 py-2 text-left text-[13px] disabled:cursor-default disabled:opacity-60",
44373
44701
  children: [
44374
- /* @__PURE__ */ jsx21("span", { children: suggestion }),
44375
- /* @__PURE__ */ jsx21(ArrowRight, { size: 14, className: "ml-auto shrink-0" })
44702
+ /* @__PURE__ */ jsx22("span", { children: suggestion }),
44703
+ /* @__PURE__ */ jsx22(ArrowRight, { size: 14, className: "ml-auto shrink-0" })
44376
44704
  ]
44377
44705
  },
44378
44706
  suggestion
44379
44707
  ))
44380
44708
  ] }) : null,
44381
- /* @__PURE__ */ jsx21(
44709
+ /* @__PURE__ */ jsx22(
44382
44710
  ResultFeedback,
44383
44711
  {
44384
44712
  followup,
@@ -44453,31 +44781,31 @@ function parseWhatIfPrompt(text) {
44453
44781
  }
44454
44782
 
44455
44783
  // src/components/WhatIfUserBubble.tsx
44456
- import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
44784
+ import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
44457
44785
  function WhatIfUserBubble({ parsed, onQuoteClick }) {
44458
44786
  const { fromStep, quotes, userText } = parsed;
44459
- return /* @__PURE__ */ jsxs18("div", { className: "flex flex-col items-end gap-2", children: [
44460
- /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.5)] px-2.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
44461
- /* @__PURE__ */ jsx22(RefreshCcw, { size: 10 }),
44462
- /* @__PURE__ */ jsx22("span", { children: fromStep != null ? `\u91CD\u8DD1\u81EA step ${fromStep}` : "\u91CD\u8DD1" })
44787
+ return /* @__PURE__ */ jsxs19("div", { className: "flex flex-col items-end gap-2", children: [
44788
+ /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.5)] px-2.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
44789
+ /* @__PURE__ */ jsx23(RefreshCcw, { size: 10 }),
44790
+ /* @__PURE__ */ jsx23("span", { children: fromStep != null ? `\u91CD\u8DD1\u81EA step ${fromStep}` : "\u91CD\u8DD1" })
44463
44791
  ] }),
44464
- quotes.length > 0 && /* @__PURE__ */ jsx22("div", { className: "flex max-w-[min(72vw,42rem)] flex-col items-stretch gap-2", children: quotes.map((quote, index) => {
44792
+ quotes.length > 0 && /* @__PURE__ */ jsx23("div", { className: "flex max-w-[min(72vw,42rem)] flex-col items-stretch gap-2", children: quotes.map((quote, index) => {
44465
44793
  const clickable = quote.stepNumber != null && !!onQuoteClick;
44466
44794
  const label = quote.stepNumber != null ? `\u6B65\u9AA4${quote.stepNumber} \xB7 ${quote.label}` : quote.label;
44467
- return /* @__PURE__ */ jsxs18("div", { className: "rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card)/0.8)] px-3 py-2 text-left", children: [
44468
- /* @__PURE__ */ jsxs18("button", { type: "button", disabled: !clickable, onClick: () => clickable && onQuoteClick(quote.stepNumber), className: "inline-flex max-w-full items-center gap-1 text-[11px] font-medium text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))] disabled:cursor-default", title: clickable ? "\u8DF3\u8F6C\u5230\u5BF9\u5E94\u6B65\u9AA4\u5361\u7247" : void 0, children: [
44469
- /* @__PURE__ */ jsx22("span", { children: "\u21B3" }),
44470
- /* @__PURE__ */ jsx22("span", { className: "truncate", children: label })
44795
+ return /* @__PURE__ */ jsxs19("div", { className: "rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card)/0.8)] px-3 py-2 text-left", children: [
44796
+ /* @__PURE__ */ jsxs19("button", { type: "button", disabled: !clickable, onClick: () => clickable && onQuoteClick(quote.stepNumber), className: "inline-flex max-w-full items-center gap-1 text-[11px] font-medium text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))] disabled:cursor-default", title: clickable ? "\u8DF3\u8F6C\u5230\u5BF9\u5E94\u6B65\u9AA4\u5361\u7247" : void 0, children: [
44797
+ /* @__PURE__ */ jsx23("span", { children: "\u21B3" }),
44798
+ /* @__PURE__ */ jsx23("span", { className: "truncate", children: label })
44471
44799
  ] }),
44472
- quote.snapshot ? /* @__PURE__ */ jsx22("div", { className: "mt-1 border-l-2 border-[hsl(var(--accent-foreground)/0.35)] pl-2 text-xs leading-relaxed text-[hsl(var(--foreground)/0.8)]", children: /* @__PURE__ */ jsx22(MarkdownContent, { className: "blade-chat-prose", children: quote.snapshot }) }) : null
44800
+ quote.snapshot ? /* @__PURE__ */ jsx23("div", { className: "mt-1 border-l-2 border-[hsl(var(--accent-foreground)/0.35)] pl-2 text-xs leading-relaxed text-[hsl(var(--foreground)/0.8)]", children: /* @__PURE__ */ jsx23(MarkdownContent, { className: "blade-chat-prose", children: quote.snapshot }) }) : null
44473
44801
  ] }, `${quote.stepNumber ?? "x"}-${index}`);
44474
44802
  }) }),
44475
- userText && /* @__PURE__ */ jsx22("div", { className: "rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))]", children: /* @__PURE__ */ jsx22(MarkdownContent, { className: "blade-chat-prose", children: userText }) })
44803
+ userText && /* @__PURE__ */ jsx23("div", { className: "rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))]", children: /* @__PURE__ */ jsx23(MarkdownContent, { className: "blade-chat-prose", children: userText }) })
44476
44804
  ] });
44477
44805
  }
44478
44806
 
44479
44807
  // src/components/UserMessageBubble.tsx
44480
- import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
44808
+ import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
44481
44809
  function isUserMessage(message) {
44482
44810
  return message.role === "user";
44483
44811
  }
@@ -44491,10 +44819,10 @@ function UserMessageBubble({ message, className }) {
44491
44819
  const imageParts = getImageParts2(message.content);
44492
44820
  const whatifParsed = text && imageParts.length === 0 && fileParts.length === 0 ? parseWhatIfPrompt(text) : null;
44493
44821
  if (whatifParsed) {
44494
- return /* @__PURE__ */ jsx23("div", { className: cn("blade-chat-user-row flex justify-end", className), children: /* @__PURE__ */ jsx23("div", { className: "blade-chat-user-col flex max-w-[72%] flex-col items-end gap-3", children: /* @__PURE__ */ jsx23(WhatIfUserBubble, { parsed: whatifParsed }) }) });
44822
+ return /* @__PURE__ */ jsx24("div", { className: cn("blade-chat-user-row flex justify-end", className), children: /* @__PURE__ */ jsx24("div", { className: "blade-chat-user-col flex max-w-[72%] flex-col items-end gap-3", children: /* @__PURE__ */ jsx24(WhatIfUserBubble, { parsed: whatifParsed }) }) });
44495
44823
  }
44496
- return /* @__PURE__ */ jsx23("div", { className: cn("blade-chat-user-row flex justify-end", className), children: /* @__PURE__ */ jsxs19("div", { className: "blade-chat-user-col flex max-w-[72%] flex-col items-end gap-3", children: [
44497
- imageParts.length > 0 && /* @__PURE__ */ jsx23("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx23(
44824
+ return /* @__PURE__ */ jsx24("div", { className: cn("blade-chat-user-row flex justify-end", className), children: /* @__PURE__ */ jsxs20("div", { className: "blade-chat-user-col flex max-w-[72%] flex-col items-end gap-3", children: [
44825
+ imageParts.length > 0 && /* @__PURE__ */ jsx24("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx24(
44498
44826
  "img",
44499
44827
  {
44500
44828
  src: part.image_url.url,
@@ -44503,21 +44831,21 @@ function UserMessageBubble({ message, className }) {
44503
44831
  },
44504
44832
  part.image_url.url
44505
44833
  )) }),
44506
- fileParts.length > 0 && /* @__PURE__ */ jsx23("div", { className: "flex flex-col items-end gap-1.5", children: fileParts.map((part) => /* @__PURE__ */ jsxs19(
44834
+ fileParts.length > 0 && /* @__PURE__ */ jsx24("div", { className: "flex flex-col items-end gap-1.5", children: fileParts.map((part) => /* @__PURE__ */ jsxs20(
44507
44835
  "div",
44508
44836
  {
44509
44837
  className: "flex items-center gap-1.5 rounded-lg border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--muted)/0.3)] px-2.5 py-1.5 text-xs text-[hsl(var(--muted-foreground))]",
44510
44838
  children: [
44511
- /* @__PURE__ */ jsx23(FileText, { size: 12, className: "shrink-0" }),
44512
- /* @__PURE__ */ jsx23("span", { className: "max-w-56 truncate", title: part.name, children: part.name })
44839
+ /* @__PURE__ */ jsx24(FileText, { size: 12, className: "shrink-0" }),
44840
+ /* @__PURE__ */ jsx24("span", { className: "max-w-56 truncate", title: part.name, children: part.name })
44513
44841
  ]
44514
44842
  },
44515
44843
  `${part.name}-${part.data.length}`
44516
44844
  )) }),
44517
- text && /* @__PURE__ */ jsx23("div", { className: "blade-chat-user-bubble max-w-full rounded-[20px] rounded-br-[6px] border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-[18px] py-[13px] text-sm leading-[1.65] text-[hsl(var(--user-msg-fg))]", children: /* @__PURE__ */ jsx23(MarkdownContent, { className: "blade-chat-prose", children: text }) }),
44518
- text && isSending(message) && /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-1 pr-1 text-[11px] font-medium text-[hsl(var(--muted-foreground))/0.85]", children: [
44519
- /* @__PURE__ */ jsx23(LoaderCircle, { size: 11, className: "animate-spin", "aria-hidden": "true" }),
44520
- /* @__PURE__ */ jsx23("span", { children: "\u53D1\u9001\u4E2D" })
44845
+ text && /* @__PURE__ */ jsx24("div", { className: "blade-chat-user-bubble max-w-full rounded-[20px] rounded-br-[6px] border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-[18px] py-[13px] text-sm leading-[1.65] text-[hsl(var(--user-msg-fg))]", children: /* @__PURE__ */ jsx24(MarkdownContent, { className: "blade-chat-prose", children: text }) }),
44846
+ text && isSending(message) && /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-1 pr-1 text-[11px] font-medium text-[hsl(var(--muted-foreground))/0.85]", children: [
44847
+ /* @__PURE__ */ jsx24(LoaderCircle, { size: 11, className: "animate-spin", "aria-hidden": "true" }),
44848
+ /* @__PURE__ */ jsx24("span", { children: "\u53D1\u9001\u4E2D" })
44521
44849
  ] })
44522
44850
  ] }) });
44523
44851
  }
@@ -44526,11 +44854,11 @@ function ErrorMessageBlock({
44526
44854
  className
44527
44855
  }) {
44528
44856
  const text = chatErrorForDisplay(getTextContent2(message.content));
44529
- return /* @__PURE__ */ jsx23("div", { className: cn("blade-chat-error-row flex min-w-0 justify-start", className), children: /* @__PURE__ */ jsx23("div", { className: "blade-chat-error-block min-w-0 max-w-full whitespace-pre-wrap break-words border-l-[3px] border-[hsl(var(--border))] px-3 py-1 text-left text-sm leading-7 text-[hsl(var(--muted-foreground))] [overflow-wrap:anywhere]", children: text }) });
44857
+ return /* @__PURE__ */ jsx24("div", { className: cn("blade-chat-error-row flex min-w-0 justify-start", className), children: /* @__PURE__ */ jsx24("div", { className: "blade-chat-error-block min-w-0 max-w-full whitespace-pre-wrap break-words border-l-[3px] border-[hsl(var(--border))] px-3 py-1 text-left text-sm leading-7 text-[hsl(var(--muted-foreground))] [overflow-wrap:anywhere]", children: text }) });
44530
44858
  }
44531
44859
 
44532
44860
  // src/components/MessageList.tsx
44533
- import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
44861
+ import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
44534
44862
  function parseModeChange(message) {
44535
44863
  if (message.kind !== "mode_change" || typeof message.content !== "string") {
44536
44864
  return null;
@@ -44590,7 +44918,7 @@ function MessageList({
44590
44918
  const userMessages = visibleRootMessages.filter((message) => isUserMessage(message));
44591
44919
  const latestUserMessage = userMessages.at(-1);
44592
44920
  const shouldPinLatestUser = latestUserMessage != null && (latestUserMessage.entry_id == null ? isStreaming : latestUserMessage.entry_id.startsWith("local-user-"));
44593
- const renderBlocks = useMemo15(() => {
44921
+ const renderBlocks = useMemo16(() => {
44594
44922
  const visible = messages.filter((message) => {
44595
44923
  if ((message.loop_name ?? "root") !== "root") return false;
44596
44924
  if (isHiddenInternalMessage(message)) return false;
@@ -44664,25 +44992,25 @@ function MessageList({
44664
44992
  }
44665
44993
  return blocks;
44666
44994
  }, [messages, isStreaming]);
44667
- return /* @__PURE__ */ jsxs20("div", { className: cn("blade-chat-messages relative min-h-0 flex-1", className), children: [
44668
- isStreaming ? /* @__PURE__ */ jsx24("output", { className: "sr-only", children: "\u6B63\u5728\u751F\u6210\u56DE\u590D" }) : null,
44669
- /* @__PURE__ */ jsxs20(
44995
+ return /* @__PURE__ */ jsxs21("div", { className: cn("blade-chat-messages relative min-h-0 flex-1", className), children: [
44996
+ isStreaming ? /* @__PURE__ */ jsx25("output", { className: "sr-only", children: "\u6B63\u5728\u751F\u6210\u56DE\u590D" }) : null,
44997
+ /* @__PURE__ */ jsxs21(
44670
44998
  StickToBottom,
44671
44999
  {
44672
45000
  className: "h-full overflow-y-hidden",
44673
45001
  initial: "instant",
44674
45002
  resize: "instant",
44675
45003
  children: [
44676
- /* @__PURE__ */ jsx24(StickToBottom.Content, { className: "blade-chat-messages-scroll", children: /* @__PURE__ */ jsxs20("div", { className: "blade-chat-messages-content mx-auto max-w-[748px]", children: [
44677
- historyPaging && (historyPaging.hasOlder || historyPaging.loading) ? /* @__PURE__ */ jsx24(LoadOlderSentinel, { ...historyPaging }) : null,
44678
- /* @__PURE__ */ jsxs20("div", { className: "flex min-w-0 flex-col", children: [
44679
- renderBlocks.length === 0 ? emptyState ?? /* @__PURE__ */ jsxs20("div", { className: "blade-chat-empty", children: [
44680
- /* @__PURE__ */ jsx24(MessageSquare, { size: 40, strokeWidth: 1.5 }),
44681
- /* @__PURE__ */ jsx24("span", { className: "text-base font-medium", children: "\u5F00\u59CB\u5BF9\u8BDD" }),
44682
- /* @__PURE__ */ jsx24("span", { className: "text-sm opacity-60", children: "\u5728\u4E0B\u65B9\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u804A\u5929" })
45004
+ /* @__PURE__ */ jsx25(StickToBottom.Content, { className: "blade-chat-messages-scroll", children: /* @__PURE__ */ jsxs21("div", { className: "blade-chat-messages-content mx-auto max-w-[748px]", children: [
45005
+ historyPaging && (historyPaging.hasOlder || historyPaging.loading) ? /* @__PURE__ */ jsx25(LoadOlderSentinel, { ...historyPaging }) : null,
45006
+ /* @__PURE__ */ jsxs21("div", { className: "flex min-w-0 flex-col", children: [
45007
+ renderBlocks.length === 0 ? emptyState ?? /* @__PURE__ */ jsxs21("div", { className: "blade-chat-empty", children: [
45008
+ /* @__PURE__ */ jsx25(MessageSquare, { size: 40, strokeWidth: 1.5 }),
45009
+ /* @__PURE__ */ jsx25("span", { className: "text-base font-medium", children: "\u5F00\u59CB\u5BF9\u8BDD" }),
45010
+ /* @__PURE__ */ jsx25("span", { className: "text-sm opacity-60", children: "\u5728\u4E0B\u65B9\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u804A\u5929" })
44683
45011
  ] }) : renderBlocks.map((block) => {
44684
45012
  if (block.type === "message") {
44685
- return /* @__PURE__ */ jsx24("div", { "data-entry-id": block.message.entry_id, children: isUserMessage(block.message) ? /* @__PURE__ */ jsx24(UserMessageBubble, { message: block.message }) : isErrorMessage(block.message) ? /* @__PURE__ */ jsx24(ErrorMessageBlock, { message: block.message }) : null }, block.key);
45013
+ return /* @__PURE__ */ jsx25("div", { "data-entry-id": block.message.entry_id, children: isUserMessage(block.message) ? /* @__PURE__ */ jsx25(UserMessageBubble, { message: block.message }) : isErrorMessage(block.message) ? /* @__PURE__ */ jsx25(ErrorMessageBlock, { message: block.message }) : null }, block.key);
44686
45014
  }
44687
45015
  if (block.type === "assistant_turn") {
44688
45016
  const blockFeedback = block.messages.map(
@@ -44693,14 +45021,14 @@ function MessageList({
44693
45021
  (message) => message.entry_id === postChatFollowup.assistant_entry_id
44694
45022
  )
44695
45023
  );
44696
- return /* @__PURE__ */ jsx24("div", { "data-entry-id": block.messages[0]?.entry_id, children: /* @__PURE__ */ jsxs20(
45024
+ return /* @__PURE__ */ jsx25("div", { "data-entry-id": block.messages[0]?.entry_id, children: /* @__PURE__ */ jsxs21(
44697
45025
  RenderErrorBoundary,
44698
45026
  {
44699
45027
  label: "\u52A9\u624B\u6D88\u606F",
44700
45028
  details: block.key,
44701
45029
  resetKey: getMessageResetSignature(block.messages),
44702
45030
  children: [
44703
- /* @__PURE__ */ jsx24(
45031
+ /* @__PURE__ */ jsx25(
44704
45032
  AssistantTurnBlock,
44705
45033
  {
44706
45034
  messages: block.messages,
@@ -44713,8 +45041,8 @@ function MessageList({
44713
45041
  sessionId
44714
45042
  }
44715
45043
  ),
44716
- blockFeedback && !hasActiveFollowup ? /* @__PURE__ */ jsx24(HistoricalResultFeedback, { feedback: blockFeedback }) : null,
44717
- hasActiveFollowup && postChatFollowup ? /* @__PURE__ */ jsx24(
45044
+ blockFeedback && !hasActiveFollowup ? /* @__PURE__ */ jsx25(HistoricalResultFeedback, { feedback: blockFeedback }) : null,
45045
+ hasActiveFollowup && postChatFollowup ? /* @__PURE__ */ jsx25(
44718
45046
  PostChatFollowupBlock,
44719
45047
  {
44720
45048
  followup: postChatFollowup,
@@ -44731,24 +45059,24 @@ function MessageList({
44731
45059
  ) }, block.key);
44732
45060
  }
44733
45061
  if (block.type === "compaction") {
44734
- return /* @__PURE__ */ jsxs20(
45062
+ return /* @__PURE__ */ jsxs21(
44735
45063
  "div",
44736
45064
  {
44737
45065
  className: "flex items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]",
44738
45066
  children: [
44739
- /* @__PURE__ */ jsx24(Layers, { size: 12 }),
44740
- /* @__PURE__ */ jsx24("span", { children: "\u4E0A\u4E0B\u6587\u5DF2\u538B\u7F29" })
45067
+ /* @__PURE__ */ jsx25(Layers, { size: 12 }),
45068
+ /* @__PURE__ */ jsx25("span", { children: "\u4E0A\u4E0B\u6587\u5DF2\u538B\u7F29" })
44741
45069
  ]
44742
45070
  },
44743
45071
  block.key
44744
45072
  );
44745
45073
  }
44746
- return /* @__PURE__ */ jsx24(PlanningDivider, { kind: block.kind }, block.key);
45074
+ return /* @__PURE__ */ jsx25(PlanningDivider, { kind: block.kind }, block.key);
44747
45075
  }),
44748
- sessionStatus === "interrupted" && !isStreaming ? /* @__PURE__ */ jsx24("div", { className: "flex", children: /* @__PURE__ */ jsx24("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
45076
+ sessionStatus === "interrupted" && !isStreaming ? /* @__PURE__ */ jsx25("div", { className: "flex", children: /* @__PURE__ */ jsx25("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
44749
45077
  ] })
44750
45078
  ] }) }),
44751
- /* @__PURE__ */ jsx24(
45079
+ /* @__PURE__ */ jsx25(
44752
45080
  PinLatestUserMessage,
44753
45081
  {
44754
45082
  userMessageCount: userMessages.length,
@@ -44758,7 +45086,7 @@ function MessageList({
44758
45086
  },
44759
45087
  sessionId ?? "no-session"
44760
45088
  ),
44761
- /* @__PURE__ */ jsx24(ScrollToBottomButton, {})
45089
+ /* @__PURE__ */ jsx25(ScrollToBottomButton, {})
44762
45090
  ]
44763
45091
  },
44764
45092
  sessionId ?? "no-session"
@@ -44774,7 +45102,7 @@ function LoadOlderSentinel({
44774
45102
  const sentinelRef = useRef22(null);
44775
45103
  const stateRef = useRef22({ hasOlder, loading, loadOlder });
44776
45104
  stateRef.current = { hasOlder, loading, loadOlder };
44777
- useEffect19(() => {
45105
+ useEffect20(() => {
44778
45106
  const sentinel = sentinelRef.current;
44779
45107
  const scroller = scrollRef.current;
44780
45108
  if (!sentinel || !scroller || typeof IntersectionObserver === "undefined") return;
@@ -44833,7 +45161,7 @@ function LoadOlderSentinel({
44833
45161
  observer.disconnect();
44834
45162
  };
44835
45163
  }, [contentRef, scrollRef]);
44836
- return /* @__PURE__ */ jsx24("div", { ref: sentinelRef, "data-history-sentinel": true, className: "flex h-6 items-center justify-center", children: loading ? /* @__PURE__ */ jsx24("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u52A0\u8F7D\u66F4\u65E9\u6D88\u606F\u2026" }) : null });
45164
+ return /* @__PURE__ */ jsx25("div", { ref: sentinelRef, "data-history-sentinel": true, className: "flex h-6 items-center justify-center", children: loading ? /* @__PURE__ */ jsx25("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u52A0\u8F7D\u66F4\u65E9\u6D88\u606F\u2026" }) : null });
44837
45165
  }
44838
45166
  function PinLatestUserMessage({
44839
45167
  userMessageCount,
@@ -44844,14 +45172,14 @@ function PinLatestUserMessage({
44844
45172
  const { contentRef, scrollRef, scrollToBottom, stopScroll } = useStickToBottomContext();
44845
45173
  const previousCountRef = useRef22(userMessageCount);
44846
45174
  const spacerHeightRef = useRef22(0);
44847
- const getScrollElement = useCallback25(() => scrollRef.current, [scrollRef]);
44848
- const getContentElement = useCallback25(() => contentRef.current, [contentRef]);
44849
- const getTargetElement = useCallback25(() => {
45175
+ const getScrollElement = useCallback26(() => scrollRef.current, [scrollRef]);
45176
+ const getContentElement = useCallback26(() => contentRef.current, [contentRef]);
45177
+ const getTargetElement = useCallback26(() => {
44850
45178
  const rows = contentRef.current?.querySelectorAll(".blade-chat-user-row");
44851
45179
  return rows?.item((rows?.length ?? 0) - 1) ?? null;
44852
45180
  }, [contentRef]);
44853
- const getSpacerHeight = useCallback25(() => spacerHeightRef.current, []);
44854
- const setSpacerHeight = useCallback25(
45181
+ const getSpacerHeight = useCallback26(() => spacerHeightRef.current, []);
45182
+ const setSpacerHeight = useCallback26(
44855
45183
  (height) => {
44856
45184
  spacerHeightRef.current = height;
44857
45185
  const content = contentRef.current;
@@ -44873,7 +45201,7 @@ function PinLatestUserMessage({
44873
45201
  stopAutoScroll: stopScroll,
44874
45202
  scrollToBottom
44875
45203
  });
44876
- useEffect19(() => {
45204
+ useEffect20(() => {
44877
45205
  if (userMessageCount > previousCountRef.current && !shouldPinLatestUser) {
44878
45206
  scrollToBottom("instant");
44879
45207
  }
@@ -44883,9 +45211,9 @@ function PinLatestUserMessage({
44883
45211
  }
44884
45212
  function ScrollToBottomButton() {
44885
45213
  const { isAtBottom, scrollToBottom } = useStickToBottomContext();
44886
- const [visible, setVisible] = useState28(false);
45214
+ const [visible, setVisible] = useState29(false);
44887
45215
  const hideTimerRef = useRef22(null);
44888
- useEffect19(() => {
45216
+ useEffect20(() => {
44889
45217
  if (isAtBottom) {
44890
45218
  if (!hideTimerRef.current) {
44891
45219
  hideTimerRef.current = setTimeout(() => {
@@ -44907,7 +45235,7 @@ function ScrollToBottomButton() {
44907
45235
  }
44908
45236
  };
44909
45237
  }, [isAtBottom]);
44910
- const handleClick = useCallback25(() => {
45238
+ const handleClick = useCallback26(() => {
44911
45239
  if (hideTimerRef.current) {
44912
45240
  clearTimeout(hideTimerRef.current);
44913
45241
  hideTimerRef.current = null;
@@ -44916,7 +45244,7 @@ function ScrollToBottomButton() {
44916
45244
  scrollToBottom();
44917
45245
  }, [scrollToBottom]);
44918
45246
  if (!visible) return null;
44919
- return /* @__PURE__ */ jsxs20(
45247
+ return /* @__PURE__ */ jsxs21(
44920
45248
  "button",
44921
45249
  {
44922
45250
  type: "button",
@@ -44924,25 +45252,25 @@ function ScrollToBottomButton() {
44924
45252
  "aria-label": "\u6EDA\u52A8\u5230\u5E95\u90E8",
44925
45253
  className: "blade-chat-scroll-bottom absolute bottom-4 right-4 flex items-center gap-1 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-1.5 text-xs text-[hsl(var(--muted-foreground))] shadow-lg transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
44926
45254
  children: [
44927
- /* @__PURE__ */ jsx24(ChevronDown, { size: 14 }),
44928
- /* @__PURE__ */ jsx24("span", { className: "blade-chat-scroll-bottom-label", children: "\u6EDA\u52A8\u5230\u5E95\u90E8" })
45255
+ /* @__PURE__ */ jsx25(ChevronDown, { size: 14 }),
45256
+ /* @__PURE__ */ jsx25("span", { className: "blade-chat-scroll-bottom-label", children: "\u6EDA\u52A8\u5230\u5E95\u90E8" })
44929
45257
  ]
44930
45258
  }
44931
45259
  );
44932
45260
  }
44933
45261
  function PlanningDivider({ kind }) {
44934
- return /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-3 py-1", children: [
44935
- /* @__PURE__ */ jsx24("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" }),
44936
- /* @__PURE__ */ jsxs20("div", { className: "inline-flex items-center gap-1.5 rounded-full border border-amber-500/30 bg-amber-500/10 px-3 py-1 text-[11px] text-amber-300", children: [
44937
- /* @__PURE__ */ jsx24(Lightbulb, { size: 12 }),
44938
- /* @__PURE__ */ jsx24("span", { children: kind === "enter" ? "\u8FDB\u5165\u89C4\u5212\u6A21\u5F0F" : "\u89C4\u5212\u5B8C\u6210" })
45262
+ return /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-3 py-1", children: [
45263
+ /* @__PURE__ */ jsx25("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" }),
45264
+ /* @__PURE__ */ jsxs21("div", { className: "inline-flex items-center gap-1.5 rounded-full border border-amber-500/30 bg-amber-500/10 px-3 py-1 text-[11px] text-amber-300", children: [
45265
+ /* @__PURE__ */ jsx25(Lightbulb, { size: 12 }),
45266
+ /* @__PURE__ */ jsx25("span", { children: kind === "enter" ? "\u8FDB\u5165\u89C4\u5212\u6A21\u5F0F" : "\u89C4\u5212\u5B8C\u6210" })
44939
45267
  ] }),
44940
- /* @__PURE__ */ jsx24("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" })
45268
+ /* @__PURE__ */ jsx25("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" })
44941
45269
  ] });
44942
45270
  }
44943
45271
 
44944
45272
  // src/components/ChatSurface.tsx
44945
- import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
45273
+ import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
44946
45274
  function themeAttr(theme) {
44947
45275
  return theme === "dark" ? "dark" : void 0;
44948
45276
  }
@@ -44979,7 +45307,7 @@ function ChatSurface({
44979
45307
  historyPaging,
44980
45308
  banner
44981
45309
  }) {
44982
- const [pending, setPending] = useState29([]);
45310
+ const [pending, setPending] = useState30([]);
44983
45311
  const currentPending = pending.filter((item) => item.sessionId === sessionId);
44984
45312
  const sendWithApps = async (text) => {
44985
45313
  const content = [...currentPending.map((item) => `[${item.label}]
@@ -44991,10 +45319,10 @@ ${item.content}`), text].filter(Boolean).join("\n\n");
44991
45319
  }
44992
45320
  return accepted;
44993
45321
  };
44994
- return /* @__PURE__ */ jsx25(McpAppMessageContext.Provider, { value: (message) => {
45322
+ return /* @__PURE__ */ jsx26(McpAppMessageContext.Provider, { value: (message) => {
44995
45323
  if (!sessionId || message.sessionId !== sessionId || isViewer) throw new Error("\u5F53\u524D\u4F1A\u8BDD\u4E0D\u80FD\u63A5\u6536\u5E94\u7528\u6D88\u606F");
44996
45324
  setPending((items) => [...items, { ...message, sessionId, id: crypto.randomUUID() }]);
44997
- }, children: /* @__PURE__ */ jsxs21(
45325
+ }, children: /* @__PURE__ */ jsxs22(
44998
45326
  "div",
44999
45327
  {
45000
45328
  "data-theme": themeAttr(theme),
@@ -45003,14 +45331,14 @@ ${item.content}`), text].filter(Boolean).join("\n\n");
45003
45331
  classNames?.root
45004
45332
  ),
45005
45333
  children: [
45006
- /* @__PURE__ */ jsx25(ConnectionBanner, { connection, className: classNames?.banner }),
45334
+ /* @__PURE__ */ jsx26(ConnectionBanner, { connection, className: classNames?.banner }),
45007
45335
  banner,
45008
- errorMessage && /* @__PURE__ */ jsxs21("div", { className: "blade-chat-error-bar flex items-start gap-2 border-b px-4 py-3 text-sm", children: [
45009
- /* @__PURE__ */ jsx25(CircleAlert, { size: 16, className: "mt-0.5 shrink-0" }),
45010
- /* @__PURE__ */ jsx25("span", { className: "min-w-0 whitespace-pre-wrap break-words [overflow-wrap:anywhere]", children: chatErrorForDisplay2(errorMessage) })
45336
+ errorMessage && /* @__PURE__ */ jsxs22("div", { className: "blade-chat-error-bar flex items-start gap-2 border-b px-4 py-3 text-sm", children: [
45337
+ /* @__PURE__ */ jsx26(CircleAlert, { size: 16, className: "mt-0.5 shrink-0" }),
45338
+ /* @__PURE__ */ jsx26("span", { className: "min-w-0 whitespace-pre-wrap break-words [overflow-wrap:anywhere]", children: chatErrorForDisplay2(errorMessage) })
45011
45339
  ] }),
45012
45340
  slots?.header,
45013
- /* @__PURE__ */ jsx25(
45341
+ /* @__PURE__ */ jsx26(
45014
45342
  MessageList,
45015
45343
  {
45016
45344
  messages,
@@ -45032,7 +45360,7 @@ ${item.content}`), text].filter(Boolean).join("\n\n");
45032
45360
  historyPaging
45033
45361
  }
45034
45362
  ),
45035
- showPlanUpdates ? /* @__PURE__ */ jsx25(
45363
+ showPlanUpdates ? /* @__PURE__ */ jsx26(
45036
45364
  CurrentPlanPanel,
45037
45365
  {
45038
45366
  messages,
@@ -45044,14 +45372,14 @@ ${item.content}`), text].filter(Boolean).join("\n\n");
45044
45372
  ) : null,
45045
45373
  beforeInput,
45046
45374
  queuePanel,
45047
- currentPending.map((item) => /* @__PURE__ */ jsxs21("div", { style: { display: "flex", gap: 8, padding: "8px 16px" }, children: [
45048
- /* @__PURE__ */ jsxs21("details", { style: { flex: 1, minWidth: 0 }, children: [
45049
- /* @__PURE__ */ jsx25("summary", { children: item.label }),
45050
- /* @__PURE__ */ jsx25("pre", { style: { whiteSpace: "pre-wrap", overflowWrap: "anywhere" }, children: item.content })
45375
+ currentPending.map((item) => /* @__PURE__ */ jsxs22("div", { style: { display: "flex", gap: 8, padding: "8px 16px" }, children: [
45376
+ /* @__PURE__ */ jsxs22("details", { style: { flex: 1, minWidth: 0 }, children: [
45377
+ /* @__PURE__ */ jsx26("summary", { children: item.label }),
45378
+ /* @__PURE__ */ jsx26("pre", { style: { whiteSpace: "pre-wrap", overflowWrap: "anywhere" }, children: item.content })
45051
45379
  ] }),
45052
- /* @__PURE__ */ jsx25("button", { type: "button", "aria-label": "\u79FB\u9664\u5F85\u53D1\u9001\u5185\u5BB9", title: "\u79FB\u9664", onClick: () => setPending((items) => items.filter((other) => other.id !== item.id)), children: /* @__PURE__ */ jsx25(X, { size: 16 }) })
45380
+ /* @__PURE__ */ jsx26("button", { type: "button", "aria-label": "\u79FB\u9664\u5F85\u53D1\u9001\u5185\u5BB9", title: "\u79FB\u9664", onClick: () => setPending((items) => items.filter((other) => other.id !== item.id)), children: /* @__PURE__ */ jsx26(X, { size: 16 }) })
45053
45381
  ] }, item.id)),
45054
- /* @__PURE__ */ jsx25(
45382
+ /* @__PURE__ */ jsx26(
45055
45383
  ChatInput,
45056
45384
  {
45057
45385
  value: inputText,
@@ -45074,13 +45402,13 @@ ${item.content}`), text].filter(Boolean).join("\n\n");
45074
45402
  }
45075
45403
 
45076
45404
  // src/components/AgentChat.tsx
45077
- import { Fragment as Fragment8, jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
45405
+ import { Fragment as Fragment8, jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
45078
45406
  function isUnauthorizedError(error61) {
45079
45407
  return error61 instanceof BladeApiError2 && error61.status === 401;
45080
45408
  }
45081
45409
  function LoginCard({ client, onLoggedIn }) {
45082
- const [loggingIn, setLoggingIn] = useState30(false);
45083
- const [loginError, setLoginError] = useState30(null);
45410
+ const [loggingIn, setLoggingIn] = useState31(false);
45411
+ const [loginError, setLoginError] = useState31(null);
45084
45412
  const handleLogin = async () => {
45085
45413
  setLoggingIn(true);
45086
45414
  setLoginError(null);
@@ -45093,11 +45421,11 @@ function LoginCard({ client, onLoggedIn }) {
45093
45421
  setLoggingIn(false);
45094
45422
  }
45095
45423
  };
45096
- return /* @__PURE__ */ jsx26("div", { className: "blade-chat-login flex flex-1 items-center justify-center p-6", children: /* @__PURE__ */ jsxs22("div", { className: "flex w-full max-w-sm flex-col items-center gap-4 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-6 py-8 text-center", children: [
45097
- /* @__PURE__ */ jsx26(LockKeyhole, { size: 28, className: "text-[hsl(var(--muted-foreground))]" }),
45098
- /* @__PURE__ */ jsx26("div", { className: "text-base font-medium text-[hsl(var(--foreground))]", children: "\u9700\u8981\u767B\u5F55\u540E\u4F7F\u7528" }),
45099
- /* @__PURE__ */ jsx26("div", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u767B\u5F55\u540E\u5373\u53EF\u4E0E\u667A\u80FD\u4F53\u5BF9\u8BDD\uFF0C\u4F60\u7684\u4F1A\u8BDD\u5185\u5BB9\u4EC5\u81EA\u5DF1\u53EF\u89C1\u3002" }),
45100
- /* @__PURE__ */ jsx26(
45424
+ return /* @__PURE__ */ jsx27("div", { className: "blade-chat-login flex flex-1 items-center justify-center p-6", children: /* @__PURE__ */ jsxs23("div", { className: "flex w-full max-w-sm flex-col items-center gap-4 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-6 py-8 text-center", children: [
45425
+ /* @__PURE__ */ jsx27(LockKeyhole, { size: 28, className: "text-[hsl(var(--muted-foreground))]" }),
45426
+ /* @__PURE__ */ jsx27("div", { className: "text-base font-medium text-[hsl(var(--foreground))]", children: "\u9700\u8981\u767B\u5F55\u540E\u4F7F\u7528" }),
45427
+ /* @__PURE__ */ jsx27("div", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u767B\u5F55\u540E\u5373\u53EF\u4E0E\u667A\u80FD\u4F53\u5BF9\u8BDD\uFF0C\u4F60\u7684\u4F1A\u8BDD\u5185\u5BB9\u4EC5\u81EA\u5DF1\u53EF\u89C1\u3002" }),
45428
+ /* @__PURE__ */ jsx27(
45101
45429
  "button",
45102
45430
  {
45103
45431
  type: "button",
@@ -45107,20 +45435,20 @@ function LoginCard({ client, onLoggedIn }) {
45107
45435
  children: loggingIn ? "\u767B\u5F55\u4E2D\u2026" : "\u767B\u5F55"
45108
45436
  }
45109
45437
  ),
45110
- loginError && /* @__PURE__ */ jsx26("div", { className: "text-xs text-[hsl(var(--destructive))]", children: loginError })
45438
+ loginError && /* @__PURE__ */ jsx27("div", { className: "text-xs text-[hsl(var(--destructive))]", children: loginError })
45111
45439
  ] }) });
45112
45440
  }
45113
45441
  function AgentChat(props) {
45114
45442
  const client = useBladeClient();
45115
- const [attempt, setAttempt] = useState30(0);
45116
- const [needLogin, setNeedLogin] = useState30(() => !client.hasToken());
45443
+ const [attempt, setAttempt] = useState31(0);
45444
+ const [needLogin, setNeedLogin] = useState31(() => !client.hasToken());
45117
45445
  if (needLogin) {
45118
- return /* @__PURE__ */ jsx26(
45446
+ return /* @__PURE__ */ jsx27(
45119
45447
  "div",
45120
45448
  {
45121
45449
  "data-theme": themeAttr(props.theme),
45122
45450
  className: cn("blade-chat flex min-h-0 flex-1 flex-col", props.classNames?.root),
45123
- children: /* @__PURE__ */ jsx26(
45451
+ children: /* @__PURE__ */ jsx27(
45124
45452
  LoginCard,
45125
45453
  {
45126
45454
  client,
@@ -45133,7 +45461,7 @@ function AgentChat(props) {
45133
45461
  }
45134
45462
  );
45135
45463
  }
45136
- return /* @__PURE__ */ jsx26(ChatSessionView, { ...props, onUnauthorized: () => setNeedLogin(true) }, attempt);
45464
+ return /* @__PURE__ */ jsx27(ChatSessionView, { ...props, onUnauthorized: () => setNeedLogin(true) }, attempt);
45137
45465
  }
45138
45466
  function ChatSessionView({
45139
45467
  sessionId,
@@ -45151,10 +45479,10 @@ function ChatSessionView({
45151
45479
  onUnauthorized
45152
45480
  }) {
45153
45481
  const client = useBladeClient();
45154
- const [planRevealRevisions, setPlanRevealRevisions] = useState30(
45482
+ const [planRevealRevisions, setPlanRevealRevisions] = useState31(
45155
45483
  () => /* @__PURE__ */ new Map()
45156
45484
  );
45157
- const handleSessionConnected = useCallback26((connectedSession) => {
45485
+ const handleSessionConnected = useCallback27((connectedSession) => {
45158
45486
  return connectedSession.on("toolResult", ({ toolCall, turn, source }) => {
45159
45487
  if (source === "reconnect_replay" || (turn.loop_id || "root") !== "root" || toolCall.status !== "done" || !isPlanUpdateTool(toolCall) || !parsePlanUpdate(toolCall.arguments)) {
45160
45488
  return;
@@ -45172,20 +45500,20 @@ function ChatSessionView({
45172
45500
  onSessionConnected: handleSessionConnected
45173
45501
  });
45174
45502
  const replay = useReplay(session);
45175
- const [stopRequested, setStopRequested] = useState30(false);
45176
- const [inputText, setInputText] = useState30("");
45177
- const [queueNotice, setQueueNotice] = useState30(null);
45178
- const [queuePendingItemId, setQueuePendingItemId] = useState30(null);
45179
- const [resultFeedback, setResultFeedback] = useState30([]);
45503
+ const [stopRequested, setStopRequested] = useState31(false);
45504
+ const [inputText, setInputText] = useState31("");
45505
+ const [queueNotice, setQueueNotice] = useState31(null);
45506
+ const [queuePendingItemId, setQueuePendingItemId] = useState31(null);
45507
+ const [resultFeedback, setResultFeedback] = useState31([]);
45180
45508
  const resolvedSessionId = session?.sessionId;
45181
45509
  const isViewer = state?.viewerRole === "viewer";
45182
45510
  const onSessionReadyRef = useRef23(onSessionReady);
45183
45511
  const readySessionRef = useRef23(null);
45184
45512
  const hasOnSessionReady = onSessionReady !== void 0;
45185
- useEffect20(() => {
45513
+ useEffect21(() => {
45186
45514
  onSessionReadyRef.current = onSessionReady;
45187
45515
  }, [onSessionReady]);
45188
- useEffect20(() => {
45516
+ useEffect21(() => {
45189
45517
  setResultFeedback([]);
45190
45518
  if (!resolvedSessionId || isViewer) return;
45191
45519
  let cancelled = false;
@@ -45210,23 +45538,23 @@ function ChatSessionView({
45210
45538
  cancelled = true;
45211
45539
  };
45212
45540
  }, [client, isViewer, resolvedSessionId]);
45213
- const resultFeedbackByEntry = useMemo16(
45541
+ const resultFeedbackByEntry = useMemo17(
45214
45542
  () => new Map(resultFeedback.map((item) => [item.assistant_entry_id, item])),
45215
45543
  [resultFeedback]
45216
45544
  );
45217
- const handleResultFeedbackSaved = useCallback26((saved) => {
45545
+ const handleResultFeedbackSaved = useCallback27((saved) => {
45218
45546
  setResultFeedback((current) => [
45219
45547
  ...current.filter((item) => item.assistant_entry_id !== saved.assistant_entry_id),
45220
45548
  saved
45221
45549
  ]);
45222
45550
  }, []);
45223
- useEffect20(() => {
45551
+ useEffect21(() => {
45224
45552
  const handler = onSessionReadyRef.current;
45225
45553
  if (!session || !hasOnSessionReady || !handler || readySessionRef.current === session) return;
45226
45554
  readySessionRef.current = session;
45227
45555
  handler(session);
45228
45556
  }, [session, hasOnSessionReady]);
45229
- useEffect20(() => {
45557
+ useEffect21(() => {
45230
45558
  if (!session) return;
45231
45559
  const offAttach = session.on("attachRequested", ({ label, content }) => {
45232
45560
  setInputText((prev) => `${prev ? `${prev}
@@ -45242,12 +45570,12 @@ ${content}`);
45242
45570
  offInsert();
45243
45571
  };
45244
45572
  }, [session]);
45245
- useEffect20(() => {
45573
+ useEffect21(() => {
45246
45574
  if (isUnauthorizedError(error61)) {
45247
45575
  onUnauthorized();
45248
45576
  }
45249
45577
  }, [error61, onUnauthorized]);
45250
- useEffect20(() => {
45578
+ useEffect21(() => {
45251
45579
  if (!session || !commands) return;
45252
45580
  const unsubscribes = Object.entries(commands).map(
45253
45581
  ([action, handler]) => session.onCommand(action, (payload) => handler(payload))
@@ -45322,7 +45650,7 @@ ${content}`);
45322
45650
  next[to] = item.id;
45323
45651
  handleQueueReorder(next);
45324
45652
  };
45325
- return /* @__PURE__ */ jsx26(
45653
+ return /* @__PURE__ */ jsx27(
45326
45654
  ChatSurface,
45327
45655
  {
45328
45656
  theme,
@@ -45332,9 +45660,9 @@ ${content}`);
45332
45660
  slots,
45333
45661
  placeholder,
45334
45662
  connection: state?.connection ?? "connecting",
45335
- banner: /* @__PURE__ */ jsxs22(Fragment8, { children: [
45336
- resolvedSessionId && !isViewer && (sessionPluginControls ? sessionPluginControls(resolvedSessionId) : /* @__PURE__ */ jsx26(SessionPluginSelector, { client, sessionId: resolvedSessionId })),
45337
- /* @__PURE__ */ jsx26(
45663
+ banner: /* @__PURE__ */ jsxs23(Fragment8, { children: [
45664
+ resolvedSessionId && !isViewer && (sessionPluginControls ? sessionPluginControls(resolvedSessionId) : /* @__PURE__ */ jsx27(SessionPluginSelector, { client, sessionId: resolvedSessionId })),
45665
+ /* @__PURE__ */ jsx27(
45338
45666
  ReplayBar,
45339
45667
  {
45340
45668
  isReplay: replay.isReplay,
@@ -45344,7 +45672,7 @@ ${content}`);
45344
45672
  onExit: () => void replay.exitToAutonomous()
45345
45673
  }
45346
45674
  ),
45347
- /* @__PURE__ */ jsx26(ReplayMismatchPrompt, { mismatch: replay.mismatch })
45675
+ /* @__PURE__ */ jsx27(ReplayMismatchPrompt, { mismatch: replay.mismatch })
45348
45676
  ] }),
45349
45677
  errorMessage,
45350
45678
  messages: state?.messages ?? [],
@@ -45356,7 +45684,7 @@ ${content}`);
45356
45684
  planRevealRevision,
45357
45685
  queuePanel: (
45358
45686
  // 只读身份不能操作队列,藏起来免得每个按钮都弹冲突。
45359
- isViewer ? void 0 : /* @__PURE__ */ jsx26(
45687
+ isViewer ? void 0 : /* @__PURE__ */ jsx27(
45360
45688
  SessionQueuePanel,
45361
45689
  {
45362
45690
  snapshot: state?.queue ?? EMPTY_SESSION_QUEUE,
@@ -45411,11 +45739,11 @@ ${content}`);
45411
45739
  }
45412
45740
 
45413
45741
  // src/components/LlmChat.tsx
45414
- import { useEffect as useEffect21, useMemo as useMemo17, useState as useState32 } from "react";
45742
+ import { useEffect as useEffect22, useMemo as useMemo18, useState as useState33 } from "react";
45415
45743
 
45416
45744
  // src/components/LlmAdvancedSettings.tsx
45417
- import { useState as useState31 } from "react";
45418
- import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
45745
+ import { useState as useState32 } from "react";
45746
+ import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
45419
45747
  var FIELDS = [
45420
45748
  { id: "baseURL", label: "\u6A21\u578B\u670D\u52A1\u5730\u5740", placeholder: "http://\u5185\u7F51\u5730\u5740/v1" },
45421
45749
  { id: "model", label: "\u6A21\u578B", placeholder: "\u6A21\u578B\u540D\u79F0" },
@@ -45461,13 +45789,13 @@ function writeOverride(settings, baseURL, override) {
45461
45789
  }
45462
45790
  function LlmAdvancedSettingsBar({ settings, defaults: defaults2, override, onChange }) {
45463
45791
  const normalized = normalizeAdvanced(settings);
45464
- const [open2, setOpen] = useState31(false);
45465
- const [draft, setDraft] = useState31(override);
45792
+ const [open2, setOpen] = useState32(false);
45793
+ const [draft, setDraft] = useState32(override);
45466
45794
  if (!normalized) return null;
45467
45795
  const fields2 = FIELDS.filter((field) => normalized[field.id]);
45468
45796
  const dirty = Object.keys(override).length > 0;
45469
- return /* @__PURE__ */ jsxs23("div", { className: "blade-chat-advanced border-t border-[hsl(var(--border))] px-4 py-2 text-xs", children: [
45470
- /* @__PURE__ */ jsxs23(
45797
+ return /* @__PURE__ */ jsxs24("div", { className: "blade-chat-advanced border-t border-[hsl(var(--border))] px-4 py-2 text-xs", children: [
45798
+ /* @__PURE__ */ jsxs24(
45471
45799
  "button",
45472
45800
  {
45473
45801
  type: "button",
@@ -45477,16 +45805,16 @@ function LlmAdvancedSettingsBar({ settings, defaults: defaults2, override, onCha
45477
45805
  },
45478
45806
  className: "flex items-center gap-1.5 text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
45479
45807
  children: [
45480
- /* @__PURE__ */ jsx27(Settings2, { size: 13 }),
45808
+ /* @__PURE__ */ jsx28(Settings2, { size: 13 }),
45481
45809
  "\u9AD8\u7EA7\u8BBE\u7F6E",
45482
- dirty && /* @__PURE__ */ jsx27("span", { className: "text-[hsl(var(--primary))]", children: "\uFF08\u5DF2\u81EA\u5B9A\u4E49\uFF09" })
45810
+ dirty && /* @__PURE__ */ jsx28("span", { className: "text-[hsl(var(--primary))]", children: "\uFF08\u5DF2\u81EA\u5B9A\u4E49\uFF09" })
45483
45811
  ]
45484
45812
  }
45485
45813
  ),
45486
- open2 && /* @__PURE__ */ jsxs23("div", { className: "mt-2 flex flex-col gap-2", children: [
45487
- fields2.map((field) => /* @__PURE__ */ jsxs23("label", { className: "flex flex-col gap-1", children: [
45488
- /* @__PURE__ */ jsx27("span", { className: "text-[hsl(var(--muted-foreground))]", children: field.label }),
45489
- /* @__PURE__ */ jsx27(
45814
+ open2 && /* @__PURE__ */ jsxs24("div", { className: "mt-2 flex flex-col gap-2", children: [
45815
+ fields2.map((field) => /* @__PURE__ */ jsxs24("label", { className: "flex flex-col gap-1", children: [
45816
+ /* @__PURE__ */ jsx28("span", { className: "text-[hsl(var(--muted-foreground))]", children: field.label }),
45817
+ /* @__PURE__ */ jsx28(
45490
45818
  "input",
45491
45819
  {
45492
45820
  type: field.secret ? "password" : "text",
@@ -45497,9 +45825,9 @@ function LlmAdvancedSettingsBar({ settings, defaults: defaults2, override, onCha
45497
45825
  }
45498
45826
  )
45499
45827
  ] }, field.id)),
45500
- normalized.apiKey && /* @__PURE__ */ jsx27("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u5BC6\u94A5\u4F1A\u5B58\u5728\u8FD9\u53F0\u6D4F\u89C8\u5668\u91CC\u3002\u53EA\u5728\u4F60\u4FE1\u5F97\u8FC7\u8FD9\u53F0\u673A\u5668\u65F6\u586B\u3002" }),
45501
- /* @__PURE__ */ jsxs23("div", { className: "flex gap-2", children: [
45502
- /* @__PURE__ */ jsx27(
45828
+ normalized.apiKey && /* @__PURE__ */ jsx28("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u5BC6\u94A5\u4F1A\u5B58\u5728\u8FD9\u53F0\u6D4F\u89C8\u5668\u91CC\u3002\u53EA\u5728\u4F60\u4FE1\u5F97\u8FC7\u8FD9\u53F0\u673A\u5668\u65F6\u586B\u3002" }),
45829
+ /* @__PURE__ */ jsxs24("div", { className: "flex gap-2", children: [
45830
+ /* @__PURE__ */ jsx28(
45503
45831
  "button",
45504
45832
  {
45505
45833
  type: "button",
@@ -45514,7 +45842,7 @@ function LlmAdvancedSettingsBar({ settings, defaults: defaults2, override, onCha
45514
45842
  children: "\u4FDD\u5B58"
45515
45843
  }
45516
45844
  ),
45517
- /* @__PURE__ */ jsx27(
45845
+ /* @__PURE__ */ jsx28(
45518
45846
  "button",
45519
45847
  {
45520
45848
  type: "button",
@@ -45533,7 +45861,7 @@ function LlmAdvancedSettingsBar({ settings, defaults: defaults2, override, onCha
45533
45861
  }
45534
45862
 
45535
45863
  // src/components/LlmChat.tsx
45536
- import { jsx as jsx28 } from "react/jsx-runtime";
45864
+ import { jsx as jsx29 } from "react/jsx-runtime";
45537
45865
  function LlmChat({
45538
45866
  classNames,
45539
45867
  renderers,
@@ -45545,12 +45873,12 @@ function LlmChat({
45545
45873
  onOverrideChange,
45546
45874
  ...options
45547
45875
  }) {
45548
- const [override, setOverride] = useState32(() => readOverride(advanced, options.baseURL));
45876
+ const [override, setOverride] = useState33(() => readOverride(advanced, options.baseURL));
45549
45877
  const effective = { ...options, ...override };
45550
45878
  const { messages, isStreaming, error: error61, send, stop, reset } = useLlmChat(effective);
45551
- const [inputText, setInputText] = useState32("");
45552
- const [stopRequested, setStopRequested] = useState32(false);
45553
- const handle = useMemo17(
45879
+ const [inputText, setInputText] = useState33("");
45880
+ const [stopRequested, setStopRequested] = useState33(false);
45881
+ const handle = useMemo18(
45554
45882
  () => ({
45555
45883
  insertText: (text) => setInputText((prev) => prev ? `${prev}
45556
45884
  ${text}` : text),
@@ -45559,10 +45887,10 @@ ${text}` : text),
45559
45887
  }),
45560
45888
  [send, reset]
45561
45889
  );
45562
- useEffect21(() => {
45890
+ useEffect22(() => {
45563
45891
  onReady?.(handle);
45564
45892
  }, [handle, onReady]);
45565
- return /* @__PURE__ */ jsx28(
45893
+ return /* @__PURE__ */ jsx29(
45566
45894
  ChatSurface,
45567
45895
  {
45568
45896
  theme,
@@ -45587,7 +45915,7 @@ ${text}` : text),
45587
45915
  setStopRequested(true);
45588
45916
  stop();
45589
45917
  },
45590
- beforeInput: advanced ? /* @__PURE__ */ jsx28(
45918
+ beforeInput: advanced ? /* @__PURE__ */ jsx29(
45591
45919
  LlmAdvancedSettingsBar,
45592
45920
  {
45593
45921
  settings: advanced,
@@ -45605,14 +45933,14 @@ ${text}` : text),
45605
45933
  }
45606
45934
 
45607
45935
  // src/components/ChatView.tsx
45608
- import { jsx as jsx29 } from "react/jsx-runtime";
45936
+ import { jsx as jsx30 } from "react/jsx-runtime";
45609
45937
  function ChatView(props) {
45610
45938
  const { mode, llm, onLlmReady, ...rest } = props;
45611
45939
  if (mode === "llm") {
45612
45940
  if (!llm) {
45613
45941
  throw new Error('ChatView: mode="llm" \u9700\u8981\u540C\u65F6\u4F20 llm={{ baseURL, model }}');
45614
45942
  }
45615
- return /* @__PURE__ */ jsx29(
45943
+ return /* @__PURE__ */ jsx30(
45616
45944
  LlmChat,
45617
45945
  {
45618
45946
  ...llm,
@@ -45625,7 +45953,188 @@ function ChatView(props) {
45625
45953
  }
45626
45954
  );
45627
45955
  }
45628
- return /* @__PURE__ */ jsx29(AgentChat, { ...rest });
45956
+ return /* @__PURE__ */ jsx30(AgentChat, { ...rest });
45957
+ }
45958
+
45959
+ // src/components/ConnectorPanel.tsx
45960
+ import { useCallback as useCallback28, useEffect as useEffect23, useMemo as useMemo19, useRef as useRef24, useState as useState34 } from "react";
45961
+
45962
+ // src/components/connector-panel-types.ts
45963
+ function selectionFromItem(item) {
45964
+ return {
45965
+ name: item.name,
45966
+ displayName: item.display_name ?? null,
45967
+ icon: item.icon,
45968
+ iconSource: item.iconSource
45969
+ };
45970
+ }
45971
+ var TRIGGER_ICON_LIMIT = 3;
45972
+ function triggerSummary(items) {
45973
+ const withIcon = items.filter((item) => Boolean(item.icon));
45974
+ return {
45975
+ icons: withIcon.slice(0, TRIGGER_ICON_LIMIT),
45976
+ overflow: Math.max(0, items.length - Math.min(withIcon.length, TRIGGER_ICON_LIMIT)),
45977
+ total: items.length
45978
+ };
45979
+ }
45980
+
45981
+ // src/components/ConnectorPanel.tsx
45982
+ import { Fragment as Fragment9, jsx as jsx31, jsxs as jsxs25 } from "react/jsx-runtime";
45983
+ function PanelDivider() {
45984
+ return /* @__PURE__ */ jsx31("div", { className: "my-1 border-[hsl(var(--border))] border-t" });
45985
+ }
45986
+ function PanelTitle({ children }) {
45987
+ return /* @__PURE__ */ jsx31("div", { className: "px-3 pt-1 pb-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children });
45988
+ }
45989
+ function ConnectorPanel({
45990
+ client,
45991
+ sessionId,
45992
+ pendingPlugins,
45993
+ onPendingPluginsChange,
45994
+ pendingDisabledReason,
45995
+ onPluginsChanged,
45996
+ onSelectedChange,
45997
+ renderComputerSection,
45998
+ renderExternalAccounts,
45999
+ renderFooterActions,
46000
+ className
46001
+ }) {
46002
+ const [query, setQuery] = useState34("");
46003
+ const [pendingCatalog, setPendingCatalog] = useState34(null);
46004
+ const [pendingLoading, setPendingLoading] = useState34(false);
46005
+ const [pendingError, setPendingError] = useState34(false);
46006
+ const activation = useSessionPluginActivation({
46007
+ client,
46008
+ // 首页不会走这个分支:待选在下面自己处理开关,不碰会话接口。
46009
+ sessionId: sessionId ?? "",
46010
+ onChange: onPluginsChanged
46011
+ });
46012
+ const { reload, items: sessionItems } = activation;
46013
+ useEffect23(() => {
46014
+ if (sessionId) reload();
46015
+ }, [reload, sessionId]);
46016
+ const loadPendingCatalog = useCallback28(async () => {
46017
+ setPendingLoading(true);
46018
+ setPendingError(false);
46019
+ try {
46020
+ const { plugins } = await client.plugins.catalog();
46021
+ setPendingCatalog(plugins);
46022
+ } catch {
46023
+ setPendingError(true);
46024
+ } finally {
46025
+ setPendingLoading(false);
46026
+ }
46027
+ }, [client]);
46028
+ useEffect23(() => {
46029
+ if (sessionId) return;
46030
+ void loadPendingCatalog();
46031
+ }, [loadPendingCatalog, sessionId]);
46032
+ const selected = useMemo19(
46033
+ () => new Set((pendingPlugins ?? []).map((item) => item.name)),
46034
+ [pendingPlugins]
46035
+ );
46036
+ const items = useMemo19(() => {
46037
+ if (sessionId) return sessionItems;
46038
+ return catalogToConnectorItems(pendingCatalog ?? []).map((item) => ({
46039
+ ...item,
46040
+ active: selected.has(item.name)
46041
+ }));
46042
+ }, [pendingCatalog, selected, sessionId, sessionItems]);
46043
+ const visibleItems = useMemo19(
46044
+ () => sessionId ? filterConnectorItems(items, query) : filterConnectorItems(items, query).map((item) => ({ ...item, config: void 0 })),
46045
+ [items, query, sessionId]
46046
+ );
46047
+ const togglePending = useCallback28((item, next) => {
46048
+ const kept = (pendingPlugins ?? []).filter((entry) => entry.name !== item.name);
46049
+ onPendingPluginsChange?.(next ? [...kept, selectionFromItem(item)] : kept);
46050
+ }, [onPendingPluginsChange, pendingPlugins]);
46051
+ const toggle = useCallback28((item, next) => {
46052
+ if (sessionId) activation.toggle(item, next);
46053
+ else togglePending(item, next);
46054
+ }, [activation, sessionId, togglePending]);
46055
+ const selectedItems = useMemo19(
46056
+ () => items.filter((item) => item.active),
46057
+ [items]
46058
+ );
46059
+ const onSelectedChangeRef = useRef24(onSelectedChange);
46060
+ onSelectedChangeRef.current = onSelectedChange;
46061
+ const latestSelected = useRef24(selectedItems);
46062
+ latestSelected.current = selectedItems;
46063
+ const reportSelected = useCallback28(() => {
46064
+ onSelectedChangeRef.current?.(latestSelected.current);
46065
+ }, []);
46066
+ const selectedNames = selectedItems.map((item) => item.name).join("\0");
46067
+ useEffect23(reportSelected, [reportSelected, selectedNames]);
46068
+ const failed = sessionId ? activation.listError : pendingError;
46069
+ return /* @__PURE__ */ jsxs25("div", { className, children: [
46070
+ /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-2 border-[hsl(var(--border))] border-b px-3 py-2", children: [
46071
+ /* @__PURE__ */ jsx31(Search, { size: 12, className: "shrink-0 text-[hsl(var(--muted-foreground))]", "aria-hidden": "true" }),
46072
+ /* @__PURE__ */ jsx31(
46073
+ "input",
46074
+ {
46075
+ value: query,
46076
+ onChange: (event) => setQuery(event.target.value),
46077
+ placeholder: "\u641C\u7D22\u8FDE\u63A5\u5668",
46078
+ "aria-label": "\u641C\u7D22\u8FDE\u63A5\u5668",
46079
+ className: "min-w-0 flex-1 bg-transparent text-[11px] outline-none placeholder:text-[hsl(var(--muted-foreground))]"
46080
+ }
46081
+ )
46082
+ ] }),
46083
+ renderComputerSection ? /* @__PURE__ */ jsxs25(Fragment9, { children: [
46084
+ /* @__PURE__ */ jsx31(PanelTitle, { children: "\u7535\u8111" }),
46085
+ renderComputerSection(query)
46086
+ ] }) : null,
46087
+ /* @__PURE__ */ jsx31(PanelDivider, {}),
46088
+ /* @__PURE__ */ jsx31(PanelTitle, { children: "\u63D2\u4EF6" }),
46089
+ !sessionId ? (
46090
+ // 首页没有会话,开关只记下「这条消息要带上谁」:不说清楚,用户会以为已经
46091
+ // 生效(issue 明确要求「明确为待选,不宣称已经激活」)。
46092
+ /* @__PURE__ */ jsx31("div", { className: "px-3 pb-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: "\u5148\u9009\u4E2D\uFF0C\u53D1\u9001\u8FD9\u6761\u6D88\u606F\u65F6\u4F1A\u4E00\u5E76\u542F\u7528" })
46093
+ ) : null,
46094
+ (sessionId ? activation.loading : pendingLoading) && visibleItems.length === 0 ? /* @__PURE__ */ jsxs25("div", { className: "px-3 py-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
46095
+ /* @__PURE__ */ jsx31(LoaderCircle, { size: 12, className: "mr-1 inline animate-spin" }),
46096
+ "\u6B63\u5728\u83B7\u53D6\u63D2\u4EF6\u2026"
46097
+ ] }) : null,
46098
+ failed ? /* @__PURE__ */ jsx31(
46099
+ "button",
46100
+ {
46101
+ type: "button",
46102
+ onClick: () => sessionId ? reload() : void loadPendingCatalog(),
46103
+ className: "px-3 py-1.5 text-left text-[11px] text-[hsl(var(--muted-foreground))] underline",
46104
+ children: "\u63D2\u4EF6\u5217\u8868\u6682\u4E0D\u53EF\u7528\uFF0C\u70B9\u51FB\u91CD\u8BD5"
46105
+ }
46106
+ ) : null,
46107
+ /* @__PURE__ */ jsx31(
46108
+ PluginConnectorList,
46109
+ {
46110
+ client,
46111
+ sessionId,
46112
+ items: visibleItems,
46113
+ inFlight: activation.inFlight,
46114
+ busy: sessionId ? activation.busy : pendingLoading,
46115
+ mutationError: sessionId ? activation.mutationError : false,
46116
+ onToggle: toggle,
46117
+ onRetry: activation.retry,
46118
+ onEditConfig: activation.editConfig,
46119
+ configuring: sessionId ? activation.configuring : null,
46120
+ onConfigSaved: activation.onConfigSaved,
46121
+ onConfigClose: activation.onConfigClose,
46122
+ disabledReason: sessionId ? null : pendingDisabledReason,
46123
+ unavailableText: failed ? null : query.trim() ? "\u6CA1\u6709\u5339\u914D\u7684\u63D2\u4EF6" : null,
46124
+ emptyText: sessionId ? "\u5C1A\u672A\u5B89\u88C5\u63D2\u4EF6" : "\u5C1A\u672A\u5B89\u88C5\u63D2\u4EF6\uFF0C\u53BB\u5E94\u7528\u5E02\u573A\u6DFB\u52A0\u4E00\u4E2A",
46125
+ draft: !sessionId
46126
+ }
46127
+ ),
46128
+ renderExternalAccounts ? /* @__PURE__ */ jsxs25(Fragment9, { children: [
46129
+ /* @__PURE__ */ jsx31(PanelDivider, {}),
46130
+ /* @__PURE__ */ jsx31(PanelTitle, { children: "\u5916\u90E8\u8D26\u53F7" }),
46131
+ renderExternalAccounts(query)
46132
+ ] }) : null,
46133
+ renderFooterActions ? /* @__PURE__ */ jsxs25(Fragment9, { children: [
46134
+ /* @__PURE__ */ jsx31(PanelDivider, {}),
46135
+ renderFooterActions()
46136
+ ] }) : null
46137
+ ] });
45629
46138
  }
45630
46139
 
45631
46140
  // src/components/ContextCard.tsx
@@ -45633,16 +46142,16 @@ import {
45633
46142
  getContextDisplayState,
45634
46143
  getContextGroupDisplayState
45635
46144
  } from "@blade-hq/agent-client";
45636
- import { jsx as jsx30, jsxs as jsxs24 } from "react/jsx-runtime";
46145
+ import { jsx as jsx32, jsxs as jsxs26 } from "react/jsx-runtime";
45637
46146
  function ContextCard({ context, className }) {
45638
46147
  const display = getContextDisplayState(context);
45639
- return /* @__PURE__ */ jsxs24(
46148
+ return /* @__PURE__ */ jsxs26(
45640
46149
  "details",
45641
46150
  {
45642
46151
  className: `blade-chat-context-card group/context-card rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] text-sm ${className ?? ""}`,
45643
46152
  children: [
45644
- /* @__PURE__ */ jsxs24("summary", { className: "blade-chat-context-summary flex cursor-pointer list-none items-center gap-2 px-3 py-2.5 [&::-webkit-details-marker]:hidden", children: [
45645
- /* @__PURE__ */ jsx30(
46153
+ /* @__PURE__ */ jsxs26("summary", { className: "blade-chat-context-summary flex cursor-pointer list-none items-center gap-2 px-3 py-2.5 [&::-webkit-details-marker]:hidden", children: [
46154
+ /* @__PURE__ */ jsx32(
45646
46155
  Layers,
45647
46156
  {
45648
46157
  size: 15,
@@ -45650,11 +46159,11 @@ function ContextCard({ context, className }) {
45650
46159
  "aria-hidden": "true"
45651
46160
  }
45652
46161
  ),
45653
- /* @__PURE__ */ jsxs24("span", { className: "blade-chat-context-copy min-w-0 flex-1", children: [
45654
- /* @__PURE__ */ jsx30("span", { className: "blade-chat-context-title block font-medium text-[hsl(var(--foreground))]", children: display.title }),
45655
- /* @__PURE__ */ jsx30("span", { className: "blade-chat-context-status block truncate text-xs text-[hsl(var(--muted-foreground))]", children: display.summary })
46162
+ /* @__PURE__ */ jsxs26("span", { className: "blade-chat-context-copy min-w-0 flex-1", children: [
46163
+ /* @__PURE__ */ jsx32("span", { className: "blade-chat-context-title block font-medium text-[hsl(var(--foreground))]", children: display.title }),
46164
+ /* @__PURE__ */ jsx32("span", { className: "blade-chat-context-status block truncate text-xs text-[hsl(var(--muted-foreground))]", children: display.summary })
45656
46165
  ] }),
45657
- /* @__PURE__ */ jsx30(
46166
+ /* @__PURE__ */ jsx32(
45658
46167
  ChevronDown,
45659
46168
  {
45660
46169
  size: 14,
@@ -45663,7 +46172,7 @@ function ContextCard({ context, className }) {
45663
46172
  }
45664
46173
  )
45665
46174
  ] }),
45666
- /* @__PURE__ */ jsx30("div", { className: "blade-chat-context-detail border-t border-[hsl(var(--border))] px-3 py-2.5 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: display.detail })
46175
+ /* @__PURE__ */ jsx32("div", { className: "blade-chat-context-detail border-t border-[hsl(var(--border))] px-3 py-2.5 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: display.detail })
45667
46176
  ]
45668
46177
  }
45669
46178
  );
@@ -45672,9 +46181,9 @@ function ContextGroupCard({ contexts, className }) {
45672
46181
  if (contexts.length === 0) return null;
45673
46182
  const single = contexts.length === 1 ? getContextDisplayState(contexts[0]) : null;
45674
46183
  const group = single ? null : getContextGroupDisplayState(contexts);
45675
- return /* @__PURE__ */ jsxs24("details", { className: `blade-chat-context-card group/context-group rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] text-sm ${className ?? ""}`, children: [
45676
- /* @__PURE__ */ jsxs24("summary", { className: "blade-chat-context-summary flex cursor-pointer list-none items-center gap-2 px-3 py-2.5 [&::-webkit-details-marker]:hidden", children: [
45677
- /* @__PURE__ */ jsx30(
46184
+ return /* @__PURE__ */ jsxs26("details", { className: `blade-chat-context-card group/context-group rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] text-sm ${className ?? ""}`, children: [
46185
+ /* @__PURE__ */ jsxs26("summary", { className: "blade-chat-context-summary flex cursor-pointer list-none items-center gap-2 px-3 py-2.5 [&::-webkit-details-marker]:hidden", children: [
46186
+ /* @__PURE__ */ jsx32(
45678
46187
  Layers,
45679
46188
  {
45680
46189
  size: 15,
@@ -45682,11 +46191,11 @@ function ContextGroupCard({ contexts, className }) {
45682
46191
  "aria-hidden": "true"
45683
46192
  }
45684
46193
  ),
45685
- /* @__PURE__ */ jsxs24("span", { className: "blade-chat-context-copy min-w-0 flex-1", children: [
45686
- /* @__PURE__ */ jsx30("span", { className: "blade-chat-context-title block font-medium text-[hsl(var(--foreground))]", children: single ? single.title : `${group?.title} \xB7 ${group?.count} \u9879` }),
45687
- /* @__PURE__ */ jsx30("span", { className: "blade-chat-context-status block truncate text-xs text-[hsl(var(--muted-foreground))]", children: single ? single.summary : group?.summary })
46194
+ /* @__PURE__ */ jsxs26("span", { className: "blade-chat-context-copy min-w-0 flex-1", children: [
46195
+ /* @__PURE__ */ jsx32("span", { className: "blade-chat-context-title block font-medium text-[hsl(var(--foreground))]", children: single ? single.title : `${group?.title} \xB7 ${group?.count} \u9879` }),
46196
+ /* @__PURE__ */ jsx32("span", { className: "blade-chat-context-status block truncate text-xs text-[hsl(var(--muted-foreground))]", children: single ? single.summary : group?.summary })
45688
46197
  ] }),
45689
- /* @__PURE__ */ jsx30(
46198
+ /* @__PURE__ */ jsx32(
45690
46199
  ChevronDown,
45691
46200
  {
45692
46201
  size: 14,
@@ -45695,7 +46204,7 @@ function ContextGroupCard({ contexts, className }) {
45695
46204
  }
45696
46205
  )
45697
46206
  ] }),
45698
- single ? /* @__PURE__ */ jsx30("div", { className: "blade-chat-context-detail border-t border-[hsl(var(--border))] px-3 py-2.5 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: single.detail }) : /* @__PURE__ */ jsx30("div", { className: "blade-chat-context-group-items flex flex-col gap-1.5 border-t border-[hsl(var(--border))] p-2", children: contexts.map((context) => /* @__PURE__ */ jsx30(
46207
+ single ? /* @__PURE__ */ jsx32("div", { className: "blade-chat-context-detail border-t border-[hsl(var(--border))] px-3 py-2.5 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: single.detail }) : /* @__PURE__ */ jsx32("div", { className: "blade-chat-context-group-items flex flex-col gap-1.5 border-t border-[hsl(var(--border))] p-2", children: contexts.map((context) => /* @__PURE__ */ jsx32(
45699
46208
  ContextCard,
45700
46209
  {
45701
46210
  context
@@ -45706,8 +46215,8 @@ function ContextGroupCard({ contexts, className }) {
45706
46215
  }
45707
46216
 
45708
46217
  // src/components/SessionMemoryToggle.tsx
45709
- import { useCallback as useCallback27, useEffect as useEffect22, useRef as useRef24, useState as useState33, useSyncExternalStore as useSyncExternalStore2 } from "react";
45710
- import { jsx as jsx31, jsxs as jsxs25 } from "react/jsx-runtime";
46218
+ import { useCallback as useCallback29, useEffect as useEffect24, useRef as useRef25, useState as useState35, useSyncExternalStore as useSyncExternalStore2 } from "react";
46219
+ import { jsx as jsx33, jsxs as jsxs27 } from "react/jsx-runtime";
45711
46220
  var saveStates = /* @__PURE__ */ new WeakMap();
45712
46221
  function getSaveState(client, sessionId) {
45713
46222
  let clientStates = saveStates.get(client);
@@ -45748,7 +46257,7 @@ function SessionMemoryToggle({
45748
46257
  throw new Error("SessionMemoryToggle \u5FC5\u987B\u5728 <BladeProvider> \u5185\u4F7F\u7528\u6216\u663E\u5F0F\u4F20\u5165 client");
45749
46258
  }
45750
46259
  const saveState = getSaveState(client, sessionId);
45751
- const subscribe = useCallback27(
46260
+ const subscribe = useCallback29(
45752
46261
  (listener) => {
45753
46262
  saveState.listeners.add(listener);
45754
46263
  return () => {
@@ -45758,19 +46267,19 @@ function SessionMemoryToggle({
45758
46267
  },
45759
46268
  [client, saveState, sessionId]
45760
46269
  );
45761
- const getSaving = useCallback27(() => saveState.saving, [saveState]);
46270
+ const getSaving = useCallback29(() => saveState.saving, [saveState]);
45762
46271
  const saving = useSyncExternalStore2(
45763
46272
  subscribe,
45764
46273
  getSaving,
45765
46274
  getSaving
45766
46275
  );
45767
- const [draftEnabled, setDraftEnabled] = useState33(enabled);
45768
- const activeSessionIdRef = useRef24(sessionId);
46276
+ const [draftEnabled, setDraftEnabled] = useState35(enabled);
46277
+ const activeSessionIdRef = useRef25(sessionId);
45769
46278
  activeSessionIdRef.current = sessionId;
45770
- useEffect22(() => {
46279
+ useEffect24(() => {
45771
46280
  setDraftEnabled(enabled);
45772
46281
  }, [enabled, sessionId]);
45773
- const update = useCallback27(
46282
+ const update = useCallback29(
45774
46283
  (nextEnabled) => {
45775
46284
  const currentSaveState = getSaveState(client, sessionId);
45776
46285
  if (currentSaveState.saving) return;
@@ -45796,9 +46305,9 @@ function SessionMemoryToggle({
45796
46305
  },
45797
46306
  [client, enabled, onError, onSaved, sessionId]
45798
46307
  );
45799
- return /* @__PURE__ */ jsxs25("label", { className: cn("flex items-center justify-between", className), children: [
45800
- /* @__PURE__ */ jsx31("span", { className: labelClassName, children: label }),
45801
- /* @__PURE__ */ jsx31(
46308
+ return /* @__PURE__ */ jsxs27("label", { className: cn("flex items-center justify-between", className), children: [
46309
+ /* @__PURE__ */ jsx33("span", { className: labelClassName, children: label }),
46310
+ /* @__PURE__ */ jsx33(
45802
46311
  "input",
45803
46312
  {
45804
46313
  type: "checkbox",
@@ -45859,6 +46368,7 @@ export {
45859
46368
  AgentChat,
45860
46369
  BladeProvider,
45861
46370
  ChatView,
46371
+ ConnectorPanel,
45862
46372
  ContextCard,
45863
46373
  ContextGroupCard,
45864
46374
  CurrentPlanPanel,
@@ -45868,6 +46378,7 @@ export {
45868
46378
  MemoryRefsHint,
45869
46379
  PLAN_AUTO_COLLAPSE_MS,
45870
46380
  PlanUpdateBlock,
46381
+ PluginConnectorList,
45871
46382
  ReplayBar,
45872
46383
  ReplayMismatchPrompt,
45873
46384
  SessionMemoryToggle,
@@ -45876,24 +46387,32 @@ export {
45876
46387
  SessionPluginIcon,
45877
46388
  SessionPluginSelector,
45878
46389
  SessionQueuePanel,
46390
+ TRIGGER_ICON_LIMIT,
45879
46391
  ToolUiCardView,
45880
46392
  WhatIfUserBubble,
46393
+ catalogToConnectorItems,
45881
46394
  classifyAgentComputerLaunchOutcome,
45882
46395
  collectMemoryRefs,
46396
+ filterConnectorItems,
45883
46397
  getPlanUpdateDisplayState,
45884
46398
  isAgentComputerCommand,
45885
46399
  isAgentComputerToolCall,
45886
46400
  isPlanUpdateTool,
46401
+ mergeConnectorItems,
45887
46402
  normalizeAdjacentUrlFormatting,
45888
46403
  parsePlanUpdate,
45889
46404
  parseWhatIfPrompt,
45890
46405
  pickCurrentPlanStep,
46406
+ pluginConnectorSummary,
46407
+ selectionFromItem,
45891
46408
  sessionPluginLabel,
46409
+ triggerSummary,
45892
46410
  useAgentSession,
45893
46411
  useBladeClient,
45894
46412
  useLlmChat,
45895
46413
  useMessagePin,
45896
- useReplay
46414
+ useReplay,
46415
+ useSessionPluginActivation
45897
46416
  };
45898
46417
  /*! Bundled license information:
45899
46418