diff --git a/application/tools/agent.py b/application/tools/agent.py
index 740e1689..de8ad725 100644
--- a/application/tools/agent.py
+++ b/application/tools/agent.py
@@ -26,6 +26,21 @@ class Agent:
tools_by_id = {str(tool["_id"]): tool for tool in user_tools}
return tools_by_id
+ def _build_tool_parameters(self, action):
+ params = {"type": "object", "properties": {}, "required": []}
+ for param_type in ["query_params", "headers", "body", "parameters"]:
+ if param_type in action and action[param_type].get("properties"):
+ for k, v in action[param_type]["properties"].items():
+ if v.get("filled_by_llm", True):
+ params["properties"][k] = {
+ key: value
+ for key, value in v.items()
+ if key != "filled_by_llm" and key != "value"
+ }
+
+ params["required"].append(k)
+ return params
+
def _prepare_tools(self, tools_dict):
self.tools = [
{
@@ -33,26 +48,7 @@ class Agent:
"function": {
"name": f"{action['name']}_{tool_id}",
"description": action["description"],
- "parameters": {
- **action["parameters"],
- "properties": {
- k: {
- key: value
- for key, value in v.items()
- if key != "filled_by_llm" and key != "value"
- }
- for k, v in action["parameters"]["properties"].items()
- if v.get("filled_by_llm", True)
- },
- "required": [
- key
- for key in action["parameters"]["required"]
- if key in action["parameters"]["properties"]
- and action["parameters"]["properties"][key].get(
- "filled_by_llm", True
- )
- ],
- },
+ "parameters": self._build_tool_parameters(action),
},
}
for tool_id, tool in tools_dict.items()
@@ -79,21 +75,49 @@ class Agent:
)
)
- for param, details in action_data["parameters"]["properties"].items():
- if param not in call_args and "value" in details:
- call_args[param] = details["value"]
+ query_params, headers, body, parameters = {}, {}, {}, {}
+ param_types = {
+ "query_params": query_params,
+ "headers": headers,
+ "body": body,
+ "parameters": parameters,
+ }
+
+ for param_type, target_dict in param_types.items():
+ if param_type in action_data and action_data[param_type].get("properties"):
+ for param, details in action_data[param_type]["properties"].items():
+ if param not in call_args and "value" in details:
+ target_dict[param] = details["value"]
+
+ for param, value in call_args.items():
+ for param_type, target_dict in param_types.items():
+ if param_type in action_data and param in action_data[param_type].get(
+ "properties", {}
+ ):
+ target_dict[param] = value
tm = ToolManager(config={})
tool = tm.load_tool(
tool_data["name"],
tool_config=(
- tool_data["config"]["actions"][action_name]
+ {
+ "url": tool_data["config"]["actions"][action_name]["url"],
+ "method": tool_data["config"]["actions"][action_name]["method"],
+ "headers": headers,
+ "query_params": query_params,
+ }
if tool_data["name"] == "api_tool"
else tool_data["config"]
),
)
- print(f"Executing tool: {action_name} with args: {call_args}")
- result = tool.execute_action(action_name, **call_args)
+ if tool_data["name"] == "api_tool":
+ print(
+ f"Executing api: {action_name} with query_params: {query_params}, headers: {headers}, body: {body}"
+ )
+ result = tool.execute_action(action_name, **body)
+ else:
+ print(f"Executing tool: {action_name} with args: {call_args}")
+ result = tool.execute_action(action_name, **parameters)
call_id = getattr(call, "id", None)
return result, call_id
diff --git a/application/tools/implementations/api_tool.py b/application/tools/implementations/api_tool.py
index da105e39..5d0fec70 100644
--- a/application/tools/implementations/api_tool.py
+++ b/application/tools/implementations/api_tool.py
@@ -15,11 +15,16 @@ class APITool(Tool):
self.url = config.get("url", "")
self.method = config.get("method", "GET")
self.headers = config.get("headers", {"Content-Type": "application/json"})
+ self.query_params = config.get("query_params", {})
def execute_action(self, action_name, **kwargs):
- return self._make_api_call(self.url, self.method, self.headers, kwargs)
+ return self._make_api_call(
+ self.url, self.method, self.headers, self.query_params, kwargs
+ )
- def _make_api_call(self, url, method, headers, body):
+ def _make_api_call(self, url, method, headers, query_params, body):
+ if query_params:
+ url = f"{url}?{requests.compat.urlencode(query_params)}"
if isinstance(body, dict):
body = json.dumps(body)
try:
diff --git a/frontend/src/assets/circle-check.svg b/frontend/src/assets/circle-check.svg
new file mode 100644
index 00000000..f0e8390d
--- /dev/null
+++ b/frontend/src/assets/circle-check.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/circle-x.svg b/frontend/src/assets/circle-x.svg
new file mode 100644
index 00000000..d6bdd2c3
--- /dev/null
+++ b/frontend/src/assets/circle-x.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/index.css b/frontend/src/index.css
index b8cf596e..85d6fced 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -50,11 +50,11 @@ body.dark {
@layer components {
.table-default {
- @apply block w-full table-auto content-start justify-center rounded-xl border border-silver dark:border-silver/40 text-center dark:text-bright-gray overflow-auto;
+ @apply block w-full table-auto justify-center rounded-xl border border-silver dark:border-silver/40 text-center dark:text-bright-gray overflow-auto;
}
.table-default th {
- @apply p-4 font-normal text-gray-400 text-nowrap; /* Remove border-r */
+ @apply p-4 font-normal text-gray-400 text-nowrap;
}
.table-default th {
@@ -62,15 +62,15 @@ body.dark {
}
.table-default th:last-child {
- flex: 0; /* Ensure the last column does not stretch unnecessarily */
+ flex: 0;
}
.table-default td {
- @apply border-t w-full border-silver dark:border-silver/40 px-4 py-2; /* Remove border-r */
+ @apply border-t w-full border-silver dark:border-silver/40 px-4 py-2;
}
.table-default td:last-child {
- @apply border-r-0; /* Ensure no right border on the last column */
+ @apply border-r-0;
}
.table-default th,
diff --git a/frontend/src/modals/AddActionModal.tsx b/frontend/src/modals/AddActionModal.tsx
new file mode 100644
index 00000000..c52d89f8
--- /dev/null
+++ b/frontend/src/modals/AddActionModal.tsx
@@ -0,0 +1,75 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+
+import Exit from '../assets/exit.svg';
+import Input from '../components/Input';
+import { ActiveState } from '../models/misc';
+
+export default function AddActionModal({
+ modalState,
+ setModalState,
+ handleSubmit,
+}: {
+ modalState: ActiveState;
+ setModalState: (state: ActiveState) => void;
+ handleSubmit: (actionName: string) => void;
+}) {
+ const { t } = useTranslation();
+ const [actionName, setActionName] = React.useState('');
+ return (
+
+
+
+
+
+
+ New Action
+
+
+
+ Action Name
+
+ setActionName(e.target.value)}
+ borderVariant="thin"
+ placeholder={'Enter name'}
+ >
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/modals/AddToolModal.tsx b/frontend/src/modals/AddToolModal.tsx
index c1bdb052..d4706431 100644
--- a/frontend/src/modals/AddToolModal.tsx
+++ b/frontend/src/modals/AddToolModal.tsx
@@ -1,11 +1,12 @@
import React, { useRef } from 'react';
+import { useTranslation } from 'react-i18next';
+
import userService from '../api/services/userService';
import Exit from '../assets/exit.svg';
-import { ActiveState } from '../models/misc';
-import { AvailableTool } from './types';
-import ConfigToolModal from './ConfigToolModal';
import { useOutsideAlerter } from '../hooks';
-import { useTranslation } from 'react-i18next';
+import { ActiveState } from '../models/misc';
+import ConfigToolModal from './ConfigToolModal';
+import { AvailableToolType } from './types';
export default function AddToolModal({
message,
@@ -18,12 +19,11 @@ export default function AddToolModal({
setModalState: (state: ActiveState) => void;
getUserTools: () => void;
}) {
- const [availableTools, setAvailableTools] = React.useState(
- [],
- );
- const [selectedTool, setSelectedTool] = React.useState(
- null,
- );
+ const [availableTools, setAvailableTools] = React.useState<
+ AvailableToolType[]
+ >([]);
+ const [selectedTool, setSelectedTool] =
+ React.useState(null);
const [configModalState, setConfigModalState] =
React.useState('INACTIVE');
const modalRef = useRef(null);
@@ -46,7 +46,7 @@ export default function AddToolModal({
});
};
- const handleAddTool = (tool: AvailableTool) => {
+ const handleAddTool = (tool: AvailableToolType) => {
if (Object.keys(tool.configRequirements).length === 0) {
userService
.createTool({
diff --git a/frontend/src/modals/ConfigToolModal.tsx b/frontend/src/modals/ConfigToolModal.tsx
index 4a8ca881..f26029fc 100644
--- a/frontend/src/modals/ConfigToolModal.tsx
+++ b/frontend/src/modals/ConfigToolModal.tsx
@@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
import Exit from '../assets/exit.svg';
import Input from '../components/Input';
import { ActiveState } from '../models/misc';
-import { AvailableTool } from './types';
+import { AvailableToolType } from './types';
import userService from '../api/services/userService';
export default function ConfigToolModal({
@@ -15,13 +15,13 @@ export default function ConfigToolModal({
}: {
modalState: ActiveState;
setModalState: (state: ActiveState) => void;
- tool: AvailableTool | null;
+ tool: AvailableToolType | null;
getUserTools: () => void;
}) {
const { t } = useTranslation();
const [authKey, setAuthKey] = React.useState('');
- const handleAddTool = (tool: AvailableTool) => {
+ const handleAddTool = (tool: AvailableToolType) => {
userService
.createTool({
name: tool.name,
@@ -75,7 +75,7 @@ export default function ConfigToolModal({