Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d5659a3
fix(document-store): inject req.user into refresh body to prevent Typ…
maxtechera Mar 6, 2026
1325827
🔒 Security: Fix CVE-2026-27606 - Rollup path traversal vulnerability
Mar 10, 2026
4893117
style: remove trailing whitespace from MCP files
Mar 10, 2026
fd95a22
style: fix additional lint errors
Mar 10, 2026
07acddd
style: fix console.log line length lint errors
Mar 10, 2026
ae2638e
style: fix remaining prettier formatting issues
Mar 10, 2026
3cd4676
fix: upgrade zod to ^3.25.0 for MCP SDK compatibility
maxtechera Mar 11, 2026
902b6e2
fix: upgrade zod to ^3.25.0 for MCP SDK compatibility
maxtechera Mar 11, 2026
6c47607
fix(components): optimize AAIDomains loader memory for large datasets
diecoscai Mar 12, 2026
c55c910
fix(components): preserve domain_tags for contentFields compatibility
diecoscai Mar 12, 2026
84248a8
Merge pull request #1005 from the-answerai/fix/zod-mcp-compatibility
maxtechera Mar 12, 2026
dac6859
fix(documentstore): batch chunk saves to prevent OOM on large datasets
diecoscai Mar 12, 2026
e38a3e3
fix(documentstore): batch vector upsert with RecordManager guard
diecoscai Mar 12, 2026
801c074
style(documentstore): fix Prettier formatting in documentstore service
diecoscai Mar 12, 2026
c08042c
style(components): fix Prettier formatting in AAIDomains loader
diecoscai Mar 12, 2026
6f43038
fix(documentstore): batch pipeline to prevent OOM on large document sets
diecoscai Mar 12, 2026
b374ef7
Revert "fix(components): optimize AAIDomains loader memory for large …
diecoscai Mar 12, 2026
435ac85
Merge pull request #1008 from the-answerai/revert-1006-fix/aai-domain…
diecoscai Mar 12, 2026
eb992b9
Merge pull request #1004 from the-answerai/security/rollup-cve-2026-2…
maxtechera Mar 12, 2026
03fdb80
chore: removed old support links (#1010)
bradtaylorsf Mar 13, 2026
f9b38ac
Merge pull request #1001 from the-answerai/fix/agent-714-refresh-docs…
maxtechera Mar 13, 2026
8903768
fix: resolve build errors in components and server packages
maxtechera Mar 13, 2026
2c65b2c
Merge pull request #1011 from the-answerai/fix/build-errors-tsconfig-…
maxtechera Mar 13, 2026
b5dd547
fix: remove debug console.log statements that leak sensitive data
maxtechera Mar 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@
"nth-check": "2.1.1",
"path-to-regexp": "0.1.12",
"prismjs": "1.29.0",
"rollup": "4.45.0",
"rollup": "4.59.0",
"semver": "7.7.1",
"send": ">=0.19.0 <1.0.0",
"serve-static": ">=1.16.0",
Expand Down
3 changes: 1 addition & 2 deletions packages/components/credentials/AnswerAgentApi.credential.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ class AnswerAgentApi implements INodeCredential {
this.label = 'AnswerAgent API'
this.name = 'answerAgentApi'
this.version = 1.0
this.description =
'You can find your API key in <a target="_blank" href="/sidekick-studio/apikey">API Keys</a> settings'
this.description = 'You can find your API key in <a target="_blank" href="/sidekick-studio/apikey">API Keys</a> settings'
this.inputs = [
{
label: 'API Key',
Expand Down
31 changes: 2 additions & 29 deletions packages/components/nodes/tools/MCP/Confluence/ConfluenceMCP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,32 +101,13 @@ class Confluence_MCP implements INode {
}

async getTools(nodeData: INodeData, options: ICommonObject): Promise<Tool[]> {
console.log('[CONFLUENCE MCP DEBUG] ========== getTools START ==========')
console.log('[CONFLUENCE MCP DEBUG] Timestamp:', new Date().toISOString())
console.log('[CONFLUENCE MCP DEBUG] nodeData.credential ID:', nodeData?.credential || 'NONE')
try {
console.log('[CONFLUENCE MCP DEBUG] options keys:', Object.keys(options || {}).join(', '))
} catch (e) {
console.log('[CONFLUENCE MCP DEBUG] options keys: ERROR -', String(e))
}

console.time('[CONFLUENCE MCP DEBUG] getCredentialData')
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
console.timeEnd('[CONFLUENCE MCP DEBUG] getCredentialData')

console.log('[CONFLUENCE MCP DEBUG] credentialData keys:', Object.keys(credentialData || {}).join(', '))
const confluenceApiKey = getCredentialParam('accessToken', credentialData, nodeData)
const confluenceApiEmail = getCredentialParam('username', credentialData, nodeData)
const confluenceUrl = getCredentialParam('baseURL', credentialData, nodeData)

console.log('[CONFLUENCE MCP DEBUG] Credentials loaded:')
console.log('[CONFLUENCE MCP DEBUG] - apiKey exists:', !!confluenceApiKey, '(length:', confluenceApiKey?.length || 0, ')')
console.log('[CONFLUENCE MCP DEBUG] - email exists:', !!confluenceApiEmail, '(value:', confluenceApiEmail || 'MISSING', ')')
console.log('[CONFLUENCE MCP DEBUG] - url exists:', !!confluenceUrl, '(value:', confluenceUrl || 'MISSING', ')')


const packagePath = getNodeModulesPackagePath('@answerai/confluence-mcp/build/index.js')
console.log('[CONFLUENCE MCP DEBUG] Package path:', packagePath)


const serverParams = {
command: process.execPath,
args: [packagePath],
Expand All @@ -137,18 +118,10 @@ class Confluence_MCP implements INode {
}
}

console.log('[CONFLUENCE MCP DEBUG] Creating MCPToolkit with command:', serverParams.command)
const toolkit = new MCPToolkit(serverParams, 'stdio')

console.time('[CONFLUENCE MCP DEBUG] toolkit.initialize')
console.log('[CONFLUENCE MCP DEBUG] Calling toolkit.initialize() at', new Date().toISOString())
await toolkit.initialize()
console.timeEnd('[CONFLUENCE MCP DEBUG] toolkit.initialize')
console.log('[CONFLUENCE MCP DEBUG] toolkit.initialize() completed at', new Date().toISOString())

const tools = toolkit.tools ?? []
console.log('[CONFLUENCE MCP DEBUG] Tools loaded:', tools.length)
console.log('[CONFLUENCE MCP DEBUG] ========== getTools END ==========')

return tools
}
Expand Down
29 changes: 1 addition & 28 deletions packages/components/nodes/tools/MCP/Jira/JiraMCP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,31 +101,12 @@ class Jira_MCP implements INode {
}

async getTools(nodeData: INodeData, options: ICommonObject): Promise<Tool[]> {
console.log('[JIRA MCP DEBUG] ========== getTools START ==========')
console.log('[JIRA MCP DEBUG] Timestamp:', new Date().toISOString())
console.log('[JIRA MCP DEBUG] nodeData.credential ID:', nodeData?.credential || 'NONE')
try {
console.log('[JIRA MCP DEBUG] options keys:', Object.keys(options || {}).join(', '))
} catch (e) {
console.log('[JIRA MCP DEBUG] options keys: ERROR -', String(e))
}

console.time('[JIRA MCP DEBUG] getCredentialData')
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
console.timeEnd('[JIRA MCP DEBUG] getCredentialData')

console.log('[JIRA MCP DEBUG] credentialData keys:', Object.keys(credentialData || {}).join(', '))
const jiraApiKey = getCredentialParam('accessToken', credentialData, nodeData)
const jiraApiEmail = getCredentialParam('username', credentialData, nodeData)
const jiraUrl = getCredentialParam('host', credentialData, nodeData)

console.log('[JIRA MCP DEBUG] Credentials loaded:')
console.log('[JIRA MCP DEBUG] - apiKey exists:', !!jiraApiKey, '(length:', jiraApiKey?.length || 0, ')')
console.log('[JIRA MCP DEBUG] - email exists:', !!jiraApiEmail, '(value:', jiraApiEmail || 'MISSING', ')')
console.log('[JIRA MCP DEBUG] - url exists:', !!jiraUrl, '(value:', jiraUrl || 'MISSING', ')')


const packagePath = getNodeModulesPackagePath('@answerai/jira-mcp/build/index.js')
console.log('[JIRA MCP DEBUG] Package path:', packagePath)

const serverParams = {
command: process.execPath,
Expand All @@ -137,18 +118,10 @@ class Jira_MCP implements INode {
}
}

console.log('[JIRA MCP DEBUG] Creating MCPToolkit with command:', serverParams.command)
const toolkit = new MCPToolkit(serverParams, 'stdio')

console.time('[JIRA MCP DEBUG] toolkit.initialize')
console.log('[JIRA MCP DEBUG] Calling toolkit.initialize() at', new Date().toISOString())
await toolkit.initialize()
console.timeEnd('[JIRA MCP DEBUG] toolkit.initialize')
console.log('[JIRA MCP DEBUG] toolkit.initialize() completed at', new Date().toISOString())

const tools = toolkit.tools ?? []
console.log('[JIRA MCP DEBUG] Tools loaded:', tools.length)
console.log('[JIRA MCP DEBUG] ========== getTools END ==========')

return tools
}
Expand Down
30 changes: 2 additions & 28 deletions packages/components/nodes/tools/MCP/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,38 +89,14 @@ export class MCPToolkit extends BaseToolkit {

async initialize() {
if (this._tools === null) {
console.log('[MCP TOOLKIT DEBUG] ========== initialize START ==========')
console.log('[MCP TOOLKIT DEBUG] Timestamp:', new Date().toISOString())
console.log('[MCP TOOLKIT DEBUG] Transport type:', this.transportType)
console.log('[MCP TOOLKIT DEBUG] Server params command:', this.serverParams.command)
console.log('[MCP TOOLKIT DEBUG] Server params env keys:', Object.keys(this.serverParams.env || {}).join(', '))

try {
console.time('[MCP TOOLKIT DEBUG] createClient')
console.log('[MCP TOOLKIT DEBUG] Creating client at', new Date().toISOString())
this.client = await this.createClient()
console.timeEnd('[MCP TOOLKIT DEBUG] createClient')
console.log('[MCP TOOLKIT DEBUG] Client created successfully at', new Date().toISOString())

console.time('[MCP TOOLKIT DEBUG] tools/list request')
console.log('[MCP TOOLKIT DEBUG] Requesting tools/list at', new Date().toISOString())
this._tools = await this.client.request({ method: 'tools/list' }, ListToolsResultSchema)
console.timeEnd('[MCP TOOLKIT DEBUG] tools/list request')
console.log('[MCP TOOLKIT DEBUG] tools/list received at', new Date().toISOString())
console.log('[MCP TOOLKIT DEBUG] Received', this._tools.tools?.length || 0, 'tools')

console.time('[MCP TOOLKIT DEBUG] get_tools')
this.tools = await this.get_tools()
console.timeEnd('[MCP TOOLKIT DEBUG] get_tools')

// Close the initial client after initialization
console.log('[MCP TOOLKIT DEBUG] Closing client at', new Date().toISOString())
await this.client.close()
console.log('[MCP TOOLKIT DEBUG] Client closed at', new Date().toISOString())
console.log('[MCP TOOLKIT DEBUG] ========== initialize SUCCESS ==========')
} catch (error) {
console.error('[MCP TOOLKIT DEBUG] ========== initialize FAILED ==========')
console.error('[MCP TOOLKIT DEBUG] Error timestamp:', new Date().toISOString())
console.error('MCP Toolkit: Failed to initialize, setting empty tools:', error)
this._tools = { tools: [] }
this.tools = []
Expand All @@ -132,8 +108,6 @@ export class MCPToolkit extends BaseToolkit {
}
}
}
} else {
console.log('[MCP TOOLKIT DEBUG] initialize called but _tools already set, skipping')
}
}

Expand All @@ -154,11 +128,11 @@ export class MCPToolkit extends BaseToolkit {
})
})
const res = await Promise.allSettled(toolsPromises)
const errors = res.filter((r:any) => r.status === 'rejected')
const errors = res.filter((r: any) => r.status === 'rejected')
if (errors.length !== 0) {
console.error('MCP Tools failed to be resolved', errors)
}
const successes = res.filter((r:any) => r.status === 'fulfilled').map((r:any ) => r.value)
const successes = res.filter((r: any) => r.status === 'fulfilled').map((r: any) => r.value)
return successes
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@
"xlsx": "0.18.5",
"youtube-data-mcp-server": "^1.0.16",
"youtube-transcript": "^1.2.1",
"zod": "3.22.4",
"zod": "^3.25.0",
"zod-to-json-schema": "^3.21.4"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions packages/components/src/storageUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ const _deleteLocalFolderRecursive = async (directory: string, deleteParentChatfl
await fs.promises.access(directory)

if (deleteParentChatflowFolder) {
await fs.promises.rmdir(directory, { recursive: true })
await fs.promises.rm(directory, { recursive: true, force: true })
}

// Get stats of the path to determine if it's a file or directory
Expand All @@ -691,7 +691,7 @@ const _deleteLocalFolderRecursive = async (directory: string, deleteParentChatfl
}

// Delete the directory itself after emptying it
await fs.promises.rmdir(directory, { recursive: true })
await fs.promises.rm(directory, { recursive: true, force: true })
} else {
// If it's a file, delete it directly
await fs.promises.unlink(directory)
Expand Down
16 changes: 0 additions & 16 deletions packages/components/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -635,43 +635,27 @@ const decryptCredentialData = async (encryptedData: string): Promise<ICommonObje
* @returns {Promise<ICommonObject>}
*/
export const getCredentialData = async (selectedCredentialId: string, options: ICommonObject): Promise<ICommonObject> => {
console.log('[getCredentialData DEBUG] Called with ID:', selectedCredentialId)
console.log('[getCredentialData DEBUG] Timestamp:', new Date().toISOString())

const appDataSource = options.appDataSource as DataSource
const databaseEntities = options.databaseEntities as IDatabaseEntity

try {
if (!selectedCredentialId) {
console.log('[getCredentialData DEBUG] No credential ID provided, returning empty')
return {}
}

console.time('[getCredentialData DEBUG] Database query')
const credential = await appDataSource.getRepository(databaseEntities['Credential']).findOneBy({
id: selectedCredentialId
})
console.timeEnd('[getCredentialData DEBUG] Database query')

if (!credential) {
console.log('[getCredentialData DEBUG] Credential not found in database for ID:', selectedCredentialId)
return {}
}

console.log('[getCredentialData DEBUG] Credential found, name:', credential?.name || 'N/A')
console.log('[getCredentialData DEBUG] Credential workspaceId:', credential?.workspaceId || 'N/A')

// Decrypt credentialData
console.time('[getCredentialData DEBUG] Decrypt credential')
const decryptedCredentialData = await decryptCredentialData(credential.encryptedData)
console.timeEnd('[getCredentialData DEBUG] Decrypt credential')

console.log('[getCredentialData DEBUG] Decrypted data keys:', Object.keys(decryptedCredentialData).join(', '))
console.log('[getCredentialData DEBUG] Returning credential data')

return decryptedCredentialData
} catch (e) {
console.error('[getCredentialData DEBUG] ERROR:', e)
throw new Error(e)
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/components/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"lib": ["ES2020", "ES2021.String"],
"lib": ["ES2022", "ES2021.String"],
"experimentalDecorators": true /* Enable experimental support for TC39 stage 2 draft decorators. */,
"emitDecoratorMetadata": true /* Emit design-type metadata for decorated declarations in source files. */,
"target": "ES2020", // or higher
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/docs/community/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ Yes! Sharing how you use AnswerAgentAI is a way of contribution. Export your cha

## 🐞 Report Bugs

Found an issue? [Report it](https://airtable.com/appIQM0aGhytwZPAO/pagWTeVKuMvGPcK2F/form).
Found an issue? [Report it](https://github.com/the-answerai/theanswer/issues).
4 changes: 0 additions & 4 deletions packages/docs/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -725,10 +725,6 @@ const config: Config = {
{
to: '/docs/community',
label: 'Help Center'
},
{
label: 'Contact Support',
href: 'https://calendly.com/lastrev/answeragent-demo'
}
]
},
Expand Down
2 changes: 1 addition & 1 deletion packages/embed-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"aai-embed": "workspace:*",
"eslint": "8.37.0",
"react": "18.2.0",
"rollup": "3.29.5",
"rollup": "3.30.0",
"rollup-plugin-serve": "3.0.0",
"rollup-plugin-typescript-paths": "1.4.0",
"tslib": "^2.8.1",
Expand Down
1 change: 1 addition & 0 deletions packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
"express-mysql-session": "^3.0.3",
"express-rate-limit": "^6.9.0",
"express-session": "^1.18.1",
"@langchain/core": "0.3.61",
"flowise-components": "workspace:^",
"flowise-nim-container-manager": "^1.0.11",
"flowise-ui": "workspace:^",
Expand Down
11 changes: 2 additions & 9 deletions packages/server/src/controllers/chatflows/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,7 @@ const getAllChatflows = async (req: Request, res: Response, next: NextFunction)
const workspaceIds = workspaceIdsQuery ? workspaceIdsQuery.split(',').filter(Boolean) : undefined
const workspaceId = workspaceIds ? undefined : req.user?.activeWorkspaceId

const apiResponse = await chatflowsService.getAllChatflows(
req.query?.type as ChatflowType,
workspaceId,
page,
limit,
workspaceIds
)
const apiResponse = await chatflowsService.getAllChatflows(req.query?.type as ChatflowType, workspaceId, page, limit, workspaceIds)
return res.json(apiResponse)
} catch (error) {
next(error)
Expand Down Expand Up @@ -135,8 +129,7 @@ const getChatflowById = async (req: Request, res: Response, next: NextFunction)
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: chatflowsController.getChatflowById - id not provided!`)
}
const apiResponse = await chatflowsService.getChatflowById(req.params.id)
const assignedWorkspaces =
(req.user as { assignedWorkspaces?: Array<{ id: string }> } | undefined)?.assignedWorkspaces || []
const assignedWorkspaces = (req.user as { assignedWorkspaces?: Array<{ id: string }> } | undefined)?.assignedWorkspaces || []
const hasWorkspaceAccess = apiResponse.workspaceId
? assignedWorkspaces.some((ws: { id: string }) => ws.id === apiResponse.workspaceId)
: false
Expand Down
3 changes: 2 additions & 1 deletion packages/server/src/controllers/documentstore/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,8 @@ const refreshDocStoreMiddleware = async (req: Request, res: Response, next: Next
)
}
const subscriptionId = req.user?.activeOrganizationSubscriptionId || ''
const body = req.body
const body = req.body || {}
body.user = req.user
const apiResponse = await documentStoreService.refreshDocStoreMiddleware(
req.params.id,
body,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ const createInternalPrediction = async (req: Request, res: Response, next: NextF
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Chatflow ${req.params.id} not found`)
}

const assignedWorkspaces =
(req.user as { assignedWorkspaces?: Array<{ id: string }> } | undefined)?.assignedWorkspaces || []
const assignedWorkspaces = (req.user as { assignedWorkspaces?: Array<{ id: string }> } | undefined)?.assignedWorkspaces || []
const hasWorkspaceAccess = chatflow.workspaceId
? assignedWorkspaces.some((ws: { id: string }) => ws.id === chatflow.workspaceId)
: false
Expand Down
Loading
Loading