Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Super agi api #992

Merged
merged 72 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
c112071
added create-api-key route
Aryan-Singh-14 Jul 29, 2023
b32c737
added models
Aryan-Singh-14 Jul 29, 2023
e848831
API key generation and authentication logic added
Aryan-Singh-14 Jul 31, 2023
41c3c8e
added event listener
Aryan-Singh-14 Jul 31, 2023
91bb8ea
added events
Aryan-Singh-14 Jul 31, 2023
59d2e52
added webhook logic
Aryan-Singh-14 Aug 1, 2023
ff9731d
fixed nonetype issue
Aryan-Singh-14 Aug 1, 2023
ce6256e
add get_organisation_from_api_key
Fluder-Paradyne Aug 1, 2023
6602de2
refactored agent.py
Aryan-Singh-14 Aug 1, 2023
3948353
pause agent,resume agent and get run resources api added
Aryan-Singh-14 Aug 4, 2023
41e1161
removed gui/app/api changes
Aryan-Singh-14 Aug 4, 2023
b222b12
removed ast import (not required in code)
Aryan-Singh-14 Aug 4, 2023
6aa9eae
code refactored
Aryan-Singh-14 Aug 5, 2023
0aed37b
removed comments
Aryan-Singh-14 Aug 5, 2023
637abf1
changed name of fnction in worker.py
Aryan-Singh-14 Aug 5, 2023
9674937
reverted changes in controllers/agent.py
Aryan-Singh-14 Aug 5, 2023
7d74569
added error handling in get_tool_and_toolkit_arr
Aryan-Singh-14 Aug 5, 2023
c31e4fb
removed test_app.py
Aryan-Singh-14 Aug 5, 2023
4f510ba
Merge branch 'dev' of github.com:TransformerOptimus/SuperAGI into sup…
Aryan-Singh-14 Aug 7, 2023
60ce35f
moved logic to models
Aryan-Singh-14 Aug 7, 2023
11a2c37
made changes according to comments of code review
Aryan-Singh-14 Aug 8, 2023
257e062
reverted tools.json changes
Aryan-Singh-14 Aug 8, 2023
c104377
removed whitespaces
Aryan-Singh-14 Aug 8, 2023
fe8ef22
variable renamed, queries optimised and code refactored
Aryan-Singh-14 Aug 9, 2023
90f00ce
api keys frontend, key addition done
namansleeps2 Aug 9, 2023
521d803
removed unused imports
Aryan-Singh-14 Aug 9, 2023
e9f6818
revert tools.json
Aryan-Singh-14 Aug 9, 2023
1b35814
Added get all api keys, delete api key by id and edit api key by id
Aryan-Singh-14 Aug 9, 2023
bcea2c0
renamed controller names
Aryan-Singh-14 Aug 9, 2023
371ed8a
removed unused imports
Aryan-Singh-14 Aug 9, 2023
6d5be27
added error handling in end points which use s3
Aryan-Singh-14 Aug 10, 2023
84f945e
Merge branch 'superAGI_api' of github.com:TransformerOptimus/SuperAGI…
namansleeps2 Aug 10, 2023
4714bfb
error handling added
Aryan-Singh-14 Aug 10, 2023
ff0ea96
creation and displaying of api keys completed
namansleeps2 Aug 10, 2023
b69745f
creation and displaying of api keys completed 2
namansleeps2 Aug 10, 2023
58186f6
test cases added for model functions and end points
Aryan-Singh-14 Aug 14, 2023
3bede4d
renamed update_api_key function
Aryan-Singh-14 Aug 14, 2023
cd2c4f6
resolved a simple merge conflict-1
Aryan-Singh-14 Aug 14, 2023
b4d17a3
added new line
Aryan-Singh-14 Aug 14, 2023
2bcec88
making classes
namansleeps2 Aug 16, 2023
9e06dfd
minor changes
namansleeps2 Aug 16, 2023
fe09e4b
Merge branch 'dev' into superAGI_api
Fluder-Paradyne Aug 16, 2023
8b1b85a
minor changes and complete
namansleeps2 Aug 16, 2023
ebf49ea
fixed indentation
Aryan-Singh-14 Aug 16, 2023
1ec0f06
fixed indentation
Aryan-Singh-14 Aug 16, 2023
818f7ba
Merge branch 'superAGI_api' of github.com:TransformerOptimus/SuperAGI…
Aryan-Singh-14 Aug 16, 2023
c9a5ab1
fixed minor issue
Aryan-Singh-14 Aug 16, 2023
aed8cbd
removed backslash
Aryan-Singh-14 Aug 16, 2023
bf6c257
merge dev
Aryan-Singh-14 Aug 16, 2023
bf544eb
Delete test_path
Aryan-Singh-14 Aug 16, 2023
aaba9e6
fixed tests
Aryan-Singh-14 Aug 16, 2023
d7886c3
Merge remote-tracking branch 'origin/superAGI_api' into superAGI_api
Aryan-Singh-14 Aug 16, 2023
767e472
Merge remote-tracking branch 'origin/dev' into superAGI_api
Aryan-Singh-14 Aug 16, 2023
99946a9
fixed tests
Aryan-Singh-14 Aug 16, 2023
2a1509b
fixed tests
Aryan-Singh-14 Aug 16, 2023
622db7b
fixed tests
Aryan-Singh-14 Aug 16, 2023
5211200
fixed tests
Aryan-Singh-14 Aug 16, 2023
3b4427f
fixed tests
Aryan-Singh-14 Aug 16, 2023
1061bb8
merged UI changes
Aryan-Singh-14 Aug 16, 2023
22cc81a
merged UI changes
Aryan-Singh-14 Aug 16, 2023
2dbeaaf
route change
Fluder-Paradyne Aug 16, 2023
a1adb59
Merge branch 'superAGI_api' of github.com:TransformerOptimus/SuperAGI…
Aryan-Singh-14 Aug 16, 2023
a804294
tweaked routes
Aryan-Singh-14 Aug 16, 2023
431338a
merged dev
Aryan-Singh-14 Aug 16, 2023
068c724
minor changes
namansleeps2 Aug 17, 2023
147b94f
minor changes for PR
namansleeps2 Aug 17, 2023
eecb369
minor changes for PR
namansleeps2 Aug 17, 2023
7e83202
minor fixes
namansleeps2 Aug 17, 2023
16800ab
minor fixes
namansleeps2 Aug 17, 2023
dde538f
minor fixes
namansleeps2 Aug 17, 2023
c859e5e
fix test
Fluder-Paradyne Aug 17, 2023
b5103f0
Merge branch 'superAGI_api' of https://github.com/TransformerOptimus/…
Fluder-Paradyne Aug 17, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ jobs:
ENV: DEV
PLAIN_OUTPUT: True
REDIS_URL: "localhost:6379"
IS_TESTING: True

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
31 changes: 31 additions & 0 deletions gui/pages/Content/Agents/Agents.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -429,4 +429,35 @@
color: #888888 !important;
text-decoration: line-through;
pointerEvents: none !important;
}

