@dataverse-kit/agent-kit 0.2.0 → 0.3.0
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/README.md +42 -2
- package/dist/index.cjs +882 -397
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +171 -6
- package/dist/index.d.ts +171 -6
- package/dist/index.mjs +880 -390
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/conversation/MessageList.tsx
|
|
2
|
-
import * as
|
|
2
|
+
import * as React11 from "react";
|
|
3
3
|
import { Button as Button3, makeStyles as makeStyles10, tokens as tokens9 } from "@fluentui/react-components";
|
|
4
4
|
import { ArrowDownRegular } from "@fluentui/react-icons";
|
|
5
5
|
|
|
@@ -585,12 +585,40 @@ function useRovingTabindex(options) {
|
|
|
585
585
|
return { activeIndex, setActiveIndex, getItemProps };
|
|
586
586
|
}
|
|
587
587
|
|
|
588
|
-
// src/
|
|
588
|
+
// src/a11y/useReturnFocus.ts
|
|
589
589
|
import * as React4 from "react";
|
|
590
|
+
function useReturnFocus({ open, containerRef, manageInitialFocus = true }) {
|
|
591
|
+
const openerRef = React4.useRef(null);
|
|
592
|
+
const wasOpen = React4.useRef(open);
|
|
593
|
+
React4.useEffect(() => {
|
|
594
|
+
const container = containerRef.current;
|
|
595
|
+
const doc = container?.ownerDocument ?? (typeof document !== "undefined" ? document : void 0);
|
|
596
|
+
if (!doc) return;
|
|
597
|
+
if (open && !wasOpen.current) {
|
|
598
|
+
const active = doc.activeElement;
|
|
599
|
+
openerRef.current = active instanceof HTMLElement && active !== doc.body ? active : null;
|
|
600
|
+
if (manageInitialFocus && container) {
|
|
601
|
+
const first = container.querySelector(
|
|
602
|
+
'a[href],button:not([disabled]),input:not([disabled]),textarea:not([disabled]),select:not([disabled]),[tabindex]:not([tabindex="-1"])'
|
|
603
|
+
);
|
|
604
|
+
(first ?? container).focus();
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
if (!open && wasOpen.current) {
|
|
608
|
+
const opener = openerRef.current;
|
|
609
|
+
if (opener && opener.isConnected) opener.focus();
|
|
610
|
+
openerRef.current = null;
|
|
611
|
+
}
|
|
612
|
+
wasOpen.current = open;
|
|
613
|
+
}, [open, containerRef, manageInitialFocus]);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// src/hooks/useStickyScroll.ts
|
|
617
|
+
import * as React5 from "react";
|
|
590
618
|
function useStickyScroll(ref, messageCount) {
|
|
591
|
-
const wasPinnedRef =
|
|
592
|
-
const [isPinned, setIsPinned] =
|
|
593
|
-
const onScroll =
|
|
619
|
+
const wasPinnedRef = React5.useRef(true);
|
|
620
|
+
const [isPinned, setIsPinned] = React5.useState(true);
|
|
621
|
+
const onScroll = React5.useCallback(() => {
|
|
594
622
|
const el = ref.current;
|
|
595
623
|
if (!el) return;
|
|
596
624
|
const pinned = shouldStickToBottom({
|
|
@@ -601,14 +629,14 @@ function useStickyScroll(ref, messageCount) {
|
|
|
601
629
|
wasPinnedRef.current = pinned;
|
|
602
630
|
setIsPinned(pinned);
|
|
603
631
|
}, [ref]);
|
|
604
|
-
const scrollToBottom =
|
|
632
|
+
const scrollToBottom = React5.useCallback(() => {
|
|
605
633
|
const el = ref.current;
|
|
606
634
|
if (!el) return;
|
|
607
635
|
el.scrollTo({ top: el.scrollHeight, behavior: "auto" });
|
|
608
636
|
wasPinnedRef.current = true;
|
|
609
637
|
setIsPinned(true);
|
|
610
638
|
}, [ref]);
|
|
611
|
-
|
|
639
|
+
React5.useEffect(() => {
|
|
612
640
|
if (!wasPinnedRef.current) return;
|
|
613
641
|
const el = ref.current;
|
|
614
642
|
if (!el) return;
|
|
@@ -618,30 +646,30 @@ function useStickyScroll(ref, messageCount) {
|
|
|
618
646
|
}
|
|
619
647
|
|
|
620
648
|
// src/hooks/useConversation.ts
|
|
621
|
-
import * as
|
|
649
|
+
import * as React6 from "react";
|
|
622
650
|
var fallbackId = 0;
|
|
623
651
|
function useConversation(options) {
|
|
624
652
|
const { service, seed, grounding, conversationId, createId } = options;
|
|
625
|
-
const [state, setState] =
|
|
626
|
-
const [announcement, setAnnouncement] =
|
|
627
|
-
const abortRef =
|
|
628
|
-
const stateRef =
|
|
653
|
+
const [state, setState] = React6.useState(() => initialConversation(seed));
|
|
654
|
+
const [announcement, setAnnouncement] = React6.useState(NO_ANNOUNCEMENT);
|
|
655
|
+
const abortRef = React6.useRef(null);
|
|
656
|
+
const stateRef = React6.useRef(state);
|
|
629
657
|
stateRef.current = state;
|
|
630
|
-
const nextId =
|
|
658
|
+
const nextId = React6.useCallback(
|
|
631
659
|
() => createId?.() ?? `m${++fallbackId}-${Date.now().toString(36)}`,
|
|
632
660
|
[createId]
|
|
633
661
|
);
|
|
634
|
-
const commit =
|
|
662
|
+
const commit = React6.useCallback((next) => {
|
|
635
663
|
const previous = stateRef.current;
|
|
636
664
|
stateRef.current = next;
|
|
637
665
|
setState(next);
|
|
638
666
|
const derived = deriveAnnouncement(next, previous);
|
|
639
667
|
if (derived.polite || derived.assertive) setAnnouncement(derived);
|
|
640
668
|
}, []);
|
|
641
|
-
const cancel =
|
|
669
|
+
const cancel = React6.useCallback(() => {
|
|
642
670
|
abortRef.current?.abort();
|
|
643
671
|
}, []);
|
|
644
|
-
const send =
|
|
672
|
+
const send = React6.useCallback(
|
|
645
673
|
async (text, attachments) => {
|
|
646
674
|
if (!text.trim()) return;
|
|
647
675
|
abortRef.current?.abort();
|
|
@@ -678,13 +706,13 @@ function useConversation(options) {
|
|
|
678
706
|
},
|
|
679
707
|
[service, grounding, conversationId, nextId, commit]
|
|
680
708
|
);
|
|
681
|
-
|
|
709
|
+
React6.useEffect(() => () => abortRef.current?.abort(), []);
|
|
682
710
|
const busy = state.status === "connecting" || state.status === "streaming";
|
|
683
711
|
return { state, announcement, busy, send, cancel };
|
|
684
712
|
}
|
|
685
713
|
|
|
686
714
|
// src/conversation/MessageBubble.tsx
|
|
687
|
-
import * as
|
|
715
|
+
import * as React10 from "react";
|
|
688
716
|
import { Avatar, makeStyles as makeStyles7, mergeClasses as mergeClasses4, tokens as tokens6 } from "@fluentui/react-components";
|
|
689
717
|
|
|
690
718
|
// src/conversation/StreamingText.tsx
|
|
@@ -761,7 +789,7 @@ function ActionToolbar({ actions, label, className }) {
|
|
|
761
789
|
}
|
|
762
790
|
|
|
763
791
|
// src/internal/CardSurface.tsx
|
|
764
|
-
import * as
|
|
792
|
+
import * as React7 from "react";
|
|
765
793
|
import { makeStyles as makeStyles4, mergeClasses as mergeClasses2, tokens as tokens3 } from "@fluentui/react-components";
|
|
766
794
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
767
795
|
var useStyles3 = makeStyles4({
|
|
@@ -777,7 +805,7 @@ var useStyles3 = makeStyles4({
|
|
|
777
805
|
},
|
|
778
806
|
attention: { borderLeft: `3px solid ${tokens3.colorBrandStroke1}` }
|
|
779
807
|
});
|
|
780
|
-
var CardSurface =
|
|
808
|
+
var CardSurface = React7.forwardRef(
|
|
781
809
|
function CardSurface2({ emphasis = "none", className, children, ...rest }, ref) {
|
|
782
810
|
const styles = useStyles3();
|
|
783
811
|
return /* @__PURE__ */ jsx4(
|
|
@@ -793,7 +821,7 @@ var CardSurface = React6.forwardRef(
|
|
|
793
821
|
);
|
|
794
822
|
|
|
795
823
|
// src/internal/ConfirmInline.tsx
|
|
796
|
-
import * as
|
|
824
|
+
import * as React8 from "react";
|
|
797
825
|
import { Button as Button2, makeStyles as makeStyles5, tokens as tokens4, Text } from "@fluentui/react-components";
|
|
798
826
|
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
799
827
|
var useStyles4 = makeStyles5({
|
|
@@ -804,11 +832,11 @@ var FOCUSABLE = 'a[href],button:not([disabled]),input:not([disabled]),textarea:n
|
|
|
804
832
|
function ConfirmInline(props) {
|
|
805
833
|
const { open, title, body, confirmLabel = "Confirm", cancelLabel = "Cancel", destructive, onConfirm, onCancel } = props;
|
|
806
834
|
const styles = useStyles4();
|
|
807
|
-
const ref =
|
|
808
|
-
const returnTo =
|
|
809
|
-
const titleId =
|
|
810
|
-
const bodyId =
|
|
811
|
-
|
|
835
|
+
const ref = React8.useRef(null);
|
|
836
|
+
const returnTo = React8.useRef(null);
|
|
837
|
+
const titleId = React8.useId();
|
|
838
|
+
const bodyId = React8.useId();
|
|
839
|
+
React8.useEffect(() => {
|
|
812
840
|
if (!open) return;
|
|
813
841
|
returnTo.current = document.activeElement ?? null;
|
|
814
842
|
const first = ref.current?.querySelector(FOCUSABLE);
|
|
@@ -863,7 +891,7 @@ function ConfirmInline(props) {
|
|
|
863
891
|
}
|
|
864
892
|
|
|
865
893
|
// src/internal/Disclosure.tsx
|
|
866
|
-
import * as
|
|
894
|
+
import * as React9 from "react";
|
|
867
895
|
import { makeStyles as makeStyles6, tokens as tokens5, mergeClasses as mergeClasses3 } from "@fluentui/react-components";
|
|
868
896
|
import { ChevronRightRegular, ChevronDownRegular } from "@fluentui/react-icons";
|
|
869
897
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
@@ -891,7 +919,7 @@ function Disclosure({
|
|
|
891
919
|
className
|
|
892
920
|
}) {
|
|
893
921
|
const styles = useStyles5();
|
|
894
|
-
const [open, setOpen] =
|
|
922
|
+
const [open, setOpen] = React9.useState(defaultOpen);
|
|
895
923
|
const panelId = `${id}-panel`;
|
|
896
924
|
return /* @__PURE__ */ jsxs4("div", { className, children: [
|
|
897
925
|
/* @__PURE__ */ jsxs4(
|
|
@@ -988,7 +1016,7 @@ function MessageBubble(props) {
|
|
|
988
1016
|
const { message, author, isRunStart = true, locale, ...actionHandlers } = props;
|
|
989
1017
|
const styles = useStyles6();
|
|
990
1018
|
const hidden = useVisuallyHiddenStyles();
|
|
991
|
-
const [revealed, setRevealed] =
|
|
1019
|
+
const [revealed, setRevealed] = React10.useState(false);
|
|
992
1020
|
const own = message.role === "user";
|
|
993
1021
|
const name = author?.displayName ?? (own ? "You" : message.provider ?? "Assistant");
|
|
994
1022
|
const time = new Intl.DateTimeFormat(locale, { timeStyle: "short" }).format(new Date(message.createdAt));
|
|
@@ -1126,21 +1154,21 @@ function MessageList(props) {
|
|
|
1126
1154
|
...actionHandlers
|
|
1127
1155
|
} = props;
|
|
1128
1156
|
const styles = useStyles9();
|
|
1129
|
-
const scrollerRef =
|
|
1157
|
+
const scrollerRef = React11.useRef(null);
|
|
1130
1158
|
const { onScroll, scrollToBottom, isPinned } = useStickyScroll(scrollerRef, messages.length);
|
|
1131
|
-
const byId =
|
|
1159
|
+
const byId = React11.useMemo(
|
|
1132
1160
|
() => new Map((participants ?? []).map((p) => [p.id, p])),
|
|
1133
1161
|
[participants]
|
|
1134
1162
|
);
|
|
1135
|
-
const runStarts =
|
|
1163
|
+
const runStarts = React11.useMemo(() => {
|
|
1136
1164
|
const groups = groupMessages(messages, { windowMs: groupWindowMs, timeZone });
|
|
1137
1165
|
return new Set(groups.map((g) => g.messageIds[0]));
|
|
1138
1166
|
}, [messages, groupWindowMs, timeZone]);
|
|
1139
|
-
const buckets =
|
|
1167
|
+
const buckets = React11.useMemo(
|
|
1140
1168
|
() => bucketByDay(messages, { timeZone, now }),
|
|
1141
1169
|
[messages, timeZone, now]
|
|
1142
1170
|
);
|
|
1143
|
-
const dividerBefore =
|
|
1171
|
+
const dividerBefore = React11.useMemo(() => {
|
|
1144
1172
|
const map = /* @__PURE__ */ new Map();
|
|
1145
1173
|
for (const bucket of buckets) map.set(bucket.messageIds[0], bucket.label);
|
|
1146
1174
|
return map;
|
|
@@ -1157,7 +1185,7 @@ function MessageList(props) {
|
|
|
1157
1185
|
"aria-label": "Conversation",
|
|
1158
1186
|
tabIndex: 0,
|
|
1159
1187
|
children: [
|
|
1160
|
-
messages.length === 0 ? emptyState ?? null : messages.map((message) => /* @__PURE__ */ jsxs8(
|
|
1188
|
+
messages.length === 0 ? emptyState ?? null : messages.map((message) => /* @__PURE__ */ jsxs8(React11.Fragment, { children: [
|
|
1161
1189
|
dividerBefore.has(message.id) ? /* @__PURE__ */ jsx11(DayDivider, { label: dividerBefore.get(message.id), locale }) : null,
|
|
1162
1190
|
/* @__PURE__ */ jsx11(
|
|
1163
1191
|
MessageBubble,
|
|
@@ -1189,20 +1217,77 @@ function MessageList(props) {
|
|
|
1189
1217
|
}
|
|
1190
1218
|
|
|
1191
1219
|
// src/conversation/Composer.tsx
|
|
1192
|
-
import * as
|
|
1193
|
-
import { Button as Button4, Textarea, makeStyles as makeStyles11, tokens as tokens10, Tooltip as Tooltip2 } from "@fluentui/react-components";
|
|
1220
|
+
import * as React12 from "react";
|
|
1221
|
+
import { Button as Button4, Textarea, makeStyles as makeStyles11, mergeClasses as mergeClasses5, tokens as tokens10, Tooltip as Tooltip2 } from "@fluentui/react-components";
|
|
1194
1222
|
import { SendRegular, StopRegular } from "@fluentui/react-icons";
|
|
1195
1223
|
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1224
|
+
var MAX_ROWS = 6;
|
|
1196
1225
|
var useStyles10 = makeStyles11({
|
|
1197
|
-
|
|
1198
|
-
display: "flex",
|
|
1199
|
-
gap: tokens10.spacingHorizontalS,
|
|
1200
|
-
alignItems: "flex-end",
|
|
1226
|
+
wrapper: {
|
|
1201
1227
|
padding: tokens10.spacingVerticalS,
|
|
1202
1228
|
borderTop: `1px solid ${tokens10.colorNeutralStroke2}`
|
|
1203
1229
|
},
|
|
1204
|
-
|
|
1205
|
-
|
|
1230
|
+
// The Teams send box: ONE rounded container holding the field and the affordances.
|
|
1231
|
+
box: {
|
|
1232
|
+
display: "flex",
|
|
1233
|
+
alignItems: "flex-end",
|
|
1234
|
+
gap: tokens10.spacingHorizontalXXS,
|
|
1235
|
+
paddingLeft: tokens10.spacingHorizontalS,
|
|
1236
|
+
paddingRight: tokens10.spacingHorizontalXXS,
|
|
1237
|
+
paddingTop: tokens10.spacingVerticalXXS,
|
|
1238
|
+
paddingBottom: tokens10.spacingVerticalXXS,
|
|
1239
|
+
borderRadius: tokens10.borderRadiusXLarge,
|
|
1240
|
+
border: `1px solid ${tokens10.colorNeutralStroke1}`,
|
|
1241
|
+
backgroundColor: tokens10.colorNeutralBackground1,
|
|
1242
|
+
// ★ The ring moves to the CONTAINER because the field's own indicator is suppressed below.
|
|
1243
|
+
// It is an `outline`, not a box-shadow, so forced-colors still paints it (a11y rule 5).
|
|
1244
|
+
":focus-within": {
|
|
1245
|
+
border: `1px solid ${tokens10.colorCompoundBrandStroke}`,
|
|
1246
|
+
outline: `2px solid ${tokens10.colorCompoundBrandStroke}`,
|
|
1247
|
+
outlineOffset: "-1px"
|
|
1248
|
+
}
|
|
1249
|
+
},
|
|
1250
|
+
boxDisabled: {
|
|
1251
|
+
backgroundColor: tokens10.colorNeutralBackgroundDisabled,
|
|
1252
|
+
border: `1px solid ${tokens10.colorNeutralStrokeDisabled}`
|
|
1253
|
+
},
|
|
1254
|
+
// Fluent's Textarea has no transparent appearance, so its chrome is removed here and the
|
|
1255
|
+
// container above supplies it. `::after` is Fluent's focus underline.
|
|
1256
|
+
field: {
|
|
1257
|
+
flexGrow: 1,
|
|
1258
|
+
minWidth: 0,
|
|
1259
|
+
backgroundColor: "transparent",
|
|
1260
|
+
border: "none",
|
|
1261
|
+
borderRadius: 0,
|
|
1262
|
+
"::after": { display: "none" }
|
|
1263
|
+
},
|
|
1264
|
+
fieldInner: {
|
|
1265
|
+
backgroundColor: "transparent",
|
|
1266
|
+
// ★ Fluent's Textarea ships `min-height: 52px` (measured). The affordance buttons are 32px,
|
|
1267
|
+
// so the default left the placeholder on one line and the icons on another — the single
|
|
1268
|
+
// visible difference from the Teams reference. Matching the button height puts them on
|
|
1269
|
+
// one baseline; growth past one row is then driven by `rows`, up to maxHeight.
|
|
1270
|
+
minHeight: "32px",
|
|
1271
|
+
maxHeight: "160px",
|
|
1272
|
+
paddingLeft: 0,
|
|
1273
|
+
paddingRight: 0
|
|
1274
|
+
},
|
|
1275
|
+
actions: {
|
|
1276
|
+
display: "flex",
|
|
1277
|
+
alignItems: "center",
|
|
1278
|
+
gap: tokens10.spacingHorizontalXXS
|
|
1279
|
+
// ★ No extra bottom padding: `alignItems: flex-end` on the box already pins this row to the
|
|
1280
|
+
// field's last line, and padding on top of it pushed the send glyph visibly below the
|
|
1281
|
+
// baseline on a single-row box (measured against the Teams reference).
|
|
1282
|
+
},
|
|
1283
|
+
divider: {
|
|
1284
|
+
width: "1px",
|
|
1285
|
+
alignSelf: "center",
|
|
1286
|
+
height: "20px",
|
|
1287
|
+
marginLeft: tokens10.spacingHorizontalXXS,
|
|
1288
|
+
marginRight: tokens10.spacingHorizontalXXS,
|
|
1289
|
+
backgroundColor: tokens10.colorNeutralStroke2
|
|
1290
|
+
}
|
|
1206
1291
|
});
|
|
1207
1292
|
function Composer(props) {
|
|
1208
1293
|
const {
|
|
@@ -1218,7 +1303,8 @@ function Composer(props) {
|
|
|
1218
1303
|
toolbar
|
|
1219
1304
|
} = props;
|
|
1220
1305
|
const styles = useStyles10();
|
|
1221
|
-
const
|
|
1306
|
+
const vh = useVisuallyHiddenStyles();
|
|
1307
|
+
const hintId = React12.useId();
|
|
1222
1308
|
const submit = () => {
|
|
1223
1309
|
const text = value.trim();
|
|
1224
1310
|
if (!text || busy || disabled) return;
|
|
@@ -1232,56 +1318,77 @@ function Composer(props) {
|
|
|
1232
1318
|
submit();
|
|
1233
1319
|
};
|
|
1234
1320
|
const hint = sendOn === "enter" ? "Press Enter to send, Shift plus Enter for a new line." : "Press Control or Command plus Enter to send.";
|
|
1235
|
-
|
|
1236
|
-
|
|
1321
|
+
const rows = Math.min(MAX_ROWS, Math.max(1, value.split("\n").length));
|
|
1322
|
+
return /* @__PURE__ */ jsxs9("div", { className: styles.wrapper, children: [
|
|
1323
|
+
/* @__PURE__ */ jsxs9("div", { className: mergeClasses5(styles.box, disabled && styles.boxDisabled), children: [
|
|
1237
1324
|
/* @__PURE__ */ jsx12(
|
|
1238
1325
|
Textarea,
|
|
1239
1326
|
{
|
|
1327
|
+
className: styles.field,
|
|
1240
1328
|
value,
|
|
1241
1329
|
onChange: (_, data) => onChange(data.value),
|
|
1242
1330
|
onKeyDown,
|
|
1243
1331
|
placeholder,
|
|
1244
1332
|
disabled,
|
|
1245
1333
|
maxLength,
|
|
1246
|
-
resize: "
|
|
1334
|
+
resize: "none",
|
|
1335
|
+
appearance: "outline",
|
|
1247
1336
|
"aria-label": placeholder,
|
|
1248
1337
|
"aria-describedby": hintId,
|
|
1249
|
-
textarea: { "aria-multiline": true }
|
|
1338
|
+
textarea: { "aria-multiline": true, rows, className: styles.fieldInner }
|
|
1250
1339
|
}
|
|
1251
1340
|
),
|
|
1252
|
-
/* @__PURE__ */
|
|
1341
|
+
/* @__PURE__ */ jsxs9("div", { className: styles.actions, children: [
|
|
1342
|
+
toolbar,
|
|
1343
|
+
toolbar ? /* @__PURE__ */ jsx12("span", { className: styles.divider, "aria-hidden": "true" }) : null,
|
|
1344
|
+
busy && onStop ? /* @__PURE__ */ jsx12(Tooltip2, { content: "Stop generating", relationship: "label", withArrow: true, children: /* @__PURE__ */ jsx12(Button4, { appearance: "subtle", icon: /* @__PURE__ */ jsx12(StopRegular, {}), onClick: onStop }) }) : /* @__PURE__ */ jsx12(Tooltip2, { content: "Send", relationship: "label", withArrow: true, children: /* @__PURE__ */ jsx12(
|
|
1345
|
+
Button4,
|
|
1346
|
+
{
|
|
1347
|
+
appearance: "subtle",
|
|
1348
|
+
icon: /* @__PURE__ */ jsx12(SendRegular, {}),
|
|
1349
|
+
onClick: submit,
|
|
1350
|
+
disabled: !value.trim() || busy || disabled
|
|
1351
|
+
}
|
|
1352
|
+
) })
|
|
1353
|
+
] })
|
|
1253
1354
|
] }),
|
|
1254
|
-
|
|
1255
|
-
busy && onStop ? /* @__PURE__ */ jsx12(Tooltip2, { content: "Stop generating", relationship: "label", withArrow: true, children: /* @__PURE__ */ jsx12(Button4, { appearance: "secondary", icon: /* @__PURE__ */ jsx12(StopRegular, {}), onClick: onStop }) }) : /* @__PURE__ */ jsx12(Tooltip2, { content: "Send", relationship: "label", withArrow: true, children: /* @__PURE__ */ jsx12(
|
|
1256
|
-
Button4,
|
|
1257
|
-
{
|
|
1258
|
-
appearance: "primary",
|
|
1259
|
-
icon: /* @__PURE__ */ jsx12(SendRegular, {}),
|
|
1260
|
-
onClick: submit,
|
|
1261
|
-
disabled: !value.trim() || busy || disabled
|
|
1262
|
-
}
|
|
1263
|
-
) })
|
|
1355
|
+
/* @__PURE__ */ jsx12("span", { id: hintId, className: vh.root, children: hint })
|
|
1264
1356
|
] });
|
|
1265
1357
|
}
|
|
1266
1358
|
|
|
1267
1359
|
// src/conversation/SuggestedPrompts.tsx
|
|
1268
|
-
import { Button as Button5, makeStyles as makeStyles12, tokens as tokens11 } from "@fluentui/react-components";
|
|
1360
|
+
import { Button as Button5, makeStyles as makeStyles12, mergeClasses as mergeClasses6, tokens as tokens11 } from "@fluentui/react-components";
|
|
1269
1361
|
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1270
1362
|
var useStyles11 = makeStyles12({
|
|
1271
1363
|
root: { display: "flex", flexWrap: "wrap", gap: tokens11.spacingHorizontalXS, padding: tokens11.spacingVerticalXS },
|
|
1364
|
+
// ★ The heading is `width: 100%`, so it takes the PARENT's text-align while the chips take the
|
|
1365
|
+
// flex row's justification. That split is why the label could look centred while the chips
|
|
1366
|
+
// stayed left-packed — the two are aligned by different mechanisms and must both be set.
|
|
1367
|
+
center: { justifyContent: "center" },
|
|
1368
|
+
headingCenter: { textAlign: "center" },
|
|
1272
1369
|
heading: { width: "100%", fontSize: tokens11.fontSizeBase200, color: tokens11.colorNeutralForeground3 }
|
|
1273
1370
|
});
|
|
1274
1371
|
function SuggestedPrompts({
|
|
1275
1372
|
prompts,
|
|
1276
1373
|
onPick,
|
|
1277
|
-
heading = "Suggested follow-ups"
|
|
1374
|
+
heading = "Suggested follow-ups",
|
|
1375
|
+
align = "start"
|
|
1278
1376
|
}) {
|
|
1279
1377
|
const styles = useStyles11();
|
|
1280
1378
|
if (prompts.length === 0) return null;
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1379
|
+
const centered = align === "center";
|
|
1380
|
+
return /* @__PURE__ */ jsxs10(
|
|
1381
|
+
"div",
|
|
1382
|
+
{
|
|
1383
|
+
className: mergeClasses6(styles.root, centered && styles.center),
|
|
1384
|
+
role: "group",
|
|
1385
|
+
"aria-label": heading,
|
|
1386
|
+
children: [
|
|
1387
|
+
/* @__PURE__ */ jsx13("span", { className: mergeClasses6(styles.heading, centered && styles.headingCenter), children: heading }),
|
|
1388
|
+
prompts.map((prompt) => /* @__PURE__ */ jsx13(Button5, { size: "small", appearance: "outline", onClick: () => onPick(prompt), children: prompt }, prompt))
|
|
1389
|
+
]
|
|
1390
|
+
}
|
|
1391
|
+
);
|
|
1285
1392
|
}
|
|
1286
1393
|
|
|
1287
1394
|
// src/conversation/EmptyConversation.tsx
|
|
@@ -1310,7 +1417,7 @@ function EmptyConversation({
|
|
|
1310
1417
|
return /* @__PURE__ */ jsxs11("div", { className: styles.root, children: [
|
|
1311
1418
|
/* @__PURE__ */ jsx14(Text2, { as: "h2", size: 500, weight: "semibold", children: title }),
|
|
1312
1419
|
/* @__PURE__ */ jsx14(Text2, { children: description }),
|
|
1313
|
-
onPick && prompts.length > 0 ? /* @__PURE__ */ jsx14(SuggestedPrompts, { prompts, onPick, heading: "Try one of these" }) : null
|
|
1420
|
+
onPick && prompts.length > 0 ? /* @__PURE__ */ jsx14(SuggestedPrompts, { prompts, onPick, heading: "Try one of these", align: "center" }) : null
|
|
1314
1421
|
] });
|
|
1315
1422
|
}
|
|
1316
1423
|
|
|
@@ -1460,14 +1567,14 @@ function UsageMeter({
|
|
|
1460
1567
|
}
|
|
1461
1568
|
|
|
1462
1569
|
// src/ops/ThrottleNotice.tsx
|
|
1463
|
-
import * as
|
|
1570
|
+
import * as React13 from "react";
|
|
1464
1571
|
import { MessageBar as MessageBar3, MessageBarBody as MessageBarBody3, MessageBarTitle as MessageBarTitle3, MessageBarActions as MessageBarActions3, Button as Button8 } from "@fluentui/react-components";
|
|
1465
1572
|
import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1466
1573
|
function ThrottleNotice({ failure, onRetry, now = Date.now }) {
|
|
1467
1574
|
const retryAfterMs = failure?.retryAfterMs;
|
|
1468
1575
|
const eligible = Boolean(failure?.recoverable && retryAfterMs && retryAfterMs > 0);
|
|
1469
|
-
const [remaining, setRemaining] =
|
|
1470
|
-
|
|
1576
|
+
const [remaining, setRemaining] = React13.useState(retryAfterMs ?? 0);
|
|
1577
|
+
React13.useEffect(() => {
|
|
1471
1578
|
if (!eligible) return;
|
|
1472
1579
|
const deadline = now() + (retryAfterMs ?? 0);
|
|
1473
1580
|
setRemaining(retryAfterMs ?? 0);
|
|
@@ -1526,7 +1633,7 @@ function AgentPicker({
|
|
|
1526
1633
|
}
|
|
1527
1634
|
|
|
1528
1635
|
// src/ops/RunTimeline.tsx
|
|
1529
|
-
import * as
|
|
1636
|
+
import * as React14 from "react";
|
|
1530
1637
|
import { makeStyles as makeStyles15, tokens as tokens14, Text as Text3 } from "@fluentui/react-components";
|
|
1531
1638
|
import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1532
1639
|
var useStyles14 = makeStyles15({
|
|
@@ -1546,7 +1653,7 @@ var TOOL_STATUS = {
|
|
|
1546
1653
|
};
|
|
1547
1654
|
function RunTimeline({ message, defaultOpen = false }) {
|
|
1548
1655
|
const styles = useStyles14();
|
|
1549
|
-
const id =
|
|
1656
|
+
const id = React14.useId();
|
|
1550
1657
|
const calls = message.toolCalls ?? [];
|
|
1551
1658
|
const sources = message.sources ?? [];
|
|
1552
1659
|
const hasAnything = calls.length > 0 || sources.length > 0 || message.usage || message.failure;
|
|
@@ -1654,18 +1761,397 @@ function AgentOpsPanel(props) {
|
|
|
1654
1761
|
] });
|
|
1655
1762
|
}
|
|
1656
1763
|
|
|
1764
|
+
// src/support/AgentLauncher.tsx
|
|
1765
|
+
import { makeStyles as makeStyles18, mergeClasses as mergeClasses7, tokens as tokens17, Badge as Badge3 } from "@fluentui/react-components";
|
|
1766
|
+
import { jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1767
|
+
var useStyles17 = makeStyles18({
|
|
1768
|
+
root: {
|
|
1769
|
+
position: "absolute",
|
|
1770
|
+
top: "30%",
|
|
1771
|
+
display: "flex",
|
|
1772
|
+
flexDirection: "column",
|
|
1773
|
+
zIndex: 100
|
|
1774
|
+
},
|
|
1775
|
+
right: { right: 0, alignItems: "flex-end" },
|
|
1776
|
+
left: { left: 0, alignItems: "flex-start" },
|
|
1777
|
+
hidden: { display: "none" },
|
|
1778
|
+
pill: {
|
|
1779
|
+
display: "flex",
|
|
1780
|
+
alignItems: "center",
|
|
1781
|
+
gap: tokens17.spacingHorizontalS,
|
|
1782
|
+
border: "none",
|
|
1783
|
+
cursor: "pointer",
|
|
1784
|
+
padding: `${tokens17.spacingVerticalM} ${tokens17.spacingHorizontalM}`,
|
|
1785
|
+
color: tokens17.colorNeutralForegroundOnBrand,
|
|
1786
|
+
fontFamily: tokens17.fontFamilyBase,
|
|
1787
|
+
fontSize: tokens17.fontSizeBase300,
|
|
1788
|
+
// ★ Collapsed shows the icon only; the LABEL IS STILL IN THE DOM (see below), so the
|
|
1789
|
+
// expand-on-hover is purely visual and the button is named for AT at every width.
|
|
1790
|
+
maxWidth: "44px",
|
|
1791
|
+
overflow: "hidden",
|
|
1792
|
+
whiteSpace: "nowrap",
|
|
1793
|
+
transitionProperty: "max-width",
|
|
1794
|
+
transitionDuration: tokens17.durationNormal,
|
|
1795
|
+
":hover": { maxWidth: "260px" },
|
|
1796
|
+
":hover .fui-launcher-label": { opacity: 1 },
|
|
1797
|
+
":focus-within .fui-launcher-label": { opacity: 1 },
|
|
1798
|
+
// ★ :focus-within as well as :hover — a keyboard user must get the same reveal, and this is
|
|
1799
|
+
// the affordance the M365 reference only shows on pointer hover.
|
|
1800
|
+
":focus-within": { maxWidth: "260px" },
|
|
1801
|
+
":focus-visible": { outline: `2px solid ${tokens17.colorStrokeFocus2}`, outlineOffset: "-2px" }
|
|
1802
|
+
},
|
|
1803
|
+
primary: { backgroundColor: tokens17.colorBrandBackground, ":hover": { backgroundColor: tokens17.colorBrandBackgroundHover, maxWidth: "260px" } },
|
|
1804
|
+
secondary: { backgroundColor: tokens17.colorBrandBackgroundStatic, ":hover": { backgroundColor: tokens17.colorBrandBackgroundStatic, maxWidth: "260px" } },
|
|
1805
|
+
firstRight: { borderTopLeftRadius: tokens17.borderRadiusXLarge },
|
|
1806
|
+
lastRight: { borderBottomLeftRadius: tokens17.borderRadiusXLarge },
|
|
1807
|
+
firstLeft: { borderTopRightRadius: tokens17.borderRadiusXLarge },
|
|
1808
|
+
lastLeft: { borderBottomRightRadius: tokens17.borderRadiusXLarge },
|
|
1809
|
+
// ★★ flexShrink BELONGS ON THE ICON, NOT THE TEXT. With it on the text, a collapsed 44px pill
|
|
1810
|
+
// (20px of content box after padding) gave the unshrinkable label the whole width and squeezed
|
|
1811
|
+
// the icon to ZERO — so the collapsed rail showed two clipped letters instead of a glyph.
|
|
1812
|
+
// MEASURED on Chromatic build 18: svgWidth 0, reported as "the content is off screen".
|
|
1813
|
+
icon: { flexShrink: 0, display: "flex", fontSize: "20px", lineHeight: 1 },
|
|
1814
|
+
// ★ The label FADES rather than relying on the clip. `overflow: hidden` cuts at the PADDING box,
|
|
1815
|
+
// so a 44px pill still showed ~4px of the first letter beside the icon. Opacity keeps the label
|
|
1816
|
+
// in the accessible name (see the class docstring) while hiding it from sight.
|
|
1817
|
+
text: {
|
|
1818
|
+
flexShrink: 1,
|
|
1819
|
+
minWidth: 0,
|
|
1820
|
+
opacity: 0,
|
|
1821
|
+
transitionProperty: "opacity",
|
|
1822
|
+
transitionDuration: tokens17.durationNormal,
|
|
1823
|
+
"@media (prefers-reduced-motion: reduce)": { transitionDuration: "1ms" }
|
|
1824
|
+
}
|
|
1825
|
+
});
|
|
1826
|
+
function AgentLauncher({
|
|
1827
|
+
items,
|
|
1828
|
+
onSelect,
|
|
1829
|
+
side = "right",
|
|
1830
|
+
label = "Assistant",
|
|
1831
|
+
hidden = false
|
|
1832
|
+
}) {
|
|
1833
|
+
const styles = useStyles17();
|
|
1834
|
+
if (items.length === 0) return null;
|
|
1835
|
+
return /* @__PURE__ */ jsx25(
|
|
1836
|
+
"div",
|
|
1837
|
+
{
|
|
1838
|
+
className: mergeClasses7(styles.root, side === "right" ? styles.right : styles.left, hidden && styles.hidden),
|
|
1839
|
+
role: "group",
|
|
1840
|
+
"aria-label": label,
|
|
1841
|
+
children: items.map((item, i) => /* @__PURE__ */ jsxs19(
|
|
1842
|
+
"button",
|
|
1843
|
+
{
|
|
1844
|
+
type: "button",
|
|
1845
|
+
onClick: () => onSelect(item.id),
|
|
1846
|
+
className: mergeClasses7(
|
|
1847
|
+
styles.pill,
|
|
1848
|
+
i === 0 ? styles.primary : styles.secondary,
|
|
1849
|
+
i === 0 && (side === "right" ? styles.firstRight : styles.firstLeft),
|
|
1850
|
+
i === items.length - 1 && (side === "right" ? styles.lastRight : styles.lastLeft)
|
|
1851
|
+
),
|
|
1852
|
+
children: [
|
|
1853
|
+
/* @__PURE__ */ jsx25("span", { className: styles.icon, "aria-hidden": "true", children: item.icon }),
|
|
1854
|
+
/* @__PURE__ */ jsx25("span", { className: mergeClasses7(styles.text, "fui-launcher-label"), children: item.label }),
|
|
1855
|
+
item.badgeCount ? /* @__PURE__ */ jsx25(Badge3, { appearance: "filled", color: "danger", children: item.badgeCount }) : null
|
|
1856
|
+
]
|
|
1857
|
+
},
|
|
1858
|
+
item.id
|
|
1859
|
+
))
|
|
1860
|
+
}
|
|
1861
|
+
);
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
// src/support/AssistantPanel.tsx
|
|
1865
|
+
import * as React15 from "react";
|
|
1866
|
+
import { Button as Button9, Switch, Text as Text6, Tooltip as Tooltip4, makeStyles as makeStyles19, mergeClasses as mergeClasses8, tokens as tokens18 } from "@fluentui/react-components";
|
|
1867
|
+
import { DismissRegular, ArrowDownloadRegular, SpeakerMuteRegular, Speaker2Regular } from "@fluentui/react-icons";
|
|
1868
|
+
import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1869
|
+
var useStyles18 = makeStyles19({
|
|
1870
|
+
root: {
|
|
1871
|
+
display: "flex",
|
|
1872
|
+
flexDirection: "column",
|
|
1873
|
+
height: "100%",
|
|
1874
|
+
minWidth: "320px",
|
|
1875
|
+
backgroundColor: tokens18.colorNeutralBackground1,
|
|
1876
|
+
borderLeft: `1px solid ${tokens18.colorNeutralStroke2}`,
|
|
1877
|
+
// ★ transform, not width/left — those two lay out on every frame and a transcript is an
|
|
1878
|
+
// expensive subtree to reflow 60 times a second.
|
|
1879
|
+
transform: "translateX(0)",
|
|
1880
|
+
transitionProperty: "transform",
|
|
1881
|
+
transitionDuration: tokens18.durationGentle,
|
|
1882
|
+
transitionTimingFunction: tokens18.curveDecelerateMid,
|
|
1883
|
+
// ★★ prefers-reduced-motion is honoured, and it is not decoration: a full-height panel
|
|
1884
|
+
// sliding across the viewport is exactly the vestibular trigger the setting exists for.
|
|
1885
|
+
"@media (prefers-reduced-motion: reduce)": { transitionDuration: "1ms" }
|
|
1886
|
+
},
|
|
1887
|
+
closed: {
|
|
1888
|
+
transform: "translateX(100%)",
|
|
1889
|
+
// ★ Hidden from AT as well as sight. A translated-off panel is still in the a11y tree and
|
|
1890
|
+
// still tabbable, so a keyboard user would tab into a drawer they cannot see.
|
|
1891
|
+
visibility: "hidden"
|
|
1892
|
+
},
|
|
1893
|
+
header: { display: "flex", alignItems: "center", gap: tokens18.spacingHorizontalS, padding: tokens18.spacingVerticalS },
|
|
1894
|
+
tabstrip: { display: "flex", gap: tokens18.spacingHorizontalXXS, flexGrow: 1 },
|
|
1895
|
+
tab: {
|
|
1896
|
+
display: "flex",
|
|
1897
|
+
alignItems: "center",
|
|
1898
|
+
gap: tokens18.spacingHorizontalXS,
|
|
1899
|
+
border: "none",
|
|
1900
|
+
background: "none",
|
|
1901
|
+
cursor: "pointer",
|
|
1902
|
+
padding: `${tokens18.spacingVerticalXS} ${tokens18.spacingHorizontalS}`,
|
|
1903
|
+
color: tokens18.colorNeutralForeground2,
|
|
1904
|
+
fontFamily: tokens18.fontFamilyBase,
|
|
1905
|
+
borderBottom: `2px solid transparent`,
|
|
1906
|
+
":focus-visible": { outline: `2px solid ${tokens18.colorStrokeFocus2}`, outlineOffset: "-2px" }
|
|
1907
|
+
},
|
|
1908
|
+
tabSelected: { color: tokens18.colorNeutralForeground1, borderBottom: `2px solid ${tokens18.colorCompoundBrandStroke}` },
|
|
1909
|
+
title: { padding: `0 ${tokens18.spacingHorizontalM} ${tokens18.spacingVerticalS}` },
|
|
1910
|
+
status: {
|
|
1911
|
+
padding: `${tokens18.spacingVerticalXS} ${tokens18.spacingHorizontalM}`,
|
|
1912
|
+
color: tokens18.colorNeutralForeground3,
|
|
1913
|
+
fontSize: tokens18.fontSizeBase200
|
|
1914
|
+
},
|
|
1915
|
+
body: { flexGrow: 1, minHeight: 0, display: "flex", flexDirection: "column" },
|
|
1916
|
+
footer: {
|
|
1917
|
+
display: "flex",
|
|
1918
|
+
alignItems: "center",
|
|
1919
|
+
justifyContent: "space-between",
|
|
1920
|
+
padding: tokens18.spacingVerticalXS,
|
|
1921
|
+
borderTop: `1px solid ${tokens18.colorNeutralStroke2}`
|
|
1922
|
+
}
|
|
1923
|
+
});
|
|
1924
|
+
function AssistantPanel(props) {
|
|
1925
|
+
const {
|
|
1926
|
+
title,
|
|
1927
|
+
tabs,
|
|
1928
|
+
activeTabId,
|
|
1929
|
+
onTabChange,
|
|
1930
|
+
onClose,
|
|
1931
|
+
enabled,
|
|
1932
|
+
onEnabledChange,
|
|
1933
|
+
status,
|
|
1934
|
+
onDownloadTranscript,
|
|
1935
|
+
muted,
|
|
1936
|
+
onMutedChange,
|
|
1937
|
+
children,
|
|
1938
|
+
open = true,
|
|
1939
|
+
onDismiss
|
|
1940
|
+
} = props;
|
|
1941
|
+
const styles = useStyles18();
|
|
1942
|
+
const baseId = React15.useId();
|
|
1943
|
+
const rootRef = React15.useRef(null);
|
|
1944
|
+
useReturnFocus({ open, containerRef: rootRef });
|
|
1945
|
+
const selectedIndex = Math.max(0, tabs.findIndex((t) => t.id === activeTabId));
|
|
1946
|
+
const roving = useRovingTabindex({
|
|
1947
|
+
itemCount: tabs.length,
|
|
1948
|
+
orientation: "horizontal",
|
|
1949
|
+
// ★ MANUAL ACTIVATION: arrows move focus, Enter/Space selects. That is what the kit's
|
|
1950
|
+
// useRovingTabindex does everywhere, and it is the APG pattern for tabs whose panel is not
|
|
1951
|
+
// free to render. Do not special-case it here; consistency is worth more than the one
|
|
1952
|
+
// keystroke, and a divergent strip is the kind of thing nobody notices until it is shipped.
|
|
1953
|
+
onActivate: (i) => tabs[i] && onTabChange(tabs[i].id)
|
|
1954
|
+
});
|
|
1955
|
+
const { setActiveIndex } = roving;
|
|
1956
|
+
React15.useEffect(() => {
|
|
1957
|
+
setActiveIndex(selectedIndex);
|
|
1958
|
+
}, [selectedIndex, setActiveIndex]);
|
|
1959
|
+
return /* @__PURE__ */ jsxs20(
|
|
1960
|
+
"section",
|
|
1961
|
+
{
|
|
1962
|
+
ref: rootRef,
|
|
1963
|
+
className: mergeClasses8(styles.root, !open && styles.closed),
|
|
1964
|
+
"aria-label": title,
|
|
1965
|
+
"aria-hidden": !open || void 0,
|
|
1966
|
+
tabIndex: -1,
|
|
1967
|
+
onKeyDown: (e) => {
|
|
1968
|
+
if (e.key !== "Escape" || !onDismiss) return;
|
|
1969
|
+
e.stopPropagation();
|
|
1970
|
+
onDismiss();
|
|
1971
|
+
},
|
|
1972
|
+
children: [
|
|
1973
|
+
/* @__PURE__ */ jsxs20("div", { className: styles.header, children: [
|
|
1974
|
+
/* @__PURE__ */ jsx26("div", { className: styles.tabstrip, role: "tablist", "aria-label": `${title} views`, children: tabs.map((tab, i) => {
|
|
1975
|
+
const item = roving.getItemProps(i);
|
|
1976
|
+
const selected = tab.id === activeTabId;
|
|
1977
|
+
return /* @__PURE__ */ jsxs20(
|
|
1978
|
+
"button",
|
|
1979
|
+
{
|
|
1980
|
+
type: "button",
|
|
1981
|
+
role: "tab",
|
|
1982
|
+
id: `${baseId}-tab-${tab.id}`,
|
|
1983
|
+
"aria-selected": selected,
|
|
1984
|
+
"aria-controls": `${baseId}-panel`,
|
|
1985
|
+
className: mergeClasses8(styles.tab, selected && styles.tabSelected),
|
|
1986
|
+
...item,
|
|
1987
|
+
onClick: () => {
|
|
1988
|
+
roving.setActiveIndex(i);
|
|
1989
|
+
onTabChange(tab.id);
|
|
1990
|
+
},
|
|
1991
|
+
children: [
|
|
1992
|
+
tab.icon,
|
|
1993
|
+
/* @__PURE__ */ jsx26("span", { children: tab.label })
|
|
1994
|
+
]
|
|
1995
|
+
},
|
|
1996
|
+
tab.id
|
|
1997
|
+
);
|
|
1998
|
+
}) }),
|
|
1999
|
+
onEnabledChange ? /* @__PURE__ */ jsx26(Switch, { checked: enabled ?? true, onChange: (_, d) => onEnabledChange(d.checked), label: enabled ?? true ? "On" : "Off" }) : null,
|
|
2000
|
+
onClose ? /* @__PURE__ */ jsx26(Tooltip4, { content: "Close", relationship: "label", withArrow: true, children: /* @__PURE__ */ jsx26(Button9, { appearance: "subtle", icon: /* @__PURE__ */ jsx26(DismissRegular, {}), onClick: onClose }) }) : null
|
|
2001
|
+
] }),
|
|
2002
|
+
/* @__PURE__ */ jsx26(Text6, { as: "h2", size: 600, weight: "semibold", className: styles.title, children: title }),
|
|
2003
|
+
/* @__PURE__ */ jsxs20("div", { className: styles.body, id: `${baseId}-panel`, role: "tabpanel", "aria-labelledby": `${baseId}-tab-${activeTabId}`, children: [
|
|
2004
|
+
status ? /* @__PURE__ */ jsx26("div", { className: styles.status, children: status }) : null,
|
|
2005
|
+
children
|
|
2006
|
+
] }),
|
|
2007
|
+
onDownloadTranscript || onMutedChange ? /* @__PURE__ */ jsxs20("div", { className: styles.footer, children: [
|
|
2008
|
+
onDownloadTranscript ? /* @__PURE__ */ jsx26(Tooltip4, { content: "Download transcript", relationship: "label", withArrow: true, children: /* @__PURE__ */ jsx26(Button9, { appearance: "subtle", icon: /* @__PURE__ */ jsx26(ArrowDownloadRegular, {}), onClick: onDownloadTranscript }) }) : /* @__PURE__ */ jsx26("span", {}),
|
|
2009
|
+
onMutedChange ? /* @__PURE__ */ jsx26(Tooltip4, { content: muted ? "Unmute" : "Mute", relationship: "label", withArrow: true, children: /* @__PURE__ */ jsx26(
|
|
2010
|
+
Button9,
|
|
2011
|
+
{
|
|
2012
|
+
appearance: "subtle",
|
|
2013
|
+
"aria-pressed": !!muted,
|
|
2014
|
+
icon: muted ? /* @__PURE__ */ jsx26(SpeakerMuteRegular, {}) : /* @__PURE__ */ jsx26(Speaker2Regular, {}),
|
|
2015
|
+
onClick: () => onMutedChange(!muted)
|
|
2016
|
+
}
|
|
2017
|
+
) }) : /* @__PURE__ */ jsx26("span", {})
|
|
2018
|
+
] }) : null
|
|
2019
|
+
]
|
|
2020
|
+
}
|
|
2021
|
+
);
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
// src/support/FeedbackPanel.tsx
|
|
2025
|
+
import * as React16 from "react";
|
|
2026
|
+
import {
|
|
2027
|
+
Button as Button10,
|
|
2028
|
+
Radio,
|
|
2029
|
+
RadioGroup,
|
|
2030
|
+
Text as Text7,
|
|
2031
|
+
Textarea as Textarea2,
|
|
2032
|
+
makeStyles as makeStyles20,
|
|
2033
|
+
mergeClasses as mergeClasses9,
|
|
2034
|
+
tokens as tokens19
|
|
2035
|
+
} from "@fluentui/react-components";
|
|
2036
|
+
import { StarRegular, StarFilled } from "@fluentui/react-icons";
|
|
2037
|
+
import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2038
|
+
var STARS = [1, 2, 3, 4, 5];
|
|
2039
|
+
var useStyles19 = makeStyles20({
|
|
2040
|
+
root: { display: "flex", flexDirection: "column", gap: tokens19.spacingVerticalM, padding: tokens19.spacingVerticalL, maxWidth: "680px" },
|
|
2041
|
+
field: { display: "flex", flexDirection: "column", gap: tokens19.spacingVerticalXS },
|
|
2042
|
+
stars: { display: "flex", gap: tokens19.spacingHorizontalXS },
|
|
2043
|
+
star: {
|
|
2044
|
+
border: "none",
|
|
2045
|
+
background: "none",
|
|
2046
|
+
cursor: "pointer",
|
|
2047
|
+
padding: tokens19.spacingVerticalXXS,
|
|
2048
|
+
color: tokens19.colorNeutralForeground2,
|
|
2049
|
+
fontSize: "26px",
|
|
2050
|
+
lineHeight: 1,
|
|
2051
|
+
":focus-visible": { outline: `2px solid ${tokens19.colorStrokeFocus2}`, outlineOffset: "2px" }
|
|
2052
|
+
},
|
|
2053
|
+
starOn: { color: tokens19.colorCompoundBrandForeground1 },
|
|
2054
|
+
footer: { display: "flex", justifyContent: "flex-end", gap: tokens19.spacingHorizontalS },
|
|
2055
|
+
note: { color: tokens19.colorNeutralForeground3, fontSize: tokens19.fontSizeBase200 }
|
|
2056
|
+
});
|
|
2057
|
+
function FeedbackPanel(props) {
|
|
2058
|
+
const {
|
|
2059
|
+
value,
|
|
2060
|
+
onChange,
|
|
2061
|
+
onSubmit,
|
|
2062
|
+
onCancel,
|
|
2063
|
+
heading = "Send feedback",
|
|
2064
|
+
ratingLabel = "Rate your experience",
|
|
2065
|
+
attachments,
|
|
2066
|
+
privacyNote,
|
|
2067
|
+
busy = false
|
|
2068
|
+
} = props;
|
|
2069
|
+
const styles = useStyles19();
|
|
2070
|
+
const baseId = React16.useId();
|
|
2071
|
+
const roving = useRovingTabindex({
|
|
2072
|
+
itemCount: STARS.length,
|
|
2073
|
+
orientation: "horizontal",
|
|
2074
|
+
onActivate: (i) => onChange({ ...value, rating: i + 1 })
|
|
2075
|
+
});
|
|
2076
|
+
const canSubmit = value.rating > 0 && value.mayContact !== void 0 && !busy;
|
|
2077
|
+
return /* @__PURE__ */ jsxs21("div", { className: styles.root, children: [
|
|
2078
|
+
/* @__PURE__ */ jsx27(Text7, { as: "h2", size: 600, weight: "semibold", children: heading }),
|
|
2079
|
+
/* @__PURE__ */ jsxs21("div", { className: styles.field, children: [
|
|
2080
|
+
/* @__PURE__ */ jsx27(Text7, { id: `${baseId}-rating`, children: ratingLabel }),
|
|
2081
|
+
/* @__PURE__ */ jsx27("div", { className: styles.stars, role: "radiogroup", "aria-labelledby": `${baseId}-rating`, children: STARS.map((n, i) => {
|
|
2082
|
+
const item = roving.getItemProps(i);
|
|
2083
|
+
const on = value.rating >= n;
|
|
2084
|
+
return /* @__PURE__ */ jsx27(
|
|
2085
|
+
"button",
|
|
2086
|
+
{
|
|
2087
|
+
type: "button",
|
|
2088
|
+
role: "radio",
|
|
2089
|
+
"aria-checked": value.rating === n,
|
|
2090
|
+
"aria-label": `${n} of 5`,
|
|
2091
|
+
className: mergeClasses9(styles.star, on && styles.starOn),
|
|
2092
|
+
...item,
|
|
2093
|
+
onClick: () => {
|
|
2094
|
+
roving.setActiveIndex(i);
|
|
2095
|
+
onChange({ ...value, rating: n });
|
|
2096
|
+
},
|
|
2097
|
+
children: on ? /* @__PURE__ */ jsx27(StarFilled, {}) : /* @__PURE__ */ jsx27(StarRegular, {})
|
|
2098
|
+
},
|
|
2099
|
+
n
|
|
2100
|
+
);
|
|
2101
|
+
}) })
|
|
2102
|
+
] }),
|
|
2103
|
+
/* @__PURE__ */ jsxs21("div", { className: styles.field, children: [
|
|
2104
|
+
/* @__PURE__ */ jsx27(Text7, { id: `${baseId}-detail`, children: "Explain in more detail" }),
|
|
2105
|
+
/* @__PURE__ */ jsx27(
|
|
2106
|
+
Textarea2,
|
|
2107
|
+
{
|
|
2108
|
+
"aria-labelledby": `${baseId}-detail`,
|
|
2109
|
+
placeholder: "Do not include any private or sensitive information.",
|
|
2110
|
+
value: value.comment,
|
|
2111
|
+
onChange: (_, d) => onChange({ ...value, comment: d.value }),
|
|
2112
|
+
resize: "vertical"
|
|
2113
|
+
}
|
|
2114
|
+
)
|
|
2115
|
+
] }),
|
|
2116
|
+
attachments ? /* @__PURE__ */ jsxs21("div", { className: styles.field, children: [
|
|
2117
|
+
/* @__PURE__ */ jsx27(Text7, { children: "Add more details" }),
|
|
2118
|
+
attachments
|
|
2119
|
+
] }) : null,
|
|
2120
|
+
/* @__PURE__ */ jsxs21("div", { className: styles.field, children: [
|
|
2121
|
+
/* @__PURE__ */ jsx27(Text7, { id: `${baseId}-consent`, children: "May we contact you about your feedback?" }),
|
|
2122
|
+
/* @__PURE__ */ jsxs21(
|
|
2123
|
+
RadioGroup,
|
|
2124
|
+
{
|
|
2125
|
+
"aria-labelledby": `${baseId}-consent`,
|
|
2126
|
+
value: value.mayContact === void 0 ? "" : value.mayContact ? "yes" : "no",
|
|
2127
|
+
onChange: (_, d) => onChange({ ...value, mayContact: d.value === "yes" }),
|
|
2128
|
+
children: [
|
|
2129
|
+
/* @__PURE__ */ jsx27(Radio, { value: "yes", label: "Yes, you may contact me" }),
|
|
2130
|
+
/* @__PURE__ */ jsx27(Radio, { value: "no", label: "No, don't contact me" })
|
|
2131
|
+
]
|
|
2132
|
+
}
|
|
2133
|
+
)
|
|
2134
|
+
] }),
|
|
2135
|
+
privacyNote ? /* @__PURE__ */ jsx27("div", { className: styles.note, children: privacyNote }) : null,
|
|
2136
|
+
/* @__PURE__ */ jsxs21("div", { className: styles.footer, children: [
|
|
2137
|
+
onCancel ? /* @__PURE__ */ jsx27(Button10, { appearance: "secondary", onClick: onCancel, children: "Cancel" }) : null,
|
|
2138
|
+
/* @__PURE__ */ jsx27(Button10, { appearance: "primary", disabled: !canSubmit, onClick: () => onSubmit(value), children: "Submit" })
|
|
2139
|
+
] })
|
|
2140
|
+
] });
|
|
2141
|
+
}
|
|
2142
|
+
|
|
1657
2143
|
// src/shell/AgentAppShell.tsx
|
|
1658
|
-
import * as
|
|
1659
|
-
import { makeStyles as
|
|
2144
|
+
import * as React17 from "react";
|
|
2145
|
+
import { makeStyles as makeStyles21, tokens as tokens20, Button as Button11 } from "@fluentui/react-components";
|
|
1660
2146
|
import { NavigationRegular } from "@fluentui/react-icons";
|
|
1661
2147
|
import { BREAKPOINTS, resolveBreakpoint, useContainerWidth } from "@dataverse-kit/surface-kit/v9";
|
|
1662
|
-
import { Fragment as Fragment4, jsx as
|
|
1663
|
-
var
|
|
2148
|
+
import { Fragment as Fragment4, jsx as jsx28, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2149
|
+
var useStyles20 = makeStyles21({
|
|
1664
2150
|
root: {
|
|
1665
2151
|
display: "flex",
|
|
1666
2152
|
height: "100%",
|
|
1667
2153
|
minHeight: 0,
|
|
1668
|
-
backgroundColor:
|
|
2154
|
+
backgroundColor: tokens20.colorNeutralBackground2,
|
|
1669
2155
|
position: "relative",
|
|
1670
2156
|
overflow: "hidden"
|
|
1671
2157
|
},
|
|
@@ -1673,8 +2159,8 @@ var useStyles17 = makeStyles18({
|
|
|
1673
2159
|
display: "flex",
|
|
1674
2160
|
flexDirection: "column",
|
|
1675
2161
|
minHeight: 0,
|
|
1676
|
-
backgroundColor:
|
|
1677
|
-
borderRight: `1px solid ${
|
|
2162
|
+
backgroundColor: tokens20.colorNeutralBackground1,
|
|
2163
|
+
borderRight: `1px solid ${tokens20.colorNeutralStroke2}`
|
|
1678
2164
|
},
|
|
1679
2165
|
// Below `md` the list overlays the conversation instead of shrinking it to nothing.
|
|
1680
2166
|
sidebarOverlay: {
|
|
@@ -1683,12 +2169,12 @@ var useStyles17 = makeStyles18({
|
|
|
1683
2169
|
bottom: 0,
|
|
1684
2170
|
left: 0,
|
|
1685
2171
|
zIndex: 2,
|
|
1686
|
-
boxShadow:
|
|
2172
|
+
boxShadow: tokens20.shadow16
|
|
1687
2173
|
},
|
|
1688
|
-
scrim: { position: "absolute", inset: "0", zIndex: 1, backgroundColor:
|
|
2174
|
+
scrim: { position: "absolute", inset: "0", zIndex: 1, backgroundColor: tokens20.colorBackgroundOverlay },
|
|
1689
2175
|
main: { flex: 1, display: "flex", flexDirection: "column", minWidth: 0, minHeight: 0 },
|
|
1690
2176
|
body: { flex: 1, minHeight: 0, display: "flex", flexDirection: "column" },
|
|
1691
|
-
toggle: { position: "absolute", top:
|
|
2177
|
+
toggle: { position: "absolute", top: tokens20.spacingVerticalS, left: tokens20.spacingHorizontalS, zIndex: 3 }
|
|
1692
2178
|
});
|
|
1693
2179
|
function AgentAppShell(props) {
|
|
1694
2180
|
const {
|
|
@@ -1702,7 +2188,7 @@ function AgentAppShell(props) {
|
|
|
1702
2188
|
onSidebarOpenChange,
|
|
1703
2189
|
label = "Agent workspace"
|
|
1704
2190
|
} = props;
|
|
1705
|
-
const styles =
|
|
2191
|
+
const styles = useStyles20();
|
|
1706
2192
|
const [containerRef, measuredWidth] = useContainerWidth();
|
|
1707
2193
|
const width = props.containerWidth ?? (measuredWidth > 0 ? measuredWidth : void 0);
|
|
1708
2194
|
const effective = width ?? BREAKPOINTS.xl;
|
|
@@ -1710,17 +2196,17 @@ function AgentAppShell(props) {
|
|
|
1710
2196
|
const railVisible = effective >= BREAKPOINTS.sm;
|
|
1711
2197
|
const sidebarInline = effective >= BREAKPOINTS.md;
|
|
1712
2198
|
const rightPaneVisible = effective >= BREAKPOINTS.lg;
|
|
1713
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
2199
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React17.useState(false);
|
|
1714
2200
|
const overlayOpen = sidebarOpen ?? uncontrolledOpen;
|
|
1715
2201
|
const setOverlayOpen = (open) => {
|
|
1716
2202
|
onSidebarOpenChange?.(open);
|
|
1717
2203
|
if (sidebarOpen === void 0) setUncontrolledOpen(open);
|
|
1718
2204
|
};
|
|
1719
|
-
return /* @__PURE__ */
|
|
2205
|
+
return /* @__PURE__ */ jsxs22("div", { ref: containerRef, className: styles.root, "data-breakpoint": breakpoint, "aria-label": label, children: [
|
|
1720
2206
|
rail && railVisible ? rail : null,
|
|
1721
|
-
sidebar && sidebarInline ? /* @__PURE__ */
|
|
1722
|
-
sidebar && !sidebarInline && overlayOpen ? /* @__PURE__ */
|
|
1723
|
-
/* @__PURE__ */
|
|
2207
|
+
sidebar && sidebarInline ? /* @__PURE__ */ jsx28("div", { className: styles.sidebar, style: { width: sidebarWidth }, children: sidebar }) : null,
|
|
2208
|
+
sidebar && !sidebarInline && overlayOpen ? /* @__PURE__ */ jsxs22(Fragment4, { children: [
|
|
2209
|
+
/* @__PURE__ */ jsx28(
|
|
1724
2210
|
"div",
|
|
1725
2211
|
{
|
|
1726
2212
|
className: styles.scrim,
|
|
@@ -1728,23 +2214,23 @@ function AgentAppShell(props) {
|
|
|
1728
2214
|
"aria-hidden": "true"
|
|
1729
2215
|
}
|
|
1730
2216
|
),
|
|
1731
|
-
/* @__PURE__ */
|
|
2217
|
+
/* @__PURE__ */ jsx28("div", { className: `${styles.sidebar} ${styles.sidebarOverlay}`, style: { width: sidebarWidth }, children: sidebar })
|
|
1732
2218
|
] }) : null,
|
|
1733
|
-
/* @__PURE__ */
|
|
1734
|
-
sidebar && !sidebarInline ? /* @__PURE__ */
|
|
1735
|
-
|
|
2219
|
+
/* @__PURE__ */ jsxs22("div", { className: styles.main, children: [
|
|
2220
|
+
sidebar && !sidebarInline ? /* @__PURE__ */ jsx28(
|
|
2221
|
+
Button11,
|
|
1736
2222
|
{
|
|
1737
2223
|
className: styles.toggle,
|
|
1738
2224
|
size: "small",
|
|
1739
2225
|
appearance: "subtle",
|
|
1740
|
-
icon: /* @__PURE__ */
|
|
2226
|
+
icon: /* @__PURE__ */ jsx28(NavigationRegular, {}),
|
|
1741
2227
|
"aria-label": overlayOpen ? "Hide conversations" : "Show conversations",
|
|
1742
2228
|
"aria-expanded": overlayOpen,
|
|
1743
2229
|
onClick: () => setOverlayOpen(!overlayOpen)
|
|
1744
2230
|
}
|
|
1745
2231
|
) : null,
|
|
1746
2232
|
header,
|
|
1747
|
-
/* @__PURE__ */
|
|
2233
|
+
/* @__PURE__ */ jsx28("div", { className: styles.body, children })
|
|
1748
2234
|
] }),
|
|
1749
2235
|
rightPaneVisible ? rightPane : null
|
|
1750
2236
|
] });
|
|
@@ -1752,36 +2238,36 @@ function AgentAppShell(props) {
|
|
|
1752
2238
|
|
|
1753
2239
|
// src/shell/AppRail.tsx
|
|
1754
2240
|
import {
|
|
1755
|
-
Button as
|
|
2241
|
+
Button as Button12,
|
|
1756
2242
|
Menu,
|
|
1757
2243
|
MenuTrigger,
|
|
1758
2244
|
MenuPopover,
|
|
1759
2245
|
MenuList,
|
|
1760
2246
|
MenuItem,
|
|
1761
|
-
Tooltip as
|
|
1762
|
-
makeStyles as
|
|
1763
|
-
mergeClasses as
|
|
1764
|
-
tokens as
|
|
2247
|
+
Tooltip as Tooltip5,
|
|
2248
|
+
makeStyles as makeStyles22,
|
|
2249
|
+
mergeClasses as mergeClasses10,
|
|
2250
|
+
tokens as tokens21
|
|
1765
2251
|
} from "@fluentui/react-components";
|
|
1766
2252
|
import { MoreHorizontalRegular } from "@fluentui/react-icons";
|
|
1767
|
-
import { jsx as
|
|
1768
|
-
var
|
|
2253
|
+
import { jsx as jsx29, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2254
|
+
var useStyles21 = makeStyles22({
|
|
1769
2255
|
root: {
|
|
1770
2256
|
display: "flex",
|
|
1771
2257
|
flexDirection: "column",
|
|
1772
2258
|
alignItems: "center",
|
|
1773
|
-
gap:
|
|
1774
|
-
padding:
|
|
1775
|
-
backgroundColor:
|
|
1776
|
-
borderRight: `1px solid ${
|
|
2259
|
+
gap: tokens21.spacingVerticalXS,
|
|
2260
|
+
padding: tokens21.spacingVerticalS,
|
|
2261
|
+
backgroundColor: tokens21.colorNeutralBackground3,
|
|
2262
|
+
borderRight: `1px solid ${tokens21.colorNeutralStroke2}`,
|
|
1777
2263
|
minHeight: 0
|
|
1778
2264
|
},
|
|
1779
2265
|
spacer: { flex: 1 },
|
|
1780
2266
|
button: {
|
|
1781
2267
|
position: "relative",
|
|
1782
|
-
":focus-visible": { outline: `2px solid ${
|
|
2268
|
+
":focus-visible": { outline: `2px solid ${tokens21.colorStrokeFocus2}`, outlineOffset: "1px" }
|
|
1783
2269
|
},
|
|
1784
|
-
selected: { backgroundColor:
|
|
2270
|
+
selected: { backgroundColor: tokens21.colorNeutralBackground1Selected },
|
|
1785
2271
|
badge: {
|
|
1786
2272
|
position: "absolute",
|
|
1787
2273
|
top: "2px",
|
|
@@ -1789,58 +2275,58 @@ var useStyles18 = makeStyles19({
|
|
|
1789
2275
|
minWidth: "16px",
|
|
1790
2276
|
height: "16px",
|
|
1791
2277
|
padding: "0 3px",
|
|
1792
|
-
borderRadius:
|
|
1793
|
-
backgroundColor:
|
|
1794
|
-
color:
|
|
2278
|
+
borderRadius: tokens21.borderRadiusCircular,
|
|
2279
|
+
backgroundColor: tokens21.colorPaletteRedBackground3,
|
|
2280
|
+
color: tokens21.colorNeutralForegroundOnBrand,
|
|
1795
2281
|
fontSize: "10px",
|
|
1796
2282
|
lineHeight: "16px"
|
|
1797
2283
|
}
|
|
1798
2284
|
});
|
|
1799
2285
|
function AppRail(props) {
|
|
1800
2286
|
const { items, selectedId, onSelect, maxVisible = 6, label = "Apps", footer } = props;
|
|
1801
|
-
const styles =
|
|
2287
|
+
const styles = useStyles21();
|
|
1802
2288
|
const visible = items.slice(0, maxVisible);
|
|
1803
2289
|
const overflow = items.slice(maxVisible);
|
|
1804
|
-
return /* @__PURE__ */
|
|
1805
|
-
visible.map((item) => /* @__PURE__ */
|
|
1806
|
-
|
|
2290
|
+
return /* @__PURE__ */ jsxs23("nav", { className: styles.root, "aria-label": label, children: [
|
|
2291
|
+
visible.map((item) => /* @__PURE__ */ jsx29(Tooltip5, { content: item.label, relationship: "label", positioning: "after", withArrow: true, children: /* @__PURE__ */ jsx29(
|
|
2292
|
+
Button12,
|
|
1807
2293
|
{
|
|
1808
2294
|
appearance: "subtle",
|
|
1809
2295
|
icon: item.icon,
|
|
1810
|
-
className:
|
|
2296
|
+
className: mergeClasses10(styles.button, item.id === selectedId && styles.selected),
|
|
1811
2297
|
"aria-pressed": item.id === selectedId,
|
|
1812
2298
|
"aria-label": item.badgeCount ? `${item.label}, ${item.badgeCount} unread` : item.label,
|
|
1813
2299
|
onClick: () => onSelect(item.id),
|
|
1814
|
-
children: item.badgeCount ? /* @__PURE__ */
|
|
2300
|
+
children: item.badgeCount ? /* @__PURE__ */ jsx29("span", { className: styles.badge, "aria-hidden": "true", children: item.badgeCount }) : null
|
|
1815
2301
|
}
|
|
1816
2302
|
) }, item.id)),
|
|
1817
|
-
overflow.length > 0 ? /* @__PURE__ */
|
|
1818
|
-
/* @__PURE__ */
|
|
1819
|
-
|
|
2303
|
+
overflow.length > 0 ? /* @__PURE__ */ jsxs23(Menu, { children: [
|
|
2304
|
+
/* @__PURE__ */ jsx29(MenuTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsx29(
|
|
2305
|
+
Button12,
|
|
1820
2306
|
{
|
|
1821
2307
|
appearance: "subtle",
|
|
1822
|
-
icon: /* @__PURE__ */
|
|
2308
|
+
icon: /* @__PURE__ */ jsx29(MoreHorizontalRegular, {}),
|
|
1823
2309
|
className: styles.button,
|
|
1824
2310
|
"aria-label": `More apps, ${overflow.length} hidden`
|
|
1825
2311
|
}
|
|
1826
2312
|
) }),
|
|
1827
|
-
/* @__PURE__ */
|
|
2313
|
+
/* @__PURE__ */ jsx29(MenuPopover, { children: /* @__PURE__ */ jsx29(MenuList, { children: overflow.map((item) => /* @__PURE__ */ jsx29(MenuItem, { icon: item.icon, onClick: () => onSelect(item.id), children: item.label }, item.id)) }) })
|
|
1828
2314
|
] }) : null,
|
|
1829
|
-
/* @__PURE__ */
|
|
2315
|
+
/* @__PURE__ */ jsx29("div", { className: styles.spacer }),
|
|
1830
2316
|
footer
|
|
1831
2317
|
] });
|
|
1832
2318
|
}
|
|
1833
2319
|
|
|
1834
2320
|
// src/shell/ConversationList.tsx
|
|
1835
|
-
import * as
|
|
1836
|
-
import { makeStyles as
|
|
2321
|
+
import * as React18 from "react";
|
|
2322
|
+
import { makeStyles as makeStyles24, tokens as tokens23, Text as Text8 } from "@fluentui/react-components";
|
|
1837
2323
|
|
|
1838
2324
|
// src/shell/ConversationListItem.tsx
|
|
1839
|
-
import { makeStyles as
|
|
2325
|
+
import { makeStyles as makeStyles23, mergeClasses as mergeClasses11, tokens as tokens22 } from "@fluentui/react-components";
|
|
1840
2326
|
|
|
1841
2327
|
// src/shell/AgentAvatar.tsx
|
|
1842
2328
|
import { Avatar as Avatar2 } from "@fluentui/react-components";
|
|
1843
|
-
import { jsx as
|
|
2329
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
1844
2330
|
var STATUS = {
|
|
1845
2331
|
available: "available",
|
|
1846
2332
|
busy: "busy",
|
|
@@ -1851,7 +2337,7 @@ var STATUS = {
|
|
|
1851
2337
|
};
|
|
1852
2338
|
function AgentAvatar({ participant, presence, size = 32, name }) {
|
|
1853
2339
|
const displayName = name ?? participant?.displayName ?? "Unknown";
|
|
1854
|
-
return /* @__PURE__ */
|
|
2340
|
+
return /* @__PURE__ */ jsx30(
|
|
1855
2341
|
Avatar2,
|
|
1856
2342
|
{
|
|
1857
2343
|
name: displayName,
|
|
@@ -1865,49 +2351,49 @@ function AgentAvatar({ participant, presence, size = 32, name }) {
|
|
|
1865
2351
|
}
|
|
1866
2352
|
|
|
1867
2353
|
// src/shell/ConversationListItem.tsx
|
|
1868
|
-
import { jsx as
|
|
1869
|
-
var
|
|
2354
|
+
import { jsx as jsx31, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2355
|
+
var useStyles22 = makeStyles23({
|
|
1870
2356
|
row: {
|
|
1871
2357
|
display: "flex",
|
|
1872
|
-
gap:
|
|
2358
|
+
gap: tokens22.spacingHorizontalS,
|
|
1873
2359
|
alignItems: "center",
|
|
1874
|
-
padding: `${
|
|
1875
|
-
borderRadius:
|
|
2360
|
+
padding: `${tokens22.spacingVerticalS} ${tokens22.spacingHorizontalS}`,
|
|
2361
|
+
borderRadius: tokens22.borderRadiusMedium,
|
|
1876
2362
|
cursor: "pointer",
|
|
1877
|
-
":hover": { backgroundColor:
|
|
2363
|
+
":hover": { backgroundColor: tokens22.colorNeutralBackground1Hover }
|
|
1878
2364
|
},
|
|
1879
2365
|
// ★ The ACTIVE row (aria-activedescendant target) gets a visible focus indicator, because
|
|
1880
2366
|
// real DOM focus stays on the listbox — without this the keyboard user sees nothing move.
|
|
1881
|
-
active: { outline: `2px solid ${
|
|
1882
|
-
selected: { backgroundColor:
|
|
2367
|
+
active: { outline: `2px solid ${tokens22.colorStrokeFocus2}`, outlineOffset: "-2px" },
|
|
2368
|
+
selected: { backgroundColor: tokens22.colorNeutralBackground1Selected },
|
|
1883
2369
|
body: { flex: 1, minWidth: 0 },
|
|
1884
2370
|
title: {
|
|
1885
2371
|
display: "block",
|
|
1886
|
-
fontSize:
|
|
1887
|
-
fontWeight:
|
|
2372
|
+
fontSize: tokens22.fontSizeBase300,
|
|
2373
|
+
fontWeight: tokens22.fontWeightSemibold,
|
|
1888
2374
|
overflow: "hidden",
|
|
1889
2375
|
textOverflow: "ellipsis",
|
|
1890
2376
|
whiteSpace: "nowrap"
|
|
1891
2377
|
},
|
|
1892
|
-
muted: { fontWeight:
|
|
2378
|
+
muted: { fontWeight: tokens22.fontWeightRegular, color: tokens22.colorNeutralForeground3 },
|
|
1893
2379
|
preview: {
|
|
1894
2380
|
display: "block",
|
|
1895
|
-
fontSize:
|
|
1896
|
-
color:
|
|
2381
|
+
fontSize: tokens22.fontSizeBase200,
|
|
2382
|
+
color: tokens22.colorNeutralForeground3,
|
|
1897
2383
|
overflow: "hidden",
|
|
1898
2384
|
textOverflow: "ellipsis",
|
|
1899
2385
|
whiteSpace: "nowrap"
|
|
1900
2386
|
},
|
|
1901
2387
|
meta: { display: "flex", flexDirection: "column", alignItems: "flex-end", gap: "2px" },
|
|
1902
|
-
time: { fontSize:
|
|
2388
|
+
time: { fontSize: tokens22.fontSizeBase100, color: tokens22.colorNeutralForeground3 },
|
|
1903
2389
|
unread: {
|
|
1904
2390
|
minWidth: "18px",
|
|
1905
2391
|
height: "18px",
|
|
1906
|
-
padding: `0 ${
|
|
1907
|
-
borderRadius:
|
|
1908
|
-
backgroundColor:
|
|
1909
|
-
color:
|
|
1910
|
-
fontSize:
|
|
2392
|
+
padding: `0 ${tokens22.spacingHorizontalXXS}`,
|
|
2393
|
+
borderRadius: tokens22.borderRadiusCircular,
|
|
2394
|
+
backgroundColor: tokens22.colorBrandBackground,
|
|
2395
|
+
color: tokens22.colorNeutralForegroundOnBrand,
|
|
2396
|
+
fontSize: tokens22.fontSizeBase100,
|
|
1911
2397
|
lineHeight: "18px",
|
|
1912
2398
|
textAlign: "center"
|
|
1913
2399
|
}
|
|
@@ -1926,27 +2412,27 @@ function conversationAccessibleName(summary, locale) {
|
|
|
1926
2412
|
}
|
|
1927
2413
|
function ConversationListItem(props) {
|
|
1928
2414
|
const { summary, selected, active, id, locale, onSelect } = props;
|
|
1929
|
-
const styles =
|
|
2415
|
+
const styles = useStyles22();
|
|
1930
2416
|
const time = summary.timestamp ? new Intl.DateTimeFormat(locale, { timeStyle: "short" }).format(new Date(summary.timestamp)) : void 0;
|
|
1931
|
-
return /* @__PURE__ */
|
|
2417
|
+
return /* @__PURE__ */ jsxs24(
|
|
1932
2418
|
"div",
|
|
1933
2419
|
{
|
|
1934
2420
|
id,
|
|
1935
2421
|
role: "option",
|
|
1936
2422
|
"aria-selected": selected,
|
|
1937
2423
|
"aria-label": conversationAccessibleName(summary, locale),
|
|
1938
|
-
className:
|
|
2424
|
+
className: mergeClasses11(styles.row, selected && styles.selected, active && styles.active),
|
|
1939
2425
|
onClick: () => onSelect(summary.id),
|
|
1940
2426
|
"data-conversation-option": true,
|
|
1941
2427
|
children: [
|
|
1942
|
-
/* @__PURE__ */
|
|
1943
|
-
/* @__PURE__ */
|
|
1944
|
-
/* @__PURE__ */
|
|
1945
|
-
summary.preview ? /* @__PURE__ */
|
|
2428
|
+
/* @__PURE__ */ jsx31(AgentAvatar, { participant: summary.participant, presence: summary.presence, size: 32 }),
|
|
2429
|
+
/* @__PURE__ */ jsxs24("div", { className: styles.body, "aria-hidden": "true", children: [
|
|
2430
|
+
/* @__PURE__ */ jsx31("span", { className: mergeClasses11(styles.title, summary.muted && styles.muted), children: summary.title }),
|
|
2431
|
+
summary.preview ? /* @__PURE__ */ jsx31("span", { className: styles.preview, children: summary.preview }) : null
|
|
1946
2432
|
] }),
|
|
1947
|
-
/* @__PURE__ */
|
|
1948
|
-
time ? /* @__PURE__ */
|
|
1949
|
-
!summary.muted && summary.unreadCount ? /* @__PURE__ */
|
|
2433
|
+
/* @__PURE__ */ jsxs24("div", { className: styles.meta, "aria-hidden": "true", children: [
|
|
2434
|
+
time ? /* @__PURE__ */ jsx31("span", { className: styles.time, children: time }) : null,
|
|
2435
|
+
!summary.muted && summary.unreadCount ? /* @__PURE__ */ jsx31("span", { className: styles.unread, children: summary.unreadCount }) : null
|
|
1950
2436
|
] })
|
|
1951
2437
|
]
|
|
1952
2438
|
}
|
|
@@ -1954,27 +2440,27 @@ function ConversationListItem(props) {
|
|
|
1954
2440
|
}
|
|
1955
2441
|
|
|
1956
2442
|
// src/shell/ConversationList.tsx
|
|
1957
|
-
import { jsx as
|
|
1958
|
-
var
|
|
2443
|
+
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
2444
|
+
var useStyles23 = makeStyles24({
|
|
1959
2445
|
root: {
|
|
1960
2446
|
display: "flex",
|
|
1961
2447
|
flexDirection: "column",
|
|
1962
2448
|
gap: "2px",
|
|
1963
|
-
padding:
|
|
2449
|
+
padding: tokens23.spacingHorizontalXS,
|
|
1964
2450
|
overflowY: "auto",
|
|
1965
2451
|
minHeight: 0,
|
|
1966
|
-
":focus-visible": { outline: `2px solid ${
|
|
2452
|
+
":focus-visible": { outline: `2px solid ${tokens23.colorStrokeFocus2}`, outlineOffset: "-2px" }
|
|
1967
2453
|
},
|
|
1968
|
-
empty: { padding:
|
|
2454
|
+
empty: { padding: tokens23.spacingVerticalM, color: tokens23.colorNeutralForeground3 }
|
|
1969
2455
|
});
|
|
1970
2456
|
function ConversationList(props) {
|
|
1971
2457
|
const { items, selectedId, onSelect, label = "Conversations", locale, empty } = props;
|
|
1972
|
-
const styles =
|
|
1973
|
-
const listRef =
|
|
1974
|
-
const idBase =
|
|
2458
|
+
const styles = useStyles23();
|
|
2459
|
+
const listRef = React18.useRef(null);
|
|
2460
|
+
const idBase = React18.useId();
|
|
1975
2461
|
const selectedIndex = Math.max(0, items.findIndex((i) => i.id === selectedId));
|
|
1976
|
-
const [active, setActive] =
|
|
1977
|
-
|
|
2462
|
+
const [active, setActive] = React18.useState(selectedIndex);
|
|
2463
|
+
React18.useEffect(() => {
|
|
1978
2464
|
setActive((current) => {
|
|
1979
2465
|
if (items.length === 0) return 0;
|
|
1980
2466
|
if (selectedIndex >= 0 && items[selectedIndex]) return selectedIndex;
|
|
@@ -1982,7 +2468,7 @@ function ConversationList(props) {
|
|
|
1982
2468
|
});
|
|
1983
2469
|
}, [selectedIndex, items]);
|
|
1984
2470
|
const optionId = (index) => `${idBase}-opt-${index}`;
|
|
1985
|
-
|
|
2471
|
+
React18.useEffect(() => {
|
|
1986
2472
|
const el = listRef.current?.ownerDocument.getElementById(optionId(active));
|
|
1987
2473
|
el?.scrollIntoView?.({ block: "nearest" });
|
|
1988
2474
|
}, [active, idBase]);
|
|
@@ -2005,9 +2491,9 @@ function ConversationList(props) {
|
|
|
2005
2491
|
setActive(next);
|
|
2006
2492
|
};
|
|
2007
2493
|
if (items.length === 0) {
|
|
2008
|
-
return /* @__PURE__ */
|
|
2494
|
+
return /* @__PURE__ */ jsx32("div", { className: styles.root, children: empty ?? /* @__PURE__ */ jsx32(Text8, { className: styles.empty, size: 200, children: "No conversations yet." }) });
|
|
2009
2495
|
}
|
|
2010
|
-
return /* @__PURE__ */
|
|
2496
|
+
return /* @__PURE__ */ jsx32(
|
|
2011
2497
|
"div",
|
|
2012
2498
|
{
|
|
2013
2499
|
ref: listRef,
|
|
@@ -2017,7 +2503,7 @@ function ConversationList(props) {
|
|
|
2017
2503
|
tabIndex: 0,
|
|
2018
2504
|
"aria-activedescendant": optionId(active),
|
|
2019
2505
|
onKeyDown,
|
|
2020
|
-
children: items.map((summary, index) => /* @__PURE__ */
|
|
2506
|
+
children: items.map((summary, index) => /* @__PURE__ */ jsx32(
|
|
2021
2507
|
ConversationListItem,
|
|
2022
2508
|
{
|
|
2023
2509
|
id: optionId(index),
|
|
@@ -2035,7 +2521,7 @@ function ConversationList(props) {
|
|
|
2035
2521
|
|
|
2036
2522
|
// src/shell/ConversationHeader.tsx
|
|
2037
2523
|
import {
|
|
2038
|
-
Button as
|
|
2524
|
+
Button as Button13,
|
|
2039
2525
|
Menu as Menu2,
|
|
2040
2526
|
MenuTrigger as MenuTrigger2,
|
|
2041
2527
|
MenuPopover as MenuPopover2,
|
|
@@ -2043,27 +2529,27 @@ import {
|
|
|
2043
2529
|
MenuItem as MenuItem2,
|
|
2044
2530
|
Tab,
|
|
2045
2531
|
TabList,
|
|
2046
|
-
Text as
|
|
2047
|
-
makeStyles as
|
|
2048
|
-
tokens as
|
|
2532
|
+
Text as Text9,
|
|
2533
|
+
makeStyles as makeStyles25,
|
|
2534
|
+
tokens as tokens24
|
|
2049
2535
|
} from "@fluentui/react-components";
|
|
2050
2536
|
import { MoreHorizontalRegular as MoreHorizontalRegular2 } from "@fluentui/react-icons";
|
|
2051
|
-
import { jsx as
|
|
2052
|
-
var
|
|
2537
|
+
import { jsx as jsx33, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2538
|
+
var useStyles24 = makeStyles25({
|
|
2053
2539
|
root: {
|
|
2054
2540
|
display: "flex",
|
|
2055
2541
|
flexDirection: "column",
|
|
2056
|
-
gap:
|
|
2057
|
-
padding: `${
|
|
2058
|
-
borderBottom: `1px solid ${
|
|
2059
|
-
backgroundColor:
|
|
2542
|
+
gap: tokens24.spacingVerticalXS,
|
|
2543
|
+
padding: `${tokens24.spacingVerticalS} ${tokens24.spacingHorizontalM} 0`,
|
|
2544
|
+
borderBottom: `1px solid ${tokens24.colorNeutralStroke2}`,
|
|
2545
|
+
backgroundColor: tokens24.colorNeutralBackground1
|
|
2060
2546
|
},
|
|
2061
|
-
top: { display: "flex", alignItems: "center", gap:
|
|
2062
|
-
identity: { display: "flex", alignItems: "center", gap:
|
|
2547
|
+
top: { display: "flex", alignItems: "center", gap: tokens24.spacingHorizontalS },
|
|
2548
|
+
identity: { display: "flex", alignItems: "center", gap: tokens24.spacingHorizontalS, minWidth: 0 },
|
|
2063
2549
|
titles: { display: "flex", flexDirection: "column", minWidth: 0 },
|
|
2064
|
-
subtitle: { color:
|
|
2550
|
+
subtitle: { color: tokens24.colorNeutralForeground3, fontSize: tokens24.fontSizeBase200 },
|
|
2065
2551
|
spacer: { flex: 1 },
|
|
2066
|
-
tabRow: { display: "flex", alignItems: "flex-end", gap:
|
|
2552
|
+
tabRow: { display: "flex", alignItems: "flex-end", gap: tokens24.spacingHorizontalS }
|
|
2067
2553
|
});
|
|
2068
2554
|
function ConversationHeader(props) {
|
|
2069
2555
|
const {
|
|
@@ -2077,22 +2563,22 @@ function ConversationHeader(props) {
|
|
|
2077
2563
|
actions,
|
|
2078
2564
|
trailing
|
|
2079
2565
|
} = props;
|
|
2080
|
-
const styles =
|
|
2566
|
+
const styles = useStyles24();
|
|
2081
2567
|
const inline = (actions ?? []).slice(0, 2);
|
|
2082
2568
|
const overflow = (actions ?? []).slice(2);
|
|
2083
|
-
return /* @__PURE__ */
|
|
2084
|
-
/* @__PURE__ */
|
|
2085
|
-
/* @__PURE__ */
|
|
2086
|
-
/* @__PURE__ */
|
|
2087
|
-
/* @__PURE__ */
|
|
2088
|
-
/* @__PURE__ */
|
|
2089
|
-
subtitle ? /* @__PURE__ */
|
|
2569
|
+
return /* @__PURE__ */ jsxs25("header", { className: styles.root, children: [
|
|
2570
|
+
/* @__PURE__ */ jsxs25("div", { className: styles.top, children: [
|
|
2571
|
+
/* @__PURE__ */ jsxs25("div", { className: styles.identity, children: [
|
|
2572
|
+
/* @__PURE__ */ jsx33(AgentAvatar, { participant, presence, size: 32, name: title }),
|
|
2573
|
+
/* @__PURE__ */ jsxs25("div", { className: styles.titles, children: [
|
|
2574
|
+
/* @__PURE__ */ jsx33(Text9, { weight: "semibold", truncate: true, wrap: false, children: title }),
|
|
2575
|
+
subtitle ? /* @__PURE__ */ jsx33("span", { className: styles.subtitle, children: subtitle }) : null
|
|
2090
2576
|
] })
|
|
2091
2577
|
] }),
|
|
2092
|
-
/* @__PURE__ */
|
|
2578
|
+
/* @__PURE__ */ jsx33("div", { className: styles.spacer }),
|
|
2093
2579
|
trailing,
|
|
2094
|
-
inline.map((action) => /* @__PURE__ */
|
|
2095
|
-
|
|
2580
|
+
inline.map((action) => /* @__PURE__ */ jsx33(
|
|
2581
|
+
Button13,
|
|
2096
2582
|
{
|
|
2097
2583
|
appearance: "subtle",
|
|
2098
2584
|
size: "small",
|
|
@@ -2102,80 +2588,80 @@ function ConversationHeader(props) {
|
|
|
2102
2588
|
},
|
|
2103
2589
|
action.key
|
|
2104
2590
|
)),
|
|
2105
|
-
overflow.length > 0 ? /* @__PURE__ */
|
|
2106
|
-
/* @__PURE__ */
|
|
2107
|
-
|
|
2591
|
+
overflow.length > 0 ? /* @__PURE__ */ jsxs25(Menu2, { children: [
|
|
2592
|
+
/* @__PURE__ */ jsx33(MenuTrigger2, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsx33(
|
|
2593
|
+
Button13,
|
|
2108
2594
|
{
|
|
2109
2595
|
appearance: "subtle",
|
|
2110
2596
|
size: "small",
|
|
2111
|
-
icon: /* @__PURE__ */
|
|
2597
|
+
icon: /* @__PURE__ */ jsx33(MoreHorizontalRegular2, {}),
|
|
2112
2598
|
"aria-label": `More actions, ${overflow.length} available`
|
|
2113
2599
|
}
|
|
2114
2600
|
) }),
|
|
2115
|
-
/* @__PURE__ */
|
|
2601
|
+
/* @__PURE__ */ jsx33(MenuPopover2, { children: /* @__PURE__ */ jsx33(MenuList2, { children: overflow.map((action) => /* @__PURE__ */ jsx33(MenuItem2, { icon: action.icon, onClick: action.onClick, children: action.label }, action.key)) }) })
|
|
2116
2602
|
] }) : null
|
|
2117
2603
|
] }),
|
|
2118
|
-
tabs && tabs.length > 0 ? /* @__PURE__ */
|
|
2604
|
+
tabs && tabs.length > 0 ? /* @__PURE__ */ jsx33("div", { className: styles.tabRow, children: /* @__PURE__ */ jsx33(
|
|
2119
2605
|
TabList,
|
|
2120
2606
|
{
|
|
2121
2607
|
selectedValue: selectedTabId,
|
|
2122
2608
|
onTabSelect: (_, data) => onTabSelect?.(data.value),
|
|
2123
2609
|
size: "small",
|
|
2124
|
-
children: tabs.map((tab) => /* @__PURE__ */
|
|
2610
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsx33(Tab, { value: tab.id, children: tab.label }, tab.id))
|
|
2125
2611
|
}
|
|
2126
2612
|
) }) : null
|
|
2127
2613
|
] });
|
|
2128
2614
|
}
|
|
2129
2615
|
|
|
2130
2616
|
// src/shell/RightPane.tsx
|
|
2131
|
-
import * as
|
|
2132
|
-
import { Button as
|
|
2133
|
-
import { DismissRegular } from "@fluentui/react-icons";
|
|
2134
|
-
import { jsx as
|
|
2135
|
-
var
|
|
2617
|
+
import * as React19 from "react";
|
|
2618
|
+
import { Button as Button14, makeStyles as makeStyles26, tokens as tokens25, Text as Text10 } from "@fluentui/react-components";
|
|
2619
|
+
import { DismissRegular as DismissRegular2 } from "@fluentui/react-icons";
|
|
2620
|
+
import { jsx as jsx34, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2621
|
+
var useStyles25 = makeStyles26({
|
|
2136
2622
|
root: {
|
|
2137
2623
|
display: "flex",
|
|
2138
2624
|
flexDirection: "column",
|
|
2139
|
-
borderLeft: `1px solid ${
|
|
2140
|
-
backgroundColor:
|
|
2625
|
+
borderLeft: `1px solid ${tokens25.colorNeutralStroke2}`,
|
|
2626
|
+
backgroundColor: tokens25.colorNeutralBackground1,
|
|
2141
2627
|
minHeight: 0
|
|
2142
2628
|
},
|
|
2143
2629
|
head: {
|
|
2144
2630
|
display: "flex",
|
|
2145
2631
|
alignItems: "center",
|
|
2146
2632
|
justifyContent: "space-between",
|
|
2147
|
-
gap:
|
|
2148
|
-
padding:
|
|
2149
|
-
borderBottom: `1px solid ${
|
|
2633
|
+
gap: tokens25.spacingHorizontalS,
|
|
2634
|
+
padding: tokens25.spacingVerticalS,
|
|
2635
|
+
borderBottom: `1px solid ${tokens25.colorNeutralStroke2}`
|
|
2150
2636
|
},
|
|
2151
|
-
body: { flex: 1, overflowY: "auto", padding:
|
|
2637
|
+
body: { flex: 1, overflowY: "auto", padding: tokens25.spacingVerticalM }
|
|
2152
2638
|
});
|
|
2153
2639
|
function RightPane({ open, title, onClose, children, width = 320 }) {
|
|
2154
|
-
const styles =
|
|
2155
|
-
const labelId =
|
|
2640
|
+
const styles = useStyles25();
|
|
2641
|
+
const labelId = React19.useId();
|
|
2156
2642
|
if (!open) return null;
|
|
2157
|
-
return /* @__PURE__ */
|
|
2158
|
-
/* @__PURE__ */
|
|
2159
|
-
/* @__PURE__ */
|
|
2160
|
-
/* @__PURE__ */
|
|
2161
|
-
|
|
2643
|
+
return /* @__PURE__ */ jsxs26("aside", { className: styles.root, style: { width }, "aria-labelledby": labelId, children: [
|
|
2644
|
+
/* @__PURE__ */ jsxs26("div", { className: styles.head, children: [
|
|
2645
|
+
/* @__PURE__ */ jsx34(Text10, { id: labelId, weight: "semibold", children: title }),
|
|
2646
|
+
/* @__PURE__ */ jsx34(
|
|
2647
|
+
Button14,
|
|
2162
2648
|
{
|
|
2163
2649
|
appearance: "subtle",
|
|
2164
2650
|
size: "small",
|
|
2165
|
-
icon: /* @__PURE__ */
|
|
2651
|
+
icon: /* @__PURE__ */ jsx34(DismissRegular2, {}),
|
|
2166
2652
|
onClick: onClose,
|
|
2167
2653
|
"aria-label": `Close ${title}`
|
|
2168
2654
|
}
|
|
2169
2655
|
)
|
|
2170
2656
|
] }),
|
|
2171
|
-
/* @__PURE__ */
|
|
2657
|
+
/* @__PURE__ */ jsx34("div", { className: styles.body, children })
|
|
2172
2658
|
] });
|
|
2173
2659
|
}
|
|
2174
2660
|
|
|
2175
2661
|
// src/shell/GlobalSearchBar.tsx
|
|
2176
|
-
import { SearchBox, makeStyles as
|
|
2177
|
-
import { jsx as
|
|
2178
|
-
var
|
|
2662
|
+
import { SearchBox, makeStyles as makeStyles27 } from "@fluentui/react-components";
|
|
2663
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
2664
|
+
var useStyles26 = makeStyles27({
|
|
2179
2665
|
root: { width: "100%", maxWidth: "640px" }
|
|
2180
2666
|
});
|
|
2181
2667
|
function GlobalSearchBar({
|
|
@@ -2184,8 +2670,8 @@ function GlobalSearchBar({
|
|
|
2184
2670
|
onSubmit,
|
|
2185
2671
|
placeholder = "Search conversations"
|
|
2186
2672
|
}) {
|
|
2187
|
-
const styles =
|
|
2188
|
-
return /* @__PURE__ */
|
|
2673
|
+
const styles = useStyles26();
|
|
2674
|
+
return /* @__PURE__ */ jsx35(
|
|
2189
2675
|
SearchBox,
|
|
2190
2676
|
{
|
|
2191
2677
|
className: styles.root,
|
|
@@ -2201,45 +2687,45 @@ function GlobalSearchBar({
|
|
|
2201
2687
|
}
|
|
2202
2688
|
|
|
2203
2689
|
// src/grounding/CitationChip.tsx
|
|
2204
|
-
import { Tooltip as
|
|
2205
|
-
import { jsx as
|
|
2206
|
-
var
|
|
2690
|
+
import { Tooltip as Tooltip6, makeStyles as makeStyles28, tokens as tokens26 } from "@fluentui/react-components";
|
|
2691
|
+
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
2692
|
+
var useStyles27 = makeStyles28({
|
|
2207
2693
|
chip: {
|
|
2208
2694
|
display: "inline-flex",
|
|
2209
2695
|
alignItems: "center",
|
|
2210
2696
|
justifyContent: "center",
|
|
2211
2697
|
minWidth: "18px",
|
|
2212
2698
|
height: "18px",
|
|
2213
|
-
padding: `0 ${
|
|
2699
|
+
padding: `0 ${tokens26.spacingHorizontalXXS}`,
|
|
2214
2700
|
marginLeft: "2px",
|
|
2215
2701
|
verticalAlign: "super",
|
|
2216
|
-
fontSize:
|
|
2702
|
+
fontSize: tokens26.fontSizeBase100,
|
|
2217
2703
|
lineHeight: "18px",
|
|
2218
|
-
borderRadius:
|
|
2219
|
-
border: `1px solid ${
|
|
2220
|
-
backgroundColor:
|
|
2221
|
-
color:
|
|
2704
|
+
borderRadius: tokens26.borderRadiusSmall,
|
|
2705
|
+
border: `1px solid ${tokens26.colorNeutralStroke2}`,
|
|
2706
|
+
backgroundColor: tokens26.colorNeutralBackground3,
|
|
2707
|
+
color: tokens26.colorNeutralForeground2,
|
|
2222
2708
|
cursor: "pointer",
|
|
2223
|
-
":hover": { backgroundColor:
|
|
2224
|
-
":focus-visible": { outline: `2px solid ${
|
|
2709
|
+
":hover": { backgroundColor: tokens26.colorNeutralBackground3Hover },
|
|
2710
|
+
":focus-visible": { outline: `2px solid ${tokens26.colorStrokeFocus2}`, outlineOffset: "1px" }
|
|
2225
2711
|
},
|
|
2226
2712
|
inert: { cursor: "default" }
|
|
2227
2713
|
});
|
|
2228
2714
|
function CitationChip({ marker, source, onOpen }) {
|
|
2229
|
-
const styles =
|
|
2715
|
+
const styles = useStyles27();
|
|
2230
2716
|
const label = source ? `Source ${marker}: ${source.title}` : `Source ${marker}`;
|
|
2231
2717
|
if (!source || !onOpen) {
|
|
2232
|
-
return /* @__PURE__ */
|
|
2718
|
+
return /* @__PURE__ */ jsx36("span", { className: `${styles.chip} ${styles.inert}`, "aria-label": label, children: marker });
|
|
2233
2719
|
}
|
|
2234
|
-
return /* @__PURE__ */
|
|
2720
|
+
return /* @__PURE__ */ jsx36(Tooltip6, { content: source.title, relationship: "description", withArrow: true, children: /* @__PURE__ */ jsx36("button", { type: "button", className: styles.chip, "aria-label": label, onClick: () => onOpen(source), children: marker }) });
|
|
2235
2721
|
}
|
|
2236
2722
|
|
|
2237
2723
|
// src/grounding/CitationList.tsx
|
|
2238
|
-
import * as
|
|
2239
|
-
import { makeStyles as
|
|
2724
|
+
import * as React20 from "react";
|
|
2725
|
+
import { makeStyles as makeStyles30, tokens as tokens28 } from "@fluentui/react-components";
|
|
2240
2726
|
|
|
2241
2727
|
// src/grounding/SourceCard.tsx
|
|
2242
|
-
import { Button as
|
|
2728
|
+
import { Button as Button15, Text as Text11, makeStyles as makeStyles29, tokens as tokens27 } from "@fluentui/react-components";
|
|
2243
2729
|
import {
|
|
2244
2730
|
DocumentRegular,
|
|
2245
2731
|
DatabaseRegular,
|
|
@@ -2247,7 +2733,7 @@ import {
|
|
|
2247
2733
|
BookRegular,
|
|
2248
2734
|
DocumentBulletListRegular
|
|
2249
2735
|
} from "@fluentui/react-icons";
|
|
2250
|
-
import { jsx as
|
|
2736
|
+
import { jsx as jsx37, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2251
2737
|
var ICONS = {
|
|
2252
2738
|
dataverse: DatabaseRegular,
|
|
2253
2739
|
document: DocumentRegular,
|
|
@@ -2255,38 +2741,38 @@ var ICONS = {
|
|
|
2255
2741
|
knowledge: BookRegular,
|
|
2256
2742
|
other: DocumentBulletListRegular
|
|
2257
2743
|
};
|
|
2258
|
-
var
|
|
2259
|
-
root: { gap:
|
|
2260
|
-
head: { display: "flex", alignItems: "center", gap:
|
|
2261
|
-
marker: { color:
|
|
2262
|
-
snippet: { color:
|
|
2263
|
-
meta: { display: "flex", alignItems: "center", gap:
|
|
2744
|
+
var useStyles28 = makeStyles29({
|
|
2745
|
+
root: { gap: tokens27.spacingVerticalXXS },
|
|
2746
|
+
head: { display: "flex", alignItems: "center", gap: tokens27.spacingHorizontalXS },
|
|
2747
|
+
marker: { color: tokens27.colorNeutralForeground3, fontSize: tokens27.fontSizeBase200 },
|
|
2748
|
+
snippet: { color: tokens27.colorNeutralForeground2, fontSize: tokens27.fontSizeBase200 },
|
|
2749
|
+
meta: { display: "flex", alignItems: "center", gap: tokens27.spacingHorizontalS, marginTop: tokens27.spacingVerticalXXS }
|
|
2264
2750
|
});
|
|
2265
2751
|
function SourceCard({ source, marker, onOpen, showSnippet = true }) {
|
|
2266
|
-
const styles =
|
|
2752
|
+
const styles = useStyles28();
|
|
2267
2753
|
const Icon = ICONS[source.kind] ?? ICONS.other;
|
|
2268
|
-
return /* @__PURE__ */
|
|
2269
|
-
/* @__PURE__ */
|
|
2270
|
-
/* @__PURE__ */
|
|
2271
|
-
marker ? /* @__PURE__ */
|
|
2754
|
+
return /* @__PURE__ */ jsxs27(CardSurface, { className: styles.root, children: [
|
|
2755
|
+
/* @__PURE__ */ jsxs27("div", { className: styles.head, children: [
|
|
2756
|
+
/* @__PURE__ */ jsx37(Icon, { "aria-hidden": "true" }),
|
|
2757
|
+
marker ? /* @__PURE__ */ jsxs27("span", { className: styles.marker, children: [
|
|
2272
2758
|
"[",
|
|
2273
2759
|
marker,
|
|
2274
2760
|
"]"
|
|
2275
2761
|
] }) : null,
|
|
2276
|
-
/* @__PURE__ */
|
|
2762
|
+
/* @__PURE__ */ jsx37(Text11, { weight: "semibold", children: source.title })
|
|
2277
2763
|
] }),
|
|
2278
|
-
showSnippet && source.snippet ? /* @__PURE__ */
|
|
2279
|
-
/* @__PURE__ */
|
|
2280
|
-
onOpen && (source.recordId || source.url) ? /* @__PURE__ */
|
|
2281
|
-
/* @__PURE__ */
|
|
2764
|
+
showSnippet && source.snippet ? /* @__PURE__ */ jsx37("span", { className: styles.snippet, children: source.snippet }) : null,
|
|
2765
|
+
/* @__PURE__ */ jsxs27("div", { className: styles.meta, children: [
|
|
2766
|
+
onOpen && (source.recordId || source.url) ? /* @__PURE__ */ jsx37(Button15, { size: "small", appearance: "subtle", onClick: () => onOpen(source), children: source.recordId ? "Open record" : "Open" }) : null,
|
|
2767
|
+
/* @__PURE__ */ jsx37("span", { className: styles.snippet, children: source.score === void 0 ? "Relevance not reported" : `Relevance ${Math.round(source.score * 100)}%` })
|
|
2282
2768
|
] })
|
|
2283
2769
|
] });
|
|
2284
2770
|
}
|
|
2285
2771
|
|
|
2286
2772
|
// src/grounding/CitationList.tsx
|
|
2287
|
-
import { jsx as
|
|
2288
|
-
var
|
|
2289
|
-
list: { display: "flex", flexDirection: "column", gap:
|
|
2773
|
+
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
2774
|
+
var useStyles29 = makeStyles30({
|
|
2775
|
+
list: { display: "flex", flexDirection: "column", gap: tokens28.spacingVerticalXS, listStyle: "none", margin: 0, padding: 0 }
|
|
2290
2776
|
});
|
|
2291
2777
|
function CitationList({
|
|
2292
2778
|
text,
|
|
@@ -2294,38 +2780,38 @@ function CitationList({
|
|
|
2294
2780
|
onOpenSource,
|
|
2295
2781
|
defaultOpen = false
|
|
2296
2782
|
}) {
|
|
2297
|
-
const styles =
|
|
2298
|
-
const id =
|
|
2299
|
-
const { used, citations } =
|
|
2783
|
+
const styles = useStyles29();
|
|
2784
|
+
const id = React20.useId();
|
|
2785
|
+
const { used, citations } = React20.useMemo(() => renumberCitations(text, sources), [text, sources]);
|
|
2300
2786
|
if (used.length === 0) return null;
|
|
2301
2787
|
const markerFor = (sourceId) => citations.find((c) => c.sourceId === sourceId)?.marker;
|
|
2302
|
-
return /* @__PURE__ */
|
|
2788
|
+
return /* @__PURE__ */ jsx38(
|
|
2303
2789
|
Disclosure,
|
|
2304
2790
|
{
|
|
2305
2791
|
id,
|
|
2306
2792
|
defaultOpen,
|
|
2307
2793
|
summary: `${used.length} source${used.length === 1 ? "" : "s"}`,
|
|
2308
|
-
children: /* @__PURE__ */
|
|
2794
|
+
children: /* @__PURE__ */ jsx38("ul", { className: styles.list, children: used.map((source) => /* @__PURE__ */ jsx38("li", { children: /* @__PURE__ */ jsx38(SourceCard, { source, marker: markerFor(source.id), onOpen: onOpenSource }) }, source.id)) })
|
|
2309
2795
|
}
|
|
2310
2796
|
);
|
|
2311
2797
|
}
|
|
2312
2798
|
|
|
2313
2799
|
// src/grounding/AnswerWithCitations.tsx
|
|
2314
|
-
import * as
|
|
2315
|
-
import { makeStyles as
|
|
2316
|
-
import { jsx as
|
|
2317
|
-
var
|
|
2800
|
+
import * as React21 from "react";
|
|
2801
|
+
import { makeStyles as makeStyles31 } from "@fluentui/react-components";
|
|
2802
|
+
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
2803
|
+
var useStyles30 = makeStyles31({ root: { whiteSpace: "pre-wrap", wordBreak: "break-word" } });
|
|
2318
2804
|
function AnswerWithCitations({
|
|
2319
2805
|
text,
|
|
2320
2806
|
citations = [],
|
|
2321
2807
|
sources = [],
|
|
2322
2808
|
onOpenSource
|
|
2323
2809
|
}) {
|
|
2324
|
-
const styles =
|
|
2325
|
-
const segments =
|
|
2326
|
-
const byId =
|
|
2327
|
-
return /* @__PURE__ */
|
|
2328
|
-
(segment, i) => segment.kind === "text" ? /* @__PURE__ */
|
|
2810
|
+
const styles = useStyles30();
|
|
2811
|
+
const segments = React21.useMemo(() => splitTextByCitations(text, citations), [text, citations]);
|
|
2812
|
+
const byId = React21.useMemo(() => new Map(sources.map((s) => [s.id, s])), [sources]);
|
|
2813
|
+
return /* @__PURE__ */ jsx39("span", { className: styles.root, children: segments.map(
|
|
2814
|
+
(segment, i) => segment.kind === "text" ? /* @__PURE__ */ jsx39(React21.Fragment, { children: segment.text }, i) : /* @__PURE__ */ jsx39(
|
|
2329
2815
|
CitationChip,
|
|
2330
2816
|
{
|
|
2331
2817
|
marker: segment.marker ?? "",
|
|
@@ -2338,20 +2824,20 @@ function AnswerWithCitations({
|
|
|
2338
2824
|
}
|
|
2339
2825
|
|
|
2340
2826
|
// src/grounding/GroundingPanel.tsx
|
|
2341
|
-
import * as
|
|
2342
|
-
import { Text as
|
|
2343
|
-
import { jsx as
|
|
2344
|
-
var
|
|
2827
|
+
import * as React22 from "react";
|
|
2828
|
+
import { Text as Text12, makeStyles as makeStyles32, tokens as tokens29 } from "@fluentui/react-components";
|
|
2829
|
+
import { jsx as jsx40, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2830
|
+
var useStyles31 = makeStyles32({
|
|
2345
2831
|
grid: {
|
|
2346
2832
|
display: "grid",
|
|
2347
2833
|
gridTemplateColumns: "minmax(96px, max-content) 1fr",
|
|
2348
|
-
gap: `${
|
|
2834
|
+
gap: `${tokens29.spacingVerticalXXS} ${tokens29.spacingHorizontalM}`,
|
|
2349
2835
|
margin: 0,
|
|
2350
|
-
fontSize:
|
|
2836
|
+
fontSize: tokens29.fontSizeBase200
|
|
2351
2837
|
},
|
|
2352
|
-
key: { color:
|
|
2353
|
-
value: { margin: 0, wordBreak: "break-word", fontFamily:
|
|
2354
|
-
empty: { fontSize:
|
|
2838
|
+
key: { color: tokens29.colorNeutralForeground3, margin: 0 },
|
|
2839
|
+
value: { margin: 0, wordBreak: "break-word", fontFamily: tokens29.fontFamilyMonospace },
|
|
2840
|
+
empty: { fontSize: tokens29.fontSizeBase200, color: tokens29.colorNeutralForeground3 }
|
|
2355
2841
|
});
|
|
2356
2842
|
function render(value) {
|
|
2357
2843
|
if (value === null || value === void 0) return "\u2014";
|
|
@@ -2363,45 +2849,45 @@ function GroundingPanel({
|
|
|
2363
2849
|
title = "What this answer used",
|
|
2364
2850
|
defaultOpen = false
|
|
2365
2851
|
}) {
|
|
2366
|
-
const styles =
|
|
2367
|
-
const id =
|
|
2852
|
+
const styles = useStyles31();
|
|
2853
|
+
const id = React22.useId();
|
|
2368
2854
|
const entries = Object.entries(grounding ?? {});
|
|
2369
2855
|
if (entries.length === 0) return null;
|
|
2370
|
-
return /* @__PURE__ */
|
|
2371
|
-
/* @__PURE__ */
|
|
2372
|
-
/* @__PURE__ */
|
|
2373
|
-
/* @__PURE__ */
|
|
2856
|
+
return /* @__PURE__ */ jsxs28(Disclosure, { id, defaultOpen, summary: title, children: [
|
|
2857
|
+
/* @__PURE__ */ jsx40("dl", { className: styles.grid, children: entries.map(([key, value]) => /* @__PURE__ */ jsxs28(React22.Fragment, { children: [
|
|
2858
|
+
/* @__PURE__ */ jsx40("dt", { className: styles.key, children: key }),
|
|
2859
|
+
/* @__PURE__ */ jsx40("dd", { className: styles.value, children: render(value) })
|
|
2374
2860
|
] }, key)) }),
|
|
2375
|
-
/* @__PURE__ */
|
|
2861
|
+
/* @__PURE__ */ jsx40(Text12, { as: "p", className: styles.empty, children: "These facts were supplied by the app, not produced by the model." })
|
|
2376
2862
|
] });
|
|
2377
2863
|
}
|
|
2378
2864
|
|
|
2379
2865
|
// src/grounding/ProviderAttribution.tsx
|
|
2380
|
-
import { makeStyles as
|
|
2866
|
+
import { makeStyles as makeStyles33, tokens as tokens30 } from "@fluentui/react-components";
|
|
2381
2867
|
import { ShieldErrorRegular as ShieldErrorRegular2 } from "@fluentui/react-icons";
|
|
2382
|
-
import { jsx as
|
|
2383
|
-
var
|
|
2868
|
+
import { jsx as jsx41, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2869
|
+
var useStyles32 = makeStyles33({
|
|
2384
2870
|
root: {
|
|
2385
2871
|
display: "flex",
|
|
2386
2872
|
alignItems: "center",
|
|
2387
|
-
gap:
|
|
2388
|
-
fontSize:
|
|
2389
|
-
color:
|
|
2873
|
+
gap: tokens30.spacingHorizontalXXS,
|
|
2874
|
+
fontSize: tokens30.fontSizeBase100,
|
|
2875
|
+
color: tokens30.colorNeutralForeground3
|
|
2390
2876
|
},
|
|
2391
|
-
guarded: { color:
|
|
2877
|
+
guarded: { color: tokens30.colorPaletteDarkOrangeForeground1 }
|
|
2392
2878
|
});
|
|
2393
2879
|
function ProviderAttribution({ provider, model, guarded }) {
|
|
2394
|
-
const styles =
|
|
2880
|
+
const styles = useStyles32();
|
|
2395
2881
|
if (!provider && !model && !guarded) return null;
|
|
2396
2882
|
const who = [provider, model].filter(Boolean).join(" \xB7 ");
|
|
2397
2883
|
if (guarded) {
|
|
2398
|
-
return /* @__PURE__ */
|
|
2399
|
-
/* @__PURE__ */
|
|
2884
|
+
return /* @__PURE__ */ jsxs29("span", { className: `${styles.root} ${styles.guarded}`, children: [
|
|
2885
|
+
/* @__PURE__ */ jsx41(ShieldErrorRegular2, { "aria-hidden": "true" }),
|
|
2400
2886
|
"Withheld and replaced with safe text",
|
|
2401
2887
|
who ? ` \u2014 not ${who}'s words` : ""
|
|
2402
2888
|
] });
|
|
2403
2889
|
}
|
|
2404
|
-
return /* @__PURE__ */
|
|
2890
|
+
return /* @__PURE__ */ jsxs29("span", { className: styles.root, children: [
|
|
2405
2891
|
"Answered by ",
|
|
2406
2892
|
who || "the agent"
|
|
2407
2893
|
] });
|
|
@@ -2411,57 +2897,57 @@ function messageAttribution(message) {
|
|
|
2411
2897
|
}
|
|
2412
2898
|
|
|
2413
2899
|
// src/actions/ActionCard.tsx
|
|
2414
|
-
import * as
|
|
2415
|
-
import { Text as
|
|
2416
|
-
import { jsx as
|
|
2417
|
-
var
|
|
2418
|
-
head: { display: "flex", alignItems: "center", gap:
|
|
2419
|
-
description: { color:
|
|
2420
|
-
footer: { display: "flex", gap:
|
|
2900
|
+
import * as React23 from "react";
|
|
2901
|
+
import { Text as Text13, makeStyles as makeStyles34, tokens as tokens31 } from "@fluentui/react-components";
|
|
2902
|
+
import { jsx as jsx42, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2903
|
+
var useStyles33 = makeStyles34({
|
|
2904
|
+
head: { display: "flex", alignItems: "center", gap: tokens31.spacingHorizontalXS },
|
|
2905
|
+
description: { color: tokens31.colorNeutralForeground2, fontSize: tokens31.fontSizeBase200 },
|
|
2906
|
+
footer: { display: "flex", gap: tokens31.spacingHorizontalS, justifyContent: "flex-end", marginTop: tokens31.spacingVerticalXS }
|
|
2421
2907
|
});
|
|
2422
2908
|
function ActionCard({ title, description, icon, pending, children, footer }) {
|
|
2423
|
-
const styles =
|
|
2424
|
-
return /* @__PURE__ */
|
|
2425
|
-
/* @__PURE__ */
|
|
2426
|
-
icon ?
|
|
2427
|
-
/* @__PURE__ */
|
|
2909
|
+
const styles = useStyles33();
|
|
2910
|
+
return /* @__PURE__ */ jsxs30(CardSurface, { emphasis: pending ? "attention" : "none", children: [
|
|
2911
|
+
/* @__PURE__ */ jsxs30("div", { className: styles.head, children: [
|
|
2912
|
+
icon ? React23.cloneElement(icon, { "aria-hidden": "true" }) : null,
|
|
2913
|
+
/* @__PURE__ */ jsx42(Text13, { weight: "semibold", children: title })
|
|
2428
2914
|
] }),
|
|
2429
|
-
description ? /* @__PURE__ */
|
|
2915
|
+
description ? /* @__PURE__ */ jsx42("span", { className: styles.description, children: description }) : null,
|
|
2430
2916
|
children,
|
|
2431
|
-
footer ? /* @__PURE__ */
|
|
2917
|
+
footer ? /* @__PURE__ */ jsx42("div", { className: styles.footer, children: footer }) : null
|
|
2432
2918
|
] });
|
|
2433
2919
|
}
|
|
2434
2920
|
|
|
2435
2921
|
// src/actions/ApprovalCard.tsx
|
|
2436
|
-
import * as
|
|
2437
|
-
import { Button as
|
|
2438
|
-
import { CheckmarkRegular, DismissRegular as
|
|
2922
|
+
import * as React25 from "react";
|
|
2923
|
+
import { Button as Button17, Spinner, makeStyles as makeStyles37, tokens as tokens34 } from "@fluentui/react-components";
|
|
2924
|
+
import { CheckmarkRegular, DismissRegular as DismissRegular3, EditRegular } from "@fluentui/react-icons";
|
|
2439
2925
|
|
|
2440
2926
|
// src/actions/ParameterReview.tsx
|
|
2441
|
-
import * as
|
|
2442
|
-
import { Input, makeStyles as
|
|
2443
|
-
import { jsx as
|
|
2444
|
-
var
|
|
2927
|
+
import * as React24 from "react";
|
|
2928
|
+
import { Input, makeStyles as makeStyles35, tokens as tokens32, Text as Text14 } from "@fluentui/react-components";
|
|
2929
|
+
import { jsx as jsx43, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2930
|
+
var useStyles34 = makeStyles35({
|
|
2445
2931
|
grid: {
|
|
2446
2932
|
display: "grid",
|
|
2447
2933
|
gridTemplateColumns: "minmax(110px, max-content) 1fr",
|
|
2448
|
-
gap: `${
|
|
2934
|
+
gap: `${tokens32.spacingVerticalXS} ${tokens32.spacingHorizontalM}`,
|
|
2449
2935
|
alignItems: "center",
|
|
2450
2936
|
margin: 0
|
|
2451
2937
|
},
|
|
2452
|
-
key: { margin: 0, color:
|
|
2938
|
+
key: { margin: 0, color: tokens32.colorNeutralForeground2, fontSize: tokens32.fontSizeBase200 },
|
|
2453
2939
|
value: { margin: 0 },
|
|
2454
2940
|
raw: {
|
|
2455
2941
|
whiteSpace: "pre-wrap",
|
|
2456
2942
|
wordBreak: "break-all",
|
|
2457
|
-
fontFamily:
|
|
2458
|
-
fontSize:
|
|
2459
|
-
color:
|
|
2943
|
+
fontFamily: tokens32.fontFamilyMonospace,
|
|
2944
|
+
fontSize: tokens32.fontSizeBase200,
|
|
2945
|
+
color: tokens32.colorNeutralForeground2
|
|
2460
2946
|
}
|
|
2461
2947
|
});
|
|
2462
2948
|
function ParameterReview({ argumentsJson, readOnly = true, onChange }) {
|
|
2463
|
-
const styles =
|
|
2464
|
-
const parsed =
|
|
2949
|
+
const styles = useStyles34();
|
|
2950
|
+
const parsed = React24.useMemo(() => {
|
|
2465
2951
|
try {
|
|
2466
2952
|
const value = JSON.parse(argumentsJson);
|
|
2467
2953
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -2470,18 +2956,18 @@ function ParameterReview({ argumentsJson, readOnly = true, onChange }) {
|
|
|
2470
2956
|
}
|
|
2471
2957
|
}, [argumentsJson]);
|
|
2472
2958
|
if (!parsed) {
|
|
2473
|
-
return /* @__PURE__ */
|
|
2474
|
-
/* @__PURE__ */
|
|
2475
|
-
/* @__PURE__ */
|
|
2959
|
+
return /* @__PURE__ */ jsxs31("div", { children: [
|
|
2960
|
+
/* @__PURE__ */ jsx43(Text14, { size: 200, children: "Arguments (unparsed)" }),
|
|
2961
|
+
/* @__PURE__ */ jsx43("pre", { className: styles.raw, children: argumentsJson || "(empty)" })
|
|
2476
2962
|
] });
|
|
2477
2963
|
}
|
|
2478
2964
|
const set = (key, next) => {
|
|
2479
2965
|
if (!onChange) return;
|
|
2480
2966
|
onChange(JSON.stringify({ ...parsed, [key]: next }));
|
|
2481
2967
|
};
|
|
2482
|
-
return /* @__PURE__ */
|
|
2483
|
-
/* @__PURE__ */
|
|
2484
|
-
/* @__PURE__ */
|
|
2968
|
+
return /* @__PURE__ */ jsx43("dl", { className: styles.grid, children: Object.entries(parsed).map(([key, value]) => /* @__PURE__ */ jsxs31(React24.Fragment, { children: [
|
|
2969
|
+
/* @__PURE__ */ jsx43("dt", { className: styles.key, children: key }),
|
|
2970
|
+
/* @__PURE__ */ jsx43("dd", { className: styles.value, children: readOnly ? /* @__PURE__ */ jsx43("span", { className: styles.raw, children: typeof value === "string" ? value : JSON.stringify(value) }) : /* @__PURE__ */ jsx43(
|
|
2485
2971
|
Input,
|
|
2486
2972
|
{
|
|
2487
2973
|
size: "small",
|
|
@@ -2494,32 +2980,32 @@ function ParameterReview({ argumentsJson, readOnly = true, onChange }) {
|
|
|
2494
2980
|
}
|
|
2495
2981
|
|
|
2496
2982
|
// src/actions/ActionResult.tsx
|
|
2497
|
-
import { MessageBar as MessageBar4, MessageBarBody as MessageBarBody4, MessageBarTitle as MessageBarTitle4, MessageBarActions as MessageBarActions4, Button as
|
|
2498
|
-
import { jsx as
|
|
2983
|
+
import { MessageBar as MessageBar4, MessageBarBody as MessageBarBody4, MessageBarTitle as MessageBarTitle4, MessageBarActions as MessageBarActions4, Button as Button16, makeStyles as makeStyles36, tokens as tokens33 } from "@fluentui/react-components";
|
|
2984
|
+
import { jsx as jsx44, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2499
2985
|
var INTENT2 = { succeeded: "success", failed: "error", denied: "warning" };
|
|
2500
2986
|
var TITLE = { succeeded: "Done", failed: "Failed", denied: "Not approved" };
|
|
2501
|
-
var
|
|
2502
|
-
id: { display: "block", marginTop:
|
|
2987
|
+
var useStyles35 = makeStyles36({
|
|
2988
|
+
id: { display: "block", marginTop: tokens33.spacingVerticalXXS, fontSize: tokens33.fontSizeBase100, color: tokens33.colorNeutralForeground3, fontFamily: tokens33.fontFamilyMonospace }
|
|
2503
2989
|
});
|
|
2504
2990
|
function ActionResult({ status, message, correlationId, onRetry }) {
|
|
2505
|
-
const styles =
|
|
2506
|
-
return /* @__PURE__ */
|
|
2507
|
-
/* @__PURE__ */
|
|
2508
|
-
/* @__PURE__ */
|
|
2991
|
+
const styles = useStyles35();
|
|
2992
|
+
return /* @__PURE__ */ jsxs32(MessageBar4, { intent: INTENT2[status], children: [
|
|
2993
|
+
/* @__PURE__ */ jsxs32(MessageBarBody4, { children: [
|
|
2994
|
+
/* @__PURE__ */ jsx44(MessageBarTitle4, { children: TITLE[status] }),
|
|
2509
2995
|
message,
|
|
2510
|
-
correlationId ? /* @__PURE__ */
|
|
2996
|
+
correlationId ? /* @__PURE__ */ jsxs32("span", { className: styles.id, children: [
|
|
2511
2997
|
"Correlation id: ",
|
|
2512
2998
|
correlationId
|
|
2513
2999
|
] }) : null
|
|
2514
3000
|
] }),
|
|
2515
|
-
status === "failed" && onRetry ? /* @__PURE__ */
|
|
3001
|
+
status === "failed" && onRetry ? /* @__PURE__ */ jsx44(MessageBarActions4, { children: /* @__PURE__ */ jsx44(Button16, { size: "small", onClick: onRetry, children: "Try again" }) }) : null
|
|
2516
3002
|
] });
|
|
2517
3003
|
}
|
|
2518
3004
|
|
|
2519
3005
|
// src/actions/ApprovalCard.tsx
|
|
2520
|
-
import { Fragment as Fragment8, jsx as
|
|
2521
|
-
var
|
|
2522
|
-
busy: { display: "flex", alignItems: "center", gap:
|
|
3006
|
+
import { Fragment as Fragment8, jsx as jsx45, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
3007
|
+
var useStyles36 = makeStyles37({
|
|
3008
|
+
busy: { display: "flex", alignItems: "center", gap: tokens34.spacingHorizontalXS, fontSize: tokens34.fontSizeBase200 }
|
|
2523
3009
|
});
|
|
2524
3010
|
function ApprovalCard({
|
|
2525
3011
|
toolCall,
|
|
@@ -2528,15 +3014,15 @@ function ApprovalCard({
|
|
|
2528
3014
|
allowEdit = false,
|
|
2529
3015
|
busy = false
|
|
2530
3016
|
}) {
|
|
2531
|
-
const styles =
|
|
2532
|
-
const [args, setArgs] =
|
|
2533
|
-
const [editing, setEditing] =
|
|
2534
|
-
const [decided, setDecided] =
|
|
3017
|
+
const styles = useStyles36();
|
|
3018
|
+
const [args, setArgs] = React25.useState(toolCall.argumentsJson);
|
|
3019
|
+
const [editing, setEditing] = React25.useState(false);
|
|
3020
|
+
const [decided, setDecided] = React25.useState(false);
|
|
2535
3021
|
const settled = toolCall.status === "succeeded" || toolCall.status === "failed" || toolCall.status === "denied";
|
|
2536
3022
|
if (settled) {
|
|
2537
|
-
return /* @__PURE__ */
|
|
2538
|
-
/* @__PURE__ */
|
|
2539
|
-
/* @__PURE__ */
|
|
3023
|
+
return /* @__PURE__ */ jsxs33(ActionCard, { title: toolCall.name, description: "Tool call", children: [
|
|
3024
|
+
/* @__PURE__ */ jsx45(ParameterReview, { argumentsJson: toolCall.argumentsJson }),
|
|
3025
|
+
/* @__PURE__ */ jsx45(
|
|
2540
3026
|
ActionResult,
|
|
2541
3027
|
{
|
|
2542
3028
|
status: toolCall.status === "succeeded" ? "succeeded" : toolCall.status === "denied" ? "denied" : "failed",
|
|
@@ -2557,29 +3043,29 @@ function ApprovalCard({
|
|
|
2557
3043
|
setDecided(true);
|
|
2558
3044
|
onDeny(toolCall);
|
|
2559
3045
|
};
|
|
2560
|
-
return /* @__PURE__ */
|
|
3046
|
+
return /* @__PURE__ */ jsx45(
|
|
2561
3047
|
ActionCard,
|
|
2562
3048
|
{
|
|
2563
3049
|
title: toolCall.name,
|
|
2564
3050
|
description: "The agent is asking to run this. Check the details before approving.",
|
|
2565
3051
|
pending: !locked,
|
|
2566
|
-
footer: locked ? /* @__PURE__ */
|
|
2567
|
-
/* @__PURE__ */
|
|
3052
|
+
footer: locked ? /* @__PURE__ */ jsxs33("span", { className: styles.busy, children: [
|
|
3053
|
+
/* @__PURE__ */ jsx45(Spinner, { size: "tiny" }),
|
|
2568
3054
|
" Submitting\u2026"
|
|
2569
|
-
] }) : /* @__PURE__ */
|
|
2570
|
-
allowEdit ? /* @__PURE__ */
|
|
2571
|
-
/* @__PURE__ */
|
|
2572
|
-
/* @__PURE__ */
|
|
3055
|
+
] }) : /* @__PURE__ */ jsxs33(Fragment8, { children: [
|
|
3056
|
+
allowEdit ? /* @__PURE__ */ jsx45(Button17, { size: "small", icon: /* @__PURE__ */ jsx45(EditRegular, {}), onClick: () => setEditing((v) => !v), children: editing ? "Done editing" : "Edit" }) : null,
|
|
3057
|
+
/* @__PURE__ */ jsx45(Button17, { size: "small", icon: /* @__PURE__ */ jsx45(DismissRegular3, {}), onClick: deny, disabled: locked, children: "Deny" }),
|
|
3058
|
+
/* @__PURE__ */ jsx45(Button17, { size: "small", appearance: "primary", icon: /* @__PURE__ */ jsx45(CheckmarkRegular, {}), onClick: approve, disabled: locked, children: "Approve" })
|
|
2573
3059
|
] }),
|
|
2574
|
-
children: /* @__PURE__ */
|
|
3060
|
+
children: /* @__PURE__ */ jsx45(ParameterReview, { argumentsJson: args, readOnly: !editing, onChange: setArgs })
|
|
2575
3061
|
}
|
|
2576
3062
|
);
|
|
2577
3063
|
}
|
|
2578
3064
|
|
|
2579
3065
|
// src/actions/ToolCallCard.tsx
|
|
2580
|
-
import * as
|
|
2581
|
-
import { Badge as
|
|
2582
|
-
import { jsx as
|
|
3066
|
+
import * as React26 from "react";
|
|
3067
|
+
import { Badge as Badge4, Spinner as Spinner2, makeStyles as makeStyles38, tokens as tokens35 } from "@fluentui/react-components";
|
|
3068
|
+
import { jsx as jsx46, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2583
3069
|
var LABEL = {
|
|
2584
3070
|
proposed: "Proposed",
|
|
2585
3071
|
running: "Running",
|
|
@@ -2594,41 +3080,41 @@ var COLOUR = {
|
|
|
2594
3080
|
failed: "danger",
|
|
2595
3081
|
denied: "warning"
|
|
2596
3082
|
};
|
|
2597
|
-
var
|
|
2598
|
-
head: { display: "flex", alignItems: "center", gap:
|
|
2599
|
-
name: { fontFamily:
|
|
3083
|
+
var useStyles37 = makeStyles38({
|
|
3084
|
+
head: { display: "flex", alignItems: "center", gap: tokens35.spacingHorizontalXS },
|
|
3085
|
+
name: { fontFamily: tokens35.fontFamilyMonospace, fontSize: tokens35.fontSizeBase200 },
|
|
2600
3086
|
result: {
|
|
2601
3087
|
whiteSpace: "pre-wrap",
|
|
2602
3088
|
wordBreak: "break-all",
|
|
2603
|
-
fontFamily:
|
|
2604
|
-
fontSize:
|
|
2605
|
-
marginTop:
|
|
3089
|
+
fontFamily: tokens35.fontFamilyMonospace,
|
|
3090
|
+
fontSize: tokens35.fontSizeBase200,
|
|
3091
|
+
marginTop: tokens35.spacingVerticalXS
|
|
2606
3092
|
}
|
|
2607
3093
|
});
|
|
2608
3094
|
function ToolCallCard({ toolCall, defaultExpanded = false }) {
|
|
2609
|
-
const styles =
|
|
2610
|
-
const id =
|
|
2611
|
-
return /* @__PURE__ */
|
|
3095
|
+
const styles = useStyles37();
|
|
3096
|
+
const id = React26.useId();
|
|
3097
|
+
return /* @__PURE__ */ jsx46(CardSurface, { children: /* @__PURE__ */ jsxs34(
|
|
2612
3098
|
Disclosure,
|
|
2613
3099
|
{
|
|
2614
3100
|
id,
|
|
2615
3101
|
defaultOpen: defaultExpanded,
|
|
2616
|
-
summary: /* @__PURE__ */
|
|
2617
|
-
/* @__PURE__ */
|
|
2618
|
-
/* @__PURE__ */
|
|
2619
|
-
toolCall.status === "running" ? /* @__PURE__ */
|
|
3102
|
+
summary: /* @__PURE__ */ jsxs34("span", { className: styles.head, children: [
|
|
3103
|
+
/* @__PURE__ */ jsx46("span", { className: styles.name, children: toolCall.name }),
|
|
3104
|
+
/* @__PURE__ */ jsx46(Badge4, { appearance: "tint", color: COLOUR[toolCall.status], children: LABEL[toolCall.status] }),
|
|
3105
|
+
toolCall.status === "running" ? /* @__PURE__ */ jsx46(Spinner2, { size: "extra-tiny" }) : null
|
|
2620
3106
|
] }),
|
|
2621
3107
|
children: [
|
|
2622
|
-
/* @__PURE__ */
|
|
2623
|
-
toolCall.resultText ? /* @__PURE__ */
|
|
2624
|
-
toolCall.failure ? /* @__PURE__ */
|
|
3108
|
+
/* @__PURE__ */ jsx46(ParameterReview, { argumentsJson: toolCall.argumentsJson }),
|
|
3109
|
+
toolCall.resultText ? /* @__PURE__ */ jsx46("div", { className: styles.result, children: toolCall.resultText }) : null,
|
|
3110
|
+
toolCall.failure ? /* @__PURE__ */ jsx46("div", { className: styles.result, children: toolCall.failure.message }) : null
|
|
2625
3111
|
]
|
|
2626
3112
|
}
|
|
2627
3113
|
) });
|
|
2628
3114
|
}
|
|
2629
3115
|
|
|
2630
3116
|
// src/host/AgentKitHostProvider.tsx
|
|
2631
|
-
import * as
|
|
3117
|
+
import * as React27 from "react";
|
|
2632
3118
|
import { FluentProvider, IdPrefixProvider } from "@fluentui/react-components";
|
|
2633
3119
|
|
|
2634
3120
|
// src/theme/index.ts
|
|
@@ -2665,16 +3151,16 @@ function resolveHostTheme(input = {}) {
|
|
|
2665
3151
|
var nextAgentIdPrefix = createIdPrefixCounter("dvkak");
|
|
2666
3152
|
|
|
2667
3153
|
// src/host/AgentKitHostProvider.tsx
|
|
2668
|
-
import { jsx as
|
|
3154
|
+
import { jsx as jsx47 } from "react/jsx-runtime";
|
|
2669
3155
|
function AgentKitHostProvider(props) {
|
|
2670
3156
|
const { children, theme, hostTheme, isDarkTheme, targetDocument, className, style } = props;
|
|
2671
|
-
const [generated] =
|
|
3157
|
+
const [generated] = React27.useState(nextAgentIdPrefix);
|
|
2672
3158
|
const idPrefix = props.idPrefix ?? generated;
|
|
2673
|
-
const resolved =
|
|
3159
|
+
const resolved = React27.useMemo(
|
|
2674
3160
|
() => resolveHostTheme({ theme, hostTheme, isDarkTheme }),
|
|
2675
3161
|
[theme, hostTheme, isDarkTheme]
|
|
2676
3162
|
);
|
|
2677
|
-
return /* @__PURE__ */
|
|
3163
|
+
return /* @__PURE__ */ jsx47(IdPrefixProvider, { value: idPrefix, children: /* @__PURE__ */ jsx47(
|
|
2678
3164
|
FluentProvider,
|
|
2679
3165
|
{
|
|
2680
3166
|
theme: resolved,
|
|
@@ -2983,12 +3469,14 @@ export {
|
|
|
2983
3469
|
AgentAppShell,
|
|
2984
3470
|
AgentAvatar,
|
|
2985
3471
|
AgentKitHostProvider,
|
|
3472
|
+
AgentLauncher,
|
|
2986
3473
|
AgentOpsPanel,
|
|
2987
3474
|
AgentPicker,
|
|
2988
3475
|
AgentStatusBadge,
|
|
2989
3476
|
AnswerWithCitations,
|
|
2990
3477
|
AppRail,
|
|
2991
3478
|
ApprovalCard,
|
|
3479
|
+
AssistantPanel,
|
|
2992
3480
|
AvailabilityBanner,
|
|
2993
3481
|
CitationChip,
|
|
2994
3482
|
CitationList,
|
|
@@ -3000,6 +3488,7 @@ export {
|
|
|
3000
3488
|
DEFAULT_GROUP_WINDOW_MS,
|
|
3001
3489
|
DayDivider,
|
|
3002
3490
|
EmptyConversation,
|
|
3491
|
+
FeedbackPanel,
|
|
3003
3492
|
GlobalSearchBar,
|
|
3004
3493
|
GroundingPanel,
|
|
3005
3494
|
LiveAnnouncer,
|
|
@@ -3061,6 +3550,7 @@ export {
|
|
|
3061
3550
|
splitTextByCitations,
|
|
3062
3551
|
useConversation,
|
|
3063
3552
|
useFocusRestore,
|
|
3553
|
+
useReturnFocus,
|
|
3064
3554
|
useRovingTabindex,
|
|
3065
3555
|
useStickyScroll,
|
|
3066
3556
|
useVisuallyHiddenStyles
|