running MVP2
This commit is contained in:
parent
1b59810e0d
commit
2a02bb1c01
12 changed files with 199 additions and 110 deletions
|
|
@ -642,8 +642,13 @@ class HandlingTasks:
|
|||
action.result = first_doc.documentData.get("result", "")
|
||||
elif hasattr(first_doc, 'documentData') and isinstance(first_doc.documentData, str):
|
||||
action.result = first_doc.documentData
|
||||
action.execResultLabel = result.resultLabel or result_label
|
||||
await self.createActionMessage(action, result, workflow, result.resultLabel or result_label, created_documents, task_step, task_index)
|
||||
# Preserve the action's execResultLabel for document routing
|
||||
# Action methods should NOT return resultLabel - this is managed by the action handler
|
||||
if not action.execResultLabel:
|
||||
logger.warning(f"Action {action.execMethod}.{action.execAction} has no execResultLabel set")
|
||||
# Always use the action's execResultLabel for message creation to ensure proper document routing
|
||||
message_result_label = action.execResultLabel
|
||||
await self.createActionMessage(action, result, workflow, message_result_label, created_documents, task_step, task_index)
|
||||
|
||||
# Log action results
|
||||
logger.info(f"✓ Action completed successfully")
|
||||
|
|
@ -719,7 +724,7 @@ class HandlingTasks:
|
|||
return ActionResult(
|
||||
success=result.success,
|
||||
documents=original_documents, # Preserve original documents field from method result
|
||||
resultLabel=result.resultLabel or result_label,
|
||||
resultLabel=action.execResultLabel, # Always use action's execResultLabel
|
||||
error=result.error or ""
|
||||
)
|
||||
except Exception as e:
|
||||
|
|
@ -728,7 +733,7 @@ class HandlingTasks:
|
|||
return ActionResult(
|
||||
success=False,
|
||||
documents=[], # Empty documents for error case
|
||||
resultLabel=result_label,
|
||||
resultLabel=action.execResultLabel,
|
||||
error=str(e)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,17 @@ import inspect
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
def action(func):
|
||||
"""Decorator to mark a method as an available action"""
|
||||
"""Decorator to mark a method as an available action
|
||||
|
||||
IMPORTANT: Action methods should NOT return resultLabel in their ActionResult.
|
||||
The resultLabel is managed by the action handler using the action's execResultLabel
|
||||
from the action plan. This ensures consistent document routing throughout the workflow.
|
||||
|
||||
Action methods should only return:
|
||||
- success: bool
|
||||
- documents: List[ActionDocument]
|
||||
- error: str (if success=False)
|
||||
"""
|
||||
@wraps(func)
|
||||
async def wrapper(self, parameters: Dict[str, Any], *args, **kwargs):
|
||||
return await func(self, parameters, *args, **kwargs)
|
||||
|
|
|
|||
|
|
@ -468,7 +468,8 @@ class ServiceCenter:
|
|||
token = None
|
||||
token_status = "unknown"
|
||||
try:
|
||||
token = self.interfaceApp.getToken(connection.authority.value)
|
||||
# Use getConnectionToken to find token for this specific connection
|
||||
token = self.interfaceApp.getConnectionToken(connection.id)
|
||||
if token:
|
||||
if hasattr(token, 'expiresAt') and token.expiresAt:
|
||||
current_time = get_utc_timestamp()
|
||||
|
|
|
|||
|
|
@ -740,9 +740,13 @@ class AppObjects:
|
|||
"message": f"Error checking username availability: {str(e)}"
|
||||
}
|
||||
|
||||
def saveToken(self, token: Token) -> None:
|
||||
"""Save a token for the current user"""
|
||||
def saveAccessToken(self, token: Token) -> None:
|
||||
"""Save an access token for the current user (must NOT have connectionId)"""
|
||||
try:
|
||||
# Validate that this is NOT a connection token
|
||||
if token.connectionId:
|
||||
raise ValueError("Access tokens cannot have connectionId - use saveConnectionToken instead")
|
||||
|
||||
# Validate user context
|
||||
if not self.currentUser or not self.currentUser.id:
|
||||
raise ValueError("No valid user context available for token storage")
|
||||
|
|
@ -758,7 +762,7 @@ class AppObjects:
|
|||
|
||||
# Convert to dict and ensure all fields are properly set
|
||||
token_dict = token.dict()
|
||||
# Ensure userId is set to current user (this might override the token's userId)
|
||||
# Ensure userId is set to current user
|
||||
token_dict["userId"] = self.currentUser.id
|
||||
|
||||
# Save to database
|
||||
|
|
@ -767,19 +771,57 @@ class AppObjects:
|
|||
# Clear cache to ensure fresh data
|
||||
self._clearTableCache("tokens")
|
||||
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error saving token: {str(e)}")
|
||||
logger.error(f"Error saving access token: {str(e)}")
|
||||
raise
|
||||
|
||||
def getToken(self, authority: str, auto_refresh: bool = True) -> Optional[Token]:
|
||||
"""Get the latest valid token for the current user and authority, optionally auto-refresh if expired"""
|
||||
def saveConnectionToken(self, token: Token) -> None:
|
||||
"""Save a connection token (must have connectionId)"""
|
||||
try:
|
||||
# Get tokens for this user and authority
|
||||
# Validate that this IS a connection token
|
||||
if not token.connectionId:
|
||||
raise ValueError("Connection tokens must have connectionId - use saveAccessToken instead")
|
||||
|
||||
# Validate user context
|
||||
if not self.currentUser or not self.currentUser.id:
|
||||
raise ValueError("No valid user context available for token storage")
|
||||
|
||||
# Set the user ID for the connection token
|
||||
token.userId = self.currentUser.id
|
||||
|
||||
# Ensure token has required fields
|
||||
if not token.id:
|
||||
token.id = str(uuid.uuid4())
|
||||
if not token.createdAt:
|
||||
token.createdAt = get_utc_timestamp()
|
||||
|
||||
# Convert to dict and ensure all fields are properly set
|
||||
token_dict = token.dict()
|
||||
# Ensure userId is set to current user
|
||||
token_dict["userId"] = self.currentUser.id
|
||||
|
||||
# Save to database
|
||||
self.db.recordCreate("tokens", token_dict)
|
||||
|
||||
# Clear cache to ensure fresh data
|
||||
self._clearTableCache("tokens")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error saving connection token: {str(e)}")
|
||||
raise
|
||||
|
||||
def getAccessToken(self, authority: str, auto_refresh: bool = True) -> Optional[Token]:
|
||||
"""Get the latest valid access token for the current user and authority, optionally auto-refresh if expired"""
|
||||
try:
|
||||
# Validate that we're not looking for connection tokens
|
||||
if not self.currentUser or not self.currentUser.id:
|
||||
raise ValueError("No valid user context available for token retrieval")
|
||||
|
||||
# Get access tokens for this user and authority (must NOT have connectionId)
|
||||
tokens = self.db.getRecordset("tokens", recordFilter={
|
||||
"userId": self.currentUser.id,
|
||||
"authority": authority
|
||||
"authority": authority,
|
||||
"connectionId": None # Ensure we only get access tokens
|
||||
})
|
||||
|
||||
if not tokens:
|
||||
|
|
@ -792,8 +834,6 @@ class AppObjects:
|
|||
# Check if token is expired
|
||||
if latest_token.expiresAt and latest_token.expiresAt < get_utc_timestamp():
|
||||
if auto_refresh:
|
||||
|
||||
|
||||
# Import TokenManager here to avoid circular imports
|
||||
from modules.security.tokenManager import TokenManager
|
||||
token_manager = TokenManager()
|
||||
|
|
@ -802,45 +842,58 @@ class AppObjects:
|
|||
refreshed_token = token_manager.refresh_token(latest_token)
|
||||
if refreshed_token:
|
||||
# Save the new token and delete the old one
|
||||
self.saveToken(refreshed_token)
|
||||
self.deleteToken(authority)
|
||||
self.saveAccessToken(refreshed_token)
|
||||
self.deleteAccessToken(authority)
|
||||
|
||||
|
||||
return refreshed_token
|
||||
else:
|
||||
logger.warning(f"Failed to refresh expired token for {authority}")
|
||||
logger.warning(f"Failed to refresh expired access token for {authority}")
|
||||
return None
|
||||
else:
|
||||
logger.warning(f"Token for {authority} is expired (expiresAt: {latest_token.expiresAt})")
|
||||
logger.warning(f"Access token for {authority} is expired (expiresAt: {latest_token.expiresAt})")
|
||||
return None
|
||||
|
||||
return latest_token
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting token: {str(e)}")
|
||||
logger.error(f"Error getting access token: {str(e)}")
|
||||
return None
|
||||
|
||||
def getTokenForConnection(self, connectionId: str, auto_refresh: bool = True) -> Optional[Token]:
|
||||
"""Get the token for a specific connection, optionally auto-refresh if expired"""
|
||||
def getConnectionToken(self, connectionId: str, auto_refresh: bool = True) -> Optional[Token]:
|
||||
"""Get the connection token for a specific connectionId, optionally auto-refresh if expired"""
|
||||
try:
|
||||
logger.debug(f"Getting connection token for connectionId: {connectionId}")
|
||||
|
||||
# Validate connectionId
|
||||
if not connectionId:
|
||||
raise ValueError("connectionId is required for getConnectionToken")
|
||||
|
||||
# Get token for this specific connection
|
||||
logger.debug(f"Querying tokens table with connectionId: {connectionId}")
|
||||
|
||||
# Query for specific connection
|
||||
tokens = self.db.getRecordset("tokens", recordFilter={
|
||||
"connectionId": connectionId
|
||||
})
|
||||
|
||||
logger.debug(f"Raw tokens from database for connectionId {connectionId}: {tokens}")
|
||||
logger.debug(f"Tokens count: {len(tokens) if tokens else 0}")
|
||||
|
||||
if not tokens:
|
||||
logger.warning(f"No token found for connection: {connectionId}")
|
||||
logger.warning(f"No connection token found for connectionId: {connectionId}")
|
||||
return None
|
||||
|
||||
# Sort by expiration date and get the latest (most recent expiration)
|
||||
logger.debug(f"Sorting tokens by expiresAt, current tokens: {tokens}")
|
||||
tokens.sort(key=lambda x: x.get("expiresAt", 0), reverse=True)
|
||||
latest_token = Token(**tokens[0])
|
||||
logger.debug(f"Latest connection token: {latest_token}")
|
||||
logger.debug(f"Token expiresAt: {latest_token.expiresAt}, type: {type(latest_token.expiresAt)}")
|
||||
logger.debug(f"Current UTC timestamp: {get_utc_timestamp()}, type: {type(get_utc_timestamp())}")
|
||||
|
||||
# Check if token is expired
|
||||
if latest_token.expiresAt and latest_token.expiresAt < get_utc_timestamp():
|
||||
if auto_refresh:
|
||||
|
||||
|
||||
# Import TokenManager here to avoid circular imports
|
||||
from modules.security.tokenManager import TokenManager
|
||||
token_manager = TokenManager()
|
||||
|
|
@ -849,31 +902,36 @@ class AppObjects:
|
|||
refreshed_token = token_manager.refresh_token(latest_token)
|
||||
if refreshed_token:
|
||||
# Save the new token and delete the old one
|
||||
self.saveToken(refreshed_token)
|
||||
self.deleteTokenByConnectionId(connectionId)
|
||||
self.saveConnectionToken(refreshed_token)
|
||||
self.deleteConnectionTokenByConnectionId(connectionId)
|
||||
|
||||
|
||||
return refreshed_token
|
||||
else:
|
||||
logger.warning(f"Failed to refresh expired token for connection {connectionId}")
|
||||
logger.warning(f"Failed to refresh expired connection token for connectionId {connectionId}")
|
||||
return None
|
||||
else:
|
||||
logger.warning(f"Token for connection {connectionId} is expired (expiresAt: {latest_token.expiresAt})")
|
||||
logger.warning(f"Connection token for connectionId {connectionId} is expired (expiresAt: {latest_token.expiresAt})")
|
||||
return None
|
||||
|
||||
logger.debug(f"Returning valid connection token: {latest_token}")
|
||||
return latest_token
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting token for connection {connectionId}: {str(e)}")
|
||||
logger.error(f"Error getting connection token for connectionId {connectionId}: {str(e)}")
|
||||
return None
|
||||
|
||||
def deleteToken(self, authority: str) -> None:
|
||||
"""Delete all tokens for the current user and authority"""
|
||||
def deleteAccessToken(self, authority: str) -> None:
|
||||
"""Delete all access tokens for the current user and authority"""
|
||||
try:
|
||||
# Get tokens to delete
|
||||
# Validate user context
|
||||
if not self.currentUser or not self.currentUser.id:
|
||||
raise ValueError("No valid user context available for token deletion")
|
||||
|
||||
# Get access tokens to delete (must NOT have connectionId)
|
||||
tokens = self.db.getRecordset("tokens", recordFilter={
|
||||
"userId": self.currentUser.id,
|
||||
"authority": authority
|
||||
"authority": authority,
|
||||
"connectionId": None # Ensure we only delete access tokens
|
||||
})
|
||||
|
||||
# Delete each token
|
||||
|
|
@ -884,13 +942,17 @@ class AppObjects:
|
|||
self._clearTableCache("tokens")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error deleting token: {str(e)}")
|
||||
logger.error(f"Error deleting access token: {str(e)}")
|
||||
raise
|
||||
|
||||
def deleteTokenByConnectionId(self, connectionId: str) -> None:
|
||||
"""Delete all tokens for a specific connection"""
|
||||
def deleteConnectionTokenByConnectionId(self, connectionId: str) -> None:
|
||||
"""Delete all connection tokens for a specific connectionId"""
|
||||
try:
|
||||
# Get tokens to delete
|
||||
# Validate connectionId
|
||||
if not connectionId:
|
||||
raise ValueError("connectionId is required for deleteConnectionTokenByConnectionId")
|
||||
|
||||
# Get connection tokens to delete
|
||||
tokens = self.db.getRecordset("tokens", recordFilter={
|
||||
"connectionId": connectionId
|
||||
})
|
||||
|
|
@ -903,9 +965,15 @@ class AppObjects:
|
|||
self._clearTableCache("tokens")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error deleting token for connection {connectionId}: {str(e)}")
|
||||
logger.error(f"Error deleting connection token for connectionId {connectionId}: {str(e)}")
|
||||
raise
|
||||
|
||||
# Backward compatibility method
|
||||
def getTokenForConnection(self, connectionId: str, auto_refresh: bool = True) -> Optional[Token]:
|
||||
"""Backward compatibility method - use getConnectionToken instead"""
|
||||
logger.warning("getTokenForConnection is deprecated, use getConnectionToken instead")
|
||||
return self.getConnectionToken(connectionId, auto_refresh)
|
||||
|
||||
def cleanupExpiredTokens(self) -> int:
|
||||
"""Clean up expired tokens for all connections, returns count of cleaned tokens"""
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -31,32 +31,41 @@ register_model_labels(
|
|||
)
|
||||
|
||||
class ActionResult(BaseModel, ModelMixin):
|
||||
"""Clean action result with documents as primary output"""
|
||||
"""Clean action result with documents as primary output
|
||||
|
||||
IMPORTANT: Action methods should NOT set resultLabel in their return value.
|
||||
The resultLabel is managed by the action handler using the action's execResultLabel
|
||||
from the action plan. This ensures consistent document routing throughout the workflow.
|
||||
"""
|
||||
# Core result
|
||||
success: bool = Field(description="Whether execution succeeded")
|
||||
error: Optional[str] = Field(None, description="Error message if failed")
|
||||
|
||||
# Primary output - documents
|
||||
documents: List[ActionDocument] = Field(default_factory=list, description="Document outputs")
|
||||
resultLabel: Optional[str] = Field(None, description="Label for document routing")
|
||||
resultLabel: Optional[str] = Field(None, description="Label for document routing (set by action handler, not by action methods)")
|
||||
|
||||
@classmethod
|
||||
def success(cls, documents: List[ActionDocument] = None, resultLabel: str = None) -> 'ActionResult':
|
||||
"""Create a successful action result"""
|
||||
def success(cls, documents: List[ActionDocument] = None) -> 'ActionResult':
|
||||
"""Create a successful action result
|
||||
|
||||
Note: Do not set resultLabel - this is managed by the action handler
|
||||
"""
|
||||
return cls(
|
||||
success=True,
|
||||
documents=documents or [],
|
||||
resultLabel=resultLabel
|
||||
documents=documents or []
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def failure(cls, error: str, documents: List[ActionDocument] = None, resultLabel: str = None) -> 'ActionResult':
|
||||
"""Create a failed action result"""
|
||||
def failure(cls, error: str, documents: List[ActionDocument] = None) -> 'ActionResult':
|
||||
"""Create a failed action result
|
||||
|
||||
Note: Do not set resultLabel - this is managed by the action handler
|
||||
"""
|
||||
return cls(
|
||||
success=False,
|
||||
documents=documents or [],
|
||||
error=error,
|
||||
resultLabel=resultLabel
|
||||
error=error
|
||||
)
|
||||
|
||||
# Register labels for ActionResult
|
||||
|
|
|
|||
|
|
@ -102,18 +102,25 @@ class MethodOutlook(MethodBase):
|
|||
Helper function to get Microsoft connection details.
|
||||
"""
|
||||
try:
|
||||
logger.debug(f"Getting Microsoft connection for reference: {connectionReference}")
|
||||
|
||||
# Get the connection from the service
|
||||
userConnection = self.service.getUserConnectionFromConnectionReference(connectionReference)
|
||||
if not userConnection:
|
||||
logger.error(f"Connection not found: {connectionReference}")
|
||||
return None
|
||||
|
||||
logger.debug(f"Found connection: {userConnection.id}, status: {userConnection.status.value}, authority: {userConnection.authority.value}")
|
||||
|
||||
# Get the token for this specific connection
|
||||
token = self.service.interfaceApp.getTokenForConnection(userConnection.id)
|
||||
token = self.service.interfaceApp.getConnectionToken(userConnection.id)
|
||||
if not token:
|
||||
logger.error(f"Token not found for connection: {userConnection.id}")
|
||||
logger.debug(f"Connection details: {userConnection}")
|
||||
return None
|
||||
|
||||
logger.debug(f"Token retrieved for connection {userConnection.id}")
|
||||
|
||||
# Check if token is expired
|
||||
if hasattr(token, 'expiresAt') and token.expiresAt:
|
||||
current_time = get_utc_timestamp()
|
||||
|
|
@ -126,8 +133,6 @@ class MethodOutlook(MethodBase):
|
|||
logger.error(f"Connection is not active: {userConnection.id}, status: {userConnection.status.value}")
|
||||
return None
|
||||
|
||||
|
||||
|
||||
return {
|
||||
"id": userConnection.id,
|
||||
"accessToken": token.tokenAccess,
|
||||
|
|
@ -482,8 +487,7 @@ class MethodOutlook(MethodBase):
|
|||
"timestamp": get_utc_timestamp()
|
||||
},
|
||||
"mimeType": "application/json"
|
||||
}],
|
||||
resultLabel="outlook_emails"
|
||||
}]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -529,8 +533,10 @@ class MethodOutlook(MethodBase):
|
|||
)
|
||||
|
||||
# Get Microsoft connection
|
||||
logger.debug(f"Getting Microsoft connection for sendEmail action")
|
||||
connection = self._getMicrosoftConnection(connectionReference)
|
||||
if not connection:
|
||||
logger.error(f"Failed to get Microsoft connection for reference: {connectionReference}")
|
||||
return ActionResult.failure(error="Failed to get Microsoft connection")
|
||||
|
||||
# Get the composed email document
|
||||
|
|
@ -777,8 +783,7 @@ class MethodOutlook(MethodBase):
|
|||
"timestamp": get_utc_timestamp()
|
||||
},
|
||||
"mimeType": "application/json"
|
||||
}],
|
||||
resultLabel="email_draft_created"
|
||||
}]
|
||||
)
|
||||
else:
|
||||
logger.error(f"Failed to create draft. Status: {response.status_code}, Response: {response.text}")
|
||||
|
|
@ -815,8 +820,7 @@ class MethodOutlook(MethodBase):
|
|||
"timestamp": get_utc_timestamp()
|
||||
},
|
||||
"mimeType": "application/json"
|
||||
}],
|
||||
resultLabel="outlook_email_draft"
|
||||
}]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -998,8 +1002,7 @@ class MethodOutlook(MethodBase):
|
|||
"timestamp": get_utc_timestamp()
|
||||
},
|
||||
"mimeType": "application/json"
|
||||
}],
|
||||
resultLabel="outlook_email_search"
|
||||
}]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -1122,8 +1125,7 @@ class MethodOutlook(MethodBase):
|
|||
"timestamp": get_utc_timestamp()
|
||||
},
|
||||
"mimeType": "application/json"
|
||||
}],
|
||||
resultLabel="outlook_drafts_list"
|
||||
}]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -1233,8 +1235,7 @@ class MethodOutlook(MethodBase):
|
|||
"timestamp": get_utc_timestamp()
|
||||
},
|
||||
"mimeType": "application/json"
|
||||
}],
|
||||
resultLabel="outlook_drafts_found"
|
||||
}]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -1377,8 +1378,7 @@ class MethodOutlook(MethodBase):
|
|||
"timestamp": get_utc_timestamp()
|
||||
},
|
||||
"mimeType": "application/json"
|
||||
}],
|
||||
resultLabel="outlook_drafts_folder_check"
|
||||
}]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -1618,8 +1618,7 @@ class MethodOutlook(MethodBase):
|
|||
"documentName": f"composed_email_{int(get_utc_timestamp())}.json",
|
||||
"documentData": result_data,
|
||||
"mimeType": "application/json"
|
||||
}],
|
||||
resultLabel="composed_email"
|
||||
}]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -1662,8 +1661,7 @@ class MethodOutlook(MethodBase):
|
|||
"status": "ready"
|
||||
},
|
||||
"mimeType": "application/json"
|
||||
}],
|
||||
resultLabel="permissions_ready"
|
||||
}]
|
||||
)
|
||||
else:
|
||||
return ActionResult(
|
||||
|
|
@ -1680,8 +1678,7 @@ class MethodOutlook(MethodBase):
|
|||
},
|
||||
"mimeType": "application/json"
|
||||
}],
|
||||
error="Connection lacks necessary permissions for Outlook operations",
|
||||
resultLabel="permissions_missing"
|
||||
error="Connection lacks necessary permissions for Outlook operations"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class MethodSharepoint(MethodBase):
|
|||
return None
|
||||
|
||||
# Get the token for this specific connection
|
||||
token = self.service.interfaceApp.getTokenForConnection(userConnection.id)
|
||||
token = self.service.interfaceApp.getConnectionToken(userConnection.id)
|
||||
if not token:
|
||||
logger.warning(f"No token found for connection {userConnection.id}")
|
||||
return None
|
||||
|
|
@ -283,8 +283,7 @@ class MethodSharepoint(MethodBase):
|
|||
"documentData": result_data,
|
||||
"mimeType": output_mime_type
|
||||
}
|
||||
],
|
||||
resultLabel="sharepoint_find_path"
|
||||
]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -474,8 +473,7 @@ class MethodSharepoint(MethodBase):
|
|||
"documentData": result_data,
|
||||
"mimeType": output_mime_type
|
||||
}
|
||||
],
|
||||
resultLabel="sharepoint_documents"
|
||||
]
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error reading SharePoint documents: {str(e)}")
|
||||
|
|
@ -652,8 +650,7 @@ class MethodSharepoint(MethodBase):
|
|||
"documentData": result_data,
|
||||
"mimeType": output_mime_type
|
||||
}
|
||||
],
|
||||
resultLabel="sharepoint_upload"
|
||||
]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -861,8 +858,7 @@ class MethodSharepoint(MethodBase):
|
|||
"documentData": result_data,
|
||||
"mimeType": output_mime_type
|
||||
}
|
||||
],
|
||||
resultLabel="sharepoint_document_list"
|
||||
]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -562,8 +562,7 @@ class MethodWeb(MethodBase):
|
|||
"documentData": result_data,
|
||||
"mimeType": output_mime_type
|
||||
}
|
||||
],
|
||||
resultLabel="web_search_results"
|
||||
]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -698,8 +697,7 @@ class MethodWeb(MethodBase):
|
|||
"documentData": result_data,
|
||||
"mimeType": output_mime_type
|
||||
}
|
||||
],
|
||||
resultLabel="web_crawl_results"
|
||||
]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -803,8 +801,7 @@ class MethodWeb(MethodBase):
|
|||
"documentData": result_data,
|
||||
"mimeType": output_mime_type
|
||||
}
|
||||
],
|
||||
resultLabel="web_scrape_results"
|
||||
]
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -223,9 +223,9 @@ async def auth_callback(code: str, state: str, request: Request) -> HTMLResponse
|
|||
createdAt=get_utc_timestamp()
|
||||
)
|
||||
|
||||
# Save token
|
||||
# Save access token (no connectionId)
|
||||
appInterface = getInterface(user)
|
||||
appInterface.saveToken(token)
|
||||
appInterface.saveAccessToken(token)
|
||||
|
||||
# Return success page with token data
|
||||
return HTMLResponse(
|
||||
|
|
@ -347,7 +347,7 @@ async def auth_callback(code: str, state: str, request: Request) -> HTMLResponse
|
|||
expiresAt=create_expiration_timestamp(token_response.get("expires_in", 0)),
|
||||
createdAt=get_utc_timestamp()
|
||||
)
|
||||
interface.saveToken(token)
|
||||
interface.saveConnectionToken(token)
|
||||
|
||||
# Return success page with connection data
|
||||
return HTMLResponse(
|
||||
|
|
@ -491,7 +491,7 @@ async def refresh_token(
|
|||
logger.debug(f"Found Google connection: {google_connection.id}, status={google_connection.status}")
|
||||
|
||||
# Get the token for this specific connection using the new method
|
||||
current_token = appInterface.getTokenForConnection(google_connection.id, auto_refresh=False)
|
||||
current_token = appInterface.getConnectionToken(google_connection.id, auto_refresh=False)
|
||||
|
||||
if not current_token:
|
||||
raise HTTPException(
|
||||
|
|
@ -507,9 +507,9 @@ async def refresh_token(
|
|||
|
||||
refreshed_token = token_manager.refresh_token(current_token)
|
||||
if refreshed_token:
|
||||
# Save the new token and delete the old one
|
||||
appInterface.saveToken(refreshed_token)
|
||||
appInterface.deleteTokenByConnectionId(google_connection.id)
|
||||
# Save the new connection token and delete the old one
|
||||
appInterface.saveConnectionToken(refreshed_token)
|
||||
appInterface.deleteConnectionTokenByConnectionId(google_connection.id)
|
||||
|
||||
# Update the connection's expiration time
|
||||
google_connection.expiresAt = float(refreshed_token.expiresAt)
|
||||
|
|
|
|||
|
|
@ -103,8 +103,8 @@ async def login(
|
|||
expiresAt=expires_at.timestamp()
|
||||
)
|
||||
|
||||
# Save token
|
||||
userInterface.saveToken(token)
|
||||
# Save access token
|
||||
userInterface.saveAccessToken(token)
|
||||
|
||||
# Create response data
|
||||
response_data = {
|
||||
|
|
|
|||
|
|
@ -173,9 +173,9 @@ async def auth_callback(code: str, state: str, request: Request) -> HTMLResponse
|
|||
createdAt=get_utc_timestamp()
|
||||
)
|
||||
|
||||
# Save token
|
||||
# Save access token (no connectionId)
|
||||
appInterface = getInterface(user)
|
||||
appInterface.saveToken(token)
|
||||
appInterface.saveAccessToken(token)
|
||||
|
||||
# Create JWT token data
|
||||
jwt_token_data = {
|
||||
|
|
@ -198,8 +198,8 @@ async def auth_callback(code: str, state: str, request: Request) -> HTMLResponse
|
|||
createdAt=get_utc_timestamp()
|
||||
)
|
||||
|
||||
# Save JWT token
|
||||
appInterface.saveToken(jwt_token_obj)
|
||||
# Save JWT access token
|
||||
appInterface.saveAccessToken(jwt_token_obj)
|
||||
|
||||
# Convert token to dict and ensure proper timestamp handling
|
||||
token_dict = jwt_token_obj.to_dict()
|
||||
|
|
@ -328,7 +328,7 @@ async def auth_callback(code: str, state: str, request: Request) -> HTMLResponse
|
|||
)
|
||||
|
||||
|
||||
interface.saveToken(token)
|
||||
interface.saveConnectionToken(token)
|
||||
|
||||
|
||||
# Return success page with connection data
|
||||
|
|
@ -499,7 +499,7 @@ async def refresh_token(
|
|||
|
||||
# Get the token for this specific connection using the new method
|
||||
# Enable auto-refresh to handle expired tokens gracefully
|
||||
current_token = appInterface.getTokenForConnection(msft_connection.id, auto_refresh=True)
|
||||
current_token = appInterface.getConnectionToken(msft_connection.id, auto_refresh=True)
|
||||
|
||||
if not current_token:
|
||||
raise HTTPException(
|
||||
|
|
@ -515,9 +515,9 @@ async def refresh_token(
|
|||
|
||||
refreshed_token = token_manager.refresh_token(current_token)
|
||||
if refreshed_token:
|
||||
# Save the new token and delete the old one
|
||||
appInterface.saveToken(refreshed_token)
|
||||
appInterface.deleteTokenByConnectionId(msft_connection.id)
|
||||
# Save the new connection token and delete the old one
|
||||
appInterface.saveConnectionToken(refreshed_token)
|
||||
appInterface.deleteConnectionTokenByConnectionId(msft_connection.id)
|
||||
|
||||
# Update the connection's expiration time
|
||||
msft_connection.expiresAt = float(refreshed_token.expiresAt)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
|
||||
TODO
|
||||
|
||||
- ui: Besseres Rendering der Tasks, Actions, Files (hierarchisch eingerückt) und der Log Entries ohne Rahmen
|
||||
- ui: Beim Laden des Workflows die Logs und Messages synchron laden chronologisch
|
||||
- documents: Sprechende Filenamen für user, ein Label für die interne Nutzung
|
||||
- Chat: Pro Action und Task eine Message an den User in der UserLanguage
|
||||
|
||||
|
||||
- check history --> tasks?
|
||||
- model reference diagram for all models. who uses who? --> to see the basic building blocks
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue