Cordis-brygga
Cordis-bryggan bäddar in DeepSeek Harness-motorn (DSH) i Libre WebUI:s backend. DSH körs som ett pluginträd i en Cordis-miljö som Libre WebUI tillhandahåller. Funktionerna kommer därför som Cordis-tjänster i stället för importerade moduler.
Bryggan är avstängd som standard. Inget på den här sidan sker förrän en operatör aktiverar den (se Cordis-konfiguration).
Varför en brygga i stället för direkt integration
Att importera DSH-paket från Libre WebUI:s tjänster vore kortare men sämre. Direkt import gör motorn till ett kompileringsberoende. Att byta modelladapter, ersätta agentloopen eller ta bort motorn kräver då ändringar och ny driftsättning av Libre WebUI.
Bryggan vänder på detta. Libre WebUI beror på ett enda abstrakt kontrakt, och ett Cordis-kompositionsdokument avgör vad som uppfyller det:
- Byt mål utan ombyggnad. Kompositionen är en YAML-fil, så att rikta motorn mot en annan leverantör är en konfigurationsändring.
- Konfigurera funktioner. Varje funktion är en Loader-rad. Operatörens ändringar tillämpas nästa gång värden startar.
- Ta bort utan rester. Varje tjänst, lyssnare och effekt som motorn installerar ägs av rotfibern. När den avvecklas tas allt bort, så motorn kan stoppas utan att Libre WebUI startas om.
Lager
Konkreta DSH-beroenden stannar i backend/src/cordis/dsh/. Rutter och applikationstjänster använder bryggans kontrakt. Work-drivrutinen har en separat komposition i minnet och laddar aldrig värdens filsystemplugins.
Kontrakt
Kontraktet finns i backend/src/cordis/contracts.ts. Det är avsiktligt begränsat till strukturerna som Libre WebUI:s API behöver, utan motorns interna termer.
| Kontrakt | Syfte |
|---|---|
DshEngine.status() | Livscykeltillstånd för varje motortjänst (pending / ready / failed) |
DshEngine.modelConfiguration() | Standardmodell och leverantör i den körande kompositionen |
DshEngine.listSessions() | Sessionsöversikter med de senaste först |
DshEngine.getSession(id) | En session med projicerade meddelanden |
DshEngine.createSession(opts) | Reservera sessions-id och arbetskatalog |
DshEngine.updateSessionSettings(id, settings) | Spara faktiskt modellval och native filsystembehörighet när sessionen är inaktiv |
DshEngine.decideApproval(id, approvalId, decision) | Avgör en väntande native verktygsbegäran för dess ägande session |
DshEngine.deleteSession(id) | Avsluta en session och avveckla dess agent |
DshEngine.listAgents() | Aktiva agenter, markerade som rot eller barn |
DshEngine.listTools() | Modellvända verktyg som motorn registrerat |
DshEngine.sendMessage(id, txt) | Starta en tur och returnera ett strömhandtag |
DshEngine.cancel(id) | Avbryt en sessions pågående tur |
Kontraktet publiceras som Cordis-tjänsten libreDshEngine. En konsument läser det med ctx.get('libreDshEngine') och importerar aldrig bryggmodulen.
EngineStreamChunk innehåller text, reasoning, tool-call, tool-result, approval-request, approval-decision, error och done. Liveramar skickas utifrån ägande agent och session; motsvarande beständiga assistentmeddelande skickas inte en gång till. sendMessage ger ett handtag vars subscribe spelar upp det som redan skickats, så en snabb första token inte försvinner mellan turens start och HTTP-hanterarens anslutning av lyssnaren.
Förloppet för en chattur
NDJSON används i stället för WebSocket eftersom en tur är en enda sekvens från server till klient efter begäran. Att hålla den i POST undviker en andra handskakning, biljett och återanslutningsprotokoll och håller hela turen i en autentiserad begäran.
DONE och PENDING
Cordis aktiverar ett plugin när dess deklarerade tjänster finns. En rad befinner sig därför ibland i ett tillstånd där den ännu inte körs. Två olika begrepp är viktiga; att blanda ihop dem är den vanligaste orsaken till en tyst motor.
Loader-radens tillstånd. Loader följer varje rad genom PENDING → LOADING → ACTIVE eller FAILED. Saknas deklarerade tjänster väntar raden utan tidsgräns i stället för att misslyckas. Därför kan en ofullständig komposition starta en motor som inte levererar något.
Tjänstens tillgänglighet. Värden rapporterar förväntade tjänster så här:
| Tillstånd | Betydelse | Orsak |
|---|---|---|
pending | Inte registrerad i kontexten | Den tillhandahållande raden har inte aktiverats eller är avstängd |
ready | Registrerad och användbar | Den tillhandahållande raden har aktiverats |
failed | Deklarerad men oanvändbar | Rapporteras med en detail-sträng |
host.status() listar alla förväntade tjänster med tillgänglighet och namnger nödvändiga tjänster som saknas. GET /api/cordis/health visar samma information. Om en komposition utelämnar en nödvändig tjänst ger starten ett fel i stället för en motor som svarar med tomma listor.
Två beroendekedjor är lätta att få fel:
dsh-toolskan inte starta utansystemPrompt.dsh-agent-loopkan först starta näragents,sessions,llm,tools,systemPromptochsessionProjectionsfinns.
Om något av detta saknas kan sessionslagringen fungera medan motorn aldrig besvarar ett meddelande.
Leverantörskonfiguration
Den medföljande raden libre-webui-llm-adapter betjänar modellleverantörerna som konfigurerats i Libre WebUI. Modellväljaren på motorsidan väljer en leverantörsmodell för sessionen utan att byta raden.
Ändringar i kompositionens pluginrader gäller nästa gång värden startar. Starta om backend eller slå av och på Cordis när administratörens reglage är upplåst. Sparade sessioner finns kvar i lagret och återupptas genom den aktuella kompositionen.
Betrodd integrationskod kan använda Cordis Loaders livscykel-API:er direkt. Bryggan erbjuder ingen endpoint för adapterbyte och återställer inte automatiskt föregående adapter om ersättaren misslyckas.
Återställning
När värdens rotfiber avvecklas försvinner allt som motorn installerat. Denna ägarrelation är hela garantin, eftersom:
- Plugins registrerar tjänsterna, så tjänsterna dras tillbaka med sina fibrer.
- Prenumerationer på
session/eventregistreras i bryggans egen konstruktor och tillhör bryggradens fiber. - Bryggan håller reda på agenthandtag och avvecklar dem i sin städningseffekt.
- Värden avvecklar rotkontexten, som äger varje rad.
stopCordisHost() är idempotent och ingår i backendens nedstängning, så motorns timer och filhandtag frigörs utan att vänta på processens slut.
Sessionsidentitet och beständighet
Motorsidan reserverar ett ogenomskinligt sessions-id vid skapandet. Med beständig lagring sparas huvudet direkt, så även en tom session överlever omstart. Bryggan listar sparade och aktiva sessioner, läser loggar via DSH:s validerade lagrings-API och återupptar agenten under samma id vid uppföljning. Nya användarmeddelanden använder DSH:s konstruktor för identifierade meddelanden.
Borttagning avbryter och avvecklar agenten innan sessionens artefakt tas bort. Den lokala JSONL-adaptern validerar lagrings- och sessionssökvägar och avvisar symboliska länkar. Anpassade lagringsbackender utan stöd för borttagning ger ett fel i stället för att påstå att data tagits bort.
Avbrott når den native agenten, modellbegäran och verktygsarbetet. En frånkopplad klient avbryter sin tur; färdiga meddelanden är fortfarande läsbara. Buffrad återspelning är begränsad och bevarar snabba svar innan en läsare ansluter.
Värdmotorn är en solofunktion med en enda replika. Teaminstallationer kan inte montera dess lokala JSONL-runtime. Sandboxed Work använder i stället sina befintliga SQL-repositories för uppgifter, körningar, meddelanden, godkännanden och händelser.
HTTP-gränssnitt
| Metod | Sökväg | Syfte |
|---|---|---|
GET | /api/cordis/health | Bryggans status; utan autentisering |
GET | /api/cordis/sessions | Lista sessioner |
POST | /api/cordis/sessions | Skapa en session |
GET | /api/cordis/sessions/:id | Läs en session med meddelanden |
DELETE | /api/cordis/sessions/:id | Avsluta en session |
POST | /api/cordis/sessions/:id/messages | Skicka meddelande och strömma NDJSON |
POST | /api/cordis/sessions/:id/cancel | Avbryt den pågående turen |
GET | /api/cordis/agents | Lista aktiva agenter |
GET | /api/cordis/tools | Lista registrerade verktyg |
Alla rutter utom /health kräver en autentiserad administratörssession och svarar 503 med code satt till CORDIS_DISABLED, CORDIS_STARTING eller CORDIS_UNAVAILABLE när bryggan inte kan betjäna anrop.

