mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 19:00:59 +03:00
Feature/Add teams, gmail, outlook tools (#4577)
* add teams, gmail, outlook tools * update docs link * update credentials for oauth2 * add jira tool * add google drive, google calendar, google sheets tools, powerpoint, excel, word doc loader * update jira logo * Refactor Gmail and Outlook tools to remove maxOutputLength parameter and enhance request handling. Update response formatting to include parameters in the output. Adjust Google Drive tools to simplify success messages by removing unnecessary parameter details.
This commit is contained in:
@@ -585,42 +585,87 @@ const _showHideOperation = (nodeData: Record<string, any>, inputParam: Record<st
|
||||
if (path.includes('$index') && index) {
|
||||
path = path.replace('$index', index.toString())
|
||||
}
|
||||
const groundValue = get(nodeData.inputs, path, '')
|
||||
let groundValue = get(nodeData.inputs, path, '')
|
||||
if (groundValue && typeof groundValue === 'string' && groundValue.startsWith('[') && groundValue.endsWith(']')) {
|
||||
groundValue = JSON.parse(groundValue)
|
||||
}
|
||||
|
||||
if (Array.isArray(comparisonValue)) {
|
||||
if (displayType === 'show' && !comparisonValue.includes(groundValue)) {
|
||||
inputParam.display = false
|
||||
// Handle case where groundValue is an array
|
||||
if (Array.isArray(groundValue)) {
|
||||
if (Array.isArray(comparisonValue)) {
|
||||
// Both are arrays - check if there's any intersection
|
||||
const hasIntersection = comparisonValue.some((val) => groundValue.includes(val))
|
||||
if (displayType === 'show' && !hasIntersection) {
|
||||
inputParam.display = false
|
||||
}
|
||||
if (displayType === 'hide' && hasIntersection) {
|
||||
inputParam.display = false
|
||||
}
|
||||
} else if (typeof comparisonValue === 'string') {
|
||||
// comparisonValue is string, groundValue is array - check if array contains the string
|
||||
const matchFound = groundValue.some((val) => comparisonValue === val || new RegExp(comparisonValue).test(val))
|
||||
if (displayType === 'show' && !matchFound) {
|
||||
inputParam.display = false
|
||||
}
|
||||
if (displayType === 'hide' && matchFound) {
|
||||
inputParam.display = false
|
||||
}
|
||||
} else if (typeof comparisonValue === 'boolean' || typeof comparisonValue === 'number') {
|
||||
// For boolean/number comparison with array, check if array contains the value
|
||||
const matchFound = groundValue.includes(comparisonValue)
|
||||
if (displayType === 'show' && !matchFound) {
|
||||
inputParam.display = false
|
||||
}
|
||||
if (displayType === 'hide' && matchFound) {
|
||||
inputParam.display = false
|
||||
}
|
||||
} else if (typeof comparisonValue === 'object') {
|
||||
// For object comparison with array, use deep equality check
|
||||
const matchFound = groundValue.some((val) => isEqual(comparisonValue, val))
|
||||
if (displayType === 'show' && !matchFound) {
|
||||
inputParam.display = false
|
||||
}
|
||||
if (displayType === 'hide' && matchFound) {
|
||||
inputParam.display = false
|
||||
}
|
||||
}
|
||||
if (displayType === 'hide' && comparisonValue.includes(groundValue)) {
|
||||
inputParam.display = false
|
||||
}
|
||||
} else if (typeof comparisonValue === 'string') {
|
||||
if (displayType === 'show' && !(comparisonValue === groundValue || new RegExp(comparisonValue).test(groundValue))) {
|
||||
inputParam.display = false
|
||||
}
|
||||
if (displayType === 'hide' && (comparisonValue === groundValue || new RegExp(comparisonValue).test(groundValue))) {
|
||||
inputParam.display = false
|
||||
}
|
||||
} else if (typeof comparisonValue === 'boolean') {
|
||||
if (displayType === 'show' && comparisonValue !== groundValue) {
|
||||
inputParam.display = false
|
||||
}
|
||||
if (displayType === 'hide' && comparisonValue === groundValue) {
|
||||
inputParam.display = false
|
||||
}
|
||||
} else if (typeof comparisonValue === 'object') {
|
||||
if (displayType === 'show' && !isEqual(comparisonValue, groundValue)) {
|
||||
inputParam.display = false
|
||||
}
|
||||
if (displayType === 'hide' && isEqual(comparisonValue, groundValue)) {
|
||||
inputParam.display = false
|
||||
}
|
||||
} else if (typeof comparisonValue === 'number') {
|
||||
if (displayType === 'show' && comparisonValue !== groundValue) {
|
||||
inputParam.display = false
|
||||
}
|
||||
if (displayType === 'hide' && comparisonValue === groundValue) {
|
||||
inputParam.display = false
|
||||
} else {
|
||||
// Original logic for non-array groundValue
|
||||
if (Array.isArray(comparisonValue)) {
|
||||
if (displayType === 'show' && !comparisonValue.includes(groundValue)) {
|
||||
inputParam.display = false
|
||||
}
|
||||
if (displayType === 'hide' && comparisonValue.includes(groundValue)) {
|
||||
inputParam.display = false
|
||||
}
|
||||
} else if (typeof comparisonValue === 'string') {
|
||||
if (displayType === 'show' && !(comparisonValue === groundValue || new RegExp(comparisonValue).test(groundValue))) {
|
||||
inputParam.display = false
|
||||
}
|
||||
if (displayType === 'hide' && (comparisonValue === groundValue || new RegExp(comparisonValue).test(groundValue))) {
|
||||
inputParam.display = false
|
||||
}
|
||||
} else if (typeof comparisonValue === 'boolean') {
|
||||
if (displayType === 'show' && comparisonValue !== groundValue) {
|
||||
inputParam.display = false
|
||||
}
|
||||
if (displayType === 'hide' && comparisonValue === groundValue) {
|
||||
inputParam.display = false
|
||||
}
|
||||
} else if (typeof comparisonValue === 'object') {
|
||||
if (displayType === 'show' && !isEqual(comparisonValue, groundValue)) {
|
||||
inputParam.display = false
|
||||
}
|
||||
if (displayType === 'hide' && isEqual(comparisonValue, groundValue)) {
|
||||
inputParam.display = false
|
||||
}
|
||||
} else if (typeof comparisonValue === 'number') {
|
||||
if (displayType === 'show' && comparisonValue !== groundValue) {
|
||||
inputParam.display = false
|
||||
}
|
||||
if (displayType === 'hide' && comparisonValue === groundValue) {
|
||||
inputParam.display = false
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -28,6 +28,7 @@ import { getErrorMessage } from './error'
|
||||
|
||||
export const SOURCE_DOCUMENTS_PREFIX = '\n\n----FLOWISE_SOURCE_DOCUMENTS----\n\n'
|
||||
export const ARTIFACTS_PREFIX = '\n\n----FLOWISE_ARTIFACTS----\n\n'
|
||||
export const TOOL_ARGS_PREFIX = '\n\n----FLOWISE_TOOL_ARGS----\n\n'
|
||||
|
||||
export type AgentFinish = {
|
||||
returnValues: Record<string, any>
|
||||
@@ -444,9 +445,19 @@ export class AgentExecutor extends BaseChain<ChainValues, AgentExecutorOutput> {
|
||||
if (typeof toolOutput === 'string' && toolOutput.includes(ARTIFACTS_PREFIX)) {
|
||||
toolOutput = toolOutput.split(ARTIFACTS_PREFIX)[0]
|
||||
}
|
||||
let toolInput
|
||||
if (typeof toolOutput === 'string' && toolOutput.includes(TOOL_ARGS_PREFIX)) {
|
||||
const splitArray = toolOutput.split(TOOL_ARGS_PREFIX)
|
||||
toolOutput = splitArray[0]
|
||||
try {
|
||||
toolInput = JSON.parse(splitArray[1])
|
||||
} catch (e) {
|
||||
console.error('Error parsing tool input from tool')
|
||||
}
|
||||
}
|
||||
usedTools.push({
|
||||
tool: tool.name,
|
||||
toolInput: action.toolInput as any,
|
||||
toolInput: toolInput ?? (action.toolInput as any),
|
||||
toolOutput
|
||||
})
|
||||
} else {
|
||||
@@ -502,6 +513,10 @@ export class AgentExecutor extends BaseChain<ChainValues, AgentExecutorOutput> {
|
||||
console.error('Error parsing source documents from tool')
|
||||
}
|
||||
}
|
||||
if (typeof observation === 'string' && observation.includes(TOOL_ARGS_PREFIX)) {
|
||||
const observationArray = observation.split(TOOL_ARGS_PREFIX)
|
||||
observation = observationArray[0]
|
||||
}
|
||||
return { action, observation: observation ?? '' }
|
||||
})
|
||||
)
|
||||
@@ -610,6 +625,10 @@ export class AgentExecutor extends BaseChain<ChainValues, AgentExecutorOutput> {
|
||||
const observationArray = observation.split(ARTIFACTS_PREFIX)
|
||||
observation = observationArray[0]
|
||||
}
|
||||
if (typeof observation === 'string' && observation.includes(TOOL_ARGS_PREFIX)) {
|
||||
const observationArray = observation.split(TOOL_ARGS_PREFIX)
|
||||
observation = observationArray[0]
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof ToolInputParsingException) {
|
||||
if (this.handleParsingErrors === true) {
|
||||
|
||||
@@ -1215,3 +1215,68 @@ export const handleDocumentLoaderDocuments = async (loader: DocumentLoader, text
|
||||
|
||||
return docs
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if OAuth2 token is expired and refresh if needed
|
||||
* @param {string} credentialId
|
||||
* @param {ICommonObject} credentialData
|
||||
* @param {ICommonObject} options
|
||||
* @param {number} bufferTimeMs - Buffer time in milliseconds before expiry (default: 5 minutes)
|
||||
* @returns {Promise<ICommonObject>}
|
||||
*/
|
||||
export const refreshOAuth2Token = async (
|
||||
credentialId: string,
|
||||
credentialData: ICommonObject,
|
||||
options: ICommonObject,
|
||||
bufferTimeMs: number = 5 * 60 * 1000
|
||||
): Promise<ICommonObject> => {
|
||||
// Check if token is expired and refresh if needed
|
||||
if (credentialData.expires_at) {
|
||||
const expiryTime = new Date(credentialData.expires_at)
|
||||
const currentTime = new Date()
|
||||
|
||||
if (currentTime.getTime() > expiryTime.getTime() - bufferTimeMs) {
|
||||
if (!credentialData.refresh_token) {
|
||||
throw new Error('Access token is expired and no refresh token is available. Please re-authorize the credential.')
|
||||
}
|
||||
|
||||
try {
|
||||
// Import fetch dynamically to avoid issues
|
||||
const fetch = (await import('node-fetch')).default
|
||||
|
||||
// Call the refresh API endpoint
|
||||
const refreshResponse = await fetch(
|
||||
`${options.baseURL || 'http://localhost:3000'}/api/v1/oauth2-credential/refresh/${credentialId}`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
if (!refreshResponse.ok) {
|
||||
const errorData = await refreshResponse.text()
|
||||
throw new Error(`Failed to refresh token: ${refreshResponse.status} ${refreshResponse.statusText} - ${errorData}`)
|
||||
}
|
||||
|
||||
await refreshResponse.json()
|
||||
|
||||
// Get the updated credential data
|
||||
const updatedCredentialData = await getCredentialData(credentialId, options)
|
||||
|
||||
return updatedCredentialData
|
||||
} catch (error) {
|
||||
console.error('Failed to refresh access token:', error)
|
||||
throw new Error(
|
||||
`Failed to refresh access token: ${
|
||||
error instanceof Error ? error.message : 'Unknown error'
|
||||
}. Please re-authorize the credential.`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Token is not expired, return original data
|
||||
return credentialData
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user