Hop til hovedindhold

Cordis-bro

Cordis-broen indlejrer DeepSeek Harness-motoren (DSH) i Libre WebUI's backend. DSH kører som et plugintræ i et Cordis-miljø, som Libre WebUI er vært for. Funktionerne leveres derfor som Cordis-tjenester frem for importerede moduler.

Broen er slået fra som standard. Intet på denne side sker, før en operatør aktiverer den (se Cordis-konfiguration).

Hvorfor en bro frem for direkte integration

Det ville være kortere, men dårligere, at importere DSH-pakker fra Libre WebUI's tjenester. Direkte import gør motoren til en afhængighed ved kompilering. Udskiftning af modeladapter, agentløkke eller hele motoren kræver så ændringer og en ny udrulning af Libre WebUI.

Broen vender forholdet om. Libre WebUI afhænger af én abstrakt kontrakt, og et Cordis-kompositionsdokument bestemmer, hvad der opfylder den:

  • Skift mål uden nyt build. Kompositionen er en YAML-fil, så en anden udbyder vælges gennem konfiguration.
  • Konfigurer funktioner. Hver funktion er en Loader-række. Operatørens ændringer i kompositionen træder i kraft, næste gang værten starter.
  • Fjern alt ordentligt. Hver tjeneste, lytter og effekt, som motoren opretter, tilhører rodfiberen. Oprydning af fiberen fjerner det hele, så motoren kan stoppes uden at genstarte Libre WebUI.

Lag

De konkrete DSH-afhængigheder bliver i backend/src/cordis/dsh/. Ruter og applikationstjenester bruger broens kontrakter. Work-driveren har en separat komposition i hukommelsen og indlæser aldrig værtens filsystemplugins.

Kontrakter

Kontrakten findes i backend/src/cordis/contracts.ts. Den er bevidst snæver: de strukturer, Libre WebUI's API behøver, uden motorens interne ordforråd.

KontraktFormål
DshEngine.status()Livscyklustilstand for hver motortjeneste (pending / ready / failed)
DshEngine.modelConfiguration()Standardmodel og -udbyder i den kørende komposition
DshEngine.listSessions()Sessionsoversigter, nyeste først
DshEngine.getSession(id)En session med dens projicerede beskeder
DshEngine.createSession(opts)Reserver et sessions-id og en arbejdsmappe
DshEngine.updateSessionSettings(id, settings)Gem den faktiske model og native filsystemrettigheder, mens sessionen er inaktiv
DshEngine.decideApproval(id, approvalId, decision)Afgør en afventende native værktøjsgodkendelse for den session, den tilhører
DshEngine.deleteSession(id)Afslut sessionen og ryd dens agent op
DshEngine.listAgents()Aktive agenter, markeret som rod eller barn
DshEngine.listTools()Modelvendte værktøjer registreret af motoren
DshEngine.sendMessage(id, txt)Start en tur og returner et stream-handle
DshEngine.cancel(id)Annuller en sessions igangværende tur

Kontrakten udstilles som Cordis-tjenesten libreDshEngine. En forbruger læser den med ctx.get('libreDshEngine') og importerer aldrig bromodulet.

EngineStreamChunk indeholder text, reasoning, tool-call, tool-result, approval-request, approval-decision, error og done. Live-frames routes efter deres agent og session; den tilsvarende varigt gemte assistentbesked udsendes ikke igen. sendMessage returnerer et handle, hvis subscribe genafspiller alt, der allerede er udsendt. Et hurtigt første token går derfor ikke tabt mellem motorens start af turen og HTTP-handlerens tilslutning af sin lytter.

Forløbet for én chattur

NDJSON bruges frem for WebSocket, fordi en tur er én sekvens fra server til klient efter anmodningen. At beholde den i POST undgår endnu et handshake, en billet og en genforbindelsesprotokol og holder hele turen i én autentificeret anmodning.

DONE og PENDING

Cordis aktiverer et plugin, når dets deklarerede tjenester er tilgængelige. En række tilbringer derfor tid i tilstande, hvor den endnu ikke kører. To forskellige begreber er vigtige; forveksling af dem er den hyppigste årsag til en tavs motor.

Loader-rækkens tilstand. Loader følger hver række gennem PENDING → LOADING → ACTIVE eller FAILED. Mangler en deklareret tjeneste, bliver rækken ved med at afvente i stedet for at fejle. Derfor kan en ufuldstændig komposition starte en motor, som ikke leverer noget.

