1+ <script >
2+ import { createEventDispatcher } from ' svelte' ;
3+ import { slide } from ' svelte/transition' ;
4+ import { Input } from ' @sveltestrap/sveltestrap' ;
5+ import BotsharpTooltip from ' $lib/common/tooltip/BotsharpTooltip.svelte' ;
6+ import Markdown from ' $lib/common/markdown/Markdown.svelte' ;
7+
8+ const svelteDispatch = createEventDispatcher ();
9+
10+ const duration = 200 ;
11+
12+ /** @type {import('$agentTypes').AgentUtility} */
13+ export let utility;
14+
15+ /** @type {number} */
16+ export let utilityIndex;
17+
18+ /** @type {number} */
19+ export let windowWidth;
20+
21+ /** @type {any} */
22+ export let utilityMapper;
23+
24+ /** @type {any[]} */
25+ export let utilityCategoryOptions;
26+
27+ /** @type {boolean} */
28+ export let collapsed = true ;
29+
30+
31+ /**
32+ * @param {any} e
33+ */
34+ function toggleUtility (e ) {
35+ svelteDispatch (' toggle' , {
36+ utilityIdx: utilityIndex,
37+ checked: e .target .checked
38+ });
39+ }
40+
41+ function deleteUtility () {
42+ svelteDispatch (' delete' , {
43+ utilityIdx: utilityIndex,
44+ field: ' utility'
45+ });
46+ }
47+
48+ function resetUtility () {
49+ svelteDispatch (' reset' , {
50+ utilityIdx: utilityIndex
51+ });
52+ }
53+
54+ /**
55+ * @param {any} e
56+ */
57+ function changeUtilityCategory (e ) {
58+ svelteDispatch (' change' , {
59+ utilityIdx: utilityIndex,
60+ field: ' utility-category' ,
61+ value: e .target .value
62+ });
63+ }
64+
65+ /**
66+ * @param {any} e
67+ */
68+ function changeUtilityName (e ) {
69+ svelteDispatch (' change' , {
70+ utilityIdx: utilityIndex,
71+ field: ' utility-name' ,
72+ value: e .target .value
73+ });
74+ }
75+
76+ /**
77+ * @param {any} e
78+ */
79+ function changeUtilityVisibility (e ) {
80+ svelteDispatch (' change' , {
81+ utilityIdx: utilityIndex,
82+ field: ' utility-visibility' ,
83+ value: e .target .value
84+ });
85+ }
86+
87+ /**
88+ * @param {number} fid
89+ * @param {string} type
90+ */
91+ function deleteUtilityItem (fid , type ) {
92+ svelteDispatch (' delete' , {
93+ utilityIdx: utilityIndex,
94+ field: ' utility-item' ,
95+ subfield: type,
96+ itemIdx: fid
97+ });
98+ }
99+
100+ /**
101+ * @param {any} e
102+ * @param {number} fid
103+ */
104+ function changeUtilityItemVisibility (e , fid ) {
105+ svelteDispatch (' change' , {
106+ utilityIdx: utilityIndex,
107+ field: ' utility-item-visibility' ,
108+ itemIdx: fid,
109+ value: e .target .value
110+ });
111+ }
112+
113+ function toggleCollapse () {
114+ svelteDispatch (' collapse' , {
115+ utilityIdx: utilityIndex,
116+ collapsed: ! collapsed
117+ });
118+ }
119+
120+ /**
121+ * @param {string[]} options
122+ * @param {string} placeholder
123+ */
124+ function getUtilityOptions (options , placeholder = ' ' ) {
125+ let list = options? .sort ((a , b ) => a .localeCompare (b))? .map (x => {
126+ return {
127+ label: x,
128+ value: x
129+ };
130+ }) || [];
131+
132+ list = [{
133+ label: placeholder || ' ' ,
134+ value: ' '
135+ }, ... list];
136+ return list;
137+ }
138+
139+ /**
140+ * @param {string} category
141+ * @param {string} name
142+ * @param {string} key
143+ */
144+ function getUtilityItemDescription (category , name , key ) {
145+ // @ts-ignore
146+ const desc = utilityMapper[category]? .find (x => x .name === name)? .items ? .find (x => x .function_name === key)? .description ;
147+ return desc || ' ' ;
148+ }
149+ < / script>
150+
151+ < div class = " utility-wrapper" >
152+ < div class = " utility-row utility-row-primary" >
153+ < div class = " utility-label fw-bold" >
154+ < div class = " line-align-center" >
155+ < i
156+ class = " bx bx-chevron-right clickable fs-6 collapse-toggle"
157+ class : rotated= {! collapsed}
158+ role= " button"
159+ tabindex= " 0"
160+ on: keydown= {() => {}}
161+ on: click= {() => toggleCollapse ()}
162+ / >
163+ < / div>
164+ < div class = " line-align-center" >
165+ {` Utility #${ utilityIndex + 1 } ` }
166+ < / div>
167+ < div class = " utility-tooltip" >
168+ < div class = " line-align-center" >
169+ < Input
170+ type= " checkbox"
171+ checked= {! utility .disabled }
172+ on: change= {e => toggleUtility (e)}
173+ / >
174+ < / div>
175+ <!-- < div
176+ class = " line-align-center"
177+ data- bs- toggle= " tooltip"
178+ data- bs- placement= " top"
179+ title= " Uncheck to disable utility"
180+ >
181+ < i class = " bx bx-info-circle fs-6" / >
182+ < / div> -->
183+ < / div>
184+ < / div>
185+ < div class = " utility-value" >
186+ < div class = " utility-input line-align-center" >
187+ < Input
188+ type= " select"
189+ value= {utility .category }
190+ disabled= {utility .disabled }
191+ on: change= {e => changeUtilityCategory (e)}
192+ >
193+ {#each utilityCategoryOptions as option}
194+ < option value= {option .value } selected= {option .value == utility .category }>
195+ {option .label }
196+ < / option>
197+ {/ each}
198+ < / Input>
199+ < / div>
200+ < div class = " utility-delete line-align-center" >
201+ < i
202+ class = " bx bxs-no-entry text-danger clickable fs-6"
203+ role= " link"
204+ tabindex= " 0"
205+ on: keydown= {() => {}}
206+ on: click= {() => deleteUtility ()}
207+ / >
208+ < / div>
209+ < / div>
210+ < / div>
211+
212+ {#if ! collapsed}
213+ < div class = " utility-row utility-row-secondary" transition: slide= {{ duration: duration }}>
214+ {#if utility .category }
215+ {
216+ @const utilityOptions = getUtilityOptions (utilityMapper[utility .category ]? .map ((/** @type {any} */ x ) => x .name ), ' Select a utility' )
217+ }
218+ < div class = " utility-content" >
219+ < div class = " utility-list-item" >
220+ < div class = " utility-label d-flex" style= " gap: 10px;" >
221+ < div class = " line-align-center" > {' Name' }< / div>
222+ {#if utility .name }
223+ < div class = " line-align-center" >
224+ <!-- svelte- ignore a11y- click- events- have- key- events -->
225+ <!-- svelte- ignore a11y- no- static - element- interactions -->
226+ < i
227+ class = " mdi mdi-refresh clickable fs-6"
228+ style= " padding-top: 3px;"
229+ data- bs- toggle= " tooltip"
230+ data- bs- placement= " top"
231+ title= " Reset"
232+ on: click= {() => resetUtility ()}
233+ / >
234+ < / div>
235+ {/ if }
236+ < / div>
237+ < div class = " utility-value" >
238+ < div class = " utility-input line-align-center" >
239+ < Input
240+ type= " select"
241+ value= {utility .name }
242+ disabled= {utility .disabled }
243+ on: change= {e => changeUtilityName (e)}
244+ >
245+ {#each utilityOptions as option}
246+ < option value= {option .value } selected= {option .value == utility .name }>
247+ {option .label }
248+ < / option>
249+ {/ each}
250+ < / Input>
251+ < / div>
252+ < div class = " utility-delete line-align-center" >< / div>
253+ < / div>
254+ < / div>
255+ < div class = " utility-list-item" >
256+ < div class = " utility-label line-align-center" >
257+ {' Visibility' }
258+ < / div>
259+ < div class = " utility-value" >
260+ < div class = " utility-input line-align-center" >
261+ < Input
262+ type= " text"
263+ disabled= {utility .disabled }
264+ maxlength= {1000 }
265+ value= {utility .visibility_expression }
266+ on: change= {e => changeUtilityVisibility (e)}
267+ / >
268+ < / div>
269+ < div class = " utility-delete line-align-center" >< / div>
270+ < / div>
271+ < / div>
272+ < / div>
273+ {/ if }
274+ {#each utility .items as item, fid (fid)}
275+ < div class = " utility-content" >
276+ {#if item .function_name }
277+ {
278+ @const description = getUtilityItemDescription (utility .category , utility .name , item .function_name )
279+ }
280+ < div class = " utility-list-item" >
281+ < div class = " utility-label d-flex" style= " gap: 10px;" >
282+ < div class = " line-align-center" > {' Function' }< / div>
283+ {#if description}
284+ < div class = " line-align-center" >
285+ < i
286+ class = " bx bx-info-circle fs-6"
287+ id= {` utility-${ utilityIndex} -${ fid} ` }
288+ / >
289+ < BotsharpTooltip
290+ containerClasses= " agent-utility-desc"
291+ style= {` min-width: ${ Math .floor (windowWidth* 0.3 )} px;` }
292+ target= {` utility-${ utilityIndex} -${ fid} ` }
293+ placement= " right"
294+ persist
295+ >
296+ < Markdown
297+ rawText
298+ scrollable
299+ containerClasses= {' markdown-div' }
300+ containerStyles= {` max-width: ${ Math .floor (windowWidth* 0.55 )} px;` }
301+ text= {description}
302+ / >
303+ < / BotsharpTooltip>
304+ < / div>
305+ {/ if }
306+ < / div>
307+ < div class = " utility-value" >
308+ < div class = " utility-input line-align-center" >
309+ < Input
310+ type= " text"
311+ value= {item .function_display_name }
312+ disabled
313+ / >
314+ < / div>
315+ < div class = " utility-delete line-align-center" >
316+ < i
317+ class = " bx bxs-no-entry text-danger clickable fs-6"
318+ role= " link"
319+ tabindex= " 0"
320+ on: keydown= {() => {}}
321+ on: click= {() => deleteUtilityItem (fid, ' function' )}
322+ / >
323+ < / div>
324+ < / div>
325+ < / div>
326+ {/ if }
327+ {#if item .template_name }
328+ < div class = " utility-list-item" >
329+ < div class = " utility-label line-align-center" >
330+ {' Template' }
331+ < / div>
332+ < div class = " utility-value" >
333+ < div class = " utility-input line-align-center" >
334+ < Input
335+ type= " text"
336+ value= {item .template_display_name }
337+ disabled
338+ / >
339+ < / div>
340+ < div class = " utility-delete line-align-center" >
341+ < i
342+ class = " bx bxs-no-entry text-danger clickable fs-6"
343+ role= " link"
344+ tabindex= " 0"
345+ on: keydown= {() => {}}
346+ on: click= {() => deleteUtilityItem (fid, ' template' )}
347+ / >
348+ < / div>
349+ < / div>
350+ < / div>
351+ {/ if }
352+ < div class = " utility-list-item" >
353+ < div class = " utility-label line-align-center" >
354+ {' Visibility' }
355+ < / div>
356+ < div class = " utility-value" >
357+ < div class = " utility-input line-align-center" >
358+ < Input
359+ type= " text"
360+ disabled= {utility .disabled }
361+ maxlength= {1000 }
362+ value= {item .visibility_expression }
363+ on: change= {e => changeUtilityItemVisibility (e, fid)}
364+ / >
365+ < / div>
366+ < div class = " utility-delete line-align-center" >< / div>
367+ < / div>
368+ < / div>
369+ < / div>
370+ {/ each}
371+ < / div>
372+ {/ if }
373+ < / div>
0 commit comments