chore: import upstream snapshot with attribution
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
+123
View File
@@ -0,0 +1,123 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceAddLabelParams {
accessToken: string
domain: string
pageId: string
labelName: string
prefix?: string
cloudId?: string
}
export interface ConfluenceAddLabelResponse {
success: boolean
output: {
ts: string
pageId: string
labelName: string
labelId: string
}
}
export const confluenceAddLabelTool: ToolConfig<
ConfluenceAddLabelParams,
ConfluenceAddLabelResponse
> = {
id: 'confluence_add_label',
name: 'Confluence Add Label',
description: 'Add a label to a Confluence page for organization and categorization.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence page ID to add the label to',
},
labelName: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name of the label to add',
},
prefix: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Label prefix: global (default), my, team, or system',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/labels',
method: 'POST',
headers: (params: ConfluenceAddLabelParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceAddLabelParams) => ({
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId?.trim(),
labelName: params.labelName?.trim(),
prefix: params.prefix || 'global',
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
pageId: data.pageId ?? '',
labelName: data.labelName ?? data.name ?? '',
labelId: data.id ?? '',
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
pageId: {
type: 'string',
description: 'Page ID that the label was added to',
},
labelName: {
type: 'string',
description: 'Name of the added label',
},
labelId: {
type: 'string',
description: 'ID of the added label',
},
},
}
@@ -0,0 +1,151 @@
import {
CONTENT_BODY_OUTPUT_PROPERTIES,
TIMESTAMP_OUTPUT,
VERSION_OUTPUT_PROPERTIES,
} from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceCreateBlogPostParams {
accessToken: string
domain: string
spaceId: string
title: string
content: string
status?: string
cloudId?: string
}
export interface ConfluenceCreateBlogPostResponse {
success: boolean
output: {
ts: string
id: string
title: string
status: string | null
spaceId: string
authorId: string | null
body: Record<string, any> | null
version: Record<string, any> | null
webUrl: string | null
}
}
export const confluenceCreateBlogPostTool: ToolConfig<
ConfluenceCreateBlogPostParams,
ConfluenceCreateBlogPostResponse
> = {
id: 'confluence_create_blogpost',
name: 'Confluence Create Blog Post',
description: 'Create a new blog post in a Confluence space.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
spaceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the space to create the blog post in',
},
title: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Title of the blog post',
},
content: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Blog post content in Confluence storage format (HTML)',
},
status: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Blog post status: current (default) or draft',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/blogposts',
method: 'POST',
headers: (params: ConfluenceCreateBlogPostParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceCreateBlogPostParams) => ({
domain: params.domain,
accessToken: params.accessToken,
spaceId: params.spaceId?.trim(),
title: params.title,
content: params.content,
status: params.status || 'current',
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
id: data.id ?? '',
title: data.title ?? '',
status: data.status ?? null,
spaceId: data.spaceId ?? '',
authorId: data.authorId ?? null,
body: data.body ?? null,
version: data.version ?? null,
webUrl: data.webUrl ?? data._links?.webui ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
id: { type: 'string', description: 'Created blog post ID' },
title: { type: 'string', description: 'Blog post title' },
status: { type: 'string', description: 'Blog post status', optional: true },
spaceId: { type: 'string', description: 'Space ID' },
authorId: { type: 'string', description: 'Author account ID', optional: true },
body: {
type: 'object',
description: 'Blog post body content',
properties: CONTENT_BODY_OUTPUT_PROPERTIES,
optional: true,
},
version: {
type: 'object',
description: 'Blog post version information',
properties: VERSION_OUTPUT_PROPERTIES,
optional: true,
},
webUrl: { type: 'string', description: 'URL to view the blog post', optional: true },
},
}
+106
View File
@@ -0,0 +1,106 @@
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceCreateCommentParams {
accessToken: string
domain: string
pageId: string
comment: string
cloudId?: string
}
export interface ConfluenceCreateCommentResponse {
success: boolean
output: {
ts: string
commentId: string
pageId: string
}
}
export const confluenceCreateCommentTool: ToolConfig<
ConfluenceCreateCommentParams,
ConfluenceCreateCommentResponse
> = {
id: 'confluence_create_comment',
name: 'Confluence Create Comment',
description: 'Add a comment to a Confluence page.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence page ID to comment on',
},
comment: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Comment text in Confluence storage format',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/comments',
method: 'POST',
headers: (params: ConfluenceCreateCommentParams) => {
return {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
body: (params: ConfluenceCreateCommentParams) => {
return {
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
pageId: params.pageId,
comment: params.comment,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
commentId: data.id,
pageId: data.pageId || '',
},
}
},
outputs: {
ts: { type: 'string', description: 'Timestamp of creation' },
commentId: { type: 'string', description: 'Created comment ID' },
pageId: { type: 'string', description: 'Page ID' },
},
}
+151
View File
@@ -0,0 +1,151 @@
import { CONTENT_BODY_OUTPUT_PROPERTIES, VERSION_OUTPUT_PROPERTIES } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceCreatePageParams {
accessToken: string
domain: string
spaceId: string
title: string
content: string
parentId?: string
cloudId?: string
}
export interface ConfluenceCreatePageResponse {
success: boolean
output: {
ts: string
pageId: string
title: string
status: string | null
spaceId: string | null
parentId: string | null
body: Record<string, any> | null
version: Record<string, any> | null
url: string
}
}
export const confluenceCreatePageTool: ToolConfig<
ConfluenceCreatePageParams,
ConfluenceCreatePageResponse
> = {
id: 'confluence_create_page',
name: 'Confluence Create Page',
description: 'Create a new page in a Confluence space.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
spaceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence space ID where the page will be created',
},
title: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Title of the new page',
},
content: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Page content in Confluence storage format (HTML)',
},
parentId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Parent page ID if creating a child page',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/create-page',
method: 'POST',
headers: (params: ConfluenceCreatePageParams) => {
return {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
body: (params: ConfluenceCreatePageParams) => {
return {
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
spaceId: params.spaceId,
title: params.title,
content: params.content,
parentId: params.parentId,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
pageId: data.id ?? '',
title: data.title ?? '',
status: data.status ?? null,
spaceId: data.spaceId ?? null,
parentId: data.parentId ?? null,
body: data.body ?? null,
version: data.version ?? null,
url: data.url || data._links?.webui || '',
},
}
},
outputs: {
ts: { type: 'string', description: 'Timestamp of creation' },
pageId: { type: 'string', description: 'Created page ID' },
title: { type: 'string', description: 'Page title' },
status: { type: 'string', description: 'Page status', optional: true },
spaceId: { type: 'string', description: 'Space ID', optional: true },
parentId: { type: 'string', description: 'Parent page ID', optional: true },
body: {
type: 'object',
description: 'Page body content',
properties: CONTENT_BODY_OUTPUT_PROPERTIES,
optional: true,
},
version: {
type: 'object',
description: 'Page version information',
properties: VERSION_OUTPUT_PROPERTIES,
optional: true,
},
url: { type: 'string', description: 'Page URL' },
},
}
@@ -0,0 +1,127 @@
import { TIMESTAMP_OUTPUT, VERSION_OUTPUT_PROPERTIES } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceCreatePagePropertyParams {
accessToken: string
domain: string
pageId: string
key: string
value: any
cloudId?: string
}
export interface ConfluenceCreatePagePropertyResponse {
success: boolean
output: {
ts: string
pageId: string
propertyId: string
key: string
value: any
version: {
number: number
} | null
}
}
export const confluenceCreatePagePropertyTool: ToolConfig<
ConfluenceCreatePagePropertyParams,
ConfluenceCreatePagePropertyResponse
> = {
id: 'confluence_create_page_property',
name: 'Confluence Create Page Property',
description: 'Create a new custom property (metadata) on a Confluence page.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the page to add the property to',
},
key: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The key/name for the property',
},
value: {
type: 'json',
required: true,
visibility: 'user-or-llm',
description: 'The value for the property (can be any JSON value)',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/page-properties',
method: 'POST',
headers: (params: ConfluenceCreatePagePropertyParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceCreatePagePropertyParams) => ({
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId?.trim(),
key: params.key,
value: params.value,
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
pageId: data.pageId ?? '',
propertyId: data.id ?? '',
key: data.key ?? '',
value: data.value ?? null,
version: data.version ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
pageId: { type: 'string', description: 'ID of the page' },
propertyId: { type: 'string', description: 'ID of the created property' },
key: { type: 'string', description: 'Property key' },
value: { type: 'json', description: 'Property value' },
version: {
type: 'object',
description: 'Version information',
properties: VERSION_OUTPUT_PROPERTIES,
optional: true,
},
},
}
+134
View File
@@ -0,0 +1,134 @@
import { SPACE_DESCRIPTION_OUTPUT_PROPERTIES, TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceCreateSpaceParams {
accessToken: string
domain: string
name: string
key: string
description?: string
cloudId?: string
}
export interface ConfluenceCreateSpaceResponse {
success: boolean
output: {
ts: string
spaceId: string
name: string
key: string
type: string
status: string
url: string
homepageId: string | null
description: { value: string; representation: string } | null
}
}
export const confluenceCreateSpaceTool: ToolConfig<
ConfluenceCreateSpaceParams,
ConfluenceCreateSpaceResponse
> = {
id: 'confluence_create_space',
name: 'Confluence Create Space',
description: 'Create a new Confluence space.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name for the new space',
},
key: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Unique key for the space (uppercase, no spaces)',
},
description: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Description for the new space',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/space',
method: 'POST',
headers: (params: ConfluenceCreateSpaceParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceCreateSpaceParams) => ({
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
name: params.name,
key: params.key,
description: params.description,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
spaceId: data.id ?? '',
name: data.name ?? '',
key: data.key ?? '',
type: data.type ?? '',
status: data.status ?? '',
url: data._links?.webui ?? '',
homepageId: data.homepageId ?? null,
description: data.description ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
spaceId: { type: 'string', description: 'Created space ID' },
name: { type: 'string', description: 'Space name' },
key: { type: 'string', description: 'Space key' },
type: { type: 'string', description: 'Space type' },
status: { type: 'string', description: 'Space status' },
url: { type: 'string', description: 'URL to view the space' },
homepageId: { type: 'string', description: 'Homepage ID', optional: true },
description: {
type: 'object',
description: 'Space description',
properties: SPACE_DESCRIPTION_OUTPUT_PROPERTIES,
optional: true,
},
},
}
@@ -0,0 +1,118 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceCreateSpacePropertyParams {
accessToken: string
domain: string
spaceId: string
key: string
value?: unknown
cloudId?: string
}
export interface ConfluenceCreateSpacePropertyResponse {
success: boolean
output: {
ts: string
propertyId: string
key: string
value: unknown
spaceId: string
}
}
export const confluenceCreateSpacePropertyTool: ToolConfig<
ConfluenceCreateSpacePropertyParams,
ConfluenceCreateSpacePropertyResponse
> = {
id: 'confluence_create_space_property',
name: 'Confluence Create Space Property',
description: 'Create a property on a Confluence space.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
spaceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Space ID to create the property on',
},
key: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Property key/name',
},
value: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description: 'Property value (JSON)',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/space-properties',
method: 'POST',
headers: (params: ConfluenceCreateSpacePropertyParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceCreateSpacePropertyParams) => ({
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
spaceId: params.spaceId,
action: 'create',
key: params.key,
value: params.value,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
propertyId: data.propertyId ?? '',
key: data.key ?? '',
value: data.value ?? null,
spaceId: data.spaceId ?? '',
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
propertyId: { type: 'string', description: 'Created property ID' },
key: { type: 'string', description: 'Property key' },
value: { type: 'json', description: 'Property value' },
spaceId: { type: 'string', description: 'Space ID' },
},
}
@@ -0,0 +1,97 @@
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceDeleteAttachmentParams {
accessToken: string
domain: string
attachmentId: string
cloudId?: string
}
export interface ConfluenceDeleteAttachmentResponse {
success: boolean
output: {
ts: string
attachmentId: string
deleted: boolean
}
}
export const confluenceDeleteAttachmentTool: ToolConfig<
ConfluenceDeleteAttachmentParams,
ConfluenceDeleteAttachmentResponse
> = {
id: 'confluence_delete_attachment',
name: 'Confluence Delete Attachment',
description: 'Delete an attachment from a Confluence page (moves to trash).',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
attachmentId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence attachment ID to delete',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/attachment',
method: 'DELETE',
headers: (params: ConfluenceDeleteAttachmentParams) => {
return {
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
body: (params: ConfluenceDeleteAttachmentParams) => {
return {
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
attachmentId: params.attachmentId,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
attachmentId: data.attachmentId || '',
deleted: true,
},
}
},
outputs: {
ts: { type: 'string', description: 'Timestamp of deletion' },
attachmentId: { type: 'string', description: 'Deleted attachment ID' },
deleted: { type: 'boolean', description: 'Deletion status' },
},
}
@@ -0,0 +1,95 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceDeleteBlogPostParams {
accessToken: string
domain: string
blogPostId: string
cloudId?: string
}
export interface ConfluenceDeleteBlogPostResponse {
success: boolean
output: {
ts: string
blogPostId: string
deleted: boolean
}
}
export const confluenceDeleteBlogPostTool: ToolConfig<
ConfluenceDeleteBlogPostParams,
ConfluenceDeleteBlogPostResponse
> = {
id: 'confluence_delete_blogpost',
name: 'Confluence Delete Blog Post',
description: 'Delete a Confluence blog post.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
blogPostId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the blog post to delete',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/blogposts',
method: 'DELETE',
headers: (params: ConfluenceDeleteBlogPostParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceDeleteBlogPostParams) => ({
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
blogPostId: params.blogPostId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
blogPostId: data.blogPostId ?? '',
deleted: true,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
blogPostId: { type: 'string', description: 'Deleted blog post ID' },
deleted: { type: 'boolean', description: 'Deletion status' },
},
}
@@ -0,0 +1,97 @@
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceDeleteCommentParams {
accessToken: string
domain: string
commentId: string
cloudId?: string
}
export interface ConfluenceDeleteCommentResponse {
success: boolean
output: {
ts: string
commentId: string
deleted: boolean
}
}
export const confluenceDeleteCommentTool: ToolConfig<
ConfluenceDeleteCommentParams,
ConfluenceDeleteCommentResponse
> = {
id: 'confluence_delete_comment',
name: 'Confluence Delete Comment',
description: 'Delete a comment from a Confluence page.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
commentId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence comment ID to delete',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/comment',
method: 'DELETE',
headers: (params: ConfluenceDeleteCommentParams) => {
return {
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
body: (params: ConfluenceDeleteCommentParams) => {
return {
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
commentId: params.commentId,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
commentId: data.commentId || '',
deleted: true,
},
}
},
outputs: {
ts: { type: 'string', description: 'Timestamp of deletion' },
commentId: { type: 'string', description: 'Deleted comment ID' },
deleted: { type: 'boolean', description: 'Deletion status' },
},
}
+114
View File
@@ -0,0 +1,114 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceDeleteLabelParams {
accessToken: string
domain: string
pageId: string
labelName: string
cloudId?: string
}
export interface ConfluenceDeleteLabelResponse {
success: boolean
output: {
ts: string
pageId: string
labelName: string
deleted: boolean
}
}
export const confluenceDeleteLabelTool: ToolConfig<
ConfluenceDeleteLabelParams,
ConfluenceDeleteLabelResponse
> = {
id: 'confluence_delete_label',
name: 'Confluence Delete Label',
description: 'Remove a label from a Confluence page.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence page ID to remove the label from',
},
labelName: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name of the label to remove',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/labels',
method: 'DELETE',
headers: (params: ConfluenceDeleteLabelParams) => ({
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceDeleteLabelParams) => ({
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId?.trim(),
labelName: params.labelName?.trim(),
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
pageId: data.pageId ?? '',
labelName: data.labelName ?? '',
deleted: true,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
pageId: {
type: 'string',
description: 'Page ID the label was removed from',
},
labelName: {
type: 'string',
description: 'Name of the removed label',
},
deleted: {
type: 'boolean',
description: 'Deletion status',
},
},
}
+107
View File
@@ -0,0 +1,107 @@
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceDeletePageParams {
accessToken: string
domain: string
pageId: string
purge?: boolean
cloudId?: string
}
export interface ConfluenceDeletePageResponse {
success: boolean
output: {
ts: string
pageId: string
deleted: boolean
}
}
export const confluenceDeletePageTool: ToolConfig<
ConfluenceDeletePageParams,
ConfluenceDeletePageResponse
> = {
id: 'confluence_delete_page',
name: 'Confluence Delete Page',
description:
'Delete a Confluence page. By default moves to trash; use purge=true to permanently delete.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence page ID to delete',
},
purge: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description:
'If true, permanently deletes the page instead of moving to trash (default: false)',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: (params: ConfluenceDeletePageParams) => '/api/tools/confluence/page',
method: 'DELETE',
headers: (params: ConfluenceDeletePageParams) => {
return {
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
body: (params: ConfluenceDeletePageParams) => {
return {
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId,
purge: params.purge || false,
cloudId: params.cloudId,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
pageId: data.pageId || '',
deleted: true,
},
}
},
outputs: {
ts: { type: 'string', description: 'Timestamp of deletion' },
pageId: { type: 'string', description: 'Deleted page ID' },
deleted: { type: 'boolean', description: 'Deletion status' },
},
}
@@ -0,0 +1,105 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceDeletePagePropertyParams {
accessToken: string
domain: string
pageId: string
propertyId: string
cloudId?: string
}
export interface ConfluenceDeletePagePropertyResponse {
success: boolean
output: {
ts: string
pageId: string
propertyId: string
deleted: boolean
}
}
export const confluenceDeletePagePropertyTool: ToolConfig<
ConfluenceDeletePagePropertyParams,
ConfluenceDeletePagePropertyResponse
> = {
id: 'confluence_delete_page_property',
name: 'Confluence Delete Page Property',
description: 'Delete a content property from a Confluence page by its property ID.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the page containing the property',
},
propertyId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the property to delete',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/page-properties',
method: 'DELETE',
headers: (params: ConfluenceDeletePagePropertyParams) => ({
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceDeletePagePropertyParams) => ({
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId?.trim(),
propertyId: params.propertyId?.trim(),
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
pageId: data.pageId ?? '',
propertyId: data.propertyId ?? '',
deleted: true,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
pageId: { type: 'string', description: 'ID of the page' },
propertyId: { type: 'string', description: 'ID of the deleted property' },
deleted: { type: 'boolean', description: 'Deletion status' },
},
}
+108
View File
@@ -0,0 +1,108 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceDeleteSpaceParams {
accessToken: string
domain: string
spaceId: string
cloudId?: string
}
export interface ConfluenceDeleteSpaceResponse {
success: boolean
output: {
ts: string
spaceId: string
deleted: boolean
longTaskId?: string
longTaskStatusLink?: string
}
}
export const confluenceDeleteSpaceTool: ToolConfig<
ConfluenceDeleteSpaceParams,
ConfluenceDeleteSpaceResponse
> = {
id: 'confluence_delete_space',
name: 'Confluence Delete Space',
description: 'Delete a Confluence space.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
spaceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the space to delete',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/space',
method: 'DELETE',
headers: (params: ConfluenceDeleteSpaceParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceDeleteSpaceParams) => ({
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
spaceId: params.spaceId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
spaceId: data.spaceId ?? '',
deleted: true,
longTaskId: data.longTaskId,
longTaskStatusLink: data.longTaskStatusLink,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
spaceId: { type: 'string', description: 'Deleted space ID' },
deleted: { type: 'boolean', description: 'Deletion status' },
longTaskId: {
type: 'string',
description:
'ID of the long-running deletion task; poll Confluence long-task API to track completion',
},
longTaskStatusLink: {
type: 'string',
description: 'Relative link to the long-task status endpoint',
},
},
}
@@ -0,0 +1,107 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceDeleteSpacePropertyParams {
accessToken: string
domain: string
spaceId: string
propertyId: string
cloudId?: string
}
export interface ConfluenceDeleteSpacePropertyResponse {
success: boolean
output: {
ts: string
spaceId: string
propertyId: string
deleted: boolean
}
}
export const confluenceDeleteSpacePropertyTool: ToolConfig<
ConfluenceDeleteSpacePropertyParams,
ConfluenceDeleteSpacePropertyResponse
> = {
id: 'confluence_delete_space_property',
name: 'Confluence Delete Space Property',
description: 'Delete a property from a Confluence space.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
spaceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Space ID the property belongs to',
},
propertyId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Property ID to delete',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/space-properties',
method: 'POST',
headers: (params: ConfluenceDeleteSpacePropertyParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceDeleteSpacePropertyParams) => ({
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
spaceId: params.spaceId,
action: 'delete',
propertyId: params.propertyId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
spaceId: data.spaceId ?? '',
propertyId: data.propertyId ?? '',
deleted: true,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
spaceId: { type: 'string', description: 'Space ID' },
propertyId: { type: 'string', description: 'Deleted property ID' },
deleted: { type: 'boolean', description: 'Deletion status' },
},
}
+144
View File
@@ -0,0 +1,144 @@
import {
CONTENT_BODY_OUTPUT_PROPERTIES,
TIMESTAMP_OUTPUT,
VERSION_OUTPUT_PROPERTIES,
} from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceGetBlogPostParams {
accessToken: string
domain: string
blogPostId: string
bodyFormat?: string
cloudId?: string
}
export interface ConfluenceGetBlogPostResponse {
success: boolean
output: {
ts: string
id: string
title: string
status: string | null
spaceId: string | null
authorId: string | null
createdAt: string | null
version: {
number: number
message?: string
createdAt?: string
} | null
body: {
storage?: { value: string }
} | null
webUrl: string | null
}
}
export const confluenceGetBlogPostTool: ToolConfig<
ConfluenceGetBlogPostParams,
ConfluenceGetBlogPostResponse
> = {
id: 'confluence_get_blogpost',
name: 'Confluence Get Blog Post',
description: 'Get a specific Confluence blog post by ID, including its content.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
blogPostId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the blog post to retrieve',
},
bodyFormat: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Format for blog post body: storage, atlas_doc_format, or view',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/blogposts',
method: 'POST',
headers: (params: ConfluenceGetBlogPostParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceGetBlogPostParams) => ({
domain: params.domain,
accessToken: params.accessToken,
blogPostId: params.blogPostId?.trim(),
bodyFormat: params.bodyFormat || 'storage',
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
id: data.id ?? '',
title: data.title ?? '',
status: data.status ?? null,
spaceId: data.spaceId ?? null,
authorId: data.authorId ?? null,
createdAt: data.createdAt ?? null,
version: data.version ?? null,
body: data.body ?? null,
webUrl: data.webUrl ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
id: { type: 'string', description: 'Blog post ID' },
title: { type: 'string', description: 'Blog post title' },
status: { type: 'string', description: 'Blog post status', optional: true },
spaceId: { type: 'string', description: 'Space ID', optional: true },
authorId: { type: 'string', description: 'Author account ID', optional: true },
createdAt: { type: 'string', description: 'Creation timestamp', optional: true },
version: {
type: 'object',
description: 'Version information',
properties: VERSION_OUTPUT_PROPERTIES,
optional: true,
},
body: {
type: 'object',
description: 'Blog post body content in requested format(s)',
properties: CONTENT_BODY_OUTPUT_PROPERTIES,
optional: true,
},
webUrl: { type: 'string', description: 'URL to view the blog post', optional: true },
},
}
@@ -0,0 +1,126 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceGetPageAncestorsParams {
accessToken: string
domain: string
pageId: string
limit?: number
cloudId?: string
}
export interface ConfluenceGetPageAncestorsResponse {
success: boolean
output: {
ts: string
pageId: string
ancestors: Array<{
id: string
title: string
status: string | null
spaceId: string | null
webUrl: string | null
}>
}
}
export const confluenceGetPageAncestorsTool: ToolConfig<
ConfluenceGetPageAncestorsParams,
ConfluenceGetPageAncestorsResponse
> = {
id: 'confluence_get_page_ancestors',
name: 'Confluence Get Page Ancestors',
description:
'Get the ancestor (parent) pages of a specific Confluence page. Returns the full hierarchy from the page up to the root.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the page to get ancestors for',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of ancestors to return (default: 25, max: 250)',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/page-ancestors',
method: 'POST',
headers: (params: ConfluenceGetPageAncestorsParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceGetPageAncestorsParams) => ({
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId?.trim(),
limit: params.limit ? Number(params.limit) : 25,
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
pageId: data.pageId ?? '',
ancestors: data.ancestors ?? [],
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
pageId: {
type: 'string',
description: 'ID of the page whose ancestors were retrieved',
},
ancestors: {
type: 'array',
description: 'Array of ancestor pages, ordered from direct parent to root',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Ancestor page ID' },
title: { type: 'string', description: 'Ancestor page title' },
status: { type: 'string', description: 'Page status', optional: true },
spaceId: { type: 'string', description: 'Space ID', optional: true },
webUrl: { type: 'string', description: 'URL to view the page', optional: true },
},
},
},
},
}
@@ -0,0 +1,143 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceGetPageChildrenParams {
accessToken: string
domain: string
pageId: string
limit?: number
cursor?: string
cloudId?: string
}
export interface ConfluenceGetPageChildrenResponse {
success: boolean
output: {
ts: string
parentId: string
children: Array<{
id: string
title: string
status: string | null
spaceId: string | null
childPosition: number | null
webUrl: string | null
}>
nextCursor: string | null
}
}
export const confluenceGetPageChildrenTool: ToolConfig<
ConfluenceGetPageChildrenParams,
ConfluenceGetPageChildrenResponse
> = {
id: 'confluence_get_page_children',
name: 'Confluence Get Page Children',
description:
'Get all child pages of a specific Confluence page. Useful for navigating page hierarchies.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the parent page to get children from',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of child pages to return (default: 50, max: 250)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response to get the next page of results',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/page-children',
method: 'POST',
headers: (params: ConfluenceGetPageChildrenParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceGetPageChildrenParams) => ({
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId?.trim(),
limit: params.limit ? Number(params.limit) : 50,
cursor: params.cursor,
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
parentId: data.parentId ?? '',
children: data.children ?? [],
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
parentId: {
type: 'string',
description: 'ID of the parent page',
},
children: {
type: 'array',
description: 'Array of child pages',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Child page ID' },
title: { type: 'string', description: 'Child page title' },
status: { type: 'string', description: 'Page status', optional: true },
spaceId: { type: 'string', description: 'Space ID', optional: true },
childPosition: { type: 'number', description: 'Position among siblings', optional: true },
webUrl: { type: 'string', description: 'URL to view the page', optional: true },
},
},
},
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
@@ -0,0 +1,147 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceGetPageDescendantsParams {
accessToken: string
domain: string
pageId: string
limit?: number
cursor?: string
cloudId?: string
}
export interface ConfluenceGetPageDescendantsResponse {
success: boolean
output: {
ts: string
descendants: Array<{
id: string
title: string
type: string | null
status: string | null
spaceId: string | null
parentId: string | null
childPosition: number | null
depth: number | null
}>
pageId: string
nextCursor: string | null
}
}
export const confluenceGetPageDescendantsTool: ToolConfig<
ConfluenceGetPageDescendantsParams,
ConfluenceGetPageDescendantsResponse
> = {
id: 'confluence_get_page_descendants',
name: 'Confluence Get Page Descendants',
description: 'Get all descendants of a Confluence page recursively.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Page ID to get descendants for',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of descendants to return (default: 50, max: 250)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/page-descendants',
method: 'POST',
headers: (params: ConfluenceGetPageDescendantsParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceGetPageDescendantsParams) => ({
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
pageId: params.pageId,
limit: params.limit,
cursor: params.cursor,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
descendants: data.descendants || [],
pageId: data.pageId ?? '',
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
descendants: {
type: 'array',
description: 'Array of descendant pages',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Page ID' },
title: { type: 'string', description: 'Page title' },
type: {
type: 'string',
description: 'Content type (page, whiteboard, database, etc.)',
optional: true,
},
status: { type: 'string', description: 'Page status', optional: true },
spaceId: { type: 'string', description: 'Space ID', optional: true },
parentId: { type: 'string', description: 'Parent page ID', optional: true },
childPosition: { type: 'number', description: 'Position among siblings', optional: true },
depth: { type: 'number', description: 'Depth in the hierarchy', optional: true },
},
},
},
pageId: { type: 'string', description: 'Parent page ID' },
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
@@ -0,0 +1,157 @@
import {
BODY_FORMAT_PROPERTIES,
DETAILED_VERSION_OUTPUT_PROPERTIES,
TIMESTAMP_OUTPUT,
} from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceGetPageVersionParams {
accessToken: string
domain: string
pageId: string
versionNumber: number
cloudId?: string
}
export interface ConfluenceGetPageVersionResponse {
success: boolean
output: {
ts: string
pageId: string
title: string | null
content: string | null
version: {
number: number
message: string | null
minorEdit: boolean
authorId: string | null
createdAt: string | null
contentTypeModified: boolean | null
collaborators: string[] | null
prevVersion: number | null
nextVersion: number | null
}
body: {
storage?: {
value: string
representation: string
}
} | null
}
}
export const confluenceGetPageVersionTool: ToolConfig<
ConfluenceGetPageVersionParams,
ConfluenceGetPageVersionResponse
> = {
id: 'confluence_get_page_version',
name: 'Confluence Get Page Version',
description: 'Get details about a specific version of a Confluence page.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the page',
},
versionNumber: {
type: 'number',
required: true,
visibility: 'user-or-llm',
description: 'The version number to retrieve (e.g., 1, 2, 3)',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/page-versions',
method: 'POST',
headers: (params: ConfluenceGetPageVersionParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceGetPageVersionParams) => ({
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId?.trim(),
versionNumber: Number(params.versionNumber),
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
pageId: data.pageId ?? '',
title: data.title ?? null,
content: data.content ?? null,
version: data.version ?? {
number: 0,
message: null,
minorEdit: false,
authorId: null,
createdAt: null,
},
body: data.body ?? null,
},
}
},
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,
},
},
}
@@ -0,0 +1,143 @@
import { PAGE_ITEM_PROPERTIES, TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceGetPagesByLabelParams {
accessToken: string
domain: string
labelId: string
limit?: number
cursor?: string
cloudId?: string
}
export interface ConfluenceGetPagesByLabelResponse {
success: boolean
output: {
ts: string
labelId: string
pages: Array<{
id: string
title: string
status: string | null
spaceId: string | null
parentId: string | null
authorId: string | null
createdAt: string | null
version: {
number: number
message?: string
createdAt?: string
} | null
}>
nextCursor: string | null
}
}
export const confluenceGetPagesByLabelTool: ToolConfig<
ConfluenceGetPagesByLabelParams,
ConfluenceGetPagesByLabelResponse
> = {
id: 'confluence_get_pages_by_label',
name: 'Confluence Get Pages by Label',
description: 'Retrieve all pages that have a specific label applied.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
labelId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the label to get pages for',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of pages to return (default: 50, max: 250)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: (params: ConfluenceGetPagesByLabelParams) => {
const query = new URLSearchParams({
domain: params.domain,
accessToken: params.accessToken,
labelId: params.labelId,
limit: String(params.limit || 50),
})
if (params.cursor) {
query.set('cursor', params.cursor)
}
if (params.cloudId) {
query.set('cloudId', params.cloudId)
}
return `/api/tools/confluence/pages-by-label?${query.toString()}`
},
method: 'GET',
headers: (params: ConfluenceGetPagesByLabelParams) => ({
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
labelId: data.labelId ?? '',
pages: data.pages ?? [],
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
labelId: { type: 'string', description: 'ID of the label' },
pages: {
type: 'array',
description: 'Array of pages with this label',
items: {
type: 'object',
properties: PAGE_ITEM_PROPERTIES,
},
},
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
+136
View File
@@ -0,0 +1,136 @@
import { SPACE_DESCRIPTION_OUTPUT_PROPERTIES, TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceGetSpaceParams {
accessToken: string
domain: string
spaceId: string
cloudId?: string
}
export interface ConfluenceGetSpaceResponse {
success: boolean
output: {
ts: string
spaceId: string
name: string
key: string
type: string
status: string
url: string
authorId: string | null
createdAt: string | null
homepageId: string | null
description: {
value: string
representation: string
} | null
}
}
export const confluenceGetSpaceTool: ToolConfig<
ConfluenceGetSpaceParams,
ConfluenceGetSpaceResponse
> = {
id: 'confluence_get_space',
name: 'Confluence Get Space',
description: 'Get details about a specific Confluence space.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
spaceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence space ID to retrieve',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: (params: ConfluenceGetSpaceParams) => {
const query = new URLSearchParams({
domain: params.domain,
accessToken: params.accessToken,
spaceId: params.spaceId,
})
if (params.cloudId) {
query.set('cloudId', params.cloudId)
}
return `/api/tools/confluence/space?${query.toString()}`
},
method: 'GET',
headers: (params: ConfluenceGetSpaceParams) => {
return {
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
spaceId: data.id,
name: data.name,
key: data.key,
type: data.type,
status: data.status,
url: data._links?.webui || '',
authorId: data.authorId ?? null,
createdAt: data.createdAt ?? null,
homepageId: data.homepageId ?? null,
description: data.description ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
spaceId: { type: 'string', description: 'Space ID' },
name: { type: 'string', description: 'Space name' },
key: { type: 'string', description: 'Space key' },
type: { type: 'string', description: 'Space type (global, personal)' },
status: { type: 'string', description: 'Space status (current, archived)' },
url: { type: 'string', description: 'URL to view the space in Confluence' },
authorId: { type: 'string', description: 'Account ID of the space creator', optional: true },
createdAt: {
type: 'string',
description: 'ISO 8601 timestamp when the space was created',
optional: true,
},
homepageId: { type: 'string', description: 'ID of the space homepage', optional: true },
description: {
type: 'object',
description: 'Space description content',
properties: SPACE_DESCRIPTION_OUTPUT_PROPERTIES,
optional: true,
},
},
}
+130
View File
@@ -0,0 +1,130 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceGetTaskParams {
accessToken: string
domain: string
taskId: string
cloudId?: string
}
export interface ConfluenceGetTaskResponse {
success: boolean
output: {
ts: string
id: string
localId: string | null
spaceId: string | null
pageId: string | null
blogPostId: string | null
status: string
body: string | null
createdBy: string | null
assignedTo: string | null
completedBy: string | null
createdAt: string | null
updatedAt: string | null
dueAt: string | null
completedAt: string | null
}
}
export const confluenceGetTaskTool: ToolConfig<ConfluenceGetTaskParams, ConfluenceGetTaskResponse> =
{
id: 'confluence_get_task',
name: 'Confluence Get Task',
description: 'Get a specific Confluence inline task by ID.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
taskId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the task to retrieve',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/tasks',
method: 'POST',
headers: (params: ConfluenceGetTaskParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceGetTaskParams) => ({
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
taskId: params.taskId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
const task = data.task || data
return {
success: true,
output: {
ts: new Date().toISOString(),
id: task.id ?? '',
localId: task.localId ?? null,
spaceId: task.spaceId ?? null,
pageId: task.pageId ?? null,
blogPostId: task.blogPostId ?? null,
status: task.status ?? '',
body: task.body ?? null,
createdBy: task.createdBy ?? null,
assignedTo: task.assignedTo ?? null,
completedBy: task.completedBy ?? null,
createdAt: task.createdAt ?? null,
updatedAt: task.updatedAt ?? null,
dueAt: task.dueAt ?? null,
completedAt: task.completedAt ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
id: { type: 'string', description: 'Task ID' },
localId: { type: 'string', description: 'Local task ID', optional: true },
spaceId: { type: 'string', description: 'Space ID', optional: true },
pageId: { type: 'string', description: 'Page ID', optional: true },
blogPostId: { type: 'string', description: 'Blog post ID', optional: true },
status: { type: 'string', description: 'Task status (complete or incomplete)' },
body: { type: 'string', description: 'Task body content in storage format', optional: true },
createdBy: { type: 'string', description: 'Creator account ID', optional: true },
assignedTo: { type: 'string', description: 'Assignee account ID', optional: true },
completedBy: { type: 'string', description: 'Completer account ID', optional: true },
createdAt: { type: 'string', description: 'Creation timestamp', optional: true },
updatedAt: { type: 'string', description: 'Last update timestamp', optional: true },
dueAt: { type: 'string', description: 'Due date', optional: true },
completedAt: { type: 'string', description: 'Completion timestamp', optional: true },
},
}
+113
View File
@@ -0,0 +1,113 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceGetUserParams {
accessToken: string
domain: string
accountId: string
cloudId?: string
}
export interface ConfluenceGetUserResponse {
success: boolean
output: {
ts: string
accountId: string
displayName: string
email: string | null
accountType: string | null
profilePicture: string | null
publicName: string | null
}
}
export const confluenceGetUserTool: ToolConfig<ConfluenceGetUserParams, ConfluenceGetUserResponse> =
{
id: 'confluence_get_user',
name: 'Confluence Get User',
description: 'Get display name and profile info for a Confluence user by account ID.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
accountId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The Atlassian account ID of the user to look up',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/user',
method: 'POST',
headers: (params: ConfluenceGetUserParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceGetUserParams) => ({
domain: params.domain,
accessToken: params.accessToken,
accountId: params.accountId?.trim(),
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
accountId: data.accountId ?? '',
displayName: data.displayName ?? '',
email: data.email ?? null,
accountType: data.accountType ?? null,
profilePicture: data.profilePicture?.path ?? null,
publicName: data.publicName ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
accountId: { type: 'string', description: 'Atlassian account ID of the user' },
displayName: { type: 'string', description: 'Display name of the user' },
email: { type: 'string', description: 'Email address of the user', optional: true },
accountType: {
type: 'string',
description: 'Account type (e.g., atlassian, app, customer)',
optional: true,
},
profilePicture: {
type: 'string',
description: 'Path to the user profile picture',
optional: true,
},
publicName: { type: 'string', description: 'Public name of the user', optional: true },
},
}
+108
View File
@@ -0,0 +1,108 @@
import { confluenceAddLabelTool } from '@/tools/confluence/add_label'
import { confluenceCreateBlogPostTool } from '@/tools/confluence/create_blogpost'
import { confluenceCreateCommentTool } from '@/tools/confluence/create_comment'
import { confluenceCreatePageTool } from '@/tools/confluence/create_page'
import { confluenceCreatePagePropertyTool } from '@/tools/confluence/create_page_property'
import { confluenceCreateSpaceTool } from '@/tools/confluence/create_space'
import { confluenceCreateSpacePropertyTool } from '@/tools/confluence/create_space_property'
import { confluenceDeleteAttachmentTool } from '@/tools/confluence/delete_attachment'
import { confluenceDeleteBlogPostTool } from '@/tools/confluence/delete_blogpost'
import { confluenceDeleteCommentTool } from '@/tools/confluence/delete_comment'
import { confluenceDeleteLabelTool } from '@/tools/confluence/delete_label'
import { confluenceDeletePageTool } from '@/tools/confluence/delete_page'
import { confluenceDeletePagePropertyTool } from '@/tools/confluence/delete_page_property'
import { confluenceDeleteSpaceTool } from '@/tools/confluence/delete_space'
import { confluenceDeleteSpacePropertyTool } from '@/tools/confluence/delete_space_property'
import { confluenceGetBlogPostTool } from '@/tools/confluence/get_blogpost'
import { confluenceGetPageAncestorsTool } from '@/tools/confluence/get_page_ancestors'
import { confluenceGetPageChildrenTool } from '@/tools/confluence/get_page_children'
import { confluenceGetPageDescendantsTool } from '@/tools/confluence/get_page_descendants'
import { confluenceGetPageVersionTool } from '@/tools/confluence/get_page_version'
import { confluenceGetPagesByLabelTool } from '@/tools/confluence/get_pages_by_label'
import { confluenceGetSpaceTool } from '@/tools/confluence/get_space'
import { confluenceGetTaskTool } from '@/tools/confluence/get_task'
import { confluenceGetUserTool } from '@/tools/confluence/get_user'
import { confluenceListAttachmentsTool } from '@/tools/confluence/list_attachments'
import { confluenceListBlogPostsTool } from '@/tools/confluence/list_blogposts'
import { confluenceListBlogPostsInSpaceTool } from '@/tools/confluence/list_blogposts_in_space'
import { confluenceListCommentsTool } from '@/tools/confluence/list_comments'
import { confluenceListLabelsTool } from '@/tools/confluence/list_labels'
import { confluenceListPagePropertiesTool } from '@/tools/confluence/list_page_properties'
import { confluenceListPageVersionsTool } from '@/tools/confluence/list_page_versions'
import { confluenceListPagesInSpaceTool } from '@/tools/confluence/list_pages_in_space'
import { confluenceListSpaceLabelsTool } from '@/tools/confluence/list_space_labels'
import { confluenceListSpacePermissionsTool } from '@/tools/confluence/list_space_permissions'
import { confluenceListSpacePropertiesTool } from '@/tools/confluence/list_space_properties'
import { confluenceListSpacesTool } from '@/tools/confluence/list_spaces'
import { confluenceListTasksTool } from '@/tools/confluence/list_tasks'
import { confluenceRetrieveTool } from '@/tools/confluence/retrieve'
import { confluenceSearchTool } from '@/tools/confluence/search'
import { confluenceSearchInSpaceTool } from '@/tools/confluence/search_in_space'
import { confluenceUpdateTool } from '@/tools/confluence/update'
import { confluenceUpdateBlogPostTool } from '@/tools/confluence/update_blogpost'
import { confluenceUpdateCommentTool } from '@/tools/confluence/update_comment'
import { confluenceUpdateSpaceTool } from '@/tools/confluence/update_space'
import { confluenceUpdateTaskTool } from '@/tools/confluence/update_task'
import { confluenceUploadAttachmentTool } from '@/tools/confluence/upload_attachment'
export {
// Page Tools
confluenceRetrieveTool,
confluenceUpdateTool,
confluenceCreatePageTool,
confluenceDeletePageTool,
confluenceListPagesInSpaceTool,
confluenceGetPageChildrenTool,
confluenceGetPageAncestorsTool,
confluenceGetPageDescendantsTool,
// Page Version Tools
confluenceListPageVersionsTool,
confluenceGetPageVersionTool,
// Page Properties Tools
confluenceListPagePropertiesTool,
confluenceCreatePagePropertyTool,
confluenceDeletePagePropertyTool,
// Blog Post Tools
confluenceListBlogPostsTool,
confluenceGetBlogPostTool,
confluenceCreateBlogPostTool,
confluenceUpdateBlogPostTool,
confluenceDeleteBlogPostTool,
confluenceListBlogPostsInSpaceTool,
// Search Tools
confluenceSearchTool,
confluenceSearchInSpaceTool,
// Comment Tools
confluenceCreateCommentTool,
confluenceListCommentsTool,
confluenceUpdateCommentTool,
confluenceDeleteCommentTool,
// Attachment Tools
confluenceListAttachmentsTool,
confluenceDeleteAttachmentTool,
confluenceUploadAttachmentTool,
// Label Tools
confluenceListLabelsTool,
confluenceAddLabelTool,
confluenceDeleteLabelTool,
confluenceGetPagesByLabelTool,
confluenceListSpaceLabelsTool,
// User Tools
confluenceGetUserTool,
// Space Tools
confluenceGetSpaceTool,
confluenceCreateSpaceTool,
confluenceUpdateSpaceTool,
confluenceDeleteSpaceTool,
confluenceListSpacesTool,
// Space Property Tools
confluenceListSpacePropertiesTool,
confluenceCreateSpacePropertyTool,
confluenceDeleteSpacePropertyTool,
// Space Permission Tools
confluenceListSpacePermissionsTool,
// Task Tools
confluenceListTasksTool,
confluenceGetTaskTool,
confluenceUpdateTaskTool,
}
@@ -0,0 +1,128 @@
import { ATTACHMENTS_OUTPUT, TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceListAttachmentsParams {
accessToken: string
domain: string
pageId: string
limit?: number
cursor?: string
cloudId?: string
}
export interface ConfluenceListAttachmentsResponse {
success: boolean
output: {
ts: string
attachments: Array<{
id: string
title: string
fileSize: number
mediaType: string
downloadUrl: string
}>
nextCursor: string | null
}
}
export const confluenceListAttachmentsTool: ToolConfig<
ConfluenceListAttachmentsParams,
ConfluenceListAttachmentsResponse
> = {
id: 'confluence_list_attachments',
name: 'Confluence List Attachments',
description: 'List all attachments on a Confluence page.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence page ID to list attachments from',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of attachments to return (default: 50, max: 250)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: (params: ConfluenceListAttachmentsParams) => {
const query = new URLSearchParams({
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId,
limit: String(params.limit || 50),
})
if (params.cursor) {
query.set('cursor', params.cursor)
}
if (params.cloudId) {
query.set('cloudId', params.cloudId)
}
return `/api/tools/confluence/attachments?${query.toString()}`
},
method: 'GET',
headers: (params: ConfluenceListAttachmentsParams) => {
return {
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
attachments: data.attachments || [],
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
attachments: ATTACHMENTS_OUTPUT,
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
+167
View File
@@ -0,0 +1,167 @@
import { TIMESTAMP_OUTPUT, VERSION_OUTPUT_PROPERTIES } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceListBlogPostsParams {
accessToken: string
domain: string
limit?: number
status?: string
sort?: string
cursor?: string
cloudId?: string
}
export interface ConfluenceListBlogPostsResponse {
success: boolean
output: {
ts: string
blogPosts: Array<{
id: string
title: string
status: string | null
spaceId: string | null
authorId: string | null
createdAt: string | null
version: {
number: number
message?: string
createdAt?: string
} | null
webUrl: string | null
}>
nextCursor: string | null
}
}
export const confluenceListBlogPostsTool: ToolConfig<
ConfluenceListBlogPostsParams,
ConfluenceListBlogPostsResponse
> = {
id: 'confluence_list_blogposts',
name: 'Confluence List Blog Posts',
description: 'List all blog posts across all accessible Confluence spaces.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of blog posts to return (default: 25, max: 250)',
},
status: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by status: current, archived, trashed, or draft',
},
sort: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Sort order: created-date, -created-date, modified-date, -modified-date, title, -title',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: (params: ConfluenceListBlogPostsParams) => {
const query = new URLSearchParams({
domain: params.domain,
accessToken: params.accessToken,
limit: String(params.limit || 25),
})
if (params.status) {
query.set('status', params.status)
}
if (params.sort) {
query.set('sort', params.sort)
}
if (params.cursor) {
query.set('cursor', params.cursor)
}
if (params.cloudId) {
query.set('cloudId', params.cloudId)
}
return `/api/tools/confluence/blogposts?${query.toString()}`
},
method: 'GET',
headers: (params: ConfluenceListBlogPostsParams) => ({
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
blogPosts: data.blogPosts ?? [],
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
blogPosts: {
type: 'array',
description: 'Array of blog posts',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Blog post ID' },
title: { type: 'string', description: 'Blog post title' },
status: { type: 'string', description: 'Blog post status', optional: true },
spaceId: { type: 'string', description: 'Space ID', optional: true },
authorId: { type: 'string', description: 'Author account ID', optional: true },
createdAt: { type: 'string', description: 'Creation timestamp', optional: true },
version: {
type: 'object',
description: 'Version information',
properties: VERSION_OUTPUT_PROPERTIES,
optional: true,
},
webUrl: { type: 'string', description: 'URL to view the blog post', optional: true },
},
},
},
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
@@ -0,0 +1,178 @@
import {
CONTENT_BODY_OUTPUT_PROPERTIES,
TIMESTAMP_OUTPUT,
VERSION_OUTPUT_PROPERTIES,
} from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceListBlogPostsInSpaceParams {
accessToken: string
domain: string
spaceId: string
limit?: number
status?: string
bodyFormat?: string
cursor?: string
cloudId?: string
}
export interface ConfluenceListBlogPostsInSpaceResponse {
success: boolean
output: {
ts: string
blogPosts: Array<{
id: string
title: string
status: string | null
spaceId: string | null
authorId: string | null
createdAt: string | null
version: {
number: number
message?: string
createdAt?: string
} | null
body: {
storage?: { value: string }
} | null
webUrl: string | null
}>
nextCursor: string | null
}
}
export const confluenceListBlogPostsInSpaceTool: ToolConfig<
ConfluenceListBlogPostsInSpaceParams,
ConfluenceListBlogPostsInSpaceResponse
> = {
id: 'confluence_list_blogposts_in_space',
name: 'Confluence List Blog Posts in Space',
description: 'List all blog posts within a specific Confluence space.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
spaceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the Confluence space to list blog posts from',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of blog posts to return (default: 25, max: 250)',
},
status: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by status: current, archived, trashed, or draft',
},
bodyFormat: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Format for blog post body: storage, atlas_doc_format, or view',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/space-blogposts',
method: 'POST',
headers: (params: ConfluenceListBlogPostsInSpaceParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceListBlogPostsInSpaceParams) => ({
domain: params.domain,
accessToken: params.accessToken,
spaceId: params.spaceId?.trim(),
limit: params.limit ? Number(params.limit) : 25,
status: params.status,
bodyFormat: params.bodyFormat,
cursor: params.cursor,
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
blogPosts: data.blogPosts ?? [],
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
blogPosts: {
type: 'array',
description: 'Array of blog posts in the space',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Blog post ID' },
title: { type: 'string', description: 'Blog post title' },
status: { type: 'string', description: 'Blog post status', optional: true },
spaceId: { type: 'string', description: 'Space ID', optional: true },
authorId: { type: 'string', description: 'Author account ID', optional: true },
createdAt: { type: 'string', description: 'Creation timestamp', optional: true },
version: {
type: 'object',
description: 'Version information',
properties: VERSION_OUTPUT_PROPERTIES,
optional: true,
},
body: {
type: 'object',
description: 'Blog post body content',
properties: CONTENT_BODY_OUTPUT_PROPERTIES,
optional: true,
},
webUrl: { type: 'string', description: 'URL to view the blog post', optional: true },
},
},
},
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
+138
View File
@@ -0,0 +1,138 @@
import { COMMENTS_OUTPUT, TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceListCommentsParams {
accessToken: string
domain: string
pageId: string
limit?: number
bodyFormat?: string
cursor?: string
cloudId?: string
}
export interface ConfluenceListCommentsResponse {
success: boolean
output: {
ts: string
comments: Array<{
id: string
body: string
createdAt: string
authorId: string
}>
nextCursor: string | null
}
}
export const confluenceListCommentsTool: ToolConfig<
ConfluenceListCommentsParams,
ConfluenceListCommentsResponse
> = {
id: 'confluence_list_comments',
name: 'Confluence List Comments',
description: 'List all comments on a Confluence page.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence page ID to list comments from',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of comments to return (default: 25)',
},
bodyFormat: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Format for the comment body: storage, atlas_doc_format, view, or export_view (default: storage)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: (params: ConfluenceListCommentsParams) => {
const query = new URLSearchParams({
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId,
limit: String(params.limit || 25),
})
if (params.bodyFormat) {
query.set('bodyFormat', params.bodyFormat)
}
if (params.cursor) {
query.set('cursor', params.cursor)
}
if (params.cloudId) {
query.set('cloudId', params.cloudId)
}
return `/api/tools/confluence/comments?${query.toString()}`
},
method: 'GET',
headers: (params: ConfluenceListCommentsParams) => {
return {
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
comments: data.comments || [],
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
comments: COMMENTS_OUTPUT,
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
+133
View File
@@ -0,0 +1,133 @@
import { LABEL_ITEM_PROPERTIES } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceListLabelsParams {
accessToken: string
domain: string
pageId: string
limit?: number
cursor?: string
cloudId?: string
}
export interface ConfluenceListLabelsResponse {
success: boolean
output: {
ts: string
labels: Array<{
id: string
name: string
prefix: string
}>
nextCursor: string | null
}
}
export const confluenceListLabelsTool: ToolConfig<
ConfluenceListLabelsParams,
ConfluenceListLabelsResponse
> = {
id: 'confluence_list_labels',
name: 'Confluence List Labels',
description: 'List all labels on a Confluence page.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence page ID to list labels from',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of labels to return (default: 25, max: 250)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: (params: ConfluenceListLabelsParams) => {
const query = new URLSearchParams({
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId,
limit: String(params.limit || 25),
})
if (params.cursor) {
query.set('cursor', params.cursor)
}
if (params.cloudId) {
query.set('cloudId', params.cloudId)
}
return `/api/tools/confluence/labels?${query.toString()}`
},
method: 'GET',
headers: (params: ConfluenceListLabelsParams) => {
return {
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
labels: data.labels || [],
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: { type: 'string', description: 'Timestamp of retrieval' },
labels: {
type: 'array',
description: 'Array of labels on the page',
items: {
type: 'object',
properties: LABEL_ITEM_PROPERTIES,
},
},
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
@@ -0,0 +1,149 @@
import { TIMESTAMP_OUTPUT, VERSION_OUTPUT_PROPERTIES } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceListPagePropertiesParams {
accessToken: string
domain: string
pageId: string
limit?: number
cursor?: string
cloudId?: string
}
export interface ConfluenceListPagePropertiesResponse {
success: boolean
output: {
ts: string
pageId: string
properties: Array<{
id: string
key: string
value: any
version: {
number: number
message?: string
createdAt?: string
} | null
}>
nextCursor: string | null
}
}
export const confluenceListPagePropertiesTool: ToolConfig<
ConfluenceListPagePropertiesParams,
ConfluenceListPagePropertiesResponse
> = {
id: 'confluence_list_page_properties',
name: 'Confluence List Page Properties',
description: 'List all custom properties (metadata) attached to a Confluence page.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the page to list properties from',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of properties to return (default: 50, max: 250)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: (params: ConfluenceListPagePropertiesParams) => {
const query = new URLSearchParams({
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId,
limit: String(params.limit || 50),
})
if (params.cursor) {
query.set('cursor', params.cursor)
}
if (params.cloudId) {
query.set('cloudId', params.cloudId)
}
return `/api/tools/confluence/page-properties?${query.toString()}`
},
method: 'GET',
headers: (params: ConfluenceListPagePropertiesParams) => ({
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
pageId: data.pageId ?? '',
properties: data.properties ?? [],
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
pageId: { type: 'string', description: 'ID of the page' },
properties: {
type: 'array',
description: 'Array of content properties',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Property ID' },
key: { type: 'string', description: 'Property key' },
value: { type: 'json', description: 'Property value (can be any JSON)' },
version: {
type: 'object',
description: 'Version information',
properties: VERSION_OUTPUT_PROPERTIES,
optional: true,
},
},
},
},
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
@@ -0,0 +1,131 @@
import { TIMESTAMP_OUTPUT, VERSION_OUTPUT_PROPERTIES } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceListPageVersionsParams {
accessToken: string
domain: string
pageId: string
limit?: number
cursor?: string
cloudId?: string
}
export interface ConfluenceListPageVersionsResponse {
success: boolean
output: {
ts: string
pageId: string
versions: Array<{
number: number
message: string | null
minorEdit: boolean
authorId: string | null
createdAt: string | null
}>
nextCursor: string | null
}
}
export const confluenceListPageVersionsTool: ToolConfig<
ConfluenceListPageVersionsParams,
ConfluenceListPageVersionsResponse
> = {
id: 'confluence_list_page_versions',
name: 'Confluence List Page Versions',
description: 'List all versions (revision history) of a Confluence page.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the page to get versions for',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of versions to return (default: 50, max: 250)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/page-versions',
method: 'POST',
headers: (params: ConfluenceListPageVersionsParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceListPageVersionsParams) => ({
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId?.trim(),
limit: params.limit ? Number(params.limit) : 50,
cursor: params.cursor,
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
pageId: data.pageId ?? '',
versions: data.versions ?? [],
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
pageId: { type: 'string', description: 'ID of the page' },
versions: {
type: 'array',
description: 'Array of page versions',
items: {
type: 'object',
properties: VERSION_OUTPUT_PROPERTIES,
},
},
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
@@ -0,0 +1,174 @@
import {
CONTENT_BODY_OUTPUT_PROPERTIES,
PAGE_ITEM_PROPERTIES,
TIMESTAMP_OUTPUT,
} from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceListPagesInSpaceParams {
accessToken: string
domain: string
spaceId: string
limit?: number
status?: string
bodyFormat?: string
cursor?: string
cloudId?: string
}
export interface ConfluenceListPagesInSpaceResponse {
success: boolean
output: {
ts: string
pages: Array<{
id: string
title: string
status: string | null
spaceId: string | null
parentId: string | null
authorId: string | null
createdAt: string | null
version: {
number: number
message?: string
createdAt?: string
} | null
body: {
storage?: { value: string }
} | null
webUrl: string | null
}>
nextCursor: string | null
}
}
export const confluenceListPagesInSpaceTool: ToolConfig<
ConfluenceListPagesInSpaceParams,
ConfluenceListPagesInSpaceResponse
> = {
id: 'confluence_list_pages_in_space',
name: 'Confluence List Pages in Space',
description:
'List all pages within a specific Confluence space. Supports pagination and filtering by status.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
spaceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the Confluence space to list pages from',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of pages to return (default: 50, max: 250)',
},
status: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter pages by status: current, archived, trashed, or draft',
},
bodyFormat: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Format for page body content: storage, atlas_doc_format, or view. If not specified, body is not included.',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response to get the next page of results',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/space-pages',
method: 'POST',
headers: (params: ConfluenceListPagesInSpaceParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceListPagesInSpaceParams) => ({
domain: params.domain,
accessToken: params.accessToken,
spaceId: params.spaceId?.trim(),
limit: params.limit ? Number(params.limit) : 50,
status: params.status,
bodyFormat: params.bodyFormat,
cursor: params.cursor,
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
pages: data.pages ?? [],
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
pages: {
type: 'array',
description: 'Array of pages in the space',
items: {
type: 'object',
properties: {
...PAGE_ITEM_PROPERTIES,
body: {
type: 'object',
description: 'Page body content (if bodyFormat was specified)',
properties: CONTENT_BODY_OUTPUT_PROPERTIES,
optional: true,
},
webUrl: {
type: 'string',
description: 'URL to view the page in Confluence',
optional: true,
},
},
},
},
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
@@ -0,0 +1,134 @@
import { LABEL_ITEM_PROPERTIES, TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceListSpaceLabelsParams {
accessToken: string
domain: string
spaceId: string
limit?: number
cursor?: string
cloudId?: string
}
export interface ConfluenceListSpaceLabelsResponse {
success: boolean
output: {
ts: string
spaceId: string
labels: Array<{
id: string
name: string
prefix: string
}>
nextCursor: string | null
}
}
export const confluenceListSpaceLabelsTool: ToolConfig<
ConfluenceListSpaceLabelsParams,
ConfluenceListSpaceLabelsResponse
> = {
id: 'confluence_list_space_labels',
name: 'Confluence List Space Labels',
description: 'List all labels associated with a Confluence space.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
spaceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the Confluence space to list labels from',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of labels to return (default: 25, max: 250)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: (params: ConfluenceListSpaceLabelsParams) => {
const query = new URLSearchParams({
domain: params.domain,
accessToken: params.accessToken,
spaceId: params.spaceId,
limit: String(params.limit || 25),
})
if (params.cursor) {
query.set('cursor', params.cursor)
}
if (params.cloudId) {
query.set('cloudId', params.cloudId)
}
return `/api/tools/confluence/space-labels?${query.toString()}`
},
method: 'GET',
headers: (params: ConfluenceListSpaceLabelsParams) => ({
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
spaceId: data.spaceId ?? '',
labels: data.labels ?? [],
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
spaceId: { type: 'string', description: 'ID of the space' },
labels: {
type: 'array',
description: 'Array of labels on the space',
items: {
type: 'object',
properties: LABEL_ITEM_PROPERTIES,
},
},
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
@@ -0,0 +1,156 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceListSpacePermissionsParams {
accessToken: string
domain: string
spaceId: string
limit?: number
cursor?: string
cloudId?: string
}
export interface ConfluenceListSpacePermissionsResponse {
success: boolean
output: {
ts: string
permissions: Array<{
id: string
principalType: string | null
principalId: string | null
operationKey: string | null
operationTargetType: string | null
anonymousAccess: boolean
unlicensedAccess: boolean
}>
spaceId: string
nextCursor: string | null
}
}
export const confluenceListSpacePermissionsTool: ToolConfig<
ConfluenceListSpacePermissionsParams,
ConfluenceListSpacePermissionsResponse
> = {
id: 'confluence_list_space_permissions',
name: 'Confluence List Space Permissions',
description: 'List permissions for a Confluence space.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
spaceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Space ID to list permissions for',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of permissions to return (default: 50, max: 250)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/space-permissions',
method: 'POST',
headers: (params: ConfluenceListSpacePermissionsParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceListSpacePermissionsParams) => ({
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
spaceId: params.spaceId,
limit: params.limit,
cursor: params.cursor,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
permissions: data.permissions || [],
spaceId: data.spaceId ?? '',
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
permissions: {
type: 'array',
description: 'Array of space permissions',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Permission ID' },
principalType: {
type: 'string',
description: 'Principal type (user, group, role)',
optional: true,
},
principalId: { type: 'string', description: 'Principal ID', optional: true },
operationKey: {
type: 'string',
description: 'Operation key (read, create, delete, etc.)',
optional: true,
},
operationTargetType: {
type: 'string',
description: 'Target type (page, blogpost, space, etc.)',
optional: true,
},
anonymousAccess: { type: 'boolean', description: 'Whether anonymous access is allowed' },
unlicensedAccess: {
type: 'boolean',
description: 'Whether unlicensed access is allowed',
},
},
},
},
spaceId: { type: 'string', description: 'Space ID' },
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
@@ -0,0 +1,133 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceListSpacePropertiesParams {
accessToken: string
domain: string
spaceId: string
limit?: number
cursor?: string
cloudId?: string
}
export interface ConfluenceListSpacePropertiesResponse {
success: boolean
output: {
ts: string
properties: Array<{
id: string
key: string
value: unknown
}>
spaceId: string
nextCursor: string | null
}
}
export const confluenceListSpacePropertiesTool: ToolConfig<
ConfluenceListSpacePropertiesParams,
ConfluenceListSpacePropertiesResponse
> = {
id: 'confluence_list_space_properties',
name: 'Confluence List Space Properties',
description: 'List properties on a Confluence space.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
spaceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Space ID to list properties for',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of properties to return (default: 50, max: 250)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/space-properties',
method: 'POST',
headers: (params: ConfluenceListSpacePropertiesParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceListSpacePropertiesParams) => ({
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
spaceId: params.spaceId,
limit: params.limit,
cursor: params.cursor,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
properties: data.properties || [],
spaceId: data.spaceId ?? '',
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
properties: {
type: 'array',
description: 'Array of space properties',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Property ID' },
key: { type: 'string', description: 'Property key' },
value: { type: 'json', description: 'Property value' },
},
},
},
spaceId: { type: 'string', description: 'Space ID' },
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
+120
View File
@@ -0,0 +1,120 @@
import { SPACES_OUTPUT, TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceListSpacesParams {
accessToken: string
domain: string
limit?: number
cursor?: string
cloudId?: string
}
export interface ConfluenceListSpacesResponse {
success: boolean
output: {
ts: string
spaces: Array<{
id: string
name: string
key: string
type: string
status: string
}>
nextCursor: string | null
}
}
export const confluenceListSpacesTool: ToolConfig<
ConfluenceListSpacesParams,
ConfluenceListSpacesResponse
> = {
id: 'confluence_list_spaces',
name: 'Confluence List Spaces',
description: 'List all Confluence spaces accessible to the user.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of spaces to return (default: 25, max: 250)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: (params: ConfluenceListSpacesParams) => {
const query = new URLSearchParams({
domain: params.domain,
accessToken: params.accessToken,
limit: String(params.limit || 25),
})
if (params.cursor) {
query.set('cursor', params.cursor)
}
if (params.cloudId) {
query.set('cloudId', params.cloudId)
}
return `/api/tools/confluence/spaces?${query.toString()}`
},
method: 'GET',
headers: (params: ConfluenceListSpacesParams) => {
return {
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
spaces: data.spaces || [],
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
spaces: SPACES_OUTPUT,
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
+181
View File
@@ -0,0 +1,181 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceListTasksParams {
accessToken: string
domain: string
pageId?: string
spaceId?: string
assignedTo?: string
status?: string
limit?: number
cursor?: string
cloudId?: string
}
export interface ConfluenceListTasksResponse {
success: boolean
output: {
ts: string
tasks: Array<{
id: string
localId: string | null
spaceId: string | null
pageId: string | null
blogPostId: string | null
status: string
body: string | null
createdBy: string | null
assignedTo: string | null
completedBy: string | null
createdAt: string | null
updatedAt: string | null
dueAt: string | null
completedAt: string | null
}>
nextCursor: string | null
}
}
export const confluenceListTasksTool: ToolConfig<
ConfluenceListTasksParams,
ConfluenceListTasksResponse
> = {
id: 'confluence_list_tasks',
name: 'Confluence List Tasks',
description:
'List inline tasks from Confluence. Optionally filter by page, space, assignee, or status.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter tasks by page ID',
},
spaceId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter tasks by space ID',
},
assignedTo: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter tasks by assignee account ID',
},
status: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter tasks by status (complete or incomplete)',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of tasks to return (default: 50, max: 250)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor from previous response',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/tasks',
method: 'POST',
headers: (params: ConfluenceListTasksParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceListTasksParams) => ({
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
pageId: params.pageId,
spaceId: params.spaceId,
assignedTo: params.assignedTo,
status: params.status,
limit: params.limit,
cursor: params.cursor,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
tasks: data.tasks || [],
nextCursor: data.nextCursor ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
tasks: {
type: 'array',
description: 'Array of Confluence tasks',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Task ID' },
localId: { type: 'string', description: 'Local task ID', optional: true },
spaceId: { type: 'string', description: 'Space ID', optional: true },
pageId: { type: 'string', description: 'Page ID', optional: true },
blogPostId: { type: 'string', description: 'Blog post ID', optional: true },
status: { type: 'string', description: 'Task status (complete or incomplete)' },
body: {
type: 'string',
description: 'Task body content in storage format',
optional: true,
},
createdBy: { type: 'string', description: 'Creator account ID', optional: true },
assignedTo: { type: 'string', description: 'Assignee account ID', optional: true },
completedBy: { type: 'string', description: 'Completer account ID', optional: true },
createdAt: { type: 'string', description: 'Creation timestamp', optional: true },
updatedAt: { type: 'string', description: 'Last update timestamp', optional: true },
dueAt: { type: 'string', description: 'Due date', optional: true },
completedAt: { type: 'string', description: 'Completion timestamp', optional: true },
},
},
},
nextCursor: {
type: 'string',
description: 'Cursor for fetching the next page of results',
optional: true,
},
},
}
+117
View File
@@ -0,0 +1,117 @@
import type { ConfluenceRetrieveParams, ConfluenceRetrieveResponse } from '@/tools/confluence/types'
import {
BODY_FORMAT_PROPERTIES,
TIMESTAMP_OUTPUT,
VERSION_OUTPUT_PROPERTIES,
} from '@/tools/confluence/types'
import { transformPageData } from '@/tools/confluence/utils'
import type { ToolConfig } from '@/tools/types'
export const confluenceRetrieveTool: ToolConfig<
ConfluenceRetrieveParams,
ConfluenceRetrieveResponse
> = {
id: 'confluence_retrieve',
name: 'Confluence Retrieve',
description: 'Retrieve content from Confluence pages using the Confluence API.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence page ID to retrieve (numeric ID from page URL or API)',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: (params: ConfluenceRetrieveParams) => {
return '/api/tools/confluence/page'
},
method: 'POST',
headers: (params: ConfluenceRetrieveParams) => {
return {
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
body: (params: ConfluenceRetrieveParams) => {
return {
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId,
cloudId: params.cloudId,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return transformPageData(data)
},
outputs: {
ts: TIMESTAMP_OUTPUT,
pageId: { type: 'string', description: 'Confluence page ID' },
title: { type: 'string', description: 'Page title' },
content: { type: 'string', description: 'Page content with HTML tags stripped' },
status: {
type: 'string',
description: 'Page status (current, archived, trashed, draft)',
optional: true,
},
spaceId: { type: 'string', description: 'ID of the space containing the page', optional: true },
parentId: { type: 'string', description: 'ID of the parent page', optional: true },
authorId: { type: 'string', description: 'Account ID of the page author', optional: true },
createdAt: {
type: 'string',
description: 'ISO 8601 timestamp when the page was created',
optional: true,
},
url: { type: 'string', description: 'URL to view the page in Confluence', optional: true },
body: {
type: 'object',
description: 'Raw page body content in storage format',
properties: {
storage: {
type: 'object',
description: 'Body in storage format (Confluence markup)',
properties: BODY_FORMAT_PROPERTIES,
optional: true,
},
},
optional: true,
},
version: {
type: 'object',
description: 'Page version information',
properties: VERSION_OUTPUT_PROPERTIES,
optional: true,
},
},
}
+114
View File
@@ -0,0 +1,114 @@
import { SEARCH_RESULT_ITEM_PROPERTIES } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceSearchParams {
accessToken: string
domain: string
query: string
limit?: number
cloudId?: string
}
export interface ConfluenceSearchResponse {
success: boolean
output: {
ts: string
results: Array<{
id: string
title: string
type: string
url: string
excerpt: string
}>
}
}
export const confluenceSearchTool: ToolConfig<ConfluenceSearchParams, ConfluenceSearchResponse> = {
id: 'confluence_search',
name: 'Confluence Search',
description: 'Search for content across Confluence pages, blog posts, and other content.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
query: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Search query string',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of results to return (default: 25)',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/search',
method: 'POST',
headers: (params: ConfluenceSearchParams) => {
return {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
body: (params: ConfluenceSearchParams) => {
return {
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
query: params.query,
limit: params.limit ? Number(params.limit) : 25,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
results: data.results || [],
},
}
},
outputs: {
ts: { type: 'string', description: 'Timestamp of search' },
results: {
type: 'array',
description: 'Array of search results',
items: {
type: 'object',
properties: SEARCH_RESULT_ITEM_PROPERTIES,
},
},
},
}
@@ -0,0 +1,144 @@
import { SEARCH_RESULT_ITEM_PROPERTIES, TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceSearchInSpaceParams {
accessToken: string
domain: string
spaceKey: string
query?: string
contentType?: string
limit?: number
cloudId?: string
}
export interface ConfluenceSearchInSpaceResponse {
success: boolean
output: {
ts: string
spaceKey: string
totalSize: number
results: Array<{
id: string
title: string
type: string
status: string | null
url: string
excerpt: string
lastModified: string | null
}>
}
}
export const confluenceSearchInSpaceTool: ToolConfig<
ConfluenceSearchInSpaceParams,
ConfluenceSearchInSpaceResponse
> = {
id: 'confluence_search_in_space',
name: 'Confluence Search in Space',
description:
'Search for content within a specific Confluence space. Optionally filter by text query and content type.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
spaceKey: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The key of the Confluence space to search in (e.g., "ENG", "HR")',
},
query: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Text search query. If not provided, returns all content in the space.',
},
contentType: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by content type: page, blogpost, attachment, or comment',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of results to return (default: 25, max: 250)',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/search-in-space',
method: 'POST',
headers: (params: ConfluenceSearchInSpaceParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceSearchInSpaceParams) => ({
domain: params.domain,
accessToken: params.accessToken,
spaceKey: params.spaceKey?.trim(),
query: params.query,
contentType: params.contentType,
limit: params.limit ? Number(params.limit) : 25,
cloudId: params.cloudId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
spaceKey: data.spaceKey ?? '',
totalSize: data.totalSize ?? 0,
results: data.results ?? [],
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
spaceKey: {
type: 'string',
description: 'The space key that was searched',
},
totalSize: {
type: 'number',
description: 'Total number of matching results',
},
results: {
type: 'array',
description: 'Array of search results',
items: {
type: 'object',
properties: SEARCH_RESULT_ITEM_PROPERTIES,
},
},
},
}
+716
View File
@@ -0,0 +1,716 @@
import type { OutputProperty, ToolResponse } from '@/tools/types'
/**
* Shared output property constants for Confluence tools.
* Based on Confluence REST API v2 response schemas:
* @see https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-page/
* @see https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-space/
* @see https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-comment/
* @see https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-attachment/
* @see https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-label/
*/
/**
* Version object properties shared across pages, comments, and attachments.
* Based on Confluence API v2 version structure.
*/
export const VERSION_OUTPUT_PROPERTIES = {
number: { type: 'number', description: 'Version number' },
message: { type: 'string', description: 'Version message', optional: true },
minorEdit: { type: 'boolean', description: 'Whether this is a minor edit', optional: true },
authorId: { type: 'string', description: 'Account ID of the version author', optional: true },
createdAt: {
type: 'string',
description: 'ISO 8601 timestamp of version creation',
optional: true,
},
} as const satisfies Record<string, OutputProperty>
/**
* Detailed version object properties for get_page_version endpoint.
* Based on Confluence API v2 DetailedVersion schema.
*/
export const DETAILED_VERSION_OUTPUT_PROPERTIES = {
number: { type: 'number', description: 'Version number' },
message: { type: 'string', description: 'Version message', optional: true },
minorEdit: { type: 'boolean', description: 'Whether this is a minor edit' },
authorId: { type: 'string', description: 'Account ID of the version author', optional: true },
createdAt: {
type: 'string',
description: 'ISO 8601 timestamp of version creation',
optional: true,
},
contentTypeModified: {
type: 'boolean',
description: 'Whether the content type was modified in this version',
optional: true,
},
collaborators: {
type: 'array',
description: 'List of collaborator account IDs for this version',
items: { type: 'string' },
optional: true,
},
prevVersion: {
type: 'number',
description: 'Previous version number',
optional: true,
},
nextVersion: {
type: 'number',
description: 'Next version number',
optional: true,
},
} as const satisfies Record<string, OutputProperty>
/**
* Complete detailed version object output definition.
*/
export const DETAILED_VERSION_OUTPUT: OutputProperty = {
type: 'object',
description: 'Detailed version information',
properties: DETAILED_VERSION_OUTPUT_PROPERTIES,
}
/**
* Complete version object output definition.
*/
export const VERSION_OUTPUT: OutputProperty = {
type: 'object',
description: 'Version information',
properties: VERSION_OUTPUT_PROPERTIES,
}
/**
* Page item properties from Confluence API v2.
* Based on GET /wiki/api/v2/pages response structure.
*/
export const PAGE_ITEM_PROPERTIES = {
id: { type: 'string', description: 'Unique page identifier' },
title: { type: 'string', description: 'Page title' },
status: { type: 'string', description: 'Page status (e.g., current, archived, trashed, draft)' },
spaceId: { type: 'string', description: 'ID of the space containing the page' },
parentId: {
type: 'string',
description: 'ID of the parent page (null if top-level)',
optional: true,
},
authorId: { type: 'string', description: 'Account ID of the page author' },
createdAt: { type: 'string', description: 'ISO 8601 timestamp when the page was created' },
version: {
type: 'object',
description: 'Page version information',
properties: VERSION_OUTPUT_PROPERTIES,
},
} as const satisfies Record<string, OutputProperty>
/**
* Complete page object output definition.
*/
export const PAGE_OUTPUT: OutputProperty = {
type: 'object',
description: 'Confluence page object',
properties: PAGE_ITEM_PROPERTIES,
}
/**
* Pages array output definition for list endpoints.
*/
export const PAGES_OUTPUT: OutputProperty = {
type: 'array',
description: 'Array of Confluence pages',
items: {
type: 'object',
properties: PAGE_ITEM_PROPERTIES,
},
}
/**
* Space description object properties.
* Based on Confluence API v2 space description structure.
*/
export const SPACE_DESCRIPTION_OUTPUT_PROPERTIES = {
value: { type: 'string', description: 'Description text content' },
representation: {
type: 'string',
description: 'Content representation format (e.g., plain, view, storage)',
},
} as const satisfies Record<string, OutputProperty>
/**
* Space item properties from Confluence API v2.
* Based on GET /wiki/api/v2/spaces response structure.
*/
export const SPACE_ITEM_PROPERTIES = {
id: { type: 'string', description: 'Unique space identifier' },
key: { type: 'string', description: 'Space key (short identifier used in URLs)' },
name: { type: 'string', description: 'Space name' },
type: { type: 'string', description: 'Space type (e.g., global, personal)' },
status: { type: 'string', description: 'Space status (e.g., current, archived)' },
authorId: { type: 'string', description: 'Account ID of the space creator', optional: true },
createdAt: {
type: 'string',
description: 'ISO 8601 timestamp when the space was created',
optional: true,
},
homepageId: { type: 'string', description: 'ID of the space homepage', optional: true },
description: {
type: 'object',
description: 'Space description',
properties: SPACE_DESCRIPTION_OUTPUT_PROPERTIES,
optional: true,
},
} as const satisfies Record<string, OutputProperty>
/**
* Complete space object output definition.
*/
export const SPACE_OUTPUT: OutputProperty = {
type: 'object',
description: 'Confluence space object',
properties: SPACE_ITEM_PROPERTIES,
}
/**
* Spaces array output definition for list endpoints.
*/
export const SPACES_OUTPUT: OutputProperty = {
type: 'array',
description: 'Array of Confluence spaces',
items: {
type: 'object',
properties: SPACE_ITEM_PROPERTIES,
},
}
/**
* Body format inner object properties (storage, view, atlas_doc_format).
* Based on Confluence API v2 body structure.
*/
export const BODY_FORMAT_PROPERTIES = {
value: { type: 'string', description: 'The content value in the specified format' },
representation: {
type: 'string',
description: 'Content representation type',
optional: true,
},
} as const satisfies Record<string, OutputProperty>
/**
* Page/Blog post body object properties.
* Based on Confluence API v2 body structure with multiple format options.
*/
export const CONTENT_BODY_OUTPUT_PROPERTIES = {
storage: {
type: 'object',
description: 'Body in storage format (Confluence markup)',
properties: BODY_FORMAT_PROPERTIES,
optional: true,
},
view: {
type: 'object',
description: 'Body in view format (rendered HTML)',
properties: BODY_FORMAT_PROPERTIES,
optional: true,
},
atlas_doc_format: {
type: 'object',
description: 'Body in Atlassian Document Format (ADF)',
properties: BODY_FORMAT_PROPERTIES,
optional: true,
},
} as const satisfies Record<string, OutputProperty>
/**
* Complete body object output definition for pages and blog posts.
*/
export const CONTENT_BODY_OUTPUT: OutputProperty = {
type: 'object',
description: 'Page or blog post body content in requested format(s)',
properties: CONTENT_BODY_OUTPUT_PROPERTIES,
optional: true,
}
/**
* Comment body object properties.
* Based on Confluence API v2 comment body structure.
*/
export const COMMENT_BODY_OUTPUT_PROPERTIES = {
value: { type: 'string', description: 'Comment body content' },
representation: {
type: 'string',
description: 'Content representation format (e.g., storage, view)',
},
} as const satisfies Record<string, OutputProperty>
/**
* Comment item properties from Confluence API v2.
* Based on GET /wiki/api/v2/footer-comments and GET /wiki/api/v2/inline-comments response.
*/
export const COMMENT_ITEM_PROPERTIES = {
id: { type: 'string', description: 'Unique comment identifier' },
status: { type: 'string', description: 'Comment status (e.g., current)' },
title: { type: 'string', description: 'Comment title', optional: true },
pageId: { type: 'string', description: 'ID of the page the comment belongs to', optional: true },
blogPostId: {
type: 'string',
description: 'ID of the blog post the comment belongs to',
optional: true,
},
parentCommentId: { type: 'string', description: 'ID of the parent comment', optional: true },
body: {
type: 'object',
description: 'Comment body content',
properties: COMMENT_BODY_OUTPUT_PROPERTIES,
optional: true,
},
createdAt: { type: 'string', description: 'ISO 8601 timestamp when the comment was created' },
authorId: { type: 'string', description: 'Account ID of the comment author' },
version: {
type: 'object',
description: 'Comment version information',
properties: VERSION_OUTPUT_PROPERTIES,
optional: true,
},
} as const satisfies Record<string, OutputProperty>
/**
* Complete comment object output definition.
*/
export const COMMENT_OUTPUT: OutputProperty = {
type: 'object',
description: 'Confluence comment object',
properties: COMMENT_ITEM_PROPERTIES,
}
/**
* Comments array output definition for list endpoints.
*/
export const COMMENTS_OUTPUT: OutputProperty = {
type: 'array',
description: 'Array of Confluence comments',
items: {
type: 'object',
properties: COMMENT_ITEM_PROPERTIES,
},
}
/**
* Attachment item properties from Confluence API v2.
* Based on GET /wiki/api/v2/attachments response structure.
*/
export const ATTACHMENT_ITEM_PROPERTIES = {
id: { type: 'string', description: 'Unique attachment identifier (prefixed with "att")' },
title: { type: 'string', description: 'Attachment file name' },
status: { type: 'string', description: 'Attachment status (e.g., current, archived, trashed)' },
mediaType: { type: 'string', description: 'MIME type of the attachment' },
fileSize: { type: 'number', description: 'File size in bytes' },
downloadUrl: { type: 'string', description: 'URL to download the attachment' },
webuiUrl: {
type: 'string',
description: 'URL to view the attachment in Confluence UI',
optional: true,
},
pageId: {
type: 'string',
description: 'ID of the page the attachment belongs to',
optional: true,
},
blogPostId: {
type: 'string',
description: 'ID of the blog post the attachment belongs to',
optional: true,
},
comment: { type: 'string', description: 'Comment/description of the attachment', optional: true },
version: {
type: 'object',
description: 'Attachment version information',
properties: VERSION_OUTPUT_PROPERTIES,
optional: true,
},
} as const satisfies Record<string, OutputProperty>
/**
* Complete attachment object output definition.
*/
export const ATTACHMENT_OUTPUT: OutputProperty = {
type: 'object',
description: 'Confluence attachment object',
properties: ATTACHMENT_ITEM_PROPERTIES,
}
/**
* Attachments array output definition for list endpoints.
*/
export const ATTACHMENTS_OUTPUT: OutputProperty = {
type: 'array',
description: 'Array of Confluence attachments',
items: {
type: 'object',
properties: ATTACHMENT_ITEM_PROPERTIES,
},
}
/**
* Label item properties from Confluence API v2.
* Based on GET /wiki/api/v2/labels response structure.
*/
export const LABEL_ITEM_PROPERTIES = {
id: { type: 'string', description: 'Unique label identifier' },
name: { type: 'string', description: 'Label name' },
prefix: { type: 'string', description: 'Label prefix/type (e.g., global, my, team)' },
} as const satisfies Record<string, OutputProperty>
/**
* Complete label object output definition.
*/
export const LABEL_OUTPUT: OutputProperty = {
type: 'object',
description: 'Confluence label object',
properties: LABEL_ITEM_PROPERTIES,
}
/**
* Labels array output definition for list endpoints.
*/
export const LABELS_OUTPUT: OutputProperty = {
type: 'array',
description: 'Array of Confluence labels',
items: {
type: 'object',
properties: LABEL_ITEM_PROPERTIES,
},
}
/**
* Search result space info properties.
* Based on Confluence search API space object in results.
*/
export const SEARCH_RESULT_SPACE_PROPERTIES = {
id: { type: 'string', description: 'Space identifier' },
key: { type: 'string', description: 'Space key' },
name: { type: 'string', description: 'Space name' },
} as const satisfies Record<string, OutputProperty>
/**
* Search result item properties from Confluence API.
* Based on GET /wiki/rest/api/search response structure.
*/
export const SEARCH_RESULT_ITEM_PROPERTIES = {
id: { type: 'string', description: 'Unique content identifier' },
title: { type: 'string', description: 'Content title' },
type: { type: 'string', description: 'Content type (e.g., page, blogpost, attachment, comment)' },
status: { type: 'string', description: 'Content status (e.g., current)', optional: true },
url: { type: 'string', description: 'URL to view the content in Confluence' },
excerpt: { type: 'string', description: 'Text excerpt matching the search query' },
spaceKey: {
type: 'string',
description: 'Key of the space containing the content',
optional: true,
},
space: {
type: 'object',
description: 'Space information for the content',
properties: SEARCH_RESULT_SPACE_PROPERTIES,
optional: true,
},
lastModified: {
type: 'string',
description: 'ISO 8601 timestamp of last modification',
optional: true,
},
entityType: {
type: 'string',
description: 'Entity type identifier (e.g., content, space)',
optional: true,
},
} as const satisfies Record<string, OutputProperty>
/**
* Complete search result object output definition.
*/
export const SEARCH_RESULT_OUTPUT: OutputProperty = {
type: 'object',
description: 'Confluence search result object',
properties: SEARCH_RESULT_ITEM_PROPERTIES,
}
/**
* Search results array output definition.
*/
export const SEARCH_RESULTS_OUTPUT: OutputProperty = {
type: 'array',
description: 'Array of search results',
items: {
type: 'object',
properties: SEARCH_RESULT_ITEM_PROPERTIES,
},
}
/**
* Pagination links properties for list responses.
*/
export const PAGINATION_LINKS_PROPERTIES = {
next: { type: 'string', description: 'URL to fetch the next page of results', optional: true },
base: { type: 'string', description: 'Base URL for the API', optional: true },
} as const satisfies Record<string, OutputProperty>
/**
* Common timestamp output property.
*/
export const TIMESTAMP_OUTPUT: OutputProperty = {
type: 'string',
description: 'ISO 8601 timestamp of the operation',
}
/**
* Common page ID output property.
*/
export const PAGE_ID_OUTPUT: OutputProperty = {
type: 'string',
description: 'Confluence page ID',
}
/**
* Common success status output property.
*/
export const SUCCESS_OUTPUT: OutputProperty = {
type: 'boolean',
description: 'Operation success status',
}
/**
* Common deleted status output property.
*/
export const DELETED_OUTPUT: OutputProperty = {
type: 'boolean',
description: 'Deletion status',
}
/**
* Common URL output property.
*/
export const URL_OUTPUT: OutputProperty = {
type: 'string',
description: 'URL to view in Confluence',
}
export interface ConfluenceRetrieveParams {
accessToken: string
pageId: string
domain: string
cloudId?: string
}
export interface ConfluenceRetrieveResponse extends ToolResponse {
output: {
ts: string
pageId: string
content: string
title: string
}
}
interface ConfluencePage {
id: string
title: string
spaceKey?: string
url?: string
lastModified?: string
}
export interface ConfluenceUpdateParams {
accessToken: string
domain: string
pageId: string
title?: string
content?: string
cloudId?: string
}
export interface ConfluenceUpdateResponse extends ToolResponse {
output: {
ts: string
pageId: string
title: string
success: boolean
}
}
interface ConfluenceCreatePageParams {
accessToken: string
domain: string
spaceId: string
title: string
content: string
parentId?: string
cloudId?: string
}
interface ConfluenceCreatePageResponse extends ToolResponse {
output: {
ts: string
pageId: string
title: string
url: string
}
}
interface ConfluenceDeletePageParams {
accessToken: string
domain: string
pageId: string
cloudId?: string
}
interface ConfluenceDeletePageResponse extends ToolResponse {
output: {
ts: string
pageId: string
deleted: boolean
}
}
interface ConfluenceSearchParams {
accessToken: string
domain: string
query: string
limit?: number
cloudId?: string
}
interface ConfluenceSearchResponse extends ToolResponse {
output: {
ts: string
results: Array<{
id: string
title: string
type: string
url: string
excerpt: string
}>
}
}
interface ConfluenceCommentParams {
accessToken: string
domain: string
pageId: string
comment: string
cloudId?: string
}
interface ConfluenceCommentResponse extends ToolResponse {
output: {
ts: string
commentId: string
pageId: string
}
}
interface ConfluenceAttachmentParams {
accessToken: string
domain: string
pageId?: string
attachmentId?: string
limit?: number
cloudId?: string
}
interface ConfluenceAttachmentResponse extends ToolResponse {
output: {
ts: string
attachments?: Array<{
id: string
title: string
fileSize: number
mediaType: string
downloadUrl: string
}>
attachmentId?: string
deleted?: boolean
}
}
interface ConfluenceUploadAttachmentParams {
accessToken: string
domain: string
pageId: string
file: any
fileName?: string
comment?: string
cloudId?: string
}
interface ConfluenceUploadAttachmentResponse extends ToolResponse {
output: {
ts: string
attachmentId: string
title: string
fileSize: number
mediaType: string
downloadUrl: string
pageId: string
}
}
interface ConfluenceLabelParams {
accessToken: string
domain: string
pageId: string
labelName?: string
cloudId?: string
}
interface ConfluenceLabelResponse extends ToolResponse {
output: {
ts: string
labels?: Array<{
id: string
name: string
prefix: string
}>
pageId?: string
labelName?: string
added?: boolean
removed?: boolean
}
}
interface ConfluenceSpaceParams {
accessToken: string
domain: string
spaceId?: string
limit?: number
cloudId?: string
}
interface ConfluenceSpaceResponse extends ToolResponse {
output: {
ts: string
spaces?: Array<{
id: string
name: string
key: string
type: string
status: string
}>
spaceId?: string
name?: string
key?: string
type?: string
status?: string
}
}
export type ConfluenceResponse =
| ConfluenceRetrieveResponse
| ConfluenceUpdateResponse
| ConfluenceCreatePageResponse
| ConfluenceDeletePageResponse
| ConfluenceSearchResponse
| ConfluenceCommentResponse
| ConfluenceAttachmentResponse
| ConfluenceUploadAttachmentResponse
| ConfluenceLabelResponse
| ConfluenceSpaceResponse
+121
View File
@@ -0,0 +1,121 @@
import type { ConfluenceUpdateParams, ConfluenceUpdateResponse } from '@/tools/confluence/types'
import { CONTENT_BODY_OUTPUT_PROPERTIES, VERSION_OUTPUT_PROPERTIES } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export const confluenceUpdateTool: ToolConfig<ConfluenceUpdateParams, ConfluenceUpdateResponse> = {
id: 'confluence_update',
name: 'Confluence Update',
description: 'Update a Confluence page using the Confluence API.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence page ID to update (numeric ID from page URL or API)',
},
title: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New title for the page',
},
content: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New content for the page in Confluence storage format',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: (params: ConfluenceUpdateParams) => {
return '/api/tools/confluence/page'
},
method: 'PUT',
headers: (params: ConfluenceUpdateParams) => {
return {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
body: (params: ConfluenceUpdateParams) => {
const body: Record<string, any> = {
domain: params.domain,
accessToken: params.accessToken,
pageId: params.pageId,
cloudId: params.cloudId,
title: params.title,
body: params.content ? { value: params.content } : undefined,
version: { message: 'Updated via Sim' },
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
pageId: data.id ?? '',
title: data.title ?? '',
status: data.status ?? null,
spaceId: data.spaceId ?? null,
body: data.body ?? null,
version: data.version ?? null,
url: data._links?.webui ?? null,
success: true,
},
}
},
outputs: {
ts: { type: 'string', description: 'Timestamp of update' },
pageId: { type: 'string', description: 'Confluence page ID' },
title: { type: 'string', description: 'Updated page title' },
status: { type: 'string', description: 'Page status', optional: true },
spaceId: { type: 'string', description: 'Space ID', optional: true },
body: {
type: 'object',
description: 'Page body content in storage format',
properties: CONTENT_BODY_OUTPUT_PROPERTIES,
optional: true,
},
version: {
type: 'object',
description: 'Page version information',
properties: VERSION_OUTPUT_PROPERTIES,
optional: true,
},
url: { type: 'string', description: 'URL to view the page in Confluence', optional: true },
success: { type: 'boolean', description: 'Update operation success status' },
},
}
@@ -0,0 +1,123 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceUpdateBlogPostParams {
accessToken: string
domain: string
blogPostId: string
title?: string
content?: string
cloudId?: string
}
export interface ConfluenceUpdateBlogPostResponse {
success: boolean
output: {
ts: string
blogPostId: string
title: string
status: string | null
spaceId: string | null
version: Record<string, unknown> | null
url: string
}
}
export const confluenceUpdateBlogPostTool: ToolConfig<
ConfluenceUpdateBlogPostParams,
ConfluenceUpdateBlogPostResponse
> = {
id: 'confluence_update_blogpost',
name: 'Confluence Update Blog Post',
description: 'Update an existing Confluence blog post title and/or content.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
blogPostId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the blog post to update',
},
title: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New title for the blog post',
},
content: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New content for the blog post in storage format',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/blogposts',
method: 'PUT',
headers: (params: ConfluenceUpdateBlogPostParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceUpdateBlogPostParams) => ({
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
blogPostId: params.blogPostId,
title: params.title,
content: params.content,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
blogPostId: data.id ?? '',
title: data.title ?? '',
status: data.status ?? null,
spaceId: data.spaceId ?? null,
version: data.version ?? null,
url: data._links?.webui ?? '',
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
blogPostId: { type: 'string', description: 'Updated blog post ID' },
title: { type: 'string', description: 'Blog post title' },
status: { type: 'string', description: 'Blog post status', optional: true },
spaceId: { type: 'string', description: 'Space ID', optional: true },
version: { type: 'json', description: 'Version information', optional: true },
url: { type: 'string', description: 'URL to view the blog post' },
},
}
+106
View File
@@ -0,0 +1,106 @@
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceUpdateCommentParams {
accessToken: string
domain: string
commentId: string
comment: string
cloudId?: string
}
export interface ConfluenceUpdateCommentResponse {
success: boolean
output: {
ts: string
commentId: string
updated: boolean
}
}
export const confluenceUpdateCommentTool: ToolConfig<
ConfluenceUpdateCommentParams,
ConfluenceUpdateCommentResponse
> = {
id: 'confluence_update_comment',
name: 'Confluence Update Comment',
description: 'Update an existing comment on a Confluence page.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
commentId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence comment ID to update',
},
comment: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Updated comment text in Confluence storage format',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/comment',
method: 'PUT',
headers: (params: ConfluenceUpdateCommentParams) => {
return {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
body: (params: ConfluenceUpdateCommentParams) => {
return {
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
commentId: params.commentId,
comment: params.comment,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
commentId: data.id || data.commentId,
updated: true,
},
}
},
outputs: {
ts: { type: 'string', description: 'Timestamp of update' },
commentId: { type: 'string', description: 'Updated comment ID' },
updated: { type: 'boolean', description: 'Update status' },
},
}
+131
View File
@@ -0,0 +1,131 @@
import { SPACE_DESCRIPTION_OUTPUT_PROPERTIES, TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceUpdateSpaceParams {
accessToken: string
domain: string
spaceId: string
name?: string
description?: string
cloudId?: string
}
export interface ConfluenceUpdateSpaceResponse {
success: boolean
output: {
ts: string
spaceId: string
name: string
key: string
type: string
status: string
url: string
description: { value: string; representation: string } | null
}
}
export const confluenceUpdateSpaceTool: ToolConfig<
ConfluenceUpdateSpaceParams,
ConfluenceUpdateSpaceResponse
> = {
id: 'confluence_update_space',
name: 'Confluence Update Space',
description: 'Update a Confluence space name or description.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
spaceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the space to update',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New name for the space',
},
description: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New description for the space',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/space',
method: 'PUT',
headers: (params: ConfluenceUpdateSpaceParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceUpdateSpaceParams) => ({
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
spaceId: params.spaceId,
name: params.name,
description: params.description,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
spaceId: data.id ?? '',
name: data.name ?? '',
key: data.key ?? '',
type: data.type ?? '',
status: data.status ?? '',
url: data._links?.webui ?? '',
description: data.description ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
spaceId: { type: 'string', description: 'Updated space ID' },
name: { type: 'string', description: 'Space name' },
key: { type: 'string', description: 'Space key' },
type: { type: 'string', description: 'Space type' },
status: { type: 'string', description: 'Space status' },
url: { type: 'string', description: 'URL to view the space' },
description: {
type: 'object',
description: 'Space description',
properties: SPACE_DESCRIPTION_OUTPUT_PROPERTIES,
optional: true,
},
},
}
+141
View File
@@ -0,0 +1,141 @@
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceUpdateTaskParams {
accessToken: string
domain: string
taskId: string
status: string
cloudId?: string
}
export interface ConfluenceUpdateTaskResponse {
success: boolean
output: {
ts: string
id: string
localId: string | null
spaceId: string | null
pageId: string | null
blogPostId: string | null
status: string
body: string | null
createdBy: string | null
assignedTo: string | null
completedBy: string | null
createdAt: string | null
updatedAt: string | null
dueAt: string | null
completedAt: string | null
}
}
export const confluenceUpdateTaskTool: ToolConfig<
ConfluenceUpdateTaskParams,
ConfluenceUpdateTaskResponse
> = {
id: 'confluence_update_task',
name: 'Confluence Update Task',
description: 'Update the status of a Confluence inline task (complete or incomplete).',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
taskId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the task to update',
},
status: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'New status for the task (complete or incomplete)',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/tasks',
method: 'POST',
headers: (params: ConfluenceUpdateTaskParams) => ({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
body: (params: ConfluenceUpdateTaskParams) => ({
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
action: 'update',
taskId: params.taskId,
status: params.status,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
const task = data.task || data
return {
success: true,
output: {
ts: new Date().toISOString(),
id: task.id ?? '',
localId: task.localId ?? null,
spaceId: task.spaceId ?? null,
pageId: task.pageId ?? null,
blogPostId: task.blogPostId ?? null,
status: task.status ?? '',
body: task.body ?? null,
createdBy: task.createdBy ?? null,
assignedTo: task.assignedTo ?? null,
completedBy: task.completedBy ?? null,
createdAt: task.createdAt ?? null,
updatedAt: task.updatedAt ?? null,
dueAt: task.dueAt ?? null,
completedAt: task.completedAt ?? null,
},
}
},
outputs: {
ts: TIMESTAMP_OUTPUT,
id: { type: 'string', description: 'Task ID' },
localId: { type: 'string', description: 'Local task ID', optional: true },
spaceId: { type: 'string', description: 'Space ID', optional: true },
pageId: { type: 'string', description: 'Page ID', optional: true },
blogPostId: { type: 'string', description: 'Blog post ID', optional: true },
status: { type: 'string', description: 'Updated task status' },
body: { type: 'string', description: 'Task body content in storage format', optional: true },
createdBy: { type: 'string', description: 'Creator account ID', optional: true },
assignedTo: { type: 'string', description: 'Assignee account ID', optional: true },
completedBy: { type: 'string', description: 'Completer account ID', optional: true },
createdAt: { type: 'string', description: 'Creation timestamp', optional: true },
updatedAt: { type: 'string', description: 'Last update timestamp', optional: true },
dueAt: { type: 'string', description: 'Due date', optional: true },
completedAt: { type: 'string', description: 'Completion timestamp', optional: true },
},
}
@@ -0,0 +1,134 @@
import type { ToolConfig } from '@/tools/types'
export interface ConfluenceUploadAttachmentParams {
accessToken: string
domain: string
pageId: string
file: any
fileName?: string
comment?: string
cloudId?: string
}
export interface ConfluenceUploadAttachmentResponse {
success: boolean
output: {
ts: string
attachmentId: string
title: string
fileSize: number
mediaType: string
downloadUrl: string
pageId: string
}
}
export const confluenceUploadAttachmentTool: ToolConfig<
ConfluenceUploadAttachmentParams,
ConfluenceUploadAttachmentResponse
> = {
id: 'confluence_upload_attachment',
name: 'Confluence Upload Attachment',
description: 'Upload a file as an attachment to a Confluence page.',
version: '1.0.0',
oauth: {
required: true,
provider: 'confluence',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Confluence',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
},
pageId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Confluence page ID to attach the file to',
},
file: {
type: 'file',
required: true,
visibility: 'user-or-llm',
description: 'The file to upload as an attachment',
},
fileName: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional custom file name for the attachment',
},
comment: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional comment to add to the attachment',
},
cloudId: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: () => '/api/tools/confluence/upload-attachment',
method: 'POST',
headers: (params: ConfluenceUploadAttachmentParams) => {
return {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}
},
body: (params: ConfluenceUploadAttachmentParams) => {
return {
domain: params.domain,
accessToken: params.accessToken,
cloudId: params.cloudId,
pageId: params.pageId,
file: params.file,
fileName: params.fileName,
comment: params.comment,
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
ts: new Date().toISOString(),
attachmentId: data.attachmentId || '',
title: data.title || '',
fileSize: data.fileSize || 0,
mediaType: data.mediaType || '',
downloadUrl: data.downloadUrl || '',
pageId: data.pageId || '',
},
}
},
outputs: {
ts: { type: 'string', description: 'Timestamp of upload' },
attachmentId: { type: 'string', description: 'Uploaded attachment ID' },
title: { type: 'string', description: 'Attachment file name' },
fileSize: { type: 'number', description: 'File size in bytes' },
mediaType: { type: 'string', description: 'MIME type of the attachment' },
downloadUrl: { type: 'string', description: 'Download URL for the attachment' },
pageId: { type: 'string', description: 'Page ID the attachment was added to' },
},
}
+121
View File
@@ -0,0 +1,121 @@
import type { RetryOptions } from '@/lib/knowledge/documents/utils'
import { fetchWithRetry } from '@/lib/knowledge/documents/utils'
/**
* Strips protocol and trailing slashes from a Confluence domain to produce
* a bare host (e.g. `yoursite.atlassian.net`).
*/
export function normalizeConfluenceDomainHost(domain: string): string {
return domain
.trim()
.replace(/^https?:\/\//i, '')
.replace(/\/+$/, '')
}
export async function getConfluenceCloudId(
domain: string,
accessToken: string,
retryOptions?: RetryOptions
): Promise<string> {
const response = await fetchWithRetry(
'https://api.atlassian.com/oauth/token/accessible-resources',
{
method: 'GET',
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json',
},
},
retryOptions
)
const resources = await response.json()
if (!Array.isArray(resources) || resources.length === 0) {
throw new Error('No Confluence resources found')
}
const normalized = `https://${normalizeConfluenceDomainHost(domain)}`.toLowerCase()
const match = resources.find(
(r: { url: string }) => r.url.toLowerCase().replace(/\/+$/, '') === normalized
)
if (match) {
return match.id
}
if (resources.length === 1) {
return resources[0].id
}
throw new Error(
`Could not match Confluence domain "${domain}" to any accessible resource. ` +
`Available sites: ${resources.map((r: { url: string }) => r.url).join(', ')}`
)
}
function decodeHtmlEntities(text: string): string {
let decoded = text
let previous: string
do {
previous = decoded
decoded = decoded
.replace(/&nbsp;/g, ' ')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&quot;/g, '"')
.replace(/&#39;/g, "'")
decoded = decoded.replace(/&amp;/g, '&')
} while (decoded !== previous)
return decoded
}
function stripHtmlTags(html: string): string {
let text = html
let previous: string
do {
previous = text
text = text.replace(/<[^>]*>/g, '')
text = text.replace(/[<>]/g, '')
} while (text !== previous)
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 || ''
const cleanContent = cleanHtmlContent(rawContent)
return {
success: true,
output: {
ts: new Date().toISOString(),
pageId: data.id ?? '',
title: data.title ?? '',
content: cleanContent,
status: data.status ?? null,
spaceId: data.spaceId ?? null,
parentId: data.parentId ?? null,
authorId: data.authorId ?? null,
createdAt: data.createdAt ?? null,
url: data._links?.webui ?? null,
body: data.body ?? null,
version: data.version ?? null,
},
}
}