Tjenestens tilgængelighed. Værten rapporterer hver forventet tjeneste sådan:

TilstandBetydningÅrsag
pendingIkke registreret i kontekstenDen leverende række er ikke aktiveret eller er deaktiveret
readyRegistreret og brugbarDen leverende række blev aktiveret
failedDeklareret, men ubrugeligRapporteret med en detail-streng

host.status() viser alle forventede tjenester og deres tilgængelighed samt navnene på manglende nødvendige tjenester. GET /api/cordis/health viser det samme. Udelader en komposition en nødvendig tjeneste, fejler opstarten i stedet for at udstille en motor, der svarer med tomme lister.

To afhængighedskæder er lette at konfigurere forkert:

  • dsh-tools kan ikke starte uden systemPrompt.
  • dsh-agent-loop kan først starte, når agents, sessions, llm, tools, systemPrompt og sessionProjections alle findes.

Mangler en af dem, kan sessionslageret virke, mens motoren aldrig besvarer en besked.

Udbyderkonfiguration

Den medfølgende libre-webui-llm-adapter-række betjener de modeludbydere, der er konfigureret i Libre WebUI. Modelvælgeren på motorsiden vælger en udbydermodel til sessionen uden at udskifte rækken.

Ændringer i kompositionens pluginrækker gælder ved næste værtsstart. Genstart backend, eller slå Cordis fra og til, når administratorkontakten er ulåst. Gemte sessioner bliver i det konfigurerede lager og genoptages gennem den aktuelle komposition.

Betroet integrationskode kan bruge Cordis Loaders livscyklus-API'er direkte. Broen har intet endpoint til adapterskift og gendanner ikke automatisk en tidligere adapter, hvis erstatningen fejler.

Tilbagerulning

Oprydning af værtens rodfiber fjerner alt, motoren installerede. Dette ejerskab er hele garantien, fordi:

  • Plugins registrerer tjenesterne, så tjenesterne trækkes tilbage sammen med deres fiber.
  • Abonnementer på session/event registreres i broens egen konstruktør og tilhører brorækkens fiber.
  • Broen sporer agent-handles og rydder dem op i sin oprydningseffekt.
  • Værten rydder rodkonteksten op, og denne ejer alle rækker.

stopCordisHost() er idempotent og indgår i backendens nedlukning, så motorens timere og fil-handles frigives uden at vente på, at processen afsluttes.

Sessionsidentitet og persistens

Motorsiden reserverer et uigennemsigtigt sessions-id ved oprettelsen. Med persistens bliver headeren gemt straks, så selv en tom session overlever genstart. Broen viser gemte og aktive sessioner, læser logge gennem DSH's validerede persistens-API og genoptager agenten med samme id ved en opfølgning. Nye brugerbeskeder bruger DSH's konstruktør til identificerede beskeder.

Sletning annullerer og rydder agenten op, før sessionens artefakt fjernes. Den lokale JSONL-sletteadapter validerer lager- og sessionsstier og afviser symbolske links. Tilpassede persistensbackends uden sletteunderstøttelse returnerer en fejl i stedet for at påstå, at data blev fjernet.

Annullering når den native agent, modelanmodningen og værktøjsarbejdet. En klient, der afbryder forbindelsen, annullerer sin tur; afsluttede beskeder forbliver læsbare. Genafspilning af bufferen er begrænset og bevarer hurtige svar, før en læser tilsluttes.

Værtsmotoren er en solo-funktion med én replika. Teaminstallationer kan ikke montere dens lokale JSONL-runtime. Sandboxed Work bruger i stedet sine eksisterende SQL-repositories til opgaver, kørsler, beskeder, godkendelser og hændelser.

HTTP-grænseflade

MetodeStiFormål
GET/api/cordis/healthBrostatus; uden autentificering
GET/api/cordis/sessionsVis sessioner
POST/api/cordis/sessionsOpret en session
GET/api/cordis/sessions/:idLæs sessionen med beskeder
DELETE/api/cordis/sessions/:idAfslut en session
POST/api/cordis/sessions/:id/messagesSend en besked og stream NDJSON
POST/api/cordis/sessions/:id/cancelAnnuller den igangværende tur
GET/api/cordis/agentsVis aktive agenter
GET/api/cordis/toolsVis registrerede værktøjer

