@arbidocs/blocks 0.5.114 → 0.5.116
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ConnectedCallDock-2KXEQENS.cjs → ConnectedCallDock-WER7R222.cjs} +21 -21
- package/dist/{ConnectedCallDock-2KXEQENS.cjs.map → ConnectedCallDock-WER7R222.cjs.map} +1 -1
- package/dist/{ConnectedCallRoom-MU3NPNXF.cjs → ConnectedCallRoom-T7OBQTYP.cjs} +14 -14
- package/dist/{ConnectedCallRoom-MU3NPNXF.cjs.map → ConnectedCallRoom-T7OBQTYP.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-VH3I65H6.cjs → ConnectedNativeDocxComparison-546ILGLW.cjs} +19 -19
- package/dist/{ConnectedNativeDocxComparison-VH3I65H6.cjs.map → ConnectedNativeDocxComparison-546ILGLW.cjs.map} +1 -1
- package/dist/{ConnectedProductionSetDialog-4EAY6KAZ.cjs → ConnectedProductionSetDialog-LHB4VQWC.cjs} +3 -3
- package/dist/{ConnectedProductionSetDialog-4EAY6KAZ.cjs.map → ConnectedProductionSetDialog-LHB4VQWC.cjs.map} +1 -1
- package/dist/{ConnectedStreamedWordArtifact-KQSHCA75.cjs → ConnectedStreamedWordArtifact-S2ZFZLZQ.cjs} +19 -19
- package/dist/{ConnectedStreamedWordArtifact-KQSHCA75.cjs.map → ConnectedStreamedWordArtifact-S2ZFZLZQ.cjs.map} +1 -1
- package/dist/{DocumentReviewCard-OCPFVMLD.cjs → DocumentReviewCard-ZSBZBGFK.cjs} +15 -15
- package/dist/{DocumentReviewCard-OCPFVMLD.cjs.map → DocumentReviewCard-ZSBZBGFK.cjs.map} +1 -1
- package/dist/{FilesViewerDialog-BAGOEMXW.cjs → FilesViewerDialog-6UKR5WEF.cjs} +44 -44
- package/dist/{FilesViewerDialog-BAGOEMXW.cjs.map → FilesViewerDialog-6UKR5WEF.cjs.map} +1 -1
- package/dist/{NativeDocxEditor-EJEIJDOC.cjs → NativeDocxEditor-2LQY2CTV.cjs} +6 -6
- package/dist/{NativeDocxEditor-EJEIJDOC.cjs.map → NativeDocxEditor-2LQY2CTV.cjs.map} +1 -1
- package/dist/{WorkspaceTableView-IMAZICIZ.cjs → WorkspaceTableView-J3C6VH4T.cjs} +8 -8
- package/dist/{WorkspaceTableView-IMAZICIZ.cjs.map → WorkspaceTableView-J3C6VH4T.cjs.map} +1 -1
- package/dist/agents/index.cjs +297 -297
- package/dist/{ai-7U4B4CVF.cjs → ai-IM4A23YT.cjs} +24 -24
- package/dist/ai-IM4A23YT.cjs.map +1 -0
- package/dist/calls/index.cjs +121 -121
- package/dist/chat/DraftingDocChip.d.ts +3 -1
- package/dist/chat/DraftingDocChip.js +7 -4
- package/dist/chat/DraftingDocChip.js.map +2 -2
- package/dist/chat/index.cjs +37 -37
- package/dist/{chunk-4ED7CNOX.cjs → chunk-2CSLFAGF.cjs} +430 -150
- package/dist/chunk-2CSLFAGF.cjs.map +1 -0
- package/dist/{chunk-Q6DQGGP4.cjs → chunk-325GVZE6.cjs} +3 -3
- package/dist/{chunk-Q6DQGGP4.cjs.map → chunk-325GVZE6.cjs.map} +1 -1
- package/dist/{chunk-LFRNBT2I.cjs → chunk-557MJ4IH.cjs} +20 -20
- package/dist/{chunk-LFRNBT2I.cjs.map → chunk-557MJ4IH.cjs.map} +1 -1
- package/dist/{chunk-JSQQV23D.cjs → chunk-6UTKM5AB.cjs} +3 -3
- package/dist/{chunk-JSQQV23D.cjs.map → chunk-6UTKM5AB.cjs.map} +1 -1
- package/dist/{chunk-H5OLHP2U.cjs → chunk-7OPOPYV6.cjs} +3 -3
- package/dist/{chunk-H5OLHP2U.cjs.map → chunk-7OPOPYV6.cjs.map} +1 -1
- package/dist/{chunk-AHT6DQNI.cjs → chunk-B2HNNG25.cjs} +50 -50
- package/dist/{chunk-AHT6DQNI.cjs.map → chunk-B2HNNG25.cjs.map} +1 -1
- package/dist/{chunk-WW6LXQY6.cjs → chunk-B3LZITVF.cjs} +12 -12
- package/dist/{chunk-WW6LXQY6.cjs.map → chunk-B3LZITVF.cjs.map} +1 -1
- package/dist/{chunk-V5IMYLYK.cjs → chunk-BQ5RIWWT.cjs} +3 -3
- package/dist/{chunk-V5IMYLYK.cjs.map → chunk-BQ5RIWWT.cjs.map} +1 -1
- package/dist/{chunk-INEPPS4H.cjs → chunk-COD5ENHK.cjs} +4 -4
- package/dist/{chunk-INEPPS4H.cjs.map → chunk-COD5ENHK.cjs.map} +1 -1
- package/dist/{chunk-MC4F2URI.cjs → chunk-CPG7II4E.cjs} +28 -28
- package/dist/{chunk-MC4F2URI.cjs.map → chunk-CPG7II4E.cjs.map} +1 -1
- package/dist/{chunk-7XT5B2DZ.cjs → chunk-CPR6EHG7.cjs} +47 -47
- package/dist/{chunk-7XT5B2DZ.cjs.map → chunk-CPR6EHG7.cjs.map} +1 -1
- package/dist/{chunk-3U36VYMD.cjs → chunk-DDIW4HLU.cjs} +27 -27
- package/dist/{chunk-3U36VYMD.cjs.map → chunk-DDIW4HLU.cjs.map} +1 -1
- package/dist/chunk-HB2O4THB.cjs +18 -0
- package/dist/{chunk-ZZA756I4.cjs.map → chunk-HB2O4THB.cjs.map} +1 -1
- package/dist/{chunk-IFOGBMAE.cjs → chunk-KLMNCBLY.cjs} +9 -6
- package/dist/chunk-KLMNCBLY.cjs.map +1 -0
- package/dist/{chunk-TDN33HSK.cjs → chunk-KTQOGT2L.cjs} +6 -6
- package/dist/{chunk-TDN33HSK.cjs.map → chunk-KTQOGT2L.cjs.map} +1 -1
- package/dist/{chunk-UUENH4BJ.cjs → chunk-KXIRVKCJ.cjs} +3 -3
- package/dist/{chunk-UUENH4BJ.cjs.map → chunk-KXIRVKCJ.cjs.map} +1 -1
- package/dist/{chunk-436I7PQL.cjs → chunk-NIE3N6OM.cjs} +9 -9
- package/dist/{chunk-436I7PQL.cjs.map → chunk-NIE3N6OM.cjs.map} +1 -1
- package/dist/{chunk-XKDUPU7B.cjs → chunk-NJCK6V6U.cjs} +4 -4
- package/dist/{chunk-XKDUPU7B.cjs.map → chunk-NJCK6V6U.cjs.map} +1 -1
- package/dist/{chunk-5QUL5BZO.cjs → chunk-NNUK5ZM7.cjs} +4 -4
- package/dist/{chunk-5QUL5BZO.cjs.map → chunk-NNUK5ZM7.cjs.map} +1 -1
- package/dist/{chunk-4NPCDS2X.cjs → chunk-NY3YUCOW.cjs} +3 -3
- package/dist/{chunk-4NPCDS2X.cjs.map → chunk-NY3YUCOW.cjs.map} +1 -1
- package/dist/{chunk-6DCIZA3X.cjs → chunk-OEREKAAP.cjs} +75 -75
- package/dist/{chunk-6DCIZA3X.cjs.map → chunk-OEREKAAP.cjs.map} +1 -1
- package/dist/{chunk-3ODEWSRO.cjs → chunk-P77YTTJ3.cjs} +4 -4
- package/dist/{chunk-3ODEWSRO.cjs.map → chunk-P77YTTJ3.cjs.map} +1 -1
- package/dist/{chunk-3R6YHJ3G.cjs → chunk-QHOHDNBU.cjs} +6 -6
- package/dist/{chunk-3R6YHJ3G.cjs.map → chunk-QHOHDNBU.cjs.map} +1 -1
- package/dist/{chunk-LYTIQQQ2.cjs → chunk-R7CJEIA5.cjs} +3 -3
- package/dist/{chunk-LYTIQQQ2.cjs.map → chunk-R7CJEIA5.cjs.map} +1 -1
- package/dist/{chunk-MGQSLMTC.cjs → chunk-SB4M3ITT.cjs} +239 -85
- package/dist/chunk-SB4M3ITT.cjs.map +1 -0
- package/dist/{chunk-2W5E62EY.cjs → chunk-SGYSDABK.cjs} +6 -6
- package/dist/{chunk-2W5E62EY.cjs.map → chunk-SGYSDABK.cjs.map} +1 -1
- package/dist/{chunk-UNDQYTRF.cjs → chunk-T23UTIRI.cjs} +6 -6
- package/dist/{chunk-UNDQYTRF.cjs.map → chunk-T23UTIRI.cjs.map} +1 -1
- package/dist/{chunk-E4BLRF2L.cjs → chunk-TDO5UWXF.cjs} +5 -5
- package/dist/{chunk-E4BLRF2L.cjs.map → chunk-TDO5UWXF.cjs.map} +1 -1
- package/dist/{chunk-4IOYQLKG.cjs → chunk-TP5PGWIO.cjs} +3 -3
- package/dist/{chunk-4IOYQLKG.cjs.map → chunk-TP5PGWIO.cjs.map} +1 -1
- package/dist/{chunk-7X3FS5HQ.cjs → chunk-TT4IF52H.cjs} +35 -35
- package/dist/{chunk-7X3FS5HQ.cjs.map → chunk-TT4IF52H.cjs.map} +1 -1
- package/dist/{chunk-NHHEMBXQ.cjs → chunk-VGCTYTEW.cjs} +22 -14
- package/dist/chunk-VGCTYTEW.cjs.map +1 -0
- package/dist/{chunk-HM5L4SBC.cjs → chunk-VKH3BEZE.cjs} +3 -3
- package/dist/{chunk-HM5L4SBC.cjs.map → chunk-VKH3BEZE.cjs.map} +1 -1
- package/dist/{chunk-GQXPNIRE.cjs → chunk-WAV762GP.cjs} +6 -6
- package/dist/{chunk-GQXPNIRE.cjs.map → chunk-WAV762GP.cjs.map} +1 -1
- package/dist/{chunk-MZ2KZXNU.cjs → chunk-WXUU3COI.cjs} +3 -3
- package/dist/{chunk-MZ2KZXNU.cjs.map → chunk-WXUU3COI.cjs.map} +1 -1
- package/dist/{chunk-BW5MF464.cjs → chunk-XKVPSOKP.cjs} +4 -4
- package/dist/{chunk-BW5MF464.cjs.map → chunk-XKVPSOKP.cjs.map} +1 -1
- package/dist/{chunk-57EE6CMW.cjs → chunk-Y24V6HPR.cjs} +15 -15
- package/dist/{chunk-57EE6CMW.cjs.map → chunk-Y24V6HPR.cjs.map} +1 -1
- package/dist/{chunk-ET3NVY27.cjs → chunk-YGBHY67W.cjs} +5 -5
- package/dist/{chunk-ET3NVY27.cjs.map → chunk-YGBHY67W.cjs.map} +1 -1
- package/dist/{chunk-7TEUGFIL.cjs → chunk-YGXOKB5Z.cjs} +4 -4
- package/dist/{chunk-7TEUGFIL.cjs.map → chunk-YGXOKB5Z.cjs.map} +1 -1
- package/dist/connect/docx.cjs +23 -23
- package/dist/connect/index.cjs +1231 -1069
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/viewer.cjs +33 -33
- package/dist/connection/conversation/ConnectedConversation.js +143 -55
- package/dist/connection/conversation/ConnectedConversation.js.map +2 -2
- package/dist/connection/conversation/ConversationSendButton.d.ts +1 -0
- package/dist/connection/conversation/ConversationSendButton.js +3 -2
- package/dist/connection/conversation/ConversationSendButton.js.map +2 -2
- package/dist/connection/conversation/DocumentTargetNotice.d.ts +7 -0
- package/dist/connection/conversation/DocumentTargetNotice.js +45 -0
- package/dist/connection/conversation/DocumentTargetNotice.js.map +7 -0
- package/dist/connection/conversation/documentSwitch.d.ts +9 -0
- package/dist/connection/conversation/documentSwitch.js +40 -0
- package/dist/connection/conversation/documentSwitch.js.map +7 -0
- package/dist/connection/docx/ConnectedNativeDocxEditor.js +10 -2
- package/dist/connection/docx/ConnectedNativeDocxEditor.js.map +2 -2
- package/dist/connection/viewer/ConnectedDocumentViewer.js +124 -21
- package/dist/connection/viewer/ConnectedDocumentViewer.js.map +2 -2
- package/dist/connection/viewer/VersionDropdown.d.ts +9 -0
- package/dist/connection/viewer/VersionDropdown.js +39 -0
- package/dist/connection/viewer/VersionDropdown.js.map +7 -0
- package/dist/connection/viewer/ViewerPdfPane.js +4 -1
- package/dist/connection/viewer/ViewerPdfPane.js.map +2 -2
- package/dist/connection/viewer/useViewerBlobs.d.ts +3 -1
- package/dist/connection/viewer/useViewerBlobs.js +14 -8
- package/dist/connection/viewer/useViewerBlobs.js.map +2 -2
- package/dist/connection/viewer/useViewerTabs.js +10 -0
- package/dist/connection/viewer/useViewerTabs.js.map +2 -2
- package/dist/dashboards/index.cjs +1 -1
- package/dist/docx/DocxCommandMenu.d.ts +8 -0
- package/dist/docx/DocxCommandMenu.js +202 -0
- package/dist/docx/DocxCommandMenu.js.map +7 -0
- package/dist/docx/NativeDocxEditor.d.ts +4 -2
- package/dist/docx/NativeDocxEditor.js +54 -13
- package/dist/docx/NativeDocxEditor.js.map +2 -2
- package/dist/docx/RibbonMenu.d.ts +3 -1
- package/dist/docx/RibbonMenu.js +10 -3
- package/dist/docx/RibbonMenu.js.map +2 -2
- package/dist/docx/RibbonOverflow.d.ts +3 -0
- package/dist/docx/RibbonOverflow.js +24 -1
- package/dist/docx/RibbonOverflow.js.map +2 -2
- package/dist/docx/index.cjs +38 -38
- package/dist/docx/signatures/SignatureFields.d.ts +5 -1
- package/dist/docx/signatures/SignatureFields.js +57 -10
- package/dist/docx/signatures/SignatureFields.js.map +2 -2
- package/dist/embed/index.cjs +38 -38
- package/dist/files/index.cjs +224 -224
- package/dist/index.cjs +1731 -1731
- package/dist/settings/index.cjs +147 -147
- package/dist/shell/index.cjs +90 -90
- package/dist/site/index.cjs +5 -5
- package/dist/studio/index.cjs +27 -27
- package/dist/styles.css +1 -1
- package/dist/workflow-canvas/index.cjs +54 -54
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +5 -5
- package/src/docx/styles.css +94 -0
- package/dist/ai-7U4B4CVF.cjs.map +0 -1
- package/dist/chunk-4ED7CNOX.cjs.map +0 -1
- package/dist/chunk-IFOGBMAE.cjs.map +0 -1
- package/dist/chunk-MGQSLMTC.cjs.map +0 -1
- package/dist/chunk-NHHEMBXQ.cjs.map +0 -1
- package/dist/chunk-ZZA756I4.cjs +0 -18
package/dist/connect/viewer.cjs
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var chunkSB4M3ITT_cjs = require('../chunk-SB4M3ITT.cjs');
|
|
5
5
|
require('../chunk-4CIVQWAX.cjs');
|
|
6
6
|
var chunkPL7HUTM3_cjs = require('../chunk-PL7HUTM3.cjs');
|
|
7
|
-
require('../chunk-
|
|
8
|
-
require('../chunk-
|
|
9
|
-
require('../chunk-
|
|
10
|
-
require('../chunk-
|
|
11
|
-
require('../chunk-
|
|
7
|
+
require('../chunk-YGXOKB5Z.cjs');
|
|
8
|
+
require('../chunk-KXIRVKCJ.cjs');
|
|
9
|
+
require('../chunk-TT4IF52H.cjs');
|
|
10
|
+
require('../chunk-NJCK6V6U.cjs');
|
|
11
|
+
require('../chunk-NNUK5ZM7.cjs');
|
|
12
12
|
require('../chunk-223D4727.cjs');
|
|
13
13
|
require('../chunk-SNUBQMIS.cjs');
|
|
14
|
-
require('../chunk-
|
|
14
|
+
require('../chunk-VGCTYTEW.cjs');
|
|
15
15
|
require('../chunk-4ONPEVTP.cjs');
|
|
16
16
|
require('../chunk-V3KLUWQQ.cjs');
|
|
17
17
|
require('../chunk-P5AQYC4D.cjs');
|
|
18
|
-
require('../chunk-
|
|
18
|
+
require('../chunk-WAV762GP.cjs');
|
|
19
19
|
require('../chunk-YYPZOEED.cjs');
|
|
20
20
|
require('../chunk-GNZAH6UI.cjs');
|
|
21
21
|
require('../chunk-JH6JTI76.cjs');
|
|
@@ -24,42 +24,31 @@ require('../chunk-DTMBAFIL.cjs');
|
|
|
24
24
|
require('../chunk-ZESMRGDV.cjs');
|
|
25
25
|
require('../chunk-VCEX7COE.cjs');
|
|
26
26
|
require('../chunk-34HQO4ZQ.cjs');
|
|
27
|
-
require('../chunk-
|
|
28
|
-
require('../chunk-WW6LXQY6.cjs');
|
|
27
|
+
require('../chunk-B3LZITVF.cjs');
|
|
29
28
|
require('../chunk-MZZ3SBQL.cjs');
|
|
30
|
-
require('../chunk-
|
|
31
|
-
require('../chunk-
|
|
29
|
+
require('../chunk-NY3YUCOW.cjs');
|
|
30
|
+
require('../chunk-325GVZE6.cjs');
|
|
32
31
|
require('../chunk-ZPPMAL5P.cjs');
|
|
33
32
|
require('../chunk-ORELHENJ.cjs');
|
|
34
33
|
require('../chunk-NWNVWO6L.cjs');
|
|
35
34
|
require('../chunk-SK6HQ46Q.cjs');
|
|
36
|
-
require('../chunk-
|
|
37
|
-
require('../chunk-
|
|
38
|
-
require('../chunk-Z2XZ2D4N.cjs');
|
|
39
|
-
require('../chunk-YZSQ7F5K.cjs');
|
|
40
|
-
require('../chunk-MCXS6X37.cjs');
|
|
41
|
-
require('../chunk-KQF7POTG.cjs');
|
|
35
|
+
require('../chunk-MNIQDXM6.cjs');
|
|
36
|
+
require('../chunk-E3Y7RI3J.cjs');
|
|
42
37
|
require('../chunk-VLCY46K6.cjs');
|
|
43
|
-
require('../chunk-
|
|
44
|
-
require('../chunk-75BNMCUX.cjs');
|
|
38
|
+
require('../chunk-VKH3BEZE.cjs');
|
|
45
39
|
require('../chunk-OEJQFPWO.cjs');
|
|
46
40
|
require('../chunk-OYXWQTHF.cjs');
|
|
47
41
|
require('../chunk-S237ORM3.cjs');
|
|
48
42
|
require('../chunk-II2OEXHW.cjs');
|
|
49
|
-
require('../chunk-
|
|
50
|
-
require('../chunk-LYTIQQQ2.cjs');
|
|
43
|
+
require('../chunk-R7CJEIA5.cjs');
|
|
51
44
|
require('../chunk-3YEXZX4H.cjs');
|
|
52
45
|
require('../chunk-4PA6VCCR.cjs');
|
|
53
|
-
require('../chunk-
|
|
46
|
+
require('../chunk-WXUU3COI.cjs');
|
|
54
47
|
require('../chunk-AHDJXIUB.cjs');
|
|
55
|
-
require('../chunk-YVCOQHCE.cjs');
|
|
56
48
|
require('../chunk-RL2HI6NP.cjs');
|
|
57
49
|
require('../chunk-6UZC4XVV.cjs');
|
|
58
|
-
require('../chunk-
|
|
59
|
-
require('../chunk-QRAQZTJE.cjs');
|
|
60
|
-
require('../chunk-UDSHVNU3.cjs');
|
|
50
|
+
require('../chunk-YVCOQHCE.cjs');
|
|
61
51
|
require('../chunk-JV5TVUOU.cjs');
|
|
62
|
-
require('../chunk-IPSHAMO2.cjs');
|
|
63
52
|
require('../chunk-E7TE2WVT.cjs');
|
|
64
53
|
require('../chunk-EG7EJFUE.cjs');
|
|
65
54
|
require('../chunk-VG24E4JJ.cjs');
|
|
@@ -71,21 +60,32 @@ require('../chunk-HQDR43JC.cjs');
|
|
|
71
60
|
require('../chunk-JR2YSBD5.cjs');
|
|
72
61
|
require('../chunk-3YZKDCWY.cjs');
|
|
73
62
|
require('../chunk-SJSGSHIT.cjs');
|
|
74
|
-
require('../chunk-PPCATBOY.cjs');
|
|
75
63
|
require('../chunk-ZW6FPIFC.cjs');
|
|
76
|
-
require('../chunk-
|
|
77
|
-
require('../chunk-
|
|
78
|
-
require('../chunk-
|
|
64
|
+
require('../chunk-CT3SLXB7.cjs');
|
|
65
|
+
require('../chunk-DEXUL3T6.cjs');
|
|
66
|
+
require('../chunk-6WMMZLEV.cjs');
|
|
67
|
+
require('../chunk-Z2XZ2D4N.cjs');
|
|
68
|
+
require('../chunk-YZSQ7F5K.cjs');
|
|
69
|
+
require('../chunk-MCXS6X37.cjs');
|
|
70
|
+
require('../chunk-KQF7POTG.cjs');
|
|
71
|
+
require('../chunk-75BNMCUX.cjs');
|
|
72
|
+
require('../chunk-FX3K6LNZ.cjs');
|
|
73
|
+
require('../chunk-QGVOT7E4.cjs');
|
|
74
|
+
require('../chunk-QRAQZTJE.cjs');
|
|
75
|
+
require('../chunk-UDSHVNU3.cjs');
|
|
76
|
+
require('../chunk-IPSHAMO2.cjs');
|
|
77
|
+
require('../chunk-PPCATBOY.cjs');
|
|
79
78
|
require('../chunk-TKHCIHE2.cjs');
|
|
80
79
|
require('../chunk-JDFBEGQO.cjs');
|
|
81
80
|
require('../chunk-ULWRNGGE.cjs');
|
|
81
|
+
require('../chunk-LJJJ6CYH.cjs');
|
|
82
82
|
require('../chunk-PLIF5CUV.cjs');
|
|
83
83
|
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
Object.defineProperty(exports, "ConnectedDocumentViewer", {
|
|
87
87
|
enumerable: true,
|
|
88
|
-
get: function () { return
|
|
88
|
+
get: function () { return chunkSB4M3ITT_cjs.ConnectedDocumentViewer; }
|
|
89
89
|
});
|
|
90
90
|
Object.defineProperty(exports, "ConnectedDocumentToolsProvider", {
|
|
91
91
|
enumerable: true,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import {
|
|
4
4
|
ArbiBotHeadIcon as ArbiBotIcon,
|
|
5
5
|
READ_ONLY_MEETING_TEXT,
|
|
@@ -61,6 +61,8 @@ import { ConnectedConversationEmpty } from "./ConnectedConversationEmpty.js";
|
|
|
61
61
|
import { ConnectedMessageArea as MessageArea } from "./ConnectedMessageArea.js";
|
|
62
62
|
import { ConversationAlert } from "./ConversationAlert.js";
|
|
63
63
|
import { ConversationComposer } from "./ConversationComposer.js";
|
|
64
|
+
import { DocumentTargetNotice } from "./DocumentTargetNotice.js";
|
|
65
|
+
import { createDocumentSwitchGuard, switchInScope } from "./documentSwitch.js";
|
|
64
66
|
import { ConversationSendButton } from "./ConversationSendButton.js";
|
|
65
67
|
import { MicButton } from "./MicButton.js";
|
|
66
68
|
import { useMeetingThreadMessages } from "./useMeetingThreadMessages.js";
|
|
@@ -330,7 +332,24 @@ function ConversationThread({
|
|
|
330
332
|
parentMessageId,
|
|
331
333
|
messageHistory
|
|
332
334
|
});
|
|
335
|
+
const scopeKey = JSON.stringify([selectedWorkspaceId, currentConversationId]);
|
|
336
|
+
const documentSwitchGuards = useRef(
|
|
337
|
+
/* @__PURE__ */ new Map()
|
|
338
|
+
);
|
|
339
|
+
if (!documentSwitchGuards.current.has(scopeKey)) {
|
|
340
|
+
documentSwitchGuards.current.set(scopeKey, createDocumentSwitchGuard());
|
|
341
|
+
}
|
|
342
|
+
const switchingDocument = documentSwitchGuards.current.get(scopeKey);
|
|
343
|
+
const [, setSwitchState] = useState({ scope: scopeKey, pending: false, failed: false });
|
|
344
|
+
const documentSwitchPending = switchingDocument.isPending();
|
|
345
|
+
const documentSwitchFailed = switchingDocument.hasFailed();
|
|
333
346
|
const handleUserSend = useCallback(() => {
|
|
347
|
+
if (switchingDocument.isPending()) return;
|
|
348
|
+
if (switchingDocument.hasFailed()) {
|
|
349
|
+
session.setAutoSendDraft(false);
|
|
350
|
+
switchingDocument.acknowledgeFailure();
|
|
351
|
+
setSwitchState({ scope: scopeKey, pending: false, failed: false });
|
|
352
|
+
}
|
|
334
353
|
const draft = selectDraft(session.getState());
|
|
335
354
|
if (!pendingAnswer && slashWorkflows.openForDraft(draft)) {
|
|
336
355
|
session.setDraft("");
|
|
@@ -339,7 +358,15 @@ function ConversationThread({
|
|
|
339
358
|
if (refuseChatWhenOffline()) return;
|
|
340
359
|
scrollToBottom();
|
|
341
360
|
handleComposerSend();
|
|
342
|
-
}, [
|
|
361
|
+
}, [
|
|
362
|
+
pendingAnswer,
|
|
363
|
+
slashWorkflows,
|
|
364
|
+
handleComposerSend,
|
|
365
|
+
scrollToBottom,
|
|
366
|
+
session,
|
|
367
|
+
switchingDocument,
|
|
368
|
+
scopeKey
|
|
369
|
+
]);
|
|
343
370
|
useEffect(() => {
|
|
344
371
|
if (editingMessageId && inputRef.current) {
|
|
345
372
|
const textarea = inputRef.current;
|
|
@@ -359,12 +386,41 @@ function ConversationThread({
|
|
|
359
386
|
const findDocument = (id) => id ? allWorkspaceDocuments?.find((d) => d.external_id === id) : void 0;
|
|
360
387
|
const draftingDocument = findDocument(turnDocumentId);
|
|
361
388
|
const attachableDocument = turnDocumentId ? void 0 : findDocument(openDocumentId);
|
|
389
|
+
const differentVisibleDocument = Boolean(
|
|
390
|
+
turnDocumentId && openDocumentId && turnDocumentId !== openDocumentId
|
|
391
|
+
);
|
|
392
|
+
const targetTitle = draftingDocument ? getDocumentTitle(draftingDocument) : turnDocumentId;
|
|
393
|
+
const visibleDocument = findDocument(openDocumentId);
|
|
394
|
+
const visibleTitle = visibleDocument ? getDocumentTitle(visibleDocument) : openDocumentId;
|
|
395
|
+
const sameTitle = targetTitle && visibleTitle && targetTitle === visibleTitle;
|
|
396
|
+
const switchThreadDocument = (documentId) => {
|
|
397
|
+
if (isGenerating || switchingDocument.isPending()) return;
|
|
398
|
+
const isCurrent = () => {
|
|
399
|
+
const state = session.getState();
|
|
400
|
+
return state.workspaceId === selectedWorkspaceId && state.conversationId === currentConversationId;
|
|
401
|
+
};
|
|
402
|
+
setSwitchState({ scope: scopeKey, pending: true, failed: false });
|
|
403
|
+
void switchInScope(
|
|
404
|
+
switchingDocument,
|
|
405
|
+
() => threadDocument.bind(documentId),
|
|
406
|
+
isCurrent,
|
|
407
|
+
(pending) => setSwitchState({ scope: scopeKey, pending, failed: false }),
|
|
408
|
+
() => {
|
|
409
|
+
setSwitchState({ scope: scopeKey, pending: false, failed: true });
|
|
410
|
+
session.setAutoSendDraft(false);
|
|
411
|
+
}
|
|
412
|
+
);
|
|
413
|
+
};
|
|
362
414
|
useDocumentAutoAdd({
|
|
363
415
|
selectedWorkspaceId,
|
|
364
416
|
allWorkspaceDocuments,
|
|
365
417
|
hasContent: !isEmptyConversation || Boolean(parentMessageId || messageHistory?.length || isGenerating)
|
|
366
418
|
});
|
|
367
|
-
useAutoSendDraft(
|
|
419
|
+
useAutoSendDraft(
|
|
420
|
+
handleComposerSend,
|
|
421
|
+
!isLoadingWorkspaceDocuments && !documentSwitchPending && !documentSwitchFailed,
|
|
422
|
+
() => !switchingDocument.isPending()
|
|
423
|
+
);
|
|
368
424
|
useStartRequestedDraft();
|
|
369
425
|
const orphanedMessage = getOrphanedLastMessage(messageHistory, isGenerating, assistantMode);
|
|
370
426
|
return /* @__PURE__ */ jsxs(ConversationBody, { children: [
|
|
@@ -464,58 +520,90 @@ function ConversationThread({
|
|
|
464
520
|
"data-testid": "meeting-thread-read-only",
|
|
465
521
|
children: READ_ONLY_MEETING_TEXT
|
|
466
522
|
}
|
|
467
|
-
) : /* @__PURE__ */
|
|
468
|
-
|
|
469
|
-
{
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
/* @__PURE__ */ jsx(
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
523
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
524
|
+
documentSwitchPending && /* @__PURE__ */ jsx("p", { className: "mx-3 mb-2 text-sm text-muted-foreground", role: "status", children: "Switching this thread\u2019s document\u2026" }),
|
|
525
|
+
documentSwitchFailed && /* @__PURE__ */ jsxs("div", { className: "mx-3 mb-2 text-sm text-destructive", role: "status", children: [
|
|
526
|
+
/* @__PURE__ */ jsx("p", { children: "The document switch failed. Check which document this thread will use before sending." }),
|
|
527
|
+
/* @__PURE__ */ jsx(
|
|
528
|
+
"button",
|
|
529
|
+
{
|
|
530
|
+
type: "button",
|
|
531
|
+
className: "underline",
|
|
532
|
+
onClick: () => {
|
|
533
|
+
session.setAutoSendDraft(false);
|
|
534
|
+
switchingDocument.acknowledgeFailure();
|
|
535
|
+
setSwitchState({ scope: scopeKey, pending: false, failed: false });
|
|
536
|
+
},
|
|
537
|
+
children: "Use the current thread document"
|
|
538
|
+
}
|
|
539
|
+
)
|
|
540
|
+
] }),
|
|
541
|
+
!paMode && differentVisibleDocument && /* @__PURE__ */ jsx(
|
|
542
|
+
DocumentTargetNotice,
|
|
543
|
+
{
|
|
544
|
+
target: sameTitle ? `${targetTitle} (${turnDocumentId})` : targetTitle,
|
|
545
|
+
visible: sameTitle ? `${visibleTitle} (${openDocumentId})` : visibleTitle,
|
|
546
|
+
onSwitch: visibleDocument ? () => switchThreadDocument(openDocumentId) : void 0,
|
|
547
|
+
disabled: isGenerating || documentSwitchPending
|
|
548
|
+
}
|
|
549
|
+
),
|
|
550
|
+
/* @__PURE__ */ jsx(
|
|
551
|
+
ConversationComposer,
|
|
552
|
+
{
|
|
553
|
+
handleSendMessage: handleUserSend,
|
|
554
|
+
placeholder: pendingAnswer ? assistant.answerPlaceholder : void 0,
|
|
555
|
+
isGenerating,
|
|
556
|
+
shouldOfferFollowUp: !showScrollToBottom,
|
|
557
|
+
inputRef,
|
|
558
|
+
isBranching,
|
|
559
|
+
onCancelBranching: session.cancelEditing,
|
|
560
|
+
modelSelector: paMode ? void 0 : modelSelector,
|
|
561
|
+
skills: composerSkills,
|
|
562
|
+
onBrowseSkills: browseSkills,
|
|
563
|
+
contextUsage: latestContextUsage,
|
|
564
|
+
isConversationEmpty: messageHistory.length === 0 && !isBranching,
|
|
565
|
+
leftButton: paMode ? /* @__PURE__ */ jsx(PaModeBadge, { icon: /* @__PURE__ */ jsx(ArbiBotIcon, { size: 16, className: "shrink-0" }) }) : /* @__PURE__ */ jsxs(ComposerAccessories, { children: [
|
|
566
|
+
composerAccessory,
|
|
567
|
+
threadDocument.unavailable ? /* @__PURE__ */ jsx(
|
|
568
|
+
DraftingDocChip,
|
|
569
|
+
{
|
|
570
|
+
state: "unavailable",
|
|
571
|
+
title: "",
|
|
572
|
+
disabled: isGenerating || documentSwitchPending,
|
|
573
|
+
onDetach: () => switchThreadDocument(null)
|
|
574
|
+
}
|
|
575
|
+
) : draftingDocument ? /* @__PURE__ */ jsx(
|
|
576
|
+
DraftingDocChip,
|
|
577
|
+
{
|
|
578
|
+
title: getDocumentTitle(draftingDocument),
|
|
579
|
+
disabled: isGenerating || documentSwitchPending,
|
|
580
|
+
onDetach: threadDocument.documentId ? () => switchThreadDocument(null) : void 0
|
|
581
|
+
}
|
|
582
|
+
) : attachableDocument && /* @__PURE__ */ jsx(
|
|
583
|
+
DraftingDocChip,
|
|
584
|
+
{
|
|
585
|
+
state: "attach",
|
|
586
|
+
title: getDocumentTitle(attachableDocument),
|
|
587
|
+
disabled: isGenerating || documentSwitchPending,
|
|
588
|
+
onAttach: () => switchThreadDocument(attachableDocument.external_id)
|
|
589
|
+
}
|
|
590
|
+
)
|
|
591
|
+
] }),
|
|
592
|
+
rightButton: /* @__PURE__ */ jsxs(ComposerTools, { children: [
|
|
593
|
+
composerTools,
|
|
594
|
+
/* @__PURE__ */ jsx(MicButton, { inputRef }),
|
|
595
|
+
/* @__PURE__ */ jsx(
|
|
596
|
+
ConversationSendButton,
|
|
597
|
+
{
|
|
598
|
+
onClick: handleUserSend,
|
|
599
|
+
disabled: documentSwitchPending,
|
|
600
|
+
hasOrphanedMessage: !isGenerating && orphanedMessage !== null
|
|
601
|
+
}
|
|
602
|
+
)
|
|
603
|
+
] })
|
|
604
|
+
}
|
|
605
|
+
)
|
|
606
|
+
] })
|
|
519
607
|
] })
|
|
520
608
|
}
|
|
521
609
|
),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/connection/conversation/ConnectedConversation.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * ConnectedConversationThread\n *\n * The open conversation, connected: its messages (or what an empty one shows), and the composer\n * dock under them (a failed or orphaned turn's alert, the agent's pending question, the running\n * turn's control bar, the composer). It reads and writes the session; what is the host's own (its\n * model picker, what the conversation reads, a settings button) comes in as props.\n */\n\nimport {\n ArbiBotHeadIcon as ArbiBotIcon,\n READ_ONLY_MEETING_TEXT,\n buildPendingFirstTurn,\n getOrphanedLastMessage,\n refuseChatWhenOffline,\n resolveConfigModel,\n selectDraft,\n transcriptSegmentOf,\n useAnswerAgentQuestion,\n useArbiSession,\n useArbiSessionState,\n useArbiSessionStore,\n useAskAgain,\n useAutoSendDraft,\n useConfig,\n useConnectRunStream,\n useConversationData,\n useConversationIsShared,\n useConversationItems,\n useConversationTurn,\n useDocumentAutoAdd,\n useDocuments,\n useThreadDocument,\n useUserSettings,\n useWorkspaceRole,\n} from '@arbidocs/react'\nimport { getDocumentTitle } from '@arbidocs/react/ui'\nimport { useOpenDocumentId, useTurnDocumentId, useAssistantCopy } from '@arbidocs/react/shell'\nimport type { ChatMessage as Message } from '@arbidocs/sdk/browser'\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from 'react'\nimport { ConversationFilter } from '../../chat/TranscriptLine'\nimport { ComposerAccessories, ComposerTools, PaModeBadge } from '../../chat/ConversationParts'\nimport { ComposerContainer, ComposerDock, ScrollToBottom } from '../../chat/Composer'\nimport {\n ConversationBody,\n ConversationLoading,\n ConversationMain,\n} from '../../chat/ConversationLayout'\nimport { DraftingDocChip } from '../../chat/DraftingDocChip'\nimport { PendingAnswerBar } from '../../chat/PendingAnswerBar'\nimport { TaskEmptyState } from '../../agents/tasks/TaskEmptyState'\nimport {\n CallConversationEmpty,\n ProvisionalSpeakers,\n} from '../../calls/connected/CallConversationParts'\nimport { useProvisionalSpeakers } from '../../calls/connected/provisional-speakers'\nimport {\n TranscriptRunsContext,\n threadTranscriptRuns,\n} from '../../calls/connected/transcript-runs-context'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { useStartRequestedDraft } from './useStartRequestedDraft'\nimport { useAddFromUrls } from '../files/upload/useAddFromUrls'\nimport { ConnectedConversationStart } from '../workflows/ConnectedConversationStart'\nimport { useSlashSkillWorkflows } from '../workflows/useSlashSkillWorkflows'\nimport { AgentControlBar } from './AgentControlBar'\nimport { AskAgainContext } from './AskAgainContext'\nimport { ConnectedConversationEmpty } from './ConnectedConversationEmpty'\nimport { ConnectedMessageArea as MessageArea } from './ConnectedMessageArea'\nimport { ConversationAlert } from './ConversationAlert'\nimport { ConversationComposer } from './ConversationComposer'\nimport { ConversationSendButton } from './ConversationSendButton'\nimport { MicButton } from './MicButton'\nimport type { MessageTimerSubscription } from './MessageLiveSeconds'\nimport { useMeetingThreadMessages } from './useMeetingThreadMessages'\nimport { useThreadScroll } from './useThreadScroll'\n\nexport interface ConnectedConversationThreadProps {\n /** Controlled selection, mirrored into the shared session without route parsing. */\n conversationId?: string | null\n /** The composer's model picker (the host's). Absent: none. */\n modelSelector?: ReactNode\n}\n\n/** The thread body as the page frames it: the page fills the composer's context and tools. */\ninterface ConversationThreadProps {\n modelSelector?: ReactNode\n /** Left in the composer: what the conversation reads (the page's context button). */\n composerAccessory?: ReactNode\n /** Beside the microphone (the page's developer settings button). */\n composerTools?: ReactNode\n}\n\nexport function ConversationThread({\n modelSelector,\n composerAccessory,\n composerTools,\n}: ConversationThreadProps) {\n const containerRef = useRef<HTMLDivElement>(null)\n const inputRef = useRef<HTMLTextAreaElement>(null)\n const session = useArbiSessionStore()\n const environment = useBlocksEnvironment()\n const { notify, openUpload, openSkillsBrowser } = environment\n\n // Generation state for all conversations (background detection, stream control).\n const generatingConversations = useArbiSessionState((state) => state.generating)\n const { data: userSettings } = useUserSettings()\n\n const currentConversationId = useArbiSessionState((state) => state.conversationId)\n // The open task, if it is one: an empty task shows itself rather than the generic empty page.\n const { conversations } = useConversationItems()\n const currentTask = currentConversationId\n ? conversations.find((c) => c.external_id === currentConversationId)\n : undefined\n\n // The assistant message currently streaming in this conversation: target for out-of-band\n // control (pause / resume / status probe).\n const streamingAssistantId = currentConversationId\n ? (generatingConversations[currentConversationId]?.streamingAssistantId ?? null)\n : null\n\n const editingMessageId = useArbiSessionState((state) => state.editingMessageId)\n\n const {\n selectedWorkspaceId,\n parentMessageId,\n messageHistory,\n threadsLoading,\n isEmptyConversation,\n } = useConversationData()\n\n // Attach to a run that is generating in THIS conversation but that this client did not start\n // itself: a background/scheduled agent run, or the same account on another device.\n useConnectRunStream(currentConversationId, messageHistory)\n\n // The in-flight assistant message drives the docked control bar's live status and steps\n // drawer; its timer subscription feeds the elapsed ticker.\n const streamingMessage = useMemo(\n () =>\n streamingAssistantId\n ? (messageHistory as Message[]).find((m) => m.external_id === streamingAssistantId)\n : undefined,\n [messageHistory, streamingAssistantId]\n )\n const queuedUserMessages = useMemo(\n () =>\n (messageHistory as Message[])\n .filter((message) => message.role === 'user' && message.status === 'queued')\n .map(({ external_id, content }) => ({ external_id, content })),\n [messageHistory]\n )\n const streamingLiveTimer = useMemo<MessageTimerSubscription | undefined>(\n () =>\n streamingMessage\n ? {\n conversationId: streamingMessage.conversation_ext_id,\n messageId: streamingMessage.external_id,\n isUser: false,\n isGenerating: true,\n }\n : undefined,\n [streamingMessage]\n )\n\n // The agent paused to ask a question (ask_user / Human-in-the-loop). Find the latest assistant\n // message still awaiting an answer, so the prompt docks (chips + the composer) instead of a\n // mid-stream input card.\n const pendingAnswer = useMemo(() => {\n for (let i = messageHistory.length - 1; i >= 0; i--) {\n const m = messageHistory[i]\n if (m.role === 'assistant' && m.pendingUserInput) {\n return {\n request: m.pendingUserInput,\n assistantMessageExtId: m.external_id,\n conversationExtId: m.conversation_ext_id,\n }\n }\n }\n return null\n }, [messageHistory])\n\n // Send an answer to a pending agent question (from a chip or the composer).\n const answerQuestion = useAnswerAgentQuestion()\n const submitAnswer = useCallback(\n async (answer: string) => {\n const trimmed = answer.trim()\n if (!pendingAnswer || !trimmed) return\n session.setDraft('')\n try {\n await answerQuestion(pendingAnswer, trimmed)\n } catch (err) {\n console.error('Failed to answer agent', err)\n notify('Failed to send your answer', 'error')\n }\n },\n [pendingAnswer, answerQuestion, session, notify]\n )\n\n // All workspace documents, for counts and auto-add.\n const { data: allWorkspaceDocuments = [], isLoading: isLoadingWorkspaceDocuments } =\n useDocuments()\n\n // The parent message's configuration, for the model it ran with.\n const parentMessage = useMemo(() => {\n if (!parentMessageId || !messageHistory) return null\n return messageHistory.find((m) => m.external_id === parentMessageId)\n }, [parentMessageId, messageHistory])\n const parentConfigName = parentMessage?.config_ext_id || userSettings?.last_config || 'default'\n const { data: parentConfig } = useConfig(parentConfigName, { enabled: !!parentConfigName })\n\n // Reconcile stale isGenerating state with backend truth. If the backend says the last message\n // is completed/failed but this client still thinks it is generating, clear the stale state\n // (covers a silent SSE death, a page reload, etc.).\n useEffect(() => {\n for (const [convId, genState] of Object.entries(generatingConversations)) {\n if (!genState.isGenerating) continue\n const conv = conversations.find((c) => c.external_id === convId)\n if (!conv?.last_message_status) continue\n if (conv.last_message_status === 'completed' || conv.last_message_status === 'failed') {\n session.setConversationGenerating(convId, false, null)\n }\n }\n }, [conversations, generatingConversations, session])\n\n // Continuing a thread or branch runs on its config, and the picker shows that config's model,\n // unless the person picks another. Only runs on parentMessageId changes, never on\n // parentConfig/messageHistory updates, so the person can freely toggle the model picker without\n // it being overwritten. Skipped while the parent is a freshly-created streaming message\n // (config_ext_id is null).\n useEffect(() => {\n if (!parentMessageId) return\n const parentMsg = messageHistory?.find((m) => m.external_id === parentMessageId)\n if (parentMsg?.config_ext_id && parentConfig && 'QueryLLM' in parentConfig) {\n session.setChatModelName(resolveConfigModel(parentConfig))\n session.setChatModel(parentMsg.config_ext_id)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [parentMessageId])\n\n // Thread vs chat: in a thread, a comment without an @Assistant mention never expects a reply.\n // A shared chat is a thread, and so is a solo one set to answer only when @mentioned.\n const isSharedConversation = useConversationIsShared()\n const assistantMode =\n isSharedConversation || currentTask?.assistant_mode === 'mentioned' ? 'mentioned' : 'always'\n\n // A thread call's meeting thread is read-only for workspace guests (they may join the call).\n const isGuest = useWorkspaceRole() === 'guest'\n const meetingReadOnly = isGuest && !!currentTask?.meeting_call_ext_id\n const meetingCallExtId = currentTask?.meeting_call_ext_id ?? null\n const threadMessages = useMeetingThreadMessages(meetingCallExtId, messageHistory)\n\n const [firstTurnPrompt, setFirstTurnPrompt] = useState<string | null>(null)\n const currentUserExtId = useArbiSession().user?.external_id ?? ''\n const pendingFirstTurn = useMemo(\n () => (firstTurnPrompt ? buildPendingFirstTurn(firstTurnPrompt, currentUserExtId) : null),\n [firstTurnPrompt, currentUserExtId]\n )\n const uploadUrls = useAddFromUrls({\n onZipFiles: (files) => openUpload?.(files, { source: 'computer' }),\n })\n\n const {\n isGenerating,\n hasError,\n lastFailedMessage,\n lastErrorMessage,\n handleCreateBranch,\n handleSendMessage,\n handleAbortGeneration,\n handleRetrySend,\n handleRetryOrphanedMessage,\n } = useConversationTurn({ selectedWorkspaceId, parentMessageId })\n const handleAskAgain = useAskAgain({ isGenerating, handleCreateBranch })\n\n // A PA conversation: any of its questions carries the personal_agent tool.\n const paMode = useArbiSessionState((state) => state.paMode)\n useEffect(() => {\n if (messageHistory.length === 0) return\n const hasPaTool = messageHistory.some(\n (m) =>\n m.role === 'user' && m.tools && 'personal_agent' in (m.tools as Record<string, unknown>)\n )\n if (hasPaTool !== paMode) session.setPaMode(hasPaTool)\n }, [messageHistory, paMode, session])\n\n // A meeting thread shows everything, typed comments only, or its transcript only.\n const [meetingView, setMeetingView] = useState<'all' | 'chat' | 'transcript'>('all')\n useEffect(() => setMeetingView('all'), [currentConversationId])\n const shownThreadMessages = useMemo(() => {\n if (!meetingCallExtId || meetingView === 'all') return threadMessages\n const isLine = (m: (typeof threadMessages)[number]) =>\n !!transcriptSegmentOf(m.tools ?? m.meta?.tools)\n return threadMessages.filter((m) => (meetingView === 'transcript' ? isLine(m) : !isLine(m)))\n }, [meetingCallExtId, meetingView, threadMessages])\n const transcriptLineCount = useMemo(\n () =>\n meetingCallExtId\n ? threadMessages.filter((m) => transcriptSegmentOf(m.tools ?? m.meta?.tools)).length\n : 0,\n [meetingCallExtId, threadMessages]\n )\n\n // Visible messages: while editing, the edited message and everything after it are hidden.\n const visibleMessages = useMemo(() => {\n if (!editingMessageId) return shownThreadMessages\n const editIndex = shownThreadMessages.findIndex((m) => m.external_id === editingMessageId)\n if (editIndex < 0) return shownThreadMessages\n return shownThreadMessages.slice(0, editIndex)\n }, [shownThreadMessages, editingMessageId])\n // Transcript lines group into runs per speaker; each speaker's newest line lights up as they talk.\n const transcriptRunInfo = useMemo(\n () => threadTranscriptRuns(meetingCallExtId ? visibleMessages : []),\n [meetingCallExtId, visibleMessages]\n )\n // While I am in this meeting's call: \"<speaker> is speaking\u2026\" until their line arrives.\n const threadLines = useMemo(\n () =>\n threadMessages.flatMap((m) => {\n const seg = transcriptSegmentOf(m.tools ?? m.meta?.tools)\n return seg\n ? [\n {\n speakerId: seg.speaker_ext_id,\n at: Date.parse(seg.started_at ?? m.created_at ?? '') || 0,\n },\n ]\n : []\n }),\n [threadMessages]\n )\n const provisionalSpeakers = useProvisionalSpeakers(meetingCallExtId, threadLines)\n const showProvisional = !!meetingCallExtId && meetingView !== 'chat'\n\n // The latest context usage, from the last assistant message. finalContextUsage (the true\n // per-turn total from response.completed, with spent_gbp/budget_gbp) first; agentSteps only\n // cover function_call/reasoning items, so a step's own `context` is at best a mid-turn partial.\n // They are read only for messages saved before finalContextUsage existed.\n const latestContextUsage = useMemo(() => {\n const messages = messageHistory as Message[]\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.role !== 'assistant') continue\n if (msg.finalContextUsage) return msg.finalContextUsage\n if (!msg.agentSteps) continue\n for (let j = msg.agentSteps.length - 1; j >= 0; j--) {\n if (msg.agentSteps[j].context) return msg.agentSteps[j].context\n }\n }\n return null\n }, [messageHistory])\n\n // The edited message's parent, which the edit branches from.\n const editedMessageParentId = useMemo(() => {\n if (!editingMessageId) return null\n const editedMsg = messageHistory.find((m) => m.external_id === editingMessageId)\n return editedMsg?.parent_message_ext_id ?? null\n }, [editingMessageId, messageHistory])\n\n const isBranching = !!editingMessageId\n\n // Send, after an orphaned question (one left without its answer) if there is one.\n const handleSendMessageWithOrphanCheck = useCallback(async () => {\n const orphanedMessage = getOrphanedLastMessage(messageHistory, isGenerating, assistantMode)\n const draftMessage = selectDraft(session.getState()).trim()\n\n if (orphanedMessage) {\n // An orphaned question and an empty draft: ask it again.\n if (draftMessage === '') {\n await handleRetryOrphanedMessage(\n orphanedMessage.content,\n orphanedMessage.parent_message_ext_id ?? null,\n orphanedMessage.external_id\n )\n return\n }\n\n // An orphaned question and a new draft: the draft replaces it.\n await handleRetryOrphanedMessage(\n draftMessage,\n orphanedMessage.parent_message_ext_id ?? null,\n orphanedMessage.external_id\n )\n session.setDraft('')\n return\n }\n\n // No orphaned question: a normal send.\n await handleSendMessage()\n }, [\n messageHistory,\n isGenerating,\n assistantMode,\n handleRetryOrphanedMessage,\n handleSendMessage,\n session,\n ])\n\n // An edit sends as a branch; anything else sends normally.\n const handleSendMessageForEdit = useCallback(async () => {\n if (isBranching && editedMessageParentId) {\n const draftMessage = selectDraft(session.getState()).trim()\n if (!draftMessage) return\n\n // Clear the timers of the messages after the branch point.\n const editIndex = messageHistory.findIndex((m) => m.external_id === editingMessageId)\n if (editIndex >= 0) {\n Object.keys(session.getState().messageTimers).forEach((key) => {\n const keyIndex = parseInt(key)\n if (!isNaN(keyIndex) && keyIndex > editIndex) session.clearMessageTimer(key)\n })\n }\n\n session.completeEditing()\n session.setDraft('')\n await handleCreateBranch(editedMessageParentId, draftMessage)\n return\n }\n\n await handleSendMessageWithOrphanCheck()\n }, [\n isBranching,\n editedMessageParentId,\n editingMessageId,\n messageHistory,\n session,\n handleCreateBranch,\n handleSendMessageWithOrphanCheck,\n ])\n\n // While the agent waits on an answer, the composer answers the question (interject) instead of\n // sending a new message.\n const handleComposerSend = useCallback(() => {\n const draft = selectDraft(session.getState())\n if (pendingAnswer) {\n submitAnswer(draft)\n return\n }\n // A brand-new chat has no thread to show until the server confirms the question.\n if (!currentConversationId) setFirstTurnPrompt(draft.trim())\n handleSendMessageForEdit()\n }, [pendingAnswer, currentConversationId, submitAnswer, handleSendMessageForEdit, session])\n\n // The pending first turn lasts only while the new chat generates; once the thread exists it is\n // replaced.\n useEffect(() => {\n if (!isGenerating) setFirstTurnPrompt(null)\n }, [isGenerating])\n\n // The person's send (Enter or the Send button): `/skill` or `/skill text` opens the skill's form\n // instead of sending a bare command. Auto-sends of launched drafts go through handleComposerSend\n // directly, so a launched skill is never intercepted again.\n const slashWorkflows = useSlashSkillWorkflows({ landing: 'current-chat' })\n // The composer's slash menu offers the built-in skills; a picked one opens this launcher.\n const composerSkills = useMemo(\n () => ({ openFor: slashWorkflows.openFor }),\n [slashWorkflows.openFor]\n )\n const browseSkills = useMemo(\n () => (openSkillsBrowser ? () => openSkillsBrowser() : undefined),\n [openSkillsBrowser]\n )\n\n const { showScrollToBottom, scrollToBottom } = useThreadScroll({\n currentConversationId,\n parentMessageId,\n messageHistory,\n })\n\n const handleUserSend = useCallback(() => {\n const draft = selectDraft(session.getState())\n if (!pendingAnswer && slashWorkflows.openForDraft(draft)) {\n session.setDraft('')\n return\n }\n // Offline, nothing is sent.\n if (refuseChatWhenOffline()) return\n // Their message lands at the bottom of the thread: bring the view down to it, even when they\n // had scrolled up to read a streaming answer.\n scrollToBottom()\n handleComposerSend()\n }, [pendingAnswer, slashWorkflows, handleComposerSend, scrollToBottom, session])\n\n // Focus the input when editing starts, its caret at the end.\n useEffect(() => {\n if (editingMessageId && inputRef.current) {\n const textarea = inputRef.current\n textarea.focus()\n const len = textarea.value.length\n textarea.setSelectionRange(len, len)\n }\n }, [editingMessageId])\n\n // Drafting mode: the thread's own document, which the assistant reads on demand and edits as\n // tracked changes (sent as a reference, `active_artifact_ext_id`): the one the thread is bound to,\n // else one made in it and open. A document merely open beside an unbound thread is only offered\n // (attach): being open never turns a question into an edit.\n const threadDocument = useThreadDocument()\n const turnDocumentId = useTurnDocumentId({\n boundDocumentId: threadDocument.documentId,\n conversationId: currentConversationId,\n workspaceId: selectedWorkspaceId,\n })\n const assistant = useAssistantCopy()\n const openDocumentId = useOpenDocumentId({ workspaceId: selectedWorkspaceId })\n const findDocument = (id: string | null) =>\n id ? allWorkspaceDocuments?.find((d) => d.external_id === id) : undefined\n const draftingDocument = findDocument(turnDocumentId)\n const attachableDocument = turnDocumentId ? undefined : findDocument(openDocumentId)\n\n // Empty chats follow workspace documents; sending the first message freezes that selection.\n useDocumentAutoAdd({\n selectedWorkspaceId,\n allWorkspaceDocuments,\n hasContent:\n !isEmptyConversation || Boolean(parentMessageId || messageHistory?.length || isGenerating),\n })\n\n // A draft handed over by a launch or the workspace home's ask bar sends on arrival, but only\n // after the documents query settles. MUST stay declared after useDocumentAutoAdd: effects run in\n // declaration order, and sending before auto-add seeds the new chat's documents posts the\n // question with none attached.\n useAutoSendDraft(handleComposerSend, !isLoadingWorkspaceDocuments)\n // `openNewConversation({ prompt })`: the prompt becomes the draft, sent as above.\n useStartRequestedDraft()\n\n const orphanedMessage = getOrphanedLastMessage(messageHistory, isGenerating, assistantMode)\n\n return (\n <ConversationBody>\n <ConversationMain data-testid={`conversation-${currentConversationId}`}>\n {threadsLoading ? (\n <ConversationLoading />\n ) : messageHistory.length > 0 || isBranching ? (\n <AskAgainContext.Provider value={handleAskAgain}>\n <TranscriptRunsContext.Provider value={transcriptRunInfo}>\n {meetingCallExtId && transcriptLineCount > 0 && (\n <div className=\"flex justify-center py-2\">\n <ConversationFilter<typeof meetingView>\n value={meetingView}\n onChange={setMeetingView}\n options={[\n { value: 'all', label: 'All' },\n { value: 'chat', label: 'Chat', testId: 'chat-filter' },\n {\n value: 'transcript',\n label: 'Transcript',\n count: transcriptLineCount,\n testId: 'transcript-filter',\n },\n ]}\n />\n </div>\n )}\n <MessageArea ref={containerRef} messages={visibleMessages} />\n {showProvisional && <ProvisionalSpeakers ids={provisionalSpeakers} />}\n </TranscriptRunsContext.Provider>\n </AskAgainContext.Provider>\n ) : meetingCallExtId ? (\n // A meeting thread with nothing yet: call-aware, not the upload prompt.\n <div>\n <CallConversationEmpty callExtId={meetingCallExtId} />\n <ProvisionalSpeakers ids={provisionalSpeakers} />\n </div>\n ) : currentTask && currentTask.status != null ? (\n <TaskEmptyState task={currentTask} />\n ) : pendingFirstTurn && isGenerating ? (\n <MessageArea ref={containerRef} messages={pendingFirstTurn} />\n ) : (\n <ConnectedConversationEmpty\n hasDocuments={allWorkspaceDocuments.length > 0}\n onUsePrompt={(text) => {\n session.setDraft(text)\n inputRef?.current?.focus()\n }}\n onAddDocuments={(files) => openUpload?.(files, { source: 'computer' })}\n onUrlsSubmit={uploadUrls}\n onImportFromEmail={\n openUpload ? () => openUpload(undefined, { source: 'email' }) : undefined\n }\n below={<ConnectedConversationStart />}\n />\n )}\n </ConversationMain>\n\n {/* The composer dock: the thread's alerts and bars, then the composer. */}\n <ComposerDock\n floating={\n <ScrollToBottom\n className=\"left-auto right-3 translate-x-0\"\n show={showScrollToBottom}\n onClick={scrollToBottom}\n />\n }\n >\n <ComposerContainer className=\"mx-auto max-w-[49rem] px-3 sm:px-6\">\n {/* A question left without its answer (stopped, reloaded, the backend failed), else a\n send that failed. */}\n {orphanedMessage ? (\n <ConversationAlert\n type={\n messageHistory[messageHistory.length - 1]?.role === 'assistant' &&\n messageHistory[messageHistory.length - 1].status === 'failed'\n ? 'backend-failed'\n : 'orphaned'\n }\n message={orphanedMessage}\n onRetryOrphaned={handleRetryOrphanedMessage}\n />\n ) : hasError && lastFailedMessage ? (\n <ConversationAlert\n type=\"send-failed\"\n errorMessage={lastErrorMessage || undefined}\n onRetrySend={handleRetrySend}\n isRetrying={isGenerating}\n />\n ) : null}\n\n {pendingAnswer && (\n <PendingAnswerBar\n key={pendingAnswer.assistantMessageExtId}\n question={pendingAnswer.request.question}\n options={pendingAnswer.request.options}\n timeoutSeconds={pendingAnswer.request.timeout_seconds}\n onPick={submitAnswer}\n />\n )}\n\n {/* Out-of-band control (pause / resume / status) for the running turn. Hidden while\n ask_user is pending: that flow owns the composer. */}\n {isGenerating && !pendingAnswer && streamingAssistantId && (\n <AgentControlBar\n key={streamingAssistantId}\n assistantMessageExtId={streamingAssistantId}\n agentSteps={streamingMessage?.agentSteps}\n liveTimer={streamingLiveTimer}\n onStop={handleAbortGeneration}\n queuedMessages={queuedUserMessages}\n />\n )}\n\n {meetingReadOnly ? (\n <p\n className=\"py-3 text-center text-sm text-muted-foreground\"\n data-testid=\"meeting-thread-read-only\"\n >\n {READ_ONLY_MEETING_TEXT}\n </p>\n ) : (\n <ConversationComposer\n handleSendMessage={handleUserSend}\n placeholder={pendingAnswer ? assistant.answerPlaceholder : undefined}\n isGenerating={isGenerating}\n shouldOfferFollowUp={!showScrollToBottom}\n inputRef={inputRef}\n isBranching={isBranching}\n onCancelBranching={session.cancelEditing}\n modelSelector={paMode ? undefined : modelSelector}\n skills={composerSkills}\n onBrowseSkills={browseSkills}\n contextUsage={latestContextUsage}\n isConversationEmpty={messageHistory.length === 0 && !isBranching}\n leftButton={\n paMode ? (\n <PaModeBadge icon={<ArbiBotIcon size={16} className=\"shrink-0\" />} />\n ) : (\n <ComposerAccessories>\n {composerAccessory}\n {threadDocument.unavailable ? (\n <DraftingDocChip\n state=\"unavailable\"\n title=\"\"\n onDetach={() => threadDocument.bind(null)}\n />\n ) : draftingDocument ? (\n <DraftingDocChip\n title={getDocumentTitle(draftingDocument)}\n onDetach={\n threadDocument.documentId ? () => threadDocument.bind(null) : undefined\n }\n />\n ) : (\n attachableDocument && (\n <DraftingDocChip\n state=\"attach\"\n title={getDocumentTitle(attachableDocument)}\n onAttach={() => threadDocument.bind(attachableDocument.external_id)}\n />\n )\n )}\n </ComposerAccessories>\n )\n }\n rightButton={\n <ComposerTools>\n {composerTools}\n <MicButton inputRef={inputRef} />\n <ConversationSendButton\n onClick={handleUserSend}\n hasOrphanedMessage={!isGenerating && orphanedMessage !== null}\n />\n </ComposerTools>\n }\n />\n )}\n </ComposerContainer>\n </ComposerDock>\n {slashWorkflows.launcher}\n </ConversationBody>\n )\n}\n\n/**\n * The open conversation's thread, connected: its messages and the composer, with no tabs or history\n * around it. `ConnectedConversationPage` is the same thread in the tabbed workspace page.\n */\nexport function ConnectedConversationThread({\n conversationId,\n modelSelector,\n}: ConnectedConversationThreadProps) {\n const session = useArbiSessionStore()\n useEffect(() => {\n if (conversationId === undefined) return\n if (session.getState().conversationId !== conversationId) {\n session.setConversationId(conversationId)\n }\n }, [conversationId, session])\n return <ConversationThread modelSelector={modelSelector} />\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * ConnectedConversationThread\n *\n * The open conversation, connected: its messages (or what an empty one shows), and the composer\n * dock under them (a failed or orphaned turn's alert, the agent's pending question, the running\n * turn's control bar, the composer). It reads and writes the session; what is the host's own (its\n * model picker, what the conversation reads, a settings button) comes in as props.\n */\n\nimport {\n ArbiBotHeadIcon as ArbiBotIcon,\n READ_ONLY_MEETING_TEXT,\n buildPendingFirstTurn,\n getOrphanedLastMessage,\n refuseChatWhenOffline,\n resolveConfigModel,\n selectDraft,\n transcriptSegmentOf,\n useAnswerAgentQuestion,\n useArbiSession,\n useArbiSessionState,\n useArbiSessionStore,\n useAskAgain,\n useAutoSendDraft,\n useConfig,\n useConnectRunStream,\n useConversationData,\n useConversationIsShared,\n useConversationItems,\n useConversationTurn,\n useDocumentAutoAdd,\n useDocuments,\n useThreadDocument,\n useUserSettings,\n useWorkspaceRole,\n} from '@arbidocs/react'\nimport { getDocumentTitle } from '@arbidocs/react/ui'\nimport { useOpenDocumentId, useTurnDocumentId, useAssistantCopy } from '@arbidocs/react/shell'\nimport type { ChatMessage as Message } from '@arbidocs/sdk/browser'\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from 'react'\nimport { ConversationFilter } from '../../chat/TranscriptLine'\nimport { ComposerAccessories, ComposerTools, PaModeBadge } from '../../chat/ConversationParts'\nimport { ComposerContainer, ComposerDock, ScrollToBottom } from '../../chat/Composer'\nimport {\n ConversationBody,\n ConversationLoading,\n ConversationMain,\n} from '../../chat/ConversationLayout'\nimport { DraftingDocChip } from '../../chat/DraftingDocChip'\nimport { PendingAnswerBar } from '../../chat/PendingAnswerBar'\nimport { TaskEmptyState } from '../../agents/tasks/TaskEmptyState'\nimport {\n CallConversationEmpty,\n ProvisionalSpeakers,\n} from '../../calls/connected/CallConversationParts'\nimport { useProvisionalSpeakers } from '../../calls/connected/provisional-speakers'\nimport {\n TranscriptRunsContext,\n threadTranscriptRuns,\n} from '../../calls/connected/transcript-runs-context'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { useStartRequestedDraft } from './useStartRequestedDraft'\nimport { useAddFromUrls } from '../files/upload/useAddFromUrls'\nimport { ConnectedConversationStart } from '../workflows/ConnectedConversationStart'\nimport { useSlashSkillWorkflows } from '../workflows/useSlashSkillWorkflows'\nimport { AgentControlBar } from './AgentControlBar'\nimport { AskAgainContext } from './AskAgainContext'\nimport { ConnectedConversationEmpty } from './ConnectedConversationEmpty'\nimport { ConnectedMessageArea as MessageArea } from './ConnectedMessageArea'\nimport { ConversationAlert } from './ConversationAlert'\nimport { ConversationComposer } from './ConversationComposer'\nimport { DocumentTargetNotice } from './DocumentTargetNotice'\nimport { createDocumentSwitchGuard, switchInScope } from './documentSwitch'\nimport { ConversationSendButton } from './ConversationSendButton'\nimport { MicButton } from './MicButton'\nimport type { MessageTimerSubscription } from './MessageLiveSeconds'\nimport { useMeetingThreadMessages } from './useMeetingThreadMessages'\nimport { useThreadScroll } from './useThreadScroll'\n\nexport interface ConnectedConversationThreadProps {\n /** Controlled selection, mirrored into the shared session without route parsing. */\n conversationId?: string | null\n /** The composer's model picker (the host's). Absent: none. */\n modelSelector?: ReactNode\n}\n\n/** The thread body as the page frames it: the page fills the composer's context and tools. */\ninterface ConversationThreadProps {\n modelSelector?: ReactNode\n /** Left in the composer: what the conversation reads (the page's context button). */\n composerAccessory?: ReactNode\n /** Beside the microphone (the page's developer settings button). */\n composerTools?: ReactNode\n}\n\nexport function ConversationThread({\n modelSelector,\n composerAccessory,\n composerTools,\n}: ConversationThreadProps) {\n const containerRef = useRef<HTMLDivElement>(null)\n const inputRef = useRef<HTMLTextAreaElement>(null)\n const session = useArbiSessionStore()\n const environment = useBlocksEnvironment()\n const { notify, openUpload, openSkillsBrowser } = environment\n\n // Generation state for all conversations (background detection, stream control).\n const generatingConversations = useArbiSessionState((state) => state.generating)\n const { data: userSettings } = useUserSettings()\n\n const currentConversationId = useArbiSessionState((state) => state.conversationId)\n // The open task, if it is one: an empty task shows itself rather than the generic empty page.\n const { conversations } = useConversationItems()\n const currentTask = currentConversationId\n ? conversations.find((c) => c.external_id === currentConversationId)\n : undefined\n\n // The assistant message currently streaming in this conversation: target for out-of-band\n // control (pause / resume / status probe).\n const streamingAssistantId = currentConversationId\n ? (generatingConversations[currentConversationId]?.streamingAssistantId ?? null)\n : null\n\n const editingMessageId = useArbiSessionState((state) => state.editingMessageId)\n\n const {\n selectedWorkspaceId,\n parentMessageId,\n messageHistory,\n threadsLoading,\n isEmptyConversation,\n } = useConversationData()\n\n // Attach to a run that is generating in THIS conversation but that this client did not start\n // itself: a background/scheduled agent run, or the same account on another device.\n useConnectRunStream(currentConversationId, messageHistory)\n\n // The in-flight assistant message drives the docked control bar's live status and steps\n // drawer; its timer subscription feeds the elapsed ticker.\n const streamingMessage = useMemo(\n () =>\n streamingAssistantId\n ? (messageHistory as Message[]).find((m) => m.external_id === streamingAssistantId)\n : undefined,\n [messageHistory, streamingAssistantId]\n )\n const queuedUserMessages = useMemo(\n () =>\n (messageHistory as Message[])\n .filter((message) => message.role === 'user' && message.status === 'queued')\n .map(({ external_id, content }) => ({ external_id, content })),\n [messageHistory]\n )\n const streamingLiveTimer = useMemo<MessageTimerSubscription | undefined>(\n () =>\n streamingMessage\n ? {\n conversationId: streamingMessage.conversation_ext_id,\n messageId: streamingMessage.external_id,\n isUser: false,\n isGenerating: true,\n }\n : undefined,\n [streamingMessage]\n )\n\n // The agent paused to ask a question (ask_user / Human-in-the-loop). Find the latest assistant\n // message still awaiting an answer, so the prompt docks (chips + the composer) instead of a\n // mid-stream input card.\n const pendingAnswer = useMemo(() => {\n for (let i = messageHistory.length - 1; i >= 0; i--) {\n const m = messageHistory[i]\n if (m.role === 'assistant' && m.pendingUserInput) {\n return {\n request: m.pendingUserInput,\n assistantMessageExtId: m.external_id,\n conversationExtId: m.conversation_ext_id,\n }\n }\n }\n return null\n }, [messageHistory])\n\n // Send an answer to a pending agent question (from a chip or the composer).\n const answerQuestion = useAnswerAgentQuestion()\n const submitAnswer = useCallback(\n async (answer: string) => {\n const trimmed = answer.trim()\n if (!pendingAnswer || !trimmed) return\n session.setDraft('')\n try {\n await answerQuestion(pendingAnswer, trimmed)\n } catch (err) {\n console.error('Failed to answer agent', err)\n notify('Failed to send your answer', 'error')\n }\n },\n [pendingAnswer, answerQuestion, session, notify]\n )\n\n // All workspace documents, for counts and auto-add.\n const { data: allWorkspaceDocuments = [], isLoading: isLoadingWorkspaceDocuments } =\n useDocuments()\n\n // The parent message's configuration, for the model it ran with.\n const parentMessage = useMemo(() => {\n if (!parentMessageId || !messageHistory) return null\n return messageHistory.find((m) => m.external_id === parentMessageId)\n }, [parentMessageId, messageHistory])\n const parentConfigName = parentMessage?.config_ext_id || userSettings?.last_config || 'default'\n const { data: parentConfig } = useConfig(parentConfigName, { enabled: !!parentConfigName })\n\n // Reconcile stale isGenerating state with backend truth. If the backend says the last message\n // is completed/failed but this client still thinks it is generating, clear the stale state\n // (covers a silent SSE death, a page reload, etc.).\n useEffect(() => {\n for (const [convId, genState] of Object.entries(generatingConversations)) {\n if (!genState.isGenerating) continue\n const conv = conversations.find((c) => c.external_id === convId)\n if (!conv?.last_message_status) continue\n if (conv.last_message_status === 'completed' || conv.last_message_status === 'failed') {\n session.setConversationGenerating(convId, false, null)\n }\n }\n }, [conversations, generatingConversations, session])\n\n // Continuing a thread or branch runs on its config, and the picker shows that config's model,\n // unless the person picks another. Only runs on parentMessageId changes, never on\n // parentConfig/messageHistory updates, so the person can freely toggle the model picker without\n // it being overwritten. Skipped while the parent is a freshly-created streaming message\n // (config_ext_id is null).\n useEffect(() => {\n if (!parentMessageId) return\n const parentMsg = messageHistory?.find((m) => m.external_id === parentMessageId)\n if (parentMsg?.config_ext_id && parentConfig && 'QueryLLM' in parentConfig) {\n session.setChatModelName(resolveConfigModel(parentConfig))\n session.setChatModel(parentMsg.config_ext_id)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [parentMessageId])\n\n // Thread vs chat: in a thread, a comment without an @Assistant mention never expects a reply.\n // A shared chat is a thread, and so is a solo one set to answer only when @mentioned.\n const isSharedConversation = useConversationIsShared()\n const assistantMode =\n isSharedConversation || currentTask?.assistant_mode === 'mentioned' ? 'mentioned' : 'always'\n\n // A thread call's meeting thread is read-only for workspace guests (they may join the call).\n const isGuest = useWorkspaceRole() === 'guest'\n const meetingReadOnly = isGuest && !!currentTask?.meeting_call_ext_id\n const meetingCallExtId = currentTask?.meeting_call_ext_id ?? null\n const threadMessages = useMeetingThreadMessages(meetingCallExtId, messageHistory)\n\n const [firstTurnPrompt, setFirstTurnPrompt] = useState<string | null>(null)\n const currentUserExtId = useArbiSession().user?.external_id ?? ''\n const pendingFirstTurn = useMemo(\n () => (firstTurnPrompt ? buildPendingFirstTurn(firstTurnPrompt, currentUserExtId) : null),\n [firstTurnPrompt, currentUserExtId]\n )\n const uploadUrls = useAddFromUrls({\n onZipFiles: (files) => openUpload?.(files, { source: 'computer' }),\n })\n\n const {\n isGenerating,\n hasError,\n lastFailedMessage,\n lastErrorMessage,\n handleCreateBranch,\n handleSendMessage,\n handleAbortGeneration,\n handleRetrySend,\n handleRetryOrphanedMessage,\n } = useConversationTurn({ selectedWorkspaceId, parentMessageId })\n const handleAskAgain = useAskAgain({ isGenerating, handleCreateBranch })\n\n // A PA conversation: any of its questions carries the personal_agent tool.\n const paMode = useArbiSessionState((state) => state.paMode)\n useEffect(() => {\n if (messageHistory.length === 0) return\n const hasPaTool = messageHistory.some(\n (m) =>\n m.role === 'user' && m.tools && 'personal_agent' in (m.tools as Record<string, unknown>)\n )\n if (hasPaTool !== paMode) session.setPaMode(hasPaTool)\n }, [messageHistory, paMode, session])\n\n // A meeting thread shows everything, typed comments only, or its transcript only.\n const [meetingView, setMeetingView] = useState<'all' | 'chat' | 'transcript'>('all')\n useEffect(() => setMeetingView('all'), [currentConversationId])\n const shownThreadMessages = useMemo(() => {\n if (!meetingCallExtId || meetingView === 'all') return threadMessages\n const isLine = (m: (typeof threadMessages)[number]) =>\n !!transcriptSegmentOf(m.tools ?? m.meta?.tools)\n return threadMessages.filter((m) => (meetingView === 'transcript' ? isLine(m) : !isLine(m)))\n }, [meetingCallExtId, meetingView, threadMessages])\n const transcriptLineCount = useMemo(\n () =>\n meetingCallExtId\n ? threadMessages.filter((m) => transcriptSegmentOf(m.tools ?? m.meta?.tools)).length\n : 0,\n [meetingCallExtId, threadMessages]\n )\n\n // Visible messages: while editing, the edited message and everything after it are hidden.\n const visibleMessages = useMemo(() => {\n if (!editingMessageId) return shownThreadMessages\n const editIndex = shownThreadMessages.findIndex((m) => m.external_id === editingMessageId)\n if (editIndex < 0) return shownThreadMessages\n return shownThreadMessages.slice(0, editIndex)\n }, [shownThreadMessages, editingMessageId])\n // Transcript lines group into runs per speaker; each speaker's newest line lights up as they talk.\n const transcriptRunInfo = useMemo(\n () => threadTranscriptRuns(meetingCallExtId ? visibleMessages : []),\n [meetingCallExtId, visibleMessages]\n )\n // While I am in this meeting's call: \"<speaker> is speaking\u2026\" until their line arrives.\n const threadLines = useMemo(\n () =>\n threadMessages.flatMap((m) => {\n const seg = transcriptSegmentOf(m.tools ?? m.meta?.tools)\n return seg\n ? [\n {\n speakerId: seg.speaker_ext_id,\n at: Date.parse(seg.started_at ?? m.created_at ?? '') || 0,\n },\n ]\n : []\n }),\n [threadMessages]\n )\n const provisionalSpeakers = useProvisionalSpeakers(meetingCallExtId, threadLines)\n const showProvisional = !!meetingCallExtId && meetingView !== 'chat'\n\n // The latest context usage, from the last assistant message. finalContextUsage (the true\n // per-turn total from response.completed, with spent_gbp/budget_gbp) first; agentSteps only\n // cover function_call/reasoning items, so a step's own `context` is at best a mid-turn partial.\n // They are read only for messages saved before finalContextUsage existed.\n const latestContextUsage = useMemo(() => {\n const messages = messageHistory as Message[]\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]\n if (msg.role !== 'assistant') continue\n if (msg.finalContextUsage) return msg.finalContextUsage\n if (!msg.agentSteps) continue\n for (let j = msg.agentSteps.length - 1; j >= 0; j--) {\n if (msg.agentSteps[j].context) return msg.agentSteps[j].context\n }\n }\n return null\n }, [messageHistory])\n\n // The edited message's parent, which the edit branches from.\n const editedMessageParentId = useMemo(() => {\n if (!editingMessageId) return null\n const editedMsg = messageHistory.find((m) => m.external_id === editingMessageId)\n return editedMsg?.parent_message_ext_id ?? null\n }, [editingMessageId, messageHistory])\n\n const isBranching = !!editingMessageId\n\n // Send, after an orphaned question (one left without its answer) if there is one.\n const handleSendMessageWithOrphanCheck = useCallback(async () => {\n const orphanedMessage = getOrphanedLastMessage(messageHistory, isGenerating, assistantMode)\n const draftMessage = selectDraft(session.getState()).trim()\n\n if (orphanedMessage) {\n // An orphaned question and an empty draft: ask it again.\n if (draftMessage === '') {\n await handleRetryOrphanedMessage(\n orphanedMessage.content,\n orphanedMessage.parent_message_ext_id ?? null,\n orphanedMessage.external_id\n )\n return\n }\n\n // An orphaned question and a new draft: the draft replaces it.\n await handleRetryOrphanedMessage(\n draftMessage,\n orphanedMessage.parent_message_ext_id ?? null,\n orphanedMessage.external_id\n )\n session.setDraft('')\n return\n }\n\n // No orphaned question: a normal send.\n await handleSendMessage()\n }, [\n messageHistory,\n isGenerating,\n assistantMode,\n handleRetryOrphanedMessage,\n handleSendMessage,\n session,\n ])\n\n // An edit sends as a branch; anything else sends normally.\n const handleSendMessageForEdit = useCallback(async () => {\n if (isBranching && editedMessageParentId) {\n const draftMessage = selectDraft(session.getState()).trim()\n if (!draftMessage) return\n\n // Clear the timers of the messages after the branch point.\n const editIndex = messageHistory.findIndex((m) => m.external_id === editingMessageId)\n if (editIndex >= 0) {\n Object.keys(session.getState().messageTimers).forEach((key) => {\n const keyIndex = parseInt(key)\n if (!isNaN(keyIndex) && keyIndex > editIndex) session.clearMessageTimer(key)\n })\n }\n\n session.completeEditing()\n session.setDraft('')\n await handleCreateBranch(editedMessageParentId, draftMessage)\n return\n }\n\n await handleSendMessageWithOrphanCheck()\n }, [\n isBranching,\n editedMessageParentId,\n editingMessageId,\n messageHistory,\n session,\n handleCreateBranch,\n handleSendMessageWithOrphanCheck,\n ])\n\n // While the agent waits on an answer, the composer answers the question (interject) instead of\n // sending a new message.\n const handleComposerSend = useCallback(() => {\n const draft = selectDraft(session.getState())\n if (pendingAnswer) {\n submitAnswer(draft)\n return\n }\n // A brand-new chat has no thread to show until the server confirms the question.\n if (!currentConversationId) setFirstTurnPrompt(draft.trim())\n handleSendMessageForEdit()\n }, [pendingAnswer, currentConversationId, submitAnswer, handleSendMessageForEdit, session])\n\n // The pending first turn lasts only while the new chat generates; once the thread exists it is\n // replaced.\n useEffect(() => {\n if (!isGenerating) setFirstTurnPrompt(null)\n }, [isGenerating])\n\n // The person's send (Enter or the Send button): `/skill` or `/skill text` opens the skill's form\n // instead of sending a bare command. Auto-sends of launched drafts go through handleComposerSend\n // directly, so a launched skill is never intercepted again.\n const slashWorkflows = useSlashSkillWorkflows({ landing: 'current-chat' })\n // The composer's slash menu offers the built-in skills; a picked one opens this launcher.\n const composerSkills = useMemo(\n () => ({ openFor: slashWorkflows.openFor }),\n [slashWorkflows.openFor]\n )\n const browseSkills = useMemo(\n () => (openSkillsBrowser ? () => openSkillsBrowser() : undefined),\n [openSkillsBrowser]\n )\n\n const { showScrollToBottom, scrollToBottom } = useThreadScroll({\n currentConversationId,\n parentMessageId,\n messageHistory,\n })\n\n const scopeKey = JSON.stringify([selectedWorkspaceId, currentConversationId])\n const documentSwitchGuards = useRef(\n new Map<string, ReturnType<typeof createDocumentSwitchGuard>>()\n )\n if (!documentSwitchGuards.current.has(scopeKey)) {\n documentSwitchGuards.current.set(scopeKey, createDocumentSwitchGuard())\n }\n const switchingDocument = documentSwitchGuards.current.get(scopeKey)!\n const [, setSwitchState] = useState({ scope: scopeKey, pending: false, failed: false })\n const documentSwitchPending = switchingDocument.isPending()\n const documentSwitchFailed = switchingDocument.hasFailed()\n const handleUserSend = useCallback(() => {\n if (switchingDocument.isPending()) return\n if (switchingDocument.hasFailed()) {\n session.setAutoSendDraft(false)\n switchingDocument.acknowledgeFailure()\n setSwitchState({ scope: scopeKey, pending: false, failed: false })\n }\n const draft = selectDraft(session.getState())\n if (!pendingAnswer && slashWorkflows.openForDraft(draft)) {\n session.setDraft('')\n return\n }\n // Offline, nothing is sent.\n if (refuseChatWhenOffline()) return\n // Their message lands at the bottom of the thread: bring the view down to it, even when they\n // had scrolled up to read a streaming answer.\n scrollToBottom()\n handleComposerSend()\n }, [\n pendingAnswer,\n slashWorkflows,\n handleComposerSend,\n scrollToBottom,\n session,\n switchingDocument,\n scopeKey,\n ])\n\n // Focus the input when editing starts, its caret at the end.\n useEffect(() => {\n if (editingMessageId && inputRef.current) {\n const textarea = inputRef.current\n textarea.focus()\n const len = textarea.value.length\n textarea.setSelectionRange(len, len)\n }\n }, [editingMessageId])\n\n // Drafting mode: the thread's own document, which the assistant reads on demand and edits as\n // tracked changes (sent as a reference, `active_artifact_ext_id`): the one the thread is bound to,\n // else one made in it and open. A document merely open beside an unbound thread is only offered\n // (attach): being open never turns a question into an edit.\n const threadDocument = useThreadDocument()\n const turnDocumentId = useTurnDocumentId({\n boundDocumentId: threadDocument.documentId,\n conversationId: currentConversationId,\n workspaceId: selectedWorkspaceId,\n })\n const assistant = useAssistantCopy()\n const openDocumentId = useOpenDocumentId({ workspaceId: selectedWorkspaceId })\n const findDocument = (id: string | null) =>\n id ? allWorkspaceDocuments?.find((d) => d.external_id === id) : undefined\n const draftingDocument = findDocument(turnDocumentId)\n const attachableDocument = turnDocumentId ? undefined : findDocument(openDocumentId)\n const differentVisibleDocument = Boolean(\n turnDocumentId && openDocumentId && turnDocumentId !== openDocumentId\n )\n const targetTitle = draftingDocument ? getDocumentTitle(draftingDocument) : turnDocumentId\n const visibleDocument = findDocument(openDocumentId)\n const visibleTitle = visibleDocument ? getDocumentTitle(visibleDocument) : openDocumentId\n const sameTitle = targetTitle && visibleTitle && targetTitle === visibleTitle\n const switchThreadDocument = (documentId: string | null) => {\n if (isGenerating || switchingDocument.isPending()) return\n const isCurrent = () => {\n const state = session.getState()\n return (\n state.workspaceId === selectedWorkspaceId && state.conversationId === currentConversationId\n )\n }\n setSwitchState({ scope: scopeKey, pending: true, failed: false })\n void switchInScope(\n switchingDocument,\n () => threadDocument.bind(documentId),\n isCurrent,\n (pending) => setSwitchState({ scope: scopeKey, pending, failed: false }),\n () => {\n setSwitchState({ scope: scopeKey, pending: false, failed: true })\n session.setAutoSendDraft(false)\n }\n )\n }\n\n // Empty chats follow workspace documents; sending the first message freezes that selection.\n useDocumentAutoAdd({\n selectedWorkspaceId,\n allWorkspaceDocuments,\n hasContent:\n !isEmptyConversation || Boolean(parentMessageId || messageHistory?.length || isGenerating),\n })\n\n // A draft handed over by a launch or the workspace home's ask bar sends on arrival, but only\n // after the documents query settles. MUST stay declared after useDocumentAutoAdd: effects run in\n // declaration order, and sending before auto-add seeds the new chat's documents posts the\n // question with none attached.\n useAutoSendDraft(\n handleComposerSend,\n !isLoadingWorkspaceDocuments && !documentSwitchPending && !documentSwitchFailed,\n () => !switchingDocument.isPending()\n )\n // `openNewConversation({ prompt })`: the prompt becomes the draft, sent as above.\n useStartRequestedDraft()\n\n const orphanedMessage = getOrphanedLastMessage(messageHistory, isGenerating, assistantMode)\n\n return (\n <ConversationBody>\n <ConversationMain data-testid={`conversation-${currentConversationId}`}>\n {threadsLoading ? (\n <ConversationLoading />\n ) : messageHistory.length > 0 || isBranching ? (\n <AskAgainContext.Provider value={handleAskAgain}>\n <TranscriptRunsContext.Provider value={transcriptRunInfo}>\n {meetingCallExtId && transcriptLineCount > 0 && (\n <div className=\"flex justify-center py-2\">\n <ConversationFilter<typeof meetingView>\n value={meetingView}\n onChange={setMeetingView}\n options={[\n { value: 'all', label: 'All' },\n { value: 'chat', label: 'Chat', testId: 'chat-filter' },\n {\n value: 'transcript',\n label: 'Transcript',\n count: transcriptLineCount,\n testId: 'transcript-filter',\n },\n ]}\n />\n </div>\n )}\n <MessageArea ref={containerRef} messages={visibleMessages} />\n {showProvisional && <ProvisionalSpeakers ids={provisionalSpeakers} />}\n </TranscriptRunsContext.Provider>\n </AskAgainContext.Provider>\n ) : meetingCallExtId ? (\n // A meeting thread with nothing yet: call-aware, not the upload prompt.\n <div>\n <CallConversationEmpty callExtId={meetingCallExtId} />\n <ProvisionalSpeakers ids={provisionalSpeakers} />\n </div>\n ) : currentTask && currentTask.status != null ? (\n <TaskEmptyState task={currentTask} />\n ) : pendingFirstTurn && isGenerating ? (\n <MessageArea ref={containerRef} messages={pendingFirstTurn} />\n ) : (\n <ConnectedConversationEmpty\n hasDocuments={allWorkspaceDocuments.length > 0}\n onUsePrompt={(text) => {\n session.setDraft(text)\n inputRef?.current?.focus()\n }}\n onAddDocuments={(files) => openUpload?.(files, { source: 'computer' })}\n onUrlsSubmit={uploadUrls}\n onImportFromEmail={\n openUpload ? () => openUpload(undefined, { source: 'email' }) : undefined\n }\n below={<ConnectedConversationStart />}\n />\n )}\n </ConversationMain>\n\n {/* The composer dock: the thread's alerts and bars, then the composer. */}\n <ComposerDock\n floating={\n <ScrollToBottom\n className=\"left-auto right-3 translate-x-0\"\n show={showScrollToBottom}\n onClick={scrollToBottom}\n />\n }\n >\n <ComposerContainer className=\"mx-auto max-w-[49rem] px-3 sm:px-6\">\n {/* A question left without its answer (stopped, reloaded, the backend failed), else a\n send that failed. */}\n {orphanedMessage ? (\n <ConversationAlert\n type={\n messageHistory[messageHistory.length - 1]?.role === 'assistant' &&\n messageHistory[messageHistory.length - 1].status === 'failed'\n ? 'backend-failed'\n : 'orphaned'\n }\n message={orphanedMessage}\n onRetryOrphaned={handleRetryOrphanedMessage}\n />\n ) : hasError && lastFailedMessage ? (\n <ConversationAlert\n type=\"send-failed\"\n errorMessage={lastErrorMessage || undefined}\n onRetrySend={handleRetrySend}\n isRetrying={isGenerating}\n />\n ) : null}\n\n {pendingAnswer && (\n <PendingAnswerBar\n key={pendingAnswer.assistantMessageExtId}\n question={pendingAnswer.request.question}\n options={pendingAnswer.request.options}\n timeoutSeconds={pendingAnswer.request.timeout_seconds}\n onPick={submitAnswer}\n />\n )}\n\n {/* Out-of-band control (pause / resume / status) for the running turn. Hidden while\n ask_user is pending: that flow owns the composer. */}\n {isGenerating && !pendingAnswer && streamingAssistantId && (\n <AgentControlBar\n key={streamingAssistantId}\n assistantMessageExtId={streamingAssistantId}\n agentSteps={streamingMessage?.agentSteps}\n liveTimer={streamingLiveTimer}\n onStop={handleAbortGeneration}\n queuedMessages={queuedUserMessages}\n />\n )}\n\n {meetingReadOnly ? (\n <p\n className=\"py-3 text-center text-sm text-muted-foreground\"\n data-testid=\"meeting-thread-read-only\"\n >\n {READ_ONLY_MEETING_TEXT}\n </p>\n ) : (\n <>\n {documentSwitchPending && (\n <p className=\"mx-3 mb-2 text-sm text-muted-foreground\" role=\"status\">\n Switching this thread\u2019s document\u2026\n </p>\n )}\n {documentSwitchFailed && (\n <div className=\"mx-3 mb-2 text-sm text-destructive\" role=\"status\">\n <p>\n The document switch failed. Check which document this thread will use before\n sending.\n </p>\n <button\n type=\"button\"\n className=\"underline\"\n onClick={() => {\n session.setAutoSendDraft(false)\n switchingDocument.acknowledgeFailure()\n setSwitchState({ scope: scopeKey, pending: false, failed: false })\n }}\n >\n Use the current thread document\n </button>\n </div>\n )}\n {!paMode && differentVisibleDocument && (\n <DocumentTargetNotice\n target={sameTitle ? `${targetTitle} (${turnDocumentId})` : targetTitle!}\n visible={sameTitle ? `${visibleTitle} (${openDocumentId})` : visibleTitle!}\n onSwitch={\n visibleDocument ? () => switchThreadDocument(openDocumentId!) : undefined\n }\n disabled={isGenerating || documentSwitchPending}\n />\n )}\n <ConversationComposer\n handleSendMessage={handleUserSend}\n placeholder={pendingAnswer ? assistant.answerPlaceholder : undefined}\n isGenerating={isGenerating}\n shouldOfferFollowUp={!showScrollToBottom}\n inputRef={inputRef}\n isBranching={isBranching}\n onCancelBranching={session.cancelEditing}\n modelSelector={paMode ? undefined : modelSelector}\n skills={composerSkills}\n onBrowseSkills={browseSkills}\n contextUsage={latestContextUsage}\n isConversationEmpty={messageHistory.length === 0 && !isBranching}\n leftButton={\n paMode ? (\n <PaModeBadge icon={<ArbiBotIcon size={16} className=\"shrink-0\" />} />\n ) : (\n <ComposerAccessories>\n {composerAccessory}\n {threadDocument.unavailable ? (\n <DraftingDocChip\n state=\"unavailable\"\n title=\"\"\n disabled={isGenerating || documentSwitchPending}\n onDetach={() => switchThreadDocument(null)}\n />\n ) : draftingDocument ? (\n <DraftingDocChip\n title={getDocumentTitle(draftingDocument)}\n disabled={isGenerating || documentSwitchPending}\n onDetach={\n threadDocument.documentId ? () => switchThreadDocument(null) : undefined\n }\n />\n ) : (\n attachableDocument && (\n <DraftingDocChip\n state=\"attach\"\n title={getDocumentTitle(attachableDocument)}\n disabled={isGenerating || documentSwitchPending}\n onAttach={() => switchThreadDocument(attachableDocument.external_id)}\n />\n )\n )}\n </ComposerAccessories>\n )\n }\n rightButton={\n <ComposerTools>\n {composerTools}\n <MicButton inputRef={inputRef} />\n <ConversationSendButton\n onClick={handleUserSend}\n disabled={documentSwitchPending}\n hasOrphanedMessage={!isGenerating && orphanedMessage !== null}\n />\n </ComposerTools>\n }\n />\n </>\n )}\n </ComposerContainer>\n </ComposerDock>\n {slashWorkflows.launcher}\n </ConversationBody>\n )\n}\n\n/**\n * The open conversation's thread, connected: its messages and the composer, with no tabs or history\n * around it. `ConnectedConversationPage` is the same thread in the tabbed workspace page.\n */\nexport function ConnectedConversationThread({\n conversationId,\n modelSelector,\n}: ConnectedConversationThreadProps) {\n const session = useArbiSessionStore()\n useEffect(() => {\n if (conversationId === undefined) return\n if (session.getState().conversationId !== conversationId) {\n session.setConversationId(conversationId)\n }\n }, [conversationId, session])\n return <ConversationThread modelSelector={modelSelector} />\n}\n"],
|
|
5
|
+
"mappings": ";AA6kBU,SAqHE,UArHF,KAGE,YAHF;AApkBV;AAAA,EACE,mBAAmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,wBAAwB;AACjC,SAAS,mBAAmB,mBAAmB,wBAAwB;AAEvE,SAAS,aAAa,WAAW,SAAS,QAAQ,gBAAgC;AAClF,SAAS,0BAA0B;AACnC,SAAS,qBAAqB,eAAe,mBAAmB;AAChE,SAAS,mBAAmB,cAAc,sBAAsB;AAChE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AACjC,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,8BAA8B;AACvC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,4BAA4B;AACrC,SAAS,8BAA8B;AACvC,SAAS,sBAAsB;AAC/B,SAAS,kCAAkC;AAC3C,SAAS,8BAA8B;AACvC,SAAS,uBAAuB;AAChC,SAAS,uBAAuB;AAChC,SAAS,kCAAkC;AAC3C,SAAS,wBAAwB,mBAAmB;AACpD,SAAS,yBAAyB;AAClC,SAAS,4BAA4B;AACrC,SAAS,4BAA4B;AACrC,SAAS,2BAA2B,qBAAqB;AACzD,SAAS,8BAA8B;AACvC,SAAS,iBAAiB;AAE1B,SAAS,gCAAgC;AACzC,SAAS,uBAAuB;AAkBzB,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,eAAe,OAAuB,IAAI;AAChD,QAAM,WAAW,OAA4B,IAAI;AACjD,QAAM,UAAU,oBAAoB;AACpC,QAAM,cAAc,qBAAqB;AACzC,QAAM,EAAE,QAAQ,YAAY,kBAAkB,IAAI;AAGlD,QAAM,0BAA0B,oBAAoB,CAAC,UAAU,MAAM,UAAU;AAC/E,QAAM,EAAE,MAAM,aAAa,IAAI,gBAAgB;AAE/C,QAAM,wBAAwB,oBAAoB,CAAC,UAAU,MAAM,cAAc;AAEjF,QAAM,EAAE,cAAc,IAAI,qBAAqB;AAC/C,QAAM,cAAc,wBAChB,cAAc,KAAK,CAAC,MAAM,EAAE,gBAAgB,qBAAqB,IACjE;AAIJ,QAAM,uBAAuB,wBACxB,wBAAwB,qBAAqB,GAAG,wBAAwB,OACzE;AAEJ,QAAM,mBAAmB,oBAAoB,CAAC,UAAU,MAAM,gBAAgB;AAE9E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,oBAAoB;AAIxB,sBAAoB,uBAAuB,cAAc;AAIzD,QAAM,mBAAmB;AAAA,IACvB,MACE,uBACK,eAA6B,KAAK,CAAC,MAAM,EAAE,gBAAgB,oBAAoB,IAChF;AAAA,IACN,CAAC,gBAAgB,oBAAoB;AAAA,EACvC;AACA,QAAM,qBAAqB;AAAA,IACzB,MACG,eACE,OAAO,CAAC,YAAY,QAAQ,SAAS,UAAU,QAAQ,WAAW,QAAQ,EAC1E,IAAI,CAAC,EAAE,aAAa,QAAQ,OAAO,EAAE,aAAa,QAAQ,EAAE;AAAA,IACjE,CAAC,cAAc;AAAA,EACjB;AACA,QAAM,qBAAqB;AAAA,IACzB,MACE,mBACI;AAAA,MACE,gBAAgB,iBAAiB;AAAA,MACjC,WAAW,iBAAiB;AAAA,MAC5B,QAAQ;AAAA,MACR,cAAc;AAAA,IAChB,IACA;AAAA,IACN,CAAC,gBAAgB;AAAA,EACnB;AAKA,QAAM,gBAAgB,QAAQ,MAAM;AAClC,aAAS,IAAI,eAAe,SAAS,GAAG,KAAK,GAAG,KAAK;AACnD,YAAM,IAAI,eAAe,CAAC;AAC1B,UAAI,EAAE,SAAS,eAAe,EAAE,kBAAkB;AAChD,eAAO;AAAA,UACL,SAAS,EAAE;AAAA,UACX,uBAAuB,EAAE;AAAA,UACzB,mBAAmB,EAAE;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,cAAc,CAAC;AAGnB,QAAM,iBAAiB,uBAAuB;AAC9C,QAAM,eAAe;AAAA,IACnB,OAAO,WAAmB;AACxB,YAAM,UAAU,OAAO,KAAK;AAC5B,UAAI,CAAC,iBAAiB,CAAC,QAAS;AAChC,cAAQ,SAAS,EAAE;AACnB,UAAI;AACF,cAAM,eAAe,eAAe,OAAO;AAAA,MAC7C,SAAS,KAAK;AACZ,gBAAQ,MAAM,0BAA0B,GAAG;AAC3C,eAAO,8BAA8B,OAAO;AAAA,MAC9C;AAAA,IACF;AAAA,IACA,CAAC,eAAe,gBAAgB,SAAS,MAAM;AAAA,EACjD;AAGA,QAAM,EAAE,MAAM,wBAAwB,CAAC,GAAG,WAAW,4BAA4B,IAC/E,aAAa;AAGf,QAAM,gBAAgB,QAAQ,MAAM;AAClC,QAAI,CAAC,mBAAmB,CAAC,eAAgB,QAAO;AAChD,WAAO,eAAe,KAAK,CAAC,MAAM,EAAE,gBAAgB,eAAe;AAAA,EACrE,GAAG,CAAC,iBAAiB,cAAc,CAAC;AACpC,QAAM,mBAAmB,eAAe,iBAAiB,cAAc,eAAe;AACtF,QAAM,EAAE,MAAM,aAAa,IAAI,UAAU,kBAAkB,EAAE,SAAS,CAAC,CAAC,iBAAiB,CAAC;AAK1F,YAAU,MAAM;AACd,eAAW,CAAC,QAAQ,QAAQ,KAAK,OAAO,QAAQ,uBAAuB,GAAG;AACxE,UAAI,CAAC,SAAS,aAAc;AAC5B,YAAM,OAAO,cAAc,KAAK,CAAC,MAAM,EAAE,gBAAgB,MAAM;AAC/D,UAAI,CAAC,MAAM,oBAAqB;AAChC,UAAI,KAAK,wBAAwB,eAAe,KAAK,wBAAwB,UAAU;AACrF,gBAAQ,0BAA0B,QAAQ,OAAO,IAAI;AAAA,MACvD;AAAA,IACF;AAAA,EACF,GAAG,CAAC,eAAe,yBAAyB,OAAO,CAAC;AAOpD,YAAU,MAAM;AACd,QAAI,CAAC,gBAAiB;AACtB,UAAM,YAAY,gBAAgB,KAAK,CAAC,MAAM,EAAE,gBAAgB,eAAe;AAC/E,QAAI,WAAW,iBAAiB,gBAAgB,cAAc,cAAc;AAC1E,cAAQ,iBAAiB,mBAAmB,YAAY,CAAC;AACzD,cAAQ,aAAa,UAAU,aAAa;AAAA,IAC9C;AAAA,EAEF,GAAG,CAAC,eAAe,CAAC;AAIpB,QAAM,uBAAuB,wBAAwB;AACrD,QAAM,gBACJ,wBAAwB,aAAa,mBAAmB,cAAc,cAAc;AAGtF,QAAM,UAAU,iBAAiB,MAAM;AACvC,QAAM,kBAAkB,WAAW,CAAC,CAAC,aAAa;AAClD,QAAM,mBAAmB,aAAa,uBAAuB;AAC7D,QAAM,iBAAiB,yBAAyB,kBAAkB,cAAc;AAEhF,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAwB,IAAI;AAC1E,QAAM,mBAAmB,eAAe,EAAE,MAAM,eAAe;AAC/D,QAAM,mBAAmB;AAAA,IACvB,MAAO,kBAAkB,sBAAsB,iBAAiB,gBAAgB,IAAI;AAAA,IACpF,CAAC,iBAAiB,gBAAgB;AAAA,EACpC;AACA,QAAM,aAAa,eAAe;AAAA,IAChC,YAAY,CAAC,UAAU,aAAa,OAAO,EAAE,QAAQ,WAAW,CAAC;AAAA,EACnE,CAAC;AAED,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,oBAAoB,EAAE,qBAAqB,gBAAgB,CAAC;AAChE,QAAM,iBAAiB,YAAY,EAAE,cAAc,mBAAmB,CAAC;AAGvE,QAAM,SAAS,oBAAoB,CAAC,UAAU,MAAM,MAAM;AAC1D,YAAU,MAAM;AACd,QAAI,eAAe,WAAW,EAAG;AACjC,UAAM,YAAY,eAAe;AAAA,MAC/B,CAAC,MACC,EAAE,SAAS,UAAU,EAAE,SAAS,oBAAqB,EAAE;AAAA,IAC3D;AACA,QAAI,cAAc,OAAQ,SAAQ,UAAU,SAAS;AAAA,EACvD,GAAG,CAAC,gBAAgB,QAAQ,OAAO,CAAC;AAGpC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAwC,KAAK;AACnF,YAAU,MAAM,eAAe,KAAK,GAAG,CAAC,qBAAqB,CAAC;AAC9D,QAAM,sBAAsB,QAAQ,MAAM;AACxC,QAAI,CAAC,oBAAoB,gBAAgB,MAAO,QAAO;AACvD,UAAM,SAAS,CAAC,MACd,CAAC,CAAC,oBAAoB,EAAE,SAAS,EAAE,MAAM,KAAK;AAChD,WAAO,eAAe,OAAO,CAAC,MAAO,gBAAgB,eAAe,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAE;AAAA,EAC7F,GAAG,CAAC,kBAAkB,aAAa,cAAc,CAAC;AAClD,QAAM,sBAAsB;AAAA,IAC1B,MACE,mBACI,eAAe,OAAO,CAAC,MAAM,oBAAoB,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC,EAAE,SAC5E;AAAA,IACN,CAAC,kBAAkB,cAAc;AAAA,EACnC;AAGA,QAAM,kBAAkB,QAAQ,MAAM;AACpC,QAAI,CAAC,iBAAkB,QAAO;AAC9B,UAAM,YAAY,oBAAoB,UAAU,CAAC,MAAM,EAAE,gBAAgB,gBAAgB;AACzF,QAAI,YAAY,EAAG,QAAO;AAC1B,WAAO,oBAAoB,MAAM,GAAG,SAAS;AAAA,EAC/C,GAAG,CAAC,qBAAqB,gBAAgB,CAAC;AAE1C,QAAM,oBAAoB;AAAA,IACxB,MAAM,qBAAqB,mBAAmB,kBAAkB,CAAC,CAAC;AAAA,IAClE,CAAC,kBAAkB,eAAe;AAAA,EACpC;AAEA,QAAM,cAAc;AAAA,IAClB,MACE,eAAe,QAAQ,CAAC,MAAM;AAC5B,YAAM,MAAM,oBAAoB,EAAE,SAAS,EAAE,MAAM,KAAK;AACxD,aAAO,MACH;AAAA,QACE;AAAA,UACE,WAAW,IAAI;AAAA,UACf,IAAI,KAAK,MAAM,IAAI,cAAc,EAAE,cAAc,EAAE,KAAK;AAAA,QAC1D;AAAA,MACF,IACA,CAAC;AAAA,IACP,CAAC;AAAA,IACH,CAAC,cAAc;AAAA,EACjB;AACA,QAAM,sBAAsB,uBAAuB,kBAAkB,WAAW;AAChF,QAAM,kBAAkB,CAAC,CAAC,oBAAoB,gBAAgB;AAM9D,QAAM,qBAAqB,QAAQ,MAAM;AACvC,UAAM,WAAW;AACjB,aAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,YAAM,MAAM,SAAS,CAAC;AACtB,UAAI,IAAI,SAAS,YAAa;AAC9B,UAAI,IAAI,kBAAmB,QAAO,IAAI;AACtC,UAAI,CAAC,IAAI,WAAY;AACrB,eAAS,IAAI,IAAI,WAAW,SAAS,GAAG,KAAK,GAAG,KAAK;AACnD,YAAI,IAAI,WAAW,CAAC,EAAE,QAAS,QAAO,IAAI,WAAW,CAAC,EAAE;AAAA,MAC1D;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,cAAc,CAAC;AAGnB,QAAM,wBAAwB,QAAQ,MAAM;AAC1C,QAAI,CAAC,iBAAkB,QAAO;AAC9B,UAAM,YAAY,eAAe,KAAK,CAAC,MAAM,EAAE,gBAAgB,gBAAgB;AAC/E,WAAO,WAAW,yBAAyB;AAAA,EAC7C,GAAG,CAAC,kBAAkB,cAAc,CAAC;AAErC,QAAM,cAAc,CAAC,CAAC;AAGtB,QAAM,mCAAmC,YAAY,YAAY;AAC/D,UAAMA,mBAAkB,uBAAuB,gBAAgB,cAAc,aAAa;AAC1F,UAAM,eAAe,YAAY,QAAQ,SAAS,CAAC,EAAE,KAAK;AAE1D,QAAIA,kBAAiB;AAEnB,UAAI,iBAAiB,IAAI;AACvB,cAAM;AAAA,UACJA,iBAAgB;AAAA,UAChBA,iBAAgB,yBAAyB;AAAA,UACzCA,iBAAgB;AAAA,QAClB;AACA;AAAA,MACF;AAGA,YAAM;AAAA,QACJ;AAAA,QACAA,iBAAgB,yBAAyB;AAAA,QACzCA,iBAAgB;AAAA,MAClB;AACA,cAAQ,SAAS,EAAE;AACnB;AAAA,IACF;AAGA,UAAM,kBAAkB;AAAA,EAC1B,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAGD,QAAM,2BAA2B,YAAY,YAAY;AACvD,QAAI,eAAe,uBAAuB;AACxC,YAAM,eAAe,YAAY,QAAQ,SAAS,CAAC,EAAE,KAAK;AAC1D,UAAI,CAAC,aAAc;AAGnB,YAAM,YAAY,eAAe,UAAU,CAAC,MAAM,EAAE,gBAAgB,gBAAgB;AACpF,UAAI,aAAa,GAAG;AAClB,eAAO,KAAK,QAAQ,SAAS,EAAE,aAAa,EAAE,QAAQ,CAAC,QAAQ;AAC7D,gBAAM,WAAW,SAAS,GAAG;AAC7B,cAAI,CAAC,MAAM,QAAQ,KAAK,WAAW,UAAW,SAAQ,kBAAkB,GAAG;AAAA,QAC7E,CAAC;AAAA,MACH;AAEA,cAAQ,gBAAgB;AACxB,cAAQ,SAAS,EAAE;AACnB,YAAM,mBAAmB,uBAAuB,YAAY;AAC5D;AAAA,IACF;AAEA,UAAM,iCAAiC;AAAA,EACzC,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAID,QAAM,qBAAqB,YAAY,MAAM;AAC3C,UAAM,QAAQ,YAAY,QAAQ,SAAS,CAAC;AAC5C,QAAI,eAAe;AACjB,mBAAa,KAAK;AAClB;AAAA,IACF;AAEA,QAAI,CAAC,sBAAuB,oBAAmB,MAAM,KAAK,CAAC;AAC3D,6BAAyB;AAAA,EAC3B,GAAG,CAAC,eAAe,uBAAuB,cAAc,0BAA0B,OAAO,CAAC;AAI1F,YAAU,MAAM;AACd,QAAI,CAAC,aAAc,oBAAmB,IAAI;AAAA,EAC5C,GAAG,CAAC,YAAY,CAAC;AAKjB,QAAM,iBAAiB,uBAAuB,EAAE,SAAS,eAAe,CAAC;AAEzE,QAAM,iBAAiB;AAAA,IACrB,OAAO,EAAE,SAAS,eAAe,QAAQ;AAAA,IACzC,CAAC,eAAe,OAAO;AAAA,EACzB;AACA,QAAM,eAAe;AAAA,IACnB,MAAO,oBAAoB,MAAM,kBAAkB,IAAI;AAAA,IACvD,CAAC,iBAAiB;AAAA,EACpB;AAEA,QAAM,EAAE,oBAAoB,eAAe,IAAI,gBAAgB;AAAA,IAC7D;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,WAAW,KAAK,UAAU,CAAC,qBAAqB,qBAAqB,CAAC;AAC5E,QAAM,uBAAuB;AAAA,IAC3B,oBAAI,IAA0D;AAAA,EAChE;AACA,MAAI,CAAC,qBAAqB,QAAQ,IAAI,QAAQ,GAAG;AAC/C,yBAAqB,QAAQ,IAAI,UAAU,0BAA0B,CAAC;AAAA,EACxE;AACA,QAAM,oBAAoB,qBAAqB,QAAQ,IAAI,QAAQ;AACnE,QAAM,CAAC,EAAE,cAAc,IAAI,SAAS,EAAE,OAAO,UAAU,SAAS,OAAO,QAAQ,MAAM,CAAC;AACtF,QAAM,wBAAwB,kBAAkB,UAAU;AAC1D,QAAM,uBAAuB,kBAAkB,UAAU;AACzD,QAAM,iBAAiB,YAAY,MAAM;AACvC,QAAI,kBAAkB,UAAU,EAAG;AACnC,QAAI,kBAAkB,UAAU,GAAG;AACjC,cAAQ,iBAAiB,KAAK;AAC9B,wBAAkB,mBAAmB;AACrC,qBAAe,EAAE,OAAO,UAAU,SAAS,OAAO,QAAQ,MAAM,CAAC;AAAA,IACnE;AACA,UAAM,QAAQ,YAAY,QAAQ,SAAS,CAAC;AAC5C,QAAI,CAAC,iBAAiB,eAAe,aAAa,KAAK,GAAG;AACxD,cAAQ,SAAS,EAAE;AACnB;AAAA,IACF;AAEA,QAAI,sBAAsB,EAAG;AAG7B,mBAAe;AACf,uBAAmB;AAAA,EACrB,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAGD,YAAU,MAAM;AACd,QAAI,oBAAoB,SAAS,SAAS;AACxC,YAAM,WAAW,SAAS;AAC1B,eAAS,MAAM;AACf,YAAM,MAAM,SAAS,MAAM;AAC3B,eAAS,kBAAkB,KAAK,GAAG;AAAA,IACrC;AAAA,EACF,GAAG,CAAC,gBAAgB,CAAC;AAMrB,QAAM,iBAAiB,kBAAkB;AACzC,QAAM,iBAAiB,kBAAkB;AAAA,IACvC,iBAAiB,eAAe;AAAA,IAChC,gBAAgB;AAAA,IAChB,aAAa;AAAA,EACf,CAAC;AACD,QAAM,YAAY,iBAAiB;AACnC,QAAM,iBAAiB,kBAAkB,EAAE,aAAa,oBAAoB,CAAC;AAC7E,QAAM,eAAe,CAAC,OACpB,KAAK,uBAAuB,KAAK,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI;AAClE,QAAM,mBAAmB,aAAa,cAAc;AACpD,QAAM,qBAAqB,iBAAiB,SAAY,aAAa,cAAc;AACnF,QAAM,2BAA2B;AAAA,IAC/B,kBAAkB,kBAAkB,mBAAmB;AAAA,EACzD;AACA,QAAM,cAAc,mBAAmB,iBAAiB,gBAAgB,IAAI;AAC5E,QAAM,kBAAkB,aAAa,cAAc;AACnD,QAAM,eAAe,kBAAkB,iBAAiB,eAAe,IAAI;AAC3E,QAAM,YAAY,eAAe,gBAAgB,gBAAgB;AACjE,QAAM,uBAAuB,CAAC,eAA8B;AAC1D,QAAI,gBAAgB,kBAAkB,UAAU,EAAG;AACnD,UAAM,YAAY,MAAM;AACtB,YAAM,QAAQ,QAAQ,SAAS;AAC/B,aACE,MAAM,gBAAgB,uBAAuB,MAAM,mBAAmB;AAAA,IAE1E;AACA,mBAAe,EAAE,OAAO,UAAU,SAAS,MAAM,QAAQ,MAAM,CAAC;AAChE,SAAK;AAAA,MACH;AAAA,MACA,MAAM,eAAe,KAAK,UAAU;AAAA,MACpC;AAAA,MACA,CAAC,YAAY,eAAe,EAAE,OAAO,UAAU,SAAS,QAAQ,MAAM,CAAC;AAAA,MACvE,MAAM;AACJ,uBAAe,EAAE,OAAO,UAAU,SAAS,OAAO,QAAQ,KAAK,CAAC;AAChE,gBAAQ,iBAAiB,KAAK;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAGA,qBAAmB;AAAA,IACjB;AAAA,IACA;AAAA,IACA,YACE,CAAC,uBAAuB,QAAQ,mBAAmB,gBAAgB,UAAU,YAAY;AAAA,EAC7F,CAAC;AAMD;AAAA,IACE;AAAA,IACA,CAAC,+BAA+B,CAAC,yBAAyB,CAAC;AAAA,IAC3D,MAAM,CAAC,kBAAkB,UAAU;AAAA,EACrC;AAEA,yBAAuB;AAEvB,QAAM,kBAAkB,uBAAuB,gBAAgB,cAAc,aAAa;AAE1F,SACE,qBAAC,oBACC;AAAA,wBAAC,oBAAiB,eAAa,gBAAgB,qBAAqB,IACjE,2BACC,oBAAC,uBAAoB,IACnB,eAAe,SAAS,KAAK,cAC/B,oBAAC,gBAAgB,UAAhB,EAAyB,OAAO,gBAC/B,+BAAC,sBAAsB,UAAtB,EAA+B,OAAO,mBACpC;AAAA,0BAAoB,sBAAsB,KACzC,oBAAC,SAAI,WAAU,4BACb;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP,UAAU;AAAA,UACV,SAAS;AAAA,YACP,EAAE,OAAO,OAAO,OAAO,MAAM;AAAA,YAC7B,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,cAAc;AAAA,YACtD;AAAA,cACE,OAAO;AAAA,cACP,OAAO;AAAA,cACP,OAAO;AAAA,cACP,QAAQ;AAAA,YACV;AAAA,UACF;AAAA;AAAA,MACF,GACF;AAAA,MAEF,oBAAC,eAAY,KAAK,cAAc,UAAU,iBAAiB;AAAA,MAC1D,mBAAmB,oBAAC,uBAAoB,KAAK,qBAAqB;AAAA,OACrE,GACF,IACE;AAAA;AAAA,MAEF,qBAAC,SACC;AAAA,4BAAC,yBAAsB,WAAW,kBAAkB;AAAA,QACpD,oBAAC,uBAAoB,KAAK,qBAAqB;AAAA,SACjD;AAAA,QACE,eAAe,YAAY,UAAU,OACvC,oBAAC,kBAAe,MAAM,aAAa,IACjC,oBAAoB,eACtB,oBAAC,eAAY,KAAK,cAAc,UAAU,kBAAkB,IAE5D;AAAA,MAAC;AAAA;AAAA,QACC,cAAc,sBAAsB,SAAS;AAAA,QAC7C,aAAa,CAAC,SAAS;AACrB,kBAAQ,SAAS,IAAI;AACrB,oBAAU,SAAS,MAAM;AAAA,QAC3B;AAAA,QACA,gBAAgB,CAAC,UAAU,aAAa,OAAO,EAAE,QAAQ,WAAW,CAAC;AAAA,QACrE,cAAc;AAAA,QACd,mBACE,aAAa,MAAM,WAAW,QAAW,EAAE,QAAQ,QAAQ,CAAC,IAAI;AAAA,QAElE,OAAO,oBAAC,8BAA2B;AAAA;AAAA,IACrC,GAEJ;AAAA,IAGA;AAAA,MAAC;AAAA;AAAA,QACC,UACE;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAM;AAAA,YACN,SAAS;AAAA;AAAA,QACX;AAAA,QAGF,+BAAC,qBAAkB,WAAU,sCAG1B;AAAA,4BACC;AAAA,YAAC;AAAA;AAAA,cACC,MACE,eAAe,eAAe,SAAS,CAAC,GAAG,SAAS,eACpD,eAAe,eAAe,SAAS,CAAC,EAAE,WAAW,WACjD,mBACA;AAAA,cAEN,SAAS;AAAA,cACT,iBAAiB;AAAA;AAAA,UACnB,IACE,YAAY,oBACd;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAc,oBAAoB;AAAA,cAClC,aAAa;AAAA,cACb,YAAY;AAAA;AAAA,UACd,IACE;AAAA,UAEH,iBACC;AAAA,YAAC;AAAA;AAAA,cAEC,UAAU,cAAc,QAAQ;AAAA,cAChC,SAAS,cAAc,QAAQ;AAAA,cAC/B,gBAAgB,cAAc,QAAQ;AAAA,cACtC,QAAQ;AAAA;AAAA,YAJH,cAAc;AAAA,UAKrB;AAAA,UAKD,gBAAgB,CAAC,iBAAiB,wBACjC;AAAA,YAAC;AAAA;AAAA,cAEC,uBAAuB;AAAA,cACvB,YAAY,kBAAkB;AAAA,cAC9B,WAAW;AAAA,cACX,QAAQ;AAAA,cACR,gBAAgB;AAAA;AAAA,YALX;AAAA,UAMP;AAAA,UAGD,kBACC;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,eAAY;AAAA,cAEX;AAAA;AAAA,UACH,IAEA,iCACG;AAAA,qCACC,oBAAC,OAAE,WAAU,2CAA0C,MAAK,UAAS,yDAErE;AAAA,YAED,wBACC,qBAAC,SAAI,WAAU,sCAAqC,MAAK,UACvD;AAAA,kCAAC,OAAE,mGAGH;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAU;AAAA,kBACV,SAAS,MAAM;AACb,4BAAQ,iBAAiB,KAAK;AAC9B,sCAAkB,mBAAmB;AACrC,mCAAe,EAAE,OAAO,UAAU,SAAS,OAAO,QAAQ,MAAM,CAAC;AAAA,kBACnE;AAAA,kBACD;AAAA;AAAA,cAED;AAAA,eACF;AAAA,YAED,CAAC,UAAU,4BACV;AAAA,cAAC;AAAA;AAAA,gBACC,QAAQ,YAAY,GAAG,WAAW,KAAK,cAAc,MAAM;AAAA,gBAC3D,SAAS,YAAY,GAAG,YAAY,KAAK,cAAc,MAAM;AAAA,gBAC7D,UACE,kBAAkB,MAAM,qBAAqB,cAAe,IAAI;AAAA,gBAElE,UAAU,gBAAgB;AAAA;AAAA,YAC5B;AAAA,YAEF;AAAA,cAAC;AAAA;AAAA,gBACC,mBAAmB;AAAA,gBACnB,aAAa,gBAAgB,UAAU,oBAAoB;AAAA,gBAC3D;AAAA,gBACA,qBAAqB,CAAC;AAAA,gBACtB;AAAA,gBACA;AAAA,gBACA,mBAAmB,QAAQ;AAAA,gBAC3B,eAAe,SAAS,SAAY;AAAA,gBACpC,QAAQ;AAAA,gBACR,gBAAgB;AAAA,gBAChB,cAAc;AAAA,gBACd,qBAAqB,eAAe,WAAW,KAAK,CAAC;AAAA,gBACrD,YACE,SACE,oBAAC,eAAY,MAAM,oBAAC,eAAY,MAAM,IAAI,WAAU,YAAW,GAAI,IAEnE,qBAAC,uBACE;AAAA;AAAA,kBACA,eAAe,cACd;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAM;AAAA,sBACN,OAAM;AAAA,sBACN,UAAU,gBAAgB;AAAA,sBAC1B,UAAU,MAAM,qBAAqB,IAAI;AAAA;AAAA,kBAC3C,IACE,mBACF;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO,iBAAiB,gBAAgB;AAAA,sBACxC,UAAU,gBAAgB;AAAA,sBAC1B,UACE,eAAe,aAAa,MAAM,qBAAqB,IAAI,IAAI;AAAA;AAAA,kBAEnE,IAEA,sBACE;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAM;AAAA,sBACN,OAAO,iBAAiB,kBAAkB;AAAA,sBAC1C,UAAU,gBAAgB;AAAA,sBAC1B,UAAU,MAAM,qBAAqB,mBAAmB,WAAW;AAAA;AAAA,kBACrE;AAAA,mBAGN;AAAA,gBAGJ,aACE,qBAAC,iBACE;AAAA;AAAA,kBACD,oBAAC,aAAU,UAAoB;AAAA,kBAC/B;AAAA,oBAAC;AAAA;AAAA,sBACC,SAAS;AAAA,sBACT,UAAU;AAAA,sBACV,oBAAoB,CAAC,gBAAgB,oBAAoB;AAAA;AAAA,kBAC3D;AAAA,mBACF;AAAA;AAAA,YAEJ;AAAA,aACF;AAAA,WAEJ;AAAA;AAAA,IACF;AAAA,IACC,eAAe;AAAA,KAClB;AAEJ;AAMO,SAAS,4BAA4B;AAAA,EAC1C;AAAA,EACA;AACF,GAAqC;AACnC,QAAM,UAAU,oBAAoB;AACpC,YAAU,MAAM;AACd,QAAI,mBAAmB,OAAW;AAClC,QAAI,QAAQ,SAAS,EAAE,mBAAmB,gBAAgB;AACxD,cAAQ,kBAAkB,cAAc;AAAA,IAC1C;AAAA,EACF,GAAG,CAAC,gBAAgB,OAAO,CAAC;AAC5B,SAAO,oBAAC,sBAAmB,eAA8B;AAC3D;",
|
|
6
6
|
"names": ["orphanedMessage"]
|
|
7
7
|
}
|
|
@@ -2,6 +2,7 @@ export interface ConversationSendButtonProps {
|
|
|
2
2
|
onClick: () => void;
|
|
3
3
|
/** The thread ends in a question with no answer: an empty composer offers to retry it. */
|
|
4
4
|
hasOrphanedMessage: boolean;
|
|
5
|
+
disabled?: boolean;
|
|
5
6
|
}
|
|
6
7
|
/**
|
|
7
8
|
* The composer's send button. It subscribes to the draft itself, so the conversation does not
|
|
@@ -6,7 +6,8 @@ import { hasMessageBody, useAssistantName } from "@arbidocs/react/shell";
|
|
|
6
6
|
import { ComposerSend } from "../../chat/Composer.js";
|
|
7
7
|
const ConversationSendButton = memo(function ConversationSendButton2({
|
|
8
8
|
onClick,
|
|
9
|
-
hasOrphanedMessage
|
|
9
|
+
hasOrphanedMessage,
|
|
10
|
+
disabled = false
|
|
10
11
|
}) {
|
|
11
12
|
const draftMessage = useArbiSessionState(selectDraft);
|
|
12
13
|
const assistantName = useAssistantName();
|
|
@@ -17,7 +18,7 @@ const ConversationSendButton = memo(function ConversationSendButton2({
|
|
|
17
18
|
{
|
|
18
19
|
onSend: onClick,
|
|
19
20
|
isRetry: showRetryIcon,
|
|
20
|
-
disabled: !showRetryIcon && !hasMessageBody(draftMessage, recipients)
|
|
21
|
+
disabled: disabled || !showRetryIcon && !hasMessageBody(draftMessage, recipients)
|
|
21
22
|
}
|
|
22
23
|
);
|
|
23
24
|
});
|