feat: standardize long-running tool workflows
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
title: MikeAI Auto Tool Selector
|
||||
author: MikeAI
|
||||
version: 4.3.0
|
||||
version: 4.5.0
|
||||
description: Keeps broad web access available and adds relevant portable MCP domains without acting as a gate.
|
||||
"""
|
||||
|
||||
@@ -109,6 +109,48 @@ class Filter:
|
||||
)
|
||||
return search_intent and marketplace_context
|
||||
|
||||
def _is_explicitly_readonly(self, raw_text: str) -> bool:
|
||||
"""Recognise a global read-only request, not a narrow safety exception."""
|
||||
text = self._normalise(raw_text)
|
||||
return self._matches(
|
||||
text,
|
||||
(
|
||||
r"\b(?:nur|ausschlie(?:ß|ss)lich|lediglich)\s+(?:lesen|pr[uü]fen|anzeigen|auflisten)\b",
|
||||
r"\bread[- ]only\b",
|
||||
r"\bohne\s+(?:downloads?|umbenennungen?|schreibzugriff|[aä]nderungen?)\b",
|
||||
r"\bohne\s+downloads?\b.{0,80}\b(?:[aä]nderungen?|umbenennungen?)\b",
|
||||
r"\b(?:nichts|keinerlei)\s+(?:ver[aä]ndern|[aä]ndern|schreiben)\b",
|
||||
r"\b(?:[aä]ndere|ver[aä]ndere)\s+nichts\b",
|
||||
),
|
||||
)
|
||||
|
||||
def _needs_general_operator(self, raw_text: str) -> bool:
|
||||
"""Detect broad host work by capability, not product or website name."""
|
||||
text = self._normalise(raw_text)
|
||||
if self._is_explicitly_readonly(raw_text):
|
||||
return False
|
||||
action_intent = self._matches(
|
||||
text,
|
||||
(
|
||||
r"\b(?:ausf[uü]hr|starte?|stoppe?|restart|installier|deploy|bau|erstell|"
|
||||
r"schreib|speicher|leg|kopier|verschieb|umbenenn|l[oö]sch|entfern|"
|
||||
r"download|herunterlad|konvertier|transkodier|komprimier|extrahier|"
|
||||
r"bearbeit|[aä]nder|modifizier|aktualisier|reparier|fix)\w*\b",
|
||||
r"\b(?:f[uü]hre|lass)\b.{0,80}\b(?:befehl|kommando|skript|command)\b",
|
||||
),
|
||||
)
|
||||
operational_context = self._matches(
|
||||
text,
|
||||
(
|
||||
r"\b(?:host|server|unraid|unreid|unrate|anrate|nas|linux|debian|docker|"
|
||||
r"container|terminal|shell|kommando|befehl|datei(?:system)?|ordner|"
|
||||
r"verzeichnis|pfad|share|freigabe|repository|repo|mcp|api)\b",
|
||||
r"\b(?:ffmpeg|ffprobe|yt-dlp|youtube-dl|curl|wget|git|docker\s+compose)\b",
|
||||
r"(?:^|\s)/(?:tmp|data|mnt|opt|srv|var|etc|home)(?:/|\b)",
|
||||
),
|
||||
)
|
||||
return action_intent and operational_context
|
||||
|
||||
@staticmethod
|
||||
def _add_system_rule(
|
||||
body: dict,
|
||||
@@ -129,7 +171,25 @@ class Filter:
|
||||
"the Athena Operator terminal when it can answer the unresolved question. Never "
|
||||
"duplicate an existing backend; integrate or relay it and report any remaining gap."
|
||||
)
|
||||
if "unraid" in selected and "unraid_admin" in selected:
|
||||
if "unraid" in selected and "unraid_admin" in selected and "operator" in selected:
|
||||
rule += (
|
||||
" This request explicitly authorizes general work on Unraid. Use "
|
||||
"read-only MUA first for compact evidence, then use the direct MUA "
|
||||
"management or shell tool for commands and writes on Unraid. Use "
|
||||
"the Athena Operator only for orchestration on Athena or as a "
|
||||
"fallback when the target MCP cannot perform the required operation; "
|
||||
"do not spend repeated calls inventing a second SSH path. Do not ask "
|
||||
"the user to enable another tool: all three capabilities are attached. "
|
||||
"Do not install persistent packages unless explicitly requested; "
|
||||
"prefer an existing binary or task-local temporary copy. Avoid "
|
||||
"overwrites unless authorized and verify the final artifact."
|
||||
" For long-running work, finish discovery before mutation, then use "
|
||||
"a generic start-status-result pattern: prepare prerequisites in as few "
|
||||
"calls as possible, start the long command asynchronously when the tool "
|
||||
"timeout might be exceeded, poll only compact progress, and reserve "
|
||||
"enough calls for verification, final placement, and cleanup."
|
||||
)
|
||||
elif "unraid" in selected and "unraid_admin" in selected:
|
||||
rule += (
|
||||
" This request explicitly asks for an Unraid state change. Use the "
|
||||
"read-only MUA tools to establish evidence, then the narrowest MUA "
|
||||
@@ -140,6 +200,19 @@ class Filter:
|
||||
"Do not ask the user to enable another tool: both required MUA "
|
||||
"capabilities are already attached to this request."
|
||||
)
|
||||
elif "unraid" in selected and "operator" in selected:
|
||||
rule += (
|
||||
" This request requires general filesystem, command, download, "
|
||||
"conversion or other host work on Unraid. Use read-only MUA first "
|
||||
"for compact inventory and runtime evidence, then use the Athena "
|
||||
"Operator terminal for the exact user-authorized command sequence. "
|
||||
"Do not ask the user to enable another tool: both capabilities are "
|
||||
"already attached. Do not install persistent packages unless the "
|
||||
"user explicitly requested installation; prefer an existing binary "
|
||||
"or a task-local temporary copy. Write only to the requested target, "
|
||||
"avoid overwrites unless explicitly authorized, and verify the final "
|
||||
"artifact independently before reporting success."
|
||||
)
|
||||
elif "unraid" in selected:
|
||||
rule += (
|
||||
" For bounded file or media-library inventory on Unraid, prefer "
|
||||
@@ -193,7 +266,8 @@ class Filter:
|
||||
|
||||
selected: list[str] = []
|
||||
|
||||
operator = self._matches(
|
||||
general_operator = self._needs_general_operator(raw_text)
|
||||
operator = general_operator or self._matches(
|
||||
text,
|
||||
(
|
||||
r"\bathena[- ]operator\b",
|
||||
@@ -260,25 +334,19 @@ class Filter:
|
||||
unraid_write = unraid and self._matches(
|
||||
text,
|
||||
(
|
||||
r"\b(?:update|updates|aktualisier\w*|upgrade\w*)\b.*\b(?:docker|cont[aä]iner|image|unraid)\b",
|
||||
r"\b(?:docker|cont[aä]iner|image|unraid)\b.*\b(?:update|updates|aktualisier\w*|upgrade\w*)\b",
|
||||
r"\b(?:start|stop|restart|starte|stoppe|beende|rebuild|reinitialisier|neu\s+erstell)\w*\b.*\bcont[aä]iner\b",
|
||||
r"\bcont[aä]iner\b.*\b(?:start|stop|restart|starte|stoppe|beende|rebuild|reinitialisier|neu\s+erstell)\w*\b",
|
||||
r"\b(?:installier|entfern|l[oö]sch|[aä]nder|modifizier)\w*\b.*\b(?:unraid|docker|cont[aä]iner)\b",
|
||||
r"\b(?:unraid|docker|cont[aä]iner)\b.*\b(?:installier|entfern|l[oö]sch|[aä]nder|modifizier)\w*\b",
|
||||
r"\bf[uü]hr\w*\b.*\bupdates?\b.*\b(?:durch|aus)\b",
|
||||
r"\b(?:update|updates|aktualisier\w*|upgrade\w*)\b.*\b(?:docker|cont[aä]iner|image|unraid)\b",
|
||||
r"\b(?:docker|cont[aä]iner|image|unraid)\b.*\b(?:update|updates|aktualisier\w*|upgrade\w*)\b",
|
||||
r"\b(?:start|stop|restart|starte|stoppe|beende|rebuild|reinitialisier|neu\s+erstell)\w*\b.*\bcont[aä]iner\b",
|
||||
r"\bcont[aä]iner\b.*\b(?:start|stop|restart|starte|stoppe|beende|rebuild|reinitialisier|neu\s+erstell)\w*\b",
|
||||
r"\b(?:installier|entfern|l[oö]sch|[aä]nder|modifizier)\w*\b.*\b(?:unraid|docker|cont[aä]iner)\b",
|
||||
r"\b(?:unraid|docker|cont[aä]iner)\b.*\b(?:installier|entfern|l[oö]sch|[aä]nder|modifizier)\w*\b",
|
||||
r"\bf[uü]hr\w*\b.*\bupdates?\b.*\b(?:durch|aus)\b",
|
||||
r"\b(?:lad(?:e|en)?|download|herunterlad|konvertier|transkodier|kopier|verschieb|speicher|schreib|leg|umbenenn|l[oö]sch)\w*\b.{0,160}\b(?:unraid|unreid|unrate|anrate|nas|share|freigabe)\b",
|
||||
r"\b(?:unraid|unreid|unrate|anrate|nas|share|freigabe)\b.{0,160}\b(?:lad(?:e|en)?|download|herunterlad|konvertier|transkodier|kopier|verschieb|speicher|schreib|leg|umbenenn|l[oö]sch)\w*\b",
|
||||
r"\b(?:kommando|befehl|shell[- ]befehl)\w*\b.{0,100}\b(?:auf|in)\b.{0,30}\b(?:unraid|unreid|unrate|anrate|nas)\b",
|
||||
),
|
||||
)
|
||||
if unraid_write and self._matches(
|
||||
text,
|
||||
(
|
||||
r"\b(?:nur|lediglich|ausschlie(?:ß|ss)lich)\b.{0,30}\b(?:pr[uü]f|anzeig|auflist|status|nachseh)\w*\b",
|
||||
r"\b(?:keine|keinerlei|nichts?)\b.{0,40}\b(?:[aä]nder|update|aktualisier|durchf[uü]hr|installier|download|umbenenn)\w*\b",
|
||||
r"\bohne\b.{0,50}\b(?:[aä]nder|update|aktualisier|durchf[uü]hr|installier|download|umbenenn)\w*\b",
|
||||
r"\b(?:nicht|nichts?)\b.{0,20}\b(?:durchf[uü]hr|ausf[uü]hr|aktualisier|installier)\w*\b",
|
||||
r"\b(?:[aä]nder|erstell|installier|l[oö]sch|entfern|download|umbenenn)\w*\b.{0,25}\b(?:nichts?|keine[nrms]?|keinerlei)\b",
|
||||
),
|
||||
):
|
||||
if unraid_write and self._is_explicitly_readonly(raw_text):
|
||||
unraid_write = False
|
||||
github = self._matches(
|
||||
text,
|
||||
@@ -365,6 +433,11 @@ class Filter:
|
||||
# Consumed by the versioned Open WebUI continuation patch.
|
||||
# This is a request-local execution policy, not a site rule.
|
||||
metadata["mikeai_marketplace_research"] = True
|
||||
# Long operational tasks need more executions than bounded research.
|
||||
# This is a capability-class policy, not a rule for any product, site,
|
||||
# command or MCP. The patched Open WebUI loop consumes this marker.
|
||||
if self._needs_general_operator(latest_text):
|
||||
metadata["mikeai_long_operator_task"] = True
|
||||
|
||||
if not selected:
|
||||
return body
|
||||
|
||||
@@ -31,8 +31,14 @@ replacement = """ tool_call_iterations = 0
|
||||
# Per-tool and exact-repeat limits below prevent one low-level MCP
|
||||
# operation from consuming the whole turn.
|
||||
tool_call_executions = 0
|
||||
max_tool_call_executions = 40
|
||||
max_executions_per_tool = 12
|
||||
long_operator_task = bool(
|
||||
(metadata or {}).get('mikeai_long_operator_task', False)
|
||||
)
|
||||
# Research stays tightly bounded. Explicit long-running host work
|
||||
# receives a larger, still finite budget so discovery cannot consume
|
||||
# the calls needed for execution, verification and cleanup.
|
||||
max_tool_call_executions = 64 if long_operator_task else 40
|
||||
max_executions_per_tool = 24 if long_operator_task else 12
|
||||
# Inlet filters only see the first request, not later internal
|
||||
# tool continuations. Bound the evidence injected into those
|
||||
# continuations so one broad inventory cannot consume context.
|
||||
|
||||
Reference in New Issue
Block a user