@case-framework/survey-assistant 0.5.0 → 0.7.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 +9 -4
- package/dist/attachments-B0hg3vpT.mjs +11 -0
- package/dist/attachments-B0hg3vpT.mjs.map +1 -0
- package/dist/authoring-references-BJQ_1nMX.mjs +115 -0
- package/dist/authoring-references-BJQ_1nMX.mjs.map +1 -0
- package/dist/capabilities-1KNnNO1_.mjs +73 -0
- package/dist/capabilities-1KNnNO1_.mjs.map +1 -0
- package/dist/{capabilities-CnsVuJ1k.d.mts → capabilities-DVTfogjv.d.mts} +1 -1
- package/dist/{capabilities-CnsVuJ1k.d.mts.map → capabilities-DVTfogjv.d.mts.map} +1 -1
- package/dist/capabilities-default.d.mts +1 -1
- package/dist/capabilities-default.d.mts.map +1 -1
- package/dist/capabilities-default.mjs +47 -20
- package/dist/capabilities-default.mjs.map +1 -1
- package/dist/{constants-CFUWrRtl.mjs → constants-0UHGFcRJ.mjs} +1 -1
- package/dist/{constants-CFUWrRtl.mjs.map → constants-0UHGFcRJ.mjs.map} +1 -1
- package/dist/{constants-DbrJxxOh.d.mts → constants-Be91Gay9.d.mts} +4 -4
- package/dist/{constants-DbrJxxOh.d.mts.map → constants-Be91Gay9.d.mts.map} +1 -1
- package/dist/{controller-proxy-jWIPOZAv.mjs → controller-proxy-BH05e-C2.mjs} +21 -8
- package/dist/controller-proxy-BH05e-C2.mjs.map +1 -0
- package/dist/{controller-proxy-BdKF2yrq.d.mts → controller-proxy-Bd0ZHBPF.d.mts} +11 -11
- package/dist/controller-proxy-Bd0ZHBPF.d.mts.map +1 -0
- package/dist/{digest-Dyjch_sC.d.mts → digest-SJmoYVaK.d.mts} +2 -2
- package/dist/{digest-Dyjch_sC.d.mts.map → digest-SJmoYVaK.d.mts.map} +1 -1
- package/dist/digest.d.mts +1 -1
- package/dist/{engine-DcSdLRle.mjs → engine-Bo85Oyj0.mjs} +3129 -2435
- package/dist/engine-Bo85Oyj0.mjs.map +1 -0
- package/dist/engine.d.mts +3 -3
- package/dist/engine.mjs +3 -3
- package/dist/{fair-guidance-CEdJYccK.mjs → fair-guidance-CRYCRxQm.mjs} +1 -1
- package/dist/{fair-guidance-CEdJYccK.mjs.map → fair-guidance-CRYCRxQm.mjs.map} +1 -1
- package/dist/{index-Da_Hb9-1.d.mts → index-Tnqv-yKW.d.mts} +73 -67
- package/dist/index-Tnqv-yKW.d.mts.map +1 -0
- package/dist/index-l_EK4yK7.d.mts +404 -0
- package/dist/index-l_EK4yK7.d.mts.map +1 -0
- package/dist/{index-BApnIiCI.d.mts → index-nhrgbgO5.d.mts} +24 -5
- package/dist/index-nhrgbgO5.d.mts.map +1 -0
- package/dist/{index-DhNQKOwr.d.mts → index-x0qprHgK.d.mts} +19 -7
- package/dist/index-x0qprHgK.d.mts.map +1 -0
- package/dist/{lifecycle-DWv5CiSu.d.mts → lifecycle-Bx0aq_4S.d.mts} +8 -2
- package/dist/{lifecycle-DWv5CiSu.d.mts.map → lifecycle-Bx0aq_4S.d.mts.map} +1 -1
- package/dist/{memory-thread-repository-CvYZwni6.mjs → memory-thread-repository-KWHQWFEW.mjs} +45 -14
- package/dist/memory-thread-repository-KWHQWFEW.mjs.map +1 -0
- package/dist/{protocol-DJUP4gc0.mjs → protocol-BhzQbx81.mjs} +66 -16
- package/dist/protocol-BhzQbx81.mjs.map +1 -0
- package/dist/protocol.d.mts +4 -4
- package/dist/protocol.mjs +3 -2
- package/dist/react-B3ybjJ-X.mjs +1620 -0
- package/dist/react-B3ybjJ-X.mjs.map +1 -0
- package/dist/react-integration.d.mts +1 -1
- package/dist/react-integration.mjs +1 -1
- package/dist/react.d.mts +3 -3
- package/dist/react.mjs +3 -3
- package/dist/references/assistant-operations.md +45 -39
- package/dist/references/expressions.md +28 -0
- package/dist/references/item-types.md +1 -1
- package/dist/references/localization.md +5 -4
- package/dist/references/rich-text-content.md +60 -27
- package/dist/references/source-material-surveys.md +9 -2
- package/dist/references/survey-data-model.md +9 -1
- package/dist/{request-context-D1sC54ZA.mjs → request-context-CG4SWijt.mjs} +3 -3
- package/dist/{request-context-D1sC54ZA.mjs.map → request-context-CG4SWijt.mjs.map} +1 -1
- package/dist/{request-guardrails-h4t6u8mP.mjs → request-guardrails-TmgQtqp4.mjs} +5 -12
- package/dist/request-guardrails-TmgQtqp4.mjs.map +1 -0
- package/dist/server-agent.d.mts +19 -8
- package/dist/server-agent.d.mts.map +1 -1
- package/dist/server-agent.mjs +11 -13
- package/dist/server-agent.mjs.map +1 -1
- package/dist/server-runtime.d.mts +12 -6
- package/dist/server-runtime.d.mts.map +1 -1
- package/dist/server-runtime.mjs +9 -4
- package/dist/server-runtime.mjs.map +1 -1
- package/dist/server-tasks.d.mts +1 -1
- package/dist/server-tasks.mjs +5 -5
- package/dist/server-tools.d.mts +1 -1
- package/dist/server-tools.mjs +1 -1
- package/dist/server.d.mts +7 -7
- package/dist/server.mjs +6 -6
- package/dist/storage-postgres.d.mts +1 -1
- package/dist/storage-postgres.mjs +1 -1
- package/dist/{tasks-CCtxjhwh.d.mts → tasks-CYqrcaRO.d.mts} +16 -4
- package/dist/tasks-CYqrcaRO.d.mts.map +1 -0
- package/dist/{thread-documents-Dvo6XS7o.d.mts → thread-documents-rmd6nyX9.d.mts} +1 -1
- package/dist/{thread-documents-Dvo6XS7o.d.mts.map → thread-documents-rmd6nyX9.d.mts.map} +1 -1
- package/dist/{thread-handlers-Bt9cDo-F.d.mts → thread-handlers-DBAaU7BA.d.mts} +7 -5
- package/dist/thread-handlers-DBAaU7BA.d.mts.map +1 -0
- package/dist/{tools-3tq-XqI0.mjs → tools-BvSovehT.mjs} +433 -495
- package/dist/tools-BvSovehT.mjs.map +1 -0
- package/dist/ui.css +1 -1
- package/dist/ui.d.mts +5 -4
- package/dist/ui.d.mts.map +1 -1
- package/dist/ui.mjs +744 -131
- package/dist/ui.mjs.map +1 -1
- package/docs/integration.md +43 -3
- package/package.json +21 -19
- package/dist/authoring-references-yyYC4Ydi.mjs +0 -98
- package/dist/authoring-references-yyYC4Ydi.mjs.map +0 -1
- package/dist/controller-proxy-BdKF2yrq.d.mts.map +0 -1
- package/dist/controller-proxy-jWIPOZAv.mjs.map +0 -1
- package/dist/engine-DcSdLRle.mjs.map +0 -1
- package/dist/form-authoring-BQh40yDb.mjs +0 -155
- package/dist/form-authoring-BQh40yDb.mjs.map +0 -1
- package/dist/index-BApnIiCI.d.mts.map +0 -1
- package/dist/index-Da_Hb9-1.d.mts.map +0 -1
- package/dist/index-DhNQKOwr.d.mts.map +0 -1
- package/dist/index-dV6df0W3.d.mts +0 -224
- package/dist/index-dV6df0W3.d.mts.map +0 -1
- package/dist/memory-thread-repository-CvYZwni6.mjs.map +0 -1
- package/dist/protocol-DJUP4gc0.mjs.map +0 -1
- package/dist/react-CY6N7lVi.mjs +0 -768
- package/dist/react-CY6N7lVi.mjs.map +0 -1
- package/dist/request-guardrails-h4t6u8mP.mjs.map +0 -1
- package/dist/tasks-CCtxjhwh.d.mts.map +0 -1
- package/dist/thread-handlers-Bt9cDo-F.d.mts.map +0 -1
- package/dist/tools-3tq-XqI0.mjs.map +0 -1
package/dist/ui.mjs
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { o as
|
|
2
|
+
import { Lt as getSurveyAssistantEmbeddedBinaryMarker, Mt as parseSurveyAssistantError, jt as isSurveyAssistantErrorRetryable, l as surveyAssistantTurnFinalSchema, n as SURVEY_ASSISTANT_TURN_FINAL_PART_TYPE } from "./protocol-BhzQbx81.mjs";
|
|
3
|
+
import { n as isSurveyAssistantAttachmentMediaType, t as SURVEY_ASSISTANT_ATTACHMENT_MEDIA_TYPES } from "./attachments-B0hg3vpT.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-B3ybjJ-X.mjs";
|
|
5
|
+
import { o as connectSurveyAssistantThreadLauncher } from "./controller-proxy-BH05e-C2.mjs";
|
|
5
6
|
import { getToolName, isFileUIPart, isReasoningUIPart, isToolUIPart } from "ai";
|
|
6
7
|
import { createContext, createElement, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
7
|
-
import { Collapsible, Select, Slot } from "radix-ui";
|
|
8
|
+
import { Checkbox, Collapsible, Dialog, Select, Slot, Tooltip } from "radix-ui";
|
|
8
9
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
10
|
import { clsx } from "clsx";
|
|
10
11
|
import { twMerge } from "tailwind-merge";
|
|
11
12
|
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
12
|
-
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";
|
|
13
|
+
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";
|
|
13
14
|
import { motion } from "motion/react";
|
|
14
15
|
import { createLocalizationTranslator, mergeLocalizationCatalogs } from "@case-framework/ui-localization";
|
|
15
16
|
import { cva } from "class-variance-authority";
|
|
@@ -123,9 +124,11 @@ const surveyAssistantEnMessages = {
|
|
|
123
124
|
},
|
|
124
125
|
input: {
|
|
125
126
|
placeholder: "Ask about the survey...",
|
|
126
|
-
attachFiles: "Attach
|
|
127
|
-
dropFiles: "Drop
|
|
128
|
-
|
|
127
|
+
attachFiles: "Attach a PDF, PNG, or JPG",
|
|
128
|
+
dropFiles: "Drop a PDF, PNG, or JPG to attach",
|
|
129
|
+
supportedFiles: "Supported: PDF, PNG, and JPG. Export Word documents as PDF.",
|
|
130
|
+
unsupportedFiles: "{filenames} can't be attached. Supported formats: PDF, PNG, and JPG.",
|
|
131
|
+
wordFilesUnsupported: "Word documents aren't supported. Export {filenames} as PDF, then attach the PDF.",
|
|
129
132
|
removeFile: "Remove {filename}",
|
|
130
133
|
send: "Send message",
|
|
131
134
|
stop: "Stop response",
|
|
@@ -244,6 +247,11 @@ const surveyAssistantEnMessages = {
|
|
|
244
247
|
dismiss: "Dismiss",
|
|
245
248
|
dismissAssistant: "Dismiss assistant error",
|
|
246
249
|
retry: "Try again",
|
|
250
|
+
exportDetails: "Export details",
|
|
251
|
+
showProviderDetails: "Show full provider message",
|
|
252
|
+
hideProviderDetails: "Hide provider message",
|
|
253
|
+
upstreamStatus: "Provider status {status}",
|
|
254
|
+
providerRequestId: "Request {requestId}",
|
|
247
255
|
fallbackDetail: "The assistant hit an error on the previous turn.",
|
|
248
256
|
model_unavailable: {
|
|
249
257
|
title: "Model unavailable",
|
|
@@ -269,6 +277,7 @@ const surveyAssistantEnMessages = {
|
|
|
269
277
|
threads: {
|
|
270
278
|
newChat: "New chat",
|
|
271
279
|
history: "Chat history",
|
|
280
|
+
exportSupportBundle: "Export support bundle",
|
|
272
281
|
recent: "Recent chats",
|
|
273
282
|
search: "Search chats",
|
|
274
283
|
searching: "Searching older chats…",
|
|
@@ -282,6 +291,48 @@ const surveyAssistantEnMessages = {
|
|
|
282
291
|
delete: "Delete {title}",
|
|
283
292
|
deleteTitle: "Delete chat",
|
|
284
293
|
deleteConfirm: "Delete \"{title}\" and its attachments?"
|
|
294
|
+
},
|
|
295
|
+
supportBundle: {
|
|
296
|
+
title: "Export support bundle",
|
|
297
|
+
description: "Choose which broad data categories to include. The ZIP is created and downloaded in this browser.",
|
|
298
|
+
close: "Close export dialog",
|
|
299
|
+
preparing: "Preparing diagnostic data…",
|
|
300
|
+
preparationFailed: "The support bundle could not be prepared",
|
|
301
|
+
generationFailed: "The support bundle could not be generated.",
|
|
302
|
+
chooseData: "Data to include",
|
|
303
|
+
core: {
|
|
304
|
+
title: "Core technical diagnostics (always included)",
|
|
305
|
+
description: "Request and turn identifiers, timing, status and error details, counters, and availability information."
|
|
306
|
+
},
|
|
307
|
+
categories: {
|
|
308
|
+
conversation: {
|
|
309
|
+
title: "Conversation and agent activity",
|
|
310
|
+
description: "Messages, visible reasoning, tool activity, and apply results."
|
|
311
|
+
},
|
|
312
|
+
survey: {
|
|
313
|
+
title: "Survey data",
|
|
314
|
+
description: "The submitted survey and a snapshot captured when this dialog opened."
|
|
315
|
+
},
|
|
316
|
+
attachments: {
|
|
317
|
+
title: "Attachments",
|
|
318
|
+
description: "Available source PDFs and images from this browser session."
|
|
319
|
+
}
|
|
320
|
+
},
|
|
321
|
+
sensitiveNote: "Conversation, reasoning, surveys, and attachments can contain sensitive research or authoring data. Deselect a category if you do not want to share it.",
|
|
322
|
+
estimatedSize: "Estimated ZIP size",
|
|
323
|
+
emailWarning: "This may be too large for some email providers.",
|
|
324
|
+
tooLarge: "The selection is too large. Deselect a category before downloading.",
|
|
325
|
+
unavailable: "{count} diagnostic component is unavailable or was truncated.",
|
|
326
|
+
unavailablePlural: "{count} diagnostic components are unavailable or were truncated.",
|
|
327
|
+
localOnly: "Nothing is sent automatically. You decide whether and how to share the downloaded ZIP.",
|
|
328
|
+
download: "Download support bundle",
|
|
329
|
+
downloadAgain: "Download again",
|
|
330
|
+
downloaded: "Downloaded {filename}. Attach it manually when contacting support.",
|
|
331
|
+
openEmail: "Open email draft",
|
|
332
|
+
supportDetails: "Support details to include with your request",
|
|
333
|
+
copyDetails: "Copy support details",
|
|
334
|
+
detailsCopied: "Support details copied",
|
|
335
|
+
copyDetailsFailed: "The support details could not be copied. Select and copy them manually."
|
|
285
336
|
}
|
|
286
337
|
};
|
|
287
338
|
//#endregion
|
|
@@ -338,9 +389,11 @@ const surveyAssistantNlMessages = {
|
|
|
338
389
|
},
|
|
339
390
|
input: {
|
|
340
391
|
placeholder: "Vraag iets over de survey...",
|
|
341
|
-
attachFiles: "
|
|
342
|
-
dropFiles: "Sleep
|
|
343
|
-
|
|
392
|
+
attachFiles: "Een pdf-, png- of jpg-bestand toevoegen",
|
|
393
|
+
dropFiles: "Sleep een pdf-, png- of jpg-bestand hierheen om het toe te voegen",
|
|
394
|
+
supportedFiles: "Ondersteund: pdf, png en jpg. Exporteer Word-documenten als pdf.",
|
|
395
|
+
unsupportedFiles: "{filenames} kan niet worden toegevoegd. Ondersteunde formaten: pdf, png en jpg.",
|
|
396
|
+
wordFilesUnsupported: "Word-documenten worden niet ondersteund. Exporteer {filenames} als pdf en voeg daarna de pdf toe.",
|
|
344
397
|
removeFile: "{filename} verwijderen",
|
|
345
398
|
send: "Bericht verzenden",
|
|
346
399
|
stop: "Antwoord stoppen",
|
|
@@ -459,6 +512,11 @@ const surveyAssistantNlMessages = {
|
|
|
459
512
|
dismiss: "Sluiten",
|
|
460
513
|
dismissAssistant: "Assistentfout sluiten",
|
|
461
514
|
retry: "Opnieuw proberen",
|
|
515
|
+
exportDetails: "Details exporteren",
|
|
516
|
+
showProviderDetails: "Volledig providerbericht tonen",
|
|
517
|
+
hideProviderDetails: "Providerbericht verbergen",
|
|
518
|
+
upstreamStatus: "Providerstatus {status}",
|
|
519
|
+
providerRequestId: "Verzoek {requestId}",
|
|
462
520
|
fallbackDetail: "Er is tijdens de vorige beurt een fout opgetreden.",
|
|
463
521
|
model_unavailable: {
|
|
464
522
|
title: "Model niet beschikbaar",
|
|
@@ -484,6 +542,7 @@ const surveyAssistantNlMessages = {
|
|
|
484
542
|
threads: {
|
|
485
543
|
newChat: "Nieuwe chat",
|
|
486
544
|
history: "Chatgeschiedenis",
|
|
545
|
+
exportSupportBundle: "Supportbundel exporteren",
|
|
487
546
|
recent: "Recente chats",
|
|
488
547
|
search: "Chats zoeken",
|
|
489
548
|
searching: "Oudere chats zoeken…",
|
|
@@ -497,6 +556,48 @@ const surveyAssistantNlMessages = {
|
|
|
497
556
|
delete: "{title} verwijderen",
|
|
498
557
|
deleteTitle: "Chat verwijderen",
|
|
499
558
|
deleteConfirm: "\"{title}\" en de bijlagen verwijderen?"
|
|
559
|
+
},
|
|
560
|
+
supportBundle: {
|
|
561
|
+
title: "Supportbundel exporteren",
|
|
562
|
+
description: "Kies welke brede gegevenscategorieën worden opgenomen. Het ZIP-bestand wordt in deze browser gemaakt en gedownload.",
|
|
563
|
+
close: "Exportvenster sluiten",
|
|
564
|
+
preparing: "Diagnostische gegevens voorbereiden…",
|
|
565
|
+
preparationFailed: "De supportbundel kon niet worden voorbereid",
|
|
566
|
+
generationFailed: "De supportbundel kon niet worden gemaakt.",
|
|
567
|
+
chooseData: "Op te nemen gegevens",
|
|
568
|
+
core: {
|
|
569
|
+
title: "Technische basisgegevens (altijd opgenomen)",
|
|
570
|
+
description: "Verzoek- en beurt-ID's, timing, status- en foutdetails, aantallen en beschikbaarheid."
|
|
571
|
+
},
|
|
572
|
+
categories: {
|
|
573
|
+
conversation: {
|
|
574
|
+
title: "Gesprek en agentactiviteit",
|
|
575
|
+
description: "Berichten, zichtbare redenering, hulpmiddelactiviteit en toepassingsresultaten."
|
|
576
|
+
},
|
|
577
|
+
survey: {
|
|
578
|
+
title: "Surveygegevens",
|
|
579
|
+
description: "De verzonden survey en een momentopname van toen dit venster werd geopend."
|
|
580
|
+
},
|
|
581
|
+
attachments: {
|
|
582
|
+
title: "Bijlagen",
|
|
583
|
+
description: "Beschikbare bron-pdf's en afbeeldingen uit deze browsersessie."
|
|
584
|
+
}
|
|
585
|
+
},
|
|
586
|
+
sensitiveNote: "Gesprek, redenering, surveys en bijlagen kunnen gevoelige onderzoeks- of auteursgegevens bevatten. Schakel een categorie uit als je die niet wilt delen.",
|
|
587
|
+
estimatedSize: "Geschatte ZIP-grootte",
|
|
588
|
+
emailWarning: "Dit bestand kan te groot zijn voor sommige e-mailproviders.",
|
|
589
|
+
tooLarge: "De selectie is te groot. Schakel een categorie uit voordat je downloadt.",
|
|
590
|
+
unavailable: "{count} diagnostisch onderdeel is niet beschikbaar of is ingekort.",
|
|
591
|
+
unavailablePlural: "{count} diagnostische onderdelen zijn niet beschikbaar of zijn ingekort.",
|
|
592
|
+
localOnly: "Er wordt niets automatisch verzonden. Je bepaalt zelf of en hoe je het gedownloade ZIP-bestand deelt.",
|
|
593
|
+
download: "Supportbundel downloaden",
|
|
594
|
+
downloadAgain: "Opnieuw downloaden",
|
|
595
|
+
downloaded: "{filename} is gedownload. Voeg het handmatig toe wanneer je contact opneemt met support.",
|
|
596
|
+
openEmail: "E-mailconcept openen",
|
|
597
|
+
supportDetails: "Supportgegevens voor je verzoek",
|
|
598
|
+
copyDetails: "Supportgegevens kopiëren",
|
|
599
|
+
detailsCopied: "Supportgegevens gekopieerd",
|
|
600
|
+
copyDetailsFailed: "De supportgegevens konden niet worden gekopieerd. Selecteer en kopieer ze handmatig."
|
|
500
601
|
}
|
|
501
602
|
};
|
|
502
603
|
//#endregion
|
|
@@ -771,9 +872,39 @@ const MessageContent = ({ children, className, ...props }) => /* @__PURE__ */ js
|
|
|
771
872
|
children
|
|
772
873
|
});
|
|
773
874
|
//#endregion
|
|
875
|
+
//#region src/ui/internal/tooltip.tsx
|
|
876
|
+
const TooltipProvider = Tooltip.Provider;
|
|
877
|
+
const Tooltip$1 = Tooltip.Root;
|
|
878
|
+
const TooltipTrigger = Tooltip.Trigger;
|
|
879
|
+
const TooltipContent = ({ className, sideOffset = 6, ...props }) => /* @__PURE__ */ jsx(Tooltip.Portal, { children: /* @__PURE__ */ jsx("div", {
|
|
880
|
+
className: "case-survey-assistant case-survey-assistant-portal",
|
|
881
|
+
children: /* @__PURE__ */ jsx(Tooltip.Content, {
|
|
882
|
+
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),
|
|
883
|
+
sideOffset,
|
|
884
|
+
...props
|
|
885
|
+
})
|
|
886
|
+
}) });
|
|
887
|
+
//#endregion
|
|
774
888
|
//#region src/ui/internal/prompt-input.tsx
|
|
775
|
-
const SUPPORTED_FILE_ACCEPT =
|
|
776
|
-
|
|
889
|
+
const SUPPORTED_FILE_ACCEPT = [
|
|
890
|
+
".pdf",
|
|
891
|
+
".png",
|
|
892
|
+
".jpg",
|
|
893
|
+
".jpeg",
|
|
894
|
+
...SURVEY_ASSISTANT_ATTACHMENT_MEDIA_TYPES
|
|
895
|
+
].join(",");
|
|
896
|
+
const WORD_DOCUMENT_MEDIA_TYPES = new Set([
|
|
897
|
+
"application/msword",
|
|
898
|
+
"application/vnd.ms-word",
|
|
899
|
+
"application/vnd.ms-word.document.macroenabled.12",
|
|
900
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
901
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.template"
|
|
902
|
+
]);
|
|
903
|
+
const getUnsupportedAttachmentKind = ({ name, type }) => {
|
|
904
|
+
if (isSurveyAssistantAttachmentMediaType(type)) return null;
|
|
905
|
+
if (WORD_DOCUMENT_MEDIA_TYPES.has(type.toLowerCase()) || /\.(?:doc|docm|docx|dot|dotm|dotx)$/i.test(name)) return "word";
|
|
906
|
+
return "other";
|
|
907
|
+
};
|
|
777
908
|
const formatFileSize = (size) => {
|
|
778
909
|
if (size < 1024 * 1024) return `${Math.max(1, Math.round(size / 1024))} KB`;
|
|
779
910
|
return `${(size / (1024 * 1024)).toFixed(size < 10 * 1024 * 1024 ? 1 : 0)} MB`;
|
|
@@ -801,7 +932,7 @@ const PromptInput = ({ attachmentsDisabled = false, children, className, onDragE
|
|
|
801
932
|
const [uncontrolledValue, setUncontrolledValue] = useState("");
|
|
802
933
|
const [files, setFiles] = useState([]);
|
|
803
934
|
const [isDraggingFiles, setIsDraggingFiles] = useState(false);
|
|
804
|
-
const [
|
|
935
|
+
const [unsupportedFiles, setUnsupportedFiles] = useState([]);
|
|
805
936
|
const fileDragDepthRef = useRef(0);
|
|
806
937
|
const t = useSurveyAssistantTranslation();
|
|
807
938
|
const value = controlledValue ?? uncontrolledValue;
|
|
@@ -811,10 +942,16 @@ const PromptInput = ({ attachmentsDisabled = false, children, className, onDragE
|
|
|
811
942
|
}, [controlledValue, onValueChange]);
|
|
812
943
|
const addFiles = useCallback((fileList) => {
|
|
813
944
|
const nextFiles = Array.from(fileList ?? []);
|
|
814
|
-
const supportedFiles = nextFiles.filter(
|
|
815
|
-
const
|
|
945
|
+
const supportedFiles = nextFiles.filter((file) => getUnsupportedAttachmentKind(file) === null);
|
|
946
|
+
const rejectedFiles = nextFiles.flatMap((file) => {
|
|
947
|
+
const kind = getUnsupportedAttachmentKind(file);
|
|
948
|
+
return kind ? [{
|
|
949
|
+
kind,
|
|
950
|
+
name: file.name
|
|
951
|
+
}] : [];
|
|
952
|
+
});
|
|
816
953
|
setFiles((currentFiles) => [...currentFiles, ...supportedFiles]);
|
|
817
|
-
|
|
954
|
+
setUnsupportedFiles(rejectedFiles);
|
|
818
955
|
}, []);
|
|
819
956
|
const removeFile = useCallback((index) => {
|
|
820
957
|
setFiles((currentFiles) => currentFiles.filter((_, fileIndex) => fileIndex !== index));
|
|
@@ -825,12 +962,12 @@ const PromptInput = ({ attachmentsDisabled = false, children, className, onDragE
|
|
|
825
962
|
files,
|
|
826
963
|
addFiles,
|
|
827
964
|
removeFile,
|
|
828
|
-
|
|
965
|
+
unsupportedFiles
|
|
829
966
|
}), [
|
|
830
967
|
addFiles,
|
|
831
968
|
files,
|
|
832
969
|
removeFile,
|
|
833
|
-
|
|
970
|
+
unsupportedFiles,
|
|
834
971
|
value
|
|
835
972
|
]);
|
|
836
973
|
const handleSubmit = useCallback(async (event) => {
|
|
@@ -843,7 +980,7 @@ const PromptInput = ({ attachmentsDisabled = false, children, className, onDragE
|
|
|
843
980
|
}, event) === false) return;
|
|
844
981
|
setValue("");
|
|
845
982
|
setFiles([]);
|
|
846
|
-
|
|
983
|
+
setUnsupportedFiles([]);
|
|
847
984
|
}, [
|
|
848
985
|
files,
|
|
849
986
|
onSubmit,
|
|
@@ -903,39 +1040,48 @@ const PromptInput = ({ attachmentsDisabled = false, children, className, onDragE
|
|
|
903
1040
|
});
|
|
904
1041
|
};
|
|
905
1042
|
const PromptInputBody = ({ children, className, ...props }) => {
|
|
906
|
-
const { files, removeFile,
|
|
1043
|
+
const { files, removeFile, unsupportedFiles } = usePromptInput();
|
|
907
1044
|
const t = useSurveyAssistantTranslation();
|
|
1045
|
+
const unsupportedWordFileNames = unsupportedFiles.filter((file) => file.kind === "word").map((file) => file.name);
|
|
1046
|
+
const unsupportedOtherFileNames = unsupportedFiles.filter((file) => file.kind === "other").map((file) => file.name);
|
|
908
1047
|
return /* @__PURE__ */ jsxs("div", {
|
|
909
1048
|
className: cn("contents", className),
|
|
910
1049
|
...props,
|
|
911
|
-
children: [children, (files.length > 0 ||
|
|
1050
|
+
children: [children, (files.length > 0 || unsupportedFiles.length > 0) && /* @__PURE__ */ jsxs("div", {
|
|
912
1051
|
className: "flex flex-wrap gap-2 px-3 pb-2",
|
|
913
|
-
children: [
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
className: "
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
1052
|
+
children: [
|
|
1053
|
+
files.map((file, index) => /* @__PURE__ */ jsxs("div", {
|
|
1054
|
+
className: "inline-flex max-w-full items-center gap-2 rounded-md border border-border bg-muted px-2 py-1 text-xs",
|
|
1055
|
+
children: [
|
|
1056
|
+
/* @__PURE__ */ jsx(FileIcon, { className: "size-3.5 shrink-0 text-muted-foreground" }),
|
|
1057
|
+
/* @__PURE__ */ jsx("span", {
|
|
1058
|
+
className: "min-w-0 truncate",
|
|
1059
|
+
children: file.name
|
|
1060
|
+
}),
|
|
1061
|
+
/* @__PURE__ */ jsx("span", {
|
|
1062
|
+
className: "shrink-0 text-muted-foreground",
|
|
1063
|
+
children: formatFileSize(file.size)
|
|
1064
|
+
}),
|
|
1065
|
+
/* @__PURE__ */ jsxs("button", {
|
|
1066
|
+
className: "shrink-0 rounded-sm text-muted-foreground hover:text-foreground",
|
|
1067
|
+
onClick: () => removeFile(index),
|
|
1068
|
+
type: "button",
|
|
1069
|
+
children: [/* @__PURE__ */ jsx(XIcon, { className: "size-3.5" }), /* @__PURE__ */ jsx("span", {
|
|
1070
|
+
className: "sr-only",
|
|
1071
|
+
children: t("input.removeFile", { filename: file.name })
|
|
1072
|
+
})]
|
|
1073
|
+
})
|
|
1074
|
+
]
|
|
1075
|
+
}, `${file.name}-${file.lastModified}-${index}`)),
|
|
1076
|
+
unsupportedWordFileNames.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
1077
|
+
className: "text-destructive text-xs",
|
|
1078
|
+
children: t("input.wordFilesUnsupported", { filenames: unsupportedWordFileNames.join(", ") })
|
|
1079
|
+
}),
|
|
1080
|
+
unsupportedOtherFileNames.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
1081
|
+
className: "text-destructive text-xs",
|
|
1082
|
+
children: t("input.unsupportedFiles", { filenames: unsupportedOtherFileNames.join(", ") })
|
|
1083
|
+
})
|
|
1084
|
+
]
|
|
939
1085
|
})]
|
|
940
1086
|
});
|
|
941
1087
|
};
|
|
@@ -964,28 +1110,38 @@ const PromptInputFooter = ({ className, ...props }) => /* @__PURE__ */ jsx("div"
|
|
|
964
1110
|
const PromptInputAttachmentButton = ({ accept = SUPPORTED_FILE_ACCEPT, className, disabled, onChange, ...props }) => {
|
|
965
1111
|
const { addFiles } = usePromptInput();
|
|
966
1112
|
const t = useSurveyAssistantTranslation();
|
|
967
|
-
return /* @__PURE__ */
|
|
968
|
-
|
|
969
|
-
children: [
|
|
970
|
-
|
|
971
|
-
/* @__PURE__ */
|
|
972
|
-
className: "
|
|
973
|
-
children:
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1113
|
+
return /* @__PURE__ */ jsx(TooltipProvider, {
|
|
1114
|
+
delayDuration: 300,
|
|
1115
|
+
children: /* @__PURE__ */ jsxs(Tooltip$1, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
1116
|
+
asChild: true,
|
|
1117
|
+
children: /* @__PURE__ */ jsxs("label", {
|
|
1118
|
+
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),
|
|
1119
|
+
children: [
|
|
1120
|
+
/* @__PURE__ */ jsx(PaperclipIcon, { className: "size-4" }),
|
|
1121
|
+
/* @__PURE__ */ jsx("span", {
|
|
1122
|
+
className: "sr-only",
|
|
1123
|
+
children: t("input.attachFiles")
|
|
1124
|
+
}),
|
|
1125
|
+
/* @__PURE__ */ jsx("input", {
|
|
1126
|
+
accept,
|
|
1127
|
+
className: "sr-only",
|
|
1128
|
+
disabled,
|
|
1129
|
+
multiple: true,
|
|
1130
|
+
onChange: (event) => {
|
|
1131
|
+
addFiles(event.currentTarget.files);
|
|
1132
|
+
onChange?.(event);
|
|
1133
|
+
event.currentTarget.value = "";
|
|
1134
|
+
},
|
|
1135
|
+
type: "file",
|
|
1136
|
+
...props
|
|
1137
|
+
})
|
|
1138
|
+
]
|
|
987
1139
|
})
|
|
988
|
-
|
|
1140
|
+
}), /* @__PURE__ */ jsx(TooltipContent, {
|
|
1141
|
+
align: "start",
|
|
1142
|
+
side: "top",
|
|
1143
|
+
children: t("input.supportedFiles")
|
|
1144
|
+
})] })
|
|
989
1145
|
});
|
|
990
1146
|
};
|
|
991
1147
|
const PromptInputSubmit = ({ className, status, onStop, onClick, ...props }) => {
|
|
@@ -1160,9 +1316,9 @@ const SurveyAssistantPromptInput = ({ attachmentsDisabled = false, attachmentBut
|
|
|
1160
1316
|
//#region src/ui/internal/tool-technical-details.ts
|
|
1161
1317
|
const formatOmittedLength = (length) => length.toLocaleString("en-US");
|
|
1162
1318
|
const stringifyToolTechnicalDetails = (value) => JSON.stringify(value, function redactEmbeddedBinary(key, currentValue) {
|
|
1163
|
-
const
|
|
1164
|
-
if (
|
|
1165
|
-
if (
|
|
1319
|
+
const marker = getSurveyAssistantEmbeddedBinaryMarker(currentValue, this && typeof this === "object" ? this : void 0, key);
|
|
1320
|
+
if (marker?.redacted === "base64") return `[embedded base64 omitted: ${formatOmittedLength(marker.characters)} characters]`;
|
|
1321
|
+
if (marker?.redacted === "data-url") return `[base64 data URL omitted: ${formatOmittedLength(marker.characters)} characters]`;
|
|
1166
1322
|
return currentValue;
|
|
1167
1323
|
}, 2);
|
|
1168
1324
|
//#endregion
|
|
@@ -1353,7 +1509,7 @@ const Response = ({ children, className, controls = false, plugins, ...props })
|
|
|
1353
1509
|
code: plugins?.code ?? codeHighlighter
|
|
1354
1510
|
}), [plugins]);
|
|
1355
1511
|
return /* @__PURE__ */ jsx(Streamdown, {
|
|
1356
|
-
className: cn("leading-6", "*:first:mt-0 *:last:mb-0", "[&_a]:text-primary [&_a]:underline [&_a]:underline-offset-2", "[&_blockquote]:my-3 [&_blockquote]:border-l-2 [&_blockquote]:border-border [&_blockquote]:pl-3 [&_blockquote]:text-muted-foreground", "[&_h1]:mb-2 [&_h1]:mt-4 [&_h1]:text-base [&_h1]:font-semibold", "[&_h2]:mb-2 [&_h2]:mt-4 [&_h2]:text-sm [&_h2]:font-semibold", "[&_h3]:mb-1.5 [&_h3]:mt-3 [&_h3]:text-sm [&_h3]:font-semibold", "[&_li]:my-1 [&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-5 [&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-5", "[&_p]:my-2", "**:data-[streamdown=code-block]:my-3 **:data-[streamdown=code-block]:gap-0 **:data-[streamdown=code-block]:overflow-hidden **:data-[streamdown=code-block]:rounded-lg **:data-[streamdown=code-block]:bg-muted/40 **:data-[streamdown=code-block]:p-0", "**:data-[streamdown=code-block-header]:px-2", "**:data-[streamdown=code-block-body]:rounded-none **:data-[streamdown=code-block-body]:border-0 **:data-[streamdown=code-block-body]:border-t **:data-[streamdown=code-block-body]:bg-background **:data-[streamdown=code-block-body]:p-3", "[&_strong]:font-semibold", "[&_table]:my-3 [&_table]:w-full [&_table]:border-collapse [&_td]:border [&_td]:border-border [&_td]:px-2 [&_td]:py-1 [&_th]:border [&_th]:border-border [&_th]:px-2 [&_th]:py-1 [&_th]:text-left [&_th]:font-semibold", className),
|
|
1512
|
+
className: cn("leading-6", "*:first:mt-0 *:last:mb-0", "[&_a]:text-primary [&_a]:underline [&_a]:underline-offset-2", "[&_blockquote]:my-3 [&_blockquote]:border-l-2 [&_blockquote]:border-border [&_blockquote]:pl-3 [&_blockquote]:text-muted-foreground", "[&_h1]:mb-2 [&_h1]:mt-4 [&_h1]:text-base [&_h1]:font-semibold", "[&_h2]:mb-2 [&_h2]:mt-4 [&_h2]:text-sm [&_h2]:font-semibold", "[&_h3]:mb-1.5 [&_h3]:mt-3 [&_h3]:text-sm [&_h3]:font-semibold", "[&_li]:my-1 [&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-5 [&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-5", "[&_p]:my-2", "**:data-[streamdown=inline-code]:text-[length:inherit] **:data-[streamdown=inline-code]:leading-[inherit]", "**:data-[streamdown=code-block]:my-3 **:data-[streamdown=code-block]:gap-0 **:data-[streamdown=code-block]:overflow-hidden **:data-[streamdown=code-block]:rounded-lg **:data-[streamdown=code-block]:bg-muted/40 **:data-[streamdown=code-block]:p-0", "**:data-[streamdown=code-block-header]:px-2", "**:data-[streamdown=code-block-body]:rounded-none **:data-[streamdown=code-block-body]:border-0 **:data-[streamdown=code-block-body]:border-t **:data-[streamdown=code-block-body]:bg-background **:data-[streamdown=code-block-body]:p-3", "[&_strong]:font-semibold", "[&_table]:my-3 [&_table]:w-full [&_table]:border-collapse [&_td]:border [&_td]:border-border [&_td]:px-2 [&_td]:py-1 [&_th]:border [&_th]:border-border [&_th]:px-2 [&_th]:py-1 [&_th]:text-left [&_th]:font-semibold", className),
|
|
1357
1513
|
controls,
|
|
1358
1514
|
plugins: responsePlugins,
|
|
1359
1515
|
...props,
|
|
@@ -1415,6 +1571,332 @@ const getSurveyAssistantInitialThreadLoadState = ({ error, hasSelectedThread, lo
|
|
|
1415
1571
|
return null;
|
|
1416
1572
|
};
|
|
1417
1573
|
//#endregion
|
|
1574
|
+
//#region src/ui/assistant-error-presentation.ts
|
|
1575
|
+
const getAssistantErrorPresentation = ({ authorizationError, error, t }) => {
|
|
1576
|
+
const parsed = parseSurveyAssistantError(authorizationError ? {
|
|
1577
|
+
code: "request_failed",
|
|
1578
|
+
detail: authorizationError,
|
|
1579
|
+
retryable: false
|
|
1580
|
+
} : error);
|
|
1581
|
+
return {
|
|
1582
|
+
title: t(`errors.${parsed.code}.title`),
|
|
1583
|
+
description: parsed.detail ?? t("errors.fallbackDetail"),
|
|
1584
|
+
hint: t(`errors.${parsed.code}.hint`),
|
|
1585
|
+
providerMessage: parsed.providerMessage,
|
|
1586
|
+
providerRequestId: parsed.providerRequestId,
|
|
1587
|
+
retryable: isSurveyAssistantErrorRetryable(parsed),
|
|
1588
|
+
tone: parsed.code === "model_unavailable" || parsed.code === "rate_limited" ? "warning" : "error",
|
|
1589
|
+
upstreamStatus: parsed.upstreamStatus
|
|
1590
|
+
};
|
|
1591
|
+
};
|
|
1592
|
+
//#endregion
|
|
1593
|
+
//#region src/ui/internal/checkbox.tsx
|
|
1594
|
+
const Checkbox$1 = ({ className, ...props }) => /* @__PURE__ */ jsx(Checkbox.Root, {
|
|
1595
|
+
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 disabled:cursor-not-allowed disabled:opacity-50 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground", className),
|
|
1596
|
+
...props,
|
|
1597
|
+
children: /* @__PURE__ */ jsx(Checkbox.Indicator, {
|
|
1598
|
+
className: "grid place-content-center text-current",
|
|
1599
|
+
children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-3.5" })
|
|
1600
|
+
})
|
|
1601
|
+
});
|
|
1602
|
+
//#endregion
|
|
1603
|
+
//#region src/ui/internal/dialog.tsx
|
|
1604
|
+
const Dialog$1 = Dialog.Root;
|
|
1605
|
+
const DialogTitle = Dialog.Title;
|
|
1606
|
+
const DialogDescription = Dialog.Description;
|
|
1607
|
+
const DialogContent = ({ children, className, closeLabel, ...props }) => /* @__PURE__ */ jsx(Dialog.Portal, { children: /* @__PURE__ */ jsxs("div", {
|
|
1608
|
+
className: "case-survey-assistant case-survey-assistant-portal",
|
|
1609
|
+
children: [/* @__PURE__ */ jsx(Dialog.Overlay, { className: "fixed inset-0 z-50 bg-black/20 backdrop-blur-[1px] data-[state=closed]:animate-out data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0" }), /* @__PURE__ */ jsxs(Dialog.Content, {
|
|
1610
|
+
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 data-[state=closed]:animate-out data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", className),
|
|
1611
|
+
...props,
|
|
1612
|
+
children: [children, /* @__PURE__ */ jsx(Dialog.Close, {
|
|
1613
|
+
"aria-label": closeLabel,
|
|
1614
|
+
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",
|
|
1615
|
+
type: "button",
|
|
1616
|
+
children: /* @__PURE__ */ jsx(XIcon, { className: "size-4" })
|
|
1617
|
+
})]
|
|
1618
|
+
})]
|
|
1619
|
+
}) });
|
|
1620
|
+
//#endregion
|
|
1621
|
+
//#region src/ui/support-bundle-dialog.tsx
|
|
1622
|
+
const CATEGORIES = [
|
|
1623
|
+
"conversation",
|
|
1624
|
+
"survey",
|
|
1625
|
+
"attachments"
|
|
1626
|
+
];
|
|
1627
|
+
const formatBytes = (bytes) => {
|
|
1628
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
1629
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;
|
|
1630
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;
|
|
1631
|
+
};
|
|
1632
|
+
const SurveyAssistantSupportBundleDialog = ({ config, error, fallbackFocusReturnRef, focusReturnRef, loading, onOpenChange, open, prepared }) => {
|
|
1633
|
+
const t = useSurveyAssistantTranslation();
|
|
1634
|
+
const [selection, setSelection] = useState({ ...SURVEY_ASSISTANT_DEFAULT_SUPPORT_BUNDLE_SELECTION });
|
|
1635
|
+
const [generated, setGenerated] = useState();
|
|
1636
|
+
const [generationError, setGenerationError] = useState();
|
|
1637
|
+
const [generating, setGenerating] = useState(false);
|
|
1638
|
+
const [supportDetailsCopied, setSupportDetailsCopied] = useState(false);
|
|
1639
|
+
const [supportDetailsCopyError, setSupportDetailsCopyError] = useState();
|
|
1640
|
+
const generationSequenceRef = useRef(0);
|
|
1641
|
+
const supportDetailsRef = useRef(null);
|
|
1642
|
+
useEffect(() => {
|
|
1643
|
+
generationSequenceRef.current += 1;
|
|
1644
|
+
if (open) setSelection({ ...SURVEY_ASSISTANT_DEFAULT_SUPPORT_BUNDLE_SELECTION });
|
|
1645
|
+
setGenerated(void 0);
|
|
1646
|
+
setGenerationError(void 0);
|
|
1647
|
+
setGenerating(false);
|
|
1648
|
+
setSupportDetailsCopied(false);
|
|
1649
|
+
setSupportDetailsCopyError(void 0);
|
|
1650
|
+
}, [open, prepared?.threadId]);
|
|
1651
|
+
const selectedBytes = useMemo(() => prepared ? estimateSurveyAssistantSupportBundleBytes(prepared, selection, config) : 0, [
|
|
1652
|
+
config,
|
|
1653
|
+
prepared,
|
|
1654
|
+
selection
|
|
1655
|
+
]);
|
|
1656
|
+
const blocked = Boolean(prepared && selectedBytes > prepared.limits.bundleBytes);
|
|
1657
|
+
const warning = Boolean(prepared && selectedBytes > prepared.limits.emailWarningBytes);
|
|
1658
|
+
const generate = async () => {
|
|
1659
|
+
if (!prepared || blocked) return;
|
|
1660
|
+
const generationSequence = generationSequenceRef.current + 1;
|
|
1661
|
+
generationSequenceRef.current = generationSequence;
|
|
1662
|
+
setGenerating(true);
|
|
1663
|
+
setSupportDetailsCopied(false);
|
|
1664
|
+
setSupportDetailsCopyError(void 0);
|
|
1665
|
+
try {
|
|
1666
|
+
const bundle = await generateSurveyAssistantSupportBundle(prepared, selection, config);
|
|
1667
|
+
if (generationSequenceRef.current !== generationSequence) return;
|
|
1668
|
+
downloadSurveyAssistantSupportBundle(bundle);
|
|
1669
|
+
setGenerated(bundle);
|
|
1670
|
+
setGenerationError(void 0);
|
|
1671
|
+
setSupportDetailsCopied(false);
|
|
1672
|
+
setSupportDetailsCopyError(void 0);
|
|
1673
|
+
} catch {
|
|
1674
|
+
if (generationSequenceRef.current === generationSequence) setGenerationError(t("supportBundle.generationFailed"));
|
|
1675
|
+
} finally {
|
|
1676
|
+
if (generationSequenceRef.current === generationSequence) setGenerating(false);
|
|
1677
|
+
}
|
|
1678
|
+
};
|
|
1679
|
+
const updateSelection = (category, checked) => {
|
|
1680
|
+
generationSequenceRef.current += 1;
|
|
1681
|
+
setSelection((current) => ({
|
|
1682
|
+
...current,
|
|
1683
|
+
[category]: checked
|
|
1684
|
+
}));
|
|
1685
|
+
setGenerated(void 0);
|
|
1686
|
+
setGenerationError(void 0);
|
|
1687
|
+
setGenerating(false);
|
|
1688
|
+
setSupportDetailsCopied(false);
|
|
1689
|
+
setSupportDetailsCopyError(void 0);
|
|
1690
|
+
};
|
|
1691
|
+
const mailto = generated && prepared && config ? createSurveyAssistantSupportMailto({
|
|
1692
|
+
bundle: generated,
|
|
1693
|
+
config,
|
|
1694
|
+
prepared
|
|
1695
|
+
}) : void 0;
|
|
1696
|
+
const supportDetails = generated && prepared ? createSurveyAssistantSupportDetails({
|
|
1697
|
+
bundle: generated,
|
|
1698
|
+
prepared
|
|
1699
|
+
}) : "";
|
|
1700
|
+
const copySupportDetails = async () => {
|
|
1701
|
+
if (!supportDetails) return;
|
|
1702
|
+
const copySequence = generationSequenceRef.current + 1;
|
|
1703
|
+
generationSequenceRef.current = copySequence;
|
|
1704
|
+
setSupportDetailsCopied(false);
|
|
1705
|
+
setSupportDetailsCopyError(void 0);
|
|
1706
|
+
try {
|
|
1707
|
+
if (navigator.clipboard?.writeText) await navigator.clipboard.writeText(supportDetails);
|
|
1708
|
+
else {
|
|
1709
|
+
if (!supportDetailsRef.current) throw new Error("Support details are not available.");
|
|
1710
|
+
supportDetailsRef.current.select();
|
|
1711
|
+
if (!document.execCommand("copy")) throw new Error("Copy was not available.");
|
|
1712
|
+
}
|
|
1713
|
+
if (generationSequenceRef.current !== copySequence) return;
|
|
1714
|
+
setSupportDetailsCopied(true);
|
|
1715
|
+
setSupportDetailsCopyError(void 0);
|
|
1716
|
+
} catch {
|
|
1717
|
+
if (generationSequenceRef.current !== copySequence) return;
|
|
1718
|
+
setSupportDetailsCopied(false);
|
|
1719
|
+
setSupportDetailsCopyError(t("supportBundle.copyDetailsFailed"));
|
|
1720
|
+
}
|
|
1721
|
+
};
|
|
1722
|
+
return /* @__PURE__ */ jsx(Dialog$1, {
|
|
1723
|
+
onOpenChange,
|
|
1724
|
+
open,
|
|
1725
|
+
children: /* @__PURE__ */ jsxs(DialogContent, {
|
|
1726
|
+
"aria-describedby": "survey-assistant-support-bundle-description",
|
|
1727
|
+
closeLabel: t("supportBundle.close"),
|
|
1728
|
+
onCloseAutoFocus: (event) => {
|
|
1729
|
+
const target = focusReturnRef?.current?.isConnected ? focusReturnRef.current : fallbackFocusReturnRef?.current?.isConnected ? fallbackFocusReturnRef.current : null;
|
|
1730
|
+
if (!target) return;
|
|
1731
|
+
event.preventDefault();
|
|
1732
|
+
target.focus();
|
|
1733
|
+
},
|
|
1734
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1735
|
+
className: "pr-8",
|
|
1736
|
+
children: [/* @__PURE__ */ jsx(DialogTitle, {
|
|
1737
|
+
className: "font-semibold text-base",
|
|
1738
|
+
children: t("supportBundle.title")
|
|
1739
|
+
}), /* @__PURE__ */ jsx(DialogDescription, {
|
|
1740
|
+
className: "mt-1 text-muted-foreground text-sm",
|
|
1741
|
+
id: "survey-assistant-support-bundle-description",
|
|
1742
|
+
children: t("supportBundle.description")
|
|
1743
|
+
})]
|
|
1744
|
+
}), loading ? /* @__PURE__ */ jsxs("div", {
|
|
1745
|
+
"aria-live": "polite",
|
|
1746
|
+
className: "flex min-h-28 items-center justify-center text-muted-foreground text-sm",
|
|
1747
|
+
role: "status",
|
|
1748
|
+
children: [/* @__PURE__ */ jsx(LoaderCircleIcon, { className: "mr-2 size-4 animate-spin" }), t("supportBundle.preparing")]
|
|
1749
|
+
}) : error ? /* @__PURE__ */ jsxs("div", {
|
|
1750
|
+
className: "rounded-md border border-destructive/20 bg-destructive/5 p-3 text-sm",
|
|
1751
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1752
|
+
className: "font-medium",
|
|
1753
|
+
children: t("supportBundle.preparationFailed")
|
|
1754
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1755
|
+
className: "mt-1 text-muted-foreground",
|
|
1756
|
+
children: error
|
|
1757
|
+
})]
|
|
1758
|
+
}) : prepared ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1759
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1760
|
+
className: "rounded-md border border-border bg-muted/30 p-3 text-xs",
|
|
1761
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1762
|
+
className: "font-medium",
|
|
1763
|
+
children: t("supportBundle.core.title")
|
|
1764
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1765
|
+
className: "mt-1 text-muted-foreground",
|
|
1766
|
+
children: t("supportBundle.core.description")
|
|
1767
|
+
})]
|
|
1768
|
+
}),
|
|
1769
|
+
/* @__PURE__ */ jsxs("fieldset", {
|
|
1770
|
+
className: "grid gap-2",
|
|
1771
|
+
"aria-describedby": "support-bundle-sensitive-note",
|
|
1772
|
+
children: [/* @__PURE__ */ jsx("legend", {
|
|
1773
|
+
className: "mb-1 font-medium text-sm",
|
|
1774
|
+
children: t("supportBundle.chooseData")
|
|
1775
|
+
}), CATEGORIES.map((category) => {
|
|
1776
|
+
const id = `support-bundle-${category}`;
|
|
1777
|
+
return /* @__PURE__ */ jsxs("label", {
|
|
1778
|
+
className: "flex cursor-pointer items-start gap-3 rounded-md border border-border p-3 hover:bg-muted/30",
|
|
1779
|
+
htmlFor: id,
|
|
1780
|
+
children: [/* @__PURE__ */ jsx(Checkbox$1, {
|
|
1781
|
+
checked: selection[category],
|
|
1782
|
+
id,
|
|
1783
|
+
onCheckedChange: (checked) => updateSelection(category, checked === true)
|
|
1784
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
1785
|
+
className: "min-w-0 flex-1",
|
|
1786
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
1787
|
+
className: "flex items-center justify-between gap-2 font-medium text-sm",
|
|
1788
|
+
children: [/* @__PURE__ */ jsx("span", { children: t(`supportBundle.categories.${category}.title`) }), /* @__PURE__ */ jsx("span", {
|
|
1789
|
+
className: "shrink-0 text-muted-foreground text-xs",
|
|
1790
|
+
children: formatBytes(prepared.categoryBytes[category])
|
|
1791
|
+
})]
|
|
1792
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1793
|
+
className: "mt-0.5 block text-muted-foreground text-xs",
|
|
1794
|
+
children: t(`supportBundle.categories.${category}.description`)
|
|
1795
|
+
})]
|
|
1796
|
+
})]
|
|
1797
|
+
}, category);
|
|
1798
|
+
})]
|
|
1799
|
+
}),
|
|
1800
|
+
/* @__PURE__ */ jsx("p", {
|
|
1801
|
+
className: "text-muted-foreground text-xs",
|
|
1802
|
+
id: "support-bundle-sensitive-note",
|
|
1803
|
+
children: t("supportBundle.sensitiveNote")
|
|
1804
|
+
}),
|
|
1805
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1806
|
+
"aria-live": "polite",
|
|
1807
|
+
className: "rounded-md bg-muted/40 px-3 py-2 text-xs",
|
|
1808
|
+
role: "status",
|
|
1809
|
+
children: [
|
|
1810
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1811
|
+
className: "flex justify-between gap-3",
|
|
1812
|
+
children: [/* @__PURE__ */ jsx("span", { children: t("supportBundle.estimatedSize") }), /* @__PURE__ */ jsx("span", {
|
|
1813
|
+
className: "font-medium",
|
|
1814
|
+
children: formatBytes(selectedBytes)
|
|
1815
|
+
})]
|
|
1816
|
+
}),
|
|
1817
|
+
warning && !blocked && /* @__PURE__ */ jsx("div", {
|
|
1818
|
+
className: "mt-1 text-amber-700",
|
|
1819
|
+
children: t("supportBundle.emailWarning")
|
|
1820
|
+
}),
|
|
1821
|
+
blocked && /* @__PURE__ */ jsx("div", {
|
|
1822
|
+
className: "mt-1 text-destructive",
|
|
1823
|
+
children: t("supportBundle.tooLarge")
|
|
1824
|
+
}),
|
|
1825
|
+
prepared.unavailable.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
1826
|
+
className: "mt-1 text-muted-foreground",
|
|
1827
|
+
children: t(prepared.unavailable.length === 1 ? "supportBundle.unavailable" : "supportBundle.unavailablePlural", { count: prepared.unavailable.length })
|
|
1828
|
+
}),
|
|
1829
|
+
(generationError ?? error) && /* @__PURE__ */ jsx("div", {
|
|
1830
|
+
className: "mt-1 text-destructive",
|
|
1831
|
+
children: generationError ?? error
|
|
1832
|
+
})
|
|
1833
|
+
]
|
|
1834
|
+
}),
|
|
1835
|
+
generated ? /* @__PURE__ */ jsxs(Fragment, { children: [!mailto && /* @__PURE__ */ jsxs("div", {
|
|
1836
|
+
className: "grid gap-2 rounded-md border border-border p-3",
|
|
1837
|
+
children: [
|
|
1838
|
+
/* @__PURE__ */ jsx("label", {
|
|
1839
|
+
className: "font-medium text-xs",
|
|
1840
|
+
htmlFor: "support-bundle-details",
|
|
1841
|
+
children: t("supportBundle.supportDetails")
|
|
1842
|
+
}),
|
|
1843
|
+
/* @__PURE__ */ jsx("textarea", {
|
|
1844
|
+
className: "min-h-24 resize-y rounded-md border border-input bg-background p-2 font-mono text-xs",
|
|
1845
|
+
id: "support-bundle-details",
|
|
1846
|
+
readOnly: true,
|
|
1847
|
+
ref: supportDetailsRef,
|
|
1848
|
+
value: supportDetails
|
|
1849
|
+
}),
|
|
1850
|
+
/* @__PURE__ */ jsx("div", {
|
|
1851
|
+
className: "flex justify-end",
|
|
1852
|
+
children: /* @__PURE__ */ jsxs(Button, {
|
|
1853
|
+
disabled: generating,
|
|
1854
|
+
onClick: () => void copySupportDetails(),
|
|
1855
|
+
type: "button",
|
|
1856
|
+
variant: "secondary",
|
|
1857
|
+
children: [supportDetailsCopied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {}), t(supportDetailsCopied ? "supportBundle.detailsCopied" : "supportBundle.copyDetails")]
|
|
1858
|
+
})
|
|
1859
|
+
}),
|
|
1860
|
+
supportDetailsCopyError && /* @__PURE__ */ jsx("div", {
|
|
1861
|
+
"aria-live": "polite",
|
|
1862
|
+
className: "text-destructive text-xs",
|
|
1863
|
+
role: "status",
|
|
1864
|
+
children: supportDetailsCopyError
|
|
1865
|
+
})
|
|
1866
|
+
]
|
|
1867
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1868
|
+
className: "flex flex-wrap justify-end gap-2",
|
|
1869
|
+
children: [mailto && /* @__PURE__ */ jsx(Button, {
|
|
1870
|
+
asChild: true,
|
|
1871
|
+
variant: "secondary",
|
|
1872
|
+
children: /* @__PURE__ */ jsxs("a", {
|
|
1873
|
+
href: mailto,
|
|
1874
|
+
children: [/* @__PURE__ */ jsx(MailIcon, {}), t("supportBundle.openEmail")]
|
|
1875
|
+
})
|
|
1876
|
+
}), /* @__PURE__ */ jsxs(Button, {
|
|
1877
|
+
disabled: generating,
|
|
1878
|
+
onClick: () => void generate(),
|
|
1879
|
+
type: "button",
|
|
1880
|
+
children: [generating ? /* @__PURE__ */ jsx(LoaderCircleIcon, { className: "animate-spin" }) : /* @__PURE__ */ jsx(DownloadIcon, {}), t("supportBundle.downloadAgain")]
|
|
1881
|
+
})]
|
|
1882
|
+
})] }) : /* @__PURE__ */ jsx("div", {
|
|
1883
|
+
className: "flex justify-end",
|
|
1884
|
+
children: /* @__PURE__ */ jsxs(Button, {
|
|
1885
|
+
disabled: blocked || generating,
|
|
1886
|
+
onClick: () => void generate(),
|
|
1887
|
+
type: "button",
|
|
1888
|
+
children: [generating ? /* @__PURE__ */ jsx(LoaderCircleIcon, { className: "animate-spin" }) : /* @__PURE__ */ jsx(DownloadIcon, {}), t("supportBundle.download")]
|
|
1889
|
+
})
|
|
1890
|
+
}),
|
|
1891
|
+
/* @__PURE__ */ jsx("p", {
|
|
1892
|
+
className: "text-muted-foreground text-xs",
|
|
1893
|
+
children: generated ? t("supportBundle.downloaded", { filename: generated.filename }) : t("supportBundle.localOnly")
|
|
1894
|
+
})
|
|
1895
|
+
] }) : null]
|
|
1896
|
+
})
|
|
1897
|
+
});
|
|
1898
|
+
};
|
|
1899
|
+
//#endregion
|
|
1418
1900
|
//#region src/ui/survey-assistant-panel.tsx
|
|
1419
1901
|
const isRootSurveyItem = (item) => typeof item.config === "object" && item.config !== null && item.config.isRoot === true;
|
|
1420
1902
|
const getAssistantEmptyStateContext = (controller) => {
|
|
@@ -1493,16 +1975,6 @@ const localizedToolNames = new Set([
|
|
|
1493
1975
|
const getToolDisplayName = (t, toolName, phase = "complete") => localizedToolNames.has(toolName) ? t(`activity.tools.${toolName}.${phase}`) : t(phase === "active" ? "activity.genericActive" : "activity.genericComplete");
|
|
1494
1976
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1495
1977
|
const unwrapOutput = unwrapSurveyAssistantToolOutput;
|
|
1496
|
-
const getAssistantErrorPresentation = (error, t) => {
|
|
1497
|
-
const parsed = parseSurveyAssistantError(error);
|
|
1498
|
-
return {
|
|
1499
|
-
title: t(`errors.${parsed.code}.title`),
|
|
1500
|
-
description: parsed.detail ?? t("errors.fallbackDetail"),
|
|
1501
|
-
hint: t(`errors.${parsed.code}.hint`),
|
|
1502
|
-
retryable: parsed.retryable ?? (parsed.code === "rate_limited" || parsed.code === "request_failed"),
|
|
1503
|
-
tone: parsed.code === "model_unavailable" || parsed.code === "rate_limited" ? "warning" : "error"
|
|
1504
|
-
};
|
|
1505
|
-
};
|
|
1506
1978
|
const getChangeSet = parseSurveyChangeSet;
|
|
1507
1979
|
const isChangeSet = (output) => {
|
|
1508
1980
|
return getChangeSet(output) !== null;
|
|
@@ -1909,7 +2381,7 @@ const SurveyAssistantHeaderIdentity = ({ indicatorClassName, status, title }) =>
|
|
|
1909
2381
|
})]
|
|
1910
2382
|
})]
|
|
1911
2383
|
});
|
|
1912
|
-
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 }) => {
|
|
2384
|
+
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 }) => {
|
|
1913
2385
|
const t = useSurveyAssistantTranslation();
|
|
1914
2386
|
const emptyStateContext = getAssistantEmptyStateContext(controller);
|
|
1915
2387
|
const assistantQuickPrompts = getAssistantQuickPrompts(t, emptyStateContext);
|
|
@@ -1917,6 +2389,7 @@ const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = fal
|
|
|
1917
2389
|
api,
|
|
1918
2390
|
applyPolicy,
|
|
1919
2391
|
controller,
|
|
2392
|
+
diagnosticStore,
|
|
1920
2393
|
initialMessages,
|
|
1921
2394
|
modelId,
|
|
1922
2395
|
onApplyReceipts,
|
|
@@ -1929,16 +2402,22 @@ const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = fal
|
|
|
1929
2402
|
});
|
|
1930
2403
|
const hasSubmittedMessageRef = useRef((initialMessages?.length ?? 0) > 0);
|
|
1931
2404
|
const showAssistantError = Boolean(authorizationError) || Boolean(error);
|
|
1932
|
-
const assistantErrorPresentation = getAssistantErrorPresentation(
|
|
2405
|
+
const assistantErrorPresentation = getAssistantErrorPresentation({
|
|
2406
|
+
authorizationError,
|
|
2407
|
+
error,
|
|
2408
|
+
t
|
|
2409
|
+
});
|
|
1933
2410
|
const lastMessage = messages.at(-1);
|
|
1934
2411
|
const isAssistantTurnActive = isSurveyAssistantTurnActive({
|
|
1935
2412
|
isStreaming,
|
|
1936
2413
|
state
|
|
1937
2414
|
});
|
|
1938
2415
|
const promptTextareaRef = useRef(null);
|
|
2416
|
+
const exportDetailsButtonRef = useRef(null);
|
|
1939
2417
|
const shouldRestorePromptFocusRef = useRef(false);
|
|
1940
2418
|
const turnWasActiveRef = useRef(false);
|
|
1941
2419
|
const [loadingEarlierMessages, setLoadingEarlierMessages] = useState(false);
|
|
2420
|
+
const [providerMessageExpanded, setProviderMessageExpanded] = useState(false);
|
|
1942
2421
|
const loadEarlierMessages = useCallback(async () => {
|
|
1943
2422
|
if (loadingEarlierMessages) return;
|
|
1944
2423
|
setLoadingEarlierMessages(true);
|
|
@@ -2159,15 +2638,40 @@ const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = fal
|
|
|
2159
2638
|
className: "mt-0.5 wrap-break-word text-muted-foreground",
|
|
2160
2639
|
children: assistantErrorPresentation.description
|
|
2161
2640
|
}),
|
|
2641
|
+
assistantErrorPresentation.providerMessage && /* @__PURE__ */ jsxs("div", {
|
|
2642
|
+
className: "mt-1",
|
|
2643
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
2644
|
+
className: cn("wrap-break-word text-muted-foreground text-xs", !providerMessageExpanded && "line-clamp-3"),
|
|
2645
|
+
children: assistantErrorPresentation.providerMessage
|
|
2646
|
+
}), assistantErrorPresentation.providerMessage.length > 180 && /* @__PURE__ */ jsx("button", {
|
|
2647
|
+
className: "mt-0.5 font-medium text-foreground text-xs hover:underline",
|
|
2648
|
+
onClick: () => setProviderMessageExpanded((current) => !current),
|
|
2649
|
+
type: "button",
|
|
2650
|
+
children: t(providerMessageExpanded ? "errors.hideProviderDetails" : "errors.showProviderDetails")
|
|
2651
|
+
})]
|
|
2652
|
+
}),
|
|
2653
|
+
(assistantErrorPresentation.upstreamStatus || assistantErrorPresentation.providerRequestId) && /* @__PURE__ */ jsx("p", {
|
|
2654
|
+
className: "mt-1 text-[11px] text-muted-foreground/80",
|
|
2655
|
+
children: [assistantErrorPresentation.upstreamStatus ? t("errors.upstreamStatus", { status: assistantErrorPresentation.upstreamStatus }) : null, assistantErrorPresentation.providerRequestId ? t("errors.providerRequestId", { requestId: assistantErrorPresentation.providerRequestId }) : null].filter(Boolean).join(" · ")
|
|
2656
|
+
}),
|
|
2162
2657
|
/* @__PURE__ */ jsx("p", {
|
|
2163
2658
|
className: "mt-1 text-muted-foreground/80",
|
|
2164
2659
|
children: assistantErrorPresentation.hint
|
|
2165
2660
|
}),
|
|
2166
|
-
assistantErrorPresentation.retryable && /* @__PURE__ */
|
|
2167
|
-
className: "mt-1.5
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2661
|
+
(assistantErrorPresentation.retryable || onExportDetails) && /* @__PURE__ */ jsxs("div", {
|
|
2662
|
+
className: "mt-1.5 flex flex-wrap gap-x-3 gap-y-1",
|
|
2663
|
+
children: [assistantErrorPresentation.retryable && /* @__PURE__ */ jsx("button", {
|
|
2664
|
+
className: "font-medium text-foreground text-xs hover:underline",
|
|
2665
|
+
onClick: retry,
|
|
2666
|
+
type: "button",
|
|
2667
|
+
children: t("errors.retry")
|
|
2668
|
+
}), onExportDetails && /* @__PURE__ */ jsx("button", {
|
|
2669
|
+
className: "font-medium text-foreground text-xs hover:underline",
|
|
2670
|
+
onClick: () => onExportDetails(exportDetailsButtonRef.current),
|
|
2671
|
+
ref: exportDetailsButtonRef,
|
|
2672
|
+
type: "button",
|
|
2673
|
+
children: t("errors.exportDetails")
|
|
2674
|
+
})]
|
|
2171
2675
|
})
|
|
2172
2676
|
]
|
|
2173
2677
|
})]
|
|
@@ -2222,8 +2726,9 @@ const listThreadPage = async (client, cursor) => {
|
|
|
2222
2726
|
if (client.listPage) return client.listPage(cursor ? { cursor } : void 0);
|
|
2223
2727
|
return cursor ? { threads: [] } : { threads: await client.list() };
|
|
2224
2728
|
};
|
|
2225
|
-
const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], onConfirmDeleteThread, onModelChange = () => {}, onTurnActiveChange: onAssistantTurnActiveChange, resourceId, selectedThreadStorageKey, surveyId, threadApi, threadClient: providedThreadClient, threadLauncher, ...sessionProps }) => {
|
|
2729
|
+
const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], onConfirmDeleteThread, onModelChange = () => {}, onTurnActiveChange: onAssistantTurnActiveChange, resourceId, selectedThreadStorageKey, supportBundle, surveyId, threadApi, threadClient: providedThreadClient, threadLauncher, ...sessionProps }) => {
|
|
2226
2730
|
const t = useSurveyAssistantTranslation();
|
|
2731
|
+
const supportBundleEnabled = isSurveyAssistantSupportBundleEnabled(supportBundle);
|
|
2227
2732
|
const threadClient = useMemo(() => providedThreadClient ?? createSurveyAssistantThreadClient(threadApi), [providedThreadClient, threadApi]);
|
|
2228
2733
|
const storageKey = selectedThreadStorageKey === false ? null : selectedThreadStorageKey ?? `${SELECTED_THREAD_STORAGE_KEY}:${encodeURIComponent(resourceId)}${surveyId ? `:${encodeURIComponent(surveyId)}` : ""}`;
|
|
2229
2734
|
const [threads, setThreads] = useState([]);
|
|
@@ -2242,8 +2747,23 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2242
2747
|
const [assistantTurnActive, setAssistantTurnActive] = useState(false);
|
|
2243
2748
|
const [initialLaunch, setInitialLaunch] = useState();
|
|
2244
2749
|
const [promptFocusThreadId, setPromptFocusThreadId] = useState();
|
|
2750
|
+
const [diagnosticStore] = useState(() => {
|
|
2751
|
+
try {
|
|
2752
|
+
return createSurveyAssistantDiagnosticStore(supportBundle?.limits);
|
|
2753
|
+
} catch {
|
|
2754
|
+
return createSurveyAssistantDiagnosticStore();
|
|
2755
|
+
}
|
|
2756
|
+
});
|
|
2757
|
+
const [supportBundleOpen, setSupportBundleOpen] = useState(false);
|
|
2758
|
+
const [supportBundleLoading, setSupportBundleLoading] = useState(false);
|
|
2759
|
+
const [supportBundleError, setSupportBundleError] = useState();
|
|
2760
|
+
const [preparedSupportBundle, setPreparedSupportBundle] = useState();
|
|
2245
2761
|
const historyControlsRef = useRef(null);
|
|
2762
|
+
const historyButtonRef = useRef(null);
|
|
2246
2763
|
const loadingAllThreadsRef = useRef(false);
|
|
2764
|
+
const supportBundleAbortRef = useRef(null);
|
|
2765
|
+
const supportBundleFocusReturnRef = useRef(null);
|
|
2766
|
+
const supportBundleThreadIdRef = useRef(void 0);
|
|
2247
2767
|
const selectModel = useCallback((modelId) => {
|
|
2248
2768
|
if (!models.some((model) => model.id === modelId)) return;
|
|
2249
2769
|
onModelChange(modelId);
|
|
@@ -2469,10 +2989,67 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2469
2989
|
renameThread,
|
|
2470
2990
|
threads
|
|
2471
2991
|
]);
|
|
2992
|
+
const closeSupportBundle = useCallback(() => {
|
|
2993
|
+
supportBundleAbortRef.current?.abort();
|
|
2994
|
+
supportBundleAbortRef.current = null;
|
|
2995
|
+
setSupportBundleOpen(false);
|
|
2996
|
+
setSupportBundleLoading(false);
|
|
2997
|
+
setPreparedSupportBundle(void 0);
|
|
2998
|
+
}, []);
|
|
2999
|
+
const openSupportBundle = useCallback(async (focusReturnElement) => {
|
|
3000
|
+
if (!supportBundleEnabled || !selectedThread || assistantTurnActive) return;
|
|
3001
|
+
supportBundleFocusReturnRef.current = focusReturnElement ?? historyButtonRef.current;
|
|
3002
|
+
await commitEditingThread();
|
|
3003
|
+
setHistoryOpen(false);
|
|
3004
|
+
supportBundleAbortRef.current?.abort();
|
|
3005
|
+
const abortController = new AbortController();
|
|
3006
|
+
supportBundleAbortRef.current = abortController;
|
|
3007
|
+
setSupportBundleOpen(true);
|
|
3008
|
+
supportBundleThreadIdRef.current = selectedThread.id;
|
|
3009
|
+
setSupportBundleLoading(true);
|
|
3010
|
+
setSupportBundleError(void 0);
|
|
3011
|
+
setPreparedSupportBundle(void 0);
|
|
3012
|
+
try {
|
|
3013
|
+
const prepared = await prepareSurveyAssistantSupportBundle({
|
|
3014
|
+
config: supportBundle,
|
|
3015
|
+
controller: sessionProps.controller,
|
|
3016
|
+
diagnosticStore,
|
|
3017
|
+
resourceId,
|
|
3018
|
+
signal: abortController.signal,
|
|
3019
|
+
threadClient,
|
|
3020
|
+
threadId: selectedThread.id
|
|
3021
|
+
});
|
|
3022
|
+
if (abortController.signal.aborted || selectedThread.id !== prepared.threadId) return;
|
|
3023
|
+
setPreparedSupportBundle(prepared);
|
|
3024
|
+
} catch (error) {
|
|
3025
|
+
if (abortController.signal.aborted) return;
|
|
3026
|
+
setSupportBundleError(parseSurveyAssistantError(error).detail ?? t("supportBundle.preparationFailed"));
|
|
3027
|
+
} finally {
|
|
3028
|
+
if (supportBundleAbortRef.current === abortController) {
|
|
3029
|
+
supportBundleAbortRef.current = null;
|
|
3030
|
+
setSupportBundleLoading(false);
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
}, [
|
|
3034
|
+
assistantTurnActive,
|
|
3035
|
+
commitEditingThread,
|
|
3036
|
+
diagnosticStore,
|
|
3037
|
+
resourceId,
|
|
3038
|
+
selectedThread,
|
|
3039
|
+
sessionProps.controller,
|
|
3040
|
+
supportBundle,
|
|
3041
|
+
supportBundleEnabled,
|
|
3042
|
+
t,
|
|
3043
|
+
threadClient
|
|
3044
|
+
]);
|
|
3045
|
+
useEffect(() => () => {
|
|
3046
|
+
supportBundleAbortRef.current?.abort();
|
|
3047
|
+
}, []);
|
|
2472
3048
|
const deleteThread = useCallback(async (thread) => {
|
|
2473
3049
|
if (!(onConfirmDeleteThread ? await onConfirmDeleteThread(thread) : window.confirm(t("threads.deleteConfirm", { title: thread.title })))) return;
|
|
2474
3050
|
try {
|
|
2475
3051
|
await threadClient.delete(thread.id);
|
|
3052
|
+
diagnosticStore.deleteThread(thread.id);
|
|
2476
3053
|
const remaining = threads.filter((item) => item.id !== thread.id);
|
|
2477
3054
|
setThreads(remaining);
|
|
2478
3055
|
if (selectedThread?.id === thread.id) if (remaining[0]) await selectThread(remaining[0]);
|
|
@@ -2482,6 +3059,7 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2482
3059
|
}
|
|
2483
3060
|
}, [
|
|
2484
3061
|
createThread,
|
|
3062
|
+
diagnosticStore,
|
|
2485
3063
|
onConfirmDeleteThread,
|
|
2486
3064
|
selectThread,
|
|
2487
3065
|
selectedThread,
|
|
@@ -2568,6 +3146,14 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2568
3146
|
promptFocusThreadId,
|
|
2569
3147
|
selectedThread?.id
|
|
2570
3148
|
]);
|
|
3149
|
+
useEffect(() => {
|
|
3150
|
+
if (!supportBundleOpen || supportBundleThreadIdRef.current === selectedThread?.id) return;
|
|
3151
|
+
closeSupportBundle();
|
|
3152
|
+
}, [
|
|
3153
|
+
closeSupportBundle,
|
|
3154
|
+
selectedThread?.id,
|
|
3155
|
+
supportBundleOpen
|
|
3156
|
+
]);
|
|
2571
3157
|
useEffect(() => {
|
|
2572
3158
|
const handleFocus = () => {
|
|
2573
3159
|
refreshThreadList(false);
|
|
@@ -2639,6 +3225,7 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2639
3225
|
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",
|
|
2640
3226
|
disabled: assistantTurnActive,
|
|
2641
3227
|
onClick: toggleHistory,
|
|
3228
|
+
ref: historyButtonRef,
|
|
2642
3229
|
title: t("threads.history"),
|
|
2643
3230
|
type: "button",
|
|
2644
3231
|
children: /* @__PURE__ */ jsx(HistoryIcon, { className: "size-4" })
|
|
@@ -2729,6 +3316,15 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2729
3316
|
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")
|
|
2730
3317
|
})
|
|
2731
3318
|
]
|
|
3319
|
+
}),
|
|
3320
|
+
supportBundleEnabled && /* @__PURE__ */ jsx("div", {
|
|
3321
|
+
className: "border-t border-border p-1",
|
|
3322
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
3323
|
+
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",
|
|
3324
|
+
onClick: () => void openSupportBundle(historyButtonRef.current),
|
|
3325
|
+
type: "button",
|
|
3326
|
+
children: [/* @__PURE__ */ jsx(PackageOpenIcon, { className: "size-3.5" }), t("threads.exportSupportBundle")]
|
|
3327
|
+
})
|
|
2732
3328
|
})
|
|
2733
3329
|
]
|
|
2734
3330
|
})
|
|
@@ -2736,46 +3332,63 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2736
3332
|
});
|
|
2737
3333
|
return /* @__PURE__ */ jsxs("div", {
|
|
2738
3334
|
className: "relative h-full min-h-0",
|
|
2739
|
-
children: [
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
3335
|
+
children: [
|
|
3336
|
+
/* @__PURE__ */ createElement(SurveyAssistantChatPanel, {
|
|
3337
|
+
...sessionProps,
|
|
3338
|
+
embedded,
|
|
3339
|
+
focusPromptOnMount: selectedThread.id === promptFocusThreadId,
|
|
3340
|
+
hasEarlierMessages: Boolean(nextMessageCursor),
|
|
3341
|
+
initialLaunch: initialLaunch?.input,
|
|
3342
|
+
initialMessages,
|
|
3343
|
+
key: selectedThread.id,
|
|
3344
|
+
modelId,
|
|
3345
|
+
models,
|
|
3346
|
+
diagnosticStore,
|
|
3347
|
+
onExportDetails: supportBundleEnabled ? (trigger) => void openSupportBundle(trigger) : void 0,
|
|
3348
|
+
onInitialLaunchHandled: handleInitialLaunchHandled,
|
|
3349
|
+
onModelChange: selectModel,
|
|
3350
|
+
onFirstSubmit: handleFirstSubmit,
|
|
3351
|
+
onLoadEarlierMessages: loadEarlierMessages,
|
|
3352
|
+
onTurnSettled: handleTurnSettled,
|
|
3353
|
+
onTurnActiveChange: handleTurnActiveChange,
|
|
3354
|
+
resourceId,
|
|
3355
|
+
surveyId,
|
|
3356
|
+
threadControls,
|
|
3357
|
+
threadId: selectedThread.id,
|
|
3358
|
+
threadTitle: selectedThread.title
|
|
3359
|
+
}),
|
|
3360
|
+
supportBundleEnabled && /* @__PURE__ */ jsx(SurveyAssistantSupportBundleDialog, {
|
|
3361
|
+
config: supportBundle,
|
|
3362
|
+
error: supportBundleError,
|
|
3363
|
+
fallbackFocusReturnRef: historyButtonRef,
|
|
3364
|
+
focusReturnRef: supportBundleFocusReturnRef,
|
|
3365
|
+
loading: supportBundleLoading,
|
|
3366
|
+
onOpenChange: (open) => {
|
|
3367
|
+
if (!open) closeSupportBundle();
|
|
3368
|
+
},
|
|
3369
|
+
open: supportBundleOpen,
|
|
3370
|
+
prepared: preparedSupportBundle
|
|
3371
|
+
}),
|
|
3372
|
+
threadError && /* @__PURE__ */ jsxs("div", {
|
|
3373
|
+
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",
|
|
3374
|
+
children: [
|
|
3375
|
+
/* @__PURE__ */ jsx("div", {
|
|
3376
|
+
className: "font-medium",
|
|
3377
|
+
children: t("panel.controlsUnavailable")
|
|
3378
|
+
}),
|
|
3379
|
+
/* @__PURE__ */ jsx("div", {
|
|
3380
|
+
className: "mt-0.5 text-muted-foreground",
|
|
3381
|
+
children: threadError
|
|
3382
|
+
}),
|
|
3383
|
+
/* @__PURE__ */ jsx("button", {
|
|
3384
|
+
className: "mt-1 font-medium hover:underline",
|
|
3385
|
+
onClick: () => setThreadError(null),
|
|
3386
|
+
type: "button",
|
|
3387
|
+
children: t("errors.dismiss")
|
|
3388
|
+
})
|
|
3389
|
+
]
|
|
3390
|
+
})
|
|
3391
|
+
]
|
|
2779
3392
|
});
|
|
2780
3393
|
};
|
|
2781
3394
|
const SurveyAssistantPanel = ({ language, localizations, ...props }) => /* @__PURE__ */ jsx("div", {
|