Skip to content

Commit 2f5234f

Browse files
committed
agent run task
1 parent e4f6bbf commit 2f5234f

File tree

11 files changed

+189
-16
lines changed

11 files changed

+189
-16
lines changed

src/lib/helpers/types.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
* @property {string} [type]
9292
* @property {boolean} [isPublic]
9393
* @property {boolean} [disabled]
94+
* @property {string[]} [agentIds]
9495
*/
9596

9697
/**
@@ -123,6 +124,12 @@
123124
* @property {AgentLlmConfig} llmConfig - LLM settings.
124125
*/
125126

127+
/**
128+
* @typedef {Object} InstructMessageModel
129+
* @property {string} [instruction] - User provided prompt instead of predefined template.
130+
* @property {string} [template] - The template name.
131+
*/
132+
126133
/**
127134
* @typedef {Object} RoutingRule
128135
* @property {string} type
@@ -152,10 +159,10 @@
152159
* @property {string} title - The conversation title.
153160
* @property {UserModel} user - The conversation initializer.
154161
* @property {string} agent_id - The conversation agent id.
162+
* @property {string} agent_name - The conversation entry agent name.
155163
* @property {string} channel - The conversation status.
156164
* @property {string} status - The conversation status.
157165
* @property {Object[]} states - The conversation states.
158-
* @property {number} unread_msg_count - The unread message count.
159166
* @property {Date} updated_time - The conversation updated time.
160167
* @property {Date} created_time - The conversation created time.
161168
*/

