[{"data":1,"prerenderedAt":3499},["ShallowReactive",2],{"search-de":3,"content-de-vision\u002Fdesktop-app":4,"surround-de-\u002Fvision\u002Fdesktop-app":3491},[],{"id":5,"title":6,"body":7,"description":3483,"extension":3484,"meta":3485,"navigation":3486,"path":3487,"seo":3488,"stem":3489,"__hash__":3490},"content_de\u002F5.vision\u002F6.desktop-app.md","Desktop-App & fortgeschrittene Agenten",{"type":8,"value":9,"toc":3441},"minimark",[10,14,24,52,64,69,74,84,169,180,206,210,220,253,257,275,304,404,415,426,430,447,509,513,516,542,591,595,598,609,612,685,689,703,762,766,772,779,817,832,836,1052,1071,1075,1078,1144,1157,1161,1168,1172,1175,1270,1274,1281,1620,1661,1678,1682,1691,1823,1854,1858,1865,1871,1875,1891,1895,1909,1913,1918,2031,2067,2071,2086,2213,2233,2237,2249,2322,2367,2382,2399,2403,2436,2440,2450,2488,2492,2640,2666,2670,2756,2763,2767,2782,2798,2832,2836,2842,2846,2852,3117,3121,3132,3138,3153,3220,3241,3245,3259,3431,3437],[11,12,6],"h1",{"id":13},"desktop-app-fortgeschrittene-agenten",[15,16,17,18,23],"p",{},"Dieser Teil der ",[19,20,22],"a",{"href":21},"\u002Fvision#the-roadmap","Roadmap"," bringt Owlat als native Hülle auf den Desktop, ergänzt spezialisierte Agenten für Visualisierung und Programmierung und führt abgestufte Autonomie ein, bei der das Deployment fein einstellt, wie viel Entscheidungsspielraum es an die KI delegiert.",[15,25,26,27,31,32,35,36,39,40,43,44,47,48,51],{},"Das meiste davon ist bereits gebaut, und vieles, was früher nur im Schema existierte, ist heute durchgängig angetrieben. Die Desktop-App wird als Tauri-Hülle ausgeliefert (",[28,29,30],"code",{},"apps\u002Fdesktop","); der Visualisierungsagent (",[28,33,34],{},"apps\u002Fapi\u002Fconvex\u002FvisualizationAgent.ts",") liest inzwischen echte Daten für eine erlaubte Menge von Datensätzen; das adaptive Dashboard (",[28,37,38],{},"apps\u002Fapi\u002Fconvex\u002Fanalytics\u002FadaptiveDashboard.ts",") erzwingt Rollenbedingungen; das Monitoring der Agenten-Gesundheit (",[28,41,42],{},"apps\u002Fapi\u002Fconvex\u002FagentHealth.ts",") befüllt sechs von sieben Metriken und wertet alle drei Circuit Breaker aus; die Regeln für abgestufte Autonomie (",[28,45,46],{},"apps\u002Fapi\u002Fconvex\u002Fautonomy.ts",") steuern den aktiven Routing-Schritt mit einer funktionierenden Feedback-Schleife; und der Sidecar für den Coding-Agenten (",[28,49,50],{},"apps\u002Fcode-worker",") wird inzwischen von einem eingehenden Auto-Trigger und einem GitHub-Merge-Webhook gespeist. Die folgenden Abschnitte beschreiben, was heute angebunden ist, und benennen in Callouts die Teile, die noch auf dem Weg sind.",[53,54,57],"callout",{"title":55,"type":56},"Ein Deployment, eine Organisation","info",[15,58,59,60,63],{},"Owlat betreibt inzwischen genau eine Organisation pro Deployment, daher tragen die untenstehenden Tabellen keine ",[28,61,62],{},"organizationId",". Einstellungen wie die Agentenkonfiguration und die Autonomieregeln sind deploymentweite Singletons.",[65,66,68],"h2",{"id":67},"desktop-app","Desktop-App",[70,71,73],"h3",{"id":72},"warum-tauri","Warum Tauri",[15,75,76,77,83],{},"Die Desktop-App ist mit ",[19,78,82],{"href":79,"rel":80},"https:\u002F\u002Fv2.tauri.app\u002F",[81],"nofollow","Tauri v2"," gebaut:",[85,86,87,101],"table",{},[88,89,90],"thead",{},[91,92,93,96,98],"tr",{},[94,95],"th",{},[94,97,82],{},[94,99,100],{},"Electron",[102,103,104,116,127,137,148,159],"tbody",{},[91,105,106,110,113],{},[107,108,109],"td",{},"Binärgröße",[107,111,112],{},"~5–10 MB",[107,114,115],{},"~150–200 MB",[91,117,118,121,124],{},[107,119,120],{},"Speicherverbrauch",[107,122,123],{},"Native Webview",[107,125,126],{},"Gebündeltes Chromium",[91,128,129,132,135],{},[107,130,131],{},"Lizenz",[107,133,134],{},"MIT",[107,136,134],{},[91,138,139,142,145],{},[107,140,141],{},"Backend",[107,143,144],{},"Rust",[107,146,147],{},"Node.js",[91,149,150,153,156],{},[107,151,152],{},"Auto-Update",[107,154,155],{},"Eingebauter Updater",[107,157,158],{},"electron-updater",[91,160,161,164,167],{},[107,162,163],{},"Dock-\u002FTaskleisten-Badge",[107,165,166],{},"Native API",[107,168,166],{},[15,170,171,172,175,176,179],{},"Tauri nutzt die native Webview des Betriebssystems (WebKit unter macOS, WebView2 unter Windows, WebKitGTK unter Linux) — kein gebündeltes Chromium. Die App-Hülle dupliziert keinerlei UI: Sie lädt dieselbe SPA aus ",[28,173,174],{},"apps\u002Fweb"," (gebaut mit ",[28,177,178],{},"bun run generate:desktop",", ohne einbackene Convex-URL) und richtet sie zur Laufzeit auf die URLs des aktiven Workspace.",[53,181,183],{"title":182,"type":56},"Anbindung des Auto-Updates",[15,184,185,186,189,190,193,194,197,198,201,202,205],{},"Das Updater-Plugin ist angebunden (",[28,187,188],{},"src\u002Fupdater.ts","), und der Release-Workflow signiert die Bundles. ",[28,191,192],{},"plugins.updater.pubkey"," in ",[28,195,196],{},"tauri.conf.json"," ist inzwischen mit einem öffentlichen minisign-Schlüssel befüllt, und der Endpunkt zeigt auf den GitHub-Releases-Host (",[28,199,200],{},"https:\u002F\u002Fgithub.com\u002Fwolvesdotink\u002Fowlat\u002Freleases\u002Flatest\u002Fdownload\u002Flatest.json","). Der eingecheckte Schlüssel kann ein Beispiel- bzw. Nicht-Produktionsschlüssel sein — Betreiber, die eigene Builds veröffentlichen, sollten ein eigenes Signaturschlüsselpaar erzeugen und ihn ersetzen. Siehe ",[28,203,204],{},"apps\u002Fdesktop\u002FREADME.md"," für die Schritte zu Signierung und Release.",[70,207,209],{"id":208},"architektur","Architektur",[211,212,217],"pre",{"className":213,"code":215,"language":216},[214],"language-text","apps\u002Fdesktop\u002F\n  src-tauri\u002F                 # Rust backend\n    src\u002F\n      main.rs                # Tauri app setup, plugin wiring\n      menu.rs                # Application menu\n      notifications.rs       # Native OS notifications + dock\u002Ftaskbar badge\n      shortcuts.rs           # Global keyboard shortcuts\n      window.rs              # Window create\u002Fshow\u002Ffocus helpers\n      secrets.rs             # OS-keychain commands (set\u002Fget\u002Fdelete)\n    Cargo.toml\n    tauri.conf.json          # Window config, CSP, deep-link schemes, updater\n  src\u002F                       # TypeScript bridge (runs in the webview)\n    deeplink.ts              # Cold-start + live deep-link plumbing\n    workspace.ts             # Workspace list\u002Factive-id persistence\n    keychain.ts              # Keychain bridge for session tokens\n    compose.ts               # Compose-window opener (mailto: handling)\n    notifications.ts         # Notification bridge\n    shortcuts.ts             # Shortcut registration\n    menu.ts                  # Menu wiring\n    window.ts                # Window helpers\n    shell.ts                 # System-browser open\n    dialog.ts                # Native dialog bridge\n    ssh.ts                   # SSH transport for guided VPS setup\n    autostart.ts             # Launch-at-login toggle\n    updater.ts               # Tauri updater plugin wrapper\n  package.json\n","text",[28,218,215],{"__ignoreMap":219},"",[15,221,222,223,226,227,229,230,233,234,237,238,237,241,244,245,248,249,252],{},"Es gibt keine Rust-Datei ",[28,224,225],{},"updater.rs"," — das Auto-Update übernimmt das Tauri-Updater-Plugin, gekapselt aus ",[28,228,188],{},". Session-Geheimnisse sind das Einzige, was die Rust-Seite direkt besitzt: ",[28,231,232],{},"secrets.rs"," stellt die Befehle ",[28,235,236],{},"secret_set","\u002F",[28,239,240],{},"secret_get",[28,242,243],{},"secret_delete"," bereit, gestützt auf die Crate ",[28,246,247],{},"keyring"," (Service ",[28,250,251],{},"com.owlat.desktop",").",[70,254,256],{"id":255},"zentrale-funktionen","Zentrale Funktionen",[15,258,259,263,264,267,268,270,271,274],{},[260,261,262],"strong",{},"Native Benachrichtigungen"," — betritt ein neuer Eintrag die Prüf-Warteschlange oder schickt ein Kollege eine Chat-Nachricht, wird über das Tauri-Notification-Plugin (",[28,265,266],{},"src\u002Fnotifications.ts",") das Benachrichtigungssystem des Betriebssystems ausgelöst. Das ",[260,269,163],{}," für Ungelesenes (",[28,272,273],{},"src-tauri\u002Fsrc\u002Fnotifications.rs",") wird von den reaktiven Convex-Queries gespeist, die die Webview ohnehin abonniert. Das Schließen des Hauptfensters beendet die App — es gibt kein Menüleisten-Tray.",[15,276,277,280,281,284,285,288,289,291,292,295,296,299,300,303],{},[260,278,279],{},"Deep Links"," — registriert für die Schemata ",[28,282,283],{},"owlat"," und ",[28,286,287],{},"mailto"," (",[28,290,196],{}," → ",[28,293,294],{},"plugins.deep-link","). Es gibt keinen einzelnen Brücken-Einstiegspunkt; die Web-App importiert die themenspezifischen Module direkt, und das Bootstrapping der Deep Links liegt in ",[28,297,298],{},"apps\u002Fdesktop\u002Fsrc\u002Fdeeplink.ts",", angetrieben vom Desktop-Plugin der Web-App. Der Handler in ",[28,301,302],{},"apps\u002Fweb\u002Fapp\u002Flib\u002Fdesktop\u002FdeepLink.client.ts"," leitet weiter:",[85,305,306,316],{},[88,307,308],{},[91,309,310,313],{},[94,311,312],{},"Deep Link",[94,314,315],{},"Öffnet",[102,317,318,330,342,354,366,378,388],{},[91,319,320,325],{},[107,321,322],{},[28,323,324],{},"owlat:\u002F\u002Fthread\u002F{id}",[107,326,327],{},[28,328,329],{},"\u002Fdashboard\u002Finbox\u002F{id}",[91,331,332,337],{},[107,333,334],{},[28,335,336],{},"owlat:\u002F\u002Fchat\u002F{id}",[107,338,339],{},[28,340,341],{},"\u002Fdashboard\u002Fchat\u002F{id}",[91,343,344,349],{},[107,345,346],{},[28,347,348],{},"owlat:\u002F\u002Fknowledge\u002F{id}",[107,350,351],{},[28,352,353],{},"\u002Fdashboard\u002Fknowledge\u002F{id}",[91,355,356,361],{},[107,357,358],{},[28,359,360],{},"owlat:\u002F\u002Ffile\u002F{id}",[107,362,363],{},[28,364,365],{},"\u002Fdashboard\u002Ffiles\u002F{id}",[91,367,368,373],{},[107,369,370],{},[28,371,372],{},"owlat:\u002F\u002Fcontact\u002F{id}",[107,374,375],{},[28,376,377],{},"\u002Fdashboard\u002Faudience\u002Fcontacts\u002F{id}",[91,379,380,385],{},[107,381,382],{},[28,383,384],{},"owlat:\u002F\u002Fauth?ott=…&state=…",[107,386,387],{},"löst den Workspace-Anmelde-Handshake ein",[91,389,390,395],{},[107,391,392],{},[28,393,394],{},"mailto:…",[107,396,397,398,237,401],{},"öffnet ein Verfassen-Fenster, vorbefüllt mit ",[28,399,400],{},"to",[28,402,403],{},"subject",[15,405,406,407,410,411,414],{},"Jeder nicht zugeordnete ",[28,408,409],{},"owlat:\u002F\u002F","-Pfad fällt auf ",[28,412,413],{},"\u002Fdashboard\u002F{path}"," zurück.",[15,416,417,420,421,425],{},[260,418,419],{},"Owlat als Kanal"," — der interne Chat läuft über dieselben Nachrichtentabellen und dieselbe Agenten-Strecke wie E-Mail. Die Zustellung erfolgt über reaktive Convex-Subscriptions — kein WebSocket-Server über das hinaus, was Convex ohnehin bereitstellt. Siehe ",[19,422,424],{"href":423},"\u002Fguide\u002Fchannels","Kommunikationskanäle"," für die aktiven Kanäle (E-Mail und Chat) gegenüber den rein eingehenden (SMS\u002FWhatsApp).",[70,427,429],{"id":428},"multi-workspace-authentifizierung","Multi-Workspace & Authentifizierung",[15,431,432,433,435,436,439,440,284,443,446],{},"Die Desktop-App verbindet sich mit einer oder mehreren entfernten Owlat-Instanzen. Das Modell ist in ",[28,434,204],{}," dokumentiert und über ",[28,437,438],{},"apps\u002Fdesktop\u002Fsrc\u002Fworkspace.ts",", ",[28,441,442],{},"apps\u002Fweb\u002Fapp\u002Fcomposables\u002FuseDesktopWorkspaces.ts",[28,444,445],{},"apps\u002Fweb\u002Fapp\u002Flib\u002Fdesktop\u002F"," implementiert:",[448,449,450,454,465,469,481,485,502,506],"steps",{},[70,451,453],{"id":452},"einen-workspace-hinzufügen","Einen Workspace hinzufügen",[15,455,456,457,460,461,464],{},"„Workspace hinzufügen“ öffnet die Seite ",[28,458,459],{},"\u002Fdesktop\u002Fconnect"," der Instanz im ",[260,462,463],{},"Systembrowser",", nicht in der eingebetteten Webview. Die Authentifizierung erfolgt gegen die echte Instanz mit deren vollständigem serverseitigem Ablauf.",[70,466,468],{"id":467},"ein-einmal-token-einlösen","Ein Einmal-Token einlösen",[15,470,471,472,474,475,193,478,252],{},"Bei Erfolg gibt der Browser die Kontrolle über den Deep Link ",[28,473,384],{}," zurück. Die App löst dieses Einmal-Token gegen eine header-basierte, cookielose domainübergreifende Session ein (",[28,476,477],{},"completeConnection",[28,479,480],{},"useDesktopWorkspaces.ts",[70,482,484],{"id":483},"die-session-im-schlüsselbund-des-betriebssystems-ablegen","Die Session im Schlüsselbund des Betriebssystems ablegen",[15,486,487,488,490,491,288,494,497,498,501],{},"Der Session-Blob wird über die Rust-Befehle aus ",[28,489,232],{}," in den nativen Geheimnisspeicher geschrieben, pro Workspace geschlüsselt. Die nicht geheime Workspace-Liste und die ID des aktiven Workspace liegen in ",[28,492,493],{},"workspaces.json",[28,495,496],{},"tauri-plugin-store",") und referenzieren das Geheimnis nur über ",[28,499,500],{},"tokenRef",".",[70,503,505],{"id":504},"workspaces-wechseln","Workspaces wechseln",[15,507,508],{},"Die Auswahl eines anderen Workspace lädt die Webview neu, damit sich die Singletons für Auth und Convex-Client aus den URLs des neu aktiven Workspace neu initialisieren.",[70,510,512],{"id":511},"interner-chat","Interner Chat",[15,514,515],{},"Teamkommunikation innerhalb der Desktop-App:",[517,518,519,526,532],"ul",{},[520,521,522,525],"li",{},[260,523,524],{},"Direktnachrichten"," — Eins-zu-eins-Konversationen zwischen Mitgliedern der Organisation",[520,527,528,531],{},[260,529,530],{},"Kanäle"," — themenbasierte Gruppenkonversationen (ähnlich Slack-Kanälen)",[520,533,534,537,538,541],{},[260,535,536],{},"Thread-verknüpft"," — jede Konversation kann auf einen ",[28,539,540],{},"conversationThread"," verweisen und so interne Diskussion mit der Kundenkommunikation verbinden",[15,543,544,545,288,548,551,552,555,556,559,560,563,564,288,567,570,571,573,574,578,579,582,583,586,587,590],{},"Interne Chat-Nachrichten sind Zeilen in ",[28,546,547],{},"unifiedMessages",[28,549,550],{},"apps\u002Fapi\u002Fconvex\u002Fschema\u002Fmessaging.ts",") mit ",[28,553,554],{},"channel: 'chat'",". Das Schema führt sowohl eine optionale ",[28,557,558],{},"memberId"," (der interne Absender) als auch eine optionale ",[28,561,562],{},"contactId","; der eine ausgelieferte Chat-Writer, ",[28,565,566],{},"sendChatMessage",[28,568,569],{},"apps\u002Fapi\u002Fconvex\u002FunifiedMessages.ts","), hält die ",[28,572,562],{}," des Threads fest, in dem er postet (die Mitgliedsidentität ist der authentifizierte Aufrufer). Die Vision ist, dass der ",[19,575,577],{"href":576},"\u002Fvision\u002Fknowledge-graph","Wissensgraph"," Fakten aus internen Konversationen genauso extrahiert wie aus Kunden-E-Mails. Die Live-Extraktion pro Nachricht ist inzwischen für die ",[260,580,581],{},"eingehende"," Strecke angebunden (E-Mail und eingehende Kanalnachrichten), aber ",[260,584,585],{},"interner Chat zwischen Mitgliedern"," löst noch keine Extraktion aus — ",[28,588,589],{},"unifiedMessages.sendChatMessage"," liegt nicht auf dem Extraktionspfad.",[70,592,594],{"id":593},"schnellabfragen","Schnellabfragen",[15,596,597],{},"Teammitglieder können dem System direkt aus der Desktop-App Fragen stellen:",[517,599,600,603,606],{},[520,601,602],{},"„Wie viele Kontakte sind diesen Monat dem Newsletter-Thema beigetreten?“ → fragt Audience-Daten ab",[520,604,605],{},"„Wann haben wir zuletzt mit Acme Corp gesprochen?“ → fragt Konversations-Threads ab",[520,607,608],{},"„Zeig mir den Vertrag, den wir mit ihnen abgeschlossen haben“ → semantische Dateisuche",[15,610,611],{},"Schnellabfragen holen Kontext aus dem Wissensgraphen und dem Dateisystem, erzeugen eine Antwort mit Quellenangaben und rendern sie inline.",[53,613,616],{"title":614,"type":615},"Ausgeliefert: Ask-Anything ist live","success",[15,617,618,619,291,622,625,626,629,630,633,634,637,638,642,643,646,647,650,651,654,655,288,658,661,662,665,666,439,669,672,673,676,677,680,681,684],{},"Die Ask-Anything-Oberfläche ist durchgängig angebunden. Das Backend ist ",[28,620,621],{},"quickQuery.ts",[28,623,624],{},"ask",", eine ",[28,627,628],{},"authedAction",", die ",[260,631,632],{},"sowohl"," durch das Feature-Flag ",[28,635,636],{},"ai.knowledge"," ",[639,640,641],"em",{},"als auch"," durch die Berechtigung ",[28,644,645],{},"knowledge:read"," abgesichert ist (in dieser Reihenfolge über die interne Query ",[28,648,649],{},"quickQueryGate"," geprüft, da eine ",[28,652,653],{},"'use node'","-Action nicht direkt auf die Datenbank zugreifen kann). Sie fächert über beide Retrieval-Nähte auf — hybride Vektor- und Volltextsuche über ",[28,656,657],{},"knowledgeEntries",[28,659,660],{},"knowledge\u002Fretrieval.semanticSearch",") ",[639,663,664],{},"und"," den semantischen Dateispeicher (",[28,667,668],{},"semanticFileProcessing.semanticSearch",[28,670,671],{},"vector_files",") — und ruft dann das LLM auf (",[28,674,675],{},"lib\u002Fllm\u002Fdispatch.runLlmText","), um eine belegte Antwort zu synthetisieren, die jede abgerufene Quelle nummeriert ",[260,678,679],{},"zitiert",". Die zurückgegebenen ",[28,682,683],{},"sources"," umfassen sowohl Wissenseinträge als auch Dateien; abgerufene Titel\u002FTexte werden auf Prompt-Injection bereinigt und als nicht vertrauenswürdige Daten eingezäunt, bevor das Modell sie zu sehen bekommt. Das ist eine vom Klassifikator für eingehende Mail getrennte Leseoberfläche — sie braucht keine Klassifikationskategorie „Anfrage“.",[65,686,688],{"id":687},"visualisierungsagent","Visualisierungsagent",[15,690,691,692,694,695,698,699,702],{},"Ein spezialisierter Agent (",[28,693,34],{},"), der eine natürlichsprachige Eingabe entgegennimmt und über den LLM-Anbieter eine in sich geschlossene HTML\u002FCSS\u002FJS-Visualisierung erzeugt. Die admin-geschützte Mutation ",[28,696,697],{},"createFromPrompt"," fügt eine Platzhalterzeile ein und plant die interne Action ",[28,700,701],{},"generate"," ein; Ausgaben können in Konversationen gerendert oder ans Dashboard angeheftet werden.",[53,704,706],{"title":705,"type":615},"Echte Daten für erlaubte Datensätze, sonst illustrativ",[15,707,708,710,711,714,715,439,718,439,721,284,724,727,728,439,731,734,735,738,739,742,743,746,747,750,751,754,755,758,759,761],{},[28,709,701],{}," liest inzwischen ",[260,712,713],{},"echte Kontozahlen"," — aber nur über eine feste Erlaubnisliste von vier benannten Datensätzen: ",[28,716,717],{},"email_delivery_30d",[28,719,720],{},"agent_health",[28,722,723],{},"contact_growth",[28,725,726],{},"campaign_performance",". Jeder ist auf eine handgeschriebene, nur lesende interne Query abgebildet (",[28,729,730],{},"dataEmailDelivery30d",[28,732,733],{},"dataAgentHealth",", …); es gibt ",[260,736,737],{},"keinen Kanal für freie Abfragen",". Echte Daten werden ",[260,740,741],{},"nur"," verwendet, wenn der Aufrufer ein explizites, erlaubtes Argument ",[28,744,745],{},"dataset"," übergibt — aus freien Prompts wird nie ein Datensatz erschlossen. Wird ein Datensatz übergeben, kippt der System-Prompt von „nur illustrativ“ auf „verwende genau diese Zahlen“, und der gewählte Datensatz-Schlüssel wird in ",[28,748,749],{},"dataQuery"," persistiert, damit eine spätere Aktualisierung denselben erlaubten Ausschnitt erneut abrufen kann. Ohne expliziten Datensatz — oder wenn ein Abruf fehlschlägt — fällt es auf klar gekennzeichnete illustrative Beispieldaten zurück (die sichtbare Bildunterschrift „Illustrative example — not your account data“). Die Visualisierungsseite bietet eine ",[260,752,753],{},"Auswahl"," von Datensätzen (eine Grafik auf einen Live-Datensatz umstellen) und pro Grafik eine ",[260,756,757],{},"Aktualisieren","-Aktion, die den Abruf auf Wunsch erneut ausführt — beide lesen die Spalte ",[28,760,749],{}," (den persistierten erlaubten Schlüssel).",[70,763,765],{"id":764},"so-funktioniert-es-vision","So funktioniert es (Vision)",[211,767,770],{"className":768,"code":769,"language":216},[214],"User: \"Show me our email delivery rates for the last 30 days\"\n  → createFromPrompt (admin) inserts a placeholder + schedules generate()\n  → generate() uses the explicitly-selected allowlisted dataset, if any\n    (email_delivery_30d) and fetches the REAL numbers via a read-only\n    internal query (no dataset → clearly-labeled illustrative sample data)\n  → generate() asks the LLM provider for self-contained HTML\u002FCSS\u002FJS\n    built from those exact numbers\n  → Frontend renders the html in a sandboxed iframe\n  → User can interact: hover for details, filter, change time range\n",[28,771,769],{"__ignoreMap":219},[15,773,774,775,778],{},"Der Visualisierungsagent erzeugt ",[260,776,777],{},"rohes HTML, CSS und JavaScript"," — das gibt ihm volle gestalterische Freiheit für jede Art von visueller Ausgabe. Anders als bei eingeschränkten Charting-Bibliotheken kann der Agent so genau das bauen, was die Daten brauchen: Diagramme, Dashboards, Datentabellen, animierte Fortschrittsanzeigen, interaktive Karten oder vollständig maßgeschneiderte Visualisierungen.",[517,780,781,787,793,799],{},[520,782,783,786],{},[260,784,785],{},"Volle Flexibilität"," — der Agent schreibt HTML\u002FCSS\u002FJS direkt und ist nicht auf das Vokabular einer Charting-Bibliothek beschränkt",[520,788,789,792],{},[260,790,791],{},"Interaktiv"," — JavaScript ermöglicht Hover-Tooltips, Filtern per Klick, animierte Übergänge, Echtzeit-Aktualisierungen",[520,794,795,798],{},[260,796,797],{},"Portabel"," — Visualisierungen sind in sich geschlossene HTML-Bundles, die gespeichert, geteilt, in Berichte eingebettet oder an Dashboards angeheftet werden können",[520,800,801,804,805,808,809,812,813,816],{},[260,802,803],{},"Isoliert"," — gerendert in einem sandboxed ",[28,806,807],{},"\u003Ciframe>"," mit ",[28,810,811],{},"sandbox=\"allow-scripts\""," — kein Zugriff auf die übergeordnete Seite, den Convex-Client, Cookies oder die Navigation. Das iframe kommuniziert ausschließlich per ",[28,814,815],{},"postMessage"," für Resize-Events",[53,818,821],{"title":819,"type":820},"Sandboxing ist entscheidend","warning",[15,822,823,824,827,828,831],{},"Agentengenerierter Code läuft in einem sandboxed iframe ohne Zugriff auf die Host-Anwendung. Das Attribut ",[28,825,826],{},"sandbox"," blockiert Top-Level-Navigation, Formularübermittlung, Popups und Same-Origin-Zugriff. Nur ",[28,829,830],{},"allow-scripts"," ist aktiviert, damit das eigene JavaScript der Visualisierung ausgeführt werden kann. Das verhindert, dass eingeschleuster Code auf Nutzersitzungen, Convex-Daten oder das DOM der übergeordneten Anwendung zugreift.",[70,833,835],{"id":834},"schema","Schema",[211,837,841],{"className":838,"code":839,"language":840,"meta":219,"style":219},"language-typescript shiki shiki-themes github-light github-dark-dimmed","\u002F\u002F apps\u002Fapi\u002Fconvex\u002Fschema\u002Fdashboard.ts\nvisualizations: defineTable({\n  title: v.string(),\n  description: v.optional(v.string()),\n  html: v.string(),                \u002F\u002F Self-contained HTML document (HTML + CSS + JS)\n  dataQuery: v.optional(v.string()), \u002F\u002F Allowlisted dataset key the viz was built from (for refresh); unset when illustrative\n  pinned: v.boolean(),             \u002F\u002F Pinned to dashboard\n  createdBy: v.string(),           \u002F\u002F User or agent ID\n  threadId: v.optional(v.id('conversationThreads')),\n  createdAt: v.number(),\n  updatedAt: v.number(),\n})\n  .index('by_pinned', ['pinned'])\n  .index('by_created_at', ['createdAt'])\n","typescript",[28,842,843,852,870,882,899,913,931,946,960,983,994,1004,1010,1033],{"__ignoreMap":219},[844,845,848],"span",{"class":846,"line":847},"line",1,[844,849,851],{"class":850},"sDN9O","\u002F\u002F apps\u002Fapi\u002Fconvex\u002Fschema\u002Fdashboard.ts\n",[844,853,855,859,863,867],{"class":846,"line":854},2,[844,856,858],{"class":857},"sOLd2","visualizations",[844,860,862],{"class":861},"sYgZi",": ",[844,864,866],{"class":865},"sPO5f","defineTable",[844,868,869],{"class":861},"({\n",[844,871,873,876,879],{"class":846,"line":872},3,[844,874,875],{"class":861},"  title: v.",[844,877,878],{"class":865},"string",[844,880,881],{"class":861},"(),\n",[844,883,885,888,891,894,896],{"class":846,"line":884},4,[844,886,887],{"class":861},"  description: v.",[844,889,890],{"class":865},"optional",[844,892,893],{"class":861},"(v.",[844,895,878],{"class":865},[844,897,898],{"class":861},"()),\n",[844,900,902,905,907,910],{"class":846,"line":901},5,[844,903,904],{"class":861},"  html: v.",[844,906,878],{"class":865},[844,908,909],{"class":861},"(),                ",[844,911,912],{"class":850},"\u002F\u002F Self-contained HTML document (HTML + CSS + JS)\n",[844,914,916,919,921,923,925,928],{"class":846,"line":915},6,[844,917,918],{"class":861},"  dataQuery: v.",[844,920,890],{"class":865},[844,922,893],{"class":861},[844,924,878],{"class":865},[844,926,927],{"class":861},"()), ",[844,929,930],{"class":850},"\u002F\u002F Allowlisted dataset key the viz was built from (for refresh); unset when illustrative\n",[844,932,934,937,940,943],{"class":846,"line":933},7,[844,935,936],{"class":861},"  pinned: v.",[844,938,939],{"class":865},"boolean",[844,941,942],{"class":861},"(),             ",[844,944,945],{"class":850},"\u002F\u002F Pinned to dashboard\n",[844,947,949,952,954,957],{"class":846,"line":948},8,[844,950,951],{"class":861},"  createdBy: v.",[844,953,878],{"class":865},[844,955,956],{"class":861},"(),           ",[844,958,959],{"class":850},"\u002F\u002F User or agent ID\n",[844,961,963,966,968,970,973,976,980],{"class":846,"line":962},9,[844,964,965],{"class":861},"  threadId: v.",[844,967,890],{"class":865},[844,969,893],{"class":861},[844,971,972],{"class":865},"id",[844,974,975],{"class":861},"(",[844,977,979],{"class":978},"s-HuK","'conversationThreads'",[844,981,982],{"class":861},")),\n",[844,984,986,989,992],{"class":846,"line":985},10,[844,987,988],{"class":861},"  createdAt: v.",[844,990,991],{"class":865},"number",[844,993,881],{"class":861},[844,995,997,1000,1002],{"class":846,"line":996},11,[844,998,999],{"class":861},"  updatedAt: v.",[844,1001,991],{"class":865},[844,1003,881],{"class":861},[844,1005,1007],{"class":846,"line":1006},12,[844,1008,1009],{"class":861},"})\n",[844,1011,1013,1016,1019,1021,1024,1027,1030],{"class":846,"line":1012},13,[844,1014,1015],{"class":861},"  .",[844,1017,1018],{"class":865},"index",[844,1020,975],{"class":861},[844,1022,1023],{"class":978},"'by_pinned'",[844,1025,1026],{"class":861},", [",[844,1028,1029],{"class":978},"'pinned'",[844,1031,1032],{"class":861},"])\n",[844,1034,1036,1038,1040,1042,1045,1047,1050],{"class":846,"line":1035},14,[844,1037,1015],{"class":861},[844,1039,1018],{"class":865},[844,1041,975],{"class":861},[844,1043,1044],{"class":978},"'by_created_at'",[844,1046,1026],{"class":861},[844,1048,1049],{"class":978},"'createdAt'",[844,1051,1032],{"class":861},[15,1053,1054,1055,1057,1058,237,1061,237,1064,1067,1068,1070],{},"Die Agenten-Action liegt in ",[28,1056,34],{},": die Queries ",[28,1059,1060],{},"list",[28,1062,1063],{},"get",[28,1065,1066],{},"listPinned",", die admin-geschützte Action ",[28,1069,701],{}," (die einen erlaubten Datensatz abruft, sofern er zugeordnet ist, bevor sie den LLM-Anbieter für das in sich geschlossene HTML aufruft), die nur lesenden Datensatz-Abrufer sowie die Mutationen zum An- und Abheften.",[70,1072,1074],{"id":1073},"rendering","Rendering",[15,1076,1077],{},"Das Frontend rendert Visualisierungen über ein sandboxed iframe:",[211,1079,1083],{"className":1080,"code":1081,"language":1082,"meta":219,"style":219},"language-html shiki shiki-themes github-light github-dark-dimmed","\u003Ciframe\n  :srcdoc=\"visualization.html\"\n  sandbox=\"allow-scripts\"\n  referrerpolicy=\"no-referrer\"\n  style=\"width: 100%; border: none;\"\n\u002F>\n","html",[28,1084,1085,1094,1106,1116,1126,1136],{"__ignoreMap":219},[844,1086,1087,1090],{"class":846,"line":847},[844,1088,1089],{"class":861},"\u003C",[844,1091,1093],{"class":1092},"sIAta","iframe\n",[844,1095,1096,1100,1103],{"class":846,"line":854},[844,1097,1099],{"class":1098},"sMOND","  :srcdoc",[844,1101,1102],{"class":861},"=",[844,1104,1105],{"class":978},"\"visualization.html\"\n",[844,1107,1108,1111,1113],{"class":846,"line":872},[844,1109,1110],{"class":1098},"  sandbox",[844,1112,1102],{"class":861},[844,1114,1115],{"class":978},"\"allow-scripts\"\n",[844,1117,1118,1121,1123],{"class":846,"line":884},[844,1119,1120],{"class":1098},"  referrerpolicy",[844,1122,1102],{"class":861},[844,1124,1125],{"class":978},"\"no-referrer\"\n",[844,1127,1128,1131,1133],{"class":846,"line":901},[844,1129,1130],{"class":1098},"  style",[844,1132,1102],{"class":861},[844,1134,1135],{"class":978},"\"width: 100%; border: none;\"\n",[844,1137,1138,1141],{"class":846,"line":915},[844,1139,237],{"class":1140},"sNWHW",[844,1142,1143],{"class":861},">\n",[15,1145,1146,1147,1150,1151,1153,1154,1156],{},"Das iframe nutzt ",[28,1148,1149],{},"srcdoc"," (kein Netzwerkabruf) und ",[28,1152,811],{}," (JS wird ausgeführt, aber kein DOM-Zugriff auf das übergeordnete Dokument). Ein ",[28,1155,815],{},"-Listener verarbeitet Resize-Events, damit sich die iframe-Höhe an den Inhalt anpasst.",[65,1158,1160],{"id":1159},"adaptives-dashboard","Adaptives Dashboard",[15,1162,1163,1164,1167],{},"Das Dashboard ist kein statisches Raster aus Widgets. Es passt sich daran an, ",[260,1165,1166],{},"was die Nutzerin oder der Nutzer gerade jetzt braucht"," — morgens anders als abends, montags anders als freitags, für eine Support-Leitung anders als für eine Marketing-Managerin.",[70,1169,1171],{"id":1170},"kontextsignale","Kontextsignale",[15,1173,1174],{},"Das Dashboard setzt sich aus Kontextsignalen zusammen:",[85,1176,1177,1190],{},[88,1178,1179],{},[91,1180,1181,1184,1187],{},[94,1182,1183],{},"Signal",[94,1185,1186],{},"Was es uns sagt",[94,1188,1189],{},"Beispielwirkung",[102,1191,1192,1205,1218,1231,1244,1257],{},[91,1193,1194,1199,1202],{},[107,1195,1196],{},[260,1197,1198],{},"Tageszeit",[107,1200,1201],{},"Morgens = planen, abends = auswerten",[107,1203,1204],{},"Morgens: die heute geplanten Kampagnen, die über Nacht eingegangene Warteschlange. Abends: die heutige Leistungsübersicht, offene Punkte für morgen",[91,1206,1207,1212,1215],{},[107,1208,1209],{},[260,1210,1211],{},"Wochentag",[107,1213,1214],{},"Montag = aufholen, Freitag = abschließen",[107,1216,1217],{},"Montag: der Eingangsrückstand vom Wochenende, der Kampagnenplan der Woche. Freitag: Wochenkennzahlen, ungelöste Threads",[91,1219,1220,1225,1228],{},[107,1221,1222],{},[260,1223,1224],{},"Rolle",[107,1226,1227],{},"Wofür die Person verantwortlich ist",[107,1229,1230],{},"Eine Support-Leitung sieht Warteschlangentiefe und SLA-Status. Eine Marketing-Managerin sieht Kampagnenleistung und Audience-Wachstum",[91,1232,1233,1238,1241],{},[107,1234,1235],{},[260,1236,1237],{},"Jüngste Aktivität",[107,1239,1240],{},"Woran die Person gearbeitet hat",[107,1242,1243],{},"Haben Sie die letzte Stunde an einer Kampagne gearbeitet, hebt das Dashboard deren Echtzeit-Zustellstatistiken hervor",[91,1245,1246,1251,1254],{},[107,1247,1248],{},[260,1249,1250],{},"Offene Punkte",[107,1252,1253],{},"Was Aufmerksamkeit braucht",[107,1255,1256],{},"Einträge in der Verifizierungs-Warteschlange, Kampagnen, die auf Freigabe warten, Ihnen zugewiesene Threads",[91,1258,1259,1264,1267],{},[107,1260,1261],{},[260,1262,1263],{},"Anomalien",[107,1265,1266],{},"Was gerade ungewöhnlich ist",[107,1268,1269],{},"Bounce-Rate-Spitze, ungewöhnliches Eingangsvolumen, Zustellprobleme bei einem bestimmten ISP",[70,1271,1273],{"id":1272},"so-funktioniert-es","So funktioniert es",[15,1275,1276,1277,1280],{},"Das Dashboard besteht aus ",[260,1278,1279],{},"Karten"," — jede Karte ist eine in sich geschlossene Einheit, die ihre eigenen Daten über reaktive Convex-Queries lädt. Die Layout-Engine des Dashboards entscheidet anhand der obigen Kontextsignale, welche Karten in welcher Reihenfolge angezeigt werden.",[211,1282,1284],{"className":838,"code":1283,"language":840,"meta":219,"style":219},"\u002F\u002F apps\u002Fapi\u002Fconvex\u002Fschema\u002Fdashboard.ts\ndashboardLayouts: defineTable({\n  userId: v.string(),             \u002F\u002F Per-user layout (BetterAuth user id)\n  \u002F\u002F Context-driven layout rules\n  rules: v.array(v.object({\n    condition: v.object({\n      timeRange: v.optional(v.object({    \u002F\u002F e.g., { start: '06:00', end: '12:00' }\n        start: v.string(),\n        end: v.string(),\n      })),\n      dayOfWeek: v.optional(v.array(v.number())),  \u002F\u002F 0=Sun, 1=Mon, etc.\n      role: v.optional(v.string()),\n    }),\n    cards: v.array(v.object({\n      type: v.string(),           \u002F\u002F 'verification_queue', 'campaign_performance', 'inbound_summary', etc.\n      size: v.union(v.literal('small'), v.literal('medium'), v.literal('large')),\n    })),\n    priority: v.number(),         \u002F\u002F Higher priority rules override lower ones\n  })),\n  \u002F\u002F Pinned cards always show regardless of context\n  pinnedCards: v.optional(v.array(v.object({\n    type: v.string(),\n    size: v.union(v.literal('small'), v.literal('medium'), v.literal('large')),\n  }))),\n  updatedAt: v.number(),\n})\n  .index('by_user', ['userId'])\n",[28,1285,1286,1290,1301,1313,1318,1333,1342,1359,1368,1377,1382,1403,1416,1421,1434,1447,1487,1493,1507,1513,1519,1537,1547,1581,1587,1596,1601],{"__ignoreMap":219},[844,1287,1288],{"class":846,"line":847},[844,1289,851],{"class":850},[844,1291,1292,1295,1297,1299],{"class":846,"line":854},[844,1293,1294],{"class":857},"dashboardLayouts",[844,1296,862],{"class":861},[844,1298,866],{"class":865},[844,1300,869],{"class":861},[844,1302,1303,1306,1308,1310],{"class":846,"line":872},[844,1304,1305],{"class":861},"  userId: v.",[844,1307,878],{"class":865},[844,1309,942],{"class":861},[844,1311,1312],{"class":850},"\u002F\u002F Per-user layout (BetterAuth user id)\n",[844,1314,1315],{"class":846,"line":884},[844,1316,1317],{"class":850},"  \u002F\u002F Context-driven layout rules\n",[844,1319,1320,1323,1326,1328,1331],{"class":846,"line":901},[844,1321,1322],{"class":861},"  rules: v.",[844,1324,1325],{"class":865},"array",[844,1327,893],{"class":861},[844,1329,1330],{"class":865},"object",[844,1332,869],{"class":861},[844,1334,1335,1338,1340],{"class":846,"line":915},[844,1336,1337],{"class":861},"    condition: v.",[844,1339,1330],{"class":865},[844,1341,869],{"class":861},[844,1343,1344,1347,1349,1351,1353,1356],{"class":846,"line":933},[844,1345,1346],{"class":861},"      timeRange: v.",[844,1348,890],{"class":865},[844,1350,893],{"class":861},[844,1352,1330],{"class":865},[844,1354,1355],{"class":861},"({    ",[844,1357,1358],{"class":850},"\u002F\u002F e.g., { start: '06:00', end: '12:00' }\n",[844,1360,1361,1364,1366],{"class":846,"line":948},[844,1362,1363],{"class":861},"        start: v.",[844,1365,878],{"class":865},[844,1367,881],{"class":861},[844,1369,1370,1373,1375],{"class":846,"line":962},[844,1371,1372],{"class":861},"        end: v.",[844,1374,878],{"class":865},[844,1376,881],{"class":861},[844,1378,1379],{"class":846,"line":985},[844,1380,1381],{"class":861},"      })),\n",[844,1383,1384,1387,1389,1391,1393,1395,1397,1400],{"class":846,"line":996},[844,1385,1386],{"class":861},"      dayOfWeek: v.",[844,1388,890],{"class":865},[844,1390,893],{"class":861},[844,1392,1325],{"class":865},[844,1394,893],{"class":861},[844,1396,991],{"class":865},[844,1398,1399],{"class":861},"())),  ",[844,1401,1402],{"class":850},"\u002F\u002F 0=Sun, 1=Mon, etc.\n",[844,1404,1405,1408,1410,1412,1414],{"class":846,"line":1006},[844,1406,1407],{"class":861},"      role: v.",[844,1409,890],{"class":865},[844,1411,893],{"class":861},[844,1413,878],{"class":865},[844,1415,898],{"class":861},[844,1417,1418],{"class":846,"line":1012},[844,1419,1420],{"class":861},"    }),\n",[844,1422,1423,1426,1428,1430,1432],{"class":846,"line":1035},[844,1424,1425],{"class":861},"    cards: v.",[844,1427,1325],{"class":865},[844,1429,893],{"class":861},[844,1431,1330],{"class":865},[844,1433,869],{"class":861},[844,1435,1437,1440,1442,1444],{"class":846,"line":1436},15,[844,1438,1439],{"class":861},"      type: v.",[844,1441,878],{"class":865},[844,1443,956],{"class":861},[844,1445,1446],{"class":850},"\u002F\u002F 'verification_queue', 'campaign_performance', 'inbound_summary', etc.\n",[844,1448,1450,1453,1456,1458,1461,1463,1466,1469,1471,1473,1476,1478,1480,1482,1485],{"class":846,"line":1449},16,[844,1451,1452],{"class":861},"      size: v.",[844,1454,1455],{"class":865},"union",[844,1457,893],{"class":861},[844,1459,1460],{"class":865},"literal",[844,1462,975],{"class":861},[844,1464,1465],{"class":978},"'small'",[844,1467,1468],{"class":861},"), v.",[844,1470,1460],{"class":865},[844,1472,975],{"class":861},[844,1474,1475],{"class":978},"'medium'",[844,1477,1468],{"class":861},[844,1479,1460],{"class":865},[844,1481,975],{"class":861},[844,1483,1484],{"class":978},"'large'",[844,1486,982],{"class":861},[844,1488,1490],{"class":846,"line":1489},17,[844,1491,1492],{"class":861},"    })),\n",[844,1494,1496,1499,1501,1504],{"class":846,"line":1495},18,[844,1497,1498],{"class":861},"    priority: v.",[844,1500,991],{"class":865},[844,1502,1503],{"class":861},"(),         ",[844,1505,1506],{"class":850},"\u002F\u002F Higher priority rules override lower ones\n",[844,1508,1510],{"class":846,"line":1509},19,[844,1511,1512],{"class":861},"  })),\n",[844,1514,1516],{"class":846,"line":1515},20,[844,1517,1518],{"class":850},"  \u002F\u002F Pinned cards always show regardless of context\n",[844,1520,1522,1525,1527,1529,1531,1533,1535],{"class":846,"line":1521},21,[844,1523,1524],{"class":861},"  pinnedCards: v.",[844,1526,890],{"class":865},[844,1528,893],{"class":861},[844,1530,1325],{"class":865},[844,1532,893],{"class":861},[844,1534,1330],{"class":865},[844,1536,869],{"class":861},[844,1538,1540,1543,1545],{"class":846,"line":1539},22,[844,1541,1542],{"class":861},"    type: v.",[844,1544,878],{"class":865},[844,1546,881],{"class":861},[844,1548,1550,1553,1555,1557,1559,1561,1563,1565,1567,1569,1571,1573,1575,1577,1579],{"class":846,"line":1549},23,[844,1551,1552],{"class":861},"    size: v.",[844,1554,1455],{"class":865},[844,1556,893],{"class":861},[844,1558,1460],{"class":865},[844,1560,975],{"class":861},[844,1562,1465],{"class":978},[844,1564,1468],{"class":861},[844,1566,1460],{"class":865},[844,1568,975],{"class":861},[844,1570,1475],{"class":978},[844,1572,1468],{"class":861},[844,1574,1460],{"class":865},[844,1576,975],{"class":861},[844,1578,1484],{"class":978},[844,1580,982],{"class":861},[844,1582,1584],{"class":846,"line":1583},24,[844,1585,1586],{"class":861},"  }))),\n",[844,1588,1590,1592,1594],{"class":846,"line":1589},25,[844,1591,999],{"class":861},[844,1593,991],{"class":865},[844,1595,881],{"class":861},[844,1597,1599],{"class":846,"line":1598},26,[844,1600,1009],{"class":861},[844,1602,1604,1606,1608,1610,1613,1615,1618],{"class":846,"line":1603},27,[844,1605,1015],{"class":861},[844,1607,1018],{"class":865},[844,1609,975],{"class":861},[844,1611,1612],{"class":978},"'by_user'",[844,1614,1026],{"class":861},[844,1616,1617],{"class":978},"'userId'",[844,1619,1032],{"class":861},[15,1621,1622,1623,1625,1626,1629,1630,1633,1634,1636,1637,1640,1641,1644,1645,1648,1649,1652,1653,1656,1657,1660],{},"Die Layout-Engine in ",[28,1624,38],{}," löst das aktive Layout auf: ",[28,1627,1628],{},"getLayout"," ermittelt die Rolle des Mitglieds (über ",[28,1631,1632],{},"getBetterAuthSessionWithRole",") und wertet die Regeln nach Priorität gegen die aktuelle Tageszeit, den Wochentag ",[260,1635,664],{}," die Rolle aus, mischt angeheftete Karten hinein und fällt auf einen sinnvollen Standard zurück, wenn keine Regel passt. ",[28,1638,1639],{},"saveLayout"," lässt jedes Mitglied nur das eigene Layout verwalten (geschlüsselt ",[28,1642,1643],{},"by_user"," auf die User-ID der Session) — es persistiert den vollständigen bearbeiteten Kartensatz als ",[28,1646,1647],{},"pinnedCards"," und optional die adaptiven ",[28,1650,1651],{},"rules",". Die Query ",[28,1654,1655],{},"getAvailableCards"," legt die registrierten Kartentypen offen, und ",[28,1658,1659],{},"getRawLayout"," liefert für den Editor das gespeicherte Layout (inklusive Regeln).",[53,1662,1664],{"title":1663,"type":615},"Rollenbedingungen werden erzwungen",[15,1665,1666,1667,1670,1671,1673,1674,1677],{},"Regelbedingungen unterstützen ein Feld ",[28,1668,1669],{},"role",", und ",[28,1672,1628],{}," beachtet es inzwischen: Es ermittelt die Rolle des Mitglieds, und ",[28,1675,1676],{},"matchesCondition"," trifft auf eine rollenbezogene Regel nur zu, wenn die Rolle passt (eine Regel ohne Rolle passt weiterhin auf alle). Die Rollenauflösung erfolgt nach bestem Bemühen — eine leere Rolle überspringt schlicht rollenbezogene Regeln, statt das Layout zu verweigern. Bedingungen für Tageszeit und Wochentag werden ebenso beachtet.",[70,1679,1681],{"id":1680},"kartentypen","Kartentypen",[15,1683,1684,1685,193,1688,1690],{},"Die registrierten Kartentypen stammen aus ",[28,1686,1687],{},"DEFAULT_CARDS",[28,1689,38],{},":",[85,1692,1693,1703],{},[88,1694,1695],{},[91,1696,1697,1700],{},[94,1698,1699],{},"Karte",[94,1701,1702],{},"Was sie zeigt",[102,1704,1705,1715,1724,1734,1743,1753,1763,1773,1783,1793,1803,1813],{},[91,1706,1707,1712],{},[107,1708,1709],{},[28,1710,1711],{},"verification_queue",[107,1713,1714],{},"Offene Agentenentwürfe, die eine Prüfung brauchen",[91,1716,1717,1721],{},[107,1718,1719],{},[28,1720,726],{},[107,1722,1723],{},"Kennzahlen der letzten Kampagnen",[91,1725,1726,1731],{},[107,1727,1728],{},[28,1729,1730],{},"channel_health",[107,1732,1733],{},"Status aller Kommunikationskanäle",[91,1735,1736,1740],{},[107,1737,1738],{},[28,1739,720],{},[107,1741,1742],{},"Kennzahlen der KI-Agenten-Strecke",[91,1744,1745,1750],{},[107,1746,1747],{},[28,1748,1749],{},"recent_contacts",[107,1751,1752],{},"Neu hinzugefügte oder aktive Kontakte",[91,1754,1755,1760],{},[107,1756,1757],{},[28,1758,1759],{},"queue_depth",[107,1761,1762],{},"Verarbeitungswarteschlange eingehender Nachrichten",[91,1764,1765,1770],{},[107,1766,1767],{},[28,1768,1769],{},"delivery_rates",[107,1771,1772],{},"Erfolgsquoten der E-Mail-Zustellung",[91,1774,1775,1780],{},[107,1776,1777],{},[28,1778,1779],{},"pinned_visualizations",[107,1781,1782],{},"Angeheftete Datenvisualisierungen",[91,1784,1785,1790],{},[107,1786,1787],{},[28,1788,1789],{},"knowledge_graph",[107,1791,1792],{},"Jüngste Wissenseinträge",[91,1794,1795,1800],{},[107,1796,1797],{},[28,1798,1799],{},"upcoming_campaigns",[107,1801,1802],{},"Geplante Kampagnen",[91,1804,1805,1810],{},[107,1806,1807],{},[28,1808,1809],{},"cost_by_step",[107,1811,1812],{},"LLM-Tokenkosten pro Schritt der Agenten-Strecke",[91,1814,1815,1820],{},[107,1816,1817],{},[28,1818,1819],{},"accuracy_trend",[107,1821,1822],{},"Trend von automatischer Freigabe vs. Ablehnung über die Zeit",[15,1824,1825,1826,439,1828,1830,1831,288,1833,1836,1837,1840,1841,1836,1844,1847,1848,1850,1851,1853],{},"Die letzten beiden (",[28,1827,1809],{},[28,1829,1819],{},") sind vollständig angebunden: Sie sind registrierte Kartentypen mit Renderern in ",[28,1832,174],{},[28,1834,1835],{},"CostByStepCard.vue",", das ",[28,1838,1839],{},"api.agentHealth.getCostByStep"," liest, und ",[28,1842,1843],{},"AccuracyTrendCard.vue",[28,1845,1846],{},"getAccuracyTrend"," liest) — ",[28,1849,1809],{}," schlüsselt die LLM-Kosten pro Schritt der Strecke auf, und ",[28,1852,1819],{}," stellt das Verhältnis automatischer Freigaben der Ablehnungsrate über die Zeit gegenüber.",[70,1855,1857],{"id":1856},"sinnvolle-standardwerte","Sinnvolle Standardwerte",[15,1859,1860,1861,1864],{},"Ein Mitglied, das kein Layout gespeichert hat, erhält den eingebauten Standard (",[28,1862,1863],{},"getDefaultLayout","): Prüf-Warteschlange, Kampagnenleistung, Kanalzustand, Agenten-Gesundheit, Zustellraten, jüngste Kontakte. Von dort aus speichert es Regeln, heftet Karten an und stimmt sein eigenes Layout ab.",[53,1866,1868],{"title":1867,"type":820},"Vision: Layout-Vorschläge",[15,1869,1870],{},"Das längerfristige Ziel ist ein Agent, der Layout-Änderungen vorschlägt („Sie schauen jeden Morgen auf die Kampagnenleistung, aber sie steht ganz unten — soll ich sie nach oben verschieben?“) und aus Nutzungsmustern lernt. Schema und Resolver unterstützen heute handgeschriebene Regeln; nutzungsgetriebenes Lernen und Agentenvorschläge sind noch nicht implementiert.",[70,1872,1874],{"id":1873},"agentengenerierte-dashboard-karten","Agentengenerierte Dashboard-Karten",[15,1876,1877,1878,1880,1881,1883,1884,1886,1887,1890],{},"Der Visualisierungsagent kann eine Karte ",[28,1879,1779],{}," erzeugen. Heftet ein Mitglied eine Visualisierung an, erscheint sie auf dem Dashboard und rendert ihr gespeichertes ",[28,1882,1082],{}," erneut in einem sandboxed iframe. (Die Spalte ",[28,1885,749],{}," hält inzwischen fest, aus welchem erlaubten Datensatz die Visualisierung gebaut wurde, und eine Aktion für bedarfsgesteuerte Live-Daten-Aktualisierung führt den Abruf von der Grafikkarte aus erneut aus — siehe die Anmerkung unter ",[19,1888,688],{"href":1889},"#visualization-agent",".)",[65,1892,1894],{"id":1893},"agenten-gesundheit-monitoring","Agenten-Gesundheit & Monitoring",[15,1896,1897,1898,1900,1901,1904,1905,1908],{},"Während die Agenten-Strecke eingehende Nachrichten verarbeitet, braucht das Deployment zentrales Monitoring — nicht nur zur Fehlersuche, sondern für die Sicherheit. Ein sich fehlverhaltender LLM-Anbieter oder ein Anstieg an Fehlschlägen ist ein Signal, das eine automatisierte Reaktion erfordert. Das ist in ",[28,1899,42],{}," live: Eine Action ",[28,1902,1903],{},"rollupMetrics"," läuft per Cron alle fünf Minuten, schreibt Datenpunkte in ",[28,1906,1907],{},"agentMetrics"," und wertet die Circuit Breaker aus; die Monitoring-UI liest das aggregierte Dashboard und die Metrikhistorie, während die Strecke den Breaker-Zustand intern liest.",[70,1910,1912],{"id":1911},"metriken","Metriken",[15,1914,1915,1917],{},[28,1916,1907],{}," definiert sieben Metriktypen. Der Fünf-Minuten-Rollup erfasst inzwischen alle sieben.",[85,1919,1920,1937],{},[88,1921,1922],{},[91,1923,1924,1931,1934],{},[94,1925,1926,1927,1930],{},"Metrik (",[28,1928,1929],{},"metricType",")",[94,1932,1933],{},"Was sie misst",[94,1935,1936],{},"Heute per Rollup befüllt?",[102,1938,1939,1954,1966,1978,1990,2002,2014],{},[91,1940,1941,1945,1951],{},[107,1942,1943],{},[28,1944,1759],{},[107,1946,1947,1948,1930],{},"Unverarbeitete eingehende Nachrichten (",[28,1949,1950],{},"received",[107,1952,1953],{},"Ja",[91,1955,1956,1961,1964],{},[107,1957,1958],{},[28,1959,1960],{},"processing_latency",[107,1962,1963],{},"Durchschnittliche Dauer abgeschlossener Aktionen im Zeitfenster",[107,1965,1953],{},[91,1967,1968,1973,1976],{},[107,1969,1970],{},[28,1971,1972],{},"error_rate",[107,1974,1975],{},"Fehlgeschlagene Aktionen \u002F Gesamtzahl der Aktionen im Zeitfenster",[107,1977,1953],{},[91,1979,1980,1985,1988],{},[107,1981,1982],{},[28,1983,1984],{},"auto_approve_ratio",[107,1986,1987],{},"Automatisch freigegebene vs. von Menschen geprüfte Routen im Zeitfenster",[107,1989,1953],{},[91,1991,1992,1997,2000],{},[107,1993,1994],{},[28,1995,1996],{},"rejection_rate",[107,1998,1999],{},"Ablehnungen \u002F (Freigaben + Ablehnungen) über die letzten 24 h",[107,2001,1953],{},[91,2003,2004,2009,2012],{},[107,2005,2006],{},[28,2007,2008],{},"llm_cost",[107,2010,2011],{},"Gesamter LLM-Tokenverbrauch über die Aktionen des Zeitfensters",[107,2013,1953],{},[91,2015,2016,2021,2024],{},[107,2017,2018],{},[28,2019,2020],{},"classification_accuracy",[107,2022,2023],{},"Modellqualität über die Zeit",[107,2025,2026,2027,2030],{},"Ja (Konfidenz-Näherung — mittlere selbstberichtete ",[28,2028,2029],{},"classify","-Konfidenz, keine menschliche Ground Truth)",[53,2032,2034],{"title":2033,"type":615},"Sieben von sieben Metriken werden jetzt befüllt",[15,2035,2036,2037,439,2039,284,2041,2043,2044,2046,2047,2050,2051,2053,2054,2056,2057,2060,2061,2063,2064,2066],{},"Der eingeplante Rollup leitet inzwischen zusätzlich zu ",[28,2038,1759],{},[28,2040,1960],{},[28,2042,1972],{}," auch ",[28,2045,1984],{}," (aus den ",[28,2048,2049],{},"route","-Schritt-Entscheidungen des Zeitfensters), ",[28,2052,1996],{}," (aus dem Feedback der menschlichen Verifizierungs-Warteschlange über die letzten 24 h, Ablehnungen gegen Freigaben+Ablehnungen gezählt) und ",[28,2055,2008],{}," (summierte ",[28,2058,2059],{},"tokenUsage"," über die Aktionen des Zeitfensters) ab. ",[28,2062,2020],{}," wird nun als Konfidenz-Näherung erfasst — die mittlere selbstberichtete Konfidenz der ",[28,2065,2029],{},"-Aktionen des Zeitfensters —, da es kein menschliches Ground-Truth-Signal gibt, gegen das bewertet werden könnte.",[70,2068,2070],{"id":2069},"agentenkonfiguration-pro-deployment","Agentenkonfiguration pro Deployment",[15,2072,2073,2074,2077,2078,2081,2082,2085],{},"Die operative Feinabstimmung der Strecke liegt in einer einzigen ",[28,2075,2076],{},"agentConfig","-Zeile (",[28,2079,2080],{},"apps\u002Fapi\u002Fconvex\u002Fschema\u002Finbox.ts","). Sie ist ein deploymentweiter Singleton; der Hauptschalter für den gesamten Agenten ist das Feature-Flag ",[28,2083,2084],{},"ai.agent",", keine Spalte hier:",[211,2087,2089],{"className":838,"code":2088,"language":840,"meta":219,"style":219},"agentConfig: defineTable({\n  isAutoReplyEnabled: v.boolean(),\n  confidenceThreshold: v.number(),       \u002F\u002F minimum confidence for auto-approval\n  toneDescription: v.optional(v.string()),\n  signatureTemplate: v.optional(v.string()),\n  \u002F\u002F Auto-reply rate limiting\n  maxDailyAutoReplies: v.optional(v.number()),\n  dailyAutoReplyCount: v.optional(v.number()),\n  dailyAutoReplyResetAt: v.optional(v.number()),\n  createdAt: v.number(),\n  updatedAt: v.number(),\n})\n",[28,2090,2091,2101,2110,2123,2136,2149,2154,2167,2180,2193,2201,2209],{"__ignoreMap":219},[844,2092,2093,2095,2097,2099],{"class":846,"line":847},[844,2094,2076],{"class":857},[844,2096,862],{"class":861},[844,2098,866],{"class":865},[844,2100,869],{"class":861},[844,2102,2103,2106,2108],{"class":846,"line":854},[844,2104,2105],{"class":861},"  isAutoReplyEnabled: v.",[844,2107,939],{"class":865},[844,2109,881],{"class":861},[844,2111,2112,2115,2117,2120],{"class":846,"line":872},[844,2113,2114],{"class":861},"  confidenceThreshold: v.",[844,2116,991],{"class":865},[844,2118,2119],{"class":861},"(),       ",[844,2121,2122],{"class":850},"\u002F\u002F minimum confidence for auto-approval\n",[844,2124,2125,2128,2130,2132,2134],{"class":846,"line":884},[844,2126,2127],{"class":861},"  toneDescription: v.",[844,2129,890],{"class":865},[844,2131,893],{"class":861},[844,2133,878],{"class":865},[844,2135,898],{"class":861},[844,2137,2138,2141,2143,2145,2147],{"class":846,"line":901},[844,2139,2140],{"class":861},"  signatureTemplate: v.",[844,2142,890],{"class":865},[844,2144,893],{"class":861},[844,2146,878],{"class":865},[844,2148,898],{"class":861},[844,2150,2151],{"class":846,"line":915},[844,2152,2153],{"class":850},"  \u002F\u002F Auto-reply rate limiting\n",[844,2155,2156,2159,2161,2163,2165],{"class":846,"line":933},[844,2157,2158],{"class":861},"  maxDailyAutoReplies: v.",[844,2160,890],{"class":865},[844,2162,893],{"class":861},[844,2164,991],{"class":865},[844,2166,898],{"class":861},[844,2168,2169,2172,2174,2176,2178],{"class":846,"line":948},[844,2170,2171],{"class":861},"  dailyAutoReplyCount: v.",[844,2173,890],{"class":865},[844,2175,893],{"class":861},[844,2177,991],{"class":865},[844,2179,898],{"class":861},[844,2181,2182,2185,2187,2189,2191],{"class":846,"line":962},[844,2183,2184],{"class":861},"  dailyAutoReplyResetAt: v.",[844,2186,890],{"class":865},[844,2188,893],{"class":861},[844,2190,991],{"class":865},[844,2192,898],{"class":861},[844,2194,2195,2197,2199],{"class":846,"line":985},[844,2196,988],{"class":861},[844,2198,991],{"class":865},[844,2200,881],{"class":861},[844,2202,2203,2205,2207],{"class":846,"line":996},[844,2204,999],{"class":861},[844,2206,991],{"class":865},[844,2208,881],{"class":861},[844,2210,2211],{"class":846,"line":1006},[844,2212,1009],{"class":861},[15,2214,2215,2216,2219,2220,2223,2224,2227,2228,2232],{},"Die einzige eingebaute Kostenbremse ist ",[28,2217,2218],{},"maxDailyAutoReplies"," — eine Obergrenze für automatische Antworten, nachgehalten über ",[28,2221,2222],{},"dailyAutoReplyCount"," und zurückgesetzt über ",[28,2225,2226],{},"dailyAutoReplyResetAt",". Sie begrenzt automatische Sendungen, nicht rohe LLM-Aufrufe. Siehe ",[19,2229,2231],{"href":2230},"\u002Fguide\u002Fai-agent","KI-Agent & Autonomie"," für die nutzerseitigen Steuerelemente.",[70,2234,2236],{"id":2235},"circuit-breaker","Circuit Breaker",[15,2238,2239,2240,2243,2244,193,2247,1690],{},"Die Tabelle ",[28,2241,2242],{},"agentCircuitBreakers"," definiert drei Breaker-Typen, jeder mit einem Standardschwellwert aus ",[28,2245,2246],{},"getDefaultThreshold",[28,2248,42],{},[85,2250,2251,2267],{},[88,2252,2253],{},[91,2254,2255,2261,2264],{},[94,2256,2257,2258,1930],{},"Breaker (",[28,2259,2260],{},"breakerType",[94,2262,2263],{},"Standardschwelle",[94,2265,2266],{},"Status",[102,2268,2269,2288,2305],{},[91,2270,2271,2276,2282],{},[107,2272,2273],{},[28,2274,2275],{},"llm_failure",[107,2277,2278,2281],{},[28,2279,2280],{},"0.20"," (20 % Fehlerrate)",[107,2283,2284,2287],{},[260,2285,2286],{},"Live"," — bei jedem Rollup ausgewertet",[91,2289,2290,2295,2301],{},[107,2291,2292],{},[28,2293,2294],{},"confidence_degradation",[107,2296,2297,2300],{},[28,2298,2299],{},"0.30"," (Anteil an Klassifikationen mit niedriger Konfidenz)",[107,2302,2303,2287],{},[260,2304,2286],{},[91,2306,2307,2312,2318],{},[107,2308,2309],{},[28,2310,2311],{},"rejection_spike",[107,2313,2314,2317],{},[28,2315,2316],{},"0.40"," (menschliche Ablehnungsrate über 24 h)",[107,2319,2320,2287],{},[260,2321,2286],{},[15,2323,2324,2327,2328,2331,2332,2334,2335,2337,2338,2340,2341,2344,2345,2348,2349,237,2352,2355,2356,2362,2363,2366],{},[28,2325,2326],{},"evaluateCircuitBreakers"," läuft in jedem Fünf-Minuten-Rollup und wertet inzwischen ",[260,2329,2330],{},"alle drei"," Breaker anhand der Signale dieses Zeitfensters aus — die Fehlerrate im Fenster (",[28,2333,2275],{},"), den Anteil jüngster Klassifikationen mit einer Konfidenz unter 0,5 (",[28,2336,2294],{},") und die menschliche Ablehnungsrate über 24 h (",[28,2339,2311],{},"). Jeder folgt derselben Hysterese-Zustandsmaschine: Übersteigt sein Wert die Schwelle des Breakers, löst er auf ",[28,2342,2343],{},"open"," aus; erholt sich der Wert, geht er über aufeinanderfolgende Rollups ",[28,2346,2347],{},"open → half_open → closed",", bestätigt also die Erholung, bevor die automatische Freigabe wieder anläuft. Zustandsübergänge schreiben ",[28,2350,2351],{},"trippedAt",[28,2353,2354],{},"recoveredAt",". Der ",[19,2357,2359,2360],{"href":2358},"#graduated-autonomy","Schritt ",[28,2361,2049],{}," verweigert die automatische Freigabe, solange ",[260,2364,2365],{},"irgendein"," Breaker offen ist.",[53,2368,2370],{"title":2369,"type":615},"Alle drei Breaker werden ausgewertet",[15,2371,2372,284,2374,2376,2377,2379,2380,1890],{},[28,2373,2294],{},[28,2375,2311],{}," existieren nicht länger nur im Schema — beide sind inzwischen neben ",[28,2378,2275],{}," in den Evaluator des Rollups eingebunden. (Davon getrennt reagiert auch der wöchentliche Job zur Anpassung der Autonomieschwellen weiter unten auf eine Ablehnungsrate von 40 % pro Kategorie; das ist jedoch der Autonomie-Cron, der Schwellen nachjustiert, und etwas anderes als das Auslösen des Breakers ",[28,2381,2311],{},[15,2383,2384,2385,2387,2388,2390,2391,2394,2395,2398],{},"Es gibt kein Objekt für ein Rate-Limit auf LLM-Aufrufe in der Agentenkonfiguration. Das einzige Rate-Limiting des ",[28,2386,2076],{},"-Singletons ist die Obergrenze für automatische Antworten (",[28,2389,2218],{},"), behandelt unter ",[19,2392,2070],{"href":2393},"#per-deployment-agent-config","; Tageslimits pro Kategorie liegen auf ",[28,2396,2397],{},"autonomyRules",". Eine Budgetierung von LLM-Aufrufen bzw. Nebenläufigkeit ist nicht implementiert.",[70,2400,2402],{"id":2401},"dashboard-integration","Dashboard-Integration",[15,2404,2405,2406,2410,2411,2413,2414,2417,2418,2420,2421,2423,2424,2427,2428,2430,2431,2433,2434,501],{},"Die Agenten-Gesundheit erscheint auf dem ",[19,2407,2409],{"href":2408},"#adaptive-dashboard","adaptiven Dashboard"," als registrierte Karte ",[28,2412,720],{}," (Kennzahlen der Strecke), gestützt auf ",[28,2415,2416],{},"getDashboardMetrics",", neben der Karte ",[28,2419,1759],{},". Die detaillierteren Aufschlüsselungskarten ",[28,2422,1809],{}," (LLM-Kosten pro Schritt der Strecke, gestützt auf ",[28,2425,2426],{},"getCostByStep",") und ",[28,2429,1819],{}," (Verhältnis automatischer Freigaben vs. Ablehnungsrate über die Zeit, gestützt auf ",[28,2432,1846],{},") sind registrierte Kartentypen mit fertigen Renderern in ",[28,2435,174],{},[65,2437,2439],{"id":2438},"abgestufte-autonomie","Abgestufte Autonomie",[15,2441,2442,2443,2445,2446,2449],{},"Die Vision: Das Deployment steuert pro Kategorie, wie viel Entscheidungsspielraum es an den Agenten delegiert, und das System verdient sich Vertrauen schrittweise. Das Datenmodell und die Entscheidungsfunktionen existieren (",[28,2444,46],{},", abgesichert durch das Feature-Flag ",[28,2447,2448],{},"ai.autonomy",") und steuern inzwischen den aktiven Routing-Schritt.",[53,2451,2453],{"title":2452,"type":615},"In den Routing-Schritt eingebunden",[15,2454,2455,2456,288,2458,2461,2462,2465,2466,2469,2470,2472,2473,2476,2477,2480,2481,2484,2485,2487],{},"Der Schritt ",[28,2457,2049],{},[28,2459,2460],{},"apps\u002Fapi\u002Fconvex\u002Fagent\u002Fsteps\u002Froute\u002Findex.ts",") entscheidet nun in drei Stufen, sicherste zuerst: ",[260,2463,2464],{},"(1)"," jeder offene Circuit Breaker → menschliche Prüfung (eine beeinträchtigte Strecke sendet nie automatisch); ",[260,2467,2468],{},"(2)"," ist das Flag ",[28,2471,2448],{}," aktiv, wendet ",[28,2474,2475],{},"internal.autonomy.checkPermissionInternal"," die Regel der jeweiligen Kategorie an (Schwelle + Tageslimit + Prüfung auf offene Breaker) — eine Kategorie ohne Regel wird nie automatisch freigegeben, und eine automatische Freigabe belastet das Tageslimit der Kategorie über ",[28,2478,2479],{},"incrementDailyCount","; ",[260,2482,2483],{},"(3)"," andernfalls der bisherige globale Schalter für automatische Antworten aus ",[28,2486,2076],{}," + Konfidenzschwelle + Tageslimit. Autonomie pro Kategorie ist damit nicht länger reine Speicherung — sie steuert die automatische Freigabe durchgängig, wenn das Flag aktiv ist.",[70,2489,2491],{"id":2490},"regeln-pro-kategorie","Regeln pro Kategorie",[211,2493,2495],{"className":838,"code":2494,"language":840,"meta":219,"style":219},"\u002F\u002F apps\u002Fapi\u002Fconvex\u002Fschema\u002Finbox.ts\nautonomyRules: defineTable({\n  category: v.string(),               \u002F\u002F \"support\", \"sales\", \"billing\", etc.\n  autoApproveThreshold: v.number(),   \u002F\u002F Confidence threshold (0-1)\n  maxDailyAutoActions: v.number(),    \u002F\u002F Safety cap\n  currentDailyCount: v.optional(v.number()),\n  dailyCountResetAt: v.optional(v.number()),\n  requiresHumanAbove: v.optional(v.number()), \u002F\u002F e.g., dollar amount triggers human review\n  isEnabled: v.boolean(),\n  createdAt: v.number(),\n  updatedAt: v.number(),\n})\n  .index('by_category', ['category'])\n",[28,2496,2497,2502,2512,2525,2538,2551,2564,2577,2593,2602,2610,2618,2622],{"__ignoreMap":219},[844,2498,2499],{"class":846,"line":847},[844,2500,2501],{"class":850},"\u002F\u002F apps\u002Fapi\u002Fconvex\u002Fschema\u002Finbox.ts\n",[844,2503,2504,2506,2508,2510],{"class":846,"line":854},[844,2505,2397],{"class":857},[844,2507,862],{"class":861},[844,2509,866],{"class":865},[844,2511,869],{"class":861},[844,2513,2514,2517,2519,2522],{"class":846,"line":872},[844,2515,2516],{"class":861},"  category: v.",[844,2518,878],{"class":865},[844,2520,2521],{"class":861},"(),               ",[844,2523,2524],{"class":850},"\u002F\u002F \"support\", \"sales\", \"billing\", etc.\n",[844,2526,2527,2530,2532,2535],{"class":846,"line":884},[844,2528,2529],{"class":861},"  autoApproveThreshold: v.",[844,2531,991],{"class":865},[844,2533,2534],{"class":861},"(),   ",[844,2536,2537],{"class":850},"\u002F\u002F Confidence threshold (0-1)\n",[844,2539,2540,2543,2545,2548],{"class":846,"line":901},[844,2541,2542],{"class":861},"  maxDailyAutoActions: v.",[844,2544,991],{"class":865},[844,2546,2547],{"class":861},"(),    ",[844,2549,2550],{"class":850},"\u002F\u002F Safety cap\n",[844,2552,2553,2556,2558,2560,2562],{"class":846,"line":915},[844,2554,2555],{"class":861},"  currentDailyCount: v.",[844,2557,890],{"class":865},[844,2559,893],{"class":861},[844,2561,991],{"class":865},[844,2563,898],{"class":861},[844,2565,2566,2569,2571,2573,2575],{"class":846,"line":933},[844,2567,2568],{"class":861},"  dailyCountResetAt: v.",[844,2570,890],{"class":865},[844,2572,893],{"class":861},[844,2574,991],{"class":865},[844,2576,898],{"class":861},[844,2578,2579,2582,2584,2586,2588,2590],{"class":846,"line":948},[844,2580,2581],{"class":861},"  requiresHumanAbove: v.",[844,2583,890],{"class":865},[844,2585,893],{"class":861},[844,2587,991],{"class":865},[844,2589,927],{"class":861},[844,2591,2592],{"class":850},"\u002F\u002F e.g., dollar amount triggers human review\n",[844,2594,2595,2598,2600],{"class":846,"line":962},[844,2596,2597],{"class":861},"  isEnabled: v.",[844,2599,939],{"class":865},[844,2601,881],{"class":861},[844,2603,2604,2606,2608],{"class":846,"line":985},[844,2605,988],{"class":861},[844,2607,991],{"class":865},[844,2609,881],{"class":861},[844,2611,2612,2614,2616],{"class":846,"line":996},[844,2613,999],{"class":861},[844,2615,991],{"class":865},[844,2617,881],{"class":861},[844,2619,2620],{"class":846,"line":1006},[844,2621,1009],{"class":861},[844,2623,2624,2626,2628,2630,2633,2635,2638],{"class":846,"line":1012},[844,2625,1015],{"class":861},[844,2627,1018],{"class":865},[844,2629,975],{"class":861},[844,2631,2632],{"class":978},"'by_category'",[844,2634,1026],{"class":861},[844,2636,2637],{"class":978},"'category'",[844,2639,1032],{"class":861},[15,2641,2642,2643,2646,2647,2650,2651,2653,2654,2657,2658,2661,2662,2665],{},"Regeln werden pro Kategorie über ",[28,2644,2645],{},"upsertRule"," (nur Owner\u002FAdmin) eingefügt oder aktualisiert und von ",[28,2648,2649],{},"checkPermissionInternal"," zurückgelesen (der Route-Schritt ruft es als ",[28,2652,2475],{}," auf), das ",[28,2655,2656],{},"{ mode, allowed, reason }"," zurückgibt, nachdem es die Schwelle, das Tageslimit der Kategorie (",[28,2659,2660],{},"currentDailyCount"," gegen ",[28,2663,2664],{},"maxDailyAutoActions",", zurückgesetzt in einem rollierenden 24-h-Fenster) und geprüft hat, ob irgendein Circuit Breaker offen ist.",[70,2667,2669],{"id":2668},"beispielkonfiguration","Beispielkonfiguration",[85,2671,2672,2688],{},[88,2673,2674],{},[91,2675,2676,2679,2682,2685],{},[94,2677,2678],{},"Kategorie",[94,2680,2681],{},"Schwelle",[94,2683,2684],{},"Tageslimit",[94,2686,2687],{},"Anmerkungen",[102,2689,2690,2704,2718,2732,2745],{},[91,2691,2692,2695,2698,2701],{},[107,2693,2694],{},"Einfache Empfangsbestätigungen",[107,2696,2697],{},"0,95",[107,2699,2700],{},"50",[107,2702,2703],{},"„Danke, wir schauen uns das an“",[91,2705,2706,2709,2712,2715],{},[107,2707,2708],{},"Support-FAQ",[107,2710,2711],{},"0,90",[107,2713,2714],{},"30",[107,2716,2717],{},"Standardantworten mit Datenabfrage",[91,2719,2720,2723,2726,2729],{},[107,2721,2722],{},"Abrechnungsfragen",[107,2724,2725],{},"0,85",[107,2727,2728],{},"20",[107,2730,2731],{},"Kontospezifische Antworten",[91,2733,2734,2737,2740,2742],{},[107,2735,2736],{},"Vertriebsanfragen",[107,2738,2739],{},"—",[107,2741,2739],{},[107,2743,2744],{},"Keine Regel = immer menschliche Prüfung",[91,2746,2747,2750,2752,2754],{},[107,2748,2749],{},"Beschwerden",[107,2751,2739],{},[107,2753,2739],{},[107,2755,2744],{},[15,2757,2758,2759,2762],{},"Eine Kategorie ohne Regel (oder mit ",[28,2760,2761],{},"isEnabled: false",") wird nie automatisch freigegeben.",[70,2764,2766],{"id":2765},"feedback-schleife","Feedback-Schleife",[15,2768,2769,2770,2773,2774,2777,2778,2781],{},"Menschliches Feedback wird in ",[28,2771,2772],{},"autonomyFeedback"," erfasst (",[28,2775,2776],{},"recordFeedback",": freigegeben\u002Fabgelehnt\u002Fbearbeitet plus die Konfidenz des Agenten). Ein wöchentlicher Cron (",[28,2779,2780],{},"adjustThresholds",") kalibriert daraufhin jede aktivierte Regel neu:",[517,2783,2784,2791],{},[520,2785,2786,2787,2790],{},"Übersteigt die Ablehnungsrate einer Kategorie über die letzte Woche ",[260,2788,2789],{},"40 %"," (bei mindestens 5 Datenpunkten), zieht er die Schwelle um +0,10 an (maximal 0,99).",[520,2792,2793,2794,2797],{},"Liegt die Ablehnungsrate bei mindestens 20 Datenpunkten unter ",[260,2795,2796],{},"10 %",", lockert er die Schwelle um -0,05 (minimal 0,50).",[53,2799,2801],{"title":2800,"type":615},"Die Schleife hat aktive Eingaben",[15,2802,2803,2804,862,2806,439,2809,284,2812,193,2815,2818,2819,2821,2822,2825,2826,2828,2829,2831],{},"Die Verifizierungs-Warteschlange emittiert inzwischen bei jeder Entscheidung ",[28,2805,2776],{},[28,2807,2808],{},"approveDraft",[28,2810,2811],{},"rejectDraft",[28,2813,2814],{},"editDraft",[28,2816,2817],{},"apps\u002Fapi\u002Fconvex\u002Finbox\u002Fmutations.ts"," hängen jeweils eine Zeile an ",[28,2820,2772],{}," an (eine Nachricht ohne Klassifikation wird unter ",[28,2823,2824],{},"other"," erfasst, damit das Signal nicht verloren geht). Der wöchentliche Cron ",[28,2827,2780],{}," verarbeitet diese Zeilen, um die Schwellen pro Kategorie neu zu kalibrieren, und der Rollup zur Agenten-Gesundheit nutzt dasselbe Feedback für den Breaker ",[28,2830,2311],{},". Eine „Konfidenzkalibrierung“ pro Nachricht über dieses Nachjustieren der Schwellen auf Kategorieebene hinaus gibt es weiterhin nicht.",[65,2833,2835],{"id":2834},"coding-agenten","Coding-Agenten",[15,2837,2838,2839,2841],{},"Der experimentellste Teil: ein Agent, der eine Aufgabenbeschreibung entgegennimmt und einen Pull Request erzeugt. Er läuft als Docker-Sidecar (",[28,2840,50],{},") — nicht innerhalb von Convex —, weil er ein Dateisystem und git braucht.",[70,2843,2845],{"id":2844},"aufgabenmodell","Aufgabenmodell",[15,2847,2848,2849,1690],{},"Aufgaben werden in einer eigenen Tabelle nachgehalten, nicht in ",[28,2850,2851],{},"agentActions",[211,2853,2855],{"className":838,"code":2854,"language":840,"meta":219,"style":219},"\u002F\u002F apps\u002Fapi\u002Fconvex\u002Fschema\u002FcodeWork.ts\ncodeWorkTasks: defineTable({\n  description: v.string(),\n  inboundMessageId: v.optional(v.id('inboundMessages')), \u002F\u002F source context\n  branch: v.optional(v.string()),\n  prUrl: v.optional(v.string()),\n  status: v.union(\n    v.literal('queued'),\n    v.literal('running'),\n    v.literal('testing'),\n    v.literal('review'),\n    v.literal('merged'),\n    v.literal('failed'),\n  ),\n  testResults: v.optional(v.string()),\n  errorMessage: v.optional(v.string()),\n  llmCost: v.optional(v.number()),\n  createdAt: v.number(),\n  updatedAt: v.number(),\n})\n  .index('by_status', ['status'])\n  .index('by_created_at', ['createdAt'])\n",[28,2856,2857,2862,2873,2881,2903,2916,2929,2939,2954,2967,2980,2993,3006,3019,3024,3037,3050,3063,3071,3079,3083,3101],{"__ignoreMap":219},[844,2858,2859],{"class":846,"line":847},[844,2860,2861],{"class":850},"\u002F\u002F apps\u002Fapi\u002Fconvex\u002Fschema\u002FcodeWork.ts\n",[844,2863,2864,2867,2869,2871],{"class":846,"line":854},[844,2865,2866],{"class":857},"codeWorkTasks",[844,2868,862],{"class":861},[844,2870,866],{"class":865},[844,2872,869],{"class":861},[844,2874,2875,2877,2879],{"class":846,"line":872},[844,2876,887],{"class":861},[844,2878,878],{"class":865},[844,2880,881],{"class":861},[844,2882,2883,2886,2888,2890,2892,2894,2897,2900],{"class":846,"line":884},[844,2884,2885],{"class":861},"  inboundMessageId: v.",[844,2887,890],{"class":865},[844,2889,893],{"class":861},[844,2891,972],{"class":865},[844,2893,975],{"class":861},[844,2895,2896],{"class":978},"'inboundMessages'",[844,2898,2899],{"class":861},")), ",[844,2901,2902],{"class":850},"\u002F\u002F source context\n",[844,2904,2905,2908,2910,2912,2914],{"class":846,"line":901},[844,2906,2907],{"class":861},"  branch: v.",[844,2909,890],{"class":865},[844,2911,893],{"class":861},[844,2913,878],{"class":865},[844,2915,898],{"class":861},[844,2917,2918,2921,2923,2925,2927],{"class":846,"line":915},[844,2919,2920],{"class":861},"  prUrl: v.",[844,2922,890],{"class":865},[844,2924,893],{"class":861},[844,2926,878],{"class":865},[844,2928,898],{"class":861},[844,2930,2931,2934,2936],{"class":846,"line":933},[844,2932,2933],{"class":861},"  status: v.",[844,2935,1455],{"class":865},[844,2937,2938],{"class":861},"(\n",[844,2940,2941,2944,2946,2948,2951],{"class":846,"line":948},[844,2942,2943],{"class":861},"    v.",[844,2945,1460],{"class":865},[844,2947,975],{"class":861},[844,2949,2950],{"class":978},"'queued'",[844,2952,2953],{"class":861},"),\n",[844,2955,2956,2958,2960,2962,2965],{"class":846,"line":962},[844,2957,2943],{"class":861},[844,2959,1460],{"class":865},[844,2961,975],{"class":861},[844,2963,2964],{"class":978},"'running'",[844,2966,2953],{"class":861},[844,2968,2969,2971,2973,2975,2978],{"class":846,"line":985},[844,2970,2943],{"class":861},[844,2972,1460],{"class":865},[844,2974,975],{"class":861},[844,2976,2977],{"class":978},"'testing'",[844,2979,2953],{"class":861},[844,2981,2982,2984,2986,2988,2991],{"class":846,"line":996},[844,2983,2943],{"class":861},[844,2985,1460],{"class":865},[844,2987,975],{"class":861},[844,2989,2990],{"class":978},"'review'",[844,2992,2953],{"class":861},[844,2994,2995,2997,2999,3001,3004],{"class":846,"line":1006},[844,2996,2943],{"class":861},[844,2998,1460],{"class":865},[844,3000,975],{"class":861},[844,3002,3003],{"class":978},"'merged'",[844,3005,2953],{"class":861},[844,3007,3008,3010,3012,3014,3017],{"class":846,"line":1012},[844,3009,2943],{"class":861},[844,3011,1460],{"class":865},[844,3013,975],{"class":861},[844,3015,3016],{"class":978},"'failed'",[844,3018,2953],{"class":861},[844,3020,3021],{"class":846,"line":1035},[844,3022,3023],{"class":861},"  ),\n",[844,3025,3026,3029,3031,3033,3035],{"class":846,"line":1436},[844,3027,3028],{"class":861},"  testResults: v.",[844,3030,890],{"class":865},[844,3032,893],{"class":861},[844,3034,878],{"class":865},[844,3036,898],{"class":861},[844,3038,3039,3042,3044,3046,3048],{"class":846,"line":1449},[844,3040,3041],{"class":861},"  errorMessage: v.",[844,3043,890],{"class":865},[844,3045,893],{"class":861},[844,3047,878],{"class":865},[844,3049,898],{"class":861},[844,3051,3052,3055,3057,3059,3061],{"class":846,"line":1489},[844,3053,3054],{"class":861},"  llmCost: v.",[844,3056,890],{"class":865},[844,3058,893],{"class":861},[844,3060,991],{"class":865},[844,3062,898],{"class":861},[844,3064,3065,3067,3069],{"class":846,"line":1495},[844,3066,988],{"class":861},[844,3068,991],{"class":865},[844,3070,881],{"class":861},[844,3072,3073,3075,3077],{"class":846,"line":1509},[844,3074,999],{"class":861},[844,3076,991],{"class":865},[844,3078,881],{"class":861},[844,3080,3081],{"class":846,"line":1515},[844,3082,1009],{"class":861},[844,3084,3085,3087,3089,3091,3094,3096,3099],{"class":846,"line":1521},[844,3086,1015],{"class":861},[844,3088,1018],{"class":865},[844,3090,975],{"class":861},[844,3092,3093],{"class":978},"'by_status'",[844,3095,1026],{"class":861},[844,3097,3098],{"class":978},"'status'",[844,3100,1032],{"class":861},[844,3102,3103,3105,3107,3109,3111,3113,3115],{"class":846,"line":1539},[844,3104,1015],{"class":861},[844,3106,1018],{"class":865},[844,3108,975],{"class":861},[844,3110,1044],{"class":978},[844,3112,1026],{"class":861},[844,3114,1049],{"class":978},[844,3116,1032],{"class":861},[70,3118,3120],{"id":3119},"worker-ablauf","Worker-Ablauf",[15,3122,3123,3124,3127,3128,3131],{},"Der Worker fragt Convex nach der nächsten Aufgabe im Status ",[28,3125,3126],{},"queued"," und führt sie durchgängig aus (",[28,3129,3130],{},"apps\u002Fcode-worker\u002Fsrc\u002FtaskRunner.ts","):",[211,3133,3136],{"className":3134,"code":3135,"language":216},[214],"getNextQueued()  →  claim()        status: queued → running\n  setupWorkspace()                 git clone --depth 1, checkout code-worker\u002F{taskId}\n  runCodingAgent()                 spawn the OpenCode CLI (OPENCODE_BIN) on the workspace\n  (no diff?)        → markFailed    status: failed\n  git commit\n  markTesting()                    status: running → testing\n  runTests()                       npx vitest run\n  git push origin {branch}\n  createPullRequest() (if GITHUB_* set, via @octokit\u002Frest)\n  completeWithPR()                 status: testing → review, stores prUrl + testResults\n",[28,3137,3135],{"__ignoreMap":219},[15,3139,3140,3141,3144,3145,3148,3149,3152],{},"Ein Fehlschlag an irgendeiner Stelle ruft ",[28,3142,3143],{},"markFailed"," mit dem Fehler auf. Das Ergebnis landet in ",[28,3146,3147],{},"review"," mit einem PR-Link, den ein Mensch prüfen und mergen kann — und wird dieser PR auf GitHub gemergt, setzt ein Webhook die Aufgabe automatisch auf ",[28,3150,3151],{},"merged"," (siehe unten).",[53,3154,3156],{"title":3155,"type":615},"Auto-Trigger und Merge-Webhook sind angebunden",[15,3157,3158,3159,3162,3163,661,3166,3169,3170,3173,3174,3177,3178,3182,3183,3185,3186,3189,3190,3193,3194,3197,3198,3201,3202,3205,3206,3209,3210,2661,3213,3216,3217,3219],{},"Eingehende Feature-Wünsche werden inzwischen automatisch zu Code-Aufgaben: Klassifiziert eine Nachricht als ",[28,3160,3161],{},"feature_request",", plant der Posteingangs-Lebenszyklus (",[28,3164,3165],{},"apps\u002Fapi\u002Fconvex\u002Finbox\u002FprocessingLifecycle.ts",[28,3167,3168],{},"internal.codeWorkTasks.createFromInbound"," ein, abgesichert durch das Flag ",[28,3171,3172],{},"inbox.codeTasks"," und idempotent über ",[28,3175,3176],{},"inboundMessageId",". (Das manuelle Anlegen über ",[19,3179,3181],{"href":3180},"\u002Fguide\u002Fcode-tasks","Code-Aufgaben"," funktioniert weiterhin.) Auch der Status ",[28,3184,3151],{}," ist angebunden: Ein GitHub-Webhook (",[28,3187,3188],{},"apps\u002Fapi\u002Fconvex\u002Fwebhooks\u002FgithubHttp.ts",", Route ",[28,3191,3192],{},"POST \u002Fwebhooks\u002Fgithub",", HMAC-verifiziert gegen ",[28,3195,3196],{},"GITHUB_WEBHOOK_SECRET",") verarbeitet ",[28,3199,3200],{},"pull_request","-Events vom Typ ",[28,3203,3204],{},"closed","+merged und gleicht die ",[28,3207,3208],{},"html_url"," des PR über ",[28,3211,3212],{},"markMergedByPrUrl",[28,3214,3215],{},"codeWorkTasks.prUrl"," ab — ein Mensch mergt also weiterhin in GitHub, aber die Aufgabe wechselt selbst den Status, statt bei ",[28,3218,3147],{}," hängen zu bleiben.",[53,3221,3223],{"title":3222,"type":820},"Zum Ausführen des Agenten braucht es weiterhin den Sidecar",[15,3224,3225,3226,3229,3230,3233,3234,237,3237,3240],{},"Auto-Trigger und Merge-Webhook sind angebunden, aber eine Aufgabe tatsächlich ",[639,3227,3228],{},"auszuführen"," — klonen, den Coding-Agenten aufrufen, den PR eröffnen — erfordert weiterhin den optionalen Docker-Sidecar ",[28,3231,3232],{},"code-worker"," (unten), mit OpenCode im Image und konfigurierten ",[28,3235,3236],{},"GITHUB_*",[28,3238,3239],{},"GIT_*",". Ohne den Sidecar reihen sich Aufgaben ein, aber nichts nimmt sie auf.",[70,3242,3244],{"id":3243},"compose-service","Compose-Service",[15,3246,3247,3248,3250,3251,3254,3255,3258],{},"Der Worker ist ein optionaler Sidecar, abgesichert durch das Feature-Flag ",[28,3249,3172],{}," (Profil ",[28,3252,3253],{},"inbox-codetasks",", auch unter ",[28,3256,3257],{},"dev"," aktiviert):",[211,3260,3264],{"className":3261,"code":3262,"language":3263,"meta":219,"style":219},"language-yaml shiki shiki-themes github-light github-dark-dimmed","# infra\u002Ftemplates\u002Fdocker-compose.vps.yml\ncode-worker:\n  image: ghcr.io\u002Fwolvesdotink\u002Fcode-worker:${OWLAT_VERSION}\n  volumes:\n    - code-workspace:\u002Fworkspace\n  environment:\n    CONVEX_URL: http:\u002F\u002Fconvex:3210\n    LLM_PROVIDER: ${LLM_PROVIDER:-openai}\n    LLM_BASE_URL: ${LLM_BASE_URL:-}\n    LLM_API_KEY: ${LLM_API_KEY:-}\n    LLM_MODEL: ${LLM_MODEL:-gpt-4o}\n    GITHUB_TOKEN: ${GITHUB_TOKEN:-}\n    GITHUB_OWNER: ${GITHUB_OWNER:-}\n    GITHUB_REPO: ${GITHUB_REPO:-}\n    GIT_REPO_URL: ${GIT_REPO_URL:-}\n    GIT_BASE_BRANCH: ${GIT_BASE_BRANCH:-main}\n  profiles:\n    - inbox-codetasks\n    - dev\n","yaml",[28,3265,3266,3271,3278,3288,3295,3303,3310,3320,3330,3340,3350,3360,3370,3380,3390,3400,3410,3417,3424],{"__ignoreMap":219},[844,3267,3268],{"class":846,"line":847},[844,3269,3270],{"class":850},"# infra\u002Ftemplates\u002Fdocker-compose.vps.yml\n",[844,3272,3273,3275],{"class":846,"line":854},[844,3274,3232],{"class":1092},[844,3276,3277],{"class":861},":\n",[844,3279,3280,3283,3285],{"class":846,"line":872},[844,3281,3282],{"class":1092},"  image",[844,3284,862],{"class":861},[844,3286,3287],{"class":978},"ghcr.io\u002Fwolvesdotink\u002Fcode-worker:${OWLAT_VERSION}\n",[844,3289,3290,3293],{"class":846,"line":884},[844,3291,3292],{"class":1092},"  volumes",[844,3294,3277],{"class":861},[844,3296,3297,3300],{"class":846,"line":901},[844,3298,3299],{"class":861},"    - ",[844,3301,3302],{"class":978},"code-workspace:\u002Fworkspace\n",[844,3304,3305,3308],{"class":846,"line":915},[844,3306,3307],{"class":1092},"  environment",[844,3309,3277],{"class":861},[844,3311,3312,3315,3317],{"class":846,"line":933},[844,3313,3314],{"class":1092},"    CONVEX_URL",[844,3316,862],{"class":861},[844,3318,3319],{"class":978},"http:\u002F\u002Fconvex:3210\n",[844,3321,3322,3325,3327],{"class":846,"line":948},[844,3323,3324],{"class":1092},"    LLM_PROVIDER",[844,3326,862],{"class":861},[844,3328,3329],{"class":978},"${LLM_PROVIDER:-openai}\n",[844,3331,3332,3335,3337],{"class":846,"line":962},[844,3333,3334],{"class":1092},"    LLM_BASE_URL",[844,3336,862],{"class":861},[844,3338,3339],{"class":978},"${LLM_BASE_URL:-}\n",[844,3341,3342,3345,3347],{"class":846,"line":985},[844,3343,3344],{"class":1092},"    LLM_API_KEY",[844,3346,862],{"class":861},[844,3348,3349],{"class":978},"${LLM_API_KEY:-}\n",[844,3351,3352,3355,3357],{"class":846,"line":996},[844,3353,3354],{"class":1092},"    LLM_MODEL",[844,3356,862],{"class":861},[844,3358,3359],{"class":978},"${LLM_MODEL:-gpt-4o}\n",[844,3361,3362,3365,3367],{"class":846,"line":1006},[844,3363,3364],{"class":1092},"    GITHUB_TOKEN",[844,3366,862],{"class":861},[844,3368,3369],{"class":978},"${GITHUB_TOKEN:-}\n",[844,3371,3372,3375,3377],{"class":846,"line":1012},[844,3373,3374],{"class":1092},"    GITHUB_OWNER",[844,3376,862],{"class":861},[844,3378,3379],{"class":978},"${GITHUB_OWNER:-}\n",[844,3381,3382,3385,3387],{"class":846,"line":1035},[844,3383,3384],{"class":1092},"    GITHUB_REPO",[844,3386,862],{"class":861},[844,3388,3389],{"class":978},"${GITHUB_REPO:-}\n",[844,3391,3392,3395,3397],{"class":846,"line":1436},[844,3393,3394],{"class":1092},"    GIT_REPO_URL",[844,3396,862],{"class":861},[844,3398,3399],{"class":978},"${GIT_REPO_URL:-}\n",[844,3401,3402,3405,3407],{"class":846,"line":1449},[844,3403,3404],{"class":1092},"    GIT_BASE_BRANCH",[844,3406,862],{"class":861},[844,3408,3409],{"class":978},"${GIT_BASE_BRANCH:-main}\n",[844,3411,3412,3415],{"class":846,"line":1489},[844,3413,3414],{"class":1092},"  profiles",[844,3416,3277],{"class":861},[844,3418,3419,3421],{"class":846,"line":1495},[844,3420,3299],{"class":861},[844,3422,3423],{"class":978},"inbox-codetasks\n",[844,3425,3426,3428],{"class":846,"line":1509},[844,3427,3299],{"class":861},[844,3429,3430],{"class":978},"dev\n",[53,3432,3434],{"title":3433,"type":820},"Experimentell",[15,3435,3436],{},"Coding-Agenten sind der am weitesten in der Zukunft liegende Teil der Vision. Die Klempnerei — Aufgabentabelle, Worker, PR-Erstellung — ist vorhanden, aber standardmäßig abgeschaltet und wird sich mit den Fähigkeiten der KI-Codegenerierung weiterentwickeln.",[3438,3439,3440],"style",{},"html pre.shiki code .sDN9O, html code.shiki .sDN9O{--shiki-default:#6A737D;--shiki-dark:#768390}html pre.shiki code .sOLd2, html code.shiki .sOLd2{--shiki-default:#6F42C1;--shiki-dark:#F69D50}html pre.shiki code .sYgZi, html code.shiki .sYgZi{--shiki-default:#24292E;--shiki-dark:#ADBAC7}html pre.shiki code .sPO5f, html code.shiki .sPO5f{--shiki-default:#6F42C1;--shiki-dark:#DCBDFB}html pre.shiki code .s-HuK, html code.shiki .s-HuK{--shiki-default:#032F62;--shiki-dark:#96D0FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sIAta, html code.shiki .sIAta{--shiki-default:#22863A;--shiki-dark:#8DDB8C}html pre.shiki code .sMOND, html code.shiki .sMOND{--shiki-default:#6F42C1;--shiki-dark:#6CB6FF}html pre.shiki code .sNWHW, html code.shiki .sNWHW{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FF938A;--shiki-dark-font-style:italic}",{"title":219,"searchDepth":854,"depth":854,"links":3442},[3443,3455,3460,3467,3473,3478],{"id":67,"depth":854,"text":68,"children":3444},[3445,3446,3447,3448,3449,3450,3451,3452,3453,3454],{"id":72,"depth":872,"text":73},{"id":208,"depth":872,"text":209},{"id":255,"depth":872,"text":256},{"id":428,"depth":872,"text":429},{"id":452,"depth":872,"text":453},{"id":467,"depth":872,"text":468},{"id":483,"depth":872,"text":484},{"id":504,"depth":872,"text":505},{"id":511,"depth":872,"text":512},{"id":593,"depth":872,"text":594},{"id":687,"depth":854,"text":688,"children":3456},[3457,3458,3459],{"id":764,"depth":872,"text":765},{"id":834,"depth":872,"text":835},{"id":1073,"depth":872,"text":1074},{"id":1159,"depth":854,"text":1160,"children":3461},[3462,3463,3464,3465,3466],{"id":1170,"depth":872,"text":1171},{"id":1272,"depth":872,"text":1273},{"id":1680,"depth":872,"text":1681},{"id":1856,"depth":872,"text":1857},{"id":1873,"depth":872,"text":1874},{"id":1893,"depth":854,"text":1894,"children":3468},[3469,3470,3471,3472],{"id":1911,"depth":872,"text":1912},{"id":2069,"depth":872,"text":2070},{"id":2235,"depth":872,"text":2236},{"id":2401,"depth":872,"text":2402},{"id":2438,"depth":854,"text":2439,"children":3474},[3475,3476,3477],{"id":2490,"depth":872,"text":2491},{"id":2668,"depth":872,"text":2669},{"id":2765,"depth":872,"text":2766},{"id":2834,"depth":854,"text":2835,"children":3479},[3480,3481,3482],{"id":2844,"depth":872,"text":2845},{"id":3119,"depth":872,"text":3120},{"id":3243,"depth":872,"text":3244},"Architektur der Owlat-Desktop-Hülle, des Visualisierungsagenten, des adaptiven Dashboards, der Agenten-Gesundheit, der abgestuften Autonomie und der Coding-Agenten.","md",{},true,"\u002Fvision\u002Fdesktop-app",{"title":6,"description":3483},"5.vision\u002F6.desktop-app","WVzVD4w4HP00tzD5uXQD4G3oeHq1BIXjK-O_mcdHigw",[3492,3496],{"title":3493,"path":3494,"stem":3495,"children":-1},"Semantisches Dateisystem","\u002Fvision\u002Ffile-system","5.vision\u002F5.file-system",{"title":22,"path":3497,"stem":3498,"children":-1},"\u002Fvision\u002Froadmap","5.vision\u002F7.roadmap",1786915111489]