.modal_buttons{
display: flex;
justify-content: flex-end;
margin-top: 20px
}

.modal_info_class{
margin-left: -5px;
margin-right: 5px;
}

.table_contents{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-top: 40px;
width: 100%
}

.create_settings_button{
display: flex;
justify-content: center;
align-items: center;
margin-top: 10px
}

.button_margin{
margin-top: -10px;
}
14 changes: 14 additions & 0 deletions gui/pages/Content/Marketplace/Market.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -515,3 +515,17 @@
overflow-y:scroll;
overflow-x:hidden;
}

.settings_tab_button_clicked{
background: #454254;
padding-right: 15px
}

.settings_tab_button{
background: transparent;
padding-right: 15px
}

.settings_tab_img{
margin-top: -1px;
}
286 changes: 286 additions & 0 deletions gui/pages/Dashboard/Settings/ApiKeys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
import React, {useState, useEffect, useRef} from 'react';
import {ToastContainer, toast} from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import agentStyles from "@/pages/Content/Agents/Agents.module.css";
import {
createApiKey, deleteApiKey,
editApiKey, getApiKeys,
} from "@/pages/api/DashboardService";
import {EventBus} from "@/utils/eventBus";
import {createInternalId, loadingTextEffect, preventDefault, removeTab, returnToolkitIcon} from "@/utils/utils";
import Image from "next/image";
import styles from "@/pages/Content/Marketplace/Market.module.css";
import styles1 from "@/pages/Content/Knowledge/Knowledge.module.css";