Sidan är frontend/src/pages/CordisPage.tsx och nås på /cordis i sidofältet. Den visar sessioner och verktyg, skapar sessioner och strömmar en tur till samtalet. Om bryggan är avstängd eller inte kan starta visas orsaken i stället för en tom lista, eftersom ”inga sessioner” annars ser ut som ”ingen motor”.
Webbläsarklienten är frontend/src/utils/api/cordisApi.ts. Den använder endast detta gränssnitt och importerar inga backendtyper eller @deepseek-ai/*-paket. Motorn kan därför bytas utan frontendändringar. En tur läses med sendMessage(sessionId, text, { onChunk }); klienten tolkar själv radseparerad JSON och klarar fragment över flera nätverksläsningar.
Motorns chattkontroller
Motorsidan visar Markdown, tabeller och syntaxmarkerad kod med kopieringskontroller för svar och kod. Systemprompter och tillförd körningskontext samlas under en hopfälld Sessionskontext, inte som användarens meddelanden. Synligt resonemang och verktygsaktivitet har separata utfällbara delar. Verktygsresultat förblir kopplade till rätt operation efter omladdning.
Välj en faktisk leverantörsmodell i skrivfältet. Väljaren använder tillgängliga lokala och pluginmodeller för den inloggade administratören med leverantörsidentitet. Personor och agentval i Chat är inte modell-id:n och för inte in sina instruktioner i motorsamtalet. Gamla misslyckade personamodellhuvuden ignoreras som ledtrådar till standardmodell utan att ändra den sparade loggen.
Varje session har sitt eget Endast läsning eller Skrivning i arbetsytan, genomdrivet av DSH:s filsystempolicy och bryggans kanoniska arbetsytegräns. Skrivfältet visar arbetsytans omfattning. Inställningar sparas som native sessionshändelser och överlever omstart; ändringar avvisas medan en tur pågår.
En native begäran om utökade rättigheter visas som ett kort med Tillåt en gång / Neka vid operationen. Godkännandet gäller bara den begäran och lämnar det fasta behörighetsläget oförändrat. Gamla eller avbrutna begäranden kan inte godkännas. Chat-anrop utan gränssnitt avvisar frågor de inte kan visa. Bryggan ger inte obegränsad värdåtkomst.
Ytterligare administratörsendpoints är:
| Metod | Sökväg | Syfte |
|---|---|---|
GET | /api/cordis/models | Tillgängliga leverantörsmodeller och aktuell faktisk standardmodell |
PATCH | /api/cordis/sessions/:id/settings | Ange sessionens modell och/eller behörighetsläge |
POST | /api/cordis/sessions/:id/approvals/:approvalId | Avgör en väntande begäran med allowed-once eller rejected |
Använd motorn i Chat
Aktivera både Åtkomst och policyer → CLI-agentmodeller och Cordis-motor. Administratörer kan då välja DeepSeek Harness i Chat. Varje begäran får en ny tillfällig motorsession med den medskickade samtalshistoriken. Den vanliga Chat-databasen är fortsatt auktoritativ. Oberoende samtal, förgreningar och återförsök kan inte dela osynlig motorhistorik. Loggen tas bort efter avslut eller avbrott och visas inte på motorsidan.
Standardkompositionen visar även DeepSeek Harness · modell (leverantör) under Agenter. Deras sparade id:n omsluter samma kvalificerade leverantörsrutt som motorsidan: dsh:lwui:ollama:<model> eller dsh:lwui:plugin:<plugin>:<model>, med procentkodade leverantörskomponenter. En valfri lokal native DSH-anslutning lägger till dsh:native:<provider>:<model> från instansens levande modellkatalog. De återanvänder den native leverantörens inställningar och autentiseringsuppgifter. Installera det fristående Apache-2.0-paketet från libre-webui/dsh-native-provider, eller skapa ett bundle från Libre WebUI-distributionen. Båda använder @libre-webui/dsh-native-provider och behåller nycklar i native DSH. Anslutningen kräver samma Unix-värd och OS-konto samt en privat Unix-socket; den isolerar inte program som delar konto. Den exponerar bara modellinferens, inte native agentsessioner eller verktygskörning. Konfigurationsguiden beskriver installation, profilomstart, uppdatering och borttagning. Saknas anslutningen eller den valda modellen misslyckas anropet utan leverantörsbyte. Native anrop visas även under Leverantörsanvändning med modell, rapporterade tokens, latens och resultatstatus. Basprofilen dsh behåller den aktiva kompositionens standardmodell. Anpassade adapterkompositioner erbjuder basprofilen utan att annonsera leverantörsbyten i Libre WebUI som inte stöds.
Titlar och tankesammanfattningar löser DSH-valet till dess underliggande leverantör och gör en direkt textbegäran utan verktyg eller agentsession. Basprofilen läser den körande motorns standarder, inklusive åsidosättningar i bryggraden, i stället för att gissa från katalogen. Anpassade adaptrar behöver en uttryckligen konfigurerad Ollama- eller pluginuppgiftsmodell. En otillgänglig vald leverantör ger vanligt fel eller lokal titelförhandsvisning, inte ett anrop till någon annan.
Begäran använder den autentiserade administratörens leverantörsinställningar och autentiseringsuppgifter. En annan administratörs uppgifter väljs aldrig underförstått. Den konfigurerade Cordis-arbetsytan förblir standard; Chat ersätter den inte med serveranvändarens hemkatalog.
Sandboxed Work
Med Cordis aktiverat erbjuder Work ett separat Motor-val med Libre WebUI och DeepSeek Harness. Modellväljaren behåller vanliga namn och leverantörsidentiteter. För LWUI-leverantörer sparas DSH-valet internt som dsh:<model>. Native DSH-val sparar i stället providerType: dsh, exakt native leverantörs-id och oförändrat modell-id. Vanliga kontroller av verktygsstöd och åtkomst gäller fortfarande; native autentiseringsuppgifter kräver dessutom aktiv administratör.
Varje körning skapar en isolerad DSH-agentloop i minnet. Modelladaptern får Work-historik, leverantörsmetadata, bilder och verktygsscheman. Verktygens implementationer väntar bara på resultat från Work; de kan inte läsa värdfiler eller starta värdprocesser.
Work ansvarar fortfarande för argumentvalidering, godkännanden, körning i arbetsytan, SQL-lagring av resultat och leverantörens återspelningsläge, budgetar och händelser. Ett nekat verktyg ger vanligt avvisningsresultat. Avbrott avvecklar DSH och följer Works containerstädning. Efter workeråterställning får en ny DSH-drivrutin återställd Work-kontext och upprepar inga avslutade verktygseffekter.
Work-integrationen behöver varken värdmotorns komposition eller JSONL-sessionslager. Den följer Works befintliga Docker-/Kubernetes-regler för runtime och driftsättning, inklusive teamlägets krav på delad lagring.
Säkerhetsgräns
Motorsidan och den värdbaserade Chat-agenten är bara för administratörer. Motorsessioner är en delad administratörskonsol inklusive systemprompter, inte en arbetsyta per användare. Vanliga konton kan inte läsa, skapa, ändra eller avbryta dem via API:et.
De medföljande värdfilsystemverktygen begränsar läsning och skrivning till arbetsytan med kanoniska filsystemmål, inklusive upplösning av symboliska länkar. Sessionsspecifika arbetskataloger måste stanna inom denna gräns. DSH:s native ändringspolicy och engångsgodkännanden gäller fortfarande. Operatörinstallerade kompositionsplugins är betrodd serverkod som kan ge ytterligare funktioner. Motorgodkännanden är separata från Works godkännande- och containerflöde.
Works DSH-drivrutin är separat: Den laddar inga värdfilsystem-, shell- eller lagringsplugins och kan bara köra genom Works befintliga behörighet och sandbox. Externa modellleverantörer förblir aktiva tillval med det valda kontots konfigurerade rutt.