diff --git a/src/lib/common/MultiSelect.svelte b/src/lib/common/MultiSelect.svelte
index 7926a80e..9e915c11 100644
--- a/src/lib/common/MultiSelect.svelte
+++ b/src/lib/common/MultiSelect.svelte
@@ -8,7 +8,7 @@
/** @type {string} */
export let tag;
- /** @type {{key: string, value: string}[]} */
+ /** @type {import('$commonTypes').LabelValuePair[]} */
export let options = [];
/** @type {boolean} */
@@ -24,7 +24,7 @@
export let selectedText = '';
/** @type {string[]} */
- export let selectedKeys;
+ export let selectedLabels;
/** @type {string} */
export let containerClasses = "";
@@ -51,10 +51,10 @@
/** @type {boolean} */
let showOptionList = false;
- /** @type {{key: string, value: string, checked: boolean}[]} */
+ /** @type {{label: string, value: string, checked: boolean}[]} */
let innerOptions = [];
- /** @type {{key: string, value: string, checked: boolean}[]} */
+ /** @type {{label: string, value: string, checked: boolean}[]} */
let refOptions = [];
/** @type {string} */
@@ -66,7 +66,7 @@
onMount(() => {
innerOptions = options.map(x => {
return {
- key: x.key,
+ label: x.label,
value: x.value,
checked: false
}
@@ -74,7 +74,7 @@
refOptions = options.map(x => {
return {
- key: x.key,
+ label: x.label,
value: x.value,
checked: false
}
@@ -83,11 +83,11 @@
$: {
innerOptions = innerOptions.map(x => {
- x.checked = !!selectedKeys?.includes(x.key);
+ x.checked = !!selectedLabels?.includes(x.label);
return {...x};
});
refOptions = refOptions.map(x => {
- x.checked = !!selectedKeys?.includes(x.key);
+ x.checked = !!selectedLabels?.includes(x.label);
return {...x};
});
changeDisplayText();
@@ -95,10 +95,10 @@
$: {
if (options.length > refOptions.length) {
- const curKeys = refOptions.map(x => x.key);
- const newOptions = options.filter(x => !curKeys.includes(x.key)).map(x => {
+ const curKeys = refOptions.map(x => x.label);
+ const newOptions = options.filter(x => !curKeys.includes(x.label)).map(x => {
return {
- key: x.key,
+ label: x.label,
value: x.value,
checked: false
};
@@ -147,14 +147,14 @@
*/
function checkOption(e, option) {
innerOptions = innerOptions.map(x => {
- if (x.key == option.key) {
+ if (x.label == option.label) {
x.checked = e == null ? !x.checked : e.target.checked;
}
return { ...x };
});
refOptions = refOptions.map(x => {
- if (x.key == option.key) {
+ if (x.label == option.label) {
x.checked = e == null ? !x.checked : e.target.checked;
}
return { ...x };
@@ -178,9 +178,9 @@
/** @param {boolean} checked */
function syncChangesToRef(checked) {
- const keys = innerOptions.map(x => x.key);
+ const keys = innerOptions.map(x => x.label);
refOptions = refOptions.map(x => {
- if (keys.includes(x.key)) {
+ if (keys.includes(x.label)) {
return {
...x,
checked: checked
@@ -229,7 +229,7 @@
function sendEvent() {
svelteDispatch("select", {
- selecteds: refOptions.filter(x => !!x.checked).map(x => ({ key: x.key, value: x.value }))
+ selecteds: refOptions.filter(x => !!x.checked).map(x => ({ label: x.label, value: x.value }))
});
}
@@ -343,7 +343,7 @@
/>
- {option.value}
+ {option.label}
{/each}
diff --git a/src/lib/helpers/types/agentTypes.js b/src/lib/helpers/types/agentTypes.js
index 97ea3515..21253f9b 100644
--- a/src/lib/helpers/types/agentTypes.js
+++ b/src/lib/helpers/types/agentTypes.js
@@ -131,10 +131,20 @@
/**
* @typedef {Object} AgentUtility
+ * @property {string} category
* @property {string} name
- * @property {boolean} disabled
- * @property {import('$commonTypes').NameBase[]} functions
- * @property {import('$commonTypes').NameBase[]} templates
+ * @property {boolean} disabled
+ * @property {string?} [visibility_expression]
+ * @property {UtilityItem[]} items
+ */
+
+/**
+ * @typedef {Object} UtilityItem
+ * @property {string?} [function_name]
+ * @property {string?} [function_display_name]
+ * @property {string?} [template_name]
+ * @property {string?} [template_display_name]
+ * @property {string?} [visibility_expression]
*/
/**
diff --git a/src/lib/helpers/types/commonTypes.js b/src/lib/helpers/types/commonTypes.js
index 3d3f1b15..657f45ed 100644
--- a/src/lib/helpers/types/commonTypes.js
+++ b/src/lib/helpers/types/commonTypes.js
@@ -17,6 +17,12 @@
* @property {string} name - The name.
*/
+/**
+ * @typedef {Object} LabelValuePair
+ * @property {string} label - The label.
+ * @property {string} value - The value.
+ */
+
/**
* @template T
* @typedef {Object} PagedItems
diff --git a/src/lib/helpers/utils/common.js b/src/lib/helpers/utils/common.js
index 823e8821..daa9d96d 100644
--- a/src/lib/helpers/utils/common.js
+++ b/src/lib/helpers/utils/common.js
@@ -54,8 +54,8 @@ export function formatObject(object) {
/**
- * @param {string?} str
- * @param {string?} prefix
+ * @param {string | null | undefined} str
+ * @param {string | null | undefined} prefix
*/
export function truncateByPrefix(str, prefix) {
if (!str || !prefix) {
diff --git a/src/routes/page/agent/+page.svelte b/src/routes/page/agent/+page.svelte
index 8c653b2b..5f2006f9 100644
--- a/src/routes/page/agent/+page.svelte
+++ b/src/routes/page/agent/+page.svelte
@@ -43,11 +43,12 @@
/** @type {any} */
let unsubscriber;
+ /** @type {import('$commonTypes').LabelValuePair[]} */
const agentTypeOptions = Object.entries(AgentType).map(([k, v]) => (
- { key: v, value: v }
- ));
+ { label: v, value: v }
+ )).sort((a, b) => a.label.localeCompare(b.label));
- /** @type {{ key: string, value: string }[]} */
+ /** @type {import('$commonTypes').LabelValuePair[]} */
let agentLabelOptions = [];
/** @type {string[]} */
@@ -91,7 +92,7 @@
function getAgentLabelOptions() {
return getAgentLabels().then(res => {
- agentLabelOptions = res?.map(x => ({ key: x, value: x })) || [];
+ agentLabelOptions = res?.map(x => ({ label: x, value: x })) || [];
}).catch(() => {
agentLabelOptions = [];
});
@@ -166,13 +167,13 @@
/** @param {any} e */
function selectAgentTypeOption(e) {
// @ts-ignore
- selectedAgentTypes = e.detail.selecteds?.map(x => x.key) || [];
+ selectedAgentTypes = e.detail.selecteds?.map(x => x.label) || [];
}
/** @param {any} e */
function selectAgentLabelOption(e) {
// @ts-ignore
- selectedAgentLabels = e.detail.selecteds?.map(x => x.key) || [];
+ selectedAgentLabels = e.detail.selecteds?.map(x => x.label) || [];
}
function search() {
@@ -221,7 +222,7 @@
placeholder={'Select labels'}
selectedText={'labels'}
searchMode
- selectedKeys={selectedAgentLabels}
+ selectedLabels={selectedAgentLabels}
options={agentLabelOptions}
on:select={e => selectAgentLabelOption(e)}
/>
@@ -229,7 +230,8 @@
tag={'agent-type-select'}
placeholder={'Select types'}
selectedText={'types'}
- selectedKeys={selectedAgentTypes}
+ searchMode
+ selectedLabels={selectedAgentTypes}
options={agentTypeOptions}
on:select={e => selectAgentTypeOption(e)}
/>
diff --git a/src/routes/page/agent/[agentId]/agent-components/agent-utility.svelte b/src/routes/page/agent/[agentId]/agent-components/agent-utility.svelte
index d52b47e5..69f54f87 100644
--- a/src/routes/page/agent/[agentId]/agent-components/agent-utility.svelte
+++ b/src/routes/page/agent/[agentId]/agent-components/agent-utility.svelte
@@ -14,38 +14,18 @@
export let handleAgentChange = () => {};
export const fetchUtilities = () => {
- const candidates = innerUtilities?.filter(x => !!x.name)?.map(x => {
- /** @type {import('$commonTypes').NameBase[]} */
- const functions = [];
- /** @type {import('$commonTypes').NameBase[]} */
- const templates = [];
-
- const uniqueFns = new Set();
- const uniqueTps = new Set();
- const fns = x.functions.filter(f => !!f.name);
- const tps = x.templates.filter(t => !!t.name);
-
- fns.forEach(f => {
- if (!uniqueFns.has(f.name)) {
- functions.push({ ...f });
- uniqueFns.add(f.name);
- }
- });
-
- tps.forEach(t => {
- if (!uniqueTps.has(t.name)) {
- templates.push({ ...t });
- uniqueTps.add(t.name);
- }
- });
-
- return {
- name: x.name,
- disabled: x.disabled,
- functions: functions,
- templates: templates
- };
- });
+ const list = innerUtilities?.filter(x => !!x.category && !!x.name && x.items?.length > 0) || [];
+
+ /** @type {import('$agentTypes').AgentUtility[]} */
+ const candidates = list.reduce((acc, x) => {
+ const tag = `${x.category}##${x.name}`;
+ if (!acc.visited.has(tag)) {
+ // @ts-ignore
+ acc.result.push(x);
+ acc.visited.add(tag);
+ }
+ return acc;
+ }, { result: [], visited: new Set() }).result;
innerRefresh(candidates);
return candidates;
@@ -54,65 +34,39 @@
/** @type {any} */
let utilityMapper = {};
- /** @type {string[]} */
- let utilityOptions = [];
-
/** @type {import('$agentTypes').AgentUtility[]} */
let innerUtilities = [];
onMount(async () =>{
+ init();
getAgentUtilityOptions().then(data => {
const list = data || [];
- list.forEach(item => {
- const fns = item.functions.map(f => {
- return {
- name: f.name,
- displayName: truncateByPrefix(f.name, prefix)
- };
- });
- const tps = item.templates.map(t => {
- return {
- name: t.name,
- displayName: truncateByPrefix(t.name, prefix)
- };
- });
-
- if (!utilityMapper[item.name]) {
- utilityMapper[item.name] = {
- functions: [{
- name: "",
- displayName: ""
- }, ...fns],
- templates: [{
- name: "",
- displayName: ""
- }, ...tps]
- };
- } else {
- const prevFns = utilityMapper[item.name].functions;
- const prevTps = utilityMapper[item.name].templates;
- utilityMapper[item.name].functions = [...prevFns, fns];
- utilityMapper[item.name].templates = [...prevTps, tps];
- }
+ list.forEach(utility => {
+ const content = {
+ name: utility.name,
+ items: utility.items.map(it => ({
+ ...it,
+ function_display_name: truncateByPrefix(it.function_name, prefix),
+ template_display_name: truncateByPrefix(it.template_name, prefix)
+ }))
+ };
+
+ const contents = utilityMapper[utility.category] || [];
+ contents.push(content);
+ utilityMapper[utility.category] = contents;
});
- const names = list.map(x => x.name) || [];
- utilityOptions = ["", ...names];
});
- init();
});
function init() {
const list = agent.utilities?.map(x => {
return {
...x,
- functions: x.functions?.map(f => ({
- ...f,
- displayName: truncateByPrefix(f.name, prefix)
- })) || [],
- templates: x.templates?.map(t => ({
- ...t,
- displayName: truncateByPrefix(t.name, prefix)
- })) || []
+ items: x.items.map(it => ({
+ ...it,
+ function_display_name: truncateByPrefix(it.function_name, prefix),
+ template_display_name: truncateByPrefix(it.template_name, prefix)
+ }))
};
}) || [];
innerRefresh(list);
@@ -122,20 +76,32 @@
* @param {any} e
* @param {number} idx
*/
- function changeUtility(e, idx) {
+ function changeUtilityCategory(e, idx) {
+ const found = innerUtilities.find((_, index) => index === idx);
+ if (!found) return;
+
+ const category = e.target.value;
+ found.category = category;
+ found.name = '';
+ found.items = [];
+ innerRefresh(innerUtilities);
+ handleAgentChange();
+ }
+
+ /**
+ * @param {any} e
+ * @param {number} idx
+ */
+ function changeUtilityName(e, idx) {
const found = innerUtilities.find((_, index) => index === idx);
if (!found) return;
const name = e.target.value;
found.name = name;
- found.functions = [
- // @ts-ignore
- ...utilityMapper[name].functions?.filter(x => !!x.name) || []
- ];
- found.templates = [
- // @ts-ignore
- ...utilityMapper[name].templates?.filter(x => !!x.name) || []
- ];
+
+ const foundUtility = utilityMapper[found.category]?.find((/** @type {any} */ x) => x.name == name);
+ found.items = foundUtility?.items?.map((/** @type {any} */ x) => ({...x})) || [];
+
innerRefresh(innerUtilities);
handleAgentChange();
}
@@ -144,10 +110,10 @@
innerUtilities = [
...innerUtilities,
{
+ category: '',
name: '',
disabled: false,
- functions: [],
- templates: []
+ items: []
}
];
}
@@ -159,69 +125,54 @@
}
/**
+ * @param {any} e
* @param {number} uid
- * @param {string} type
*/
- function addUtilityContent(uid, type) {
+ function changeUtilityVisibility(e, uid) {
const found = innerUtilities.find((_, index) => index === uid);
- if (!found || found.disabled) return;
-
- if (type === 'function') {
- found.functions.push({ name: '', displayName: '' });
- } else if (type === 'template') {
- found.templates.push({ name: '', displayName: '' });
- }
+ if (!found) return;
+ found.visibility_expression = e.target.value || null;
innerRefresh(innerUtilities);
handleAgentChange();
}
/**
+ * @param {any} e
* @param {number} uid
- * @param {number} id
- * @param {string} type
+ * @param {number} fid
*/
- function deleteUtilityContent(uid, id, type) {
- const found = innerUtilities.find((_, index) => index === uid);
- if (!found || found.disabled) return;
+ function changeUtilityItemVisibility(e, uid, fid) {
+ const found = innerUtilities.find((_, index) => index === uid)?.items?.find((_, index) => index === fid);
+ if (!found) return;
- if (type === 'function') {
- const fns = found.functions?.filter((_, index) => index !== id) || [];
- found.functions = fns;
- } else if (type === 'template') {
- const tps = found.templates?.filter((_, index) => index !== id) || [];
- found.templates = tps;
- }
-
+ found.visibility_expression = e.target.value || null;
innerRefresh(innerUtilities);
handleAgentChange();
}
-
/**
- * @param {any} e
* @param {number} uid
- * @param {number} idx
+ * @param {number} fid
* @param {string} type
*/
- function selectContent(e, uid, idx, type) {
- const found = innerUtilities.find((_, index) => index === uid);
- if (!found) return;
+ function deleteUtilityItem(uid, fid, type) {
+ const foundUtility = innerUtilities.find((_, index) => index === uid);
+ const foundItem = foundUtility?.items?.find((_, index) => index === fid);
+ if (!foundUtility || !foundItem) return;
- const vals = e.target.value.split("#");
if (type === 'function') {
- const fn = found.functions?.find((_, index) => index === idx);
- if (fn) {
- fn.name = vals[0];
- fn.displayName = vals[1];
- }
+ foundItem.function_name = null;
+ foundItem.function_display_name = null;
} else if (type === 'template') {
- const tp = found.templates?.find((_, index) => index === idx);
- if (tp) {
- tp.name = vals[0];
- tp.displayName = vals[1];
- }
+ foundItem.template_name = null;
+ foundItem.template_display_name = null;
}
+
+ if (foundItem.function_name == null && foundItem.template_name == null) {
+ foundUtility.items = foundUtility.items.filter((_, index) => index !== fid);
+ }
+
innerRefresh(innerUtilities);
handleAgentChange();
}
@@ -244,10 +195,11 @@
function innerRefresh(list) {
innerUtilities = list?.map(x => {
return {
+ category: x.category,
name: x.name,
disabled: x.disabled,
- functions: x.functions.map(f => ({ ...f })),
- templates: x.templates.map(t => ({ ...t }))
+ visibility_expression: x.visibility_expression,
+ items: x.items.map(it => ({ ...it }))
}
}) || [];
}
@@ -261,6 +213,36 @@
}
handleAgentChange();
}
+
+ /**
+ * @param {string[]} options
+ * @param {string} placeholder
+ */
+ function getUtilityOptions(options, placeholder = '') {
+ let list = options?.sort((a, b) => a.localeCompare(b))?.map(x => {
+ return {
+ label: x,
+ value: x
+ };
+ }) || [];
+
+ list = [{
+ label: placeholder || '',
+ value: ''
+ }, ...list];
+ return list;
+ }
+
+ /** @param {number} uid */
+ function resetUtility(uid) {
+ const found = innerUtilities.find((_, index) => index === uid);
+ if (!found) return;
+
+ const originalItems = utilityMapper[found.category]?.find((/** @type {any} */ x) => x.name === found.name)?.items || [];
+ found.items = [...originalItems];
+ innerRefresh(innerUtilities);
+ handleAgentChange();
+ }
@@ -302,7 +284,7 @@
{ toggleUtility(e, uid); }}
+ on:change={e => toggleUtility(e, uid)}
/>
{ changeUtility(e, uid); }}
+ on:change={e => changeUtilityCategory(e, uid)}
>
- {#each utilityOptions as option}
-
+ {#each getUtilityOptions(Object.keys(utilityMapper), 'Select a category') as option}
+
{/each}
@@ -334,112 +318,140 @@
role="link"
tabindex="0"
on:keydown={() => {}}
- on:click={() => { deleteUtility(uid); }}
+ on:click={() => deleteUtility(uid)}
/>
-
- {#each utility.functions as fn, fid (fid)}
+ {#if utility.category}
+
-
- {fid === 0 ? 'Functions' : ''}
+
+
{'Name'}
+ {#if utility.name}
+
+
+
+ resetUtility(uid)}
+ />
+
+ {/if}
{ selectContent(e, uid, fid, 'function'); }}
+ on:change={e => changeUtilityName(e, uid)}
>
- {#each (utilityMapper[utility.name]?.functions || []) as option}
-
+ {#each getUtilityOptions(utilityMapper[utility.category]?.map((/** @type {any} */ x) => x.name), 'Select a utility') as option}
+
{/each}
-
- {}}
- on:click={() => { deleteUtilityContent(uid, fid, 'function'); }}
- />
-
-
-
- {/each}
-
- {#if utility.functions?.length < limit}
-
-
- {utility.functions.length === 0 ? 'Functions' : ''}
-
-
-
{}}
- on:click={() => { addUtilityContent(uid, 'function'); }}
- />
+
- {/if}
-
-
-
- {#each utility.templates as tp, tid (tid)}
- {tid === 0 ? 'Templates' : ''}
+ {'Visibility'}
{ selectContent(e, uid, tid, 'template'); }}
- >
- {#each (utilityMapper[utility.name]?.templates || []) as option}
-
- {/each}
-
-
-
- {}}
- on:click={() => { deleteUtilityContent(uid, tid, 'template'); }}
+ maxlength={1000}
+ value={utility.visibility_expression}
+ on:change={e => changeUtilityVisibility(e, uid)}
/>
+
- {/each}
-
- {#if utility.templates?.length < limit}
+
+ {/if}
+ {#each utility.items as item, fid (fid)}
+
+ {#if item.function_name}
+
+
+ {'Function'}
+
+
+
+
+
+
+ {}}
+ on:click={() => deleteUtilityItem(uid, fid, 'function')}
+ />
+
+
+
+ {/if}
+ {#if item.template_name}
+
+
+ {'Template'}
+
+
+
+
+
+
+ {}}
+ on:click={() => deleteUtilityItem(uid, fid, 'template')}
+ />
+
+
+
+ {/if}
-
- {utility.templates.length === 0 ? 'Templates' : ''}
+
+ {'Visibility'}
-
{}}
- on:click={() => { addUtilityContent(uid, 'template'); }}
- />
+
+ changeUtilityItemVisibility(e, uid, fid)}
+ />
+
+
- {/if}
-
+
+ {/each}
{/each}