Proxy: ADT REST write+activate fallback when EPOD does not activate a second PROG/FUNC write
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014aUaQeLnwbb1zTpN7kHeat
This commit is contained in:
@@ -50,6 +50,8 @@ class ToolProxy:
|
||||
self.fail_streak = 0
|
||||
self.max_fail_streak = 0
|
||||
self.log = open(log_path, "a")
|
||||
self.adt = None
|
||||
self.fallbacks = [] # writes that needed the ADT activation fallback
|
||||
|
||||
def schemas(self):
|
||||
tools = [t for t in self.mcp.list_tools() if t["name"] in MODEL_TOOLS]
|
||||
@@ -123,6 +125,8 @@ class ToolProxy:
|
||||
if tool in WRITE_TOOLS and (tool == "sap_activate" or args.get("activate", True)):
|
||||
self.activations += 1
|
||||
err, text = self.mcp.call(tool, args)
|
||||
if tool == "sap_push_source":
|
||||
err, text = self._activation_fallback(args, err, text)
|
||||
result = (err, self._filter(tool, text))
|
||||
if tool in WRITE_TOOLS:
|
||||
failed = err or '"success":false' in text.replace(" ", "")
|
||||
@@ -133,6 +137,32 @@ class ToolProxy:
|
||||
self.log.flush()
|
||||
return result
|
||||
|
||||
def _activation_fallback(self, args, err, text):
|
||||
"""EPOD does not activate a second write of a PROG or FUNC (outcome notExecuted, and sap_activate
|
||||
cannot help). Write and activate the same source through ADT REST; the agent sees one normal result."""
|
||||
otype = str(args.get("objectType", "")).upper()
|
||||
if otype not in ("PROG", "FUNC") or args.get("includeType") or args.get("activate") is False \
|
||||
or '"outcome":"notExecuted"' not in text.replace(" ", ""):
|
||||
return err, text
|
||||
name = str(args.get("objectName", "")).lower()
|
||||
uri = (f"/sap/bc/adt/programs/programs/{name}" if otype == "PROG" else
|
||||
f"/sap/bc/adt/functions/groups/{str(args.get('functionGroup', '')).lower()}/fmodules/{name}")
|
||||
try:
|
||||
if self.adt is None:
|
||||
from .adt_client import AdtClient
|
||||
self.adt = AdtClient()
|
||||
done, msgs = self.adt.write_activate(uri, name.upper(), args.get("source", ""))
|
||||
except Exception as e: # noqa: BLE001 keep the EPOD result when the fallback fails
|
||||
self.fallbacks.append({"object": name, "error": str(e)[:200]})
|
||||
return err, text
|
||||
self.fallbacks.append({"object": name, "activated": done})
|
||||
out = {"success": done,
|
||||
"message": "Source written and activation requested." if done else
|
||||
"Source written. Activation failed. See the activation messages.",
|
||||
"activation": {"messages": [{"severity": sv, "message": tx} for sv, tx in msgs],
|
||||
"activationExecuted": done, "success": done}}
|
||||
return False, json.dumps(out)
|
||||
|
||||
def note(self, kind, content):
|
||||
self.log.write(json.dumps({"t": time.time(), "kind": kind, "content": content}) + "\n")
|
||||
self.log.flush()
|
||||
|
||||
Reference in New Issue
Block a user