From 34be9dbe8814ee5b2755812bc9fd1c83e097c9b2 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 25 Feb 2026 13:42:33 -0800 Subject: [PATCH 1/2] feat(confluence): return page content in get page version tool --- apps/docs/components/ui/icon-mapping.ts | 12 +-- .../docs/content/docs/en/tools/confluence.mdx | 5 ++ apps/docs/content/docs/en/tools/meta.json | 2 +- .../tools/confluence/page-versions/route.ts | 81 +++++++++++++------ apps/sim/tools/confluence/get_page_version.ts | 36 ++++++++- apps/sim/tools/confluence/utils.ts | 14 +++- 6 files changed, 116 insertions(+), 34 deletions(-) diff --git a/apps/docs/components/ui/icon-mapping.ts b/apps/docs/components/ui/icon-mapping.ts index ba0e2bf32f..8e274d3439 100644 --- a/apps/docs/components/ui/icon-mapping.ts +++ b/apps/docs/components/ui/icon-mapping.ts @@ -38,8 +38,8 @@ import { EyeIcon, FirecrawlIcon, FirefliesIcon, - GithubIcon, GitLabIcon, + GithubIcon, GmailIcon, GongIcon, GoogleBooksIcon, @@ -73,9 +73,9 @@ import { LinearIcon, LinkedInIcon, LinkupIcon, + MailServerIcon, MailchimpIcon, MailgunIcon, - MailServerIcon, Mem0Icon, MicrosoftDataverseIcon, MicrosoftExcelIcon, @@ -108,6 +108,8 @@ import { ResendIcon, RevenueCatIcon, S3Icon, + SQSIcon, + STTIcon, SalesforceIcon, SearchIcon, SendgridIcon, @@ -119,19 +121,17 @@ import { SimilarwebIcon, SlackIcon, SmtpIcon, - SQSIcon, SshIcon, - STTIcon, StagehandIcon, StripeIcon, SupabaseIcon, + TTSIcon, TavilyIcon, TelegramIcon, TextractIcon, TinybirdIcon, TranslateIcon, TrelloIcon, - TTSIcon, TwilioIcon, TypeformIcon, UpstashIcon, @@ -142,11 +142,11 @@ import { WhatsAppIcon, WikipediaIcon, WordpressIcon, - xIcon, YouTubeIcon, ZendeskIcon, ZepIcon, ZoomIcon, + xIcon, } from '@/components/icons' type IconComponent = ComponentType> diff --git a/apps/docs/content/docs/en/tools/confluence.mdx b/apps/docs/content/docs/en/tools/confluence.mdx index 7ee0f0e73e..58301d2891 100644 --- a/apps/docs/content/docs/en/tools/confluence.mdx +++ b/apps/docs/content/docs/en/tools/confluence.mdx @@ -326,6 +326,8 @@ Get details about a specific version of a Confluence page. | --------- | ---- | ----------- | | `ts` | string | ISO 8601 timestamp of the operation | | `pageId` | string | ID of the page | +| `title` | string | Page title at this version | +| `content` | string | Page content with HTML tags stripped at this version | | `version` | object | Detailed version information | | ↳ `number` | number | Version number | | ↳ `message` | string | Version message | @@ -336,6 +338,9 @@ Get details about a specific version of a Confluence page. | ↳ `collaborators` | array | List of collaborator account IDs for this version | | ↳ `prevVersion` | number | Previous version number | | ↳ `nextVersion` | number | Next version number | +| `body` | object | Raw page body content in storage format at this version | +| ↳ `value` | string | The content value in the specified format | +| ↳ `representation` | string | Content representation type | ### `confluence_list_page_properties` diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index cd896c4457..6f033e4df5 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -147,4 +147,4 @@ "zep", "zoom" ] -} +} \ No newline at end of file diff --git a/apps/sim/app/api/tools/confluence/page-versions/route.ts b/apps/sim/app/api/tools/confluence/page-versions/route.ts index 9d7c162060..e05db77820 100644 --- a/apps/sim/app/api/tools/confluence/page-versions/route.ts +++ b/apps/sim/app/api/tools/confluence/page-versions/route.ts @@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid' import { validateAlphanumericId, validateJiraCloudId } from '@/lib/core/security/input-validation' -import { getConfluenceCloudId } from '@/tools/confluence/utils' +import { cleanHtmlContent, getConfluenceCloudId } from '@/tools/confluence/utils' const logger = createLogger('ConfluencePageVersionsAPI') @@ -55,42 +55,77 @@ export async function POST(request: NextRequest) { return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 }) } - // If versionNumber is provided, get specific version + // If versionNumber is provided, get specific version with page content if (versionNumber !== undefined && versionNumber !== null) { - const url = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/pages/${pageId}/versions/${versionNumber}` + const versionUrl = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/pages/${pageId}/versions/${versionNumber}` + const pageUrl = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/pages/${pageId}?version=${versionNumber}&body-format=storage` logger.info(`Fetching version ${versionNumber} for page ${pageId}`) - const response = await fetch(url, { - method: 'GET', - headers: { - Accept: 'application/json', - Authorization: `Bearer ${accessToken}`, - }, - }) - - if (!response.ok) { - const errorData = await response.json().catch(() => null) + const [versionResponse, pageResponse] = await Promise.all([ + fetch(versionUrl, { + method: 'GET', + headers: { + Accept: 'application/json', + Authorization: `Bearer ${accessToken}`, + }, + }), + fetch(pageUrl, { + method: 'GET', + headers: { + Accept: 'application/json', + Authorization: `Bearer ${accessToken}`, + }, + }), + ]) + + if (!versionResponse.ok) { + const errorData = await versionResponse.json().catch(() => null) logger.error('Confluence API error response:', { - status: response.status, - statusText: response.statusText, + status: versionResponse.status, + statusText: versionResponse.statusText, error: JSON.stringify(errorData, null, 2), }) - const errorMessage = errorData?.message || `Failed to get page version (${response.status})` - return NextResponse.json({ error: errorMessage }, { status: response.status }) + const errorMessage = + errorData?.message || `Failed to get page version (${versionResponse.status})` + return NextResponse.json({ error: errorMessage }, { status: versionResponse.status }) } - const data = await response.json() + const versionData = await versionResponse.json() + + let title: string | null = null + let content: string | null = null + let body: Record | null = null + + if (pageResponse.ok) { + const pageData = await pageResponse.json() + title = pageData.title ?? null + body = pageData.body ?? null + + const rawContent = + pageData.body?.storage?.value || + pageData.body?.view?.value || + pageData.body?.atlas_doc_format?.value || + '' + if (rawContent) { + content = cleanHtmlContent(rawContent) + } + } else { + logger.warn(`Could not fetch page content for version ${versionNumber}: ${pageResponse.status}`) + } return NextResponse.json({ version: { - number: data.number, - message: data.message ?? null, - minorEdit: data.minorEdit ?? false, - authorId: data.authorId ?? null, - createdAt: data.createdAt ?? null, + number: versionData.number, + message: versionData.message ?? null, + minorEdit: versionData.minorEdit ?? false, + authorId: versionData.authorId ?? null, + createdAt: versionData.createdAt ?? null, }, pageId, + title, + content, + body, }) } // List all versions diff --git a/apps/sim/tools/confluence/get_page_version.ts b/apps/sim/tools/confluence/get_page_version.ts index c162e25465..dc496b38a2 100644 --- a/apps/sim/tools/confluence/get_page_version.ts +++ b/apps/sim/tools/confluence/get_page_version.ts @@ -1,4 +1,8 @@ -import { DETAILED_VERSION_OUTPUT_PROPERTIES, TIMESTAMP_OUTPUT } from '@/tools/confluence/types' +import { + BODY_FORMAT_PROPERTIES, + DETAILED_VERSION_OUTPUT_PROPERTIES, + TIMESTAMP_OUTPUT, +} from '@/tools/confluence/types' import type { ToolConfig } from '@/tools/types' export interface ConfluenceGetPageVersionParams { @@ -14,6 +18,8 @@ export interface ConfluenceGetPageVersionResponse { output: { ts: string pageId: string + title: string | null + content: string | null version: { number: number message: string | null @@ -25,6 +31,12 @@ export interface ConfluenceGetPageVersionResponse { prevVersion: number | null nextVersion: number | null } + body: { + storage?: { + value: string + representation: string + } + } | null } } @@ -100,6 +112,8 @@ export const confluenceGetPageVersionTool: ToolConfig< output: { ts: new Date().toISOString(), pageId: data.pageId ?? '', + title: data.title ?? null, + content: data.content ?? null, version: data.version ?? { number: 0, message: null, @@ -107,6 +121,7 @@ export const confluenceGetPageVersionTool: ToolConfig< authorId: null, createdAt: null, }, + body: data.body ?? null, }, } }, @@ -114,10 +129,29 @@ export const confluenceGetPageVersionTool: ToolConfig< outputs: { ts: TIMESTAMP_OUTPUT, pageId: { type: 'string', description: 'ID of the page' }, + title: { type: 'string', description: 'Page title at this version', optional: true }, + content: { + type: 'string', + description: 'Page content with HTML tags stripped at this version', + optional: true, + }, version: { type: 'object', description: 'Detailed version information', properties: DETAILED_VERSION_OUTPUT_PROPERTIES, }, + body: { + type: 'object', + description: 'Raw page body content in storage format at this version', + properties: { + storage: { + type: 'object', + description: 'Body in storage format (Confluence markup)', + properties: BODY_FORMAT_PROPERTIES, + optional: true, + }, + }, + optional: true, + }, }, } diff --git a/apps/sim/tools/confluence/utils.ts b/apps/sim/tools/confluence/utils.ts index 2f57929654..d7e55a2c56 100644 --- a/apps/sim/tools/confluence/utils.ts +++ b/apps/sim/tools/confluence/utils.ts @@ -56,13 +56,21 @@ function stripHtmlTags(html: string): string { return text.trim() } +/** + * Strips HTML tags and decodes HTML entities from raw Confluence content. + */ +export function cleanHtmlContent(rawContent: string): string { + let content = stripHtmlTags(rawContent) + content = decodeHtmlEntities(content) + content = content.replace(/\s+/g, ' ').trim() + return content +} + export function transformPageData(data: any) { const rawContent = data.body?.storage?.value || data.body?.view?.value || data.body?.atlas_doc_format?.value || '' - let cleanContent = stripHtmlTags(rawContent) - cleanContent = decodeHtmlEntities(cleanContent) - cleanContent = cleanContent.replace(/\s+/g, ' ').trim() + const cleanContent = cleanHtmlContent(rawContent) return { success: true, From 83d211ad1cb69369443257b5ed2dc573ee41a381 Mon Sep 17 00:00:00 2001 From: waleed Date: Wed, 25 Feb 2026 13:44:04 -0800 Subject: [PATCH 2/2] lint --- apps/docs/components/ui/icon-mapping.ts | 12 ++++++------ apps/docs/content/docs/en/tools/meta.json | 2 +- .../app/api/tools/confluence/page-versions/route.ts | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/apps/docs/components/ui/icon-mapping.ts b/apps/docs/components/ui/icon-mapping.ts index 8e274d3439..ba0e2bf32f 100644 --- a/apps/docs/components/ui/icon-mapping.ts +++ b/apps/docs/components/ui/icon-mapping.ts @@ -38,8 +38,8 @@ import { EyeIcon, FirecrawlIcon, FirefliesIcon, - GitLabIcon, GithubIcon, + GitLabIcon, GmailIcon, GongIcon, GoogleBooksIcon, @@ -73,9 +73,9 @@ import { LinearIcon, LinkedInIcon, LinkupIcon, - MailServerIcon, MailchimpIcon, MailgunIcon, + MailServerIcon, Mem0Icon, MicrosoftDataverseIcon, MicrosoftExcelIcon, @@ -108,8 +108,6 @@ import { ResendIcon, RevenueCatIcon, S3Icon, - SQSIcon, - STTIcon, SalesforceIcon, SearchIcon, SendgridIcon, @@ -121,17 +119,19 @@ import { SimilarwebIcon, SlackIcon, SmtpIcon, + SQSIcon, SshIcon, + STTIcon, StagehandIcon, StripeIcon, SupabaseIcon, - TTSIcon, TavilyIcon, TelegramIcon, TextractIcon, TinybirdIcon, TranslateIcon, TrelloIcon, + TTSIcon, TwilioIcon, TypeformIcon, UpstashIcon, @@ -142,11 +142,11 @@ import { WhatsAppIcon, WikipediaIcon, WordpressIcon, + xIcon, YouTubeIcon, ZendeskIcon, ZepIcon, ZoomIcon, - xIcon, } from '@/components/icons' type IconComponent = ComponentType> diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index 6f033e4df5..cd896c4457 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -147,4 +147,4 @@ "zep", "zoom" ] -} \ No newline at end of file +} diff --git a/apps/sim/app/api/tools/confluence/page-versions/route.ts b/apps/sim/app/api/tools/confluence/page-versions/route.ts index e05db77820..cdd77f4e76 100644 --- a/apps/sim/app/api/tools/confluence/page-versions/route.ts +++ b/apps/sim/app/api/tools/confluence/page-versions/route.ts @@ -111,7 +111,9 @@ export async function POST(request: NextRequest) { content = cleanHtmlContent(rawContent) } } else { - logger.warn(`Could not fetch page content for version ${versionNumber}: ${pageResponse.status}`) + logger.warn( + `Could not fetch page content for version ${versionNumber}: ${pageResponse.status}` + ) } return NextResponse.json({