Alle ruter undtagen /health kræver en autentificeret administratorsession og svarer 503 med code lig CORDIS_DISABLED, CORDIS_STARTING eller CORDIS_UNAVAILABLE, mens broen ikke kan behandle anmodninger.

Cordis-motorsiden i Libre WebUI med sessionsliste, registrerede værktøjer og en streamet chatsamtale.

Siden er frontend/src/pages/CordisPage.tsx og åbnes via /cordis i sidepanelet. Den viser sessioner og værktøjer, opretter sessioner og streamer en tur ind i samtalen. Hvis broen er slukket eller ikke kan starte, viser den årsagen frem for en tom liste, da »ingen sessioner« ellers ligner »ingen motor«.

Browserklienten er frontend/src/utils/api/cordisApi.ts. Den taler kun med denne grænseflade og importerer hverken backendtyper eller @deepseek-ai/*-pakker. Motoren kan derfor udskiftes uden frontendændringer. En tur læses med sendMessage(sessionId, text, { onChunk }); klienten parser selv linjeopdelt JSON og tåler fragmenter fordelt over netværkslæsninger.

Motorens chatkontroller

Motorsiden viser Markdown, tabeller og syntaksfremhævede kodeblokke med kopiering af svar og kode. Systemprompter og indsat runtimekontekst samles under den lukkede sektion Sessionskontekst og vises ikke som brugerens beskeder. Synligt ræsonnement og værktøjsaktivitet har hver deres foldbare sektion, og værktøjsresultater forbliver knyttet til den rigtige operation efter genindlæsning.

Vælg en faktisk udbydermodel i skrivefeltet. Vælgeren bruger den indloggede administrators tilgængelige lokale og pluginmodeller med udbyderidentitet. Chat-personaer og agentvalg er ikke model-id'er og indsætter ikke deres instruktioner i en motorsamtale. Gamle fejlede persona-modelheadere ignoreres som forslag til standardmodel uden at ændre den gemte log.

Hver session har sit eget valg mellem Kun læsning og Skrivning i arbejdsområdet, håndhævet af DSH's filsystempolitik og broens kanoniske arbejdsområdegrænse. Skrivefeltet viser arbejdsområdets omfang. Indstillinger gemmes som native sessionshændelser og overlever genstart; ændringer afvises under en aktiv tur.

En native anmodning om udvidede rettigheder vises som et Tillad én gang / Afvis-kort knyttet til operationen. Godkendelsen gælder kun denne anmodning og ændrer ikke den faste tilladelsestilstand. Forældede eller annullerede anmodninger kan ikke godkendes. Chatkald uden brugerflade afviser spørgsmål, de ikke kan vise. Broen tilbyder ikke ubegrænset værtsadgang.

De yderligere administratorendpoints er:

MetodeStiFormål
GET/api/cordis/modelsTilgængelige udbydermodeller og den aktuelle faktiske standardmodel
PATCH/api/cordis/sessions/:id/settingsAngiv sessionens model og/eller tilladelsestilstand
POST/api/cordis/sessions/:id/approvals/:approvalIdAfgør en afventende anmodning med allowed-once eller rejected

Brug motoren i Chat

Aktivér både Adgang og politikker → CLI-agentmodeller og Cordis-motor. Administratorer kan så vælge DeepSeek Harness i Chat. Hver anmodning får en ny midlertidig motorsession med dens medsendte samtalehistorik. Den normale Chat-database forbliver autoritativ; uvedkommende samtaler, forgreninger og genforsøg kan ikke dele usynlig motorhistorik. Den midlertidige log slettes efter afslutning eller annullering og vises ikke på motorsiden.

Standardkompositionen viser også DeepSeek Harness · model (udbyder) under Agenter. De gemte id'er indpakker samme kvalificerede udbyderrute som motorsiden: dsh:lwui:ollama:<model> eller dsh:lwui:plugin:<plugin>:<model>, med procentkodede udbyderkomponenter. En valgfri lokal native DSH-forbindelse tilføjer dsh:native:<provider>:<model> fra instansens livekatalog. De genbruger den native udbyders konfiguration og legitimationsoplysninger. Installér den selvstændige Apache-2.0-pakke fra libre-webui/dsh-native-provider, eller klargør et bundle fra Libre WebUI-distributionen. Begge bruger pakkenavnet @libre-webui/dsh-native-provider og holder udbydernøgler i native DSH. Forbindelsen kræver samme Unix-vært og OS-konto samt en privat Unix-socket; den kan ikke isolere programmer, som deler kontoen. Den eksponerer kun modelinferens, ikke native agentsessioner eller værktøjskørsel. Se konfigurationsguiden for installation, profilgenstart, opdatering og fjernelse. Manglende forbindelser eller valgte modeller fejler uden udbyderskift. Native kald vises også i Udbyderforbrug med model, rapporterede tokens, svartid og resultatstatus. Basisprofilen dsh beholder den kørende kompositions standardmodel. Tilpassede adapterkompositioner udstiller basisprofilen uden at annoncere ikke-understøttede Libre WebUI-udbydervalg.

Titler og tankeresuméer omsætter et DSH-valg til den underliggende udbyder og sender en direkte tekstanmodning uden værktøjer eller agentsession. En basisprofilanmodning læser den kørende motors standarder, inklusive brorækkens tilsidesættelser, frem for at gætte ud fra kataloget. Tilpassede adaptere kræver en udtrykkeligt konfigureret Ollama- eller pluginopgavemodel til disse funktioner. En utilgængelig valgt udbyder giver den normale fejl eller lokale titelvisning; det udløser ikke et kald til en anden udbyder.

Anmodningen bruger den autentificerede administrators udbyderindstillinger og legitimationsoplysninger. Andre administratorers oplysninger vælges aldrig implicit. Det konfigurerede Cordis-arbejdsområde er fortsat standard; Chat erstatter det ikke med serverbrugerens hjemmemappe.

Sandboxed Work

Når Cordis er aktiveret, tilbyder Work et særskilt Motor-valg med Libre WebUI og DeepSeek Harness. Modelvælgeren beholder normale modelnavne og udbyderidentiteter. Internt gemmes DSH-valget som dsh:<model> for LWUI-udbydere. Native valg gemmer i stedet providerType: dsh, det præcise native udbyder-id og det rå model-id. De normale adgangs- og værktøjskontroller gælder fortsat; native legitimationsoplysninger kræver desuden en aktiv administrator.

Hver kørsel opretter en isoleret DSH-agentløkke i hukommelsen. Modeladapteren modtager Work-historikken, udbydermetadata, billeder og værktøjsskemaer. Værktøjernes kode venter kun på resultater fra Work; den kan ikke læse værtsfiler eller starte værtsprocesser.

Work står stadig for argumentvalidering, godkendelser, værktøjskørsel i arbejdsområdets runtime, SQL-lagring af resultater og udbyderens genafspilningstilstand, budgetter og hændelser. Et afvist værktøj giver det normale afvisningsresultat. Annullering rydder DSH op og følger Works eksisterende containeroprydning. Efter workergendannelse modtager en ny DSH-driver den gendannede Work-kontekst uden at gentage afsluttede værktøjseffekter.

Work-integrationen behøver hverken værtens motorkomposition eller et JSONL-sessionslager. Den følger Works eksisterende Docker-/Kubernetes-regler for runtime og deployment, herunder teamtilstandens krav til delt persistens.

Sikkerhedsgrænse

Motorsiden og Chat-agenten på værten er kun for administratorer. Motorsessioner er en fælles administratorkonsol inklusive deres systemprompter, ikke et arbejdsområde pr. bruger. Almindelige konti kan ikke læse, oprette, ændre eller annullere dem via API'et.

De medfølgende værtsfilsystemværktøjer begrænser læsning og skrivning til arbejdsområdet ved at kontrollere kanoniske filsystemmål, inklusive symbolske links. Sessionsspecifikke arbejdsmapper skal forblive inden for området. DSH's native ændringspolitik og motorens engangsgodkendelser gælder fortsat. Operatørinstallerede kompositionsplugins er betroet serverkode og kan give flere muligheder. Motorgodkendelser er adskilt fra Works godkendelser og containerkørsel.

Works DSH-driver er særskilt: Den indlæser ingen værtsfilsystem-, shell- eller persistensplugins og kan kun udføre gennem Works eksisterende autorisation og sandbox. Eksterne modeludbydere er fortsat tilvalg og bruger den valgte kontos konfigurerede rute.