@case-framework/survey-assistant 0.6.0 → 0.8.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 +67 -7
- package/dist/{attachments-B0hg3vpT.mjs → attachments-BuNni5vB.mjs} +1 -1
- package/dist/{attachments-B0hg3vpT.mjs.map → attachments-BuNni5vB.mjs.map} +1 -1
- package/dist/{authoring-references-CW38pYzK.mjs → authoring-references-DbuOKerg.mjs} +13 -4
- package/dist/authoring-references-DbuOKerg.mjs.map +1 -0
- package/dist/{capabilities-DVTfogjv.d.mts → capabilities-CmeeAjEc.d.mts} +3 -4
- package/dist/capabilities-CmeeAjEc.d.mts.map +1 -0
- package/dist/capabilities-DCMA71PP.mjs +58 -0
- package/dist/capabilities-DCMA71PP.mjs.map +1 -0
- package/dist/capabilities-default.d.mts +13 -12
- package/dist/capabilities-default.d.mts.map +1 -1
- package/dist/capabilities-default.mjs +2 -414
- package/dist/{constants-BMGTgfjv.d.mts → constants-B6HzpEsx.d.mts} +7 -28
- package/dist/constants-B6HzpEsx.d.mts.map +1 -0
- package/dist/{constants-0UHGFcRJ.mjs → constants-Ct-vv9cu.mjs} +1 -1
- package/dist/{constants-0UHGFcRJ.mjs.map → constants-Ct-vv9cu.mjs.map} +1 -1
- package/dist/controller-proxy-D7uQfm5f.d.mts +65 -0
- package/dist/controller-proxy-D7uQfm5f.d.mts.map +1 -0
- package/dist/{controller-proxy-DMTqer6T.mjs → controller-proxy-DEeFl9IA.mjs} +29 -26
- package/dist/controller-proxy-DEeFl9IA.mjs.map +1 -0
- package/dist/default-fhSon2RM.mjs +760 -0
- package/dist/default-fhSon2RM.mjs.map +1 -0
- package/dist/{digest-SJmoYVaK.d.mts → digest-C39WyAWG.d.mts} +2 -3
- package/dist/digest-C39WyAWG.d.mts.map +1 -0
- package/dist/digest.d.mts +1 -1
- package/dist/digest.mjs.map +1 -1
- package/dist/{engine-CQwOAcwK.mjs → engine-nXoCWYpQ.mjs} +2821 -2018
- package/dist/engine-nXoCWYpQ.mjs.map +1 -0
- package/dist/engine.d.mts +3 -3
- package/dist/engine.mjs +3 -3
- package/dist/{fair-guidance-CRYCRxQm.mjs → fair-guidance-BmO4PswW.mjs} +1 -1
- package/dist/{fair-guidance-CRYCRxQm.mjs.map → fair-guidance-BmO4PswW.mjs.map} +1 -1
- package/dist/{index-D6nqkz0O.d.mts → index-Ciq7vHIs.d.mts} +121 -197
- package/dist/index-Ciq7vHIs.d.mts.map +1 -0
- package/dist/{index-DvTqML-0.d.mts → index-D7wT6P3t.d.mts} +294 -63
- package/dist/index-D7wT6P3t.d.mts.map +1 -0
- package/dist/index-WB5kfnz0.d.mts +348 -0
- package/dist/index-WB5kfnz0.d.mts.map +1 -0
- package/dist/{index-B0lxsAzx.d.mts → index-r5riv4md.d.mts} +50 -29
- package/dist/index-r5riv4md.d.mts.map +1 -0
- package/dist/{lifecycle-BmGAIUlv.d.mts → lifecycle-Dm8u7QFh.d.mts} +40 -18
- package/dist/lifecycle-Dm8u7QFh.d.mts.map +1 -0
- package/dist/{memory-thread-repository-CjFGVNZh.mjs → memory-thread-repository-DAnOGIB3.mjs} +89 -34
- package/dist/memory-thread-repository-DAnOGIB3.mjs.map +1 -0
- package/dist/{protocol-DJUP4gc0.mjs → protocol-CF4Bh_Ch.mjs} +182 -50
- package/dist/protocol-CF4Bh_Ch.mjs.map +1 -0
- package/dist/protocol.d.mts +4 -4
- package/dist/protocol.mjs +3 -3
- package/dist/react-C_GY-Fsc.mjs +1727 -0
- package/dist/react-C_GY-Fsc.mjs.map +1 -0
- package/dist/react-integration.d.mts +2 -2
- package/dist/react-integration.mjs +2 -2
- package/dist/react.d.mts +3 -3
- package/dist/react.mjs +3 -3
- package/dist/references/assistant-operations.md +143 -68
- package/dist/references/core-rules.md +6 -3
- package/dist/references/embedded-forms.md +34 -14
- package/dist/references/expressions.md +238 -48
- package/dist/references/fair-by-design.md +9 -9
- package/dist/references/item-types.md +306 -72
- package/dist/references/localization.md +5 -4
- package/dist/references/response-variables.md +38 -0
- package/dist/references/rich-text-content.md +60 -27
- package/dist/references/source-material-surveys.md +13 -5
- package/dist/references/survey-data-model.md +32 -9
- package/dist/{request-context-BjTHNcDd.mjs → request-context-Dg4jSwN1.mjs} +4 -10
- package/dist/request-context-Dg4jSwN1.mjs.map +1 -0
- package/dist/{request-guardrails-TmgQtqp4.mjs → request-guardrails-C0ugBOp0.mjs} +6 -5
- package/dist/request-guardrails-C0ugBOp0.mjs.map +1 -0
- package/dist/server-agent.d.mts +53 -44
- package/dist/server-agent.d.mts.map +1 -1
- package/dist/server-agent.mjs +48 -27
- package/dist/server-agent.mjs.map +1 -1
- package/dist/server-runtime.d.mts +36 -49
- package/dist/server-runtime.d.mts.map +1 -1
- package/dist/server-runtime.mjs +17 -12
- package/dist/server-runtime.mjs.map +1 -1
- package/dist/server-tasks.d.mts +2 -2
- package/dist/server-tasks.mjs +2 -313
- package/dist/server-tools.d.mts +1 -1
- package/dist/server-tools.mjs +1 -1
- package/dist/server.d.mts +13 -36
- package/dist/server.d.mts.map +1 -1
- package/dist/server.mjs +5 -5
- package/dist/server.mjs.map +1 -1
- package/dist/storage-postgres.d.mts +9 -25
- package/dist/storage-postgres.d.mts.map +1 -1
- package/dist/storage-postgres.mjs +5 -4
- package/dist/storage-postgres.mjs.map +1 -1
- package/dist/{tasks-DxzD25Zc.d.mts → tasks-B9h3LPam.d.mts} +19 -35
- package/dist/tasks-B9h3LPam.d.mts.map +1 -0
- package/dist/tasks-BZEiwgxA.mjs +396 -0
- package/dist/tasks-BZEiwgxA.mjs.map +1 -0
- package/dist/thread-documents-DrHbaXqP.d.mts +119 -0
- package/dist/thread-documents-DrHbaXqP.d.mts.map +1 -0
- package/dist/{thread-handlers-AbQbt4sX.d.mts → thread-handlers-Bef0td9N.d.mts} +10 -40
- package/dist/thread-handlers-Bef0td9N.d.mts.map +1 -0
- package/dist/{tools-CFh35R4d.mjs → tools-CEsv-WoO.mjs} +705 -578
- package/dist/tools-CEsv-WoO.mjs.map +1 -0
- package/dist/ui.css +1 -1
- package/dist/ui.d.mts +17 -55
- package/dist/ui.d.mts.map +1 -1
- package/dist/ui.mjs +759 -171
- package/dist/ui.mjs.map +1 -1
- package/docs/integration.md +51 -1
- package/package.json +49 -42
- package/dist/authoring-references-CW38pYzK.mjs.map +0 -1
- package/dist/capabilities-DVTfogjv.d.mts.map +0 -1
- package/dist/capabilities-default.mjs.map +0 -1
- package/dist/constants-BMGTgfjv.d.mts.map +0 -1
- package/dist/controller-proxy-DMTqer6T.mjs.map +0 -1
- package/dist/controller-proxy-mRvez2qw.d.mts +0 -85
- package/dist/controller-proxy-mRvez2qw.d.mts.map +0 -1
- package/dist/digest-SJmoYVaK.d.mts.map +0 -1
- package/dist/engine-CQwOAcwK.mjs.map +0 -1
- package/dist/form-authoring-kQDgC5oz.mjs +0 -155
- package/dist/form-authoring-kQDgC5oz.mjs.map +0 -1
- package/dist/index-B0lxsAzx.d.mts.map +0 -1
- package/dist/index-BS-Xjk1h.d.mts +0 -224
- package/dist/index-BS-Xjk1h.d.mts.map +0 -1
- package/dist/index-D6nqkz0O.d.mts.map +0 -1
- package/dist/index-DvTqML-0.d.mts.map +0 -1
- package/dist/lifecycle-BmGAIUlv.d.mts.map +0 -1
- package/dist/memory-thread-repository-CjFGVNZh.mjs.map +0 -1
- package/dist/protocol-DJUP4gc0.mjs.map +0 -1
- package/dist/react-Dqlmasrs.mjs +0 -768
- package/dist/react-Dqlmasrs.mjs.map +0 -1
- package/dist/request-context-BjTHNcDd.mjs.map +0 -1
- package/dist/request-guardrails-TmgQtqp4.mjs.map +0 -1
- package/dist/server-tasks.mjs.map +0 -1
- package/dist/tasks-DxzD25Zc.d.mts.map +0 -1
- package/dist/thread-documents-rmd6nyX9.d.mts +0 -107
- package/dist/thread-documents-rmd6nyX9.d.mts.map +0 -1
- package/dist/thread-handlers-AbQbt4sX.d.mts.map +0 -1
- package/dist/tools-CFh35R4d.mjs.map +0 -1
package/dist/ui.mjs
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import { n as isSurveyAssistantAttachmentMediaType, t as SURVEY_ASSISTANT_ATTACHMENT_MEDIA_TYPES } from "./attachments-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { Ft as isSurveyAssistantErrorRetryable, It as parseSurveyAssistantError, Vt as getSurveyAssistantEmbeddedBinaryMarker, l as surveyAssistantTurnFinalSchema, n as SURVEY_ASSISTANT_TURN_FINAL_PART_TYPE } from "./protocol-CF4Bh_Ch.mjs";
|
|
3
|
+
import { n as isSurveyAssistantAttachmentMediaType, t as SURVEY_ASSISTANT_ATTACHMENT_MEDIA_TYPES } from "./attachments-BuNni5vB.mjs";
|
|
4
|
+
import { E as isSurveyAssistantTurnActive, S as parseSurveyChangeSet, T as unwrapSurveyAssistantToolOutput, _ as createSurveyAssistantThreadClient, a as createSurveyAssistantSupportDetails, c as estimateSurveyAssistantSupportBundleBytes, d as prepareSurveyAssistantSupportBundle, i as SURVEY_ASSISTANT_DEFAULT_SUPPORT_BUNDLE_SELECTION, l as generateSurveyAssistantSupportBundle, m as createSurveyAssistantDiagnosticStore, o as createSurveyAssistantSupportMailto, r as useSurveyAssistantModelCatalog, s as downloadSurveyAssistantSupportBundle, t as useSurveyAssistantSession, u as isSurveyAssistantSupportBundleEnabled } from "./react-C_GY-Fsc.mjs";
|
|
5
|
+
import { a as connectSurveyAssistantThreadLauncher } from "./controller-proxy-DEeFl9IA.mjs";
|
|
6
6
|
import { getToolName, isFileUIPart, isReasoningUIPart, isToolUIPart } from "ai";
|
|
7
7
|
import { createContext, createElement, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
8
|
-
import { Collapsible
|
|
8
|
+
import { Collapsible } from "@base-ui/react/collapsible";
|
|
9
9
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
10
10
|
import { clsx } from "clsx";
|
|
11
11
|
import { twMerge } from "tailwind-merge";
|
|
12
|
-
import {
|
|
13
|
-
import { ArrowDownIcon, ArrowUpIcon, BotIcon, BrainIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, ClockIcon, DotIcon, FileIcon, HistoryIcon, ListChecksIcon, LoaderCircleIcon, MessageSquarePlusIcon, PaperclipIcon, PencilIcon, PlusIcon, SearchIcon, SparklesIcon, SquareIcon, Trash2Icon, WandSparklesIcon, WrenchIcon, XCircleIcon, XIcon } from "lucide-react";
|
|
12
|
+
import { ArrowDownIcon, ArrowUpIcon, BotIcon, BrainIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, ClockIcon, CopyIcon, DotIcon, DownloadIcon, FileIcon, HistoryIcon, ListChecksIcon, LoaderCircleIcon, MailIcon, MessageSquarePlusIcon, PackageOpenIcon, PaperclipIcon, PencilIcon, PlusIcon, SearchIcon, SparklesIcon, SquareIcon, Trash2Icon, WandSparklesIcon, WrenchIcon, XCircleIcon, XIcon } from "lucide-react";
|
|
14
13
|
import { motion } from "motion/react";
|
|
15
14
|
import { createLocalizationTranslator, mergeLocalizationCatalogs } from "@case-framework/ui-localization";
|
|
16
15
|
import { cva } from "class-variance-authority";
|
|
16
|
+
import { Button } from "@base-ui/react/button";
|
|
17
17
|
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
|
|
18
|
+
import { Tooltip } from "@base-ui/react/tooltip";
|
|
19
|
+
import { Select } from "@base-ui/react/select";
|
|
18
20
|
import { Streamdown } from "streamdown";
|
|
19
21
|
import { bundledLanguages } from "shiki/langs";
|
|
22
|
+
import { Checkbox } from "@base-ui/react/checkbox";
|
|
23
|
+
import { Dialog } from "@base-ui/react/dialog";
|
|
20
24
|
//#region src/ui/internal/collapsible.tsx
|
|
21
25
|
function Collapsible$1({ ...props }) {
|
|
22
26
|
return /* @__PURE__ */ jsx(Collapsible.Root, {
|
|
@@ -25,13 +29,13 @@ function Collapsible$1({ ...props }) {
|
|
|
25
29
|
});
|
|
26
30
|
}
|
|
27
31
|
function CollapsibleTrigger({ ...props }) {
|
|
28
|
-
return /* @__PURE__ */ jsx(Collapsible.
|
|
32
|
+
return /* @__PURE__ */ jsx(Collapsible.Trigger, {
|
|
29
33
|
"data-slot": "collapsible-trigger",
|
|
30
34
|
...props
|
|
31
35
|
});
|
|
32
36
|
}
|
|
33
37
|
function CollapsibleContent({ ...props }) {
|
|
34
|
-
return /* @__PURE__ */ jsx(Collapsible.
|
|
38
|
+
return /* @__PURE__ */ jsx(Collapsible.Panel, {
|
|
35
39
|
"data-slot": "collapsible-content",
|
|
36
40
|
...props
|
|
37
41
|
});
|
|
@@ -247,6 +251,11 @@ const surveyAssistantEnMessages = {
|
|
|
247
251
|
dismiss: "Dismiss",
|
|
248
252
|
dismissAssistant: "Dismiss assistant error",
|
|
249
253
|
retry: "Try again",
|
|
254
|
+
exportDetails: "Export details",
|
|
255
|
+
showProviderDetails: "Show full provider message",
|
|
256
|
+
hideProviderDetails: "Hide provider message",
|
|
257
|
+
upstreamStatus: "Provider status {status}",
|
|
258
|
+
providerRequestId: "Request {requestId}",
|
|
250
259
|
fallbackDetail: "The assistant hit an error on the previous turn.",
|
|
251
260
|
model_unavailable: {
|
|
252
261
|
title: "Model unavailable",
|
|
@@ -272,6 +281,7 @@ const surveyAssistantEnMessages = {
|
|
|
272
281
|
threads: {
|
|
273
282
|
newChat: "New chat",
|
|
274
283
|
history: "Chat history",
|
|
284
|
+
exportSupportBundle: "Export support bundle",
|
|
275
285
|
recent: "Recent chats",
|
|
276
286
|
search: "Search chats",
|
|
277
287
|
searching: "Searching older chats…",
|
|
@@ -285,6 +295,48 @@ const surveyAssistantEnMessages = {
|
|
|
285
295
|
delete: "Delete {title}",
|
|
286
296
|
deleteTitle: "Delete chat",
|
|
287
297
|
deleteConfirm: "Delete \"{title}\" and its attachments?"
|
|
298
|
+
},
|
|
299
|
+
supportBundle: {
|
|
300
|
+
title: "Export support bundle",
|
|
301
|
+
description: "Choose which broad data categories to include. The ZIP is created and downloaded in this browser.",
|
|
302
|
+
close: "Close export dialog",
|
|
303
|
+
preparing: "Preparing diagnostic data…",
|
|
304
|
+
preparationFailed: "The support bundle could not be prepared",
|
|
305
|
+
generationFailed: "The support bundle could not be generated.",
|
|
306
|
+
chooseData: "Data to include",
|
|
307
|
+
core: {
|
|
308
|
+
title: "Core technical diagnostics (always included)",
|
|
309
|
+
description: "Request and turn identifiers, timing, status and error details, counters, and availability information."
|
|
310
|
+
},
|
|
311
|
+
categories: {
|
|
312
|
+
conversation: {
|
|
313
|
+
title: "Conversation and agent activity",
|
|
314
|
+
description: "Messages, visible reasoning, tool activity, and apply results."
|
|
315
|
+
},
|
|
316
|
+
survey: {
|
|
317
|
+
title: "Survey data",
|
|
318
|
+
description: "The submitted survey and a snapshot captured when this dialog opened."
|
|
319
|
+
},
|
|
320
|
+
attachments: {
|
|
321
|
+
title: "Attachments",
|
|
322
|
+
description: "Available source PDFs and images from this browser session."
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
sensitiveNote: "Conversation, reasoning, surveys, and attachments can contain sensitive research or authoring data. Deselect a category if you do not want to share it.",
|
|
326
|
+
estimatedSize: "Estimated ZIP size",
|
|
327
|
+
emailWarning: "This may be too large for some email providers.",
|
|
328
|
+
tooLarge: "The selection is too large. Deselect a category before downloading.",
|
|
329
|
+
unavailable: "{count} diagnostic component is unavailable or was truncated.",
|
|
330
|
+
unavailablePlural: "{count} diagnostic components are unavailable or were truncated.",
|
|
331
|
+
localOnly: "Nothing is sent automatically. You decide whether and how to share the downloaded ZIP.",
|
|
332
|
+
download: "Download support bundle",
|
|
333
|
+
downloadAgain: "Download again",
|
|
334
|
+
downloaded: "Downloaded {filename}. Attach it manually when contacting support.",
|
|
335
|
+
openEmail: "Open email draft",
|
|
336
|
+
supportDetails: "Support details to include with your request",
|
|
337
|
+
copyDetails: "Copy support details",
|
|
338
|
+
detailsCopied: "Support details copied",
|
|
339
|
+
copyDetailsFailed: "The support details could not be copied. Select and copy them manually."
|
|
288
340
|
}
|
|
289
341
|
};
|
|
290
342
|
//#endregion
|
|
@@ -464,6 +516,11 @@ const surveyAssistantNlMessages = {
|
|
|
464
516
|
dismiss: "Sluiten",
|
|
465
517
|
dismissAssistant: "Assistentfout sluiten",
|
|
466
518
|
retry: "Opnieuw proberen",
|
|
519
|
+
exportDetails: "Details exporteren",
|
|
520
|
+
showProviderDetails: "Volledig providerbericht tonen",
|
|
521
|
+
hideProviderDetails: "Providerbericht verbergen",
|
|
522
|
+
upstreamStatus: "Providerstatus {status}",
|
|
523
|
+
providerRequestId: "Verzoek {requestId}",
|
|
467
524
|
fallbackDetail: "Er is tijdens de vorige beurt een fout opgetreden.",
|
|
468
525
|
model_unavailable: {
|
|
469
526
|
title: "Model niet beschikbaar",
|
|
@@ -489,6 +546,7 @@ const surveyAssistantNlMessages = {
|
|
|
489
546
|
threads: {
|
|
490
547
|
newChat: "Nieuwe chat",
|
|
491
548
|
history: "Chatgeschiedenis",
|
|
549
|
+
exportSupportBundle: "Supportbundel exporteren",
|
|
492
550
|
recent: "Recente chats",
|
|
493
551
|
search: "Chats zoeken",
|
|
494
552
|
searching: "Oudere chats zoeken…",
|
|
@@ -502,6 +560,48 @@ const surveyAssistantNlMessages = {
|
|
|
502
560
|
delete: "{title} verwijderen",
|
|
503
561
|
deleteTitle: "Chat verwijderen",
|
|
504
562
|
deleteConfirm: "\"{title}\" en de bijlagen verwijderen?"
|
|
563
|
+
},
|
|
564
|
+
supportBundle: {
|
|
565
|
+
title: "Supportbundel exporteren",
|
|
566
|
+
description: "Kies welke brede gegevenscategorieën worden opgenomen. Het ZIP-bestand wordt in deze browser gemaakt en gedownload.",
|
|
567
|
+
close: "Exportvenster sluiten",
|
|
568
|
+
preparing: "Diagnostische gegevens voorbereiden…",
|
|
569
|
+
preparationFailed: "De supportbundel kon niet worden voorbereid",
|
|
570
|
+
generationFailed: "De supportbundel kon niet worden gemaakt.",
|
|
571
|
+
chooseData: "Op te nemen gegevens",
|
|
572
|
+
core: {
|
|
573
|
+
title: "Technische basisgegevens (altijd opgenomen)",
|
|
574
|
+
description: "Verzoek- en beurt-ID's, timing, status- en foutdetails, aantallen en beschikbaarheid."
|
|
575
|
+
},
|
|
576
|
+
categories: {
|
|
577
|
+
conversation: {
|
|
578
|
+
title: "Gesprek en agentactiviteit",
|
|
579
|
+
description: "Berichten, zichtbare redenering, hulpmiddelactiviteit en toepassingsresultaten."
|
|
580
|
+
},
|
|
581
|
+
survey: {
|
|
582
|
+
title: "Surveygegevens",
|
|
583
|
+
description: "De verzonden survey en een momentopname van toen dit venster werd geopend."
|
|
584
|
+
},
|
|
585
|
+
attachments: {
|
|
586
|
+
title: "Bijlagen",
|
|
587
|
+
description: "Beschikbare bron-pdf's en afbeeldingen uit deze browsersessie."
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
sensitiveNote: "Gesprek, redenering, surveys en bijlagen kunnen gevoelige onderzoeks- of auteursgegevens bevatten. Schakel een categorie uit als je die niet wilt delen.",
|
|
591
|
+
estimatedSize: "Geschatte ZIP-grootte",
|
|
592
|
+
emailWarning: "Dit bestand kan te groot zijn voor sommige e-mailproviders.",
|
|
593
|
+
tooLarge: "De selectie is te groot. Schakel een categorie uit voordat je downloadt.",
|
|
594
|
+
unavailable: "{count} diagnostisch onderdeel is niet beschikbaar of is ingekort.",
|
|
595
|
+
unavailablePlural: "{count} diagnostische onderdelen zijn niet beschikbaar of zijn ingekort.",
|
|
596
|
+
localOnly: "Er wordt niets automatisch verzonden. Je bepaalt zelf of en hoe je het gedownloade ZIP-bestand deelt.",
|
|
597
|
+
download: "Supportbundel downloaden",
|
|
598
|
+
downloadAgain: "Opnieuw downloaden",
|
|
599
|
+
downloaded: "{filename} is gedownload. Voeg het handmatig toe wanneer je contact opneemt met support.",
|
|
600
|
+
openEmail: "E-mailconcept openen",
|
|
601
|
+
supportDetails: "Supportgegevens voor je verzoek",
|
|
602
|
+
copyDetails: "Supportgegevens kopiëren",
|
|
603
|
+
detailsCopied: "Supportgegevens gekopieerd",
|
|
604
|
+
copyDetailsFailed: "De supportgegevens konden niet worden gekopieerd. Selecteer en kopieer ze handmatig."
|
|
505
605
|
}
|
|
506
606
|
};
|
|
507
607
|
//#endregion
|
|
@@ -549,15 +649,18 @@ const formatDuration = (durationSeconds) => {
|
|
|
549
649
|
const ChainOfThought = memo(({ className, isStreaming = false, open, defaultOpen, defaultDuration, onOpenChange, duration: durationProp, autoClose = true, children, ...props }) => {
|
|
550
650
|
const resolvedDefaultOpen = defaultOpen ?? isStreaming;
|
|
551
651
|
const isExplicitlyClosed = defaultOpen === false;
|
|
552
|
-
const [
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
652
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(resolvedDefaultOpen);
|
|
653
|
+
const isOpen = open ?? uncontrolledOpen;
|
|
654
|
+
const setIsOpen = useCallback((nextOpen) => {
|
|
655
|
+
if (open === void 0) setUncontrolledOpen(nextOpen);
|
|
656
|
+
if (nextOpen !== isOpen) onOpenChange?.(nextOpen);
|
|
657
|
+
}, [
|
|
658
|
+
open,
|
|
659
|
+
isOpen,
|
|
660
|
+
onOpenChange
|
|
661
|
+
]);
|
|
662
|
+
const [measuredDuration, setDuration] = useState(defaultDuration);
|
|
663
|
+
const duration = durationProp ?? measuredDuration;
|
|
561
664
|
const hasEverStreamedRef = useRef(isStreaming);
|
|
562
665
|
const [hasAutoClosed, setHasAutoClosed] = useState(false);
|
|
563
666
|
const startTimeRef = useRef(null);
|
|
@@ -639,7 +742,7 @@ const ChainOfThoughtHeader = memo(({ className, children, getThinkingMessage, ..
|
|
|
639
742
|
});
|
|
640
743
|
});
|
|
641
744
|
const ChainOfThoughtContent = memo(({ className, ...props }) => /* @__PURE__ */ jsx(CollapsibleContent, {
|
|
642
|
-
className: cn("mt-2", "data-
|
|
745
|
+
className: cn("mt-2", "data-ending-style:opacity-0 data-ending-style:-translate-y-2 data-starting-style:-translate-y-2 outline-none transition-[opacity,transform,scale] ease-out motion-reduce:transition-none", className),
|
|
643
746
|
...props
|
|
644
747
|
}));
|
|
645
748
|
const stepStatusStyles = {
|
|
@@ -701,8 +804,8 @@ const buttonVariants = cva("inline-flex shrink-0 items-center justify-center gap
|
|
|
701
804
|
size: "default"
|
|
702
805
|
}
|
|
703
806
|
});
|
|
704
|
-
const Button = ({ className, variant = "default", size = "default",
|
|
705
|
-
return /* @__PURE__ */ jsx(
|
|
807
|
+
const Button$1 = ({ className, variant = "default", size = "default", ...props }) => {
|
|
808
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
706
809
|
className: cn(buttonVariants({
|
|
707
810
|
variant,
|
|
708
811
|
size,
|
|
@@ -752,7 +855,7 @@ const ConversationScrollButton = ({ className, ...props }) => {
|
|
|
752
855
|
const handleScrollToBottom = useCallback(() => {
|
|
753
856
|
scrollToBottom();
|
|
754
857
|
}, [scrollToBottom]);
|
|
755
|
-
return !isAtBottom && /* @__PURE__ */ jsx(Button, {
|
|
858
|
+
return !isAtBottom && /* @__PURE__ */ jsx(Button$1, {
|
|
756
859
|
className: cn("absolute left-1/2 z-10 size-8 -translate-x-1/2 rounded-full border border-background/60 bg-foreground text-background shadow-lg ring-1 ring-border/50 hover:bg-foreground/85 hover:text-background", className),
|
|
757
860
|
"aria-label": t("conversation.scrollToLatest"),
|
|
758
861
|
onClick: handleScrollToBottom,
|
|
@@ -777,17 +880,43 @@ const MessageContent = ({ children, className, ...props }) => /* @__PURE__ */ js
|
|
|
777
880
|
});
|
|
778
881
|
//#endregion
|
|
779
882
|
//#region src/ui/internal/tooltip.tsx
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
className: "case-survey-assistant case-survey-assistant-portal",
|
|
785
|
-
children: /* @__PURE__ */ jsx(Tooltip.Content, {
|
|
786
|
-
className: cn("z-50 max-w-64 rounded-md bg-foreground px-3 py-1.5 text-center text-background text-xs shadow-md data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0", className),
|
|
787
|
-
sideOffset,
|
|
883
|
+
function TooltipProvider({ delay = 700, ...props }) {
|
|
884
|
+
return /* @__PURE__ */ jsx(Tooltip.Provider, {
|
|
885
|
+
"data-slot": "tooltip-provider",
|
|
886
|
+
delay,
|
|
788
887
|
...props
|
|
789
|
-
})
|
|
790
|
-
}
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
function Tooltip$1({ ...props }) {
|
|
891
|
+
return /* @__PURE__ */ jsx(Tooltip.Root, {
|
|
892
|
+
"data-slot": "tooltip",
|
|
893
|
+
...props
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
function TooltipTrigger({ ...props }) {
|
|
897
|
+
return /* @__PURE__ */ jsx(Tooltip.Trigger, {
|
|
898
|
+
"data-slot": "tooltip-trigger",
|
|
899
|
+
...props
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
function TooltipContent({ className, side = "top", sideOffset = 6, align = "center", alignOffset = 0, children, ...props }) {
|
|
903
|
+
return /* @__PURE__ */ jsx(Tooltip.Portal, { children: /* @__PURE__ */ jsx("div", {
|
|
904
|
+
className: "case-survey-assistant case-survey-assistant-portal",
|
|
905
|
+
children: /* @__PURE__ */ jsx(Tooltip.Positioner, {
|
|
906
|
+
align,
|
|
907
|
+
alignOffset,
|
|
908
|
+
side,
|
|
909
|
+
sideOffset,
|
|
910
|
+
className: "isolate z-50",
|
|
911
|
+
children: /* @__PURE__ */ jsx(Tooltip.Popup, {
|
|
912
|
+
"data-slot": "tooltip-content",
|
|
913
|
+
className: cn("z-50 max-w-64 rounded-md bg-foreground px-3 py-1.5 text-center text-background text-xs shadow-md data-ending-style:opacity-0 transition-[opacity,transform,scale] ease-out motion-reduce:transition-none data-starting-style:opacity-0", className),
|
|
914
|
+
...props,
|
|
915
|
+
children
|
|
916
|
+
})
|
|
917
|
+
})
|
|
918
|
+
}) });
|
|
919
|
+
}
|
|
791
920
|
//#endregion
|
|
792
921
|
//#region src/ui/internal/prompt-input.tsx
|
|
793
922
|
const SUPPORTED_FILE_ACCEPT = [
|
|
@@ -797,7 +926,7 @@ const SUPPORTED_FILE_ACCEPT = [
|
|
|
797
926
|
".jpeg",
|
|
798
927
|
...SURVEY_ASSISTANT_ATTACHMENT_MEDIA_TYPES
|
|
799
928
|
].join(",");
|
|
800
|
-
const WORD_DOCUMENT_MEDIA_TYPES = new Set([
|
|
929
|
+
const WORD_DOCUMENT_MEDIA_TYPES = /* @__PURE__ */ new Set([
|
|
801
930
|
"application/msword",
|
|
802
931
|
"application/vnd.ms-word",
|
|
803
932
|
"application/vnd.ms-word.document.macroenabled.12",
|
|
@@ -810,8 +939,8 @@ const getUnsupportedAttachmentKind = ({ name, type }) => {
|
|
|
810
939
|
return "other";
|
|
811
940
|
};
|
|
812
941
|
const formatFileSize = (size) => {
|
|
813
|
-
if (size <
|
|
814
|
-
return `${(size /
|
|
942
|
+
if (size < 1048576) return `${Math.max(1, Math.round(size / 1024))} KB`;
|
|
943
|
+
return `${(size / 1048576).toFixed(size < 10485760 ? 1 : 0)} MB`;
|
|
815
944
|
};
|
|
816
945
|
const fileToUIPart = async (file) => {
|
|
817
946
|
const mediaType = file.type || "application/octet-stream";
|
|
@@ -1015,32 +1144,29 @@ const PromptInputAttachmentButton = ({ accept = SUPPORTED_FILE_ACCEPT, className
|
|
|
1015
1144
|
const { addFiles } = usePromptInput();
|
|
1016
1145
|
const t = useSurveyAssistantTranslation();
|
|
1017
1146
|
return /* @__PURE__ */ jsx(TooltipProvider, {
|
|
1018
|
-
|
|
1019
|
-
children: /* @__PURE__ */ jsxs(Tooltip$1, { children: [/* @__PURE__ */
|
|
1020
|
-
|
|
1021
|
-
children:
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
onChange
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
})
|
|
1042
|
-
]
|
|
1043
|
-
})
|
|
1147
|
+
delay: 300,
|
|
1148
|
+
children: /* @__PURE__ */ jsxs(Tooltip$1, { children: [/* @__PURE__ */ jsxs(TooltipTrigger, {
|
|
1149
|
+
render: /* @__PURE__ */ jsx("label", { className: cn("inline-flex size-8 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", disabled && "pointer-events-none cursor-default opacity-50", className) }),
|
|
1150
|
+
children: [
|
|
1151
|
+
/* @__PURE__ */ jsx(PaperclipIcon, { className: "size-4" }),
|
|
1152
|
+
/* @__PURE__ */ jsx("span", {
|
|
1153
|
+
className: "sr-only",
|
|
1154
|
+
children: t("input.attachFiles")
|
|
1155
|
+
}),
|
|
1156
|
+
/* @__PURE__ */ jsx("input", {
|
|
1157
|
+
accept,
|
|
1158
|
+
className: "sr-only",
|
|
1159
|
+
disabled,
|
|
1160
|
+
multiple: true,
|
|
1161
|
+
onChange: (event) => {
|
|
1162
|
+
addFiles(event.currentTarget.files);
|
|
1163
|
+
onChange?.(event);
|
|
1164
|
+
event.currentTarget.value = "";
|
|
1165
|
+
},
|
|
1166
|
+
type: "file",
|
|
1167
|
+
...props
|
|
1168
|
+
})
|
|
1169
|
+
]
|
|
1044
1170
|
}), /* @__PURE__ */ jsx(TooltipContent, {
|
|
1045
1171
|
align: "start",
|
|
1046
1172
|
side: "top",
|
|
@@ -1071,15 +1197,18 @@ const PromptInputSubmit = ({ className, status, onStop, onClick, ...props }) =>
|
|
|
1071
1197
|
};
|
|
1072
1198
|
//#endregion
|
|
1073
1199
|
//#region src/ui/internal/select.tsx
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1200
|
+
const Select$1 = Select.Root;
|
|
1201
|
+
function SelectGroup({ className, ...props }) {
|
|
1202
|
+
return /* @__PURE__ */ jsx(Select.Group, {
|
|
1203
|
+
"data-slot": "select-group",
|
|
1204
|
+
className: cn("scroll-my-1 p-1", className),
|
|
1077
1205
|
...props
|
|
1078
1206
|
});
|
|
1079
1207
|
}
|
|
1080
|
-
function SelectValue({ ...props }) {
|
|
1208
|
+
function SelectValue({ className, ...props }) {
|
|
1081
1209
|
return /* @__PURE__ */ jsx(Select.Value, {
|
|
1082
1210
|
"data-slot": "select-value",
|
|
1211
|
+
className: cn("flex flex-1 text-left", className),
|
|
1083
1212
|
...props
|
|
1084
1213
|
});
|
|
1085
1214
|
}
|
|
@@ -1089,29 +1218,30 @@ function SelectTrigger({ className, size = "default", children, ...props }) {
|
|
|
1089
1218
|
"data-size": size,
|
|
1090
1219
|
className: cn("flex w-fit items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground", className),
|
|
1091
1220
|
...props,
|
|
1092
|
-
children: [children, /* @__PURE__ */ jsx(Select.Icon, {
|
|
1093
|
-
asChild: true,
|
|
1094
|
-
children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 opacity-50" })
|
|
1095
|
-
})]
|
|
1221
|
+
children: [children, /* @__PURE__ */ jsx(Select.Icon, { render: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "pointer-events-none size-4 text-muted-foreground" }) })]
|
|
1096
1222
|
});
|
|
1097
1223
|
}
|
|
1098
|
-
function SelectContent({ className, children,
|
|
1224
|
+
function SelectContent({ className, children, side = "bottom", sideOffset = 4, align = "center", alignOffset = 0, alignItemWithTrigger = true, ...props }) {
|
|
1099
1225
|
return /* @__PURE__ */ jsx(Select.Portal, { children: /* @__PURE__ */ jsx("div", {
|
|
1100
1226
|
className: "case-survey-assistant case-survey-assistant-portal",
|
|
1101
|
-
children: /* @__PURE__ */
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
position,
|
|
1227
|
+
children: /* @__PURE__ */ jsx(Select.Positioner, {
|
|
1228
|
+
side,
|
|
1229
|
+
sideOffset,
|
|
1105
1230
|
align,
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1231
|
+
alignOffset,
|
|
1232
|
+
alignItemWithTrigger,
|
|
1233
|
+
className: "isolate z-50",
|
|
1234
|
+
children: /* @__PURE__ */ jsxs(Select.Popup, {
|
|
1235
|
+
"data-slot": "select-content",
|
|
1236
|
+
"data-align-trigger": alignItemWithTrigger,
|
|
1237
|
+
className: cn("relative z-50 max-h-(--available-height) min-w-[8rem] origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover text-popover-foreground shadow-md data-ending-style:opacity-0 data-ending-style:scale-95 transition-[opacity,transform,scale] ease-out motion-reduce:transition-none data-starting-style:opacity-0 data-starting-style:scale-95", className),
|
|
1238
|
+
...props,
|
|
1239
|
+
children: [
|
|
1240
|
+
/* @__PURE__ */ jsx(SelectScrollUpButton, {}),
|
|
1241
|
+
/* @__PURE__ */ jsx(Select.List, { children }),
|
|
1242
|
+
/* @__PURE__ */ jsx(SelectScrollDownButton, {})
|
|
1243
|
+
]
|
|
1244
|
+
})
|
|
1115
1245
|
})
|
|
1116
1246
|
}) });
|
|
1117
1247
|
}
|
|
@@ -1120,27 +1250,29 @@ function SelectItem({ className, children, ...props }) {
|
|
|
1120
1250
|
"data-slot": "select-item",
|
|
1121
1251
|
className: cn("relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2", className),
|
|
1122
1252
|
...props,
|
|
1123
|
-
children: [/* @__PURE__ */ jsx(
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1253
|
+
children: [/* @__PURE__ */ jsx(Select.ItemText, {
|
|
1254
|
+
className: "flex flex-1 shrink-0 gap-2 whitespace-nowrap",
|
|
1255
|
+
children
|
|
1256
|
+
}), /* @__PURE__ */ jsx(Select.ItemIndicator, {
|
|
1257
|
+
render: /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute right-2 flex size-4 items-center justify-center" }),
|
|
1258
|
+
children: /* @__PURE__ */ jsx(CheckIcon, { className: "pointer-events-none" })
|
|
1259
|
+
})]
|
|
1128
1260
|
});
|
|
1129
1261
|
}
|
|
1130
1262
|
function SelectScrollUpButton({ className, ...props }) {
|
|
1131
|
-
return /* @__PURE__ */ jsx(Select.
|
|
1263
|
+
return /* @__PURE__ */ jsx(Select.ScrollUpArrow, {
|
|
1132
1264
|
"data-slot": "select-scroll-up-button",
|
|
1133
1265
|
className: cn("flex cursor-default items-center justify-center py-1", className),
|
|
1134
1266
|
...props,
|
|
1135
|
-
children: /* @__PURE__ */ jsx(ChevronUpIcon, {
|
|
1267
|
+
children: /* @__PURE__ */ jsx(ChevronUpIcon, {})
|
|
1136
1268
|
});
|
|
1137
1269
|
}
|
|
1138
1270
|
function SelectScrollDownButton({ className, ...props }) {
|
|
1139
|
-
return /* @__PURE__ */ jsx(Select.
|
|
1271
|
+
return /* @__PURE__ */ jsx(Select.ScrollDownArrow, {
|
|
1140
1272
|
"data-slot": "select-scroll-down-button",
|
|
1141
1273
|
className: cn("flex cursor-default items-center justify-center py-1", className),
|
|
1142
1274
|
...props,
|
|
1143
|
-
children: /* @__PURE__ */ jsx(ChevronDownIcon, {
|
|
1275
|
+
children: /* @__PURE__ */ jsx(ChevronDownIcon, {})
|
|
1144
1276
|
});
|
|
1145
1277
|
}
|
|
1146
1278
|
//#endregion
|
|
@@ -1150,8 +1282,14 @@ const SurveyAssistantModelSelect = ({ disabled = false, modelId, models, onModel
|
|
|
1150
1282
|
const selectedModelLabel = models.find((model) => model.id === modelId)?.label ?? modelId ?? t("input.defaultModel");
|
|
1151
1283
|
if (models.length > 1) return /* @__PURE__ */ jsxs(Select$1, {
|
|
1152
1284
|
disabled,
|
|
1153
|
-
onValueChange:
|
|
1285
|
+
onValueChange: (value) => {
|
|
1286
|
+
if (value !== null) onModelChange(value);
|
|
1287
|
+
},
|
|
1154
1288
|
value: modelId ?? "",
|
|
1289
|
+
items: [...models.map((model) => ({
|
|
1290
|
+
value: model.id,
|
|
1291
|
+
label: model.label
|
|
1292
|
+
}))],
|
|
1155
1293
|
children: [/* @__PURE__ */ jsxs(SelectTrigger, {
|
|
1156
1294
|
"aria-label": t("input.model"),
|
|
1157
1295
|
className: "h-8 min-w-0 max-w-48 gap-1.5 border-0 bg-transparent px-2 text-xs shadow-none hover:bg-muted hover:text-foreground focus-visible:ring-1",
|
|
@@ -1161,13 +1299,13 @@ const SurveyAssistantModelSelect = ({ disabled = false, modelId, models, onModel
|
|
|
1161
1299
|
}), /* @__PURE__ */ jsx(SelectContent, {
|
|
1162
1300
|
align: "end",
|
|
1163
1301
|
className: "min-w-52 rounded-lg border-border p-0 shadow-lg",
|
|
1164
|
-
|
|
1165
|
-
children: models.map((model) => /* @__PURE__ */ jsx(SelectItem, {
|
|
1302
|
+
alignItemWithTrigger: false,
|
|
1303
|
+
children: /* @__PURE__ */ jsx(SelectGroup, { children: models.map((model) => /* @__PURE__ */ jsx(SelectItem, {
|
|
1166
1304
|
className: "min-h-9 rounded-md px-2 py-2 text-xs focus:bg-muted",
|
|
1167
1305
|
title: model.id,
|
|
1168
1306
|
value: model.id,
|
|
1169
1307
|
children: model.label
|
|
1170
|
-
}, model.id))
|
|
1308
|
+
}, model.id)) })
|
|
1171
1309
|
})]
|
|
1172
1310
|
});
|
|
1173
1311
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -1221,8 +1359,9 @@ const SurveyAssistantPromptInput = ({ attachmentsDisabled = false, attachmentBut
|
|
|
1221
1359
|
const formatOmittedLength = (length) => length.toLocaleString("en-US");
|
|
1222
1360
|
const stringifyToolTechnicalDetails = (value) => JSON.stringify(value, function redactEmbeddedBinary(key, currentValue) {
|
|
1223
1361
|
const parent = this && typeof this === "object" ? this : void 0;
|
|
1224
|
-
|
|
1225
|
-
if (
|
|
1362
|
+
const marker = getSurveyAssistantEmbeddedBinaryMarker(currentValue, parent, key);
|
|
1363
|
+
if (marker?.redacted === "base64") return `[embedded base64 omitted: ${formatOmittedLength(marker.characters)} characters]`;
|
|
1364
|
+
if (marker?.redacted === "data-url") return `[base64 data URL omitted: ${formatOmittedLength(marker.characters)} characters]`;
|
|
1226
1365
|
return currentValue;
|
|
1227
1366
|
}, 2);
|
|
1228
1367
|
//#endregion
|
|
@@ -1259,9 +1398,7 @@ const highlighterCache = /* @__PURE__ */ new Map();
|
|
|
1259
1398
|
const tokensCache = /* @__PURE__ */ new Map();
|
|
1260
1399
|
const subscribers = /* @__PURE__ */ new Map();
|
|
1261
1400
|
const getTokensCacheKey = (code, language) => {
|
|
1262
|
-
|
|
1263
|
-
const end = code.length > 100 ? code.slice(-100) : "";
|
|
1264
|
-
return `${language}:${code.length}:${start}:${end}`;
|
|
1401
|
+
return JSON.stringify([language, code]);
|
|
1265
1402
|
};
|
|
1266
1403
|
const getHighlighter = (language) => {
|
|
1267
1404
|
const cached = highlighterCache.get(language);
|
|
@@ -1475,6 +1612,327 @@ const getSurveyAssistantInitialThreadLoadState = ({ error, hasSelectedThread, lo
|
|
|
1475
1612
|
return null;
|
|
1476
1613
|
};
|
|
1477
1614
|
//#endregion
|
|
1615
|
+
//#region src/ui/assistant-error-presentation.ts
|
|
1616
|
+
const getAssistantErrorPresentation = ({ authorizationError, error, t }) => {
|
|
1617
|
+
const parsed = parseSurveyAssistantError(authorizationError ? {
|
|
1618
|
+
code: "request_failed",
|
|
1619
|
+
detail: authorizationError,
|
|
1620
|
+
retryable: false
|
|
1621
|
+
} : error);
|
|
1622
|
+
return {
|
|
1623
|
+
title: t(`errors.${parsed.code}.title`),
|
|
1624
|
+
description: parsed.detail ?? t("errors.fallbackDetail"),
|
|
1625
|
+
hint: t(`errors.${parsed.code}.hint`),
|
|
1626
|
+
providerMessage: parsed.providerMessage,
|
|
1627
|
+
providerRequestId: parsed.providerRequestId,
|
|
1628
|
+
retryable: isSurveyAssistantErrorRetryable(parsed),
|
|
1629
|
+
tone: parsed.code === "model_unavailable" || parsed.code === "rate_limited" ? "warning" : "error",
|
|
1630
|
+
upstreamStatus: parsed.upstreamStatus
|
|
1631
|
+
};
|
|
1632
|
+
};
|
|
1633
|
+
//#endregion
|
|
1634
|
+
//#region src/ui/internal/checkbox.tsx
|
|
1635
|
+
const Checkbox$1 = ({ className, ...props }) => /* @__PURE__ */ jsx(Checkbox.Root, {
|
|
1636
|
+
className: cn("relative flex size-4 shrink-0 items-center justify-center rounded border border-input outline-none transition-colors focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40 data-disabled:cursor-not-allowed data-disabled:opacity-50 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground", className),
|
|
1637
|
+
...props,
|
|
1638
|
+
children: /* @__PURE__ */ jsx(Checkbox.Indicator, {
|
|
1639
|
+
className: "grid place-content-center text-current",
|
|
1640
|
+
children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-3.5" })
|
|
1641
|
+
})
|
|
1642
|
+
});
|
|
1643
|
+
//#endregion
|
|
1644
|
+
//#region src/ui/internal/dialog.tsx
|
|
1645
|
+
const Dialog$1 = Dialog.Root;
|
|
1646
|
+
const DialogTitle = Dialog.Title;
|
|
1647
|
+
const DialogDescription = Dialog.Description;
|
|
1648
|
+
const DialogContent = ({ children, className, closeLabel, ...props }) => /* @__PURE__ */ jsx(Dialog.Portal, { children: /* @__PURE__ */ jsxs("div", {
|
|
1649
|
+
className: "case-survey-assistant case-survey-assistant-portal",
|
|
1650
|
+
children: [/* @__PURE__ */ jsx(Dialog.Backdrop, { className: "fixed inset-0 z-50 bg-black/20 backdrop-blur-[1px] transition-[opacity,transform,scale] ease-out motion-reduce:transition-none data-ending-style:opacity-0 data-starting-style:opacity-0" }), /* @__PURE__ */ jsxs(Dialog.Popup, {
|
|
1651
|
+
className: cn("fixed top-1/2 left-1/2 z-50 grid max-h-[min(42rem,calc(100vh-2rem))] w-[min(30rem,calc(100vw-2rem))] -translate-x-1/2 -translate-y-1/2 gap-4 overflow-y-auto rounded-xl border border-border bg-background p-4 text-foreground shadow-xl outline-none transition-[opacity,transform,scale] ease-out motion-reduce:transition-none data-ending-style:opacity-0 data-starting-style:opacity-0 data-ending-style:scale-95 data-starting-style:scale-95", className),
|
|
1652
|
+
...props,
|
|
1653
|
+
children: [children, /* @__PURE__ */ jsx(Dialog.Close, {
|
|
1654
|
+
"aria-label": closeLabel,
|
|
1655
|
+
className: "absolute top-2.5 right-2.5 flex size-7 items-center justify-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
1656
|
+
type: "button",
|
|
1657
|
+
children: /* @__PURE__ */ jsx(XIcon, { className: "size-4" })
|
|
1658
|
+
})]
|
|
1659
|
+
})]
|
|
1660
|
+
}) });
|
|
1661
|
+
//#endregion
|
|
1662
|
+
//#region src/ui/support-bundle-dialog.tsx
|
|
1663
|
+
const CATEGORIES = [
|
|
1664
|
+
"conversation",
|
|
1665
|
+
"survey",
|
|
1666
|
+
"attachments"
|
|
1667
|
+
];
|
|
1668
|
+
const formatBytes = (bytes) => {
|
|
1669
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
1670
|
+
if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KiB`;
|
|
1671
|
+
return `${(bytes / 1048576).toFixed(1)} MiB`;
|
|
1672
|
+
};
|
|
1673
|
+
const SurveyAssistantSupportBundleDialog = ({ config, error, fallbackFocusReturnRef, focusReturnRef, loading, onOpenChange, open, prepared }) => {
|
|
1674
|
+
const t = useSurveyAssistantTranslation();
|
|
1675
|
+
const [selection, setSelection] = useState({ ...SURVEY_ASSISTANT_DEFAULT_SUPPORT_BUNDLE_SELECTION });
|
|
1676
|
+
const [generated, setGenerated] = useState();
|
|
1677
|
+
const [generationError, setGenerationError] = useState();
|
|
1678
|
+
const [generating, setGenerating] = useState(false);
|
|
1679
|
+
const [supportDetailsCopied, setSupportDetailsCopied] = useState(false);
|
|
1680
|
+
const [supportDetailsCopyError, setSupportDetailsCopyError] = useState();
|
|
1681
|
+
const generationSequenceRef = useRef(0);
|
|
1682
|
+
const supportDetailsRef = useRef(null);
|
|
1683
|
+
useEffect(() => {
|
|
1684
|
+
generationSequenceRef.current += 1;
|
|
1685
|
+
if (open) setSelection({ ...SURVEY_ASSISTANT_DEFAULT_SUPPORT_BUNDLE_SELECTION });
|
|
1686
|
+
setGenerated(void 0);
|
|
1687
|
+
setGenerationError(void 0);
|
|
1688
|
+
setGenerating(false);
|
|
1689
|
+
setSupportDetailsCopied(false);
|
|
1690
|
+
setSupportDetailsCopyError(void 0);
|
|
1691
|
+
}, [open, prepared?.threadId]);
|
|
1692
|
+
const selectedBytes = useMemo(() => prepared ? estimateSurveyAssistantSupportBundleBytes(prepared, selection, config) : 0, [
|
|
1693
|
+
config,
|
|
1694
|
+
prepared,
|
|
1695
|
+
selection
|
|
1696
|
+
]);
|
|
1697
|
+
const blocked = Boolean(prepared && selectedBytes > prepared.limits.bundleBytes);
|
|
1698
|
+
const warning = Boolean(prepared && selectedBytes > prepared.limits.emailWarningBytes);
|
|
1699
|
+
const generate = async () => {
|
|
1700
|
+
if (!prepared || blocked) return;
|
|
1701
|
+
const generationSequence = generationSequenceRef.current + 1;
|
|
1702
|
+
generationSequenceRef.current = generationSequence;
|
|
1703
|
+
setGenerating(true);
|
|
1704
|
+
setSupportDetailsCopied(false);
|
|
1705
|
+
setSupportDetailsCopyError(void 0);
|
|
1706
|
+
try {
|
|
1707
|
+
const bundle = await generateSurveyAssistantSupportBundle(prepared, selection, config);
|
|
1708
|
+
if (generationSequenceRef.current !== generationSequence) return;
|
|
1709
|
+
downloadSurveyAssistantSupportBundle(bundle);
|
|
1710
|
+
setGenerated(bundle);
|
|
1711
|
+
setGenerationError(void 0);
|
|
1712
|
+
setSupportDetailsCopied(false);
|
|
1713
|
+
setSupportDetailsCopyError(void 0);
|
|
1714
|
+
} catch {
|
|
1715
|
+
if (generationSequenceRef.current === generationSequence) setGenerationError(t("supportBundle.generationFailed"));
|
|
1716
|
+
} finally {
|
|
1717
|
+
if (generationSequenceRef.current === generationSequence) setGenerating(false);
|
|
1718
|
+
}
|
|
1719
|
+
};
|
|
1720
|
+
const updateSelection = (category, checked) => {
|
|
1721
|
+
generationSequenceRef.current += 1;
|
|
1722
|
+
setSelection((current) => ({
|
|
1723
|
+
...current,
|
|
1724
|
+
[category]: checked
|
|
1725
|
+
}));
|
|
1726
|
+
setGenerated(void 0);
|
|
1727
|
+
setGenerationError(void 0);
|
|
1728
|
+
setGenerating(false);
|
|
1729
|
+
setSupportDetailsCopied(false);
|
|
1730
|
+
setSupportDetailsCopyError(void 0);
|
|
1731
|
+
};
|
|
1732
|
+
const mailto = generated && prepared && config ? createSurveyAssistantSupportMailto({
|
|
1733
|
+
bundle: generated,
|
|
1734
|
+
config,
|
|
1735
|
+
prepared
|
|
1736
|
+
}) : void 0;
|
|
1737
|
+
const supportDetails = generated && prepared ? createSurveyAssistantSupportDetails({
|
|
1738
|
+
bundle: generated,
|
|
1739
|
+
prepared
|
|
1740
|
+
}) : "";
|
|
1741
|
+
const copySupportDetails = async () => {
|
|
1742
|
+
if (!supportDetails) return;
|
|
1743
|
+
const copySequence = generationSequenceRef.current + 1;
|
|
1744
|
+
generationSequenceRef.current = copySequence;
|
|
1745
|
+
setSupportDetailsCopied(false);
|
|
1746
|
+
setSupportDetailsCopyError(void 0);
|
|
1747
|
+
try {
|
|
1748
|
+
if (navigator.clipboard?.writeText) await navigator.clipboard.writeText(supportDetails);
|
|
1749
|
+
else {
|
|
1750
|
+
if (!supportDetailsRef.current) throw new Error("Support details are not available.");
|
|
1751
|
+
supportDetailsRef.current.select();
|
|
1752
|
+
if (!document.execCommand("copy")) throw new Error("Copy was not available.");
|
|
1753
|
+
}
|
|
1754
|
+
if (generationSequenceRef.current !== copySequence) return;
|
|
1755
|
+
setSupportDetailsCopied(true);
|
|
1756
|
+
setSupportDetailsCopyError(void 0);
|
|
1757
|
+
} catch {
|
|
1758
|
+
if (generationSequenceRef.current !== copySequence) return;
|
|
1759
|
+
setSupportDetailsCopied(false);
|
|
1760
|
+
setSupportDetailsCopyError(t("supportBundle.copyDetailsFailed"));
|
|
1761
|
+
}
|
|
1762
|
+
};
|
|
1763
|
+
return /* @__PURE__ */ jsx(Dialog$1, {
|
|
1764
|
+
onOpenChange,
|
|
1765
|
+
open,
|
|
1766
|
+
children: /* @__PURE__ */ jsxs(DialogContent, {
|
|
1767
|
+
"aria-describedby": "survey-assistant-support-bundle-description",
|
|
1768
|
+
closeLabel: t("supportBundle.close"),
|
|
1769
|
+
finalFocus: () => {
|
|
1770
|
+
const target = focusReturnRef?.current?.isConnected ? focusReturnRef.current : fallbackFocusReturnRef?.current?.isConnected ? fallbackFocusReturnRef.current : null;
|
|
1771
|
+
if (!target) return;
|
|
1772
|
+
target.focus();
|
|
1773
|
+
return false;
|
|
1774
|
+
},
|
|
1775
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1776
|
+
className: "pr-8",
|
|
1777
|
+
children: [/* @__PURE__ */ jsx(DialogTitle, {
|
|
1778
|
+
className: "font-semibold text-base",
|
|
1779
|
+
children: t("supportBundle.title")
|
|
1780
|
+
}), /* @__PURE__ */ jsx(DialogDescription, {
|
|
1781
|
+
className: "mt-1 text-muted-foreground text-sm",
|
|
1782
|
+
id: "survey-assistant-support-bundle-description",
|
|
1783
|
+
children: t("supportBundle.description")
|
|
1784
|
+
})]
|
|
1785
|
+
}), loading ? /* @__PURE__ */ jsxs("div", {
|
|
1786
|
+
"aria-live": "polite",
|
|
1787
|
+
className: "flex min-h-28 items-center justify-center text-muted-foreground text-sm",
|
|
1788
|
+
role: "status",
|
|
1789
|
+
children: [/* @__PURE__ */ jsx(LoaderCircleIcon, { className: "mr-2 size-4 animate-spin" }), t("supportBundle.preparing")]
|
|
1790
|
+
}) : error ? /* @__PURE__ */ jsxs("div", {
|
|
1791
|
+
className: "rounded-md border border-destructive/20 bg-destructive/5 p-3 text-sm",
|
|
1792
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1793
|
+
className: "font-medium",
|
|
1794
|
+
children: t("supportBundle.preparationFailed")
|
|
1795
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1796
|
+
className: "mt-1 text-muted-foreground",
|
|
1797
|
+
children: error
|
|
1798
|
+
})]
|
|
1799
|
+
}) : prepared ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1800
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1801
|
+
className: "rounded-md border border-border bg-muted/30 p-3 text-xs",
|
|
1802
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1803
|
+
className: "font-medium",
|
|
1804
|
+
children: t("supportBundle.core.title")
|
|
1805
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1806
|
+
className: "mt-1 text-muted-foreground",
|
|
1807
|
+
children: t("supportBundle.core.description")
|
|
1808
|
+
})]
|
|
1809
|
+
}),
|
|
1810
|
+
/* @__PURE__ */ jsxs("fieldset", {
|
|
1811
|
+
className: "grid gap-2",
|
|
1812
|
+
"aria-describedby": "support-bundle-sensitive-note",
|
|
1813
|
+
children: [/* @__PURE__ */ jsx("legend", {
|
|
1814
|
+
className: "mb-1 font-medium text-sm",
|
|
1815
|
+
children: t("supportBundle.chooseData")
|
|
1816
|
+
}), CATEGORIES.map((category) => {
|
|
1817
|
+
const id = `support-bundle-${category}`;
|
|
1818
|
+
return /* @__PURE__ */ jsxs("label", {
|
|
1819
|
+
className: "flex cursor-pointer items-start gap-3 rounded-md border border-border p-3 hover:bg-muted/30",
|
|
1820
|
+
htmlFor: id,
|
|
1821
|
+
children: [/* @__PURE__ */ jsx(Checkbox$1, {
|
|
1822
|
+
checked: selection[category],
|
|
1823
|
+
id,
|
|
1824
|
+
onCheckedChange: (checked) => updateSelection(category, checked === true)
|
|
1825
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
1826
|
+
className: "min-w-0 flex-1",
|
|
1827
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
1828
|
+
className: "flex items-center justify-between gap-2 font-medium text-sm",
|
|
1829
|
+
children: [/* @__PURE__ */ jsx("span", { children: t(`supportBundle.categories.${category}.title`) }), /* @__PURE__ */ jsx("span", {
|
|
1830
|
+
className: "shrink-0 text-muted-foreground text-xs",
|
|
1831
|
+
children: formatBytes(prepared.categoryBytes[category])
|
|
1832
|
+
})]
|
|
1833
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1834
|
+
className: "mt-0.5 block text-muted-foreground text-xs",
|
|
1835
|
+
children: t(`supportBundle.categories.${category}.description`)
|
|
1836
|
+
})]
|
|
1837
|
+
})]
|
|
1838
|
+
}, category);
|
|
1839
|
+
})]
|
|
1840
|
+
}),
|
|
1841
|
+
/* @__PURE__ */ jsx("p", {
|
|
1842
|
+
className: "text-muted-foreground text-xs",
|
|
1843
|
+
id: "support-bundle-sensitive-note",
|
|
1844
|
+
children: t("supportBundle.sensitiveNote")
|
|
1845
|
+
}),
|
|
1846
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1847
|
+
"aria-live": "polite",
|
|
1848
|
+
className: "rounded-md bg-muted px-3 py-2 text-xs text-foreground",
|
|
1849
|
+
role: "status",
|
|
1850
|
+
children: [
|
|
1851
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1852
|
+
className: "flex justify-between gap-3 font-semibold",
|
|
1853
|
+
children: [/* @__PURE__ */ jsx("span", { children: t("supportBundle.estimatedSize") }), /* @__PURE__ */ jsx("span", { children: formatBytes(selectedBytes) })]
|
|
1854
|
+
}),
|
|
1855
|
+
warning && !blocked && /* @__PURE__ */ jsx("div", {
|
|
1856
|
+
className: "mt-1 text-amber-800 dark:text-amber-400",
|
|
1857
|
+
children: t("supportBundle.emailWarning")
|
|
1858
|
+
}),
|
|
1859
|
+
blocked && /* @__PURE__ */ jsx("div", {
|
|
1860
|
+
className: "mt-1 text-red-700 dark:text-red-400",
|
|
1861
|
+
children: t("supportBundle.tooLarge")
|
|
1862
|
+
}),
|
|
1863
|
+
prepared.unavailable.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
1864
|
+
className: "mt-1",
|
|
1865
|
+
children: t(prepared.unavailable.length === 1 ? "supportBundle.unavailable" : "supportBundle.unavailablePlural", { count: prepared.unavailable.length })
|
|
1866
|
+
}),
|
|
1867
|
+
(generationError ?? error) && /* @__PURE__ */ jsx("div", {
|
|
1868
|
+
className: "mt-1 text-red-700 dark:text-red-400",
|
|
1869
|
+
children: generationError ?? error
|
|
1870
|
+
})
|
|
1871
|
+
]
|
|
1872
|
+
}),
|
|
1873
|
+
generated ? /* @__PURE__ */ jsxs(Fragment, { children: [!mailto && /* @__PURE__ */ jsxs("div", {
|
|
1874
|
+
className: "grid gap-2 rounded-md border border-border p-3",
|
|
1875
|
+
children: [
|
|
1876
|
+
/* @__PURE__ */ jsx("label", {
|
|
1877
|
+
className: "font-medium text-xs",
|
|
1878
|
+
htmlFor: "support-bundle-details",
|
|
1879
|
+
children: t("supportBundle.supportDetails")
|
|
1880
|
+
}),
|
|
1881
|
+
/* @__PURE__ */ jsx("textarea", {
|
|
1882
|
+
className: "min-h-24 resize-y rounded-md border border-input bg-background p-2 font-mono text-xs",
|
|
1883
|
+
id: "support-bundle-details",
|
|
1884
|
+
readOnly: true,
|
|
1885
|
+
ref: supportDetailsRef,
|
|
1886
|
+
value: supportDetails
|
|
1887
|
+
}),
|
|
1888
|
+
/* @__PURE__ */ jsx("div", {
|
|
1889
|
+
className: "flex justify-end",
|
|
1890
|
+
children: /* @__PURE__ */ jsxs(Button$1, {
|
|
1891
|
+
disabled: generating,
|
|
1892
|
+
onClick: () => void copySupportDetails(),
|
|
1893
|
+
type: "button",
|
|
1894
|
+
variant: "secondary",
|
|
1895
|
+
children: [supportDetailsCopied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {}), t(supportDetailsCopied ? "supportBundle.detailsCopied" : "supportBundle.copyDetails")]
|
|
1896
|
+
})
|
|
1897
|
+
}),
|
|
1898
|
+
supportDetailsCopyError && /* @__PURE__ */ jsx("div", {
|
|
1899
|
+
"aria-live": "polite",
|
|
1900
|
+
className: "text-destructive text-xs",
|
|
1901
|
+
role: "status",
|
|
1902
|
+
children: supportDetailsCopyError
|
|
1903
|
+
})
|
|
1904
|
+
]
|
|
1905
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1906
|
+
className: "flex flex-wrap justify-end gap-2",
|
|
1907
|
+
children: [mailto && /* @__PURE__ */ jsxs(Button$1, {
|
|
1908
|
+
render: /* @__PURE__ */ jsx("a", { href: mailto }),
|
|
1909
|
+
variant: "secondary",
|
|
1910
|
+
nativeButton: false,
|
|
1911
|
+
children: [/* @__PURE__ */ jsx(MailIcon, {}), t("supportBundle.openEmail")]
|
|
1912
|
+
}), /* @__PURE__ */ jsxs(Button$1, {
|
|
1913
|
+
disabled: generating,
|
|
1914
|
+
onClick: () => void generate(),
|
|
1915
|
+
type: "button",
|
|
1916
|
+
children: [generating ? /* @__PURE__ */ jsx(LoaderCircleIcon, { className: "animate-spin" }) : /* @__PURE__ */ jsx(DownloadIcon, {}), t("supportBundle.downloadAgain")]
|
|
1917
|
+
})]
|
|
1918
|
+
})] }) : /* @__PURE__ */ jsx("div", {
|
|
1919
|
+
className: "flex justify-end",
|
|
1920
|
+
children: /* @__PURE__ */ jsxs(Button$1, {
|
|
1921
|
+
disabled: blocked || generating,
|
|
1922
|
+
onClick: () => void generate(),
|
|
1923
|
+
type: "button",
|
|
1924
|
+
children: [generating ? /* @__PURE__ */ jsx(LoaderCircleIcon, { className: "animate-spin" }) : /* @__PURE__ */ jsx(DownloadIcon, {}), t("supportBundle.download")]
|
|
1925
|
+
})
|
|
1926
|
+
}),
|
|
1927
|
+
/* @__PURE__ */ jsx("p", {
|
|
1928
|
+
className: "text-muted-foreground text-xs",
|
|
1929
|
+
children: generated ? t("supportBundle.downloaded", { filename: generated.filename }) : t("supportBundle.localOnly")
|
|
1930
|
+
})
|
|
1931
|
+
] }) : null]
|
|
1932
|
+
})
|
|
1933
|
+
});
|
|
1934
|
+
};
|
|
1935
|
+
//#endregion
|
|
1478
1936
|
//#region src/ui/survey-assistant-panel.tsx
|
|
1479
1937
|
const isRootSurveyItem = (item) => typeof item.config === "object" && item.config !== null && item.config.isRoot === true;
|
|
1480
1938
|
const getAssistantEmptyStateContext = (controller) => {
|
|
@@ -1542,7 +2000,7 @@ const hasRenderableParts = (message) => {
|
|
|
1542
2000
|
const getFilePartLabel = (part) => part.filename ?? part.mediaType;
|
|
1543
2001
|
const getToolOutput = (part) => part.state === "output-available" ? part.output : void 0;
|
|
1544
2002
|
const getToolErrorText = (part) => part.state === "output-error" ? part.errorText : void 0;
|
|
1545
|
-
const localizedToolNames = new Set([
|
|
2003
|
+
const localizedToolNames = /* @__PURE__ */ new Set([
|
|
1546
2004
|
"survey_inspect",
|
|
1547
2005
|
"survey_change",
|
|
1548
2006
|
"survey_expression",
|
|
@@ -1553,16 +2011,6 @@ const localizedToolNames = new Set([
|
|
|
1553
2011
|
const getToolDisplayName = (t, toolName, phase = "complete") => localizedToolNames.has(toolName) ? t(`activity.tools.${toolName}.${phase}`) : t(phase === "active" ? "activity.genericActive" : "activity.genericComplete");
|
|
1554
2012
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1555
2013
|
const unwrapOutput = unwrapSurveyAssistantToolOutput;
|
|
1556
|
-
const getAssistantErrorPresentation = (error, t) => {
|
|
1557
|
-
const parsed = parseSurveyAssistantError(error);
|
|
1558
|
-
return {
|
|
1559
|
-
title: t(`errors.${parsed.code}.title`),
|
|
1560
|
-
description: parsed.detail ?? t("errors.fallbackDetail"),
|
|
1561
|
-
hint: t(`errors.${parsed.code}.hint`),
|
|
1562
|
-
retryable: parsed.retryable ?? (parsed.code === "rate_limited" || parsed.code === "request_failed"),
|
|
1563
|
-
tone: parsed.code === "model_unavailable" || parsed.code === "rate_limited" ? "warning" : "error"
|
|
1564
|
-
};
|
|
1565
|
-
};
|
|
1566
2014
|
const getChangeSet = parseSurveyChangeSet;
|
|
1567
2015
|
const isChangeSet = (output) => {
|
|
1568
2016
|
return getChangeSet(output) !== null;
|
|
@@ -1969,7 +2417,7 @@ const SurveyAssistantHeaderIdentity = ({ indicatorClassName, status, title }) =>
|
|
|
1969
2417
|
})]
|
|
1970
2418
|
})]
|
|
1971
2419
|
});
|
|
1972
|
-
const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = false, focusPromptOnMount = false, hasEarlierMessages, initialLaunch, initialMessages, modelId, models, onInitialLaunchHandled, onModelChange, onFirstSubmit, onLoadEarlierMessages, onTurnSettled, onApplyReceipts, onSettleApply, onReviewChangeSets, onTurnActiveChange, resourceId, surveyId, threadControls, threadId, threadTitle }) => {
|
|
2420
|
+
const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, diagnosticStore, embedded = false, focusPromptOnMount = false, hasEarlierMessages, initialLaunch, initialMessages, modelId, models, onInitialLaunchHandled, onModelChange, onFirstSubmit, onExportDetails, onLoadEarlierMessages, onTurnSettled, onApplyReceipts, onSettleApply, onReviewChangeSets, onTurnActiveChange, resourceId, surveyId, threadControls, threadId, threadTitle }) => {
|
|
1973
2421
|
const t = useSurveyAssistantTranslation();
|
|
1974
2422
|
const emptyStateContext = getAssistantEmptyStateContext(controller);
|
|
1975
2423
|
const assistantQuickPrompts = getAssistantQuickPrompts(t, emptyStateContext);
|
|
@@ -1977,6 +2425,7 @@ const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = fal
|
|
|
1977
2425
|
api,
|
|
1978
2426
|
applyPolicy,
|
|
1979
2427
|
controller,
|
|
2428
|
+
diagnosticStore,
|
|
1980
2429
|
initialMessages,
|
|
1981
2430
|
modelId,
|
|
1982
2431
|
onApplyReceipts,
|
|
@@ -1989,16 +2438,22 @@ const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = fal
|
|
|
1989
2438
|
});
|
|
1990
2439
|
const hasSubmittedMessageRef = useRef((initialMessages?.length ?? 0) > 0);
|
|
1991
2440
|
const showAssistantError = Boolean(authorizationError) || Boolean(error);
|
|
1992
|
-
const assistantErrorPresentation = getAssistantErrorPresentation(
|
|
2441
|
+
const assistantErrorPresentation = getAssistantErrorPresentation({
|
|
2442
|
+
authorizationError,
|
|
2443
|
+
error,
|
|
2444
|
+
t
|
|
2445
|
+
});
|
|
1993
2446
|
const lastMessage = messages.at(-1);
|
|
1994
2447
|
const isAssistantTurnActive = isSurveyAssistantTurnActive({
|
|
1995
2448
|
isStreaming,
|
|
1996
2449
|
state
|
|
1997
2450
|
});
|
|
1998
2451
|
const promptTextareaRef = useRef(null);
|
|
2452
|
+
const exportDetailsButtonRef = useRef(null);
|
|
1999
2453
|
const shouldRestorePromptFocusRef = useRef(false);
|
|
2000
2454
|
const turnWasActiveRef = useRef(false);
|
|
2001
2455
|
const [loadingEarlierMessages, setLoadingEarlierMessages] = useState(false);
|
|
2456
|
+
const [providerMessageExpanded, setProviderMessageExpanded] = useState(false);
|
|
2002
2457
|
const loadEarlierMessages = useCallback(async () => {
|
|
2003
2458
|
if (loadingEarlierMessages) return;
|
|
2004
2459
|
setLoadingEarlierMessages(true);
|
|
@@ -2219,15 +2674,40 @@ const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = fal
|
|
|
2219
2674
|
className: "mt-0.5 wrap-break-word text-muted-foreground",
|
|
2220
2675
|
children: assistantErrorPresentation.description
|
|
2221
2676
|
}),
|
|
2677
|
+
assistantErrorPresentation.providerMessage && /* @__PURE__ */ jsxs("div", {
|
|
2678
|
+
className: "mt-1",
|
|
2679
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
2680
|
+
className: cn("wrap-break-word text-muted-foreground text-xs", !providerMessageExpanded && "line-clamp-3"),
|
|
2681
|
+
children: assistantErrorPresentation.providerMessage
|
|
2682
|
+
}), assistantErrorPresentation.providerMessage.length > 180 && /* @__PURE__ */ jsx("button", {
|
|
2683
|
+
className: "mt-0.5 font-medium text-foreground text-xs hover:underline",
|
|
2684
|
+
onClick: () => setProviderMessageExpanded((current) => !current),
|
|
2685
|
+
type: "button",
|
|
2686
|
+
children: t(providerMessageExpanded ? "errors.hideProviderDetails" : "errors.showProviderDetails")
|
|
2687
|
+
})]
|
|
2688
|
+
}),
|
|
2689
|
+
(assistantErrorPresentation.upstreamStatus || assistantErrorPresentation.providerRequestId) && /* @__PURE__ */ jsx("p", {
|
|
2690
|
+
className: "mt-1 text-[11px] text-muted-foreground/80",
|
|
2691
|
+
children: [assistantErrorPresentation.upstreamStatus ? t("errors.upstreamStatus", { status: assistantErrorPresentation.upstreamStatus }) : null, assistantErrorPresentation.providerRequestId ? t("errors.providerRequestId", { requestId: assistantErrorPresentation.providerRequestId }) : null].filter(Boolean).join(" · ")
|
|
2692
|
+
}),
|
|
2222
2693
|
/* @__PURE__ */ jsx("p", {
|
|
2223
2694
|
className: "mt-1 text-muted-foreground/80",
|
|
2224
2695
|
children: assistantErrorPresentation.hint
|
|
2225
2696
|
}),
|
|
2226
|
-
assistantErrorPresentation.retryable && /* @__PURE__ */
|
|
2227
|
-
className: "mt-1.5
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2697
|
+
(assistantErrorPresentation.retryable || onExportDetails) && /* @__PURE__ */ jsxs("div", {
|
|
2698
|
+
className: "mt-1.5 flex flex-wrap gap-x-3 gap-y-1",
|
|
2699
|
+
children: [assistantErrorPresentation.retryable && /* @__PURE__ */ jsx("button", {
|
|
2700
|
+
className: "font-medium text-foreground text-xs hover:underline",
|
|
2701
|
+
onClick: retry,
|
|
2702
|
+
type: "button",
|
|
2703
|
+
children: t("errors.retry")
|
|
2704
|
+
}), onExportDetails && /* @__PURE__ */ jsx("button", {
|
|
2705
|
+
className: "font-medium text-foreground text-xs hover:underline",
|
|
2706
|
+
onClick: () => onExportDetails(exportDetailsButtonRef.current),
|
|
2707
|
+
ref: exportDetailsButtonRef,
|
|
2708
|
+
type: "button",
|
|
2709
|
+
children: t("errors.exportDetails")
|
|
2710
|
+
})]
|
|
2231
2711
|
})
|
|
2232
2712
|
]
|
|
2233
2713
|
})]
|
|
@@ -2276,14 +2756,12 @@ const mergeThreads = (current, incoming) => {
|
|
|
2276
2756
|
const mergeRecentThreadPage = (current, recent) => {
|
|
2277
2757
|
if (recent.length === 0) return [];
|
|
2278
2758
|
const oldestRecentUpdate = Math.min(...recent.map((thread) => Date.parse(thread.updatedAt)));
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
const listThreadPage = async (client, cursor) => {
|
|
2282
|
-
if (client.listPage) return client.listPage(cursor ? { cursor } : void 0);
|
|
2283
|
-
return cursor ? { threads: [] } : { threads: await client.list() };
|
|
2759
|
+
const olderThreads = Number.isFinite(oldestRecentUpdate) ? current.filter((thread) => Date.parse(thread.updatedAt) <= oldestRecentUpdate) : current;
|
|
2760
|
+
return mergeThreads(olderThreads, recent);
|
|
2284
2761
|
};
|
|
2285
|
-
const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], onConfirmDeleteThread, onModelChange = () => {}, onTurnActiveChange: onAssistantTurnActiveChange, resourceId, selectedThreadStorageKey, surveyId, threadApi, threadClient: providedThreadClient, threadLauncher, ...sessionProps }) => {
|
|
2762
|
+
const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], onConfirmDeleteThread, onModelChange = () => {}, onTurnActiveChange: onAssistantTurnActiveChange, resourceId, selectedThreadStorageKey, supportBundle, surveyId, threadApi, threadClient: providedThreadClient, threadLauncher, ...sessionProps }) => {
|
|
2286
2763
|
const t = useSurveyAssistantTranslation();
|
|
2764
|
+
const supportBundleEnabled = isSurveyAssistantSupportBundleEnabled(supportBundle);
|
|
2287
2765
|
const threadClient = useMemo(() => providedThreadClient ?? createSurveyAssistantThreadClient(threadApi), [providedThreadClient, threadApi]);
|
|
2288
2766
|
const storageKey = selectedThreadStorageKey === false ? null : selectedThreadStorageKey ?? `${SELECTED_THREAD_STORAGE_KEY}:${encodeURIComponent(resourceId)}${surveyId ? `:${encodeURIComponent(surveyId)}` : ""}`;
|
|
2289
2767
|
const [threads, setThreads] = useState([]);
|
|
@@ -2302,8 +2780,23 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2302
2780
|
const [assistantTurnActive, setAssistantTurnActive] = useState(false);
|
|
2303
2781
|
const [initialLaunch, setInitialLaunch] = useState();
|
|
2304
2782
|
const [promptFocusThreadId, setPromptFocusThreadId] = useState();
|
|
2783
|
+
const [diagnosticStore] = useState(() => {
|
|
2784
|
+
try {
|
|
2785
|
+
return createSurveyAssistantDiagnosticStore(supportBundle?.limits);
|
|
2786
|
+
} catch {
|
|
2787
|
+
return createSurveyAssistantDiagnosticStore();
|
|
2788
|
+
}
|
|
2789
|
+
});
|
|
2790
|
+
const [supportBundleOpen, setSupportBundleOpen] = useState(false);
|
|
2791
|
+
const [supportBundleLoading, setSupportBundleLoading] = useState(false);
|
|
2792
|
+
const [supportBundleError, setSupportBundleError] = useState();
|
|
2793
|
+
const [preparedSupportBundle, setPreparedSupportBundle] = useState();
|
|
2305
2794
|
const historyControlsRef = useRef(null);
|
|
2795
|
+
const historyButtonRef = useRef(null);
|
|
2306
2796
|
const loadingAllThreadsRef = useRef(false);
|
|
2797
|
+
const supportBundleAbortRef = useRef(null);
|
|
2798
|
+
const supportBundleFocusReturnRef = useRef(null);
|
|
2799
|
+
const supportBundleThreadIdRef = useRef(void 0);
|
|
2307
2800
|
const selectModel = useCallback((modelId) => {
|
|
2308
2801
|
if (!models.some((model) => model.id === modelId)) return;
|
|
2309
2802
|
onModelChange(modelId);
|
|
@@ -2358,7 +2851,7 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2358
2851
|
]);
|
|
2359
2852
|
useEffect(() => {
|
|
2360
2853
|
let cancelled = false;
|
|
2361
|
-
|
|
2854
|
+
Promise.resolve().then(() => threadClient.listPage()).then(async (page) => {
|
|
2362
2855
|
if (cancelled) return;
|
|
2363
2856
|
const availableThreads = page.threads;
|
|
2364
2857
|
setThreads(availableThreads);
|
|
@@ -2401,7 +2894,7 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2401
2894
|
if (!nextThreadCursor || loadingOlderThreads) return;
|
|
2402
2895
|
setLoadingOlderThreads(true);
|
|
2403
2896
|
try {
|
|
2404
|
-
const page = await
|
|
2897
|
+
const page = await threadClient.listPage({ cursor: nextThreadCursor });
|
|
2405
2898
|
setThreads((current) => mergeThreads(current, page.threads));
|
|
2406
2899
|
setNextThreadCursor(page.nextCursor);
|
|
2407
2900
|
} catch (error) {
|
|
@@ -2438,7 +2931,7 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2438
2931
|
try {
|
|
2439
2932
|
let cursor = nextThreadCursor;
|
|
2440
2933
|
while (cursor) {
|
|
2441
|
-
const page = await
|
|
2934
|
+
const page = await threadClient.listPage({ cursor });
|
|
2442
2935
|
setThreads((current) => mergeThreads(current, page.threads));
|
|
2443
2936
|
cursor = page.nextCursor;
|
|
2444
2937
|
setNextThreadCursor(cursor);
|
|
@@ -2529,19 +3022,79 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2529
3022
|
renameThread,
|
|
2530
3023
|
threads
|
|
2531
3024
|
]);
|
|
3025
|
+
const closeSupportBundle = useCallback(() => {
|
|
3026
|
+
supportBundleAbortRef.current?.abort();
|
|
3027
|
+
supportBundleAbortRef.current = null;
|
|
3028
|
+
setSupportBundleOpen(false);
|
|
3029
|
+
setSupportBundleLoading(false);
|
|
3030
|
+
setPreparedSupportBundle(void 0);
|
|
3031
|
+
}, []);
|
|
3032
|
+
const openSupportBundle = useCallback(async (focusReturnElement) => {
|
|
3033
|
+
if (!supportBundleEnabled || !selectedThread || assistantTurnActive) return;
|
|
3034
|
+
supportBundleFocusReturnRef.current = focusReturnElement ?? historyButtonRef.current;
|
|
3035
|
+
await commitEditingThread();
|
|
3036
|
+
setHistoryOpen(false);
|
|
3037
|
+
supportBundleAbortRef.current?.abort();
|
|
3038
|
+
const abortController = new AbortController();
|
|
3039
|
+
supportBundleAbortRef.current = abortController;
|
|
3040
|
+
setSupportBundleOpen(true);
|
|
3041
|
+
supportBundleThreadIdRef.current = selectedThread.id;
|
|
3042
|
+
setSupportBundleLoading(true);
|
|
3043
|
+
setSupportBundleError(void 0);
|
|
3044
|
+
setPreparedSupportBundle(void 0);
|
|
3045
|
+
try {
|
|
3046
|
+
const prepared = await prepareSurveyAssistantSupportBundle({
|
|
3047
|
+
config: supportBundle,
|
|
3048
|
+
controller: sessionProps.controller,
|
|
3049
|
+
diagnosticStore,
|
|
3050
|
+
resourceId,
|
|
3051
|
+
signal: abortController.signal,
|
|
3052
|
+
threadClient,
|
|
3053
|
+
threadId: selectedThread.id
|
|
3054
|
+
});
|
|
3055
|
+
if (abortController.signal.aborted || selectedThread.id !== prepared.threadId) return;
|
|
3056
|
+
setPreparedSupportBundle(prepared);
|
|
3057
|
+
} catch (error) {
|
|
3058
|
+
if (abortController.signal.aborted) return;
|
|
3059
|
+
setSupportBundleError(parseSurveyAssistantError(error).detail ?? t("supportBundle.preparationFailed"));
|
|
3060
|
+
} finally {
|
|
3061
|
+
if (supportBundleAbortRef.current === abortController) {
|
|
3062
|
+
supportBundleAbortRef.current = null;
|
|
3063
|
+
setSupportBundleLoading(false);
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
}, [
|
|
3067
|
+
assistantTurnActive,
|
|
3068
|
+
commitEditingThread,
|
|
3069
|
+
diagnosticStore,
|
|
3070
|
+
resourceId,
|
|
3071
|
+
selectedThread,
|
|
3072
|
+
sessionProps.controller,
|
|
3073
|
+
supportBundle,
|
|
3074
|
+
supportBundleEnabled,
|
|
3075
|
+
t,
|
|
3076
|
+
threadClient
|
|
3077
|
+
]);
|
|
3078
|
+
useEffect(() => () => {
|
|
3079
|
+
supportBundleAbortRef.current?.abort();
|
|
3080
|
+
}, []);
|
|
2532
3081
|
const deleteThread = useCallback(async (thread) => {
|
|
2533
3082
|
if (!(onConfirmDeleteThread ? await onConfirmDeleteThread(thread) : window.confirm(t("threads.deleteConfirm", { title: thread.title })))) return;
|
|
2534
3083
|
try {
|
|
2535
3084
|
await threadClient.delete(thread.id);
|
|
3085
|
+
diagnosticStore.deleteThread(thread.id);
|
|
2536
3086
|
const remaining = threads.filter((item) => item.id !== thread.id);
|
|
2537
3087
|
setThreads(remaining);
|
|
2538
|
-
if (selectedThread?.id === thread.id)
|
|
2539
|
-
|
|
3088
|
+
if (selectedThread?.id === thread.id) {
|
|
3089
|
+
if (remaining[0]) await selectThread(remaining[0]);
|
|
3090
|
+
else await createThread();
|
|
3091
|
+
}
|
|
2540
3092
|
} catch (error) {
|
|
2541
3093
|
setThreadError(parseSurveyAssistantError(error).detail ?? t("errors.fallbackDetail"));
|
|
2542
3094
|
}
|
|
2543
3095
|
}, [
|
|
2544
3096
|
createThread,
|
|
3097
|
+
diagnosticStore,
|
|
2545
3098
|
onConfirmDeleteThread,
|
|
2546
3099
|
selectThread,
|
|
2547
3100
|
selectedThread,
|
|
@@ -2564,7 +3117,7 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2564
3117
|
}, [initialLaunch]);
|
|
2565
3118
|
const refreshThreadList = useCallback(async (reportError) => {
|
|
2566
3119
|
try {
|
|
2567
|
-
const page = await
|
|
3120
|
+
const page = await threadClient.listPage();
|
|
2568
3121
|
setThreads((current) => mergeRecentThreadPage(current, page.threads));
|
|
2569
3122
|
const current = page.threads.find((thread) => thread.id === selectedThread?.id);
|
|
2570
3123
|
if (current && !editingThreadId) setSelectedThread((selected) => {
|
|
@@ -2628,6 +3181,14 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2628
3181
|
promptFocusThreadId,
|
|
2629
3182
|
selectedThread?.id
|
|
2630
3183
|
]);
|
|
3184
|
+
useEffect(() => {
|
|
3185
|
+
if (!supportBundleOpen || supportBundleThreadIdRef.current === selectedThread?.id) return;
|
|
3186
|
+
closeSupportBundle();
|
|
3187
|
+
}, [
|
|
3188
|
+
closeSupportBundle,
|
|
3189
|
+
selectedThread?.id,
|
|
3190
|
+
supportBundleOpen
|
|
3191
|
+
]);
|
|
2631
3192
|
useEffect(() => {
|
|
2632
3193
|
const handleFocus = () => {
|
|
2633
3194
|
refreshThreadList(false);
|
|
@@ -2699,6 +3260,7 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2699
3260
|
className: "flex size-8 items-center justify-center rounded-lg text-muted-foreground hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-50",
|
|
2700
3261
|
disabled: assistantTurnActive,
|
|
2701
3262
|
onClick: toggleHistory,
|
|
3263
|
+
ref: historyButtonRef,
|
|
2702
3264
|
title: t("threads.history"),
|
|
2703
3265
|
type: "button",
|
|
2704
3266
|
children: /* @__PURE__ */ jsx(HistoryIcon, { className: "size-4" })
|
|
@@ -2789,6 +3351,15 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2789
3351
|
children: loadingOlderThreads ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(LoaderCircleIcon, { className: "mr-1.5 size-3.5 animate-spin" }), normalizedThreadSearch ? t("threads.searching") : t("threads.loadingOlder")] }) : t("threads.loadOlder")
|
|
2790
3352
|
})
|
|
2791
3353
|
]
|
|
3354
|
+
}),
|
|
3355
|
+
supportBundleEnabled && /* @__PURE__ */ jsx("div", {
|
|
3356
|
+
className: "border-t border-border p-1",
|
|
3357
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
3358
|
+
className: "flex h-9 w-full items-center gap-2 rounded-md px-2 text-left text-muted-foreground text-xs hover:bg-muted hover:text-foreground",
|
|
3359
|
+
onClick: () => void openSupportBundle(historyButtonRef.current),
|
|
3360
|
+
type: "button",
|
|
3361
|
+
children: [/* @__PURE__ */ jsx(PackageOpenIcon, { className: "size-3.5" }), t("threads.exportSupportBundle")]
|
|
3362
|
+
})
|
|
2792
3363
|
})
|
|
2793
3364
|
]
|
|
2794
3365
|
})
|
|
@@ -2796,46 +3367,63 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2796
3367
|
});
|
|
2797
3368
|
return /* @__PURE__ */ jsxs("div", {
|
|
2798
3369
|
className: "relative h-full min-h-0",
|
|
2799
|
-
children: [
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
3370
|
+
children: [
|
|
3371
|
+
/* @__PURE__ */ createElement(SurveyAssistantChatPanel, {
|
|
3372
|
+
...sessionProps,
|
|
3373
|
+
embedded,
|
|
3374
|
+
focusPromptOnMount: selectedThread.id === promptFocusThreadId,
|
|
3375
|
+
hasEarlierMessages: Boolean(nextMessageCursor),
|
|
3376
|
+
initialLaunch: initialLaunch?.input,
|
|
3377
|
+
initialMessages,
|
|
3378
|
+
key: selectedThread.id,
|
|
3379
|
+
modelId,
|
|
3380
|
+
models,
|
|
3381
|
+
diagnosticStore,
|
|
3382
|
+
onExportDetails: supportBundleEnabled ? (trigger) => void openSupportBundle(trigger) : void 0,
|
|
3383
|
+
onInitialLaunchHandled: handleInitialLaunchHandled,
|
|
3384
|
+
onModelChange: selectModel,
|
|
3385
|
+
onFirstSubmit: handleFirstSubmit,
|
|
3386
|
+
onLoadEarlierMessages: loadEarlierMessages,
|
|
3387
|
+
onTurnSettled: handleTurnSettled,
|
|
3388
|
+
onTurnActiveChange: handleTurnActiveChange,
|
|
3389
|
+
resourceId,
|
|
3390
|
+
surveyId,
|
|
3391
|
+
threadControls,
|
|
3392
|
+
threadId: selectedThread.id,
|
|
3393
|
+
threadTitle: selectedThread.title
|
|
3394
|
+
}),
|
|
3395
|
+
supportBundleEnabled && /* @__PURE__ */ jsx(SurveyAssistantSupportBundleDialog, {
|
|
3396
|
+
config: supportBundle,
|
|
3397
|
+
error: supportBundleError,
|
|
3398
|
+
fallbackFocusReturnRef: historyButtonRef,
|
|
3399
|
+
focusReturnRef: supportBundleFocusReturnRef,
|
|
3400
|
+
loading: supportBundleLoading,
|
|
3401
|
+
onOpenChange: (open) => {
|
|
3402
|
+
if (!open) closeSupportBundle();
|
|
3403
|
+
},
|
|
3404
|
+
open: supportBundleOpen,
|
|
3405
|
+
prepared: preparedSupportBundle
|
|
3406
|
+
}),
|
|
3407
|
+
threadError && /* @__PURE__ */ jsxs("div", {
|
|
3408
|
+
className: "absolute right-3 bottom-3 left-3 z-40 rounded-lg border border-destructive/20 bg-popover px-3 py-2 text-xs shadow-lg",
|
|
3409
|
+
children: [
|
|
3410
|
+
/* @__PURE__ */ jsx("div", {
|
|
3411
|
+
className: "font-medium",
|
|
3412
|
+
children: t("panel.controlsUnavailable")
|
|
3413
|
+
}),
|
|
3414
|
+
/* @__PURE__ */ jsx("div", {
|
|
3415
|
+
className: "mt-0.5 text-muted-foreground",
|
|
3416
|
+
children: threadError
|
|
3417
|
+
}),
|
|
3418
|
+
/* @__PURE__ */ jsx("button", {
|
|
3419
|
+
className: "mt-1 font-medium hover:underline",
|
|
3420
|
+
onClick: () => setThreadError(null),
|
|
3421
|
+
type: "button",
|
|
3422
|
+
children: t("errors.dismiss")
|
|
3423
|
+
})
|
|
3424
|
+
]
|
|
3425
|
+
})
|
|
3426
|
+
]
|
|
2839
3427
|
});
|
|
2840
3428
|
};
|
|
2841
3429
|
const SurveyAssistantPanel = ({ language, localizations, ...props }) => /* @__PURE__ */ jsx("div", {
|