Ajout de SEARXNG pour les recherches web

This commit is contained in:
fabien committed 2026-10-05 19:05:24 +02:00
1 parent 87eeb41364
commit 345129c7bf
30 files changed
+919 -166

No files matched your search

+10
View File
@@ -0,0 +1,10 @@
import { api } from '../client';
import type { Tool, ToolParam } from "$lib/types/api"
export const toolApi = {
getTools: (space: string) => api.get<Tool[]>(`/tool/${space}`),
getTool: (space: string, id: string) => api.get<Tool>(`/tool/${space}/${id}`),
getToolParams: (space: string, id: string) => api.get<ToolParam[]>(`/tool/${space}/${id}/params`),
createTool: (space: string,data: Partial<Tool>) => api.post<Tool>(`/tool/${space}`, data),
updateTool: (space: string,data: Partial<Tool>) => api.put<Tool>(`/tool/${space}`, data),
};
+18
View File
@@ -104,6 +104,24 @@ export interface Message {
_version: string
}
export interface Tool {
id: string
teamId: string
name: string
configuration: string
enabled: boolean
_date_created: string
_date_updated: string
_version: string
}
export interface ToolParam {
name: string
type: string
description: string
mandatory: boolean
}
export interface ToolCall {
ID: string
Type: string
@@ -17,9 +17,10 @@
href="settings/tools"
>
Outils
<span class="ml-2 text-xs bg-red-900 text-red-300 rounded-lg p-1">12</span>
<!-- <span class="ml-2 text-xs bg-red-900 text-red-300 rounded-lg p-1">12</span>-->
</a>
<!--
<a class="bt p-5 text-center"
title="Skills"
href="settings/skills">
@@ -58,4 +59,6 @@
Utilisateurs
<span class="ml-2 text-xs bg-red-900 text-red-300 rounded-lg p-1">1</span>
</a>
-->
</div>
@@ -108,7 +108,6 @@
}
const handleKeydown = (event: KeyboardEvent) => {
event.preventDefault()
if (event.key==="Escape") {
handleCancelEditAgent()
}
@@ -149,7 +148,7 @@
/>
{/key}
{:else}
<div class="rounded border p-2 my-2 border-stone-500 flex">
<div class="rounded border p-2 my-2 border-stone-500 flex formgroup">
<div class="flex-1 p-2">
<span>{ agent.name }</span>
</div>
@@ -102,7 +102,6 @@
}
const handleKeydown = (event: KeyboardEvent) => {
event.preventDefault()
if (event.key==="Escape") {
cancelEditProviderHandler()
}
@@ -146,7 +145,7 @@
/>
{/key}
{:else}
<div class="rounded border p-2 my-2 border-stone-500 flex">
<div class="rounded border p-2 my-2 border-stone-500 flex formgroup">
<div class="flex-1 p-2">
<span>{ p.name }</span>
<span class="text-stone-500">({ p.type })</span>
@@ -1 +1,96 @@
<div>Modèles</div>
<script lang="ts">
import { SvelteMap } from 'svelte/reactivity';
import { untrack } from 'svelte';
import type { Tool } from '$lib/types/api'
import type { PageProps } from './$types';
import { toolApi } from "$lib/api/endpoints/tool"
//import { validateUrl } from '$lib/utilities/validators'
import ToolForm from './ToolForm.svelte'
let { data }: PageProps = $props();
let tools = $state(untrack(()=>data.tools))
let adding = $state(false)
let editing = $state(null as string|null)
let errors = new SvelteMap<string,string>()
const cancelEditHandler = () => {
editing = null
}
const submitEdit = (tool: Tool) => {
if (errors.size === 0) {
toolApi.updateTool(data.space,tool)
.then((t)=>{
tools = tools.map((it)=>{return t.id===it.id ? t : it})
editing = null
})
.catch((err)=>{
console.log(err)
})
}
}
const handleEdit = async (id: string) => {
errors.clear()
if (adding) return
toolApi.getTool(data.space,id)
.then((data)=>{
tools = tools.map((it)=>it.id===id ? data : it)
editing = id
})
}
// const handleDelete = (id: string) => {
// toolApi.deleteTool(data.space,id)
// .then(() => {
// tools = tools.filter((it)=>it.id!==id)
// })
// .catch((err) => {console.log(err)})
// }
const handleKeydown = (event: KeyboardEvent) => {
if (event.key==="Escape") {
cancelEditHandler()
}
}
</script>
<svelte:window onkeydown={handleKeydown} />
<div class="container">
{#each tools as t (t.id) }
{#if editing===t.id}
{#key t.id}
<ToolForm
item={t}
errors={errors}
onSave={submitEdit}
onCancel={cancelEditHandler}
/>
{/key}
{:else}
<div class="rounded border p-2 my-2 border-stone-500 flex formgroup">
<div class="flex-1 p-2">
<span>{ t.name }</span>
<span class="text-stone-500">({ t.enabled })</span>
</div>
<button
class="bt small mx-1"
onclick={()=>handleEdit(t.id)}
aria-label="Modifier"
>
<i class="icon-edit"></i>
</button>
</div>
{/if}
{/each}
</div>
@@ -1,6 +1,11 @@
export function load() {
import { toolApi } from "$lib/api/endpoints/tool"
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ params }) => {
return {
title: 'Paramétrage : Outils',
back: "/settings",
back: "../settings",
space: params.space,
tools: await toolApi.getTools(params.space),
};
}
@@ -0,0 +1,100 @@
<script lang="ts">
import FormError from '$lib/components/FormError.svelte'
import { SvelteMap } from 'svelte/reactivity';
import { toolApi } from "$lib/api/endpoints/tool"
import type { Tool, ToolParam } from "$lib/types/api"
import { onMount, untrack } from 'svelte';
type Props = {
item: Tool
errors: Map<string,string>
onSave: (item: Tool) => void
onCancel: () => void
}
let {
item,
errors,
onSave,
onCancel,
}: Props = $props();
let tool = $state(untrack(()=>item))
let toolParams = $state([] as ToolParam[])
let paramValues = new SvelteMap<string, string>();
onMount(async () => {
toolParams = await toolApi.getToolParams(item.teamId, item.id)
paramValues = new SvelteMap<string, string>(Object.entries(JSON.parse(item.configuration)));
})
const autofocus = (node: HTMLElement) => {
node.focus();
}
const handleSave = (e: Event) => {
e.preventDefault()
item.configuration = JSON.stringify(Object.fromEntries(paramValues));
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={tool.name}
class="textinput"
placeholder="nom affiché"
disabled
use:autofocus
/>
<FormError key="name" errors={errors} />
</div>
<div class="formelement">
<label for="enabled">Actif</label>
<input
id="enabled"
type="checkbox"
bind:checked={tool.enabled}
class="checkboxinput"
/>
<FormError key="baseUrl" errors={errors} />
</div>
{#each toolParams as param (param.name)}
<div class="formelement">
<label for={param.name}>{param.name}</label>
<input
id={param.name}
bind:value={() => paramValues.get(param.name) ?? '', (v) => paramValues.set(param.name, v)}
class="textinput"
placeholder={param.description}
/>
<FormError key="baseUrl" errors={errors} />
</div>
{/each}
<div class="text-right">
<button type="button" class="bt" onclick={handleCancel}>Annuler</button>
<button type="submit" class="bt mx-4">Enregistrer</button>
</div>
</form>
</div>
</div>
+6 -3
View File
@@ -137,6 +137,10 @@ h2 {
@apply h-8 w-full rounded border-stone-300 bg-stone-50 px-2 py-1 text-sm text-stone-900 dark:border-stone-700 dark:bg-stone-950 dark:text-stone-100;
}
.checkboxinput {
@apply rounded border border-stone-500 bg-stone-100 text-sm text-stone-900 dark:bg-stone-900 dark:text-stone-100;
}
.areainput {
@apply w-full rounded border-stone-300 bg-stone-50 px-2 py-1 text-sm text-stone-900 dark:bg-stone-950 dark:text-stone-100;
}
@@ -275,8 +279,6 @@ h2 {
/* chat */
.message {
/*@apply rounded p-2;*/
&.user {
@apply bg-sky-500/20 px-2 py-1 text-sky-700 dark:text-sky-300;
}
@@ -318,7 +320,7 @@ h2 {
}
pre {
@apply my-2 rounded p-1 whitespace-pre dark:bg-stone-700;
@apply my-2 rounded px-2 py-1 text-xs dark:bg-stone-700;
}
p {
@@ -328,6 +330,7 @@ h2 {
.message-content {
@apply text-sm;
@apply whitespace-pre-line;
&.reasoning {
@apply text-white/50;