Skip to content

Commit 1dfae15

Browse files
committed
add agent rule action
1 parent 3b8620f commit 1dfae15

7 files changed

Lines changed: 188 additions & 25 deletions

File tree

package-lock.json

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"dependencies": {
4040
"@codemirror/commands": "^6.10.0",
4141
"@codemirror/lang-javascript": "^6.2.4",
42+
"@codemirror/lang-json": "^6.0.2",
4243
"@codemirror/lang-python": "^6.2.1",
4344
"@codemirror/language": "^6.11.3",
4445
"@codemirror/state": "^6.5.2",

src/lib/helpers/types/agentTypes.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,19 @@
229229
* @property {string} criteria
230230
* @property {string?} [displayName]
231231
* @property {boolean} disabled
232+
* @property {AgentAction?} [action]
232233
* @property {any?} [output_args]
233234
* @property {string?} [json_args]
234235
* @property {string?} [statement]
235236
*/
236237

238+
/**
239+
* @typedef {Object} AgentAction
240+
* @property {string?} [name]
241+
* @property {boolean} disabled
242+
* @property {any} [config]
243+
*/
244+
237245

238246
/**
239247
* @typedef {Object} AgentTaskSearchOption

src/lib/scss/custom/pages/_agent.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,11 @@
323323
}
324324
}
325325

326+
.agent-action-config {
327+
min-height: 0px;
328+
max-height: 200px;
329+
}
330+
326331
.code-editor {
327332
max-height: 500px;
328333
overflow-y: auto;

src/lib/services/agent-service.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,16 @@ export async function getAgentRuleOptions() {
115115
return response.data;
116116
}
117117

118+
/**
119+
* Get agent rule actions
120+
* @returns {Promise<string[]>}
121+
*/
122+
export async function getAgentRuleActions() {
123+
const url = endpoints.agentRuleActionsUrl;
124+
const response = await axios.get(url);
125+
return response.data;
126+
}
127+
118128
/**
119129
* Get agent labels
120130
* @param {number?} [size]

src/lib/services/api-endpoints.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export const endpoints = {
4040
agentCreateUrl: `${host}/agent`,
4141
agentUtilityOptionsUrl: `${host}/agent/utility/options`,
4242
agentRuleOptionsUrl: `${host}/rule/triggers`,
43+
agentRuleActionsUrl: `${host}/rule/actions`,
4344
agentLabelsUrl: `${host}/agent/labels`,
4445

4546
// agent code script:

src/routes/page/agent/[agentId]/agent-components/agent-rule.svelte

Lines changed: 159 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
import { onMount } from 'svelte';
33
import Swal from 'sweetalert2';
44
import { Card, CardBody, Input, Button } from '@sveltestrap/sveltestrap';
5-
import { getAgentRuleOptions, generateAgentCodeScript } from '$lib/services/agent-service';
5+
import { getAgentRuleOptions, generateAgentCodeScript, getAgentRuleActions } from '$lib/services/agent-service';
66
import Markdown from '$lib/common/markdown/Markdown.svelte';
77
import BotsharpTooltip from '$lib/common/tooltip/BotsharpTooltip.svelte';
88
import LoadingToComplete from '$lib/common/spinners/LoadingToComplete.svelte';
9+
import CodeScript from '$lib/common/shared/CodeScript.svelte';
910
import { ADMIN_ROLES, AI_PROGRAMMER_AGENT_ID, RULE_TRIGGER_CODE_GENERATE_TEMPLATE } from '$lib/helpers/constants';
1011
import { AgentCodeScriptType } from '$lib/helpers/enums';
1112
import { scrollToBottom } from '$lib/helpers/utils/common';
@@ -42,7 +43,8 @@
4243
return {
4344
trigger_name: x.trigger_name,
4445
disabled: x.disabled,
45-
criteria: x.criteria?.trim()
46+
criteria: x.criteria?.trim(),
47+
action: !!x.action?.name ? x.action : null
4648
};
4749
});
4850
@@ -63,6 +65,9 @@
6365
/** @type {any[]} */
6466
let ruleOptions = [];
6567
68+
/** @type {any[]} */
69+
let actionOptions = [];
70+
6671
/** @type {import('$agentTypes').AgentRule[]} */
6772
let innerRules = [];
6873
@@ -71,24 +76,34 @@
7176
7277
onMount(async () =>{
7378
resizeWindow();
74-
getAgentRuleOptions().then(data => {
75-
const list = data?.map(x => {
76-
return {
77-
name: x.trigger_name,
78-
displayName: "",
79-
output_args: x.output_args,
80-
json_args: x.json_args,
81-
statement: x.statement
82-
};
83-
}) || [];
84-
ruleOptions = [{
85-
name: "",
86-
displayName: ""
87-
}, ...list];
88-
init();
89-
});
79+
Promise.all([
80+
loadAgentRuleOptions(),
81+
loadAgentRuleActions()
82+
]);
9083
});
9184
85+
function loadAgentRuleOptions() {
86+
return new Promise((resolve, reject) => {
87+
getAgentRuleOptions().then(data => {
88+
const list = data?.map(x => {
89+
return {
90+
name: x.trigger_name,
91+
displayName: "",
92+
output_args: x.output_args,
93+
json_args: x.json_args,
94+
statement: x.statement
95+
};
96+
}) || [];
97+
ruleOptions = [{
98+
name: "",
99+
displayName: ""
100+
}, ...list];
101+
init();
102+
resolve('done');
103+
});
104+
});
105+
}
106+
92107
function init() {
93108
const list = agent.rules?.map(x => {
94109
return {
@@ -98,6 +113,18 @@
98113
}) || [];
99114
innerRefresh(list);
100115
}
116+
117+
function loadAgentRuleActions() {
118+
return new Promise((resolve, reject) => {
119+
getAgentRuleActions().then(data => {
120+
const list = data?.map(x => ({ name: x })) || [];
121+
actionOptions = [{
122+
name: ""
123+
}, ...list];
124+
resolve('done');
125+
});
126+
});
127+
}
101128
102129
/**
103130
* @param {any} e
@@ -155,12 +182,25 @@
155182
const found = innerRules.find((_, index) => index === uid);
156183
if (!found) return;
157184
158-
const val = e.target.value;
159185
if (field === 'criteria') {
160-
found.criteria = val;
186+
found.criteria = e.target.value;
187+
innerRefresh(innerRules);
188+
handleAgentChange();
189+
} else if (field === 'action-config') {
190+
if (found.action == null) {
191+
found.action = {
192+
name: '',
193+
disabled: false,
194+
config: {}
195+
};
196+
}
197+
try {
198+
found.action.config = JSON.parse(e.detail?.text || '{}');
199+
handleAgentChange();
200+
} catch {
201+
// ignore invalid JSON while typing
202+
}
161203
}
162-
innerRefresh(innerRules);
163-
handleAgentChange();
164204
}
165205
166206
/**
@@ -258,6 +298,44 @@
258298
return scriptName;
259299
}
260300
301+
/**
302+
* @param {any} e
303+
* @param {number} idx
304+
*/
305+
function changeAction(e, idx) {
306+
const found = innerRules.find((_, index) => index === idx);
307+
if (!found) return;
308+
309+
const val = e.target.value;
310+
found.action = {
311+
...found.action || {},
312+
name: val,
313+
disabled: found.action?.disabled || false
314+
};
315+
innerRefresh(innerRules);
316+
handleAgentChange();
317+
}
318+
319+
/**
320+
* @param {any} e
321+
* @param {number} uid
322+
*/
323+
function toggleAction(e, uid) {
324+
const found = innerRules.find((_, index) => index === uid);
325+
if (!found) return;
326+
327+
if (!found.action) {
328+
found.action = {
329+
name: '',
330+
disabled: false
331+
};
332+
}
333+
334+
found.action.disabled = !e.target.checked;
335+
innerRefresh(innerRules);
336+
handleAgentChange();
337+
}
338+
261339
function resizeWindow() {
262340
windowWidth = window.innerWidth;
263341
windowHeight = window.innerHeight;
@@ -421,6 +499,65 @@
421499
</div>
422500
</div>
423501
</div>
502+
503+
<div class="utility-row utility-row-secondary">
504+
<div class="utility-content">
505+
<div class="utility-list-item">
506+
<div class="utility-label line-align-center">
507+
<div class="d-flex gap-1">
508+
<div class="line-align-center">
509+
{'Action'}
510+
</div>
511+
<div class="line-align-center">
512+
<Input
513+
type="checkbox"
514+
checked={!rule.action?.disabled}
515+
on:change={e => toggleAction(e, uid)}
516+
/>
517+
</div>
518+
</div>
519+
</div>
520+
<div class="utility-value">
521+
<div class="utility-input line-align-center">
522+
<Input
523+
type="select"
524+
disabled={rule.disabled}
525+
on:change={e => changeAction(e, uid)}
526+
>
527+
{#each [...actionOptions] as option}
528+
<option value={option.name} selected={option.name == rule.action?.name}>
529+
{option.name}
530+
</option>
531+
{/each}
532+
</Input>
533+
</div>
534+
<div class="utility-delete line-align-center"></div>
535+
</div>
536+
</div>
537+
{#if rule.action?.name}
538+
<div class="utility-list-item">
539+
<div class="utility-label line-align-center">
540+
<div class="d-flex gap-1">
541+
<div class="line-align-center">
542+
{'Config'}
543+
</div>
544+
</div>
545+
</div>
546+
<div class="utility-value">
547+
<div class="utility-input line-align-center">
548+
<CodeScript
549+
language="json"
550+
containerClasses="agent-action-config"
551+
scriptText={JSON.stringify(rule.action?.config || {}, null, 2)}
552+
on:change={(e) => changeContent(e, uid, 'action-config')}
553+
/>
554+
</div>
555+
<div class="utility-delete line-align-center"></div>
556+
</div>
557+
</div>
558+
{/if}
559+
</div>
560+
</div>
424561
</div>
425562
{/each}
426563

0 commit comments

Comments
 (0)