export default function ApiKeys() {
const [apiKeys, setApiKeys] = useState([]);
const [keyName, setKeyName] = useState('');
const [editKey, setEditKey] = useState('');
const apiKeyRef = useRef(null);
const editKeyRef = useRef(null);
const [editKeyId, setEditKeyId] = useState(-1);
const [deleteKey, setDeleteKey] = useState('')
const [isLoading, setIsLoading] = useState(true)
const [activeDropdown, setActiveDropdown] = useState(null);
const [editModal, setEditModal] = useState(false);
const [deleteKeyId, setDeleteKeyId] = useState(-1);
const [deleteModal, setDeleteModal] = useState(false);
const [createModal, setCreateModal] = useState(false);
const [displayModal, setDisplayModal] = useState(false);
const [apiKeyGenerated, setApiKeyGenerated] = useState('');
const [loadingText, setLoadingText] = useState("Loading Api Keys");



useEffect(() => {
loadingTextEffect('Loading Api Keys', setLoadingText, 500);
fetchApiKeys()
}, []);


const handleModelApiKey = (event) => {
setKeyName(event.target.value);
};

const handleEditApiKey = (event) => {
setEditKey(event.target.value);
};

const createApikey = () => {
if(!keyName){
toast.error("Enter key name", {autoClose: 1800});
return;
}
createApiKey({name : keyName})
.then((response) => {
setApiKeyGenerated(response.data.api_key)
toast.success("Api Key Generated", {autoClose: 1800});
setCreateModal(false);
setDisplayModal(true);
fetchApiKeys();
})
.catch((error) => {
console.error('Error creating api key', error);
});
}
const handleCopyClick = async () => {
if (apiKeyRef.current) {
try {
await navigator.clipboard.writeText(apiKeyRef.current.value);
toast.success("Key Copied", {autoClose: 1800});
} catch (err) {
toast.error('Failed to Copy', {autoClose: 1800});
}
}
};

const fetchApiKeys = () => {
getApiKeys()
.then((response) => {
const formattedData = response.data.map(item => {
return {
...item,
created_at: `${new Date(item.created_at).getDate()}-${["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"][new Date(item.created_at).getMonth()]}-${new Date(item.created_at).getFullYear()}`
};
});
setApiKeys(formattedData)
setIsLoading(false)
})
.catch((error) => {
console.error('Error fetching Api Keys', error);
});
}

const handleEditClick = () => {
if(editKeyRef.current.value.length <1){
toast.error("Enter valid key name", {autoClose: 1800});
return;
}
editApiKey({id: editKeyId,name : editKey})
.then((response) => {
toast.success("Api Key Edited", {autoClose: 1800});
fetchApiKeys();
setEditModal(false);
setEditKey('')
setEditKeyId(-1)
})
.catch((error) => {
console.error('Error editing api key', error);
});
}

const handleDeleteClick = () => {
deleteApiKey(deleteKeyId)
.then((response) => {
toast.success("Api Key Deleted", {autoClose: 1800});
fetchApiKeys();
setDeleteModal(false);
setDeleteKeyId(-1)
setDeleteKey('')
})
.catch((error) => {
toast.error("Error deleting api key", {autoClose: 1800});
console.error('Error deleting api key', error);
});
}

return (<>
<div className="row">
<div className="col-2"></div>
<div className="col-8 col-6-scrollable">
{!isLoading ? <div>
<div className="title_wrapper mb_15">
<div className={styles.page_title}>API Keys</div>
{apiKeys && apiKeys.length > 0 && !isLoading &&
<button className={`${'primary_button mr_20'} ${agentStyles.button_margin}`} onClick={() => {setCreateModal(true); setKeyName('')}}>
Create Key
</button>}
</div>
<div>
<label className={agentStyles.form_label}>Your secret API keys are important and should be kept safe. Do not share them with anyone or expose them in any case.</label>
<label className={agentStyles.form_label}>To help keep your API keys safe, you can store them in a secure location, rotate them regularly, and use different API keys for different applications. By following these tips, you can help protect your account and your data.</label>

{apiKeys.length < 1 && <div className={agentStyles.table_contents}>
<Image width={150} height={60} src="/images/no_permissions.svg" alt="no-permissions"/>
<span className={`${styles.feed_title} ${'mt_8'}`}>No API Keys created!</span>
<div className={agentStyles.create_settings_button}>
<button className="primary_button" onClick={() => {setCreateModal(true); setKeyName('')}}>Create Key
</button>
</div>
</div>}

{apiKeys.length > 0 && <div className="scrollable_container table_container">
<table className="table_css margin_0 padding_0">
<thead>
<tr className="border_top_none">
<th className="table_header w_60">Name</th>
<th className="table_header w_18">Key</th>
<th className="table_header w_18">Created Date</th>
<th className="table_header w_4"></th>
</tr>
</thead>
</table>
<div className="overflow_auto w_100">
<table className="table_css margin_0">
<tbody>
{apiKeys.map((item, index) => (
<tr key={index}>
<td className="table_data w_60">{item.name}</td>
<td className="table_data w_18">{item.key.slice(0, 2) + "****" + item.key.slice(-4)}</td>
<td className="table_data w_18">{item.created_at}</td>
<td className="table_data w_4 cursor_pointer" onMouseLeave={() => setActiveDropdown(null)} onClick={() => {
if (activeDropdown === index) {
setActiveDropdown(null);
} else {
setActiveDropdown(index);
}
}}>
<Image className="rotate_90" width={16} height={16} src="/images/three_dots.svg" alt="run-icon"/>
<div style={activeDropdown === index ? {display: 'block'} : {display: 'none'}} onMouseLeave={() => setActiveDropdown(null)}>
<ul className="dropdown_container">
<li className="dropdown_item" onClick={() => {setEditKey(item.name); setEditKeyId(item.id); setEditModal(true); setActiveDropdown(null);}}>Edit</li>
<li className="dropdown_item" onClick={() => {setDeleteKeyId(item.id); setDeleteKey(item.name) ; setDeleteModal(true); setActiveDropdown(null);}}>Delete</li>
</ul> </div></td>
</tr>
))}
</tbody>
</table>
</div>
</div>}
</div>
</div> : <div className="loading_container">
<div className="signInInfo loading_text">{loadingText}</div>
</div>}
</div>
<div className="col-2"></div>
</div>

{createModal && (<div className="modal" onClick={() => setCreateModal(false)}>
<div className="modal-content w_35" onClick={preventDefault}>
<div className={styles.detail_name}>Create new API Key</div>
<div>
<label className={styles.form_label}>Name</label>
<input placeholder="Enter key name" className="input_medium" type="text" value={keyName} onChange={handleModelApiKey}/>
</div>
<div className={agentStyles.modal_buttons}>
<button className="secondary_button mr_10" onClick={() => setCreateModal(false)}>
Cancel
</button>
<button className="primary_button" onClick={() => createApikey()}>
Create Key
</button>
</div>
</div>
</div>)}

{displayModal && apiKeyGenerated && (<div className="modal" onClick={() => setDisplayModal(false)}>
<div className="modal-content w_35" onClick={preventDefault}>
<div className={styles.detail_name}>{keyName} is created</div>
<div>
<div className="mt_15 mb_25">
<div className={styles1.knowledge_alert}>
<div className={agentStyles.modal_info_class}>
<Image width={20} height={20} src='/images/info.svg' alt="info-icon"/>
</div>
<div>
Your secret API keys are sensitive pieces of information that should be kept confidential. Do not share them with anyone, and do not expose them in any way. If your secret API keys are compromised, someone could use them to access your API and make unauthorized changes to your data. This secret key is only displayed once for security reasons. Please save it in a secure location where you can access it easily.
</div>
</div>
</div>
<div>
<div className="title_wrapper">
<div className="flex_1"><input ref={apiKeyRef} className="input_medium" type="text" value={apiKeyGenerated} disabled />
</div>
<div>
<button className="secondary_button ml_4 padding_5" onClick={handleCopyClick}>
<Image width={20} height={21} src="/images/copy_icon.svg" alt="copy-icon"/>
</button>
</div>
</div>
</div>
</div>
<div className={agentStyles.modal_buttons}>
<button className="primary_button" onClick={() => setDisplayModal(false)}>
OK
</button>
</div>
</div>
</div>)}

{editModal && (<div className="modal" onClick={() => {setEditModal(false); setEditKey(''); setEditKeyId(-1)}}>
<div className="modal-content w_35" onClick={preventDefault}>
<div className={styles.detail_name}>Edit API Key</div>
<div>
<label className={styles.form_label}>Name</label>
<input ref={editKeyRef} placeholder={editKey} className="input_medium" type="text" onChange={handleEditApiKey}/>
</div>
<div className={agentStyles.modal_buttons}>
<button className="secondary_button mr_10" onClick={() => {setEditModal(false); setEditKey(''); setEditKeyId(-1)}}>
Cancel
</button>
<button className="primary_button" onClick={() => handleEditClick()}>
Update Changes
</button>
</div>
</div>
</div>)}

{deleteModal && (<div className="modal" onClick={() => {setDeleteModal(false); setDeleteKeyId(-1); setDeleteKey('')}}>
<div className="modal-content w_35" onClick={preventDefault}>
<div className={styles.detail_name}>Delete {deleteKey} Key</div>
<div>
<label className={styles.form_label}>Deleting this API key will make it unusable. Any API requests made using this key will be rejected. Are you sure you want to proceed?</label>
</div>
<div className={agentStyles.modal_buttons}>
<button className="secondary_button mr_10" onClick={() => {setDeleteModal(false); setDeleteKeyId(-1); setDeleteKey('')}}>
Cancel
</button>
<button className="primary_button" onClick={() => handleDeleteClick()}>
Delete Key
</button>
</div>
</div>
</div>)}
<ToastContainer/>
</>)
}
8 changes: 8 additions & 0 deletions gui/pages/Dashboard/Settings/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import styles from "@/pages/Content/Marketplace/Market.module.css";
import Image from "next/image";
import Model from "@/pages/Dashboard/Settings/Model";
import Database from "@/pages/Dashboard/Settings/Database";
import ApiKeys from "@/pages/Dashboard/Settings/ApiKeys";

export default function Settings({organisationId, sendDatabaseData}) {
const [activeTab, setActiveTab] = useState('model');
Expand Down Expand Up @@ -44,11 +45,18 @@ export default function Settings({organisationId, sendDatabaseData}) {
alt="database-icon"/>&nbsp;Database
</button>
</div>
<div>
<button onClick={() => switchTab('apikeys')} className={`${styles.tab_button} ${activeTab === 'apikeys' ? styles.settings_tab_button_clicked : styles.settings_tab_button}`}>
<Image className={styles.settings_tab_img} width={14} height={14} src="/images/key_white.svg"
alt="database-icon"/>&nbsp;API Keys
</button>
</div>
</div>
</div>
<div>
{activeTab === 'model' && <Model organisationId={organisationId}/>}
{activeTab === 'database' && <Database sendDatabaseData={sendDatabaseData} organisationId={organisationId}/>}
{activeTab === 'apikeys' && <ApiKeys />}
</div>
</div>
</div>
Expand Down
Loading
Loading