@arbidocs/blocks 0.5.112 → 0.5.114
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-KUF6RX76.cjs → ConnectedCallDock-2KXEQENS.cjs} +26 -26
- package/dist/{ConnectedCallDock-KUF6RX76.cjs.map → ConnectedCallDock-2KXEQENS.cjs.map} +1 -1
- package/dist/{ConnectedCallRoom-ZKIYB2JG.cjs → ConnectedCallRoom-MU3NPNXF.cjs} +18 -18
- package/dist/{ConnectedCallRoom-ZKIYB2JG.cjs.map → ConnectedCallRoom-MU3NPNXF.cjs.map} +1 -1
- package/dist/{ConnectedMailInviteCard-P65MQM6J.cjs → ConnectedMailInviteCard-EINB3THA.cjs} +5 -5
- package/dist/{ConnectedMailInviteCard-P65MQM6J.cjs.map → ConnectedMailInviteCard-EINB3THA.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-S4RKDH2A.cjs → ConnectedNativeDocxComparison-VH3I65H6.cjs} +21 -21
- package/dist/{ConnectedNativeDocxComparison-S4RKDH2A.cjs.map → ConnectedNativeDocxComparison-VH3I65H6.cjs.map} +1 -1
- package/dist/{ConnectedProductionSetDialog-HX4HTQ3Z.cjs → ConnectedProductionSetDialog-4EAY6KAZ.cjs} +8 -8
- package/dist/{ConnectedProductionSetDialog-HX4HTQ3Z.cjs.map → ConnectedProductionSetDialog-4EAY6KAZ.cjs.map} +1 -1
- package/dist/{ConnectedStreamedWordArtifact-A2A7Z3TT.cjs → ConnectedStreamedWordArtifact-KQSHCA75.cjs} +21 -21
- package/dist/{ConnectedStreamedWordArtifact-A2A7Z3TT.cjs.map → ConnectedStreamedWordArtifact-KQSHCA75.cjs.map} +1 -1
- package/dist/{DocumentReviewCard-4A7NF474.cjs → DocumentReviewCard-OCPFVMLD.cjs} +22 -22
- package/dist/{DocumentReviewCard-4A7NF474.cjs.map → DocumentReviewCard-OCPFVMLD.cjs.map} +1 -1
- package/dist/{FilesViewerDialog-PKCBZXDG.cjs → FilesViewerDialog-BAGOEMXW.cjs} +54 -54
- package/dist/{FilesViewerDialog-PKCBZXDG.cjs.map → FilesViewerDialog-BAGOEMXW.cjs.map} +1 -1
- package/dist/{WorkspaceTableView-J3C6VH4T.cjs → WorkspaceTableView-IMAZICIZ.cjs} +9 -9
- package/dist/{WorkspaceTableView-J3C6VH4T.cjs.map → WorkspaceTableView-IMAZICIZ.cjs.map} +1 -1
- package/dist/agents/index.cjs +298 -298
- package/dist/{ai-OYTFPMXI.cjs → ai-7U4B4CVF.cjs} +27 -27
- package/dist/ai-7U4B4CVF.cjs.map +1 -0
- package/dist/calls/index.cjs +147 -147
- package/dist/chat/index.cjs +29 -29
- package/dist/{chunk-37JPFCCU.cjs → chunk-2W5E62EY.cjs} +6 -6
- package/dist/{chunk-37JPFCCU.cjs.map → chunk-2W5E62EY.cjs.map} +1 -1
- package/dist/{chunk-N6AZYEYL.cjs → chunk-3ODEWSRO.cjs} +4 -4
- package/dist/{chunk-N6AZYEYL.cjs.map → chunk-3ODEWSRO.cjs.map} +1 -1
- package/dist/{chunk-VDFYMVMP.cjs → chunk-3R6YHJ3G.cjs} +4 -4
- package/dist/{chunk-VDFYMVMP.cjs.map → chunk-3R6YHJ3G.cjs.map} +1 -1
- package/dist/{chunk-5RCCZYAE.cjs → chunk-3U36VYMD.cjs} +36 -36
- package/dist/{chunk-5RCCZYAE.cjs.map → chunk-3U36VYMD.cjs.map} +1 -1
- package/dist/{chunk-A4FGU6YC.cjs → chunk-436I7PQL.cjs} +7 -7
- package/dist/{chunk-A4FGU6YC.cjs.map → chunk-436I7PQL.cjs.map} +1 -1
- package/dist/{chunk-J2RXQVVF.cjs → chunk-4EK7TAP7.cjs} +5 -5
- package/dist/{chunk-J2RXQVVF.cjs.map → chunk-4EK7TAP7.cjs.map} +1 -1
- package/dist/{chunk-TP5PGWIO.cjs → chunk-4IOYQLKG.cjs} +3 -3
- package/dist/{chunk-TP5PGWIO.cjs.map → chunk-4IOYQLKG.cjs.map} +1 -1
- package/dist/{chunk-ZQLRWA3Y.cjs → chunk-4NPCDS2X.cjs} +4 -4
- package/dist/{chunk-ZQLRWA3Y.cjs.map → chunk-4NPCDS2X.cjs.map} +1 -1
- package/dist/{chunk-ZEQEIFZJ.cjs → chunk-57EE6CMW.cjs} +24 -24
- package/dist/{chunk-ZEQEIFZJ.cjs.map → chunk-57EE6CMW.cjs.map} +1 -1
- package/dist/{chunk-NMT4UZQM.cjs → chunk-57NHXEU2.cjs} +5 -5
- package/dist/{chunk-NMT4UZQM.cjs.map → chunk-57NHXEU2.cjs.map} +1 -1
- package/dist/{chunk-4QTQS4LS.cjs → chunk-5QUL5BZO.cjs} +5 -5
- package/dist/{chunk-4QTQS4LS.cjs.map → chunk-5QUL5BZO.cjs.map} +1 -1
- package/dist/{chunk-MUA5PJGX.cjs → chunk-5SKHK3BG.cjs} +4 -4
- package/dist/{chunk-MUA5PJGX.cjs.map → chunk-5SKHK3BG.cjs.map} +1 -1
- package/dist/{chunk-AFXDLDPU.cjs → chunk-5UYFLFNR.cjs} +4 -4
- package/dist/{chunk-AFXDLDPU.cjs.map → chunk-5UYFLFNR.cjs.map} +1 -1
- package/dist/{chunk-FJXJ43JO.cjs → chunk-6DCIZA3X.cjs} +101 -101
- package/dist/{chunk-FJXJ43JO.cjs.map → chunk-6DCIZA3X.cjs.map} +1 -1
- package/dist/{chunk-G5TRBLKF.cjs → chunk-7TEUGFIL.cjs} +4 -4
- package/dist/{chunk-G5TRBLKF.cjs.map → chunk-7TEUGFIL.cjs.map} +1 -1
- package/dist/{chunk-ZNZGYSVB.cjs → chunk-7X3FS5HQ.cjs} +39 -39
- package/dist/{chunk-ZNZGYSVB.cjs.map → chunk-7X3FS5HQ.cjs.map} +1 -1
- package/dist/{chunk-DZDARC3V.cjs → chunk-7XT5B2DZ.cjs} +70 -70
- package/dist/{chunk-DZDARC3V.cjs.map → chunk-7XT5B2DZ.cjs.map} +1 -1
- package/dist/{chunk-5UMKMUB5.cjs → chunk-AHT6DQNI.cjs} +68 -68
- package/dist/{chunk-5UMKMUB5.cjs.map → chunk-AHT6DQNI.cjs.map} +1 -1
- package/dist/{chunk-SRET7LYT.cjs → chunk-BW5MF464.cjs} +4 -4
- package/dist/{chunk-SRET7LYT.cjs.map → chunk-BW5MF464.cjs.map} +1 -1
- package/dist/{chunk-NP4EWPIP.cjs → chunk-CJYWHUZR.cjs} +6 -6
- package/dist/{chunk-NP4EWPIP.cjs.map → chunk-CJYWHUZR.cjs.map} +1 -1
- package/dist/{chunk-NTD7VSHO.cjs → chunk-CMGNRMPA.cjs} +4 -4
- package/dist/{chunk-NTD7VSHO.cjs.map → chunk-CMGNRMPA.cjs.map} +1 -1
- package/dist/{chunk-Z3VNKPPH.cjs → chunk-E3Y7RI3J.cjs} +4 -4
- package/dist/{chunk-Z3VNKPPH.cjs.map → chunk-E3Y7RI3J.cjs.map} +1 -1
- package/dist/{chunk-TDO5UWXF.cjs → chunk-E4BLRF2L.cjs} +5 -5
- package/dist/{chunk-TDO5UWXF.cjs.map → chunk-E4BLRF2L.cjs.map} +1 -1
- package/dist/{chunk-WT7CCCIN.cjs → chunk-GNX3FBBX.cjs} +4 -4
- package/dist/{chunk-WT7CCCIN.cjs.map → chunk-GNX3FBBX.cjs.map} +1 -1
- package/dist/{chunk-3NEI27QQ.cjs → chunk-GQXPNIRE.cjs} +14 -14
- package/dist/{chunk-3NEI27QQ.cjs.map → chunk-GQXPNIRE.cjs.map} +1 -1
- package/dist/{chunk-7OPOPYV6.cjs → chunk-H5OLHP2U.cjs} +3 -3
- package/dist/{chunk-7OPOPYV6.cjs.map → chunk-H5OLHP2U.cjs.map} +1 -1
- package/dist/{chunk-IIWJQEBC.cjs → chunk-H7PHOTX2.cjs} +10 -10
- package/dist/{chunk-IIWJQEBC.cjs.map → chunk-H7PHOTX2.cjs.map} +1 -1
- package/dist/{chunk-LQHXUSWZ.cjs → chunk-HQDR43JC.cjs} +6 -6
- package/dist/{chunk-LQHXUSWZ.cjs.map → chunk-HQDR43JC.cjs.map} +1 -1
- package/dist/{chunk-6LQN4BMX.cjs → chunk-IDCD5TEZ.cjs} +5 -5
- package/dist/{chunk-6LQN4BMX.cjs.map → chunk-IDCD5TEZ.cjs.map} +1 -1
- package/dist/{chunk-6YOZKXV6.cjs → chunk-JR2YSBD5.cjs} +4 -4
- package/dist/{chunk-6YOZKXV6.cjs.map → chunk-JR2YSBD5.cjs.map} +1 -1
- package/dist/{chunk-3GYOWDNM.cjs → chunk-JSQQV23D.cjs} +5 -5
- package/dist/{chunk-3GYOWDNM.cjs.map → chunk-JSQQV23D.cjs.map} +1 -1
- package/dist/{chunk-ZFKWCGA5.cjs → chunk-JV5TVUOU.cjs} +4 -4
- package/dist/{chunk-ZFKWCGA5.cjs.map → chunk-JV5TVUOU.cjs.map} +1 -1
- package/dist/{chunk-TXFZAA3R.cjs → chunk-LFRNBT2I.cjs} +23 -23
- package/dist/{chunk-TXFZAA3R.cjs.map → chunk-LFRNBT2I.cjs.map} +1 -1
- package/dist/{chunk-R7CJEIA5.cjs → chunk-LYTIQQQ2.cjs} +3 -3
- package/dist/{chunk-R7CJEIA5.cjs.map → chunk-LYTIQQQ2.cjs.map} +1 -1
- package/dist/{chunk-6UYTG2YG.cjs → chunk-MC4F2URI.cjs} +28 -28
- package/dist/{chunk-6UYTG2YG.cjs.map → chunk-MC4F2URI.cjs.map} +1 -1
- package/dist/{chunk-NNG34ONS.cjs → chunk-MGQSLMTC.cjs} +78 -78
- package/dist/{chunk-NNG34ONS.cjs.map → chunk-MGQSLMTC.cjs.map} +1 -1
- package/dist/{chunk-3Q5L7XVI.cjs → chunk-MZ2KZXNU.cjs} +9 -9
- package/dist/{chunk-3Q5L7XVI.cjs.map → chunk-MZ2KZXNU.cjs.map} +1 -1
- package/dist/{chunk-PJ762EO2.cjs → chunk-NHHEMBXQ.cjs} +24 -24
- package/dist/{chunk-PJ762EO2.cjs.map → chunk-NHHEMBXQ.cjs.map} +1 -1
- package/dist/{chunk-ENUZ35NR.cjs → chunk-P5AQYC4D.cjs} +4 -4
- package/dist/{chunk-ENUZ35NR.cjs.map → chunk-P5AQYC4D.cjs.map} +1 -1
- package/dist/{chunk-5I2VUNZR.cjs → chunk-PGJYD67F.cjs} +6 -6
- package/dist/{chunk-5I2VUNZR.cjs.map → chunk-PGJYD67F.cjs.map} +1 -1
- package/dist/{chunk-BYN7UMC5.cjs → chunk-PL7HUTM3.cjs} +8 -8
- package/dist/{chunk-BYN7UMC5.cjs.map → chunk-PL7HUTM3.cjs.map} +1 -1
- package/dist/{chunk-NOYQ23I7.cjs → chunk-Q6DQGGP4.cjs} +6 -6
- package/dist/{chunk-NOYQ23I7.cjs.map → chunk-Q6DQGGP4.cjs.map} +1 -1
- package/dist/{chunk-T7J352JD.cjs → chunk-QMIHLJMH.cjs} +6 -6
- package/dist/{chunk-T7J352JD.cjs.map → chunk-QMIHLJMH.cjs.map} +1 -1
- package/dist/{chunk-LTEXVRCH.cjs → chunk-SBWIA4PL.cjs} +21 -21
- package/dist/{chunk-LTEXVRCH.cjs.map → chunk-SBWIA4PL.cjs.map} +1 -1
- package/dist/{chunk-ZH7LDZJX.cjs → chunk-TDN33HSK.cjs} +14 -14
- package/dist/{chunk-ZH7LDZJX.cjs.map → chunk-TDN33HSK.cjs.map} +1 -1
- package/dist/{chunk-U5T46QCS.cjs → chunk-TKHCIHE2.cjs} +3 -3
- package/dist/chunk-TKHCIHE2.cjs.map +1 -0
- package/dist/{chunk-WIAWHETB.cjs → chunk-ULPTSXXO.cjs} +4 -4
- package/dist/{chunk-WIAWHETB.cjs.map → chunk-ULPTSXXO.cjs.map} +1 -1
- package/dist/{chunk-GTWEWDIZ.cjs → chunk-UNDQYTRF.cjs} +8 -8
- package/dist/{chunk-GTWEWDIZ.cjs.map → chunk-UNDQYTRF.cjs.map} +1 -1
- package/dist/{chunk-OKHKJ5ML.cjs → chunk-UUENH4BJ.cjs} +11 -11
- package/dist/{chunk-OKHKJ5ML.cjs.map → chunk-UUENH4BJ.cjs.map} +1 -1
- package/dist/{chunk-K5MYEWD5.cjs → chunk-UZHWXKS6.cjs} +7 -7
- package/dist/{chunk-K5MYEWD5.cjs.map → chunk-UZHWXKS6.cjs.map} +1 -1
- package/dist/{chunk-QVHP4R7T.cjs → chunk-V5IMYLYK.cjs} +29 -29
- package/dist/{chunk-QVHP4R7T.cjs.map → chunk-V5IMYLYK.cjs.map} +1 -1
- package/dist/{chunk-XW524KUX.cjs → chunk-VJCSEMXT.cjs} +4 -4
- package/dist/{chunk-XW524KUX.cjs.map → chunk-VJCSEMXT.cjs.map} +1 -1
- package/dist/{chunk-B5442TKX.cjs → chunk-VRK3IQAP.cjs} +4 -4
- package/dist/{chunk-B5442TKX.cjs.map → chunk-VRK3IQAP.cjs.map} +1 -1
- package/dist/{chunk-MYRKL3JO.cjs → chunk-VWTOIGX4.cjs} +4 -4
- package/dist/{chunk-MYRKL3JO.cjs.map → chunk-VWTOIGX4.cjs.map} +1 -1
- package/dist/{chunk-Q7DB5S7N.cjs → chunk-WW6LXQY6.cjs} +12 -12
- package/dist/{chunk-Q7DB5S7N.cjs.map → chunk-WW6LXQY6.cjs.map} +1 -1
- package/dist/{chunk-NJCK6V6U.cjs → chunk-XKDUPU7B.cjs} +4 -4
- package/dist/{chunk-NJCK6V6U.cjs.map → chunk-XKDUPU7B.cjs.map} +1 -1
- package/dist/{chunk-YAPXIANR.cjs → chunk-YVCOQHCE.cjs} +5 -5
- package/dist/{chunk-YAPXIANR.cjs.map → chunk-YVCOQHCE.cjs.map} +1 -1
- package/dist/{chunk-TOM2P3MA.cjs → chunk-ZZA756I4.cjs} +4 -4
- package/dist/{chunk-TOM2P3MA.cjs.map → chunk-ZZA756I4.cjs.map} +1 -1
- package/dist/citations/index.cjs +8 -8
- package/dist/connect/docx.cjs +24 -24
- package/dist/connect/index.cjs +1489 -1433
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/viewer.cjs +40 -40
- package/dist/connection/ConnectedWorkflowBuilder.d.ts +11 -0
- package/dist/connection/ConnectedWorkflowBuilder.js +42 -3
- package/dist/connection/ConnectedWorkflowBuilder.js.map +2 -2
- package/dist/connection/conversation/ConnectedConversationPage.js +36 -2
- package/dist/connection/conversation/ConnectedConversationPage.js.map +2 -2
- package/dist/connection/report-problem/ReportProblemDialog.d.ts +2 -2
- package/dist/connection/report-problem/ReportProblemDialog.js +51 -19
- package/dist/connection/report-problem/ReportProblemDialog.js.map +2 -2
- package/dist/connection/workflows/ConnectedWorkflowsPage.js +10 -3
- package/dist/connection/workflows/ConnectedWorkflowsPage.js.map +2 -2
- package/dist/connection/workflows/useWorkflowsPageState.d.ts +1 -0
- package/dist/connection/workflows/useWorkflowsPageState.js.map +2 -2
- package/dist/dashboards/index.cjs +23 -23
- package/dist/embed/index.cjs +49 -49
- package/dist/facts/index.cjs +45 -45
- package/dist/files/index.cjs +225 -225
- package/dist/home/index.cjs +32 -32
- package/dist/index.cjs +1750 -1750
- package/dist/provider/environment.d.ts +5 -0
- package/dist/provider/environment.js +1 -1
- package/dist/provider/environment.js.map +2 -2
- package/dist/provider/requests.d.ts +2 -0
- package/dist/provider/requests.js.map +2 -2
- package/dist/retrieval/index.cjs +4 -4
- package/dist/settings/index.cjs +148 -148
- package/dist/shell/index.cjs +91 -91
- package/dist/site/index.cjs +5 -5
- package/dist/studio/index.cjs +43 -43
- package/dist/workflow-canvas/index.cjs +114 -72
- package/dist/workflow-canvas/index.cjs.map +1 -1
- package/dist/workspaces/index.cjs +18 -18
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +5 -5
- package/dist/ai-OYTFPMXI.cjs.map +0 -1
- package/dist/chunk-U5T46QCS.cjs.map +0 -1
package/dist/connect/viewer.cjs
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var chunkMGQSLMTC_cjs = require('../chunk-MGQSLMTC.cjs');
|
|
5
5
|
require('../chunk-4CIVQWAX.cjs');
|
|
6
|
-
var
|
|
7
|
-
require('../chunk-
|
|
8
|
-
require('../chunk-
|
|
9
|
-
require('../chunk-
|
|
10
|
-
require('../chunk-
|
|
11
|
-
require('../chunk-
|
|
6
|
+
var chunkPL7HUTM3_cjs = require('../chunk-PL7HUTM3.cjs');
|
|
7
|
+
require('../chunk-7TEUGFIL.cjs');
|
|
8
|
+
require('../chunk-UUENH4BJ.cjs');
|
|
9
|
+
require('../chunk-7X3FS5HQ.cjs');
|
|
10
|
+
require('../chunk-XKDUPU7B.cjs');
|
|
11
|
+
require('../chunk-5QUL5BZO.cjs');
|
|
12
12
|
require('../chunk-223D4727.cjs');
|
|
13
13
|
require('../chunk-SNUBQMIS.cjs');
|
|
14
|
-
require('../chunk-
|
|
14
|
+
require('../chunk-NHHEMBXQ.cjs');
|
|
15
15
|
require('../chunk-4ONPEVTP.cjs');
|
|
16
16
|
require('../chunk-V3KLUWQQ.cjs');
|
|
17
|
-
require('../chunk-
|
|
18
|
-
require('../chunk-
|
|
17
|
+
require('../chunk-P5AQYC4D.cjs');
|
|
18
|
+
require('../chunk-GQXPNIRE.cjs');
|
|
19
19
|
require('../chunk-YYPZOEED.cjs');
|
|
20
20
|
require('../chunk-GNZAH6UI.cjs');
|
|
21
21
|
require('../chunk-JH6JTI76.cjs');
|
|
@@ -24,72 +24,72 @@ 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-
|
|
27
|
+
require('../chunk-CT3SLXB7.cjs');
|
|
28
|
+
require('../chunk-WW6LXQY6.cjs');
|
|
28
29
|
require('../chunk-MZZ3SBQL.cjs');
|
|
29
|
-
require('../chunk-
|
|
30
|
-
require('../chunk-
|
|
30
|
+
require('../chunk-4NPCDS2X.cjs');
|
|
31
|
+
require('../chunk-Q6DQGGP4.cjs');
|
|
31
32
|
require('../chunk-ZPPMAL5P.cjs');
|
|
32
33
|
require('../chunk-ORELHENJ.cjs');
|
|
33
34
|
require('../chunk-NWNVWO6L.cjs');
|
|
34
35
|
require('../chunk-SK6HQ46Q.cjs');
|
|
35
|
-
require('../chunk-
|
|
36
|
-
require('../chunk-
|
|
36
|
+
require('../chunk-DEXUL3T6.cjs');
|
|
37
|
+
require('../chunk-6WMMZLEV.cjs');
|
|
38
|
+
require('../chunk-Z2XZ2D4N.cjs');
|
|
39
|
+
require('../chunk-YZSQ7F5K.cjs');
|
|
40
|
+
require('../chunk-MCXS6X37.cjs');
|
|
41
|
+
require('../chunk-KQF7POTG.cjs');
|
|
37
42
|
require('../chunk-VLCY46K6.cjs');
|
|
38
43
|
require('../chunk-HM5L4SBC.cjs');
|
|
44
|
+
require('../chunk-75BNMCUX.cjs');
|
|
39
45
|
require('../chunk-OEJQFPWO.cjs');
|
|
40
46
|
require('../chunk-OYXWQTHF.cjs');
|
|
41
47
|
require('../chunk-S237ORM3.cjs');
|
|
42
48
|
require('../chunk-II2OEXHW.cjs');
|
|
43
|
-
require('../chunk-
|
|
49
|
+
require('../chunk-FX3K6LNZ.cjs');
|
|
50
|
+
require('../chunk-LYTIQQQ2.cjs');
|
|
44
51
|
require('../chunk-3YEXZX4H.cjs');
|
|
45
52
|
require('../chunk-4PA6VCCR.cjs');
|
|
46
|
-
require('../chunk-
|
|
53
|
+
require('../chunk-MZ2KZXNU.cjs');
|
|
47
54
|
require('../chunk-AHDJXIUB.cjs');
|
|
55
|
+
require('../chunk-YVCOQHCE.cjs');
|
|
48
56
|
require('../chunk-RL2HI6NP.cjs');
|
|
49
57
|
require('../chunk-6UZC4XVV.cjs');
|
|
50
|
-
require('../chunk-
|
|
51
|
-
require('../chunk-
|
|
58
|
+
require('../chunk-QGVOT7E4.cjs');
|
|
59
|
+
require('../chunk-QRAQZTJE.cjs');
|
|
60
|
+
require('../chunk-UDSHVNU3.cjs');
|
|
61
|
+
require('../chunk-JV5TVUOU.cjs');
|
|
62
|
+
require('../chunk-IPSHAMO2.cjs');
|
|
52
63
|
require('../chunk-E7TE2WVT.cjs');
|
|
53
64
|
require('../chunk-EG7EJFUE.cjs');
|
|
54
65
|
require('../chunk-VG24E4JJ.cjs');
|
|
55
66
|
require('../chunk-U2FFG2B3.cjs');
|
|
56
67
|
require('../chunk-KKYNTWDU.cjs');
|
|
57
68
|
require('../chunk-M74FWYNL.cjs');
|
|
58
|
-
require('../chunk-
|
|
59
|
-
require('../chunk-
|
|
69
|
+
require('../chunk-VZOOGA47.cjs');
|
|
70
|
+
require('../chunk-HQDR43JC.cjs');
|
|
71
|
+
require('../chunk-JR2YSBD5.cjs');
|
|
60
72
|
require('../chunk-3YZKDCWY.cjs');
|
|
61
73
|
require('../chunk-SJSGSHIT.cjs');
|
|
62
|
-
require('../chunk-ZW6FPIFC.cjs');
|
|
63
|
-
require('../chunk-VZOOGA47.cjs');
|
|
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
74
|
require('../chunk-PPCATBOY.cjs');
|
|
78
|
-
require('../chunk-
|
|
75
|
+
require('../chunk-ZW6FPIFC.cjs');
|
|
76
|
+
require('../chunk-LJJJ6CYH.cjs');
|
|
77
|
+
require('../chunk-MNIQDXM6.cjs');
|
|
78
|
+
require('../chunk-E3Y7RI3J.cjs');
|
|
79
|
+
require('../chunk-TKHCIHE2.cjs');
|
|
79
80
|
require('../chunk-JDFBEGQO.cjs');
|
|
80
81
|
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 chunkMGQSLMTC_cjs.ConnectedDocumentViewer; }
|
|
89
89
|
});
|
|
90
90
|
Object.defineProperty(exports, "ConnectedDocumentToolsProvider", {
|
|
91
91
|
enumerable: true,
|
|
92
|
-
get: function () { return
|
|
92
|
+
get: function () { return chunkPL7HUTM3_cjs.ConnectedDocumentToolsProvider; }
|
|
93
93
|
});
|
|
94
94
|
//# sourceMappingURL=viewer.cjs.map
|
|
95
95
|
//# sourceMappingURL=viewer.cjs.map
|
|
@@ -28,6 +28,17 @@ export interface ConnectedWorkflowBuilderLabels {
|
|
|
28
28
|
export declare const DEFAULT_CONNECTED_WORKFLOW_BUILDER_LABELS: ConnectedWorkflowBuilderLabels;
|
|
29
29
|
/** Where a new workflow starts: started by hand, one agent step to fill in. */
|
|
30
30
|
export declare function newWorkflowBuilderValue(): WorkflowBuilderValue;
|
|
31
|
+
/**
|
|
32
|
+
* Where "Schedule a task" starts: a workflow that repeats on a schedule, with one agent step whose
|
|
33
|
+
* prompt is the task, on the default recurrence (changed in the builder). It has no title: saved,
|
|
34
|
+
* it is named from the task's first words (`withTitleFromPrompt`). Every run is a thread.
|
|
35
|
+
*/
|
|
36
|
+
export declare function scheduledTaskBuilderValue(): WorkflowBuilderValue;
|
|
37
|
+
/**
|
|
38
|
+
* A workflow left without a title is named from its first agent step's prompt (its first words),
|
|
39
|
+
* so scheduled tasks don't all share one name. Others are returned as they are.
|
|
40
|
+
*/
|
|
41
|
+
export declare function withTitleFromPrompt(value: WorkflowBuilderValue): WorkflowBuilderValue;
|
|
31
42
|
/** Workspace events a workflow can start on (notification types), in plain words. */
|
|
32
43
|
export declare const DEFAULT_WORKFLOW_EVENT_KINDS: ({
|
|
33
44
|
value: "conversation_done";
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import { Button } from "@arbidocs/react/ui";
|
|
15
15
|
import { Loader2, Play, Save } from "lucide-react";
|
|
16
16
|
import { mergeSkillWorkflows } from "../agents/index.js";
|
|
17
|
+
import { DEFAULT_RECURRENCE, buildRRule } from "../agents/tasks/rrule.js";
|
|
17
18
|
import { stepConfigProblems, validateWorkflowGraph, workflowSteps } from "../agents/workflows/run.js";
|
|
18
19
|
import { WorkflowBuilder } from "../workflow-canvas/WorkflowBuilder.js";
|
|
19
20
|
import {
|
|
@@ -63,6 +64,40 @@ function newWorkflowBuilderValue() {
|
|
|
63
64
|
trigger: DEFAULT_WORKFLOW_TRIGGER
|
|
64
65
|
};
|
|
65
66
|
}
|
|
67
|
+
function scheduledTaskBuilderValue() {
|
|
68
|
+
const value = newWorkflowBuilderValue();
|
|
69
|
+
return {
|
|
70
|
+
workflow: {
|
|
71
|
+
...value.workflow,
|
|
72
|
+
title: "",
|
|
73
|
+
run: {
|
|
74
|
+
kind: "steps",
|
|
75
|
+
steps: [
|
|
76
|
+
{
|
|
77
|
+
id: "work",
|
|
78
|
+
kind: "agent",
|
|
79
|
+
title: "The task",
|
|
80
|
+
run: { kind: "prompt", promptTemplate: "" }
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
trigger: { ...value.trigger, start: "repeat", rrule: buildRRule(DEFAULT_RECURRENCE) }
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const TITLE_WORDS = 6;
|
|
89
|
+
function withTitleFromPrompt(value) {
|
|
90
|
+
if (value.workflow.title.trim()) return value;
|
|
91
|
+
const steps = value.workflow.run.kind === "steps" ? value.workflow.run.steps : [];
|
|
92
|
+
const prompt = steps.flatMap((s) => {
|
|
93
|
+
if (s.kind !== "agent") return [];
|
|
94
|
+
const { run } = s;
|
|
95
|
+
return run && "promptTemplate" in run ? [run.promptTemplate] : [];
|
|
96
|
+
})[0];
|
|
97
|
+
const words = (prompt ?? "").trim().split(/\s+/).filter(Boolean);
|
|
98
|
+
const title = words.slice(0, TITLE_WORDS).join(" ") + (words.length > TITLE_WORDS ? "\u2026" : "");
|
|
99
|
+
return { ...value, workflow: { ...value.workflow, title: title || "Scheduled task" } };
|
|
100
|
+
}
|
|
66
101
|
const DEFAULT_WORKFLOW_EVENT_KINDS = [
|
|
67
102
|
{ value: "conversation_done", label: "A task is marked done" },
|
|
68
103
|
{ value: "conversation_ready", label: "Work is ready for me" },
|
|
@@ -135,7 +170,9 @@ function ConnectedWorkflowBuilder({
|
|
|
135
170
|
const busy = !!pending || create.isPending || update.isPending || run.isPending;
|
|
136
171
|
const save = async () => {
|
|
137
172
|
if (!workspaceId) return void 0;
|
|
138
|
-
const
|
|
173
|
+
const named = withTitleFromPrompt(value);
|
|
174
|
+
const result = id ? await update.mutateAsync({ workflowId: id, patch: builderToWorkflowUpdate(named, options) }) : await create.mutateAsync(builderToWorkflowRequest(named, workspaceId, options));
|
|
175
|
+
if (named !== value) setValue(named);
|
|
139
176
|
setId(result.external_id);
|
|
140
177
|
setLoaded(result.external_id);
|
|
141
178
|
const { trigger } = value;
|
|
@@ -147,7 +184,7 @@ function ConnectedWorkflowBuilder({
|
|
|
147
184
|
await ensureWorkspaceOpen();
|
|
148
185
|
await grantAccess.mutateAsync({ agentExtId: agentId, workspaceId });
|
|
149
186
|
}
|
|
150
|
-
await onSaved?.(result.external_id,
|
|
187
|
+
await onSaved?.(result.external_id, named);
|
|
151
188
|
return result.external_id;
|
|
152
189
|
};
|
|
153
190
|
const attempt = async (andRun) => {
|
|
@@ -227,6 +264,8 @@ export {
|
|
|
227
264
|
ConnectedWorkflowBuilder,
|
|
228
265
|
DEFAULT_CONNECTED_WORKFLOW_BUILDER_LABELS,
|
|
229
266
|
DEFAULT_WORKFLOW_EVENT_KINDS,
|
|
230
|
-
newWorkflowBuilderValue
|
|
267
|
+
newWorkflowBuilderValue,
|
|
268
|
+
scheduledTaskBuilderValue,
|
|
269
|
+
withTitleFromPrompt
|
|
231
270
|
};
|
|
232
271
|
//# sourceMappingURL=ConnectedWorkflowBuilder.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/connection/ConnectedWorkflowBuilder.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * The workflow builder bound to the connection: it loads a saved workflow (or starts from the\n * host's value), offers the host's workflows and the user's skills as steps an agent can run, its\n * agents, the people, labels, documents, events and tasks a workflow can use, and saves the\n * workflow (its trigger and its steps) or runs it now. An unattended workflow that keeps standing\n * access gives its agent the workspace once saved. Every run is a work thread that runs the steps.\n * Saved and failed are told through the environment's `notify`. Exported from\n * `@arbidocs/blocks/workflow-canvas` (it brings the graph library).\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport {\n useAgents,\n useCreateWorkflow,\n useGrantAgentAccess,\n useRunWorkflow,\n useWorkspaceUsers,\n useSkills,\n useUpdateWorkflow,\n useWorkflows,\n} from '@arbidocs/react'\nimport type { components } from '@arbidocs/client'\nimport { Button } from '@arbidocs/react/ui'\nimport { Loader2, Play, Save } from 'lucide-react'\nimport { mergeSkillWorkflows, type StepComposeOptions, type WorkflowDefinition } from '../agents'\nimport { stepConfigProblems, validateWorkflowGraph, workflowSteps } from '../agents/workflows/run'\nimport { WorkflowBuilder, type WorkflowBuilderProps } from '../workflow-canvas/WorkflowBuilder'\nimport {\n DEFAULT_WORKFLOW_TRIGGER,\n builderToWorkflowRequest,\n builderToWorkflowUpdate,\n declaredSignals,\n triggerProblem,\n workflowRecordToBuilder,\n type WorkflowBuilderValue,\n} from '../workflow-canvas/trigger'\nimport { useBlocksEnvironment } from '../provider/environment'\nimport { useConnectedWorkspace } from './ConnectionProvider'\nimport { useConnectedConversations, useConnectedTags, useListedDocuments } from './workspaceData'\n\nconst NO_WORKFLOWS: WorkflowDefinition[] = []\n\nexport interface ConnectedWorkflowBuilderLabels {\n save: string\n saving: string\n runNow: string\n /** The notification once saved. */\n saved: string\n needTrigger: string\n running: string\n /** Notified when saving (or the after-save step) fails without a message. */\n saveFailed: string\n /** Notified when \"Run now\" fails without a message. */\n runFailed: string\n /** A task (to start after) without a title. */\n untitledTask: string\n}\n\nexport const DEFAULT_CONNECTED_WORKFLOW_BUILDER_LABELS: ConnectedWorkflowBuilderLabels = {\n save: 'Save',\n saving: 'Saving\u2026',\n runNow: 'Run now',\n saved: 'Workflow saved',\n needTrigger: 'Finish setting when it starts.',\n running: 'Starting\u2026',\n saveFailed: 'Could not save the workflow',\n runFailed: 'Could not run the workflow',\n untitledTask: 'Untitled thread',\n}\n\n/** Where a new workflow starts: started by hand, one agent step to fill in. */\nexport function newWorkflowBuilderValue(): WorkflowBuilderValue {\n return {\n workflow: {\n id: 'new',\n title: 'New workflow',\n description: '',\n inputs: [],\n landing: 'chat',\n schedulable: false,\n run: {\n kind: 'steps',\n steps: [\n {\n id: 'work',\n kind: 'agent',\n title: 'Do the work',\n run: { kind: 'prompt', promptTemplate: '' },\n },\n ],\n },\n },\n trigger: DEFAULT_WORKFLOW_TRIGGER,\n }\n}\n\n/**\n * A workspace event a workflow can start on: a notification type (what the API's `event_kind` check\n * accepts), except those the workflow engine emits itself, which the API refuses as a trigger (422).\n */\ntype WorkflowEventKind = Exclude<components['schemas']['NotificationType'], 'workflow_failed'>\n\n/** Workspace events a workflow can start on (notification types), in plain words. */\nexport const DEFAULT_WORKFLOW_EVENT_KINDS = [\n { value: 'conversation_done', label: 'A task is marked done' },\n { value: 'conversation_ready', label: 'Work is ready for me' },\n { value: 'mention', label: 'Someone mentions me' },\n { value: 'workflow_completed', label: 'Another workflow finishes' },\n { value: 'workflow_signal', label: 'When a step signals' },\n // Filter on {\"language\": \"other\", \"wp_type\": \"source\"} to act on every non-English upload (e.g. Translate).\n { value: 'document_processed', label: 'A document finishes processing' },\n] satisfies Array<{ value: WorkflowEventKind; label: string }>\n\nexport interface ConnectedWorkflowBuilderProps\n extends\n Pick<StepComposeOptions, 'compose'>,\n Pick<\n WorkflowBuilderProps,\n | 'renderIcon'\n | 'labels'\n | 'canvasLabels'\n | 'inspectorLabels'\n | 'triggerLabels'\n | 'testId'\n | 'className'\n > {\n /** A saved workflow to edit (`wfl-\u2026`). */\n workflowId?: string\n /** Where a new workflow starts (e.g. a built-in journey). Default: one agent step. */\n initial?: WorkflowBuilderValue\n /**\n * Host workflows agent steps can run besides the user's skills (e.g. its built-ins with their own\n * forms); an uploaded skill of the same id is used instead (`mergeSkillWorkflows`).\n */\n workflows?: WorkflowDefinition[]\n eventKinds?: Array<{ value: string; label: string }>\n /**\n * Saved (created or updated, the agent's standing access granted): its id and the value saved.\n * It may return a promise for host setup that must finish first: \"Save\" waits for it before\n * telling saved, and \"Run now\" waits for it before running, and does not run if it rejects.\n */\n onSaved?: (workflowId: string, value: WorkflowBuilderValue) => void | Promise<void>\n /** A run started: its thread. Default: open it (the environment's `openConversation`). */\n onRun?: (conversationId: string | undefined) => void\n connectedLabels?: Partial<ConnectedWorkflowBuilderLabels>\n}\n\nexport function ConnectedWorkflowBuilder({\n workflowId,\n initial = newWorkflowBuilderValue(),\n workflows: hostWorkflows = NO_WORKFLOWS,\n eventKinds = DEFAULT_WORKFLOW_EVENT_KINDS,\n compose,\n onSaved,\n onRun,\n connectedLabels,\n testId = 'workflow-builder',\n ...builderProps\n}: ConnectedWorkflowBuilderProps) {\n const l = { ...DEFAULT_CONNECTED_WORKFLOW_BUILDER_LABELS, ...connectedLabels }\n const { notify, openConversation } = useBlocksEnvironment()\n const { workspaceId, live, ensureWorkspaceOpen } = useConnectedWorkspace()\n const members = useWorkspaceUsers(workspaceId ?? undefined, {\n enabled: live && !!workspaceId,\n beforeFetch: ensureWorkspaceOpen,\n })\n const { data: tagList } = useConnectedTags()\n const { data: docList } = useListedDocuments()\n const people = (members.data ?? []).map((m) => ({\n value: m.user.external_id,\n label: [m.user.given_name, m.user.family_name].filter(Boolean).join(' ') || m.user.email,\n }))\n const tagOptions = tagList.map((t) => ({ value: t.external_id, label: t.name }))\n const documentOptions = docList.map((d) => ({\n value: d.external_id,\n label: d.file_name ?? d.external_id,\n }))\n const saved = useWorkflows()\n const skills = useSkills()\n const agentsQuery = useAgents()\n const { data: conversations } = useConnectedConversations()\n const create = useCreateWorkflow()\n const update = useUpdateWorkflow()\n const run = useRunWorkflow()\n const grantAccess = useGrantAgentAccess()\n const [id, setId] = useState(workflowId)\n const [value, setValue] = useState<WorkflowBuilderValue>(initial)\n // Which button is working, and where it is: saving covers the host's after-save step too.\n const [pending, setPending] = useState<{ action: 'save' | 'run'; phase: 'saving' | 'running' }>()\n\n // A saved workflow opens as it was saved.\n const record = saved.data?.find((w) => w.external_id === id)\n const [loaded, setLoaded] = useState<string | undefined>(undefined)\n useEffect(() => {\n if (record && loaded !== record.external_id) {\n setValue(workflowRecordToBuilder(record))\n setLoaded(record.external_id)\n }\n }, [record, loaded])\n\n const workflows = useMemo(() => {\n const merged = mergeSkillWorkflows(hostWorkflows, skills.data ?? [])\n return [...merged.host, ...merged.skills]\n }, [hostWorkflows, skills.data])\n const agents = (agentsQuery.data ?? []).map((a) => ({\n id: a.external_id,\n label: a.given_name || a.email,\n }))\n const tasks = conversations\n .filter((c) => c.status && c.status !== 'done')\n .map((c) => ({ value: c.external_id, label: c.title || l.untitledTask }))\n const options = { resolveWorkflow: (wid: string) => workflows.find((w) => w.id === wid), compose }\n\n const problem =\n triggerProblem(value.trigger) ??\n (validateWorkflowGraph(workflowSteps(value.workflow)).length ||\n stepConfigProblems(workflowSteps(value.workflow)).length\n ? 'graph'\n : null)\n const busy = !!pending || create.isPending || update.isPending || run.isPending\n\n /**\n * Save; then, when unattended starts keep standing access, give the agent (the one picked, else\n * the one the server assigned) the workspace, so a run started next already has it; then the\n * host's after-save step. Throws if any of them fails.\n */\n const save = async (): Promise<string | undefined> => {\n if (!workspaceId) return undefined\n const result = id\n ? await update.mutateAsync({ workflowId: id, patch: builderToWorkflowUpdate(value, options) })\n : await create.mutateAsync(builderToWorkflowRequest(value, workspaceId, options))\n setId(result.external_id)\n setLoaded(result.external_id)\n const { trigger } = value\n const agentId = trigger.agentId || result.agent_ext_id\n // Standing access only: an expiring membership (an earlier \"Allow access\") is not, and a run\n // relying on it would park asking for access again. Granting upgrades it to standing.\n const hasStanding = (members.data ?? []).some(\n (m) => m.user.external_id === agentId && !m.is_temporary\n )\n if (trigger.start !== 'manual' && trigger.access === 'standing' && agentId && !hasStanding) {\n await ensureWorkspaceOpen()\n await grantAccess.mutateAsync({ agentExtId: agentId, workspaceId })\n }\n await onSaved?.(result.external_id, value)\n return result.external_id\n }\n\n const attempt = async (andRun: boolean) => {\n setPending({ action: andRun ? 'run' : 'save', phase: 'saving' })\n try {\n const savedId = await save()\n if (!savedId) return\n if (!andRun) {\n notify(l.saved, 'success')\n return\n }\n setPending({ action: 'run', phase: 'running' })\n const started = await run.mutateAsync(savedId)\n if (started.error) throw new Error(started.error)\n const conversationId = started.conversation_ext_id ?? undefined\n if (onRun) onRun(conversationId)\n else if (conversationId) openConversation(conversationId)\n } catch (e) {\n notify(\n e instanceof Error && e.message ? e.message : andRun ? l.runFailed : l.saveFailed,\n 'error'\n )\n } finally {\n setPending(undefined)\n }\n }\n\n return (\n <WorkflowBuilder\n {...builderProps}\n value={value}\n onChange={setValue}\n workflows={workflows}\n agents={agents}\n eventKinds={eventKinds}\n tasks={tasks}\n people={people}\n tags={tagOptions}\n documents={documentOptions}\n signals={declaredSignals(saved.data ?? [])}\n compose={compose}\n testId={testId}\n actions={\n <>\n {problem && problem !== 'graph' && (\n <span className=\"text-xs text-destructive\">{l.needTrigger}</span>\n )}\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={!!problem || busy || !workspaceId}\n onClick={() => void attempt(true)}\n data-testid={`${testId}-run`}\n >\n {pending?.action === 'run' ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Play className=\"size-4\" />\n )}\n {pending?.action === 'run'\n ? pending.phase === 'saving'\n ? l.saving\n : l.running\n : l.runNow}\n </Button>\n <Button\n size=\"sm\"\n disabled={!!problem || busy || !workspaceId}\n onClick={() => void attempt(false)}\n data-testid={`${testId}-save`}\n >\n {pending?.action === 'save' ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Save className=\"size-4\" />\n )}\n {pending?.action === 'save' ? l.saving : l.save}\n </Button>\n </>\n }\n />\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["/**\n * The workflow builder bound to the connection: it loads a saved workflow (or starts from the\n * host's value), offers the host's workflows and the user's skills as steps an agent can run, its\n * agents, the people, labels, documents, events and tasks a workflow can use, and saves the\n * workflow (its trigger and its steps) or runs it now. An unattended workflow that keeps standing\n * access gives its agent the workspace once saved. Every run is a work thread that runs the steps.\n * Saved and failed are told through the environment's `notify`. Exported from\n * `@arbidocs/blocks/workflow-canvas` (it brings the graph library).\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport {\n useAgents,\n useCreateWorkflow,\n useGrantAgentAccess,\n useRunWorkflow,\n useWorkspaceUsers,\n useSkills,\n useUpdateWorkflow,\n useWorkflows,\n} from '@arbidocs/react'\nimport type { components } from '@arbidocs/client'\nimport { Button } from '@arbidocs/react/ui'\nimport { Loader2, Play, Save } from 'lucide-react'\nimport { mergeSkillWorkflows, type StepComposeOptions, type WorkflowDefinition } from '../agents'\nimport { DEFAULT_RECURRENCE, buildRRule } from '../agents/tasks/rrule'\nimport { stepConfigProblems, validateWorkflowGraph, workflowSteps } from '../agents/workflows/run'\nimport { WorkflowBuilder, type WorkflowBuilderProps } from '../workflow-canvas/WorkflowBuilder'\nimport {\n DEFAULT_WORKFLOW_TRIGGER,\n builderToWorkflowRequest,\n builderToWorkflowUpdate,\n declaredSignals,\n triggerProblem,\n workflowRecordToBuilder,\n type WorkflowBuilderValue,\n} from '../workflow-canvas/trigger'\nimport { useBlocksEnvironment } from '../provider/environment'\nimport { useConnectedWorkspace } from './ConnectionProvider'\nimport { useConnectedConversations, useConnectedTags, useListedDocuments } from './workspaceData'\n\nconst NO_WORKFLOWS: WorkflowDefinition[] = []\n\nexport interface ConnectedWorkflowBuilderLabels {\n save: string\n saving: string\n runNow: string\n /** The notification once saved. */\n saved: string\n needTrigger: string\n running: string\n /** Notified when saving (or the after-save step) fails without a message. */\n saveFailed: string\n /** Notified when \"Run now\" fails without a message. */\n runFailed: string\n /** A task (to start after) without a title. */\n untitledTask: string\n}\n\nexport const DEFAULT_CONNECTED_WORKFLOW_BUILDER_LABELS: ConnectedWorkflowBuilderLabels = {\n save: 'Save',\n saving: 'Saving\u2026',\n runNow: 'Run now',\n saved: 'Workflow saved',\n needTrigger: 'Finish setting when it starts.',\n running: 'Starting\u2026',\n saveFailed: 'Could not save the workflow',\n runFailed: 'Could not run the workflow',\n untitledTask: 'Untitled thread',\n}\n\n/** Where a new workflow starts: started by hand, one agent step to fill in. */\nexport function newWorkflowBuilderValue(): WorkflowBuilderValue {\n return {\n workflow: {\n id: 'new',\n title: 'New workflow',\n description: '',\n inputs: [],\n landing: 'chat',\n schedulable: false,\n run: {\n kind: 'steps',\n steps: [\n {\n id: 'work',\n kind: 'agent',\n title: 'Do the work',\n run: { kind: 'prompt', promptTemplate: '' },\n },\n ],\n },\n },\n trigger: DEFAULT_WORKFLOW_TRIGGER,\n }\n}\n\n/**\n * Where \"Schedule a task\" starts: a workflow that repeats on a schedule, with one agent step whose\n * prompt is the task, on the default recurrence (changed in the builder). It has no title: saved,\n * it is named from the task's first words (`withTitleFromPrompt`). Every run is a thread.\n */\nexport function scheduledTaskBuilderValue(): WorkflowBuilderValue {\n const value = newWorkflowBuilderValue()\n return {\n workflow: {\n ...value.workflow,\n title: '',\n run: {\n kind: 'steps',\n steps: [\n {\n id: 'work',\n kind: 'agent',\n title: 'The task',\n run: { kind: 'prompt', promptTemplate: '' },\n },\n ],\n },\n },\n trigger: { ...value.trigger, start: 'repeat', rrule: buildRRule(DEFAULT_RECURRENCE) },\n }\n}\n\n/** Words of the task a workflow without a title is named after. */\nconst TITLE_WORDS = 6\n\n/**\n * A workflow left without a title is named from its first agent step's prompt (its first words),\n * so scheduled tasks don't all share one name. Others are returned as they are.\n */\nexport function withTitleFromPrompt(value: WorkflowBuilderValue): WorkflowBuilderValue {\n if (value.workflow.title.trim()) return value\n const steps = value.workflow.run.kind === 'steps' ? value.workflow.run.steps : []\n const prompt = steps.flatMap((s) => {\n if (s.kind !== 'agent') return []\n const { run } = s\n return run && 'promptTemplate' in run ? [run.promptTemplate] : []\n })[0]\n const words = (prompt ?? '').trim().split(/\\s+/).filter(Boolean)\n const title = words.slice(0, TITLE_WORDS).join(' ') + (words.length > TITLE_WORDS ? '\u2026' : '')\n return { ...value, workflow: { ...value.workflow, title: title || 'Scheduled task' } }\n}\n\n/**\n * A workspace event a workflow can start on: a notification type (what the API's `event_kind` check\n * accepts), except those the workflow engine emits itself, which the API refuses as a trigger (422).\n */\ntype WorkflowEventKind = Exclude<components['schemas']['NotificationType'], 'workflow_failed'>\n\n/** Workspace events a workflow can start on (notification types), in plain words. */\nexport const DEFAULT_WORKFLOW_EVENT_KINDS = [\n { value: 'conversation_done', label: 'A task is marked done' },\n { value: 'conversation_ready', label: 'Work is ready for me' },\n { value: 'mention', label: 'Someone mentions me' },\n { value: 'workflow_completed', label: 'Another workflow finishes' },\n { value: 'workflow_signal', label: 'When a step signals' },\n // Filter on {\"language\": \"other\", \"wp_type\": \"source\"} to act on every non-English upload (e.g. Translate).\n { value: 'document_processed', label: 'A document finishes processing' },\n] satisfies Array<{ value: WorkflowEventKind; label: string }>\n\nexport interface ConnectedWorkflowBuilderProps\n extends\n Pick<StepComposeOptions, 'compose'>,\n Pick<\n WorkflowBuilderProps,\n | 'renderIcon'\n | 'labels'\n | 'canvasLabels'\n | 'inspectorLabels'\n | 'triggerLabels'\n | 'testId'\n | 'className'\n > {\n /** A saved workflow to edit (`wfl-\u2026`). */\n workflowId?: string\n /** Where a new workflow starts (e.g. a built-in journey). Default: one agent step. */\n initial?: WorkflowBuilderValue\n /**\n * Host workflows agent steps can run besides the user's skills (e.g. its built-ins with their own\n * forms); an uploaded skill of the same id is used instead (`mergeSkillWorkflows`).\n */\n workflows?: WorkflowDefinition[]\n eventKinds?: Array<{ value: string; label: string }>\n /**\n * Saved (created or updated, the agent's standing access granted): its id and the value saved.\n * It may return a promise for host setup that must finish first: \"Save\" waits for it before\n * telling saved, and \"Run now\" waits for it before running, and does not run if it rejects.\n */\n onSaved?: (workflowId: string, value: WorkflowBuilderValue) => void | Promise<void>\n /** A run started: its thread. Default: open it (the environment's `openConversation`). */\n onRun?: (conversationId: string | undefined) => void\n connectedLabels?: Partial<ConnectedWorkflowBuilderLabels>\n}\n\nexport function ConnectedWorkflowBuilder({\n workflowId,\n initial = newWorkflowBuilderValue(),\n workflows: hostWorkflows = NO_WORKFLOWS,\n eventKinds = DEFAULT_WORKFLOW_EVENT_KINDS,\n compose,\n onSaved,\n onRun,\n connectedLabels,\n testId = 'workflow-builder',\n ...builderProps\n}: ConnectedWorkflowBuilderProps) {\n const l = { ...DEFAULT_CONNECTED_WORKFLOW_BUILDER_LABELS, ...connectedLabels }\n const { notify, openConversation } = useBlocksEnvironment()\n const { workspaceId, live, ensureWorkspaceOpen } = useConnectedWorkspace()\n const members = useWorkspaceUsers(workspaceId ?? undefined, {\n enabled: live && !!workspaceId,\n beforeFetch: ensureWorkspaceOpen,\n })\n const { data: tagList } = useConnectedTags()\n const { data: docList } = useListedDocuments()\n const people = (members.data ?? []).map((m) => ({\n value: m.user.external_id,\n label: [m.user.given_name, m.user.family_name].filter(Boolean).join(' ') || m.user.email,\n }))\n const tagOptions = tagList.map((t) => ({ value: t.external_id, label: t.name }))\n const documentOptions = docList.map((d) => ({\n value: d.external_id,\n label: d.file_name ?? d.external_id,\n }))\n const saved = useWorkflows()\n const skills = useSkills()\n const agentsQuery = useAgents()\n const { data: conversations } = useConnectedConversations()\n const create = useCreateWorkflow()\n const update = useUpdateWorkflow()\n const run = useRunWorkflow()\n const grantAccess = useGrantAgentAccess()\n const [id, setId] = useState(workflowId)\n const [value, setValue] = useState<WorkflowBuilderValue>(initial)\n // Which button is working, and where it is: saving covers the host's after-save step too.\n const [pending, setPending] = useState<{ action: 'save' | 'run'; phase: 'saving' | 'running' }>()\n\n // A saved workflow opens as it was saved.\n const record = saved.data?.find((w) => w.external_id === id)\n const [loaded, setLoaded] = useState<string | undefined>(undefined)\n useEffect(() => {\n if (record && loaded !== record.external_id) {\n setValue(workflowRecordToBuilder(record))\n setLoaded(record.external_id)\n }\n }, [record, loaded])\n\n const workflows = useMemo(() => {\n const merged = mergeSkillWorkflows(hostWorkflows, skills.data ?? [])\n return [...merged.host, ...merged.skills]\n }, [hostWorkflows, skills.data])\n const agents = (agentsQuery.data ?? []).map((a) => ({\n id: a.external_id,\n label: a.given_name || a.email,\n }))\n const tasks = conversations\n .filter((c) => c.status && c.status !== 'done')\n .map((c) => ({ value: c.external_id, label: c.title || l.untitledTask }))\n const options = { resolveWorkflow: (wid: string) => workflows.find((w) => w.id === wid), compose }\n\n const problem =\n triggerProblem(value.trigger) ??\n (validateWorkflowGraph(workflowSteps(value.workflow)).length ||\n stepConfigProblems(workflowSteps(value.workflow)).length\n ? 'graph'\n : null)\n const busy = !!pending || create.isPending || update.isPending || run.isPending\n\n /**\n * Save; then, when unattended starts keep standing access, give the agent (the one picked, else\n * the one the server assigned) the workspace, so a run started next already has it; then the\n * host's after-save step. Throws if any of them fails.\n */\n const save = async (): Promise<string | undefined> => {\n if (!workspaceId) return undefined\n const named = withTitleFromPrompt(value)\n const result = id\n ? await update.mutateAsync({ workflowId: id, patch: builderToWorkflowUpdate(named, options) })\n : await create.mutateAsync(builderToWorkflowRequest(named, workspaceId, options))\n if (named !== value) setValue(named)\n setId(result.external_id)\n setLoaded(result.external_id)\n const { trigger } = value\n const agentId = trigger.agentId || result.agent_ext_id\n // Standing access only: an expiring membership (an earlier \"Allow access\") is not, and a run\n // relying on it would park asking for access again. Granting upgrades it to standing.\n const hasStanding = (members.data ?? []).some(\n (m) => m.user.external_id === agentId && !m.is_temporary\n )\n if (trigger.start !== 'manual' && trigger.access === 'standing' && agentId && !hasStanding) {\n await ensureWorkspaceOpen()\n await grantAccess.mutateAsync({ agentExtId: agentId, workspaceId })\n }\n await onSaved?.(result.external_id, named)\n return result.external_id\n }\n\n const attempt = async (andRun: boolean) => {\n setPending({ action: andRun ? 'run' : 'save', phase: 'saving' })\n try {\n const savedId = await save()\n if (!savedId) return\n if (!andRun) {\n notify(l.saved, 'success')\n return\n }\n setPending({ action: 'run', phase: 'running' })\n const started = await run.mutateAsync(savedId)\n if (started.error) throw new Error(started.error)\n const conversationId = started.conversation_ext_id ?? undefined\n if (onRun) onRun(conversationId)\n else if (conversationId) openConversation(conversationId)\n } catch (e) {\n notify(\n e instanceof Error && e.message ? e.message : andRun ? l.runFailed : l.saveFailed,\n 'error'\n )\n } finally {\n setPending(undefined)\n }\n }\n\n return (\n <WorkflowBuilder\n {...builderProps}\n value={value}\n onChange={setValue}\n workflows={workflows}\n agents={agents}\n eventKinds={eventKinds}\n tasks={tasks}\n people={people}\n tags={tagOptions}\n documents={documentOptions}\n signals={declaredSignals(saved.data ?? [])}\n compose={compose}\n testId={testId}\n actions={\n <>\n {problem && problem !== 'graph' && (\n <span className=\"text-xs text-destructive\">{l.needTrigger}</span>\n )}\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={!!problem || busy || !workspaceId}\n onClick={() => void attempt(true)}\n data-testid={`${testId}-run`}\n >\n {pending?.action === 'run' ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Play className=\"size-4\" />\n )}\n {pending?.action === 'run'\n ? pending.phase === 'saving'\n ? l.saving\n : l.running\n : l.runNow}\n </Button>\n <Button\n size=\"sm\"\n disabled={!!problem || busy || !workspaceId}\n onClick={() => void attempt(false)}\n data-testid={`${testId}-save`}\n >\n {pending?.action === 'save' ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Save className=\"size-4\" />\n )}\n {pending?.action === 'save' ? l.saving : l.save}\n </Button>\n </>\n }\n />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -15,7 +15,16 @@ import {
|
|
|
15
15
|
useTransientView,
|
|
16
16
|
useWorkspaces
|
|
17
17
|
} from "@arbidocs/react";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
Button,
|
|
20
|
+
DropdownMenu,
|
|
21
|
+
DropdownMenuContent,
|
|
22
|
+
DropdownMenuItem,
|
|
23
|
+
DropdownMenuTrigger,
|
|
24
|
+
getDocumentTitle,
|
|
25
|
+
getEntityLabel
|
|
26
|
+
} from "@arbidocs/react/ui";
|
|
27
|
+
import { CalendarClock, MoreHorizontal } from "lucide-react";
|
|
19
28
|
import { parseVersionRef } from "@arbidocs/react/artifacts";
|
|
20
29
|
import { ConnectedThreadTabs, useThreadTabs } from "../threads/ConnectedThreadTabs.js";
|
|
21
30
|
import { ConnectedThreadTaskBar } from "../tasks/ConnectedThreadTaskBar.js";
|
|
@@ -26,6 +35,7 @@ import { useAddFromUrls } from "../files/upload/useAddFromUrls.js";
|
|
|
26
35
|
import { UrlInputDialog } from "../../files/UrlInputDialog.js";
|
|
27
36
|
import { closeDialog, openDialog } from "../../provider/dialog-registry.js";
|
|
28
37
|
import { useBlocksEnvironment } from "../../provider/environment.js";
|
|
38
|
+
import { useOpenWorkflow } from "../workflows/useOpenWorkflow.js";
|
|
29
39
|
import { filterConversationRows } from "../../agents/tasks/ConversationListView.js";
|
|
30
40
|
import { FilterInput } from "../../shell/FilterInput.js";
|
|
31
41
|
import { ConnectedFilterDropdown as FilterDropdown } from "../ConnectedFilterDropdown.js";
|
|
@@ -56,6 +66,7 @@ function ConnectedConversationPage({
|
|
|
56
66
|
const { openFiles } = useBlocksEnvironment();
|
|
57
67
|
useEffect(() => () => session.setActiveCitationKey(null), [session]);
|
|
58
68
|
const { isInChat, setActiveTab } = useThreadTabs();
|
|
69
|
+
const openWorkflow = useOpenWorkflow();
|
|
59
70
|
const [doneFilter, setDoneFilter] = useTransientView(
|
|
60
71
|
"threads.done",
|
|
61
72
|
"exclude"
|
|
@@ -234,7 +245,30 @@ function ConnectedConversationPage({
|
|
|
234
245
|
}
|
|
235
246
|
}
|
|
236
247
|
),
|
|
237
|
-
showPaMode && /* @__PURE__ */ jsx(NewPaChatButton, { isCompact, onClick: () => startNewChat(true) })
|
|
248
|
+
showPaMode && /* @__PURE__ */ jsx(NewPaChatButton, { isCompact, onClick: () => startNewChat(true) }),
|
|
249
|
+
!isInChat && openWorkflow && /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
250
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
251
|
+
Button,
|
|
252
|
+
{
|
|
253
|
+
variant: "ghost",
|
|
254
|
+
size: "icon",
|
|
255
|
+
"aria-label": "More actions",
|
|
256
|
+
"data-testid": "threads-more",
|
|
257
|
+
children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "size-4" })
|
|
258
|
+
}
|
|
259
|
+
) }),
|
|
260
|
+
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "end", children: /* @__PURE__ */ jsxs(
|
|
261
|
+
DropdownMenuItem,
|
|
262
|
+
{
|
|
263
|
+
onSelect: () => openWorkflow(void 0, { preset: "schedule" }),
|
|
264
|
+
"data-testid": "threads-schedule-task",
|
|
265
|
+
children: [
|
|
266
|
+
/* @__PURE__ */ jsx(CalendarClock, { className: "size-4" }),
|
|
267
|
+
" Schedule a task\u2026"
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
) })
|
|
271
|
+
] })
|
|
238
272
|
] })
|
|
239
273
|
}
|
|
240
274
|
),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/connection/conversation/ConnectedConversationPage.tsx"],
|
|
4
|
-
"sourcesContent": ["import { useThreadTagFilter } from '../threads/useThreadTagFilter'\nimport { TagFilterChips } from '../tags/TagCombineFilter'\n/** The tabbed conversation page; host-specific composer context stays in a slot. */\nimport { useEffect, useState, type ComponentType, type ReactNode } from 'react'\nimport {\n useArbiSessionStore,\n useArbiSessionState,\n useConversationDocuments,\n useConversationItems,\n useDocuments,\n useTags,\n useWorkspaceRole,\n useUserSettings,\n useTransientView,\n useWorkspaces,\n} from '@arbidocs/react'\nimport { getDocumentTitle, getEntityLabel } from '@arbidocs/react/ui'\nimport { parseVersionRef } from '@arbidocs/react/artifacts'\nimport { ConnectedThreadTabs, useThreadTabs } from '../threads/ConnectedThreadTabs'\nimport { ConnectedThreadTaskBar } from '../tasks/ConnectedThreadTaskBar'\nimport { ConnectedThreadsPage } from '../threads-page/ConnectedThreadsPage'\nimport { ConnectedConversationCallActions } from '../../calls/connected/ConnectedConversationCallActions'\nimport { ConnectedWorkspaceEntity } from '../entities/ConnectedWorkspaceEntity'\nimport { useAddFromUrls } from '../files/upload/useAddFromUrls'\nimport { UrlInputDialog } from '../../files/UrlInputDialog'\nimport { closeDialog, openDialog } from '../../provider/dialog-registry'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { filterConversationRows } from '../../agents/tasks/ConversationListView'\nimport { FilterInput } from '../../shell/FilterInput'\nimport { ConnectedFilterDropdown as FilterDropdown } from '../ConnectedFilterDropdown'\nimport {\n ConversationHistoryPane,\n ConversationHeaderActions,\n ConversationSettingsButton,\n NewChatButton,\n NewPaChatButton,\n} from '../../chat/ConversationParts'\nimport { ConversationHeader, ConversationRoot } from '../../chat/ConversationLayout'\nimport { SemanticSearchButton } from './SemanticSearchButton'\nimport { ConversationThread } from './ConnectedConversation'\nimport { ConnectedChatContextButton } from '../chat-context/ConnectedChatContextButton'\nimport type { UploadSource } from '../../provider/environment'\n\nconst DEFAULT_THREAD_VISIBILITY = { me: null, workspace: null } as {\n me: 'include' | 'exclude' | null\n workspace: 'include' | 'exclude' | null\n}\nexport interface ConnectedConversationPageProps {\n /** Controlled selection: opens the stored (or, with null, a new) thread's tab, without route parsing. */\n conversationId?: string | null\n /** The composer's model picker (the host's). Absent: none. */\n modelSelector?: ReactNode\n /** Wraps the conversation search results (the host's crash boundary, say). */\n ResultsBoundary?: ComponentType<{ children: ReactNode }>\n /** Where \"go to documents\" leads. Absent: the environment's `openFiles`. */\n onGoToDocuments?: () => void\n}\n\n/**\n * The open conversation in the tabbed workspace page: its thread tabs, task bar, history with\n * filters and search, and the URL-upload dialog around `ConnectedConversationThread`'s body.\n */\nexport function ConnectedConversationPage({\n conversationId,\n modelSelector,\n ResultsBoundary,\n onGoToDocuments,\n}: ConnectedConversationPageProps) {\n const session = useArbiSessionStore()\n useEffect(() => {\n if (conversationId === undefined) return\n const tabId = conversationId ?? 'new'\n if (session.getState().tabs.activeThread !== tabId) session.openThreadTab(conversationId)\n }, [conversationId, session])\n const { openFiles } = useBlocksEnvironment()\n useEffect(() => () => session.setActiveCitationKey(null), [session])\n const { isInChat, setActiveTab } = useThreadTabs()\n const [doneFilter, setDoneFilter] = useTransientView(\n 'threads.done',\n 'exclude' as 'include' | 'exclude' | null\n )\n const [visibilityFilters, setVisibilityFilters] = useTransientView(\n 'threads.visibility',\n DEFAULT_THREAD_VISIBILITY\n )\n const [meetingFilter, setMeetingFilter] = useTransientView(\n 'threads.meetings',\n null as 'include' | 'exclude' | null\n )\n const [threadFilter, setThreadFilter] = useTransientView('topbar.filter', '')\n\n // Get experimental flags from API\n const { data: userSettings } = useUserSettings()\n const isDeveloper = userSettings?.developer === true\n const showPaMode = userSettings?.show_pa_mode ?? false\n const searchEnabled = userSettings?.show_conversation_search === true\n // Conversation (message) semantic search is opened from the header icon; it lives on the list, so opening it from a\n // thread goes back to the list first.\n const [semanticSearchOpen, setSemanticSearchOpen] = useState(false)\n\n // Handlers for modals\n const handleSelectSource = (source: UploadSource) => {\n // Match the Files \"Add\" menu exactly: internet opens the URL dialog directly,\n // the others open their focused upload modal. (No processing-modal guard.)\n if (source === 'internet') {\n setUrlDialogOpen(true)\n return\n }\n openDialog('upload', { tab: 'upload', source })\n }\n\n const handleGoToDocuments = () => {\n // Switch to the Documents/Files page instead of opening the in-chat modal\n // preview. Dismiss the modal first in case another entry point left it open.\n closeDialog('conversationDocuments')\n if (onGoToDocuments) onGoToDocuments()\n else openFiles()\n }\n\n const handleStatusClick = () => {\n openDialog('conversationDocuments')\n }\n\n // Get current conversation ID from store\n const currentConversationId = useArbiSessionState((state) => state.conversationId)\n const { conversations: taskItems } = useConversationItems()\n const conversations = taskItems\n\n // Read-only members (`guest`) can read but not upload. Non-members also can't upload.\n const workspaceId = useArbiSessionState((state) => state.workspaceId)\n const { data: workspaces = [] } = useWorkspaces()\n const workspace = workspaces.find((item) => item.external_id === workspaceId)\n const workspaceRole = useWorkspaceRole()\n const isGuest = workspaceRole === 'guest'\n const canUpload = workspaceRole !== null && !isGuest\n\n // \"From the internet\" opens the URL dialog inline (parity with the Files Add\n // menu); it runs the upload itself and surfaces any error in the dialog.\n const [urlDialogOpen, setUrlDialogOpen] = useState(false)\n const uploadUrls = useAddFromUrls({\n onZipFiles: (files) => openDialog('upload', { tab: 'upload', files, source: 'computer' }),\n })\n const uploadDisabledReason = isGuest\n ? 'Read-only members cannot upload documents in this workspace'\n : 'You cannot upload to this workspace'\n\n // What the conversation reads: its documents, and a pinned one.\n const { data: allWorkspaceDocuments = [] } = useDocuments()\n const { data: conversationDocuments } = useConversationDocuments()\n const pinnedDocumentId = useArbiSessionState((state) => state.pinnedDocumentId)\n // A pinned older version (`doc-\u2026@v2`, \"Ask about this version\" in the viewer) names its document.\n const pinnedRef = parseVersionRef(pinnedDocumentId)\n const pinnedDocument =\n conversationDocuments?.find((d) => d.external_id === pinnedRef.docId) ??\n allWorkspaceDocuments?.find((d) => d.external_id === pinnedRef.docId)\n\n const pinnedTitle = pinnedDocument\n ? `${getDocumentTitle(pinnedDocument)}${pinnedRef.version ? ` (version ${pinnedRef.version})` : ''}`\n : null\n\n // Start a new conversation (optionally in Personal Assistant mode) in a new chat tab.\n const startNewChat = (asPaChat: boolean) => {\n session.clearConversationError(currentConversationId || 'new')\n session.startNewConversation()\n session.openThreadTab(null)\n if (asPaChat) session.setPaMode(true)\n }\n\n // The filter is part of the first tab, next to its counter, and only while that tab is selected\n // (the list). With a thread open the tab is just the glyph and the count.\n const threadFilterDropdown = (\n <FilterDropdown\n stateKey=\"threads\"\n filterStates={\n new Map([\n ['done', doneFilter],\n ['me', visibilityFilters.me],\n ['workspace', visibilityFilters.workspace],\n ['meeting', meetingFilter],\n ])\n }\n onFiltersChange={(filters) => {\n setDoneFilter(filters.get('done') ?? null)\n setMeetingFilter(filters.get('meeting') ?? null)\n setVisibilityFilters({\n me: filters.get('me') ?? null,\n workspace: filters.get('workspace') ?? null,\n })\n }}\n options={[\n {\n id: 'me',\n label: 'Only Me',\n count: conversations.filter((thread) => !thread.is_shared).length,\n },\n {\n id: 'workspace',\n label: 'Workspace',\n count: conversations.filter((thread) => thread.is_shared).length,\n },\n {\n id: 'meeting',\n label: 'Meetings',\n count: conversations.filter((thread) => !!thread.meeting_call_ext_id).length,\n },\n {\n id: 'done',\n label: 'Done',\n count: conversations.filter((thread) => thread.status === 'done').length,\n },\n ]}\n hasExternalActiveState={Boolean(threadFilter.trim())}\n renderChevron\n disableHoverOpen\n align=\"start\"\n />\n )\n\n const threadFilterBox = (\n <FilterInput\n filter={threadFilterDropdown}\n borderless\n value={threadFilter}\n onChange={setThreadFilter}\n fields={['text']}\n onFieldsChange={() => {}}\n hideFieldPicker\n ariaLabel=\"Filter threads\"\n // Done threads are hidden by default: say so, or a completed thread looks lost.\n labels={doneFilter === 'exclude' ? { placeholder: 'Done hidden' } : undefined}\n className=\"w-44 max-w-[40vw]\"\n />\n )\n // The list tab counts the threads the list shows (its filters and search applied).\n const { data: workspaceTags = [] } = useTags()\n const { tagId: threadTagId, clear: clearThreadTag } = useThreadTagFilter()\n const historyCount = filterConversationRows(\n threadTagId\n ? conversations.filter((row) => row.label_ext_ids?.includes(threadTagId))\n : conversations,\n threadFilter,\n (row) =>\n workspaceTags\n .filter((tag) => row.label_ext_ids?.includes(tag.external_id))\n .map((tag) => tag.name)\n .join(' '),\n doneFilter,\n visibilityFilters,\n meetingFilter\n ).length\n const historyFiltered =\n Boolean(threadTagId) ||\n Boolean(threadFilter.trim()) ||\n doneFilter !== null ||\n meetingFilter !== null ||\n Object.values(visibilityFilters).some(Boolean)\n\n return (\n <>\n {/* The chat scroll surface is the outer `[data-scroll-container]` (DockZone).\n This column must GROW with its content (not stay viewport-capped) so the\n sticky tab header (top-0) and sticky message-input footer (bottom-0) have\n a containing block that spans the whole thread \u2014 otherwise `position:\n sticky` is clamped to a viewport-tall box and both unpin after one\n screen of scroll. Hence `min-h-full` (fill the scroller, but no phantom\n 100vh scroll inside this nested scroller) + `shrink-0` (don't let the\n flex parent shrink this back below its content). */}\n <ConversationRoot>\n {/* Fixed Tab Header */}\n <ConversationHeader>\n <ConnectedThreadTabs\n historyCount={historyCount}\n historyFiltered={historyFiltered}\n historyActions={\n <div className=\"flex min-w-0 flex-wrap items-center gap-2\">\n {threadFilterBox}\n {threadTagId && (\n <TagFilterChips\n tags={workspaceTags}\n combination={new Map([[threadTagId, 'include']])}\n onChange={clearThreadTag}\n />\n )}\n </div>\n }\n rightContent={(isCompact) => (\n <ConversationHeaderActions>\n {searchEnabled && (\n <SemanticSearchButton\n active={semanticSearchOpen && !isInChat}\n onClick={() => {\n if (isInChat) {\n setActiveTab('history')\n setSemanticSearchOpen(true)\n } else {\n setSemanticSearchOpen((open) => !open)\n }\n }}\n />\n )}\n {isInChat && <ConnectedConversationCallActions />}\n {/* New threads start from the list's launcher: in an open thread, New Task goes\n back to the list with the launcher focused; on the list, the launcher is it. */}\n {isInChat && (\n <NewChatButton\n entityLabel=\"Task\"\n labels={{ newEntity: () => 'New Task' }}\n isCompact={isCompact}\n onClick={() => {\n startNewChat(false)\n }}\n />\n )}\n {/* Starts a fresh conversation in Personal Assistant mode: the first message\n routes through OpenClaw delegation (/v1/openclaw via the /pa handler)\n instead of the RAG pipeline. Gated by the same experimental flag as the\n in-input toggle. */}\n {showPaMode && (\n <NewPaChatButton isCompact={isCompact} onClick={() => startNewChat(true)} />\n )}\n </ConversationHeaderActions>\n )}\n />\n {/* A task thread says what it is: its activity, and Mark done for an editor. Pinned with the tabs. */}\n {isInChat && <ConnectedThreadTaskBar conversationId={currentConversationId} />}\n </ConversationHeader>\n\n {/* The open thread: its messages and the composer. */}\n {isInChat && (\n <ConversationThread\n modelSelector={modelSelector}\n // Left in the composer: what the conversation reads (its documents and facts).\n composerAccessory={\n <ConnectedChatContextButton\n documents={conversationDocuments || []}\n pinnedTitle={pinnedTitle}\n onStatusClick={handleStatusClick}\n onSelectSource={handleSelectSource}\n onAddFromSources={handleGoToDocuments}\n canUpload={canUpload}\n uploadDisabledReason={uploadDisabledReason}\n />\n }\n composerTools={\n isDeveloper && (\n <ConversationSettingsButton\n label={`${getEntityLabel('CONVERSATION')} Settings`}\n onClick={() => openDialog('conversationSettings')}\n />\n )\n }\n />\n )}\n\n {!isInChat && (\n <ConversationHistoryPane>\n {/* Semantic search (opened from the header icon) is a toolbar row atop\n the history view: the list shows through until a search is run, then results\n replace it. */}\n {searchEnabled && semanticSearchOpen ? (\n <ConnectedThreadsPage showHeader={false} search ResultsBoundary={ResultsBoundary} />\n ) : (\n <ConnectedThreadsPage showHeader={false} />\n )}\n </ConversationHistoryPane>\n )}\n </ConversationRoot>\n\n {/* \"From the internet\" dialog, opened from the Upload \u2192 source menu. */}\n <UrlInputDialog\n open={urlDialogOpen}\n onOpenChange={setUrlDialogOpen}\n onUrlsSubmit={uploadUrls}\n titleWorkspaceName={workspace?.name}\n titleIcon={\n workspace && <ConnectedWorkspaceEntity workspace={workspace} size={24} variant=\"icon\" />\n }\n />\n </>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import { useThreadTagFilter } from '../threads/useThreadTagFilter'\nimport { TagFilterChips } from '../tags/TagCombineFilter'\n/** The tabbed conversation page; host-specific composer context stays in a slot. */\nimport { useEffect, useState, type ComponentType, type ReactNode } from 'react'\nimport {\n useArbiSessionStore,\n useArbiSessionState,\n useConversationDocuments,\n useConversationItems,\n useDocuments,\n useTags,\n useWorkspaceRole,\n useUserSettings,\n useTransientView,\n useWorkspaces,\n} from '@arbidocs/react'\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n getDocumentTitle,\n getEntityLabel,\n} from '@arbidocs/react/ui'\nimport { CalendarClock, MoreHorizontal } from 'lucide-react'\nimport { parseVersionRef } from '@arbidocs/react/artifacts'\nimport { ConnectedThreadTabs, useThreadTabs } from '../threads/ConnectedThreadTabs'\nimport { ConnectedThreadTaskBar } from '../tasks/ConnectedThreadTaskBar'\nimport { ConnectedThreadsPage } from '../threads-page/ConnectedThreadsPage'\nimport { ConnectedConversationCallActions } from '../../calls/connected/ConnectedConversationCallActions'\nimport { ConnectedWorkspaceEntity } from '../entities/ConnectedWorkspaceEntity'\nimport { useAddFromUrls } from '../files/upload/useAddFromUrls'\nimport { UrlInputDialog } from '../../files/UrlInputDialog'\nimport { closeDialog, openDialog } from '../../provider/dialog-registry'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { useOpenWorkflow } from '../workflows/useOpenWorkflow'\nimport { filterConversationRows } from '../../agents/tasks/ConversationListView'\nimport { FilterInput } from '../../shell/FilterInput'\nimport { ConnectedFilterDropdown as FilterDropdown } from '../ConnectedFilterDropdown'\nimport {\n ConversationHistoryPane,\n ConversationHeaderActions,\n ConversationSettingsButton,\n NewChatButton,\n NewPaChatButton,\n} from '../../chat/ConversationParts'\nimport { ConversationHeader, ConversationRoot } from '../../chat/ConversationLayout'\nimport { SemanticSearchButton } from './SemanticSearchButton'\nimport { ConversationThread } from './ConnectedConversation'\nimport { ConnectedChatContextButton } from '../chat-context/ConnectedChatContextButton'\nimport type { UploadSource } from '../../provider/environment'\n\nconst DEFAULT_THREAD_VISIBILITY = { me: null, workspace: null } as {\n me: 'include' | 'exclude' | null\n workspace: 'include' | 'exclude' | null\n}\nexport interface ConnectedConversationPageProps {\n /** Controlled selection: opens the stored (or, with null, a new) thread's tab, without route parsing. */\n conversationId?: string | null\n /** The composer's model picker (the host's). Absent: none. */\n modelSelector?: ReactNode\n /** Wraps the conversation search results (the host's crash boundary, say). */\n ResultsBoundary?: ComponentType<{ children: ReactNode }>\n /** Where \"go to documents\" leads. Absent: the environment's `openFiles`. */\n onGoToDocuments?: () => void\n}\n\n/**\n * The open conversation in the tabbed workspace page: its thread tabs, task bar, history with\n * filters and search, and the URL-upload dialog around `ConnectedConversationThread`'s body.\n */\nexport function ConnectedConversationPage({\n conversationId,\n modelSelector,\n ResultsBoundary,\n onGoToDocuments,\n}: ConnectedConversationPageProps) {\n const session = useArbiSessionStore()\n useEffect(() => {\n if (conversationId === undefined) return\n const tabId = conversationId ?? 'new'\n if (session.getState().tabs.activeThread !== tabId) session.openThreadTab(conversationId)\n }, [conversationId, session])\n const { openFiles } = useBlocksEnvironment()\n useEffect(() => () => session.setActiveCitationKey(null), [session])\n const { isInChat, setActiveTab } = useThreadTabs()\n // The list's \"\u2026\": Schedule a task (a rare action), a new scheduled workflow made in the Workflows\n // page's builder; its runs are threads in this list. Absent in an open thread or without workflows.\n const openWorkflow = useOpenWorkflow()\n const [doneFilter, setDoneFilter] = useTransientView(\n 'threads.done',\n 'exclude' as 'include' | 'exclude' | null\n )\n const [visibilityFilters, setVisibilityFilters] = useTransientView(\n 'threads.visibility',\n DEFAULT_THREAD_VISIBILITY\n )\n const [meetingFilter, setMeetingFilter] = useTransientView(\n 'threads.meetings',\n null as 'include' | 'exclude' | null\n )\n const [threadFilter, setThreadFilter] = useTransientView('topbar.filter', '')\n\n // Get experimental flags from API\n const { data: userSettings } = useUserSettings()\n const isDeveloper = userSettings?.developer === true\n const showPaMode = userSettings?.show_pa_mode ?? false\n const searchEnabled = userSettings?.show_conversation_search === true\n // Conversation (message) semantic search is opened from the header icon; it lives on the list, so opening it from a\n // thread goes back to the list first.\n const [semanticSearchOpen, setSemanticSearchOpen] = useState(false)\n\n // Handlers for modals\n const handleSelectSource = (source: UploadSource) => {\n // Match the Files \"Add\" menu exactly: internet opens the URL dialog directly,\n // the others open their focused upload modal. (No processing-modal guard.)\n if (source === 'internet') {\n setUrlDialogOpen(true)\n return\n }\n openDialog('upload', { tab: 'upload', source })\n }\n\n const handleGoToDocuments = () => {\n // Switch to the Documents/Files page instead of opening the in-chat modal\n // preview. Dismiss the modal first in case another entry point left it open.\n closeDialog('conversationDocuments')\n if (onGoToDocuments) onGoToDocuments()\n else openFiles()\n }\n\n const handleStatusClick = () => {\n openDialog('conversationDocuments')\n }\n\n // Get current conversation ID from store\n const currentConversationId = useArbiSessionState((state) => state.conversationId)\n const { conversations: taskItems } = useConversationItems()\n const conversations = taskItems\n\n // Read-only members (`guest`) can read but not upload. Non-members also can't upload.\n const workspaceId = useArbiSessionState((state) => state.workspaceId)\n const { data: workspaces = [] } = useWorkspaces()\n const workspace = workspaces.find((item) => item.external_id === workspaceId)\n const workspaceRole = useWorkspaceRole()\n const isGuest = workspaceRole === 'guest'\n const canUpload = workspaceRole !== null && !isGuest\n\n // \"From the internet\" opens the URL dialog inline (parity with the Files Add\n // menu); it runs the upload itself and surfaces any error in the dialog.\n const [urlDialogOpen, setUrlDialogOpen] = useState(false)\n const uploadUrls = useAddFromUrls({\n onZipFiles: (files) => openDialog('upload', { tab: 'upload', files, source: 'computer' }),\n })\n const uploadDisabledReason = isGuest\n ? 'Read-only members cannot upload documents in this workspace'\n : 'You cannot upload to this workspace'\n\n // What the conversation reads: its documents, and a pinned one.\n const { data: allWorkspaceDocuments = [] } = useDocuments()\n const { data: conversationDocuments } = useConversationDocuments()\n const pinnedDocumentId = useArbiSessionState((state) => state.pinnedDocumentId)\n // A pinned older version (`doc-\u2026@v2`, \"Ask about this version\" in the viewer) names its document.\n const pinnedRef = parseVersionRef(pinnedDocumentId)\n const pinnedDocument =\n conversationDocuments?.find((d) => d.external_id === pinnedRef.docId) ??\n allWorkspaceDocuments?.find((d) => d.external_id === pinnedRef.docId)\n\n const pinnedTitle = pinnedDocument\n ? `${getDocumentTitle(pinnedDocument)}${pinnedRef.version ? ` (version ${pinnedRef.version})` : ''}`\n : null\n\n // Start a new conversation (optionally in Personal Assistant mode) in a new chat tab.\n const startNewChat = (asPaChat: boolean) => {\n session.clearConversationError(currentConversationId || 'new')\n session.startNewConversation()\n session.openThreadTab(null)\n if (asPaChat) session.setPaMode(true)\n }\n\n // The filter is part of the first tab, next to its counter, and only while that tab is selected\n // (the list). With a thread open the tab is just the glyph and the count.\n const threadFilterDropdown = (\n <FilterDropdown\n stateKey=\"threads\"\n filterStates={\n new Map([\n ['done', doneFilter],\n ['me', visibilityFilters.me],\n ['workspace', visibilityFilters.workspace],\n ['meeting', meetingFilter],\n ])\n }\n onFiltersChange={(filters) => {\n setDoneFilter(filters.get('done') ?? null)\n setMeetingFilter(filters.get('meeting') ?? null)\n setVisibilityFilters({\n me: filters.get('me') ?? null,\n workspace: filters.get('workspace') ?? null,\n })\n }}\n options={[\n {\n id: 'me',\n label: 'Only Me',\n count: conversations.filter((thread) => !thread.is_shared).length,\n },\n {\n id: 'workspace',\n label: 'Workspace',\n count: conversations.filter((thread) => thread.is_shared).length,\n },\n {\n id: 'meeting',\n label: 'Meetings',\n count: conversations.filter((thread) => !!thread.meeting_call_ext_id).length,\n },\n {\n id: 'done',\n label: 'Done',\n count: conversations.filter((thread) => thread.status === 'done').length,\n },\n ]}\n hasExternalActiveState={Boolean(threadFilter.trim())}\n renderChevron\n disableHoverOpen\n align=\"start\"\n />\n )\n\n const threadFilterBox = (\n <FilterInput\n filter={threadFilterDropdown}\n borderless\n value={threadFilter}\n onChange={setThreadFilter}\n fields={['text']}\n onFieldsChange={() => {}}\n hideFieldPicker\n ariaLabel=\"Filter threads\"\n // Done threads are hidden by default: say so, or a completed thread looks lost.\n labels={doneFilter === 'exclude' ? { placeholder: 'Done hidden' } : undefined}\n className=\"w-44 max-w-[40vw]\"\n />\n )\n // The list tab counts the threads the list shows (its filters and search applied).\n const { data: workspaceTags = [] } = useTags()\n const { tagId: threadTagId, clear: clearThreadTag } = useThreadTagFilter()\n const historyCount = filterConversationRows(\n threadTagId\n ? conversations.filter((row) => row.label_ext_ids?.includes(threadTagId))\n : conversations,\n threadFilter,\n (row) =>\n workspaceTags\n .filter((tag) => row.label_ext_ids?.includes(tag.external_id))\n .map((tag) => tag.name)\n .join(' '),\n doneFilter,\n visibilityFilters,\n meetingFilter\n ).length\n const historyFiltered =\n Boolean(threadTagId) ||\n Boolean(threadFilter.trim()) ||\n doneFilter !== null ||\n meetingFilter !== null ||\n Object.values(visibilityFilters).some(Boolean)\n\n return (\n <>\n {/* The chat scroll surface is the outer `[data-scroll-container]` (DockZone).\n This column must GROW with its content (not stay viewport-capped) so the\n sticky tab header (top-0) and sticky message-input footer (bottom-0) have\n a containing block that spans the whole thread \u2014 otherwise `position:\n sticky` is clamped to a viewport-tall box and both unpin after one\n screen of scroll. Hence `min-h-full` (fill the scroller, but no phantom\n 100vh scroll inside this nested scroller) + `shrink-0` (don't let the\n flex parent shrink this back below its content). */}\n <ConversationRoot>\n {/* Fixed Tab Header */}\n <ConversationHeader>\n <ConnectedThreadTabs\n historyCount={historyCount}\n historyFiltered={historyFiltered}\n historyActions={\n <div className=\"flex min-w-0 flex-wrap items-center gap-2\">\n {threadFilterBox}\n {threadTagId && (\n <TagFilterChips\n tags={workspaceTags}\n combination={new Map([[threadTagId, 'include']])}\n onChange={clearThreadTag}\n />\n )}\n </div>\n }\n rightContent={(isCompact) => (\n <ConversationHeaderActions>\n {searchEnabled && (\n <SemanticSearchButton\n active={semanticSearchOpen && !isInChat}\n onClick={() => {\n if (isInChat) {\n setActiveTab('history')\n setSemanticSearchOpen(true)\n } else {\n setSemanticSearchOpen((open) => !open)\n }\n }}\n />\n )}\n {isInChat && <ConnectedConversationCallActions />}\n {/* New threads start from the list's launcher: in an open thread, New Task goes\n back to the list with the launcher focused; on the list, the launcher is it. */}\n {isInChat && (\n <NewChatButton\n entityLabel=\"Task\"\n labels={{ newEntity: () => 'New Task' }}\n isCompact={isCompact}\n onClick={() => {\n startNewChat(false)\n }}\n />\n )}\n {/* Starts a fresh conversation in Personal Assistant mode: the first message\n routes through OpenClaw delegation (/v1/openclaw via the /pa handler)\n instead of the RAG pipeline. Gated by the same experimental flag as the\n in-input toggle. */}\n {showPaMode && (\n <NewPaChatButton isCompact={isCompact} onClick={() => startNewChat(true)} />\n )}\n {!isInChat && openWorkflow && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label=\"More actions\"\n data-testid=\"threads-more\"\n >\n <MoreHorizontal className=\"size-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem\n onSelect={() => openWorkflow(undefined, { preset: 'schedule' })}\n data-testid=\"threads-schedule-task\"\n >\n <CalendarClock className=\"size-4\" /> Schedule a task\u2026\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </ConversationHeaderActions>\n )}\n />\n {/* A task thread says what it is: its activity, and Mark done for an editor. Pinned with the tabs. */}\n {isInChat && <ConnectedThreadTaskBar conversationId={currentConversationId} />}\n </ConversationHeader>\n\n {/* The open thread: its messages and the composer. */}\n {isInChat && (\n <ConversationThread\n modelSelector={modelSelector}\n // Left in the composer: what the conversation reads (its documents and facts).\n composerAccessory={\n <ConnectedChatContextButton\n documents={conversationDocuments || []}\n pinnedTitle={pinnedTitle}\n onStatusClick={handleStatusClick}\n onSelectSource={handleSelectSource}\n onAddFromSources={handleGoToDocuments}\n canUpload={canUpload}\n uploadDisabledReason={uploadDisabledReason}\n />\n }\n composerTools={\n isDeveloper && (\n <ConversationSettingsButton\n label={`${getEntityLabel('CONVERSATION')} Settings`}\n onClick={() => openDialog('conversationSettings')}\n />\n )\n }\n />\n )}\n\n {!isInChat && (\n <ConversationHistoryPane>\n {/* Semantic search (opened from the header icon) is a toolbar row atop\n the history view: the list shows through until a search is run, then results\n replace it. */}\n {searchEnabled && semanticSearchOpen ? (\n <ConnectedThreadsPage showHeader={false} search ResultsBoundary={ResultsBoundary} />\n ) : (\n <ConnectedThreadsPage showHeader={false} />\n )}\n </ConversationHistoryPane>\n )}\n </ConversationRoot>\n\n {/* \"From the internet\" dialog, opened from the Upload \u2192 source menu. */}\n <UrlInputDialog\n open={urlDialogOpen}\n onOpenChange={setUrlDialogOpen}\n onUrlsSubmit={uploadUrls}\n titleWorkspaceName={workspace?.name}\n titleIcon={\n workspace && <ConnectedWorkspaceEntity workspace={workspace} size={24} variant=\"icon\" />\n }\n />\n </>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Support form with optional
|
|
1
|
+
/** Support form with optional screenshot evidence and redaction. */
|
|
2
2
|
import React, { type ReactNode } from 'react';
|
|
3
3
|
export interface ReportProblemOptions {
|
|
4
4
|
/** @deprecated No image download is created. Retained for source compatibility. */
|
|
@@ -16,7 +16,7 @@ export interface ReportProblemOptions {
|
|
|
16
16
|
}
|
|
17
17
|
export interface ReportProblemDialogProps extends ReportProblemOptions {
|
|
18
18
|
open: boolean;
|
|
19
|
-
/** The
|
|
19
|
+
/** The captured frame. Dropped once a crop is chosen. */
|
|
20
20
|
frame: Blob | null;
|
|
21
21
|
/** The kept screenshot (the crop, or a picked file). */
|
|
22
22
|
image: Blob | null;
|