fixes ai toolbox connections

This commit is contained in:
ValueOn AG 2026-04-14 13:26:12 +02:00
parent 1230a953bd
commit fe89952252
5 changed files with 50 additions and 13 deletions

View file

@ -1266,11 +1266,27 @@ class AppObjects:
return []
def getUserConnectionById(self, connectionId: str) -> Optional[UserConnection]:
"""Get a single UserConnection by ID."""
"""Get a single UserConnection by ID or by reference string (connection:authority:username)."""
try:
# Try direct UUID lookup first
connections = self.db.getRecordset(
UserConnection, recordFilter={"id": connectionId}
)
# Fallback: parse "connection:authority:username" format from AI agent
if not connections and connectionId.startswith("connection:"):
parts = connectionId.split(":", 2)
if len(parts) >= 3:
authority = parts[1]
username = parts[2]
allConns = self.db.getRecordset(UserConnection, recordFilter={"externalUsername": username})
for c in (allConns or []):
a = c.get("authority", "")
aVal = a.value if hasattr(a, "value") else str(a)
if aVal == authority:
connections = [c]
break
if connections:
conn_dict = connections[0]
return UserConnection(

View file

@ -135,6 +135,11 @@ def _createDispatchHandler(actionExecutor, methodName: str, actionName: str):
"""Create an async handler that dispatches to the ActionExecutor."""
async def _handler(args: Dict[str, Any], context: Dict[str, Any]) -> ToolResult:
try:
if context:
if "featureInstanceId" not in args and context.get("featureInstanceId"):
args["featureInstanceId"] = context["featureInstanceId"]
if "mandateId" not in args and context.get("mandateId"):
args["mandateId"] = context["mandateId"]
result = await actionExecutor.executeAction(methodName, actionName, args)
data = _formatActionResult(result)
return ToolResult(

View file

@ -44,12 +44,12 @@ def _registerConnectionTools(registry: ToolRegistry, services):
return ToolResult(toolCallId="", toolName="listConnections", success=True, data="No connections available.")
lines = []
for conn in connections:
connId = conn.get("id", "") if isinstance(conn, dict) else getattr(conn, "id", "")
authority = conn.get("authority", "?") if isinstance(conn, dict) else getattr(conn, "authority", "?")
authorityVal = authority.value if hasattr(authority, "value") else str(authority)
username = conn.get("externalUsername", "") if isinstance(conn, dict) else getattr(conn, "externalUsername", "")
email = conn.get("externalEmail", "") if isinstance(conn, dict) else getattr(conn, "externalEmail", "")
ref = f"connection:{authorityVal}:{username}"
lines.append(f"- {ref} ({email})")
lines.append(f"- connectionId: {connId} | {authorityVal} | {username} ({email})")
return ToolResult(toolCallId="", toolName="listConnections", success=True, data="\n".join(lines))
except Exception as e:
return ToolResult(toolCallId="", toolName="listConnections", success=False, error=str(e))
@ -137,7 +137,7 @@ def _registerConnectionTools(registry: ToolRegistry, services):
return ToolResult(toolCallId="", toolName="sendMail", success=False, error=str(e))
_connToolParams = {
"connectionId": {"type": "string", "description": "UserConnection ID"},
"connectionId": {"type": "string", "description": "UserConnection UUID (from listConnections output, e.g. '3fa85f64-...')"},
"service": {"type": "string", "description": "Service name (sharepoint, outlook, drive, etc.)"},
}
@ -177,7 +177,7 @@ def _registerConnectionTools(registry: ToolRegistry, services):
parameters={
"type": "object",
"properties": {
"connectionId": {"type": "string", "description": "UserConnection ID"},
"connectionId": {"type": "string", "description": "UserConnection UUID (from listConnections output)"},
"to": {"type": "array", "items": {"type": "string"}, "description": "Recipient email addresses"},
"subject": {"type": "string", "description": "Email subject"},
"body": {"type": "string", "description": "Email body — plain text or HTML markup"},

View file

@ -267,6 +267,8 @@ class AgentService:
registerCoreTools(registry, self.services)
try:
from modules.workflows.processing.shared.methodDiscovery import discoverMethods
discoverMethods(self.services)
from modules.workflows.processing.core.actionExecutor import ActionExecutor
actionExecutor = ActionExecutor(self.services)
adapter = ActionToolAdapter(actionExecutor)
@ -293,10 +295,14 @@ class AgentService:
userConnections: List[str] = []
try:
connectionService = self._getService("connection")
if connectionService and hasattr(connectionService, "getConnections"):
connections = connectionService.getConnections() or []
userConnections = [c.get("authority", "") for c in connections if c.get("authority")]
chatService = self.services.chat if hasattr(self.services, "chat") else None
if chatService and hasattr(chatService, "getUserConnections"):
connections = chatService.getUserConnections() or []
for c in connections:
authority = c.get("authority", "") if isinstance(c, dict) else getattr(c, "authority", "")
authorityVal = authority.value if hasattr(authority, "value") else str(authority)
if authorityVal:
userConnections.append(authorityVal)
except Exception as e:
logger.debug("Could not resolve user connections for toolbox activation: %s", e)
@ -370,13 +376,23 @@ class AgentService:
if registry.isValidTool(toolName):
activatedCount += 1
continue
try:
from modules.serviceCenter.services.serviceAgent.coreTools import registerCoreTools
registerCoreTools(registry, self.services)
if registry.isValidTool(toolName):
activatedCount += 1
logger.info("requestToolbox: re-registered tool '%s' (core) from toolbox '%s'", toolName, toolboxId)
continue
except Exception:
pass
try:
from modules.serviceCenter.services.serviceAgent.actionToolAdapter import ActionToolAdapter
adapter = ActionToolAdapter(self._getService("actionExecutor"))
from modules.workflows.processing.core.actionExecutor import ActionExecutor
adapter = ActionToolAdapter(ActionExecutor(self.services))
adapter.registerAll(registry)
if registry.isValidTool(toolName):
activatedCount += 1
logger.info("requestToolbox: re-registered tool '%s' from toolbox '%s'", toolName, toolboxId)
logger.info("requestToolbox: re-registered tool '%s' (action) from toolbox '%s'", toolName, toolboxId)
else:
logger.warning("requestToolbox: tool '%s' from toolbox '%s' could not be registered", toolName, toolboxId)
except Exception as regErr:

View file

@ -149,7 +149,7 @@ def _registerDefaultToolboxes() -> None:
id="email",
label="Email",
description="Send emails or save as draft via Outlook (supports HTML body and file attachments). Use sendMail with draft=true for drafts.",
requiresConnection="microsoft",
requiresConnection="msft",
isDefault=False,
tools=[
"sendMail",
@ -159,7 +159,7 @@ def _registerDefaultToolboxes() -> None:
id="sharepoint",
label="SharePoint",
description="Access SharePoint sites, lists, and files",
requiresConnection="microsoft",
requiresConnection="msft",
isDefault=False,
tools=[
"sharepoint_findDocuments", "sharepoint_readDocuments",