Rueckmeldung nach Vertrauensstufe: drei Wege nach oben (#715)

- IAgentTool.ReadsForeignContent: Werkzeuge mit Aussenkontakt erklaeren sich selbst
  (WebFetch, WebMonitor, DirectAPI, Mail, RocketChat, Telegram, TelegramClient,
  SocialMediaManager, FTP, Database); AgentConfig.TreatAsForeignReader kann nur verschaerfen
- ReportingLine: Stufe aus den Werkzeugen, "wer steht darueber", Pruefung des Wegs nach oben
  (nie Aenderungen an Aufgaben darueber, nur eine Ebene hoch, Fremdinhalt-Stufe gar kein
  Freitext) und Rahmung als untrusted_content
- Engine: Nachricht und Spawn nach oben geprueft, Text der Fremdinhalt-Stufe kommt gerahmt an
- Taskboard: task_create/update/comment, reopen und die Dubletten-Notiz folgen dem Berichtsweg
- Dispatcher: Aufgaben von Agenten der Fremdinhalt-Stufe gehen gerahmt in den Lauf
- TaskReports: Erledigt-Signal und Systemmeldung (in Pruefung, blockiert, abgebrochen) an den
  Auftraggeber, je Zustand einmal, gesammelt in einer offenen Aufgabe je Empfaenger
- OrgBriefing nennt den Berichtsweg; WebUI zeigt Stufe und Schalter am Agenten

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-09-25 09:16:29 +02:00
co-authored by Claude Opus 5.5
parent e2ffe4b380
commit 3857a7cab2
33 changed files with 1234 additions and 30 deletions
@@ -217,6 +217,13 @@ async function rendereDetails(agentId) {
const links = erstelleElement("div", { klasse: "werkzeug-info" });
const toolTitel = erstelleElement("strong", { text: tool.name });
// #715: A tool that brings in outside text changes the agent's reporting line.
if (tool.readsForeignContent) {
toolTitel.append(
" ",
erstelleElement("span", { klasse: "werkzeug-fremd", text: t("agents.readsForeign") })
);
}
const toolDesc = erstelleElement("div", {
klasse: "werkzeug-beschreibung gedaempft",
text: tool.description || ""
@@ -248,6 +255,7 @@ async function rendereDetails(agentId) {
{ method: "PUT" }
);
tool.enabled = aktiv;
aktualisiereBerichtsweg();
zeigeMeldung(
t("agents.toolToggled", {
tool: tool.name,
@@ -272,7 +280,56 @@ async function rendereDetails(agentId) {
const werkzeugeKarte = erstelleKarte(t("agents.availableTools"), [werkzeugeListe]);
detailContainer.append(basisKarte, werkzeugeKarte);
// #715: The reporting line — the tier follows from the tools; the setting can only tighten it.
const berichtswegText = erstelleElement("p", { klasse: "gedaempft" });
const aktualisiereBerichtsweg = () => {
const quellen = (agent.tools || [])
.filter((w) => w.enabled && w.readsForeignContent)
.map((w) => w.name);
if (agent.treatAsForeignReader) quellen.push(t("agents.settingSource"));
berichtswegText.textContent = quellen.length > 0
? t("agents.tierForeign", { sources: quellen.join(", ") })
: t("agents.tierStandard");
};
aktualisiereBerichtsweg();
const verschaerfenLabel = erstelleElement("label", { klasse: "schalter" });
const verschaerfenInput = erstelleElement("input", {
type: "checkbox",
checked: Boolean(agent.treatAsForeignReader),
onchange: async (e) => {
const wert = e.target.checked;
try {
await api(
`/agents/${encodeURIComponent(agent.agentId)}/foreign-reader?value=${wert}`,
{ method: "PUT" }
);
agent.treatAsForeignReader = wert;
aktualisiereBerichtsweg();
zeigeMeldung(t("agents.foreignReaderSaved", { name: agent.displayName }), "info");
} catch (err) {
e.target.checked = !wert;
zeigeMeldung(t("agents.saveFailed", { error: err.message }), "gefahr");
}
}
});
verschaerfenLabel.append(verschaerfenInput, erstelleElement("span", { klasse: "schalter-regler" }));
const verschaerfenZeile = erstelleElement(
"div",
{ klasse: "werkzeug-zeile" },
erstelleElement(
"div",
{ klasse: "werkzeug-info" },
erstelleElement("strong", { text: t("agents.treatAsForeignReader") }),
erstelleElement("div", { klasse: "werkzeug-beschreibung gedaempft", text: t("agents.treatAsForeignReaderHint") })
),
erstelleElement("div", { klasse: "werkzeug-aktionen" }, verschaerfenLabel)
);
const berichtswegKarte = erstelleKarte(t("agents.reportingLine"), [berichtswegText, verschaerfenZeile]);
detailContainer.append(basisKarte, werkzeugeKarte, berichtswegKarte);
}
function oeffneNeuerAgentDialog() {