src/lib/services/agent-service.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ export async function getAgents(filter) {
2020
let url = endpoints.agentListUrl;
2121
const response = await axios.get(url, { params: filter,
2222
paramsSerializer: {
23-
dots: true
23+
dots: true,
24+
indexes: null,
2425
}
2526
});
2627
return response.data;

src/lib/services/api-endpoints.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ export const endpoints = {
2323
agentDetailUrl: `${host}/agent/{id}`,
2424
agentRefreshUrl: `${host}/refresh-agents`,
2525

26+
// agent instruct
27+
instructCompletionUrl: `${host}/instruct/{agentId}`,
28+
2629
// router
2730
routerSettingUrl: `${host}/router/settings`,
2831

src/lib/services/auth-service.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ export async function getToken(email, password, onSucceed) {
2121
return response.json();
2222
} else {
2323
alert(response.statusText);
24+
return false
2425
}
2526
}).then(result => {
27+
if (!result) {
28+
return;
29+
}
2630
let user = getUserStore();
2731
user.token = result.access_token;
2832
userStore.set(user);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { endpoints } from '$lib/services/api-endpoints.js';
2+
import { replaceUrl } from '$lib/helpers/http';
3+
import axios from 'axios';
4+
5+
/**
6+
* Execute agent instruction by template or user provided prompt.
7+
* @param {string} agentId
8+
* @param {import('$types').InstructMessageModel} instruction
9+
*/
10+
export async function executeAgentInstruction(agentId, instruction) {
11+
let url = replaceUrl(endpoints.conversationInitUrl, {agentId: agentId});
12+
await axios.post(url, instruction);
13+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<script>
2+
import { Col, Row } from '@sveltestrap/sveltestrap';
3+
import Breadcrumb from '$lib/common/Breadcrumb.svelte';
4+
import HeadTitle from '$lib/common/HeadTitle.svelte';
5+
import { getAgents } from '$lib/services/agent-service.js';
6+
import TaskFlow from './task-flow.svelte'
7+
import { onMount } from 'svelte';
8+
import { page } from '$app/stores';
9+
const params = $page.params;
10+
11+
/** @type {import('$types').AgentModel} */
12+
let agent;
13+
let isRouterNodeSelected = false;
14+
let isAgentNodeSelected = false;
15+
16+
/** @type {import('$types').AgentFilter} */
17+
const filter = {
18+
pager: { page: 1, size: 20, count: 0 },
19+
agentIds: [params.agentId],
20+
};
21+
22+
onMount(async () => {
23+
const response = await getAgents(filter);
24+
agent = response.items[0];
25+
});
26+
27+
function handleUserNodeSelected() {
28+
isRouterNodeSelected = false;
29+
isAgentNodeSelected = false;
30+
}
31+
32+
</script>
33+
34+
<HeadTitle title="Task Flow" />
35+
<Breadcrumb title="Agent" pagetitle="Task" />
36+
37+
{#if agent}
38+
<Row>
39+
<Col>
40+
<TaskFlow agent={agent}
41+
on:userNodeSelected={(e) => handleUserNodeSelected()}/>
42+
</Col>
43+
</Row>
44+
{/if}
45+
46+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script>
2+
import Breadcrumb from '$lib/common/Breadcrumb.svelte';
3+
import HeadTitle from '$lib/common/HeadTitle.svelte';
4+
import { onMount } from 'svelte';
5+
import { page } from '$app/stores';
6+
import { executeAgentInstruction } from '$lib/services/instruct-service.js';
7+
const params = $page.params;
8+
let agentId = params.agentId;
9+
let template = params.template;
10+
11+
onMount(async () => {
12+
/** @type {import('$types').InstructMessageModel} */
13+
let inst = {
14+
template: template
15+
};
16+
await executeAgentInstruction(agentId, inst);
17+
});
18+
</script>
19+
20+
<HeadTitle title="Task Execution" />
21+
<Breadcrumb title="Task" pagetitle={template} />
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<script>
2+
import Drawflow from 'drawflow';
3+
import 'drawflow/dist/drawflow.min.css';
4+
import '$lib/drawflow/drawflow.css';
5+
import { onMount, createEventDispatcher } from 'svelte';
6+
7+
/** @type {import('$types').AgentModel} */
8+
export let agent;
9+
/** @type {import('$types').AgentTemplate[]} */
10+
let taskNodes = [];
11+
12+
const dispatch = createEventDispatcher();
13+
14+
onMount(async () => {
15+
const container = document.getElementById("drawflow");
16+
if (container) {
17+
const editor = new Drawflow(container);
18+
editor.reroute = true;
19+
editor.reroute_fix_curvature = true;
20+
editor.start();
21+
editor.on('nodeCreated', function(id) {
22+
let node = editor.getNodeFromId(id);
23+
node.data.nid = id;
24+
console.log(`Node created ${id} ${node.data.agent}`);
25+
taskNodes.push(node.data);
26+
});
27+
editor.on('nodeSelected', function(id) {
28+
console.log("Node selected " + id);
29+
// emit event
30+
});
31+
renderTaskFlow(editor);
32+
}
33+
});
34+
35+
/** @param {Drawflow} editor */
36+
function renderTaskFlow(editor){
37+
let posX = 0;
38+
const nodeSpaceX = 300, nodeSpaceY = 120;
39+
40+
let posY = nodeSpaceY * (agent.templates.length + 1) / 2;
41+
42+
// add end-user node
43+
let agentNodeId = editor.addNode('agent', 0, 1, posX, posY, 'agent',
44+
{
45+
id: ""
46+
}, `<img src=${agent.icon_url} height="30" /><span class="h6">${agent.name}</span>`, false);
47+
48+
posY = 100;
49+
posX += nodeSpaceX;
50+
agent.templates.forEach(template => {
51+
const chatTestLinkHtml = `<a href= "/page/agent/${agent.id}/task/${template.name}" class="btn btn-primary float-end" target="_blank"><i class="bx bx-run"></i></a>`;
52+
let html = `<span class="h6">${template.name}</span>${chatTestLinkHtml}`;
53+
54+
const data = {
55+
id: agent.id,
56+
agent: agent.name
57+
};
58+
let nid = editor.addNode('agent', 1, 0, posX, posY, 'enabled-node', data, html, false);
59+
editor.addConnection(agentNodeId, nid, "output_1", "input_1");
60+
61+
posY += nodeSpaceY;
62+
});
63+
}
64+
65+
/** @param {import('$types').AgentModel} router */
66+
function getPlannerName(router) {
67+
const planner = router.routing_rules.find(p => p.type == "planner");
68+
return planner?.field ?? "NaviePlanner";
69+
}
70+
</script>
71+
72+
<div id="drawflow" style="height: 75vh; width: 100%">
73+
</div>

src/routes/page/agent/router/routing-flow.svelte

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@
6363
6464
// add router node
6565
posX += nodeSpaceX;
66-
let hostNodeId = 0;
6766
let routerPosY = nodeSpaceY * (routers.length + 1) / 2;
6867
routers.forEach(router => {
6968
let profiles = [];
@@ -82,13 +81,10 @@
8281
type: router.type,
8382
};
8483
85-
let nodeId = 0;
8684
if (router.is_host) {
87-
nodeId = editor.addNode('host', 1, 1, posX, routerPosY, 'router', data, `<img src="/images/users/bot.png" height="30">${html}`, false);
88-
hostNodeId = nodeId;
89-
} else {
90-
nodeId = editor.addNode('router', 1, 1, posX, routerPosY, 'router', data, `${html}`, false);
85+
html =`<img src="/images/users/bot.png" height="30">${html}`;
9186
}
87+
let nodeId = editor.addNode('router', 1, 1, posX, routerPosY, 'router', data, `${html}`, false);;
9288
// connect user and router
9389
editor.addConnection(userNodeId, nodeId, `output_1`, `input_1`);
9490
routerPosY += nodeSpaceY * (agents.length - 1) / 2;
@@ -99,11 +95,16 @@
9995
agents.forEach(agent => {
10096
let profiles = [];
10197
const chatTestLinkHtml = `<a href= "/chat/${agent.id}" class="btn btn-primary float-end" target="_blank"><i class="bx bx-chat"></i></a>`;
102-
let html = `<span class="h6">${agent.name}</span>${chatTestLinkHtml}`;
98+
const taskLinkHtml = `<a href= "/page/agent/${agent.id}/task" class="btn btn-primary float-end" target="_blank"><i class="bx bx-task"></i></a>`;
99+
let html = `<span class="h6">${agent.name}</span>${chatTestLinkHtml}${taskLinkHtml}`;
103100
if (agent.profiles.length > 0) {
104101
profiles = agent.profiles;
105102
html += `<br/><i class="mdi mdi-folder font-size-16 text-info me-2"></i>` + profiles.join(', ');
106103
}
104+
105+
if (agent.is_host) {
106+
html =`<img src="/images/users/bot.png" height="30">${html}`;
107+
}
107108
108109
const data = {
109110
id: agent.id,
@@ -122,17 +123,19 @@
122123
editor.addConnection(r.nid, nid, `output_1`, `input_1`);
123124
} else {
124125
// editor.removeNodeInput(nid, "input_2");
125-
editor.addConnection(userNodeId, nid, `output_1`, `input_1`);
126+
// editor.addConnection(userNodeId, nid, `output_1`, `input_1`);
126127
}
127128
});
128129
});
129130
130131
} else {
131132
// profile is empty
132-
agentNodes.filter(ag => ag.type == "routing" && ag.profiles.length == 0)
133+
/*agentNodes.filter(ag => ag.type == "routing" && ag.profiles.length == 0)
133134
.forEach(r => {
134135
editor.addConnection(r.nid, nid, `output_1`, `input_1`);
135-
});
136+
});*/
137+
138+
editor.addConnection(userNodeId, nid, `output_1`, `input_1`);
136139
}
137140
138141
posY += nodeSpaceY;
@@ -143,13 +146,13 @@
143146
if (fallback) {
144147
let router = agentNodes.find(ag => ag.id == fallback.redirectTo);
145148
editor.addNodeOutput(nid);
146-
/*editor.addNodeInput(router.nid);
149+
editor.addNodeInput(router.nid);
147150
var inputs = editor.getNodeFromId(router.nid).inputs;
148151
let inputId = 0;
149152
for (let prop in inputs) {
150153
inputId++;
151154
}
152-
editor.addConnection(nid, router.nid, `output_1`, `input_${inputId}`); */
155+
editor.addConnection(nid, router.nid, `output_1`, `input_${inputId}`);
153156
}
154157
});
155158
}

src/routes/page/conversation/+page.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@
214214
<tr>
215215
<th scope="col">Title</th>
216216
<th scope="col">User Name</th>
217-
<th scope="col">Role</th>
217+
<th scope="col">Agent</th>
218218
<th scope="col">Channel</th>
219219
<th scope="col">Posted Date</th>
220220
<th scope="col">Last Date</th>
@@ -228,7 +228,7 @@
228228
<td scope="row">
229229
<a href="/page/conversation/{conv.id}">{conv.title}</a></td>
230230
<td>{conv.user.full_name}</td>
231-
<td>{conv.user.role}</td>
231+
<td>{conv.agent_name}</td>
232232
<td><span class="badge badge-soft-success">{conv.channel}</span></td>
233233
<td>{utcToLocal(conv.created_time)}</td>
234234
<td>{utcToLocal(conv.updated_time)}</td>

0 commit comments

Comments
 (0)