@heroui/agent 0.2.0-beta.6 → 0.2.0-beta.7
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/CHANGELOG.md +11 -0
- package/dist/{chart-content-7PZT4YWI.js → chart-content-E4NPTUPR.js} +1 -1
- package/dist/{chunk-QOCNMON2.js → chunk-OQGXZY5L.js} +9 -4
- package/dist/{chunk-MUAFQBVY.js → chunk-V5S5FRGV.js} +2 -2
- package/dist/{component-renderer-PTMCOJHE.js → component-renderer-46EJDPTB.js} +2103 -1619
- package/dist/contracts.d.ts +1 -1
- package/dist/contracts.js +1 -1
- package/dist/css/index.css +1 -1
- package/dist/{embed-runtime-CR7PQH3Q.js → embed-runtime-UF7XJIFA.js} +525 -314
- package/dist/index.js +2 -2
- package/dist/next.js +2 -2
- package/dist/server.js +1 -1
- package/package.json +2 -2
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
shouldRestoreActiveAgentPermissionMode,
|
|
34
34
|
storeAgentPermissionMode,
|
|
35
35
|
takeAgentShellHandoff
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-OQGXZY5L.js";
|
|
37
37
|
import {
|
|
38
38
|
ActionButton,
|
|
39
39
|
CodeBlock,
|
|
@@ -1725,8 +1725,8 @@ import {
|
|
|
1725
1725
|
useEffectEvent,
|
|
1726
1726
|
useLayoutEffect as useLayoutEffect4,
|
|
1727
1727
|
useMemo as useMemo4,
|
|
1728
|
-
useRef as
|
|
1729
|
-
useState as
|
|
1728
|
+
useRef as useRef14,
|
|
1729
|
+
useState as useState15
|
|
1730
1730
|
} from "react";
|
|
1731
1731
|
|
|
1732
1732
|
// src/contracts/identity.ts
|
|
@@ -1777,7 +1777,7 @@ var agentModelIdSchema = z2.preprocess(
|
|
|
1777
1777
|
|
|
1778
1778
|
// src/contracts/version.ts
|
|
1779
1779
|
var HEROUI_AGENT_PROTOCOL_VERSION = 5;
|
|
1780
|
-
var HEROUI_AGENT_SDK_VERSION = "0.2.0-beta.
|
|
1780
|
+
var HEROUI_AGENT_SDK_VERSION = "0.2.0-beta.7";
|
|
1781
1781
|
var HEROUI_AGENT_TASK_ID = "heroui-agents-runtime";
|
|
1782
1782
|
|
|
1783
1783
|
// src/contracts/identity.ts
|
|
@@ -1957,6 +1957,14 @@ function inferActivityKind(label) {
|
|
|
1957
1957
|
if (/data|query|load|fetch|metric|table|account/.test(normalized)) return "data";
|
|
1958
1958
|
return "thinking";
|
|
1959
1959
|
}
|
|
1960
|
+
function hasResponseAfterLatestActivity(items, options) {
|
|
1961
|
+
if (!options.hasContent) return false;
|
|
1962
|
+
const latestActivityPartIndex = items.reduce(
|
|
1963
|
+
(latest, item) => Math.max(latest, item.messagePartIndex ?? -1),
|
|
1964
|
+
-1
|
|
1965
|
+
);
|
|
1966
|
+
return options.latestContentPartIndex >= latestActivityPartIndex;
|
|
1967
|
+
}
|
|
1960
1968
|
function collectActivity(message, clientTools, options = {}) {
|
|
1961
1969
|
if (message.role !== "assistant") return [];
|
|
1962
1970
|
const items = [];
|
|
@@ -1972,7 +1980,9 @@ function collectActivity(message, clientTools, options = {}) {
|
|
|
1972
1980
|
id: part.id ?? `${message.id}-activity-${index}`,
|
|
1973
1981
|
kind: part.data.kind ?? inferActivityKind(label2),
|
|
1974
1982
|
label: label2,
|
|
1975
|
-
|
|
1983
|
+
messagePartIndex: index,
|
|
1984
|
+
sources: part.data.sources,
|
|
1985
|
+
stateKnown: false
|
|
1976
1986
|
});
|
|
1977
1987
|
}
|
|
1978
1988
|
continue;
|
|
@@ -1993,16 +2003,38 @@ function collectActivity(message, clientTools, options = {}) {
|
|
|
1993
2003
|
toolPart.output && typeof toolPart.output === "object" && "rejected" in toolPart.output && toolPart.output.rejected
|
|
1994
2004
|
);
|
|
1995
2005
|
const label = rejected ? `Skipped ${baseLabel}` : toolPart.state === "output-error" ? `Couldn\u2019t complete ${baseLabel}` : baseLabel;
|
|
1996
|
-
|
|
2006
|
+
const active = toolPart.state === "input-available" || toolPart.state === "input-streaming";
|
|
2007
|
+
const existingIndex = items.findIndex((item) => item.label === label);
|
|
2008
|
+
if (existingIndex >= 0) {
|
|
2009
|
+
const existing = items[existingIndex];
|
|
2010
|
+
if (existing) {
|
|
2011
|
+
items[existingIndex] = {
|
|
2012
|
+
...existing,
|
|
2013
|
+
active,
|
|
2014
|
+
messagePartIndex: index,
|
|
2015
|
+
stateKnown: true
|
|
2016
|
+
};
|
|
2017
|
+
}
|
|
2018
|
+
continue;
|
|
2019
|
+
}
|
|
1997
2020
|
labels.add(label);
|
|
1998
2021
|
items.push({
|
|
1999
|
-
active
|
|
2022
|
+
active,
|
|
2000
2023
|
id: toolPart.toolCallId || `${message.id}-tool-${index}`,
|
|
2001
2024
|
kind: renderTool ? "chart" : toolName === "executeSandbox" ? "code" : toolName === "getComponentSchema" ? "thinking" : inferActivityKind(label),
|
|
2002
|
-
label
|
|
2025
|
+
label,
|
|
2026
|
+
messagePartIndex: index,
|
|
2027
|
+
stateKnown: true
|
|
2003
2028
|
});
|
|
2004
2029
|
}
|
|
2005
|
-
return items;
|
|
2030
|
+
if (!options.isStreaming || items.length === 0) return items;
|
|
2031
|
+
if (items.some((item) => item.active)) return items;
|
|
2032
|
+
const activeIndex = items.length - 1;
|
|
2033
|
+
if (items[activeIndex]?.stateKnown) return items;
|
|
2034
|
+
return items.map((item, index) => ({
|
|
2035
|
+
...item,
|
|
2036
|
+
active: index === activeIndex
|
|
2037
|
+
}));
|
|
2006
2038
|
}
|
|
2007
2039
|
|
|
2008
2040
|
// src/embed/activity-trail.tsx
|
|
@@ -2016,10 +2048,10 @@ import {
|
|
|
2016
2048
|
Wrench
|
|
2017
2049
|
} from "@gravity-ui/icons";
|
|
2018
2050
|
import { Disclosure as Disclosure2 } from "@heroui/react";
|
|
2019
|
-
import { useEffect as useEffect7, useRef as
|
|
2051
|
+
import { useEffect as useEffect7, useRef as useRef5, useState as useState5 } from "react";
|
|
2020
2052
|
|
|
2021
2053
|
// src/embed/animated-status-text.tsx
|
|
2022
|
-
import { useEffect as useEffect5,
|
|
2054
|
+
import { useEffect as useEffect5, useState as useState4 } from "react";
|
|
2023
2055
|
|
|
2024
2056
|
// src/embed/shimmer-text.tsx
|
|
2025
2057
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
@@ -2028,35 +2060,64 @@ function ShimmerText({ children, className, ...props }) {
|
|
|
2028
2060
|
}
|
|
2029
2061
|
|
|
2030
2062
|
// src/embed/animated-status-text.tsx
|
|
2031
|
-
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
2063
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2064
|
+
var STATUS_SWAP_MS = 280;
|
|
2032
2065
|
function AnimatedStatusText({
|
|
2033
2066
|
animateOnMount = true,
|
|
2034
2067
|
children,
|
|
2035
2068
|
className,
|
|
2036
2069
|
...props
|
|
2037
2070
|
}) {
|
|
2038
|
-
const
|
|
2039
|
-
|
|
2071
|
+
const [transition, setTransition] = useState4(() => ({
|
|
2072
|
+
current: { animate: animateOnMount, id: 0, text: children },
|
|
2073
|
+
previous: null
|
|
2074
|
+
}));
|
|
2075
|
+
if (transition.current.text !== children) {
|
|
2076
|
+
setTransition({
|
|
2077
|
+
current: { animate: true, id: transition.current.id + 1, text: children },
|
|
2078
|
+
previous: transition.current
|
|
2079
|
+
});
|
|
2080
|
+
}
|
|
2081
|
+
const currentId = transition.current.id;
|
|
2082
|
+
const previous = transition.previous;
|
|
2040
2083
|
useEffect5(() => {
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2084
|
+
if (!previous) return;
|
|
2085
|
+
const timer = window.setTimeout(() => {
|
|
2086
|
+
setTransition(
|
|
2087
|
+
(current) => current.current.id === currentId ? { ...current, previous: null } : current
|
|
2088
|
+
);
|
|
2089
|
+
}, STATUS_SWAP_MS);
|
|
2090
|
+
return () => window.clearTimeout(timer);
|
|
2091
|
+
}, [currentId, previous]);
|
|
2092
|
+
return /* @__PURE__ */ jsxs5(
|
|
2044
2093
|
"span",
|
|
2045
2094
|
{
|
|
2046
2095
|
...props,
|
|
2047
2096
|
"aria-label": props["aria-label"] ?? children,
|
|
2048
2097
|
className: `ha-status-text${className ? ` ${className}` : ""}`,
|
|
2049
2098
|
"data-slot": "animated-text",
|
|
2050
|
-
children:
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2099
|
+
children: [
|
|
2100
|
+
/* @__PURE__ */ jsx7(
|
|
2101
|
+
"span",
|
|
2102
|
+
{
|
|
2103
|
+
"aria-hidden": "true",
|
|
2104
|
+
"data-slot": "animated-text-value",
|
|
2105
|
+
className: transition.current.animate ? "ha-status-text__value ha-status-text__value--animated" : "ha-status-text__value",
|
|
2106
|
+
children: /* @__PURE__ */ jsx7(ShimmerText, { children: transition.current.text })
|
|
2107
|
+
},
|
|
2108
|
+
transition.current.id
|
|
2109
|
+
),
|
|
2110
|
+
transition.previous ? /* @__PURE__ */ jsx7(
|
|
2111
|
+
"span",
|
|
2112
|
+
{
|
|
2113
|
+
"aria-hidden": "true",
|
|
2114
|
+
className: "ha-status-text__value ha-status-text__value--exiting",
|
|
2115
|
+
"data-slot": "animated-text-previous-value",
|
|
2116
|
+
children: /* @__PURE__ */ jsx7(ShimmerText, { children: transition.previous.text })
|
|
2117
|
+
},
|
|
2118
|
+
transition.previous.id
|
|
2119
|
+
) : null
|
|
2120
|
+
]
|
|
2060
2121
|
}
|
|
2061
2122
|
);
|
|
2062
2123
|
}
|
|
@@ -2116,25 +2177,87 @@ function useScrollShadow(ref, offset = 1) {
|
|
|
2116
2177
|
}
|
|
2117
2178
|
|
|
2118
2179
|
// src/embed/activity-trail.tsx
|
|
2119
|
-
import { jsx as jsx8, jsxs as
|
|
2180
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2120
2181
|
var FOLLOW_THRESHOLD_PX = 24;
|
|
2121
|
-
|
|
2122
|
-
|
|
2182
|
+
var ACTIVITY_FADE_MS = 160;
|
|
2183
|
+
var ACTIVITY_COLLAPSE_MS = 220;
|
|
2184
|
+
function useFollowNewestStep(ref, contentVersion, isStreaming, isExpanded) {
|
|
2185
|
+
const isFollowingRef = useRef5(true);
|
|
2123
2186
|
useEffect7(() => {
|
|
2124
2187
|
const element = ref.current;
|
|
2125
2188
|
if (!element) return;
|
|
2126
|
-
|
|
2189
|
+
let autoScrollTimer;
|
|
2190
|
+
let isAutoScrolling = false;
|
|
2191
|
+
const updateFollowing = () => {
|
|
2127
2192
|
const distanceFromBottom = element.scrollHeight - element.scrollTop - element.clientHeight;
|
|
2128
2193
|
isFollowingRef.current = distanceFromBottom <= FOLLOW_THRESHOLD_PX;
|
|
2129
2194
|
};
|
|
2195
|
+
const handleScroll = () => {
|
|
2196
|
+
if (isAutoScrolling) return;
|
|
2197
|
+
updateFollowing();
|
|
2198
|
+
};
|
|
2199
|
+
const handleUserScrollIntent = () => {
|
|
2200
|
+
isAutoScrolling = false;
|
|
2201
|
+
window.clearTimeout(autoScrollTimer);
|
|
2202
|
+
requestAnimationFrame(updateFollowing);
|
|
2203
|
+
};
|
|
2204
|
+
const followNewest = () => {
|
|
2205
|
+
if (!isExpanded || !isStreaming || !isFollowingRef.current) return;
|
|
2206
|
+
const shouldReduceMotion = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
2207
|
+
const top = element.scrollHeight;
|
|
2208
|
+
if (typeof element.scrollTo !== "function") {
|
|
2209
|
+
element.scrollTop = top;
|
|
2210
|
+
return;
|
|
2211
|
+
}
|
|
2212
|
+
isAutoScrolling = !shouldReduceMotion;
|
|
2213
|
+
element.scrollTo({ behavior: shouldReduceMotion ? "auto" : "smooth", top });
|
|
2214
|
+
window.clearTimeout(autoScrollTimer);
|
|
2215
|
+
autoScrollTimer = window.setTimeout(() => {
|
|
2216
|
+
isAutoScrolling = false;
|
|
2217
|
+
updateFollowing();
|
|
2218
|
+
}, 360);
|
|
2219
|
+
};
|
|
2130
2220
|
element.addEventListener("scroll", handleScroll, { passive: true });
|
|
2131
|
-
|
|
2132
|
-
|
|
2221
|
+
element.addEventListener("pointerdown", handleUserScrollIntent, { passive: true });
|
|
2222
|
+
element.addEventListener("touchstart", handleUserScrollIntent, { passive: true });
|
|
2223
|
+
element.addEventListener("wheel", handleUserScrollIntent, { passive: true });
|
|
2224
|
+
followNewest();
|
|
2225
|
+
const list = element.querySelector("ol");
|
|
2226
|
+
const resizeObserver = list && typeof ResizeObserver !== "undefined" ? new ResizeObserver(followNewest) : null;
|
|
2227
|
+
if (list) resizeObserver?.observe(list);
|
|
2228
|
+
return () => {
|
|
2229
|
+
element.removeEventListener("scroll", handleScroll);
|
|
2230
|
+
element.removeEventListener("pointerdown", handleUserScrollIntent);
|
|
2231
|
+
element.removeEventListener("touchstart", handleUserScrollIntent);
|
|
2232
|
+
element.removeEventListener("wheel", handleUserScrollIntent);
|
|
2233
|
+
resizeObserver?.disconnect();
|
|
2234
|
+
window.clearTimeout(autoScrollTimer);
|
|
2235
|
+
};
|
|
2236
|
+
}, [contentVersion, isExpanded, isStreaming, ref]);
|
|
2237
|
+
}
|
|
2238
|
+
function useActivityPhase(isStreaming) {
|
|
2239
|
+
const [phaseState, setPhaseState] = useState5(() => ({
|
|
2240
|
+
isStreaming,
|
|
2241
|
+
phase: isStreaming ? "expanded" : "collapsed"
|
|
2242
|
+
}));
|
|
2243
|
+
let phase = phaseState.phase;
|
|
2244
|
+
if (phaseState.isStreaming !== isStreaming) {
|
|
2245
|
+
phase = isStreaming ? "expanded" : "fading";
|
|
2246
|
+
setPhaseState({ isStreaming, phase });
|
|
2247
|
+
}
|
|
2133
2248
|
useEffect7(() => {
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2249
|
+
if (isStreaming || phase === "collapsed" || phase === "expanded") return;
|
|
2250
|
+
const shouldReduceMotion = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
2251
|
+
const nextPhase = shouldReduceMotion ? "collapsed" : phase === "fading" ? "collapsing" : "collapsed";
|
|
2252
|
+
const delay = shouldReduceMotion ? 0 : phase === "fading" ? ACTIVITY_FADE_MS : ACTIVITY_COLLAPSE_MS;
|
|
2253
|
+
const timer = window.setTimeout(() => {
|
|
2254
|
+
setPhaseState(
|
|
2255
|
+
(current) => current.isStreaming === isStreaming && current.phase === phase ? { ...current, phase: nextPhase } : current
|
|
2256
|
+
);
|
|
2257
|
+
}, delay);
|
|
2258
|
+
return () => window.clearTimeout(timer);
|
|
2259
|
+
}, [isStreaming, phase]);
|
|
2260
|
+
return phase;
|
|
2138
2261
|
}
|
|
2139
2262
|
var activityIcons = {
|
|
2140
2263
|
browse: Globe,
|
|
@@ -2144,6 +2267,12 @@ var activityIcons = {
|
|
|
2144
2267
|
search: Magnifier,
|
|
2145
2268
|
thinking: Wrench
|
|
2146
2269
|
};
|
|
2270
|
+
function ActivityStateIcon({ active }) {
|
|
2271
|
+
return /* @__PURE__ */ jsxs6("span", { className: "ha-activity-icon", "data-state": active ? "active" : "complete", children: [
|
|
2272
|
+
/* @__PURE__ */ jsx8("span", { "aria-hidden": "true", className: "ha-activity-icon-state ha-activity-icon-state--active", children: /* @__PURE__ */ jsx8("span", { className: "ha-activity-spinner" }) }),
|
|
2273
|
+
/* @__PURE__ */ jsx8("span", { "aria-hidden": "true", className: "ha-activity-icon-state ha-activity-icon-state--complete", children: /* @__PURE__ */ jsx8(CircleCheck, {}) })
|
|
2274
|
+
] });
|
|
2275
|
+
}
|
|
2147
2276
|
function formatActivityDuration(durationMs) {
|
|
2148
2277
|
const totalSeconds = Math.max(1, Math.round(durationMs / 1e3));
|
|
2149
2278
|
const hours = Math.floor(totalSeconds / 3600);
|
|
@@ -2159,63 +2288,101 @@ function ActivityStatus({ ariaLabel, label }) {
|
|
|
2159
2288
|
function ActivityTrail({
|
|
2160
2289
|
completedAt,
|
|
2161
2290
|
defaultOpen = false,
|
|
2291
|
+
hasResponseStarted = false,
|
|
2162
2292
|
isStreaming,
|
|
2163
2293
|
items,
|
|
2164
2294
|
progress,
|
|
2165
2295
|
startedAt
|
|
2166
2296
|
}) {
|
|
2167
|
-
const
|
|
2168
|
-
const
|
|
2169
|
-
const
|
|
2170
|
-
const
|
|
2171
|
-
const
|
|
2172
|
-
const
|
|
2173
|
-
const
|
|
2297
|
+
const isActivityStreaming = isStreaming && !hasResponseStarted;
|
|
2298
|
+
const phase = useActivityPhase(isActivityStreaming);
|
|
2299
|
+
const [expandedOverride, setExpandedOverride] = useState5(null);
|
|
2300
|
+
const panelRef = useRef5(null);
|
|
2301
|
+
const activityStoppedAtRef = useRef5(null);
|
|
2302
|
+
const requestedActiveIndex = items.findLastIndex((item) => item.active);
|
|
2303
|
+
const fallbackActiveIndex = items.at(-1)?.stateKnown ? -1 : items.length - 1;
|
|
2304
|
+
const activeIndex = isActivityStreaming ? requestedActiveIndex >= 0 ? requestedActiveIndex : fallbackActiveIndex : -1;
|
|
2305
|
+
const visibleItems = items.map((item, index) => ({
|
|
2306
|
+
...item,
|
|
2307
|
+
active: index === activeIndex
|
|
2308
|
+
}));
|
|
2309
|
+
const activeItem = activeIndex >= 0 ? visibleItems[activeIndex] : void 0;
|
|
2310
|
+
const latestItem = visibleItems.at(-1);
|
|
2311
|
+
const liveSummary = progress ?? activeItem?.label ?? latestItem?.label ?? "Understanding your request\u2026";
|
|
2312
|
+
const isAutoSettling = expandedOverride === null && !defaultOpen && !isActivityStreaming && (phase === "fading" || phase === "collapsing");
|
|
2313
|
+
const autoExpanded = defaultOpen || phase === "expanded" || phase === "fading";
|
|
2314
|
+
const isExpanded = expandedOverride ?? autoExpanded;
|
|
2315
|
+
const visualPhase = expandedOverride !== null || defaultOpen ? isExpanded ? "expanded" : "collapsed" : phase;
|
|
2316
|
+
useEffect7(() => {
|
|
2317
|
+
if (!isStreaming) return;
|
|
2318
|
+
if (!hasResponseStarted) {
|
|
2319
|
+
activityStoppedAtRef.current = null;
|
|
2320
|
+
return;
|
|
2321
|
+
}
|
|
2322
|
+
activityStoppedAtRef.current ??= Date.now();
|
|
2323
|
+
}, [hasResponseStarted, isStreaming]);
|
|
2324
|
+
const elapsedMs = startedAt !== void 0 && !isActivityStreaming ? Math.max(0, (activityStoppedAtRef.current ?? completedAt ?? Date.now()) - startedAt) : null;
|
|
2325
|
+
const completedSummary = elapsedMs === null ? "Activity" : `Worked for ${formatActivityDuration(elapsedMs)}`;
|
|
2326
|
+
const summary = isActivityStreaming || isAutoSettling ? liveSummary : elapsedMs === null ? "Activity" : completedSummary;
|
|
2327
|
+
const summaryItem = activeItem ?? latestItem;
|
|
2328
|
+
const summaryKind = summaryItem?.kind ?? inferActivityKind(summaryItem?.label ?? liveSummary);
|
|
2329
|
+
const SummaryIcon = activityIcons[summaryKind];
|
|
2330
|
+
const contentVersion = visibleItems.map(
|
|
2331
|
+
(item) => `${item.id}:${item.active ? 1 : 0}:${item.detail ?? ""}:${item.sources?.map((source) => source.label).join(",")}`
|
|
2332
|
+
).join("|");
|
|
2174
2333
|
useScrollShadow(panelRef);
|
|
2175
|
-
useFollowNewestStep(panelRef,
|
|
2176
|
-
return /* @__PURE__ */
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
{
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2334
|
+
useFollowNewestStep(panelRef, contentVersion, isActivityStreaming, isExpanded);
|
|
2335
|
+
return /* @__PURE__ */ jsxs6(
|
|
2336
|
+
Disclosure2,
|
|
2337
|
+
{
|
|
2338
|
+
className: "ha-activity",
|
|
2339
|
+
"data-phase": visualPhase,
|
|
2340
|
+
isExpanded,
|
|
2341
|
+
onExpandedChange: setExpandedOverride,
|
|
2342
|
+
children: [
|
|
2343
|
+
/* @__PURE__ */ jsx8(Disclosure2.Heading, { children: /* @__PURE__ */ jsxs6(Disclosure2.Trigger, { className: "ha-activity-trigger", children: [
|
|
2344
|
+
/* @__PURE__ */ jsx8("span", { "aria-hidden": "true", className: "ha-activity-summary-icon", children: /* @__PURE__ */ jsx8("span", { children: /* @__PURE__ */ jsx8(SummaryIcon, {}) }, summaryKind) }),
|
|
2345
|
+
isActivityStreaming || isAutoSettling ? /* @__PURE__ */ jsx8(
|
|
2346
|
+
AnimatedStatusText,
|
|
2347
|
+
{
|
|
2348
|
+
animateOnMount: liveSummary !== progress,
|
|
2349
|
+
className: "ha-activity-summary-label ha-progress ha-progress-shimmer",
|
|
2350
|
+
role: "status",
|
|
2351
|
+
children: summary
|
|
2352
|
+
}
|
|
2353
|
+
) : /* @__PURE__ */ jsx8("span", { className: "ha-activity-summary-label ha-activity-summary-label--complete ha-progress", children: summary }),
|
|
2354
|
+
/* @__PURE__ */ jsx8(Disclosure2.Indicator, { className: "ha-activity-chevron" })
|
|
2355
|
+
] }) }),
|
|
2356
|
+
/* @__PURE__ */ jsx8(Disclosure2.Content, { className: "ha-activity-disclosure-content", children: /* @__PURE__ */ jsx8(Disclosure2.Body, { children: /* @__PURE__ */ jsx8("div", { ref: panelRef, className: "ha-activity-panel", children: /* @__PURE__ */ jsxs6("ol", { "aria-label": "Thinking steps", children: [
|
|
2357
|
+
visibleItems.map((item) => /* @__PURE__ */ jsxs6(
|
|
2358
|
+
"li",
|
|
2359
|
+
{
|
|
2360
|
+
"aria-current": item.active ? "step" : void 0,
|
|
2361
|
+
className: "ha-activity-item",
|
|
2362
|
+
"data-active": item.active || void 0,
|
|
2363
|
+
"data-state": item.active ? "active" : "complete",
|
|
2364
|
+
children: [
|
|
2365
|
+
/* @__PURE__ */ jsx8(ActivityStateIcon, { active: item.active }),
|
|
2366
|
+
/* @__PURE__ */ jsxs6("span", { className: "ha-activity-content", children: [
|
|
2367
|
+
item.active ? /* @__PURE__ */ jsx8(AnimatedStatusText, { className: "ha-progress-shimmer", children: item.label }) : /* @__PURE__ */ jsx8("span", { children: item.label }),
|
|
2368
|
+
item.detail ? /* @__PURE__ */ jsx8("small", { className: "ha-activity-detail", "data-visible": item.active || void 0, children: /* @__PURE__ */ jsx8("span", { children: item.detail }) }) : null,
|
|
2369
|
+
item.sources?.length ? /* @__PURE__ */ jsx8("span", { "aria-label": "Sources", className: "ha-activity-sources", children: item.sources.map((source) => /* @__PURE__ */ jsxs6("span", { className: "ha-activity-source", children: [
|
|
2370
|
+
/* @__PURE__ */ jsx8(Globe, { "aria-hidden": "true" }),
|
|
2371
|
+
source.label
|
|
2372
|
+
] }, source.label)) }) : null
|
|
2373
|
+
] })
|
|
2374
|
+
]
|
|
2375
|
+
},
|
|
2376
|
+
item.id
|
|
2377
|
+
)),
|
|
2378
|
+
!isActivityStreaming ? /* @__PURE__ */ jsxs6("li", { className: "ha-activity-item", "data-complete": "true", "data-state": "complete", children: [
|
|
2379
|
+
/* @__PURE__ */ jsx8(ActivityStateIcon, { active: false }),
|
|
2380
|
+
/* @__PURE__ */ jsx8("span", { className: "ha-activity-content", children: /* @__PURE__ */ jsx8("span", { children: "Final response ready" }) })
|
|
2381
|
+
] }) : null
|
|
2382
|
+
] }) }) }) })
|
|
2383
|
+
]
|
|
2384
|
+
}
|
|
2385
|
+
);
|
|
2219
2386
|
}
|
|
2220
2387
|
|
|
2221
2388
|
// src/embed/agent-api.ts
|
|
@@ -2565,12 +2732,12 @@ function getComposerAttachmentMetadata(file) {
|
|
|
2565
2732
|
}
|
|
2566
2733
|
|
|
2567
2734
|
// src/embed/composer-attachment.tsx
|
|
2568
|
-
import { jsx as jsx9, jsxs as
|
|
2735
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2569
2736
|
function ComposerAttachment({ file, onRemove }) {
|
|
2570
2737
|
const { Icon, kind, label } = getComposerAttachmentMetadata(file);
|
|
2571
|
-
return /* @__PURE__ */
|
|
2738
|
+
return /* @__PURE__ */ jsxs7("span", { className: "ha-attachment", "data-kind": kind, children: [
|
|
2572
2739
|
/* @__PURE__ */ jsx9("span", { "aria-hidden": "true", className: "ha-attachment-icon", children: /* @__PURE__ */ jsx9(Icon, {}) }),
|
|
2573
|
-
/* @__PURE__ */
|
|
2740
|
+
/* @__PURE__ */ jsxs7("span", { className: "ha-attachment-copy", children: [
|
|
2574
2741
|
/* @__PURE__ */ jsx9("span", { className: "ha-attachment-name", title: file.name, children: file.name }),
|
|
2575
2742
|
/* @__PURE__ */ jsx9("span", { className: "ha-attachment-type", children: label })
|
|
2576
2743
|
] }),
|
|
@@ -2580,9 +2747,9 @@ function ComposerAttachment({ file, onRemove }) {
|
|
|
2580
2747
|
|
|
2581
2748
|
// src/embed/composer-context.tsx
|
|
2582
2749
|
import { Globe as Globe2, Xmark as Xmark2 } from "@gravity-ui/icons";
|
|
2583
|
-
import { jsx as jsx10, jsxs as
|
|
2750
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2584
2751
|
function ComposerContext({ onRemove, title }) {
|
|
2585
|
-
return /* @__PURE__ */ jsx10("div", { className: "ha-context", children: /* @__PURE__ */
|
|
2752
|
+
return /* @__PURE__ */ jsx10("div", { className: "ha-context", children: /* @__PURE__ */ jsxs8(
|
|
2586
2753
|
"button",
|
|
2587
2754
|
{
|
|
2588
2755
|
"aria-label": `Remove Ask about this: ${title}`,
|
|
@@ -2591,7 +2758,7 @@ function ComposerContext({ onRemove, title }) {
|
|
|
2591
2758
|
onClick: onRemove,
|
|
2592
2759
|
children: [
|
|
2593
2760
|
/* @__PURE__ */ jsx10(Globe2, { "aria-hidden": "true", className: "ha-chip-leading" }),
|
|
2594
|
-
/* @__PURE__ */
|
|
2761
|
+
/* @__PURE__ */ jsxs8("span", { className: "ha-chip-title", title, children: [
|
|
2595
2762
|
"Ask about this: ",
|
|
2596
2763
|
title
|
|
2597
2764
|
] }),
|
|
@@ -2602,7 +2769,7 @@ function ComposerContext({ onRemove, title }) {
|
|
|
2602
2769
|
}
|
|
2603
2770
|
|
|
2604
2771
|
// src/embed/composer-file-dropzone.tsx
|
|
2605
|
-
import { useCallback as useCallback4, useState as
|
|
2772
|
+
import { useCallback as useCallback4, useState as useState6 } from "react";
|
|
2606
2773
|
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
2607
2774
|
function hasFileTransfer(event) {
|
|
2608
2775
|
return event.dataTransfer?.types?.includes("Files") ?? false;
|
|
@@ -2615,7 +2782,7 @@ function ComposerFileDropzone({
|
|
|
2615
2782
|
disabled = false,
|
|
2616
2783
|
onFilesSelected
|
|
2617
2784
|
}) {
|
|
2618
|
-
const [isDragging, setIsDragging] =
|
|
2785
|
+
const [isDragging, setIsDragging] = useState6(false);
|
|
2619
2786
|
const handleDragEnter = useCallback4(
|
|
2620
2787
|
(event) => {
|
|
2621
2788
|
if (disabled || !hasFileTransfer(event)) return;
|
|
@@ -2732,7 +2899,7 @@ function removeConversationActivity(current, conversationId) {
|
|
|
2732
2899
|
// src/embed/conversation-markdown.tsx
|
|
2733
2900
|
import { Code as Code2, Heading, Link, Paragraph, Separator, Table } from "@heroui/react";
|
|
2734
2901
|
import { Children, Suspense, isValidElement, lazy, memo, useMemo } from "react";
|
|
2735
|
-
import { jsx as jsx12, jsxs as
|
|
2902
|
+
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2736
2903
|
var LazyStreamdown = lazy(
|
|
2737
2904
|
() => import("streamdown").then((module) => ({ default: module.Streamdown }))
|
|
2738
2905
|
);
|
|
@@ -2760,7 +2927,7 @@ function MarkdownTable({ children }) {
|
|
|
2760
2927
|
const headerRow = findElementByTag(tableHead?.props.children, "tr");
|
|
2761
2928
|
const headerCells = getElementChildren(headerRow);
|
|
2762
2929
|
const rows = getElementChildren(tableBody);
|
|
2763
|
-
return /* @__PURE__ */ jsx12(Table, { "data-slot": "markdown-table", variant: "secondary", children: /* @__PURE__ */ jsx12(Table.ScrollContainer, { children: /* @__PURE__ */
|
|
2930
|
+
return /* @__PURE__ */ jsx12(Table, { "data-slot": "markdown-table", variant: "secondary", children: /* @__PURE__ */ jsx12(Table.ScrollContainer, { children: /* @__PURE__ */ jsxs9(Table.Content, { "aria-label": "Markdown table", children: [
|
|
2764
2931
|
/* @__PURE__ */ jsx12(Table.Header, { children: headerCells.map((cell, index) => /* @__PURE__ */ jsx12(Table.Column, { id: `column-${index}`, children: cell.props.children }, String(cell.key))) }),
|
|
2765
2932
|
/* @__PURE__ */ jsx12(Table.Body, { children: rows.map((row, rowIndex) => /* @__PURE__ */ jsx12(Table.Row, { id: `row-${rowIndex}`, children: getElementChildren(row).map((cell) => /* @__PURE__ */ jsx12(Table.Cell, { children: cell.props.children }, String(cell.key))) }, String(row.key))) })
|
|
2766
2933
|
] }) }) });
|
|
@@ -2904,7 +3071,6 @@ function ConversationRouteStack({
|
|
|
2904
3071
|
|
|
2905
3072
|
// src/embed/conversation-turn-anchor.ts
|
|
2906
3073
|
function resolveConversationTurnAnchor({
|
|
2907
|
-
conversationId,
|
|
2908
3074
|
isActive,
|
|
2909
3075
|
lastUserMessageId,
|
|
2910
3076
|
pendingTurn
|
|
@@ -2912,22 +3078,21 @@ function resolveConversationTurnAnchor({
|
|
|
2912
3078
|
const normalizedLastUserMessageId = lastUserMessageId ?? null;
|
|
2913
3079
|
const hasActiveOptimisticUser = pendingTurn ? normalizedLastUserMessageId !== pendingTurn.previousUserMessageId : normalizedLastUserMessageId !== null;
|
|
2914
3080
|
const activeTurnMessageId = isActive ? hasActiveOptimisticUser ? normalizedLastUserMessageId : null : normalizedLastUserMessageId;
|
|
2915
|
-
const activeStreamKey = isActive ? pendingTurn?.
|
|
3081
|
+
const activeStreamKey = isActive ? pendingTurn?.scrollKey ?? null : null;
|
|
2916
3082
|
return { activeStreamKey, activeTurnMessageId };
|
|
2917
3083
|
}
|
|
2918
3084
|
|
|
2919
3085
|
// src/embed/conversation-viewport.tsx
|
|
2920
3086
|
import { ChevronDown } from "@gravity-ui/icons";
|
|
2921
3087
|
import { Button } from "@heroui/react";
|
|
2922
|
-
import { useLayoutEffect as useLayoutEffect2, useRef as
|
|
3088
|
+
import { useLayoutEffect as useLayoutEffect2, useRef as useRef7 } from "react";
|
|
2923
3089
|
|
|
2924
3090
|
// src/embed/use-conversation-scroll.ts
|
|
2925
|
-
import { useCallback as useCallback5, useEffect as useEffect9, useLayoutEffect, useRef as
|
|
3091
|
+
import { useCallback as useCallback5, useEffect as useEffect9, useLayoutEffect, useRef as useRef6, useState as useState7 } from "react";
|
|
2926
3092
|
var BOTTOM_THRESHOLD = 4;
|
|
2927
3093
|
var SCROLL_DIRECTION_THRESHOLD = 1;
|
|
2928
3094
|
var ACTIVE_TURN_SPACER_PROPERTY = "--ha-active-turn-spacer-height";
|
|
2929
|
-
var
|
|
2930
|
-
var TURN_ANCHOR_SELECTOR = '[data-turn-anchor="true"]';
|
|
3095
|
+
var USER_STREAM_ANCHOR_SELECTOR = '[data-role="user"][data-stream-anchor="true"]';
|
|
2931
3096
|
var DEFAULT_SCROLL_STATE = {
|
|
2932
3097
|
hasOverflow: false,
|
|
2933
3098
|
isAtBottom: true
|
|
@@ -2956,23 +3121,25 @@ function getNativeScrollBehavior(behavior) {
|
|
|
2956
3121
|
return "auto";
|
|
2957
3122
|
}
|
|
2958
3123
|
function useConversationScroll(ref) {
|
|
2959
|
-
const activeTurnSpacerHeightRef =
|
|
2960
|
-
const attachedRef =
|
|
2961
|
-
const
|
|
2962
|
-
const
|
|
2963
|
-
const
|
|
2964
|
-
const
|
|
2965
|
-
const
|
|
2966
|
-
const
|
|
2967
|
-
const
|
|
2968
|
-
const
|
|
3124
|
+
const activeTurnSpacerHeightRef = useRef6(0);
|
|
3125
|
+
const attachedRef = useRef6(true);
|
|
3126
|
+
const automaticFollowSuppressedRef = useRef6(false);
|
|
3127
|
+
const currentStreamKeyRef = useRef6(null);
|
|
3128
|
+
const isAutoScrollingRef = useRef6(false);
|
|
3129
|
+
const isPinnedTurnAnimatingRef = useRef6(false);
|
|
3130
|
+
const lastPinnedStreamKeyRef = useRef6(null);
|
|
3131
|
+
const lastScrollTopRef = useRef6(0);
|
|
3132
|
+
const pinnedStreamKeyRef = useRef6(null);
|
|
3133
|
+
const pinnedStreamTopRef = useRef6(null);
|
|
3134
|
+
const shouldAnimatePinnedTurnRef = useRef6(false);
|
|
3135
|
+
const [scrollState, setScrollState] = useState7(DEFAULT_SCROLL_STATE);
|
|
2969
3136
|
const setNextScrollState = useCallback5((nextState) => {
|
|
2970
3137
|
setScrollState(
|
|
2971
3138
|
(currentState) => isSameScrollState(currentState, nextState) ? currentState : nextState
|
|
2972
3139
|
);
|
|
2973
3140
|
}, []);
|
|
2974
3141
|
const updateActiveTurnSpacer = useCallback5((element) => {
|
|
2975
|
-
const anchor =
|
|
3142
|
+
const anchor = pinnedStreamKeyRef.current ? element.querySelector(USER_STREAM_ANCHOR_SELECTOR) : null;
|
|
2976
3143
|
let nextHeight = 0;
|
|
2977
3144
|
if (anchor) {
|
|
2978
3145
|
const containerRect = element.getBoundingClientRect();
|
|
@@ -3001,14 +3168,17 @@ function useConversationScroll(ref) {
|
|
|
3001
3168
|
pinnedStreamTopRef.current = null;
|
|
3002
3169
|
isPinnedTurnAnimatingRef.current = false;
|
|
3003
3170
|
shouldAnimatePinnedTurnRef.current = false;
|
|
3171
|
+
updateActiveTurnSpacer(element);
|
|
3004
3172
|
attachedRef.current = true;
|
|
3005
|
-
|
|
3173
|
+
automaticFollowSuppressedRef.current = false;
|
|
3006
3174
|
lastScrollTopRef.current = element.scrollTop;
|
|
3007
3175
|
setNextScrollState({
|
|
3008
3176
|
hasOverflow: getConversationScrollState(element).hasOverflow,
|
|
3009
3177
|
isAtBottom: true
|
|
3010
3178
|
});
|
|
3011
3179
|
const top = element.scrollHeight;
|
|
3180
|
+
const targetTop = Math.max(0, top - element.clientHeight);
|
|
3181
|
+
isAutoScrollingRef.current = Math.abs(Math.max(0, element.scrollTop) - targetTop) > SCROLL_DIRECTION_THRESHOLD;
|
|
3012
3182
|
if (typeof element.scrollTo === "function") {
|
|
3013
3183
|
element.scrollTo({ behavior: getNativeScrollBehavior(behavior), top });
|
|
3014
3184
|
} else {
|
|
@@ -3016,11 +3186,11 @@ function useConversationScroll(ref) {
|
|
|
3016
3186
|
}
|
|
3017
3187
|
lastScrollTopRef.current = Math.max(0, element.scrollTop);
|
|
3018
3188
|
},
|
|
3019
|
-
[ref, setNextScrollState]
|
|
3189
|
+
[ref, setNextScrollState, updateActiveTurnSpacer]
|
|
3020
3190
|
);
|
|
3021
3191
|
const getPinnedStreamTop = useCallback5((element) => {
|
|
3022
3192
|
if (!pinnedStreamKeyRef.current) return null;
|
|
3023
|
-
const anchor = element.querySelector(
|
|
3193
|
+
const anchor = element.querySelector(USER_STREAM_ANCHOR_SELECTOR);
|
|
3024
3194
|
if (anchor) {
|
|
3025
3195
|
const paddingTop = Number.parseFloat(window.getComputedStyle(element).paddingTop) || 0;
|
|
3026
3196
|
pinnedStreamTopRef.current = Math.max(0, anchor.offsetTop - paddingTop);
|
|
@@ -3032,8 +3202,9 @@ function useConversationScroll(ref) {
|
|
|
3032
3202
|
const maximumScrollTop = Math.max(0, element.scrollHeight - element.clientHeight);
|
|
3033
3203
|
const targetTop = Math.min(top, maximumScrollTop);
|
|
3034
3204
|
const nativeBehavior = getNativeScrollBehavior(behavior);
|
|
3035
|
-
|
|
3036
|
-
|
|
3205
|
+
const hasMovement = Math.abs(Math.max(0, element.scrollTop) - targetTop) > SCROLL_DIRECTION_THRESHOLD;
|
|
3206
|
+
isPinnedTurnAnimatingRef.current = nativeBehavior === "smooth" && hasMovement;
|
|
3207
|
+
isAutoScrollingRef.current = hasMovement;
|
|
3037
3208
|
lastScrollTopRef.current = element.scrollTop;
|
|
3038
3209
|
setNextScrollState({
|
|
3039
3210
|
hasOverflow: maximumScrollTop > BOTTOM_THRESHOLD,
|
|
@@ -3052,26 +3223,30 @@ function useConversationScroll(ref) {
|
|
|
3052
3223
|
const maintainScrollPosition = useCallback5(() => {
|
|
3053
3224
|
const element = ref.current;
|
|
3054
3225
|
if (!element) return;
|
|
3055
|
-
|
|
3226
|
+
updateActiveTurnSpacer(element);
|
|
3056
3227
|
const measuredState = getConversationScrollState(element);
|
|
3057
3228
|
const scrollTop = Math.max(0, element.scrollTop);
|
|
3058
3229
|
const scrolledUp = scrollTop < lastScrollTopRef.current - SCROLL_DIRECTION_THRESHOLD;
|
|
3059
3230
|
lastScrollTopRef.current = scrollTop;
|
|
3060
3231
|
if (scrolledUp && !measuredState.isAtBottom) {
|
|
3061
3232
|
attachedRef.current = false;
|
|
3233
|
+
automaticFollowSuppressedRef.current = true;
|
|
3062
3234
|
isAutoScrollingRef.current = false;
|
|
3063
3235
|
isPinnedTurnAnimatingRef.current = false;
|
|
3064
3236
|
pinnedStreamKeyRef.current = null;
|
|
3065
3237
|
pinnedStreamTopRef.current = null;
|
|
3066
3238
|
shouldAnimatePinnedTurnRef.current = false;
|
|
3239
|
+
updateActiveTurnSpacer(element);
|
|
3067
3240
|
setNextScrollState(measuredState);
|
|
3068
3241
|
return;
|
|
3069
3242
|
}
|
|
3070
|
-
if (!measuredState.hasOverflow || measuredState.isAtBottom) {
|
|
3243
|
+
if (!automaticFollowSuppressedRef.current && (!measuredState.hasOverflow || measuredState.isAtBottom)) {
|
|
3071
3244
|
attachedRef.current = true;
|
|
3072
3245
|
}
|
|
3073
|
-
|
|
3074
|
-
|
|
3246
|
+
const hasPinnedStream = pinnedStreamKeyRef.current !== null;
|
|
3247
|
+
const pinnedStreamTop = getPinnedStreamTop(element);
|
|
3248
|
+
if (hasPinnedStream) {
|
|
3249
|
+
automaticFollowSuppressedRef.current = true;
|
|
3075
3250
|
if (pinnedStreamTop !== null && isPinnedTurnAnimatingRef.current) {
|
|
3076
3251
|
const maximumScrollTop = Math.max(0, element.scrollHeight - element.clientHeight);
|
|
3077
3252
|
const targetTop = Math.min(pinnedStreamTop, maximumScrollTop);
|
|
@@ -3082,16 +3257,20 @@ function useConversationScroll(ref) {
|
|
|
3082
3257
|
isAutoScrollingRef.current = false;
|
|
3083
3258
|
isPinnedTurnAnimatingRef.current = false;
|
|
3084
3259
|
}
|
|
3085
|
-
if (pinnedStreamTop !== null &&
|
|
3086
|
-
const behavior = shouldAnimatePinnedTurnRef.current ? "smooth" : "auto";
|
|
3260
|
+
if (pinnedStreamTop !== null && shouldAnimatePinnedTurnRef.current) {
|
|
3087
3261
|
shouldAnimatePinnedTurnRef.current = false;
|
|
3088
|
-
scrollToPinnedPosition(element, pinnedStreamTop,
|
|
3262
|
+
scrollToPinnedPosition(element, pinnedStreamTop, "smooth");
|
|
3089
3263
|
return;
|
|
3090
3264
|
}
|
|
3265
|
+
attachedRef.current = false;
|
|
3266
|
+
setNextScrollState(measuredState);
|
|
3267
|
+
return;
|
|
3268
|
+
}
|
|
3269
|
+
if (attachedRef.current && !automaticFollowSuppressedRef.current) {
|
|
3091
3270
|
scrollToBottom("auto");
|
|
3092
3271
|
return;
|
|
3093
3272
|
}
|
|
3094
|
-
setNextScrollState(
|
|
3273
|
+
setNextScrollState(measuredState);
|
|
3095
3274
|
}, [
|
|
3096
3275
|
getPinnedStreamTop,
|
|
3097
3276
|
ref,
|
|
@@ -3106,29 +3285,43 @@ function useConversationScroll(ref) {
|
|
|
3106
3285
|
if (!element || currentStreamKeyRef.current === streamKey) return;
|
|
3107
3286
|
const hadActiveStream = currentStreamKeyRef.current !== null;
|
|
3108
3287
|
currentStreamKeyRef.current = streamKey;
|
|
3109
|
-
pinnedStreamKeyRef.current = streamKey;
|
|
3110
|
-
pinnedStreamTopRef.current = null;
|
|
3111
3288
|
if (streamKey) {
|
|
3112
|
-
|
|
3289
|
+
const startsNewUserTurn = lastPinnedStreamKeyRef.current !== streamKey;
|
|
3290
|
+
if (startsNewUserTurn) {
|
|
3291
|
+
lastPinnedStreamKeyRef.current = streamKey;
|
|
3292
|
+
pinnedStreamKeyRef.current = streamKey;
|
|
3293
|
+
pinnedStreamTopRef.current = null;
|
|
3113
3294
|
shouldAnimatePinnedTurnRef.current = true;
|
|
3295
|
+
automaticFollowSuppressedRef.current = true;
|
|
3296
|
+
attachedRef.current = true;
|
|
3297
|
+
} else {
|
|
3298
|
+
pinnedStreamKeyRef.current = null;
|
|
3299
|
+
pinnedStreamTopRef.current = null;
|
|
3300
|
+
shouldAnimatePinnedTurnRef.current = false;
|
|
3301
|
+
updateActiveTurnSpacer(element);
|
|
3114
3302
|
}
|
|
3115
|
-
attachedRef.current = true;
|
|
3116
3303
|
} else if (hadActiveStream) {
|
|
3304
|
+
pinnedStreamKeyRef.current = null;
|
|
3305
|
+
pinnedStreamTopRef.current = null;
|
|
3117
3306
|
isAutoScrollingRef.current = false;
|
|
3118
3307
|
isPinnedTurnAnimatingRef.current = false;
|
|
3119
3308
|
shouldAnimatePinnedTurnRef.current = false;
|
|
3309
|
+
automaticFollowSuppressedRef.current = true;
|
|
3310
|
+
updateActiveTurnSpacer(element);
|
|
3120
3311
|
const measuredState = getConversationScrollState(element);
|
|
3121
|
-
attachedRef.current =
|
|
3312
|
+
attachedRef.current = false;
|
|
3122
3313
|
setNextScrollState(measuredState);
|
|
3123
3314
|
}
|
|
3124
3315
|
},
|
|
3125
|
-
[ref, setNextScrollState]
|
|
3316
|
+
[ref, setNextScrollState, updateActiveTurnSpacer]
|
|
3126
3317
|
);
|
|
3127
3318
|
useLayoutEffect(() => {
|
|
3128
3319
|
const element = ref.current;
|
|
3129
3320
|
if (!element) return;
|
|
3130
3321
|
lastScrollTopRef.current = element.scrollTop;
|
|
3131
3322
|
maintainScrollPosition();
|
|
3323
|
+
automaticFollowSuppressedRef.current = true;
|
|
3324
|
+
attachedRef.current = false;
|
|
3132
3325
|
}, [maintainScrollPosition, ref]);
|
|
3133
3326
|
useEffect9(() => {
|
|
3134
3327
|
const element = ref.current;
|
|
@@ -3147,9 +3340,13 @@ function useConversationScroll(ref) {
|
|
|
3147
3340
|
if (reachedAutomaticTarget) {
|
|
3148
3341
|
isAutoScrollingRef.current = false;
|
|
3149
3342
|
isPinnedTurnAnimatingRef.current = false;
|
|
3343
|
+
if (pinnedStreamTop !== null) {
|
|
3344
|
+
automaticFollowSuppressedRef.current = true;
|
|
3345
|
+
attachedRef.current = false;
|
|
3346
|
+
}
|
|
3150
3347
|
}
|
|
3151
3348
|
setNextScrollState(
|
|
3152
|
-
wasPinnedTurnAnimating && !reachedAutomaticTarget ? { hasOverflow: measuredState.hasOverflow, isAtBottom: true } : pinnedStreamTop === null ? { hasOverflow: measuredState.hasOverflow, isAtBottom: attachedRef.current } : measuredState
|
|
3349
|
+
wasPinnedTurnAnimating && !reachedAutomaticTarget ? { hasOverflow: measuredState.hasOverflow, isAtBottom: true } : pinnedStreamTop === null ? automaticFollowSuppressedRef.current ? measuredState : { hasOverflow: measuredState.hasOverflow, isAtBottom: attachedRef.current } : measuredState
|
|
3153
3350
|
);
|
|
3154
3351
|
return;
|
|
3155
3352
|
}
|
|
@@ -3158,7 +3355,9 @@ function useConversationScroll(ref) {
|
|
|
3158
3355
|
pinnedStreamKeyRef.current = null;
|
|
3159
3356
|
pinnedStreamTopRef.current = null;
|
|
3160
3357
|
shouldAnimatePinnedTurnRef.current = false;
|
|
3358
|
+
updateActiveTurnSpacer(element);
|
|
3161
3359
|
attachedRef.current = measuredState.isAtBottom;
|
|
3360
|
+
automaticFollowSuppressedRef.current = !measuredState.isAtBottom;
|
|
3162
3361
|
setNextScrollState(measuredState);
|
|
3163
3362
|
};
|
|
3164
3363
|
element.addEventListener("scroll", handleScroll, { passive: true });
|
|
@@ -3201,7 +3400,7 @@ function useConversationScroll(ref) {
|
|
|
3201
3400
|
resizeObserver.disconnect();
|
|
3202
3401
|
}
|
|
3203
3402
|
};
|
|
3204
|
-
}, [getPinnedStreamTop, maintainScrollPosition, ref, setNextScrollState]);
|
|
3403
|
+
}, [getPinnedStreamTop, maintainScrollPosition, ref, setNextScrollState, updateActiveTurnSpacer]);
|
|
3205
3404
|
return {
|
|
3206
3405
|
hasOverflow: scrollState.hasOverflow,
|
|
3207
3406
|
isAtBottom: scrollState.isAtBottom,
|
|
@@ -3212,12 +3411,12 @@ function useConversationScroll(ref) {
|
|
|
3212
3411
|
}
|
|
3213
3412
|
|
|
3214
3413
|
// src/embed/conversation-viewport.tsx
|
|
3215
|
-
import { jsx as jsx14, jsxs as
|
|
3414
|
+
import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3216
3415
|
function ConversationViewport({
|
|
3217
3416
|
children,
|
|
3218
3417
|
streamKey = null
|
|
3219
3418
|
}) {
|
|
3220
|
-
const scrollRef =
|
|
3419
|
+
const scrollRef = useRef7(null);
|
|
3221
3420
|
const { hasOverflow, isAtBottom, maintainScrollPosition, scrollToBottom, setPinnedStream } = useConversationScroll(scrollRef);
|
|
3222
3421
|
const isScrollButtonVisible = hasOverflow && !isAtBottom;
|
|
3223
3422
|
useScrollShadow(scrollRef);
|
|
@@ -3225,7 +3424,7 @@ function ConversationViewport({
|
|
|
3225
3424
|
setPinnedStream(streamKey);
|
|
3226
3425
|
maintainScrollPosition();
|
|
3227
3426
|
}, [children, maintainScrollPosition, setPinnedStream, streamKey]);
|
|
3228
|
-
return /* @__PURE__ */
|
|
3427
|
+
return /* @__PURE__ */ jsxs10("div", { className: "ha-conversation", children: [
|
|
3229
3428
|
/* @__PURE__ */ jsx14("div", { ref: scrollRef, "aria-live": "polite", className: "ha-messages", role: "log", children }),
|
|
3230
3429
|
/* @__PURE__ */ jsx14(
|
|
3231
3430
|
"div",
|
|
@@ -3258,7 +3457,7 @@ import { Suspense as Suspense2, lazy as lazy2 } from "react";
|
|
|
3258
3457
|
// src/embed/genui-renderer-loader.ts
|
|
3259
3458
|
var componentRendererPromise;
|
|
3260
3459
|
function loadGenUIRenderer() {
|
|
3261
|
-
componentRendererPromise ??= import("./component-renderer-
|
|
3460
|
+
componentRendererPromise ??= import("./component-renderer-46EJDPTB.js").then(
|
|
3262
3461
|
(module) => ({ default: module.ComponentRenderer })
|
|
3263
3462
|
);
|
|
3264
3463
|
return componentRendererPromise;
|
|
@@ -3279,8 +3478,8 @@ function GenUIRenderer(props) {
|
|
|
3279
3478
|
// src/embed/message-actions.tsx
|
|
3280
3479
|
import { ArrowsRotateLeft, Check, Copy, ThumbsDown, ThumbsUp } from "@gravity-ui/icons";
|
|
3281
3480
|
import { Button as Button2, Popover, TextArea } from "@heroui/react";
|
|
3282
|
-
import { useCallback as useCallback6, useEffect as useEffect10, useRef as
|
|
3283
|
-
import { Fragment, jsx as jsx16, jsxs as
|
|
3481
|
+
import { useCallback as useCallback6, useEffect as useEffect10, useRef as useRef8, useState as useState8 } from "react";
|
|
3482
|
+
import { Fragment, jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3284
3483
|
var COPY_RESET_DELAY = 2e3;
|
|
3285
3484
|
var FEEDBACK_COMMENT_MAX_LENGTH = 1e3;
|
|
3286
3485
|
var NEGATIVE_FEEDBACK_REASONS = [
|
|
@@ -3298,13 +3497,13 @@ function MessageActions({
|
|
|
3298
3497
|
onFeedback,
|
|
3299
3498
|
onRetry
|
|
3300
3499
|
}) {
|
|
3301
|
-
const [isCopied, setIsCopied] =
|
|
3302
|
-
const [isFeedbackOpen, setIsFeedbackOpen] =
|
|
3303
|
-
const [feedbackComment, setFeedbackComment] =
|
|
3304
|
-
const [feedbackReasons, setFeedbackReasons] =
|
|
3305
|
-
const [feedbackPortalContainer, setFeedbackPortalContainer] =
|
|
3306
|
-
const resetTimeoutRef =
|
|
3307
|
-
const feedbackOpenedAtRef =
|
|
3500
|
+
const [isCopied, setIsCopied] = useState8(false);
|
|
3501
|
+
const [isFeedbackOpen, setIsFeedbackOpen] = useState8(false);
|
|
3502
|
+
const [feedbackComment, setFeedbackComment] = useState8("");
|
|
3503
|
+
const [feedbackReasons, setFeedbackReasons] = useState8([]);
|
|
3504
|
+
const [feedbackPortalContainer, setFeedbackPortalContainer] = useState8();
|
|
3505
|
+
const resetTimeoutRef = useRef8(null);
|
|
3506
|
+
const feedbackOpenedAtRef = useRef8(0);
|
|
3308
3507
|
const feedbackTriggerRef = useCallback6((node) => {
|
|
3309
3508
|
setFeedbackPortalContainer(node?.closest(".ha-panel") ?? void 0);
|
|
3310
3509
|
}, []);
|
|
@@ -3343,7 +3542,7 @@ function MessageActions({
|
|
|
3343
3542
|
});
|
|
3344
3543
|
setIsFeedbackOpen(false);
|
|
3345
3544
|
};
|
|
3346
|
-
return /* @__PURE__ */
|
|
3545
|
+
return /* @__PURE__ */ jsxs11("div", { "aria-label": "Message actions", className: "ha-message-actions", role: "group", children: [
|
|
3347
3546
|
showCopy ? /* @__PURE__ */ jsx16(
|
|
3348
3547
|
"button",
|
|
3349
3548
|
{
|
|
@@ -3355,7 +3554,7 @@ function MessageActions({
|
|
|
3355
3554
|
children: /* @__PURE__ */ jsx16("span", { className: "ha-message-action-icon", children: isCopied ? /* @__PURE__ */ jsx16(Check, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx16(Copy, { "aria-hidden": "true" }) }, isCopied ? "check" : "copy")
|
|
3356
3555
|
}
|
|
3357
3556
|
) : null,
|
|
3358
|
-
showFeedback ? /* @__PURE__ */
|
|
3557
|
+
showFeedback ? /* @__PURE__ */ jsxs11(Fragment, { children: [
|
|
3359
3558
|
/* @__PURE__ */ jsx16(
|
|
3360
3559
|
"button",
|
|
3361
3560
|
{
|
|
@@ -3368,7 +3567,7 @@ function MessageActions({
|
|
|
3368
3567
|
children: /* @__PURE__ */ jsx16(ThumbsUp, { "aria-hidden": "true" })
|
|
3369
3568
|
}
|
|
3370
3569
|
),
|
|
3371
|
-
/* @__PURE__ */
|
|
3570
|
+
/* @__PURE__ */ jsxs11(Popover, { isOpen: isFeedbackOpen, onOpenChange: handleFeedbackOpenChange, children: [
|
|
3372
3571
|
/* @__PURE__ */ jsx16(
|
|
3373
3572
|
Button2,
|
|
3374
3573
|
{
|
|
@@ -3394,7 +3593,7 @@ function MessageActions({
|
|
|
3394
3593
|
offset: 8,
|
|
3395
3594
|
placement: "top start",
|
|
3396
3595
|
UNSTABLE_portalContainer: feedbackPortalContainer,
|
|
3397
|
-
children: /* @__PURE__ */
|
|
3596
|
+
children: /* @__PURE__ */ jsxs11(Popover.Dialog, { className: "ha-feedback-dialog", children: [
|
|
3398
3597
|
/* @__PURE__ */ jsx16(Popover.Heading, { className: "ha-feedback-heading", children: "Help us improve" }),
|
|
3399
3598
|
/* @__PURE__ */ jsx16("p", { className: "ha-feedback-description", children: "What could be better?" }),
|
|
3400
3599
|
/* @__PURE__ */ jsx16("div", { "aria-label": "Feedback reasons", className: "ha-feedback-reasons", role: "group", children: NEGATIVE_FEEDBACK_REASONS.map((reason) => {
|
|
@@ -3427,7 +3626,7 @@ function MessageActions({
|
|
|
3427
3626
|
}
|
|
3428
3627
|
),
|
|
3429
3628
|
/* @__PURE__ */ jsx16("p", { className: "ha-feedback-privacy", children: "Avoid sharing sensitive information." }),
|
|
3430
|
-
/* @__PURE__ */
|
|
3629
|
+
/* @__PURE__ */ jsxs11("div", { className: "ha-feedback-footer", children: [
|
|
3431
3630
|
/* @__PURE__ */ jsx16(
|
|
3432
3631
|
Button2,
|
|
3433
3632
|
{
|
|
@@ -3468,7 +3667,7 @@ function MessageActions({
|
|
|
3468
3667
|
}
|
|
3469
3668
|
|
|
3470
3669
|
// src/embed/message-attachment.tsx
|
|
3471
|
-
import { jsx as jsx17, jsxs as
|
|
3670
|
+
import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3472
3671
|
function MessageAttachment({ file }) {
|
|
3473
3672
|
const name = file.filename?.trim() || "Attachment";
|
|
3474
3673
|
const type = file.mediaType?.trim() || "";
|
|
@@ -3488,7 +3687,7 @@ function MessageAttachment({ file }) {
|
|
|
3488
3687
|
}
|
|
3489
3688
|
);
|
|
3490
3689
|
}
|
|
3491
|
-
return /* @__PURE__ */
|
|
3690
|
+
return /* @__PURE__ */ jsxs12(
|
|
3492
3691
|
"a",
|
|
3493
3692
|
{
|
|
3494
3693
|
className: "ha-message-file",
|
|
@@ -3499,7 +3698,7 @@ function MessageAttachment({ file }) {
|
|
|
3499
3698
|
target: "_blank",
|
|
3500
3699
|
children: [
|
|
3501
3700
|
/* @__PURE__ */ jsx17("span", { "aria-hidden": "true", className: "ha-message-file-icon", children: /* @__PURE__ */ jsx17(Icon, {}) }),
|
|
3502
|
-
/* @__PURE__ */
|
|
3701
|
+
/* @__PURE__ */ jsxs12("span", { className: "ha-message-file-copy", children: [
|
|
3503
3702
|
/* @__PURE__ */ jsx17("span", { className: "ha-message-file-name", title: name, children: name }),
|
|
3504
3703
|
/* @__PURE__ */ jsx17("span", { className: "ha-message-file-type", children: label })
|
|
3505
3704
|
] })
|
|
@@ -3650,23 +3849,23 @@ function handleMessageQueueComposerKeyDown(event, queue) {
|
|
|
3650
3849
|
|
|
3651
3850
|
// src/embed/message-queue-list.tsx
|
|
3652
3851
|
import { ArrowUp, CircleExclamation, Clock, Grip, Pencil, TrashBin } from "@gravity-ui/icons";
|
|
3653
|
-
import { useImperativeHandle, useLayoutEffect as useLayoutEffect3, useRef as
|
|
3852
|
+
import { useImperativeHandle, useLayoutEffect as useLayoutEffect3, useRef as useRef10 } from "react";
|
|
3654
3853
|
|
|
3655
3854
|
// src/embed/use-message-queue-reorder.ts
|
|
3656
|
-
import { useRef as
|
|
3855
|
+
import { useRef as useRef9, useState as useState9 } from "react";
|
|
3657
3856
|
function useMessageQueueReorder({
|
|
3658
3857
|
messages,
|
|
3659
3858
|
onReorder,
|
|
3660
3859
|
onReorderStateChange
|
|
3661
3860
|
}) {
|
|
3662
|
-
const dragStateRef =
|
|
3663
|
-
const dropTargetRef =
|
|
3664
|
-
const positionPickerMessageIdRef =
|
|
3665
|
-
const suppressedClickMessageIdRef =
|
|
3666
|
-
const [announcement, setAnnouncement] =
|
|
3667
|
-
const [draggedMessageId, setDraggedMessageId] =
|
|
3668
|
-
const [dropTarget, setDropTarget] =
|
|
3669
|
-
const [positionPickerMessageId, setPositionPickerMessageId] =
|
|
3861
|
+
const dragStateRef = useRef9(null);
|
|
3862
|
+
const dropTargetRef = useRef9(null);
|
|
3863
|
+
const positionPickerMessageIdRef = useRef9(null);
|
|
3864
|
+
const suppressedClickMessageIdRef = useRef9(null);
|
|
3865
|
+
const [announcement, setAnnouncement] = useState9("");
|
|
3866
|
+
const [draggedMessageId, setDraggedMessageId] = useState9(null);
|
|
3867
|
+
const [dropTarget, setDropTarget] = useState9(null);
|
|
3868
|
+
const [positionPickerMessageId, setPositionPickerMessageId] = useState9(null);
|
|
3670
3869
|
const updateDropTarget = (nextTarget) => {
|
|
3671
3870
|
dropTargetRef.current = nextTarget;
|
|
3672
3871
|
setDropTarget(nextTarget);
|
|
@@ -3814,7 +4013,7 @@ function useMessageQueueReorder({
|
|
|
3814
4013
|
}
|
|
3815
4014
|
|
|
3816
4015
|
// src/embed/message-queue-list.tsx
|
|
3817
|
-
import { jsx as jsx18, jsxs as
|
|
4016
|
+
import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3818
4017
|
function focusQueueMessageAt(list, index) {
|
|
3819
4018
|
const item = list?.querySelectorAll("[data-queue-message-id]")[index];
|
|
3820
4019
|
if (!item) return false;
|
|
@@ -3834,9 +4033,9 @@ function MessageQueueList({
|
|
|
3834
4033
|
onSendNow,
|
|
3835
4034
|
ref
|
|
3836
4035
|
}) {
|
|
3837
|
-
const focusedMessageIdRef =
|
|
3838
|
-
const listRef =
|
|
3839
|
-
const previousMessagesRef =
|
|
4036
|
+
const focusedMessageIdRef = useRef10(null);
|
|
4037
|
+
const listRef = useRef10(null);
|
|
4038
|
+
const previousMessagesRef = useRef10(messages);
|
|
3840
4039
|
const {
|
|
3841
4040
|
announcement,
|
|
3842
4041
|
closePositionPicker,
|
|
@@ -3878,7 +4077,7 @@ function MessageQueueList({
|
|
|
3878
4077
|
}
|
|
3879
4078
|
if (!focusQueueMessageAt(listRef.current, index + 1)) onFocusComposer();
|
|
3880
4079
|
};
|
|
3881
|
-
return /* @__PURE__ */
|
|
4080
|
+
return /* @__PURE__ */ jsxs13("section", { "aria-label": "Queued messages", className: "ha-message-queue", children: [
|
|
3882
4081
|
/* @__PURE__ */ jsx18("div", { className: "ha-message-queue-header", children: "Queued" }),
|
|
3883
4082
|
/* @__PURE__ */ jsx18("ol", { ref: listRef, className: "ha-message-queue-list", children: messages.map((message, index) => {
|
|
3884
4083
|
const isBlocked = blockedMessageId === message.id;
|
|
@@ -3886,7 +4085,7 @@ function MessageQueueList({
|
|
|
3886
4085
|
const statusId = isBlocked ? `ha-queued-message-status-${message.id}` : void 0;
|
|
3887
4086
|
return (
|
|
3888
4087
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- Queue rows are programmatically focused for arrow-key navigation; nested controls keep their own key handling.
|
|
3889
|
-
/* @__PURE__ */
|
|
4088
|
+
/* @__PURE__ */ jsxs13(
|
|
3890
4089
|
"li",
|
|
3891
4090
|
{
|
|
3892
4091
|
"aria-describedby": statusId,
|
|
@@ -3936,18 +4135,18 @@ function MessageQueueList({
|
|
|
3936
4135
|
value: index,
|
|
3937
4136
|
onBlur: () => closePositionPicker(message.id),
|
|
3938
4137
|
onChange: (event) => moveMessageToPosition(message.id, index, Number(event.currentTarget.value)),
|
|
3939
|
-
children: messages.map((queuedMessage, position) => /* @__PURE__ */
|
|
4138
|
+
children: messages.map((queuedMessage, position) => /* @__PURE__ */ jsxs13("option", { value: position, children: [
|
|
3940
4139
|
"Position ",
|
|
3941
4140
|
position + 1,
|
|
3942
4141
|
position === index ? " (current)" : ""
|
|
3943
4142
|
] }, queuedMessage.id))
|
|
3944
4143
|
}
|
|
3945
4144
|
) : /* @__PURE__ */ jsx18("span", { "aria-hidden": "true", className: "ha-message-queue-icon", children: isBlocked ? /* @__PURE__ */ jsx18(CircleExclamation, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx18(Clock, { "aria-hidden": "true" }) }),
|
|
3946
|
-
/* @__PURE__ */
|
|
4145
|
+
/* @__PURE__ */ jsxs13("span", { className: "ha-message-queue-content", children: [
|
|
3947
4146
|
/* @__PURE__ */ jsx18("span", { className: "ha-message-queue-preview", children: getQueuedAgentMessagePreview(message) }),
|
|
3948
4147
|
isBlocked ? /* @__PURE__ */ jsx18("span", { className: "ha-message-queue-status", id: statusId, role: "status", children: "Could not send" }) : null
|
|
3949
4148
|
] }),
|
|
3950
|
-
/* @__PURE__ */
|
|
4149
|
+
/* @__PURE__ */ jsxs13("span", { className: "ha-message-queue-actions", children: [
|
|
3951
4150
|
/* @__PURE__ */ jsx18(
|
|
3952
4151
|
"button",
|
|
3953
4152
|
{
|
|
@@ -4001,7 +4200,7 @@ import { composeRenderProps as composeRenderProps2 } from "react-aria-components
|
|
|
4001
4200
|
// ../agent-ui/src/components/hover-card/hover-card.tsx
|
|
4002
4201
|
import { mergeRefs } from "@react-aria/utils";
|
|
4003
4202
|
import { useControlledState } from "@react-stately/utils";
|
|
4004
|
-
import { createContext, useCallback as useCallback7, useContext, useEffect as useEffect11, useMemo as useMemo2, useRef as
|
|
4203
|
+
import { createContext, useCallback as useCallback7, useContext, useEffect as useEffect11, useMemo as useMemo2, useRef as useRef11, useState as useState10 } from "react";
|
|
4005
4204
|
import {
|
|
4006
4205
|
OverlayArrow as OverlayArrowPrimitive,
|
|
4007
4206
|
Popover as PopoverPrimitive,
|
|
@@ -4030,11 +4229,11 @@ var HoverCardRoot = ({
|
|
|
4030
4229
|
openDelay = 700
|
|
4031
4230
|
}) => {
|
|
4032
4231
|
const [isOpen, setOpen] = useControlledState(open, defaultOpen, onOpenChange);
|
|
4033
|
-
const [portalContainer, setPortalContainer] =
|
|
4034
|
-
const triggerRef =
|
|
4035
|
-
const isPointerInsideRef =
|
|
4036
|
-
const openTimerRef =
|
|
4037
|
-
const closeTimerRef =
|
|
4232
|
+
const [portalContainer, setPortalContainer] = useState10();
|
|
4233
|
+
const triggerRef = useRef11(null);
|
|
4234
|
+
const isPointerInsideRef = useRef11(false);
|
|
4235
|
+
const openTimerRef = useRef11(void 0);
|
|
4236
|
+
const closeTimerRef = useRef11(void 0);
|
|
4038
4237
|
const clearTimers = useCallback7(() => {
|
|
4039
4238
|
clearTimeout(openTimerRef.current);
|
|
4040
4239
|
clearTimeout(closeTimerRef.current);
|
|
@@ -4251,7 +4450,7 @@ function extractSourceDomain(href) {
|
|
|
4251
4450
|
}
|
|
4252
4451
|
|
|
4253
4452
|
// ../agent-ui/src/components/chat-source/chat-source.tsx
|
|
4254
|
-
import { Fragment as Fragment2, jsx as jsx20, jsxs as
|
|
4453
|
+
import { Fragment as Fragment2, jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
4255
4454
|
var ChatSourceContext = createContext2({ sourceType: "url" });
|
|
4256
4455
|
var useChatSourceContext = () => useContext2(ChatSourceContext);
|
|
4257
4456
|
function getSourceInitial(label) {
|
|
@@ -4276,7 +4475,7 @@ var ChatSourceRoot = ({
|
|
|
4276
4475
|
() => ({ description, domain, enablePreview, faviconUrl, href, locator, sourceType, title }),
|
|
4277
4476
|
[description, domain, enablePreview, faviconUrl, href, locator, sourceType, title]
|
|
4278
4477
|
);
|
|
4279
|
-
const body = children ?? /* @__PURE__ */
|
|
4478
|
+
const body = children ?? /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
4280
4479
|
/* @__PURE__ */ jsx20(ChatSourceTrigger, {}),
|
|
4281
4480
|
enablePreview ? /* @__PURE__ */ jsx20(ChatSourcePreview, { description, title }) : null
|
|
4282
4481
|
] });
|
|
@@ -4296,11 +4495,11 @@ var ChatSourceRoot = ({
|
|
|
4296
4495
|
var ChatSourceTrigger = ({ children, className, label, ...props }) => {
|
|
4297
4496
|
const { domain, enablePreview, href, locator, sourceType, title } = useChatSourceContext();
|
|
4298
4497
|
const isUrl = sourceType === "url" && href;
|
|
4299
|
-
const triggerBody = children ?? label ?? (isUrl ? /* @__PURE__ */
|
|
4498
|
+
const triggerBody = children ?? label ?? (isUrl ? /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
4300
4499
|
/* @__PURE__ */ jsx20(ChatSourceIcon, {}),
|
|
4301
4500
|
/* @__PURE__ */ jsx20(ChatSourceTitle, { children: title ?? domain }),
|
|
4302
4501
|
locator ? /* @__PURE__ */ jsx20(ChatSourceLocator, { children: locator }) : null
|
|
4303
|
-
] }) : /* @__PURE__ */
|
|
4502
|
+
] }) : /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
4304
4503
|
/* @__PURE__ */ jsx20(ChatSourceDocumentIcon, {}),
|
|
4305
4504
|
/* @__PURE__ */ jsx20(ChatSourceTitle, { children: title }),
|
|
4306
4505
|
locator ? /* @__PURE__ */ jsx20(ChatSourceLocator, { children: locator }) : null
|
|
@@ -4378,7 +4577,7 @@ var ChatSourceIcon = ({ children, className, faviconUrl }) => {
|
|
|
4378
4577
|
"data-slot": "chat-source-icon"
|
|
4379
4578
|
});
|
|
4380
4579
|
}
|
|
4381
|
-
return /* @__PURE__ */
|
|
4580
|
+
return /* @__PURE__ */ jsxs14(
|
|
4382
4581
|
"span",
|
|
4383
4582
|
{
|
|
4384
4583
|
"aria-hidden": "true",
|
|
@@ -4445,7 +4644,7 @@ var ChatSourcePreview = ({
|
|
|
4445
4644
|
if (!enablePreview) return null;
|
|
4446
4645
|
const resolvedTitle = title ?? contextTitle;
|
|
4447
4646
|
const resolvedDescription = description ?? contextDescription;
|
|
4448
|
-
const body = sourceType === "url" && href ? /* @__PURE__ */
|
|
4647
|
+
const body = sourceType === "url" && href ? /* @__PURE__ */ jsxs14(
|
|
4449
4648
|
"a",
|
|
4450
4649
|
{
|
|
4451
4650
|
className: "aui-chat-source__preview-link",
|
|
@@ -4453,7 +4652,7 @@ var ChatSourcePreview = ({
|
|
|
4453
4652
|
rel: "noopener noreferrer",
|
|
4454
4653
|
target: "_blank",
|
|
4455
4654
|
children: [
|
|
4456
|
-
/* @__PURE__ */
|
|
4655
|
+
/* @__PURE__ */ jsxs14("div", { className: "aui-chat-source__preview-header", children: [
|
|
4457
4656
|
/* @__PURE__ */ jsx20(ChatSourceIcon, {}),
|
|
4458
4657
|
/* @__PURE__ */ jsx20("span", { className: "aui-chat-source__preview-domain", children: domain })
|
|
4459
4658
|
] }),
|
|
@@ -4461,8 +4660,8 @@ var ChatSourcePreview = ({
|
|
|
4461
4660
|
resolvedDescription ? /* @__PURE__ */ jsx20("div", { className: "aui-chat-source__preview-description", children: resolvedDescription }) : null
|
|
4462
4661
|
]
|
|
4463
4662
|
}
|
|
4464
|
-
) : /* @__PURE__ */
|
|
4465
|
-
/* @__PURE__ */
|
|
4663
|
+
) : /* @__PURE__ */ jsxs14("div", { className: "aui-chat-source__preview-link", "data-source-type": "document", children: [
|
|
4664
|
+
/* @__PURE__ */ jsxs14("div", { className: "aui-chat-source__preview-header", children: [
|
|
4466
4665
|
/* @__PURE__ */ jsx20(ChatSourceDocumentIcon, {}),
|
|
4467
4666
|
/* @__PURE__ */ jsx20("span", { className: "aui-chat-source__preview-domain", children: resolvedTitle ?? "Document" })
|
|
4468
4667
|
] }),
|
|
@@ -4488,7 +4687,7 @@ var ChatSourcePreview = ({
|
|
|
4488
4687
|
// ../agent-ui/src/components/chat-source/chat-sources.tsx
|
|
4489
4688
|
import { Disclosure as Disclosure3 } from "@heroui/react";
|
|
4490
4689
|
import { composeRenderProps as composeRenderProps3 } from "react-aria-components";
|
|
4491
|
-
import { jsx as jsx21, jsxs as
|
|
4690
|
+
import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4492
4691
|
var ChatSourcesRoot = ({ children, className, ...props }) => /* @__PURE__ */ jsx21(
|
|
4493
4692
|
Disclosure3,
|
|
4494
4693
|
{
|
|
@@ -4501,7 +4700,7 @@ var ChatSourcesRoot = ({ children, className, ...props }) => /* @__PURE__ */ jsx
|
|
|
4501
4700
|
children
|
|
4502
4701
|
}
|
|
4503
4702
|
);
|
|
4504
|
-
var ChatSourcesTrigger = ({ children, className, ...props }) => /* @__PURE__ */ jsx21(Disclosure3.Heading, { children: /* @__PURE__ */
|
|
4703
|
+
var ChatSourcesTrigger = ({ children, className, ...props }) => /* @__PURE__ */ jsx21(Disclosure3.Heading, { children: /* @__PURE__ */ jsxs15(
|
|
4505
4704
|
Disclosure3.Trigger,
|
|
4506
4705
|
{
|
|
4507
4706
|
"data-slot": "chat-sources-trigger",
|
|
@@ -4557,7 +4756,7 @@ var ChatSources = Object.assign(ChatSourcesRoot, {
|
|
|
4557
4756
|
});
|
|
4558
4757
|
|
|
4559
4758
|
// src/embed/message-sources.tsx
|
|
4560
|
-
import { jsx as jsx22, jsxs as
|
|
4759
|
+
import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4561
4760
|
function sourceFaviconUrl(url) {
|
|
4562
4761
|
return `https://www.google.com/s2/favicons?domain_url=${encodeURIComponent(url)}&sz=64`;
|
|
4563
4762
|
}
|
|
@@ -4584,8 +4783,8 @@ function MessageSources({ sources }) {
|
|
|
4584
4783
|
if (sources.length === 1) {
|
|
4585
4784
|
return /* @__PURE__ */ jsx22("div", { "aria-label": "Sources", className: "ha-message-sources", "data-count": "1", role: "group", children: /* @__PURE__ */ jsx22(SourceLink, { source: sources[0] }) });
|
|
4586
4785
|
}
|
|
4587
|
-
return /* @__PURE__ */
|
|
4588
|
-
/* @__PURE__ */
|
|
4786
|
+
return /* @__PURE__ */ jsxs16(ChatSources, { className: "ha-message-sources", "data-count": sources.length, children: [
|
|
4787
|
+
/* @__PURE__ */ jsxs16(ChatSources.Trigger, { "aria-label": `${sources.length} sources`, children: [
|
|
4589
4788
|
/* @__PURE__ */ jsx22("span", { className: "ha-sources-label", children: "Sources" }),
|
|
4590
4789
|
/* @__PURE__ */ jsx22("span", { "aria-hidden": "true", className: "ha-sources-count", children: sources.length })
|
|
4591
4790
|
] }),
|
|
@@ -4670,8 +4869,8 @@ function writeCachedProjectConfig(agentId, config) {
|
|
|
4670
4869
|
// src/embed/session-picker.tsx
|
|
4671
4870
|
import { ChevronDown as ChevronDown2, Ellipsis, Pencil as Pencil2, Plus as Plus2, TrashBin as TrashBin2 } from "@gravity-ui/icons";
|
|
4672
4871
|
import { Button as Button4, Dropdown, Input, Label as Label3, Modal, Popover as Popover2, TextField } from "@heroui/react";
|
|
4673
|
-
import { useCallback as useCallback8, useRef as
|
|
4674
|
-
import { Fragment as Fragment3, jsx as jsx24, jsxs as
|
|
4872
|
+
import { useCallback as useCallback8, useRef as useRef12, useState as useState11 } from "react";
|
|
4873
|
+
import { Fragment as Fragment3, jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
4675
4874
|
var RENAME_KEY = "rename";
|
|
4676
4875
|
var DELETE_KEY = "delete";
|
|
4677
4876
|
var MAX_TITLE_LENGTH = 80;
|
|
@@ -4687,17 +4886,17 @@ function SessionPicker({
|
|
|
4687
4886
|
onSelectConversation,
|
|
4688
4887
|
variant = "popover"
|
|
4689
4888
|
}) {
|
|
4690
|
-
const [isOpen, setIsOpen] =
|
|
4691
|
-
const [isDialogOpen, setIsDialogOpen] =
|
|
4692
|
-
const [actionMenuId, setActionMenuId] =
|
|
4693
|
-
const [dialog, setDialog] =
|
|
4694
|
-
const [renameTitle, setRenameTitle] =
|
|
4695
|
-
const [mutationError, setMutationError] =
|
|
4696
|
-
const [isPending, setIsPending] =
|
|
4697
|
-
const [portalContainer, setPortalContainer] =
|
|
4698
|
-
const pointerOpenAt =
|
|
4699
|
-
const actionPointerOpenAt =
|
|
4700
|
-
const sidebarHistoryRef =
|
|
4889
|
+
const [isOpen, setIsOpen] = useState11(false);
|
|
4890
|
+
const [isDialogOpen, setIsDialogOpen] = useState11(false);
|
|
4891
|
+
const [actionMenuId, setActionMenuId] = useState11(null);
|
|
4892
|
+
const [dialog, setDialog] = useState11(null);
|
|
4893
|
+
const [renameTitle, setRenameTitle] = useState11("");
|
|
4894
|
+
const [mutationError, setMutationError] = useState11(null);
|
|
4895
|
+
const [isPending, setIsPending] = useState11(false);
|
|
4896
|
+
const [portalContainer, setPortalContainer] = useState11();
|
|
4897
|
+
const pointerOpenAt = useRef12(0);
|
|
4898
|
+
const actionPointerOpenAt = useRef12(0);
|
|
4899
|
+
const sidebarHistoryRef = useRef12(null);
|
|
4701
4900
|
useScrollShadow(sidebarHistoryRef);
|
|
4702
4901
|
const activeConversation = groups.flatMap((group) => group.items).find((conversation) => conversation.id === activeConversationId);
|
|
4703
4902
|
const activeTitle = activeConversation?.title ?? "New chat";
|
|
@@ -4769,13 +4968,13 @@ function SessionPicker({
|
|
|
4769
4968
|
setIsPending(false);
|
|
4770
4969
|
}
|
|
4771
4970
|
};
|
|
4772
|
-
const history = groups.length ? groups.map((group) => /* @__PURE__ */
|
|
4971
|
+
const history = groups.length ? groups.map((group) => /* @__PURE__ */ jsxs17("section", { className: "ha-session-group", children: [
|
|
4773
4972
|
/* @__PURE__ */ jsx24("h3", { children: group.label }),
|
|
4774
4973
|
/* @__PURE__ */ jsx24("div", { className: "ha-session-list", children: group.items.map((conversation) => {
|
|
4775
4974
|
const isActive = conversation.id === activeConversationId;
|
|
4776
4975
|
const isBusy = busyConversationIds.has(conversation.id);
|
|
4777
4976
|
const hasCompletedUpdate = !isBusy && completedConversationIds.has(conversation.id);
|
|
4778
|
-
return /* @__PURE__ */
|
|
4977
|
+
return /* @__PURE__ */ jsxs17(
|
|
4779
4978
|
"div",
|
|
4780
4979
|
{
|
|
4781
4980
|
className: "ha-session-row",
|
|
@@ -4783,7 +4982,7 @@ function SessionPicker({
|
|
|
4783
4982
|
"data-active": isActive || void 0,
|
|
4784
4983
|
"data-completed": hasCompletedUpdate || void 0,
|
|
4785
4984
|
children: [
|
|
4786
|
-
/* @__PURE__ */
|
|
4985
|
+
/* @__PURE__ */ jsxs17(
|
|
4787
4986
|
"button",
|
|
4788
4987
|
{
|
|
4789
4988
|
"aria-current": isActive ? "page" : void 0,
|
|
@@ -4800,7 +4999,7 @@ function SessionPicker({
|
|
|
4800
4999
|
]
|
|
4801
5000
|
}
|
|
4802
5001
|
),
|
|
4803
|
-
/* @__PURE__ */
|
|
5002
|
+
/* @__PURE__ */ jsxs17(
|
|
4804
5003
|
Dropdown,
|
|
4805
5004
|
{
|
|
4806
5005
|
isOpen: actionMenuId === conversation.id,
|
|
@@ -4826,17 +5025,17 @@ function SessionPicker({
|
|
|
4826
5025
|
className: "ha-session-actions-menu",
|
|
4827
5026
|
placement: "bottom end",
|
|
4828
5027
|
UNSTABLE_portalContainer: portalContainer,
|
|
4829
|
-
children: /* @__PURE__ */
|
|
5028
|
+
children: /* @__PURE__ */ jsxs17(
|
|
4830
5029
|
Dropdown.Menu,
|
|
4831
5030
|
{
|
|
4832
5031
|
"aria-label": `Actions for ${conversation.title}`,
|
|
4833
5032
|
onAction: (key) => handleConversationAction(conversation, key),
|
|
4834
5033
|
children: [
|
|
4835
|
-
/* @__PURE__ */
|
|
5034
|
+
/* @__PURE__ */ jsxs17(Dropdown.Item, { id: RENAME_KEY, textValue: "Rename", children: [
|
|
4836
5035
|
/* @__PURE__ */ jsx24(Pencil2, { "aria-hidden": "true" }),
|
|
4837
5036
|
/* @__PURE__ */ jsx24(Label3, { children: "Rename" })
|
|
4838
5037
|
] }),
|
|
4839
|
-
/* @__PURE__ */
|
|
5038
|
+
/* @__PURE__ */ jsxs17(
|
|
4840
5039
|
Dropdown.Item,
|
|
4841
5040
|
{
|
|
4842
5041
|
id: DELETE_KEY,
|
|
@@ -4863,16 +5062,16 @@ function SessionPicker({
|
|
|
4863
5062
|
);
|
|
4864
5063
|
}) })
|
|
4865
5064
|
] }, group.label)) : /* @__PURE__ */ jsx24("p", { className: "ha-session-empty", children: "Your recent chats will appear here." });
|
|
4866
|
-
return /* @__PURE__ */
|
|
5065
|
+
return /* @__PURE__ */ jsxs17(
|
|
4867
5066
|
"div",
|
|
4868
5067
|
{
|
|
4869
5068
|
"data-variant": variant,
|
|
4870
5069
|
className: variant === "sidebar" ? "ha-session-picker ha-session-sidebar" : "ha-session-picker",
|
|
4871
5070
|
children: [
|
|
4872
|
-
variant === "sidebar" ? /* @__PURE__ */
|
|
4873
|
-
/* @__PURE__ */
|
|
5071
|
+
variant === "sidebar" ? /* @__PURE__ */ jsxs17(Fragment3, { children: [
|
|
5072
|
+
/* @__PURE__ */ jsxs17("div", { className: "ha-session-sidebar-header", children: [
|
|
4874
5073
|
/* @__PURE__ */ jsx24("h2", { children: "Chats" }),
|
|
4875
|
-
/* @__PURE__ */
|
|
5074
|
+
/* @__PURE__ */ jsxs17(
|
|
4876
5075
|
Button4,
|
|
4877
5076
|
{
|
|
4878
5077
|
fullWidth: true,
|
|
@@ -4899,8 +5098,8 @@ function SessionPicker({
|
|
|
4899
5098
|
children: history
|
|
4900
5099
|
}
|
|
4901
5100
|
)
|
|
4902
|
-
] }) : /* @__PURE__ */
|
|
4903
|
-
/* @__PURE__ */
|
|
5101
|
+
] }) : /* @__PURE__ */ jsxs17(Popover2, { isOpen, onOpenChange: handleOpenChange, children: [
|
|
5102
|
+
/* @__PURE__ */ jsxs17(
|
|
4904
5103
|
Button4,
|
|
4905
5104
|
{
|
|
4906
5105
|
"aria-label": "Choose a chat",
|
|
@@ -4985,7 +5184,7 @@ function SessionDialogContent({
|
|
|
4985
5184
|
renameTitle
|
|
4986
5185
|
}) {
|
|
4987
5186
|
if (dialog?.type === "rename") {
|
|
4988
|
-
return /* @__PURE__ */
|
|
5187
|
+
return /* @__PURE__ */ jsxs17(
|
|
4989
5188
|
"form",
|
|
4990
5189
|
{
|
|
4991
5190
|
onSubmit: (event) => {
|
|
@@ -4994,7 +5193,7 @@ function SessionDialogContent({
|
|
|
4994
5193
|
},
|
|
4995
5194
|
children: [
|
|
4996
5195
|
/* @__PURE__ */ jsx24(Modal.Header, { children: /* @__PURE__ */ jsx24(Modal.Heading, { children: "Rename chat" }) }),
|
|
4997
|
-
/* @__PURE__ */
|
|
5196
|
+
/* @__PURE__ */ jsxs17(Modal.Body, { children: [
|
|
4998
5197
|
/* @__PURE__ */ jsx24(
|
|
4999
5198
|
TextField,
|
|
5000
5199
|
{
|
|
@@ -5016,7 +5215,7 @@ function SessionDialogContent({
|
|
|
5016
5215
|
),
|
|
5017
5216
|
/* @__PURE__ */ jsx24(SessionDialogError, { message: mutationError })
|
|
5018
5217
|
] }),
|
|
5019
|
-
/* @__PURE__ */
|
|
5218
|
+
/* @__PURE__ */ jsxs17(Modal.Footer, { children: [
|
|
5020
5219
|
/* @__PURE__ */ jsx24(
|
|
5021
5220
|
Button4,
|
|
5022
5221
|
{
|
|
@@ -5035,12 +5234,12 @@ function SessionDialogContent({
|
|
|
5035
5234
|
);
|
|
5036
5235
|
}
|
|
5037
5236
|
if (dialog?.type !== "delete") return null;
|
|
5038
|
-
return /* @__PURE__ */
|
|
5237
|
+
return /* @__PURE__ */ jsxs17(Fragment3, { children: [
|
|
5039
5238
|
/* @__PURE__ */ jsx24(Modal.Header, { children: /* @__PURE__ */ jsx24(Modal.Heading, { children: "Delete chat?" }) }),
|
|
5040
|
-
/* @__PURE__ */
|
|
5041
|
-
/* @__PURE__ */
|
|
5239
|
+
/* @__PURE__ */ jsxs17(Modal.Body, { children: [
|
|
5240
|
+
/* @__PURE__ */ jsxs17("p", { children: [
|
|
5042
5241
|
"Are you sure you want to delete ",
|
|
5043
|
-
/* @__PURE__ */
|
|
5242
|
+
/* @__PURE__ */ jsxs17("strong", { children: [
|
|
5044
5243
|
"\u201C",
|
|
5045
5244
|
dialog.item.title,
|
|
5046
5245
|
"\u201D"
|
|
@@ -5049,7 +5248,7 @@ function SessionDialogContent({
|
|
|
5049
5248
|
] }),
|
|
5050
5249
|
/* @__PURE__ */ jsx24(SessionDialogError, { message: mutationError })
|
|
5051
5250
|
] }),
|
|
5052
|
-
/* @__PURE__ */
|
|
5251
|
+
/* @__PURE__ */ jsxs17(Modal.Footer, { children: [
|
|
5053
5252
|
/* @__PURE__ */ jsx24(Button4, { fullWidth: true, isDisabled: isPending, variant: "outline", onPress: onClose, children: "Cancel" }),
|
|
5054
5253
|
/* @__PURE__ */ jsx24(Button4, { fullWidth: true, isPending, variant: "danger", onPress: () => void onDelete(), children: isPending ? "Deleting\u2026" : "Delete" })
|
|
5055
5254
|
] })
|
|
@@ -5060,7 +5259,7 @@ function SessionDialogError({ message }) {
|
|
|
5060
5259
|
}
|
|
5061
5260
|
|
|
5062
5261
|
// src/embed/startup-activity-status.tsx
|
|
5063
|
-
import { useEffect as useEffect12, useState as
|
|
5262
|
+
import { useEffect as useEffect12, useState as useState12 } from "react";
|
|
5064
5263
|
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
5065
5264
|
var STARTUP_ACTIVITY_STATUSES = [
|
|
5066
5265
|
"Thinking\u2026",
|
|
@@ -5069,7 +5268,7 @@ var STARTUP_ACTIVITY_STATUSES = [
|
|
|
5069
5268
|
];
|
|
5070
5269
|
var STARTUP_ACTIVITY_STATUS_INTERVAL_MS = 1600;
|
|
5071
5270
|
function StartupActivityStatus() {
|
|
5072
|
-
const [statusIndex, setStatusIndex] =
|
|
5271
|
+
const [statusIndex, setStatusIndex] = useState12(0);
|
|
5073
5272
|
useEffect12(() => {
|
|
5074
5273
|
const timers = STARTUP_ACTIVITY_STATUSES.slice(1).map(
|
|
5075
5274
|
(_, index) => window.setTimeout(
|
|
@@ -5112,7 +5311,7 @@ function restoreTriggerSession(stored, bootstrapStatus) {
|
|
|
5112
5311
|
}
|
|
5113
5312
|
|
|
5114
5313
|
// src/embed/use-composer-draft.ts
|
|
5115
|
-
import { useCallback as useCallback9, useEffect as useEffect13, useRef as
|
|
5314
|
+
import { useCallback as useCallback9, useEffect as useEffect13, useRef as useRef13, useState as useState13 } from "react";
|
|
5116
5315
|
var AGENT_COMPOSER_DRAFT_SAVE_DEBOUNCE_MS = 300;
|
|
5117
5316
|
function useComposerDraft({
|
|
5118
5317
|
attachments,
|
|
@@ -5121,10 +5320,10 @@ function useComposerDraft({
|
|
|
5121
5320
|
setAttachments,
|
|
5122
5321
|
setInput
|
|
5123
5322
|
}) {
|
|
5124
|
-
const [restoredImageDraftKey, setRestoredImageDraftKey] =
|
|
5125
|
-
const [restoredPromptDraftKey, setRestoredPromptDraftKey] =
|
|
5126
|
-
const latestInputRef =
|
|
5127
|
-
const saveTimeoutRef =
|
|
5323
|
+
const [restoredImageDraftKey, setRestoredImageDraftKey] = useState13(null);
|
|
5324
|
+
const [restoredPromptDraftKey, setRestoredPromptDraftKey] = useState13(null);
|
|
5325
|
+
const latestInputRef = useRef13(input);
|
|
5326
|
+
const saveTimeoutRef = useRef13(null);
|
|
5128
5327
|
useEffect13(() => {
|
|
5129
5328
|
latestInputRef.current = input;
|
|
5130
5329
|
}, [input]);
|
|
@@ -5175,7 +5374,7 @@ function useComposerDraft({
|
|
|
5175
5374
|
}
|
|
5176
5375
|
|
|
5177
5376
|
// src/embed/use-persisted-model-selection.ts
|
|
5178
|
-
import { useCallback as useCallback10, useState as
|
|
5377
|
+
import { useCallback as useCallback10, useState as useState14 } from "react";
|
|
5179
5378
|
function agentModelPreferenceStorageKey(identityStorageKey) {
|
|
5180
5379
|
return `${identityStorageKey}:model`;
|
|
5181
5380
|
}
|
|
@@ -5203,7 +5402,7 @@ function storeModelPreference(identityStorageKey, modelId) {
|
|
|
5203
5402
|
}
|
|
5204
5403
|
}
|
|
5205
5404
|
function usePersistedModelSelection(identityStorageKey, configuredDefaultModelId) {
|
|
5206
|
-
const [preferredModelId, setPreferredModelId] =
|
|
5405
|
+
const [preferredModelId, setPreferredModelId] = useState14(
|
|
5207
5406
|
() => readStoredModelPreference(identityStorageKey)
|
|
5208
5407
|
);
|
|
5209
5408
|
const selectedModelId = preferredModelId ?? configuredDefaultModelId ?? DEFAULT_AGENT_PICKER_MODEL_ID;
|
|
@@ -5318,7 +5517,7 @@ async function transcribeVoiceRecording({
|
|
|
5318
5517
|
}
|
|
5319
5518
|
|
|
5320
5519
|
// src/embed/embed-runtime.tsx
|
|
5321
|
-
import { Fragment as Fragment4, jsx as jsx26, jsxs as
|
|
5520
|
+
import { Fragment as Fragment4, jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
5322
5521
|
var TRANSPORT_COMPLETION_WATCHDOG_MS = 3e4;
|
|
5323
5522
|
function createReconciliationDeferred() {
|
|
5324
5523
|
let resolve;
|
|
@@ -5361,14 +5560,14 @@ function EmbedRuntime({
|
|
|
5361
5560
|
() => new EmbedSessionManager(options.agentId, options.getAuthToken),
|
|
5362
5561
|
[options.getAuthToken, options.agentId]
|
|
5363
5562
|
);
|
|
5364
|
-
const [activeConversationId, setActiveConversationId] =
|
|
5365
|
-
const [runtimeRoutes, setRuntimeRoutes] =
|
|
5366
|
-
const runtimeRoutesRef =
|
|
5367
|
-
const activeConversationIdRef =
|
|
5368
|
-
const [error, setError] =
|
|
5369
|
-
const [history, setHistory] =
|
|
5370
|
-
const [conversationActivity, setConversationActivity] =
|
|
5371
|
-
const [messageQueues, setMessageQueues] =
|
|
5563
|
+
const [activeConversationId, setActiveConversationId] = useState15(null);
|
|
5564
|
+
const [runtimeRoutes, setRuntimeRoutes] = useState15({});
|
|
5565
|
+
const runtimeRoutesRef = useRef14(runtimeRoutes);
|
|
5566
|
+
const activeConversationIdRef = useRef14(activeConversationId);
|
|
5567
|
+
const [error, setError] = useState15(null);
|
|
5568
|
+
const [history, setHistory] = useState15([]);
|
|
5569
|
+
const [conversationActivity, setConversationActivity] = useState15(createConversationActivityState);
|
|
5570
|
+
const [messageQueues, setMessageQueues] = useState15({});
|
|
5372
5571
|
const runtime = activeConversationId ? runtimeRoutes[activeConversationId] ?? null : null;
|
|
5373
5572
|
useLayoutEffect4(() => {
|
|
5374
5573
|
runtimeRoutesRef.current = runtimeRoutes;
|
|
@@ -5411,7 +5610,7 @@ function EmbedRuntime({
|
|
|
5411
5610
|
},
|
|
5412
5611
|
[]
|
|
5413
5612
|
);
|
|
5414
|
-
const bootstrapCacheRef =
|
|
5613
|
+
const bootstrapCacheRef = useRef14(null);
|
|
5415
5614
|
const apiBaseUrl = options.apiBaseUrl;
|
|
5416
5615
|
const agentId = options.agentId;
|
|
5417
5616
|
const notifyReady = useEffectEvent(onReady);
|
|
@@ -5429,7 +5628,7 @@ function EmbedRuntime({
|
|
|
5429
5628
|
const reportEmbedLoaded = useEffectEvent((conversationId) => {
|
|
5430
5629
|
void reportEvent(options, tokenManager, conversationId, "embed_loaded");
|
|
5431
5630
|
});
|
|
5432
|
-
const appliedIdentityEpochRef =
|
|
5631
|
+
const appliedIdentityEpochRef = useRef14(identityEpoch);
|
|
5433
5632
|
useLayoutEffect4(() => {
|
|
5434
5633
|
if (appliedIdentityEpochRef.current === identityEpoch) return;
|
|
5435
5634
|
appliedIdentityEpochRef.current = identityEpoch;
|
|
@@ -5590,7 +5789,7 @@ function EmbedRuntime({
|
|
|
5590
5789
|
),
|
|
5591
5790
|
[clientToolValidationError, options.permissionDefaultMode, options.tools]
|
|
5592
5791
|
);
|
|
5593
|
-
const preloadedConversationIds =
|
|
5792
|
+
const preloadedConversationIds = useRef14(/* @__PURE__ */ new Set());
|
|
5594
5793
|
const warmAgentSession = useEffectEvent((conversationId) => {
|
|
5595
5794
|
preloadedConversationIds.current.add(conversationId);
|
|
5596
5795
|
void preloadAgentSession(options, tokenManager, conversationId, preloadClientTools);
|
|
@@ -5706,7 +5905,7 @@ function EmbedRuntime({
|
|
|
5706
5905
|
);
|
|
5707
5906
|
}, [options.suggestedPrompts, runtimeRoutes]);
|
|
5708
5907
|
const runtimeConfig = activeConversationId ? configuredRuntimeRoutes[activeConversationId]?.config ?? null : null;
|
|
5709
|
-
const openedConversationRef =
|
|
5908
|
+
const openedConversationRef = useRef14(null);
|
|
5710
5909
|
useEffect14(() => {
|
|
5711
5910
|
if (!open || !runtime || openedConversationRef.current === runtime.conversationId) return;
|
|
5712
5911
|
openedConversationRef.current = runtime.conversationId;
|
|
@@ -5716,7 +5915,7 @@ function EmbedRuntime({
|
|
|
5716
5915
|
const conversationGroups = useMemo4(() => groupConversationHistory(history), [history]);
|
|
5717
5916
|
const activeConversationTitle = history.find((conversation) => conversation.id === activeConversationId)?.title ?? "New chat";
|
|
5718
5917
|
const loadingMessage = bootstrapCacheRef.current ? "Loading chat\u2026" : "Loading assistant\u2026";
|
|
5719
|
-
return /* @__PURE__ */
|
|
5918
|
+
return /* @__PURE__ */ jsxs18(Fragment4, { children: [
|
|
5720
5919
|
open && runtime?.config.presence ? /* @__PURE__ */ jsx26(
|
|
5721
5920
|
AgentConversationPresence,
|
|
5722
5921
|
{
|
|
@@ -5726,7 +5925,7 @@ function EmbedRuntime({
|
|
|
5726
5925
|
userId: runtime.presenceUserId
|
|
5727
5926
|
}
|
|
5728
5927
|
) : null,
|
|
5729
|
-
/* @__PURE__ */
|
|
5928
|
+
/* @__PURE__ */ jsxs18(
|
|
5730
5929
|
PanelShell,
|
|
5731
5930
|
{
|
|
5732
5931
|
actionsSlot: /* @__PURE__ */ jsx26(NewChatButton, { onPress: onNewConversation }),
|
|
@@ -5833,11 +6032,11 @@ function ChatRuntime({
|
|
|
5833
6032
|
const permissionStorageKey = agentPermissionModeStorageKey(storageKey, conversationId);
|
|
5834
6033
|
const attachmentPolicyKey = options.composerAttachmentAccept;
|
|
5835
6034
|
const attachmentPolicy = useMemo4(() => ({ key: attachmentPolicyKey }), [attachmentPolicyKey]);
|
|
5836
|
-
const [attachmentSelection, setAttachmentSelection] =
|
|
6035
|
+
const [attachmentSelection, setAttachmentSelection] = useState15(() => ({
|
|
5837
6036
|
files: [],
|
|
5838
6037
|
policy: attachmentPolicy
|
|
5839
6038
|
}));
|
|
5840
|
-
const [attachmentErrorSelection, setAttachmentErrorSelection] =
|
|
6039
|
+
const [attachmentErrorSelection, setAttachmentErrorSelection] = useState15(() => ({
|
|
5841
6040
|
error: null,
|
|
5842
6041
|
policy: attachmentPolicy
|
|
5843
6042
|
}));
|
|
@@ -5863,16 +6062,16 @@ function ChatRuntime({
|
|
|
5863
6062
|
(error) => setAttachmentErrorSelection({ error, policy: attachmentPolicy }),
|
|
5864
6063
|
[attachmentPolicy]
|
|
5865
6064
|
);
|
|
5866
|
-
const [activeTurnSelection, setActiveTurnSelectionState] =
|
|
6065
|
+
const [activeTurnSelection, setActiveTurnSelectionState] = useState15(() => {
|
|
5867
6066
|
const storedMode = shouldRestoreActivePermission ? readStoredAgentPermissionMode(activePermissionStorageKey) : void 0;
|
|
5868
6067
|
const restoredMode = storedMode ?? (shouldRestoreActivePermission ? "ask" : void 0);
|
|
5869
6068
|
return restoredMode ? { modelId: void 0, permissionMode: restoredMode } : void 0;
|
|
5870
6069
|
});
|
|
5871
|
-
const [activityTimings, setActivityTimings] =
|
|
5872
|
-
const [feedbackByMessage, setFeedbackByMessage] =
|
|
5873
|
-
const [isComposerExpanded, setIsComposerExpanded] =
|
|
5874
|
-
const [input, setInput] =
|
|
5875
|
-
const [permissionSelection, setPermissionSelection] =
|
|
6070
|
+
const [activityTimings, setActivityTimings] = useState15({});
|
|
6071
|
+
const [feedbackByMessage, setFeedbackByMessage] = useState15({});
|
|
6072
|
+
const [isComposerExpanded, setIsComposerExpanded] = useState15(false);
|
|
6073
|
+
const [input, setInput] = useState15("");
|
|
6074
|
+
const [permissionSelection, setPermissionSelection] = useState15(() => {
|
|
5876
6075
|
const storedMode = options.permissionShowPicker ? readStoredAgentPermissionMode(permissionStorageKey) : void 0;
|
|
5877
6076
|
const hasUnresolvedClientTool = options.permissionShowPicker && initialMessages.some(
|
|
5878
6077
|
(message) => message.role === "assistant" && message.parts.some((part) => {
|
|
@@ -5888,19 +6087,19 @@ function ChatRuntime({
|
|
|
5888
6087
|
selectedMode: storedMode ?? (hasUnresolvedClientTool ? "ask" : options.permissionDefaultMode)
|
|
5889
6088
|
};
|
|
5890
6089
|
});
|
|
5891
|
-
const [isQueueReordering, setIsQueueReordering] =
|
|
5892
|
-
const [isReconciling, setIsReconciling] =
|
|
5893
|
-
const [localPending, setLocalPending] =
|
|
5894
|
-
const [pendingClientToolCallIds, setPendingClientToolCallIds] =
|
|
6090
|
+
const [isQueueReordering, setIsQueueReordering] = useState15(false);
|
|
6091
|
+
const [isReconciling, setIsReconciling] = useState15(false);
|
|
6092
|
+
const [localPending, setLocalPending] = useState15(false);
|
|
6093
|
+
const [pendingClientToolCallIds, setPendingClientToolCallIds] = useState15(
|
|
5895
6094
|
() => /* @__PURE__ */ new Set()
|
|
5896
6095
|
);
|
|
5897
|
-
const [isResuming, setIsResuming] =
|
|
5898
|
-
const [progress, setProgress] =
|
|
5899
|
-
const [queueDrainVersion, setQueueDrainVersion] =
|
|
5900
|
-
const [reconcileEpoch, setReconcileEpoch] =
|
|
5901
|
-
const [recoveryError, setRecoveryError] =
|
|
5902
|
-
const [selection, setSelection] =
|
|
5903
|
-
const [toolDecisions, setToolDecisions] =
|
|
6096
|
+
const [isResuming, setIsResuming] = useState15(true);
|
|
6097
|
+
const [progress, setProgress] = useState15(null);
|
|
6098
|
+
const [queueDrainVersion, setQueueDrainVersion] = useState15(0);
|
|
6099
|
+
const [reconcileEpoch, setReconcileEpoch] = useState15(0);
|
|
6100
|
+
const [recoveryError, setRecoveryError] = useState15(false);
|
|
6101
|
+
const [selection, setSelection] = useState15(null);
|
|
6102
|
+
const [toolDecisions, setToolDecisions] = useState15({});
|
|
5904
6103
|
useEffect14(() => {
|
|
5905
6104
|
if (!shouldRestoreActivePermission) {
|
|
5906
6105
|
clearStoredAgentPermissionMode(activePermissionStorageKey);
|
|
@@ -5938,7 +6137,7 @@ function ChatRuntime({
|
|
|
5938
6137
|
() => serializeClientTools(effectiveClientTools),
|
|
5939
6138
|
[effectiveClientTools]
|
|
5940
6139
|
);
|
|
5941
|
-
const clientToolManifestRef =
|
|
6140
|
+
const clientToolManifestRef = useRef14(clientToolManifest);
|
|
5942
6141
|
useLayoutEffect4(() => {
|
|
5943
6142
|
clientToolManifestRef.current = clientToolManifest;
|
|
5944
6143
|
}, [clientToolManifest]);
|
|
@@ -5947,27 +6146,27 @@ function ChatRuntime({
|
|
|
5947
6146
|
() => new Map(effectiveClientTools.map((tool) => [tool.name, tool])),
|
|
5948
6147
|
[effectiveClientTools]
|
|
5949
6148
|
);
|
|
5950
|
-
const executedToolCallsRef =
|
|
5951
|
-
const activeMessageIdRef =
|
|
5952
|
-
const isBusyRef =
|
|
5953
|
-
const isQueueReorderingRef =
|
|
5954
|
-
const messageQueueRef =
|
|
5955
|
-
const pendingTurnAnchorRef =
|
|
5956
|
-
const reconciliationDeferredRef =
|
|
5957
|
-
const reconcileMessageIdRef =
|
|
5958
|
-
const resumePromiseRef =
|
|
5959
|
-
const manualStopRequestedRef =
|
|
5960
|
-
const sendAcknowledgedRef =
|
|
5961
|
-
const sendErrorRef =
|
|
5962
|
-
const streamedMessageIdsRef =
|
|
5963
|
-
const timedMessageIdRef =
|
|
5964
|
-
const transportFailureRef =
|
|
5965
|
-
const turnStartedAtRef =
|
|
5966
|
-
const needsReconciliationRef =
|
|
5967
|
-
const clearChatErrorRef =
|
|
5968
|
-
const fileInputRef =
|
|
5969
|
-
const messageQueueListRef =
|
|
5970
|
-
const textareaRef =
|
|
6149
|
+
const executedToolCallsRef = useRef14(/* @__PURE__ */ new Set());
|
|
6150
|
+
const activeMessageIdRef = useRef14(null);
|
|
6151
|
+
const isBusyRef = useRef14(true);
|
|
6152
|
+
const isQueueReorderingRef = useRef14(false);
|
|
6153
|
+
const messageQueueRef = useRef14(messageQueue);
|
|
6154
|
+
const pendingTurnAnchorRef = useRef14(null);
|
|
6155
|
+
const reconciliationDeferredRef = useRef14(null);
|
|
6156
|
+
const reconcileMessageIdRef = useRef14(void 0);
|
|
6157
|
+
const resumePromiseRef = useRef14(null);
|
|
6158
|
+
const manualStopRequestedRef = useRef14(false);
|
|
6159
|
+
const sendAcknowledgedRef = useRef14(false);
|
|
6160
|
+
const sendErrorRef = useRef14(null);
|
|
6161
|
+
const streamedMessageIdsRef = useRef14(/* @__PURE__ */ new Set());
|
|
6162
|
+
const timedMessageIdRef = useRef14(null);
|
|
6163
|
+
const transportFailureRef = useRef14(null);
|
|
6164
|
+
const turnStartedAtRef = useRef14(null);
|
|
6165
|
+
const needsReconciliationRef = useRef14(false);
|
|
6166
|
+
const clearChatErrorRef = useRef14(() => void 0);
|
|
6167
|
+
const fileInputRef = useRef14(null);
|
|
6168
|
+
const messageQueueListRef = useRef14(null);
|
|
6169
|
+
const textareaRef = useRef14(null);
|
|
5971
6170
|
const composerDraftKey = useMemo4(
|
|
5972
6171
|
() => agentComposerDraftStorageKey(storageKey, conversationId),
|
|
5973
6172
|
[conversationId, storageKey]
|
|
@@ -6465,8 +6664,11 @@ function ChatRuntime({
|
|
|
6465
6664
|
turnStartedAtRef.current = Date.now();
|
|
6466
6665
|
prepareTransportSend();
|
|
6467
6666
|
pendingTurnAnchorRef.current = {
|
|
6468
|
-
|
|
6469
|
-
|
|
6667
|
+
previousUserMessageId: previousUserMessageId ?? null,
|
|
6668
|
+
// A failed queued message can be sent again with the same message id.
|
|
6669
|
+
// Use a fresh key per actual send attempt so each user-triggered send
|
|
6670
|
+
// receives its one permitted viewport movement.
|
|
6671
|
+
scrollKey: crypto.randomUUID()
|
|
6470
6672
|
};
|
|
6471
6673
|
setLocalPending(true);
|
|
6472
6674
|
setRecoveryError(false);
|
|
@@ -6868,8 +7070,7 @@ function ChatRuntime({
|
|
|
6868
7070
|
)?.id;
|
|
6869
7071
|
const lastUserMessageId = chatState.messages.findLast((message) => message.role === "user")?.id;
|
|
6870
7072
|
const { activeStreamKey, activeTurnMessageId } = resolveConversationTurnAnchor({
|
|
6871
|
-
|
|
6872
|
-
isActive: localPending || isRunning,
|
|
7073
|
+
isActive: hasActiveTurn,
|
|
6873
7074
|
lastUserMessageId,
|
|
6874
7075
|
pendingTurn: pendingTurnAnchorRef.current
|
|
6875
7076
|
});
|
|
@@ -6885,9 +7086,9 @@ function ChatRuntime({
|
|
|
6885
7086
|
const dictationButtonLabel = isDictationTranscribing ? "Cancel transcription" : isDictating ? "Stop dictation" : "Dictate message";
|
|
6886
7087
|
const dictationButtonTitle = isDictationSupported ? dictationButtonLabel : "Voice dictation is not supported in this browser";
|
|
6887
7088
|
const sendButtonLabel = isRunning && !hasComposerDraft ? "Stop answering" : isBusy ? "Queue message" : "Send message";
|
|
6888
|
-
return /* @__PURE__ */
|
|
6889
|
-
/* @__PURE__ */
|
|
6890
|
-
showHome ? /* @__PURE__ */
|
|
7089
|
+
return /* @__PURE__ */ jsxs18(Fragment4, { children: [
|
|
7090
|
+
/* @__PURE__ */ jsxs18(ConversationViewport, { streamKey: activeStreamKey, children: [
|
|
7091
|
+
showHome ? /* @__PURE__ */ jsxs18("div", { className: "ha-empty", children: [
|
|
6891
7092
|
/* @__PURE__ */ jsx26("h2", { children: options.greeting }),
|
|
6892
7093
|
/* @__PURE__ */ jsx26("p", { children: "Live answers with charts, metrics, and tables." })
|
|
6893
7094
|
] }) : chatState.messages.map((message) => /* @__PURE__ */ jsx26(
|
|
@@ -6917,13 +7118,13 @@ function ChatRuntime({
|
|
|
6917
7118
|
message.id
|
|
6918
7119
|
)),
|
|
6919
7120
|
standaloneStatus && (active || standaloneStatus !== DEFAULT_ACTIVITY_STATUS) ? /* @__PURE__ */ jsx26("div", { className: "ha-message", "data-role": "assistant", "data-stream-anchor": "true", children: /* @__PURE__ */ jsx26("div", { className: "ha-message-body", children: standaloneStatus === DEFAULT_ACTIVITY_STATUS ? /* @__PURE__ */ jsx26(StartupActivityStatus, {}, activeStreamKey ?? conversationId) : /* @__PURE__ */ jsx26(ActivityStatus, { label: standaloneStatus }) }) }) : null,
|
|
6920
|
-
chatState.error || recoveryError ? /* @__PURE__ */
|
|
7121
|
+
chatState.error || recoveryError ? /* @__PURE__ */ jsxs18("div", { className: "ha-error", role: "alert", children: [
|
|
6921
7122
|
/* @__PURE__ */ jsx26("span", { children: "The request could not be completed." }),
|
|
6922
7123
|
/* @__PURE__ */ jsx26("button", { type: "button", onClick: retryLastResponse, children: "Retry" })
|
|
6923
7124
|
] }) : null
|
|
6924
7125
|
] }),
|
|
6925
|
-
/* @__PURE__ */
|
|
6926
|
-
showHome && visibleSuggestedPrompts.length > 0 ? /* @__PURE__ */ jsx26("div", { "aria-label": "Suggested prompts", className: "ha-suggestions", role: "group", children: visibleSuggestedPrompts.map((prompt, index) => /* @__PURE__ */
|
|
7126
|
+
/* @__PURE__ */ jsxs18("form", { className: "ha-composer-wrap", onSubmit: submit, children: [
|
|
7127
|
+
showHome && visibleSuggestedPrompts.length > 0 ? /* @__PURE__ */ jsx26("div", { "aria-label": "Suggested prompts", className: "ha-suggestions", role: "group", children: visibleSuggestedPrompts.map((prompt, index) => /* @__PURE__ */ jsxs18(
|
|
6927
7128
|
"button",
|
|
6928
7129
|
{
|
|
6929
7130
|
className: "ha-suggestion",
|
|
@@ -6932,7 +7133,7 @@ function ChatRuntime({
|
|
|
6932
7133
|
onClick: () => submitComposerMessage(prompt),
|
|
6933
7134
|
children: [
|
|
6934
7135
|
/* @__PURE__ */ jsx26("span", { children: prompt }),
|
|
6935
|
-
options.suggestedPromptShortcuts ? /* @__PURE__ */
|
|
7136
|
+
options.suggestedPromptShortcuts ? /* @__PURE__ */ jsxs18("span", { "aria-hidden": "true", className: "ha-suggestion-shortcut", children: [
|
|
6936
7137
|
/* @__PURE__ */ jsx26("kbd", { children: "Ctrl" }),
|
|
6937
7138
|
/* @__PURE__ */ jsx26("kbd", { children: index + 1 })
|
|
6938
7139
|
] }) : /* @__PURE__ */ jsx26(ArrowUpRight, { "aria-hidden": "true" })
|
|
@@ -6956,7 +7157,7 @@ function ChatRuntime({
|
|
|
6956
7157
|
onSendNow: sendQueuedMessageNow
|
|
6957
7158
|
}
|
|
6958
7159
|
),
|
|
6959
|
-
/* @__PURE__ */
|
|
7160
|
+
/* @__PURE__ */ jsxs18(
|
|
6960
7161
|
ComposerFileDropzone,
|
|
6961
7162
|
{
|
|
6962
7163
|
className: "@container ha-composer",
|
|
@@ -7038,7 +7239,7 @@ function ChatRuntime({
|
|
|
7038
7239
|
}
|
|
7039
7240
|
}
|
|
7040
7241
|
),
|
|
7041
|
-
isDictating ? /* @__PURE__ */ jsx26("div", { className: "ha-dictation-session", children: isDictationTranscribing ? /* @__PURE__ */ jsx26("span", { className: "ha-dictation-status", role: "status", children: "Transcribing\u2026" }) : /* @__PURE__ */
|
|
7242
|
+
isDictating ? /* @__PURE__ */ jsx26("div", { className: "ha-dictation-session", children: isDictationTranscribing ? /* @__PURE__ */ jsx26("span", { className: "ha-dictation-status", role: "status", children: "Transcribing\u2026" }) : /* @__PURE__ */ jsxs18(Fragment4, { children: [
|
|
7042
7243
|
/* @__PURE__ */ jsx26(
|
|
7043
7244
|
VoiceLiveWaveform,
|
|
7044
7245
|
{
|
|
@@ -7080,7 +7281,7 @@ function ChatRuntime({
|
|
|
7080
7281
|
onChange: setSelectedModelId
|
|
7081
7282
|
}
|
|
7082
7283
|
) : null,
|
|
7083
|
-
options.composerDictation ? /* @__PURE__ */
|
|
7284
|
+
options.composerDictation ? /* @__PURE__ */ jsxs18(
|
|
7084
7285
|
"button",
|
|
7085
7286
|
{
|
|
7086
7287
|
"aria-keyshortcuts": isDictationSupported ? DICTATION_KEYBOARD_SHORTCUT : void 0,
|
|
@@ -7105,7 +7306,7 @@ function ChatRuntime({
|
|
|
7105
7306
|
}
|
|
7106
7307
|
) : null,
|
|
7107
7308
|
attachmentError || options.composerDictation && dictationError ? /* @__PURE__ */ jsx26("span", { className: "ha-dictation-error", role: "alert", children: attachmentError ?? dictationError }) : null,
|
|
7108
|
-
isRunning && !hasComposerDraft ? /* @__PURE__ */
|
|
7309
|
+
isRunning && !hasComposerDraft ? /* @__PURE__ */ jsxs18(
|
|
7109
7310
|
"button",
|
|
7110
7311
|
{
|
|
7111
7312
|
"aria-keyshortcuts": COMPOSER_ACTION_KEYBOARD_SHORTCUT,
|
|
@@ -7120,7 +7321,7 @@ function ChatRuntime({
|
|
|
7120
7321
|
/* @__PURE__ */ jsx26(ComposerControlTooltip, { shortcut: COMPOSER_ACTION_SHORTCUT_LABEL, children: sendButtonLabel })
|
|
7121
7322
|
]
|
|
7122
7323
|
}
|
|
7123
|
-
) : /* @__PURE__ */
|
|
7324
|
+
) : /* @__PURE__ */ jsxs18(
|
|
7124
7325
|
"button",
|
|
7125
7326
|
{
|
|
7126
7327
|
"aria-keyshortcuts": COMPOSER_ACTION_KEYBOARD_SHORTCUT,
|
|
@@ -7176,9 +7377,11 @@ function Message({
|
|
|
7176
7377
|
const userAttachments = message.role === "user" ? message.parts.flatMap(
|
|
7177
7378
|
(part, index) => part.type === "file" ? [/* @__PURE__ */ jsx26(MessageAttachment, { file: part }, `${message.id}-attachment-${index}`)] : []
|
|
7178
7379
|
) : [];
|
|
7380
|
+
let latestContentPartIndex = -1;
|
|
7179
7381
|
const content = message.parts.reduce((items, part, index) => {
|
|
7180
7382
|
if (part.type === "text") {
|
|
7181
7383
|
if (!part.text.trim()) return items;
|
|
7384
|
+
latestContentPartIndex = index;
|
|
7182
7385
|
return [
|
|
7183
7386
|
...items,
|
|
7184
7387
|
message.role === "assistant" ? /* @__PURE__ */ jsx26(
|
|
@@ -7196,9 +7399,11 @@ function Message({
|
|
|
7196
7399
|
}
|
|
7197
7400
|
if (part.type === "file") {
|
|
7198
7401
|
if (message.role === "user") return items;
|
|
7402
|
+
latestContentPartIndex = index;
|
|
7199
7403
|
return [...items, /* @__PURE__ */ jsx26(MessageAttachment, { file: part }, `${message.id}-file-${index}`)];
|
|
7200
7404
|
}
|
|
7201
7405
|
if (part.type === "data-component") {
|
|
7406
|
+
latestContentPartIndex = index;
|
|
7202
7407
|
return [
|
|
7203
7408
|
...items,
|
|
7204
7409
|
/* @__PURE__ */ jsx26(
|
|
@@ -7219,6 +7424,7 @@ function Message({
|
|
|
7219
7424
|
if (clientToolName && clientTool?.needsApproval) {
|
|
7220
7425
|
const toolPart = part;
|
|
7221
7426
|
if (toolPart.state !== "input-available" || toolDecisions[toolPart.toolCallId]) return items;
|
|
7427
|
+
latestContentPartIndex = index;
|
|
7222
7428
|
return [
|
|
7223
7429
|
...items,
|
|
7224
7430
|
/* @__PURE__ */ jsx26(
|
|
@@ -7235,6 +7441,10 @@ function Message({
|
|
|
7235
7441
|
}
|
|
7236
7442
|
return items;
|
|
7237
7443
|
}, []);
|
|
7444
|
+
const hasResponseStartedAfterLatestActivity = hasResponseAfterLatestActivity(activity, {
|
|
7445
|
+
hasContent: content.length > 0,
|
|
7446
|
+
latestContentPartIndex
|
|
7447
|
+
});
|
|
7238
7448
|
const visibleSources = getVisibleMessageSources(sources, {
|
|
7239
7449
|
hasContent: content.length > 0,
|
|
7240
7450
|
isStreaming
|
|
@@ -7243,7 +7453,7 @@ function Message({
|
|
|
7243
7453
|
return null;
|
|
7244
7454
|
}
|
|
7245
7455
|
if (message.role === "user") {
|
|
7246
|
-
return /* @__PURE__ */
|
|
7456
|
+
return /* @__PURE__ */ jsxs18(
|
|
7247
7457
|
"div",
|
|
7248
7458
|
{
|
|
7249
7459
|
className: "ha-message",
|
|
@@ -7266,11 +7476,12 @@ function Message({
|
|
|
7266
7476
|
className: "ha-message",
|
|
7267
7477
|
"data-role": "assistant",
|
|
7268
7478
|
"data-stream-anchor": isStreaming ? true : void 0,
|
|
7269
|
-
children: /* @__PURE__ */
|
|
7479
|
+
children: /* @__PURE__ */ jsxs18("div", { className: "ha-message-body", children: [
|
|
7270
7480
|
activity.length > 0 ? /* @__PURE__ */ jsx26(
|
|
7271
7481
|
ActivityTrail,
|
|
7272
7482
|
{
|
|
7273
7483
|
completedAt: activityTiming?.completedAt,
|
|
7484
|
+
hasResponseStarted: hasResponseStartedAfterLatestActivity,
|
|
7274
7485
|
isStreaming,
|
|
7275
7486
|
items: activity,
|
|
7276
7487
|
progress,
|
|
@@ -7334,7 +7545,7 @@ function useAgentTransport({
|
|
|
7334
7545
|
const session = restoreTriggerSession(stored, bootstrapStatus);
|
|
7335
7546
|
return session ? { [conversationId]: session } : void 0;
|
|
7336
7547
|
}, [bootstrapStatus, conversationId, sessionKey]);
|
|
7337
|
-
const reportedReconnectRef =
|
|
7548
|
+
const reportedReconnectRef = useRef14(false);
|
|
7338
7549
|
const authorizedFetch = useCallback11(
|
|
7339
7550
|
(url, init = {}) => fetchWithAgentAuthorization(tokenManager, url, init),
|
|
7340
7551
|
[tokenManager]
|