Skip to content

Commit

Permalink
chore: add listing/deleting creds from user ui
Browse files Browse the repository at this point in the history
  • Loading branch information
ibuildthecloud committed Nov 13, 2024
1 parent 7e2007e commit 13ce204
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 13 deletions.
43 changes: 43 additions & 0 deletions pkg/api/handlers/assistants.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,49 @@ func getUserThread(req api.Context, agentID string) (*v1.Thread, error) {
return newThread, err
}

func (a *AssistantHandler) DeleteCredential(req api.Context) error {
var (
id = req.PathValue("id")
cred = req.PathValue("cred_id")
)

thread, err := getUserThread(req, id)
if err != nil {
return err
}

if err := req.GPTClient.DeleteCredential(req.Context(), thread.Name, cred); err != nil {
return err
}

return nil
}

func (a *AssistantHandler) ListCredentials(req api.Context) error {
var (
id = req.PathValue("id")
)

thread, err := getUserThread(req, id)
if err != nil {
return err
}

creds, err := req.GPTClient.ListCredentials(req.Context(), gptscript.ListCredentialsOptions{
CredentialContexts: []string{thread.Name},
})
if err != nil {
return err
}

var result types.CredentialList
for _, cred := range creds {
result.Items = append(result.Items, convertCredential(cred))
}

return req.Write(result)
}

func (a *AssistantHandler) Events(req api.Context) error {
var (
id = req.PathValue("id")
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ func Router(services *services.Services) (http.Handler, error) {

// Assistants
mux.HandleFunc("GET /api/assistants", assistants.List)
mux.HandleFunc("GET /api/assistants/{id}/credentials", assistants.ListCredentials)
mux.HandleFunc("DELETE /api/assistants/{id}/credentials/{cred_id}", assistants.DeleteCredential)
mux.HandleFunc("GET /api/assistants/{id}/events", assistants.Events)
mux.HandleFunc("POST /api/assistants/{id}/invoke", assistants.Invoke)
mux.HandleFunc("GET /api/assistants/{id}/tools", assistants.Tools)
Expand Down
69 changes: 59 additions & 10 deletions ui/user/src/lib/components/navbar/Profile.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
<script lang="ts">
import ProfileIcon from '$lib/components/profile/ProfileIcon.svelte';
import { profile } from '$lib/stores';
import { profile, currentAssistant } from '$lib/stores';
import { popover } from '$lib/actions';
import { ChatService, type CredentialList } from '$lib/services';
import { Trash } from '$lib/icons';
import Loading from '$lib/icons/Loading.svelte';
const { ref, tooltip, toggle } = popover({
placement: 'bottom-end'
});
let credPromise = $state<Promise<CredentialList>>();
async function deleteCred(name: string) {
await ChatService.deleteCredential($currentAssistant.id, name);
credPromise = ChatService.listCredentials($currentAssistant.id);
}
function loadCredsAndToggle() {
if ($currentAssistant.id) {
credPromise = ChatService.listCredentials($currentAssistant.id);
}
toggle();
}
</script>

<!-- Profile -->
<div class="ml-1 flex items-center" use:ref>
<button
onclick={toggle}
onclick={loadCredsAndToggle}
type="button"
class="flex rounded-full bg-gray-800 text-sm focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"
>
Expand All @@ -28,6 +45,36 @@
{$profile.email || 'Anonymous'}
</p>
</div>
<div class="px-4 py-3" role="none">
{#if credPromise !== undefined}
{#await credPromise}
<p class="mb-1 truncate text-sm text-gray-900 dark:text-white" role="none">
Credentials <Loading class="mb-0.5 ms-1 h-3 w-3" />
</p>
{:then credentials}
<p class="mb-1 truncate text-sm text-gray-900 dark:text-white" role="none">Credentials</p>
{#if credentials?.items.length > 0}
<ul class="py-1" role="none">
{#each credentials.items as cred}
<li class="flex">
<span class="flex-1 py-2 text-sm text-black dark:text-white">{cred.name}</span>
<button>
<Trash
class="h-5 w-5 text-gray-400"
onclick={() => {
deleteCred(cred.name);
}}
/>
</button>
</li>
{/each}
</ul>
{:else}
<span class="flex-1 py-2 text-sm text-black dark:text-white">No credentials</span>
{/if}
{/await}
{/if}
</div>
<ul class="py-1" role="none">
{#if $profile.role === 1}
<li>
Expand All @@ -39,14 +86,16 @@
>
</li>
{/if}
<li>
<a
href="/oauth2/sign_out?rd=/"
rel="external"
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-white dark:hover:bg-gray-600 dark:hover:text-white"
role="menuitem">Sign out</a
>
</li>
{#if $profile.email}
<li>
<a
href="/oauth2/sign_out?rd=/"
rel="external"
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-white dark:hover:bg-gray-600 dark:hover:text-white"
role="menuitem">Sign out</a
>
</li>
{/if}
</ul>
</div>
</div>
4 changes: 1 addition & 3 deletions ui/user/src/lib/components/profile/ProfileIcon.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
<script lang="ts">
import { run } from 'svelte/legacy';
import { profile } from '$lib/stores';
let initials = $state('08');
run(() => {
$effect(() => {
if ($profile.email) {
const parts = $profile.email.split('@')[0].split(/[.-]/);
initials = parts[0].charAt(0).toUpperCase();
Expand Down
4 changes: 4 additions & 0 deletions ui/user/src/lib/services/chat/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
getProfile,
listFiles,
listAssistants,
listCredentials,
deleteCredential,
getFile,
listKnowledgeFiles,
uploadKnowledge,
Expand All @@ -21,6 +23,8 @@ export default {
listFiles,
listAssistants,
listKnowledgeFiles,
listCredentials,
deleteCredential,
uploadKnowledge,
deleteKnowledgeFile,
deleteFile,
Expand Down
13 changes: 13 additions & 0 deletions ui/user/src/lib/services/chat/operations.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
type Assistants,
type AssistantToolList,
type CredentialList,
type Files,
type KnowledgeFile,
type KnowledgeFiles,
Expand Down Expand Up @@ -76,6 +77,18 @@ export async function invoke(assistant: string, msg: string | object) {
await doPost(`/assistants/${assistant}/invoke`, msg);
}

export async function listCredentials(assistant: string): Promise<CredentialList> {
const list = (await doGet(`/assistants/${assistant}/credentials`)) as CredentialList;
if (!list.items) {
list.items = [];
}
return list;
}

export async function deleteCredential(assistant: string, id: string) {
return doDelete(`/assistants/${assistant}/credentials/${id}`);
}

export async function listTools(assistant: string): Promise<AssistantToolList> {
const list = (await doGet(`/assistants/${assistant}/tools`)) as AssistantToolList;
if (!list.items) {
Expand Down
8 changes: 8 additions & 0 deletions ui/user/src/lib/services/chat/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,11 @@ export interface AssistantToolList {
readonly?: boolean;
items: AssistantTool[];
}

export interface Credential {
name: string;
}

export interface CredentialList {
items: Credential[];
}

0 comments on commit 13ce204

Please sign in to comment.