fixes ai toolbox connections
This commit is contained in:
parent
1230a953bd
commit
fe89952252
5 changed files with 50 additions and 13 deletions
|
|
@ -1266,11 +1266,27 @@ class AppObjects:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def getUserConnectionById(self, connectionId: str) -> Optional[UserConnection]:
|
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:
|
||||||
|
# Try direct UUID lookup first
|
||||||
connections = self.db.getRecordset(
|
connections = self.db.getRecordset(
|
||||||
UserConnection, recordFilter={"id": connectionId}
|
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:
|
if connections:
|
||||||
conn_dict = connections[0]
|
conn_dict = connections[0]
|
||||||
return UserConnection(
|
return UserConnection(
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,11 @@ def _createDispatchHandler(actionExecutor, methodName: str, actionName: str):
|
||||||
"""Create an async handler that dispatches to the ActionExecutor."""
|
"""Create an async handler that dispatches to the ActionExecutor."""
|
||||||
async def _handler(args: Dict[str, Any], context: Dict[str, Any]) -> ToolResult:
|
async def _handler(args: Dict[str, Any], context: Dict[str, Any]) -> ToolResult:
|
||||||
try:
|
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)
|
result = await actionExecutor.executeAction(methodName, actionName, args)
|
||||||
data = _formatActionResult(result)
|
data = _formatActionResult(result)
|
||||||
return ToolResult(
|
return ToolResult(
|
||||||
|
|
|
||||||
|
|
@ -44,12 +44,12 @@ def _registerConnectionTools(registry: ToolRegistry, services):
|
||||||
return ToolResult(toolCallId="", toolName="listConnections", success=True, data="No connections available.")
|
return ToolResult(toolCallId="", toolName="listConnections", success=True, data="No connections available.")
|
||||||
lines = []
|
lines = []
|
||||||
for conn in connections:
|
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", "?")
|
authority = conn.get("authority", "?") if isinstance(conn, dict) else getattr(conn, "authority", "?")
|
||||||
authorityVal = authority.value if hasattr(authority, "value") else str(authority)
|
authorityVal = authority.value if hasattr(authority, "value") else str(authority)
|
||||||
username = conn.get("externalUsername", "") if isinstance(conn, dict) else getattr(conn, "externalUsername", "")
|
username = conn.get("externalUsername", "") if isinstance(conn, dict) else getattr(conn, "externalUsername", "")
|
||||||
email = conn.get("externalEmail", "") if isinstance(conn, dict) else getattr(conn, "externalEmail", "")
|
email = conn.get("externalEmail", "") if isinstance(conn, dict) else getattr(conn, "externalEmail", "")
|
||||||
ref = f"connection:{authorityVal}:{username}"
|
lines.append(f"- connectionId: {connId} | {authorityVal} | {username} ({email})")
|
||||||
lines.append(f"- {ref} ({email})")
|
|
||||||
return ToolResult(toolCallId="", toolName="listConnections", success=True, data="\n".join(lines))
|
return ToolResult(toolCallId="", toolName="listConnections", success=True, data="\n".join(lines))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return ToolResult(toolCallId="", toolName="listConnections", success=False, error=str(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))
|
return ToolResult(toolCallId="", toolName="sendMail", success=False, error=str(e))
|
||||||
|
|
||||||
_connToolParams = {
|
_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.)"},
|
"service": {"type": "string", "description": "Service name (sharepoint, outlook, drive, etc.)"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,7 +177,7 @@ def _registerConnectionTools(registry: ToolRegistry, services):
|
||||||
parameters={
|
parameters={
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"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"},
|
"to": {"type": "array", "items": {"type": "string"}, "description": "Recipient email addresses"},
|
||||||
"subject": {"type": "string", "description": "Email subject"},
|
"subject": {"type": "string", "description": "Email subject"},
|
||||||
"body": {"type": "string", "description": "Email body — plain text or HTML markup"},
|
"body": {"type": "string", "description": "Email body — plain text or HTML markup"},
|
||||||
|
|
|
||||||
|
|
@ -267,6 +267,8 @@ class AgentService:
|
||||||
registerCoreTools(registry, self.services)
|
registerCoreTools(registry, self.services)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
from modules.workflows.processing.shared.methodDiscovery import discoverMethods
|
||||||
|
discoverMethods(self.services)
|
||||||
from modules.workflows.processing.core.actionExecutor import ActionExecutor
|
from modules.workflows.processing.core.actionExecutor import ActionExecutor
|
||||||
actionExecutor = ActionExecutor(self.services)
|
actionExecutor = ActionExecutor(self.services)
|
||||||
adapter = ActionToolAdapter(actionExecutor)
|
adapter = ActionToolAdapter(actionExecutor)
|
||||||
|
|
@ -293,10 +295,14 @@ class AgentService:
|
||||||
|
|
||||||
userConnections: List[str] = []
|
userConnections: List[str] = []
|
||||||
try:
|
try:
|
||||||
connectionService = self._getService("connection")
|
chatService = self.services.chat if hasattr(self.services, "chat") else None
|
||||||
if connectionService and hasattr(connectionService, "getConnections"):
|
if chatService and hasattr(chatService, "getUserConnections"):
|
||||||
connections = connectionService.getConnections() or []
|
connections = chatService.getUserConnections() or []
|
||||||
userConnections = [c.get("authority", "") for c in connections if c.get("authority")]
|
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:
|
except Exception as e:
|
||||||
logger.debug("Could not resolve user connections for toolbox activation: %s", e)
|
logger.debug("Could not resolve user connections for toolbox activation: %s", e)
|
||||||
|
|
||||||
|
|
@ -370,13 +376,23 @@ class AgentService:
|
||||||
if registry.isValidTool(toolName):
|
if registry.isValidTool(toolName):
|
||||||
activatedCount += 1
|
activatedCount += 1
|
||||||
continue
|
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:
|
try:
|
||||||
from modules.serviceCenter.services.serviceAgent.actionToolAdapter import ActionToolAdapter
|
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)
|
adapter.registerAll(registry)
|
||||||
if registry.isValidTool(toolName):
|
if registry.isValidTool(toolName):
|
||||||
activatedCount += 1
|
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:
|
else:
|
||||||
logger.warning("requestToolbox: tool '%s' from toolbox '%s' could not be registered", toolName, toolboxId)
|
logger.warning("requestToolbox: tool '%s' from toolbox '%s' could not be registered", toolName, toolboxId)
|
||||||
except Exception as regErr:
|
except Exception as regErr:
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ def _registerDefaultToolboxes() -> None:
|
||||||
id="email",
|
id="email",
|
||||||
label="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.",
|
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,
|
isDefault=False,
|
||||||
tools=[
|
tools=[
|
||||||
"sendMail",
|
"sendMail",
|
||||||
|
|
@ -159,7 +159,7 @@ def _registerDefaultToolboxes() -> None:
|
||||||
id="sharepoint",
|
id="sharepoint",
|
||||||
label="SharePoint",
|
label="SharePoint",
|
||||||
description="Access SharePoint sites, lists, and files",
|
description="Access SharePoint sites, lists, and files",
|
||||||
requiresConnection="microsoft",
|
requiresConnection="msft",
|
||||||
isDefault=False,
|
isDefault=False,
|
||||||
tools=[
|
tools=[
|
||||||
"sharepoint_findDocuments", "sharepoint_readDocuments",
|
"sharepoint_findDocuments", "sharepoint_readDocuments",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue