correction des pb de space : le spaceId est maintenant dans l'url uniquement
This commit is contained in:
1 parent
c52460bac0
commit
0bb8d1cb46
41 files changed
+1463
-121
No files matched your search
@@ -42,7 +42,6 @@
|
||||
if (data.me) {
|
||||
auth.user = data.me.user
|
||||
space.spaces = data.me.teams
|
||||
space.id = data.me.teams[0].id
|
||||
themeToLocalStorage(auth.user.theme)
|
||||
applyTheme()
|
||||
auth.status = 'authenticated'
|
||||
@@ -63,7 +62,7 @@
|
||||
|
||||
<div id="outer" class={[uiState.sidebarDesktopOpen ? "desktopMenuOpen" : "desktopMenuClosed", uiState.sidebarMobileOpen ? "mobileMenuOpen" : "mobileMenuClosed" ]}>
|
||||
<div id="sidebar" class="flex flex-col">
|
||||
<Sidebar {handleMenuDesktop} {handleMenuMobile}/>
|
||||
<Sidebar spaceid={data.spaceid} {handleMenuDesktop} {handleMenuMobile}/>
|
||||
</div>
|
||||
<div id="main">
|
||||
<div class="flex flex-col h-screen ">
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { userApi } from "$lib/api/endpoints/user"
|
||||
import type { LayoutLoad } from './$types';
|
||||
|
||||
export const load: LayoutLoad = async () => {
|
||||
export const load: LayoutLoad = async ({params}) => {
|
||||
return {
|
||||
spaceid: params.space,
|
||||
me: await userApi.me()
|
||||
}
|
||||
}
|
||||
@@ -1 +1,144 @@
|
||||
<div>Modèles</div>
|
||||
<script lang="ts">
|
||||
|
||||
import { SvelteMap } from 'svelte/reactivity';
|
||||
|
||||
import type { Agent } from '$lib/types/api'
|
||||
import type { PageProps } from './$types';
|
||||
import { agentApi } from "$lib/api/endpoints/agent"
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
//import { validateUrl } from '$lib/utilities/validators'
|
||||
import AgentForm from './AgentForm.svelte'
|
||||
|
||||
let { data }: PageProps = $props();
|
||||
|
||||
let agents = $state([] as Agent[])
|
||||
let addingAgent = $state(false)
|
||||
let editingAgent = $state(null as string|null)
|
||||
let agentForm = $state({} as Agent)
|
||||
let errors = new SvelteMap<string,string>()
|
||||
|
||||
onMount(async ()=>{
|
||||
agents = await agentApi.getAgents(data.space)
|
||||
})
|
||||
|
||||
const handleEnterAddAgent = () => {
|
||||
if (editingAgent) return
|
||||
errors.clear()
|
||||
agentForm = {} as Agent
|
||||
addingAgent= true
|
||||
}
|
||||
|
||||
const handleCancelAddAgent = () => {
|
||||
addingAgent= false
|
||||
}
|
||||
|
||||
const handleSubmitAddAgent = (a: Agent) => {
|
||||
|
||||
if (!a.name) {
|
||||
errors.set("name","Le nom est obligatoire !")
|
||||
}
|
||||
|
||||
if (errors.size === 0) {
|
||||
agentApi.createAgent(data.space, a)
|
||||
.then((p)=>{
|
||||
agents.push(p)
|
||||
addingAgent= false
|
||||
agentForm = {} as Agent
|
||||
})
|
||||
.catch((err)=>{
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleCancelEditAgent = () => {
|
||||
editingAgent = null
|
||||
agentForm = {} as Agent
|
||||
}
|
||||
|
||||
const handleSubmitEditAgent = (a: Agent) => {
|
||||
|
||||
if (!a.name) {
|
||||
errors.set("name","Le nom est obligatoire !")
|
||||
}
|
||||
if (errors.size === 0) {
|
||||
agentApi.updateAgent(data.space,a)
|
||||
.then((p)=>{
|
||||
agents = agents.map((it: Agent)=>{return p.id===it.id ? p : it})
|
||||
editingAgent = null
|
||||
agentForm = {} as Agent
|
||||
})
|
||||
.catch((err)=>{
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleEditAgent = async (id: string) => {
|
||||
errors.clear()
|
||||
if (addingAgent) return
|
||||
agentApi.getAgent(data.space,id)
|
||||
.then((a)=>{
|
||||
agents = agents.filter((it)=>it.id===a.id ? a : it)
|
||||
editingAgent = id
|
||||
})
|
||||
.catch((err)=> console.log(err))
|
||||
}
|
||||
|
||||
const handleDeleteAgent = (id: string) => {
|
||||
agentApi.deleteAgent(data.space,id)
|
||||
.then(() => {
|
||||
agents = agents.filter((it: Agent)=>it.id!==id)
|
||||
})
|
||||
.catch((err) => {console.log(err)})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
|
||||
{#if addingAgent}
|
||||
{#key "new"}
|
||||
<AgentForm
|
||||
item={agentForm}
|
||||
errors={errors}
|
||||
onSave={handleSubmitAddAgent}
|
||||
onCancel={handleCancelAddAgent}
|
||||
providersModels={data.providersModels}
|
||||
/>
|
||||
{/key}
|
||||
{:else}
|
||||
<div class="rounded border border-dashed p-2 border-stone-500 cursor-pointer" onclick={handleEnterAddAgent} tabindex="0">
|
||||
<i class="icon-plus"></i>
|
||||
Ajouter un agent
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#each agents as agent (agent.id) }
|
||||
{#if editingAgent===agent.id}
|
||||
{#key agent.id}
|
||||
<AgentForm
|
||||
item={agent}
|
||||
errors={errors}
|
||||
onSave={handleSubmitEditAgent}
|
||||
onCancel={handleCancelEditAgent}
|
||||
providersModels={data.providersModels}
|
||||
/>
|
||||
{/key}
|
||||
{:else}
|
||||
<div class="rounded border p-2 my-2 border-stone-500 flex">
|
||||
<div class="flex-1">
|
||||
<span>{ agent.name }</span>
|
||||
</div>
|
||||
<button class="bt small mx-1" onclick={()=>handleEditAgent(agent.id)}>
|
||||
<i class="icon-edit"></i>
|
||||
</button>
|
||||
<button class="bt small mx-1" onclick={()=>handleDeleteAgent(agent.id)}>
|
||||
<i class="icon-trash-empty"></i>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
</div>
|
||||
@@ -1,7 +1,14 @@
|
||||
export function load() {
|
||||
import { agentApi } from "$lib/api/endpoints/agent"
|
||||
import {providerApi} from "$lib/api/endpoints/provider"
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
return {
|
||||
title: 'Paramétrage : Agents',
|
||||
back: "/settings",
|
||||
theme: "settings"
|
||||
back: "../settings",
|
||||
theme: "settings",
|
||||
space: params.space,
|
||||
agents: await agentApi.getAgents(params.space),
|
||||
providersModels: await providerApi.getProvidersModels(params.space),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<script lang="ts">
|
||||
|
||||
import FormError from '$lib/components/FormError.svelte';
|
||||
import Select from 'svelte-select/no-styles';
|
||||
import type { Agent, ComplexItem } from "$lib/types/api"
|
||||
|
||||
type Props = {
|
||||
item: Agent
|
||||
providersModels: ComplexItem[],
|
||||
errors: Map<string,string>
|
||||
onSave: (item: Agent) => void
|
||||
onCancel: () => void
|
||||
}
|
||||
let {
|
||||
item,
|
||||
providersModels,
|
||||
errors,
|
||||
onSave,
|
||||
onCancel,
|
||||
}: Props = $props();
|
||||
|
||||
let model = $state("")
|
||||
|
||||
const modelGroupBy = (item: Record<string, unknown>) => item.group as string;
|
||||
|
||||
const autofocus = (node: HTMLElement) => {
|
||||
node.focus();
|
||||
}
|
||||
|
||||
const handleSave = (e: Event) => {
|
||||
e.preventDefault()
|
||||
onSave(item)
|
||||
}
|
||||
|
||||
const handleCancel = (e: Event) => {
|
||||
e.preventDefault()
|
||||
onCancel()
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div class="formgroup my-2">
|
||||
<form onsubmit={handleSave} onchange={()=>{errors.clear()}}>
|
||||
<div class="formelement">
|
||||
<label for="name">Nom</label>
|
||||
<input
|
||||
id="name"
|
||||
type="text"
|
||||
bind:value={item.name}
|
||||
class="textinput"
|
||||
placeholder="nom affiché"
|
||||
use:autofocus
|
||||
/>
|
||||
<FormError key="name" errors={errors} />
|
||||
</div>
|
||||
|
||||
<div class="formelement">
|
||||
<label for="systemPrompt">Prompt système</label>
|
||||
<textarea
|
||||
id="systemPrompt"
|
||||
bind:value={item.systemPrompt}
|
||||
class="textinput"
|
||||
placeholder="prompt système"
|
||||
></textarea>
|
||||
<FormError key="baseUrl" errors={errors} />
|
||||
</div>
|
||||
|
||||
<div class="formelement">
|
||||
<label for="type" class="block my-1 flex-1">Type</label>
|
||||
<Select items={providersModels}
|
||||
valueMode="id"
|
||||
groupBy={modelGroupBy}
|
||||
bind:value={model}
|
||||
/>
|
||||
<FormError key="type" errors={errors} />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="text-right">
|
||||
<span>{item._version}</span>
|
||||
<button type="button" class="bt" onclick={handleCancel}>Annuler</button>
|
||||
<button type="submit" class="bt mx-4">Enregistrer</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
|
||||
onMount(async ()=>{
|
||||
providers = await providerApi.getProviders()
|
||||
providers = await providerApi.getProviders(data.space)
|
||||
})
|
||||
|
||||
const enterAddProviderHandler = () => {
|
||||
@@ -47,7 +47,7 @@
|
||||
errors.set("baseUrl","Mauvaise URL !")
|
||||
}
|
||||
if (errors.size === 0) {
|
||||
providerApi.createProvider(p)
|
||||
providerApi.createProvider(data.space,p)
|
||||
.then((p)=>{
|
||||
providers.push(p)
|
||||
addingProvider= false
|
||||
@@ -76,7 +76,7 @@
|
||||
errors.set("baseUrl","Mauvaise URL !")
|
||||
}
|
||||
if (errors.size === 0) {
|
||||
providerApi.updateProvider(p)
|
||||
providerApi.updateProvider(data.space,p)
|
||||
.then((p)=>{
|
||||
providers = providers.map((it)=>{return p.id===it.id ? p : it})
|
||||
editingProvider = null
|
||||
@@ -91,7 +91,7 @@
|
||||
const handleEditProvider = async (id: string) => {
|
||||
errors.clear()
|
||||
if (addingProvider) return
|
||||
providerApi.getProvider(id)
|
||||
providerApi.getProvider(data.space,id)
|
||||
.then((data)=>{
|
||||
providers = providers.map((it)=>it.id===id ? data : it)
|
||||
editingProvider = id
|
||||
@@ -99,7 +99,7 @@
|
||||
}
|
||||
|
||||
const handleDeleteProvider = (id: string) => {
|
||||
providerApi.deleteProvider(id)
|
||||
providerApi.deleteProvider(data.space,id)
|
||||
.then(() => {
|
||||
providers = providers.filter((it)=>it.id!==id)
|
||||
})
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { providerApi } from "$lib/api/endpoints/provider"
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async () => {
|
||||
export const load: PageLoad = async ({params}) => {
|
||||
return {
|
||||
title: 'Paramétrage : Modèles',
|
||||
back: "/settings",
|
||||
back: "../settings",
|
||||
theme: "settings",
|
||||
space: params.space,
|
||||
providerTypes: await providerApi.providerTypes(),
|
||||
};
|
||||
}
|
||||
@@ -25,8 +25,8 @@ type Selectable = {
|
||||
value: string
|
||||
selected: boolean
|
||||
}
|
||||
let selectedModels = $state(item.models.split(";"))
|
||||
let availableModels : Selectable[]= $state(item.models.split(";").map((it)=> {return {value:it, selected:true}}))
|
||||
let selectedModels = $state(item.models.split("|"))
|
||||
let availableModels : Selectable[]= $state(item.models.split("|").map((it)=> {return {value:it, selected:true}}))
|
||||
let modelsErrors = new SvelteMap<string,string>()
|
||||
|
||||
const autofocus = (node: HTMLElement) => {
|
||||
@@ -35,7 +35,7 @@ const autofocus = (node: HTMLElement) => {
|
||||
|
||||
const handleSave = (e: Event) => {
|
||||
e.preventDefault()
|
||||
item.models = selectedModels.join(";")
|
||||
item.models = selectedModels.join("|")
|
||||
onSave(item)
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ const handleCancel = (e: Event) => {
|
||||
const fetchModels = (e: Event) => {
|
||||
e.preventDefault()
|
||||
modelsErrors.clear()
|
||||
providerApi.getAvailableModels(item)
|
||||
providerApi.getAvailableModels(item.teamId, item)
|
||||
.then((data) => {
|
||||
availableModels = data.map((it)=>{
|
||||
return { value: it, selected: selectedModels.includes(it)}
|
||||
@@ -81,7 +81,7 @@ const handleModelChange = () => {
|
||||
<div class="formelement">
|
||||
<label for="type" class="block my-1 flex-1">Type</label>
|
||||
<Select items={providerTypes}
|
||||
valueMode="id" itemId="id" label="text"
|
||||
valueMode="id"
|
||||
bind:value={item.type}
|
||||
/>
|
||||
<FormError key="type" errors={errors} />
|
||||
@@ -114,7 +114,7 @@ const handleModelChange = () => {
|
||||
</div>
|
||||
|
||||
<div class="formelement">
|
||||
<label for="apiKey">Models</label>
|
||||
<label for="models">Models</label>
|
||||
<button class="bt small" onclick={fetchModels}>
|
||||
Afficher les modèles disponibles
|
||||
</button>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
onMount(async ()=> {
|
||||
addresses = await userApi.listAddresses(form.id)
|
||||
timezones = (await miscApi.listTimezones()).map((it)=>{return {id:it, text:it}})
|
||||
timezones = (await miscApi.listTimezones()).map((it)=>{return {value:it, label:it}})
|
||||
})
|
||||
|
||||
$effect(()=>{
|
||||
@@ -118,7 +118,7 @@
|
||||
|
||||
<div class="formelement">
|
||||
<label for="timezone" class="block my-1 flex-1">Timezone</label>
|
||||
<Select items={timezones} bind:value={form.timezone} valueMode="id" itemId="id" label="text"/>
|
||||
<Select items={timezones} bind:value={form.timezone} valueMode="id" />
|
||||
<FormError key="timezone" errors={errors} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -199,11 +199,11 @@ h2 {
|
||||
}
|
||||
|
||||
.svelte-select-list {
|
||||
@apply absolute right-0 left-0 z-10 max-h-64 w-full overflow-y-auto rounded-sm border-none bg-stone-50 px-4 shadow-md dark:bg-stone-800;
|
||||
@apply absolute right-0 left-0 z-10 max-h-64 w-full overflow-y-auto rounded-sm border-none bg-stone-50 shadow-md dark:bg-stone-800;
|
||||
}
|
||||
|
||||
.svelte-select-list .list-group-title {
|
||||
@apply h-8 cursor-default px-5 text-sm leading-10 font-medium text-ellipsis whitespace-nowrap text-gray-400 uppercase;
|
||||
@apply h-8 cursor-default px-2 text-sm leading-10 font-medium text-ellipsis whitespace-nowrap text-gray-400 uppercase;
|
||||
}
|
||||
|
||||
.svelte-select-list .empty {
|
||||
@@ -215,7 +215,7 @@ h2 {
|
||||
}
|
||||
|
||||
.item.group-item {
|
||||
@apply px-10;
|
||||
@apply px-4;
|
||||
}
|
||||
|
||||
.item.active {
|
||||
|
||||
Reference in new issue
Block a user