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
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:
@@ -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 },
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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 },
|
||||
},
|
||||
}
|
||||
@@ -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 },
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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(/ /g, ' ')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, "'")
|
||||
decoded = decoded.replace(/&/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,
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user