mirror of
https://github.com/simstudioai/sim.git
synced 2026-03-15 03:00:33 -04:00
Compare commits
17 Commits
main
...
waleedlati
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e958ba13d5 | ||
|
|
b68a264965 | ||
|
|
399db331a2 | ||
|
|
04461de3ca | ||
|
|
e96b84764f | ||
|
|
f185b6b0cf | ||
|
|
490de05a25 | ||
|
|
ea45ee6c4e | ||
|
|
a494656afe | ||
|
|
6da784eed4 | ||
|
|
973fe96418 | ||
|
|
3ff834285f | ||
|
|
58a5c7dd00 | ||
|
|
1dc4ff2c62 | ||
|
|
f09fef9aee | ||
|
|
2a97824a05 | ||
|
|
3eb6c082f2 |
@@ -38,8 +38,8 @@ import {
|
||||
EyeIcon,
|
||||
FirecrawlIcon,
|
||||
FirefliesIcon,
|
||||
GithubIcon,
|
||||
GitLabIcon,
|
||||
GithubIcon,
|
||||
GmailIcon,
|
||||
GongIcon,
|
||||
GoogleBooksIcon,
|
||||
@@ -73,9 +73,9 @@ import {
|
||||
LinearIcon,
|
||||
LinkedInIcon,
|
||||
LinkupIcon,
|
||||
MailServerIcon,
|
||||
MailchimpIcon,
|
||||
MailgunIcon,
|
||||
MailServerIcon,
|
||||
Mem0Icon,
|
||||
MicrosoftDataverseIcon,
|
||||
MicrosoftExcelIcon,
|
||||
@@ -108,6 +108,8 @@ import {
|
||||
ResendIcon,
|
||||
RevenueCatIcon,
|
||||
S3Icon,
|
||||
SQSIcon,
|
||||
STTIcon,
|
||||
SalesforceIcon,
|
||||
SearchIcon,
|
||||
SendgridIcon,
|
||||
@@ -119,19 +121,17 @@ import {
|
||||
SimilarwebIcon,
|
||||
SlackIcon,
|
||||
SmtpIcon,
|
||||
SQSIcon,
|
||||
SshIcon,
|
||||
STTIcon,
|
||||
StagehandIcon,
|
||||
StripeIcon,
|
||||
SupabaseIcon,
|
||||
TTSIcon,
|
||||
TavilyIcon,
|
||||
TelegramIcon,
|
||||
TextractIcon,
|
||||
TinybirdIcon,
|
||||
TranslateIcon,
|
||||
TrelloIcon,
|
||||
TTSIcon,
|
||||
TwilioIcon,
|
||||
TypeformIcon,
|
||||
UpstashIcon,
|
||||
@@ -142,11 +142,11 @@ import {
|
||||
WhatsAppIcon,
|
||||
WikipediaIcon,
|
||||
WordpressIcon,
|
||||
xIcon,
|
||||
YouTubeIcon,
|
||||
ZendeskIcon,
|
||||
ZepIcon,
|
||||
ZoomIcon,
|
||||
xIcon,
|
||||
} from '@/components/icons'
|
||||
|
||||
type IconComponent = ComponentType<SVGProps<SVGSVGElement>>
|
||||
|
||||
@@ -1013,6 +1013,85 @@ Get details about a specific Confluence space.
|
||||
| ↳ `value` | string | Description text content |
|
||||
| ↳ `representation` | string | Content representation format \(e.g., plain, view, storage\) |
|
||||
|
||||
### `confluence_create_space`
|
||||
|
||||
Create a new Confluence space.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `name` | string | Yes | Name for the new space |
|
||||
| `key` | string | Yes | Unique key for the space \(uppercase, no spaces\) |
|
||||
| `description` | string | No | Description for the new space |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `spaceId` | string | Created space ID |
|
||||
| `name` | string | Space name |
|
||||
| `key` | string | Space key |
|
||||
| `type` | string | Space type |
|
||||
| `status` | string | Space status |
|
||||
| `url` | string | URL to view the space |
|
||||
| `homepageId` | string | Homepage ID |
|
||||
| `description` | object | Space description |
|
||||
| ↳ `value` | string | Description text content |
|
||||
| ↳ `representation` | string | Content representation format \(e.g., plain, view, storage\) |
|
||||
|
||||
### `confluence_update_space`
|
||||
|
||||
Update a Confluence space name or description.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `spaceId` | string | Yes | ID of the space to update |
|
||||
| `name` | string | No | New name for the space |
|
||||
| `description` | string | No | New description for the space |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `spaceId` | string | Updated space ID |
|
||||
| `name` | string | Space name |
|
||||
| `key` | string | Space key |
|
||||
| `type` | string | Space type |
|
||||
| `status` | string | Space status |
|
||||
| `url` | string | URL to view the space |
|
||||
| `description` | object | Space description |
|
||||
| ↳ `value` | string | Description text content |
|
||||
| ↳ `representation` | string | Content representation format \(e.g., plain, view, storage\) |
|
||||
|
||||
### `confluence_delete_space`
|
||||
|
||||
Delete a Confluence space.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `spaceId` | string | Yes | ID of the space to delete |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `spaceId` | string | Deleted space ID |
|
||||
| `deleted` | boolean | Deletion status |
|
||||
|
||||
### `confluence_list_spaces`
|
||||
|
||||
List all Confluence spaces accessible to the user.
|
||||
@@ -1045,4 +1124,311 @@ List all Confluence spaces accessible to the user.
|
||||
| ↳ `representation` | string | Content representation format \(e.g., plain, view, storage\) |
|
||||
| `nextCursor` | string | Cursor for fetching the next page of results |
|
||||
|
||||
### `confluence_list_space_properties`
|
||||
|
||||
List properties on a Confluence space.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `spaceId` | string | Yes | Space ID to list properties for |
|
||||
| `limit` | number | No | Maximum number of properties to return \(default: 50, max: 250\) |
|
||||
| `cursor` | string | No | Pagination cursor from previous response |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `properties` | array | Array of space properties |
|
||||
| ↳ `id` | string | Property ID |
|
||||
| ↳ `key` | string | Property key |
|
||||
| ↳ `value` | json | Property value |
|
||||
| `spaceId` | string | Space ID |
|
||||
| `nextCursor` | string | Cursor for fetching the next page of results |
|
||||
|
||||
### `confluence_create_space_property`
|
||||
|
||||
Create a property on a Confluence space.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `spaceId` | string | Yes | Space ID to create the property on |
|
||||
| `key` | string | Yes | Property key/name |
|
||||
| `value` | json | No | Property value \(JSON\) |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `propertyId` | string | Created property ID |
|
||||
| `key` | string | Property key |
|
||||
| `value` | json | Property value |
|
||||
| `spaceId` | string | Space ID |
|
||||
|
||||
### `confluence_delete_space_property`
|
||||
|
||||
Delete a property from a Confluence space.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `spaceId` | string | Yes | Space ID the property belongs to |
|
||||
| `propertyId` | string | Yes | Property ID to delete |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `spaceId` | string | Space ID |
|
||||
| `propertyId` | string | Deleted property ID |
|
||||
| `deleted` | boolean | Deletion status |
|
||||
|
||||
### `confluence_list_space_permissions`
|
||||
|
||||
List permissions for a Confluence space.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `spaceId` | string | Yes | Space ID to list permissions for |
|
||||
| `limit` | number | No | Maximum number of permissions to return \(default: 50, max: 250\) |
|
||||
| `cursor` | string | No | Pagination cursor from previous response |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `permissions` | array | Array of space permissions |
|
||||
| ↳ `id` | string | Permission ID |
|
||||
| ↳ `principalType` | string | Principal type \(user, group, role\) |
|
||||
| ↳ `principalId` | string | Principal ID |
|
||||
| ↳ `operationKey` | string | Operation key \(read, create, delete, etc.\) |
|
||||
| ↳ `operationTargetType` | string | Target type \(page, blogpost, space, etc.\) |
|
||||
| ↳ `anonymousAccess` | boolean | Whether anonymous access is allowed |
|
||||
| ↳ `unlicensedAccess` | boolean | Whether unlicensed access is allowed |
|
||||
| `spaceId` | string | Space ID |
|
||||
| `nextCursor` | string | Cursor for fetching the next page of results |
|
||||
|
||||
### `confluence_get_page_descendants`
|
||||
|
||||
Get all descendants of a Confluence page recursively.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `pageId` | string | Yes | Page ID to get descendants for |
|
||||
| `limit` | number | No | Maximum number of descendants to return \(default: 50, max: 250\) |
|
||||
| `cursor` | string | No | Pagination cursor from previous response |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `descendants` | array | Array of descendant pages |
|
||||
| ↳ `id` | string | Page ID |
|
||||
| ↳ `title` | string | Page title |
|
||||
| ↳ `type` | string | Content type \(page, whiteboard, database, etc.\) |
|
||||
| ↳ `status` | string | Page status |
|
||||
| ↳ `spaceId` | string | Space ID |
|
||||
| ↳ `parentId` | string | Parent page ID |
|
||||
| ↳ `childPosition` | number | Position among siblings |
|
||||
| ↳ `depth` | number | Depth in the hierarchy |
|
||||
| `pageId` | string | Parent page ID |
|
||||
| `nextCursor` | string | Cursor for fetching the next page of results |
|
||||
|
||||
### `confluence_list_tasks`
|
||||
|
||||
List inline tasks from Confluence. Optionally filter by page, space, assignee, or status.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `pageId` | string | No | Filter tasks by page ID |
|
||||
| `spaceId` | string | No | Filter tasks by space ID |
|
||||
| `assignedTo` | string | No | Filter tasks by assignee account ID |
|
||||
| `status` | string | No | Filter tasks by status \(complete or incomplete\) |
|
||||
| `limit` | number | No | Maximum number of tasks to return \(default: 50, max: 250\) |
|
||||
| `cursor` | string | No | Pagination cursor from previous response |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `tasks` | array | Array of Confluence tasks |
|
||||
| ↳ `id` | string | Task ID |
|
||||
| ↳ `localId` | string | Local task ID |
|
||||
| ↳ `spaceId` | string | Space ID |
|
||||
| ↳ `pageId` | string | Page ID |
|
||||
| ↳ `blogPostId` | string | Blog post ID |
|
||||
| ↳ `status` | string | Task status \(complete or incomplete\) |
|
||||
| ↳ `body` | string | Task body content in storage format |
|
||||
| ↳ `createdBy` | string | Creator account ID |
|
||||
| ↳ `assignedTo` | string | Assignee account ID |
|
||||
| ↳ `completedBy` | string | Completer account ID |
|
||||
| ↳ `createdAt` | string | Creation timestamp |
|
||||
| ↳ `updatedAt` | string | Last update timestamp |
|
||||
| ↳ `dueAt` | string | Due date |
|
||||
| ↳ `completedAt` | string | Completion timestamp |
|
||||
| `nextCursor` | string | Cursor for fetching the next page of results |
|
||||
|
||||
### `confluence_get_task`
|
||||
|
||||
Get a specific Confluence inline task by ID.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `taskId` | string | Yes | The ID of the task to retrieve |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `id` | string | Task ID |
|
||||
| `localId` | string | Local task ID |
|
||||
| `spaceId` | string | Space ID |
|
||||
| `pageId` | string | Page ID |
|
||||
| `blogPostId` | string | Blog post ID |
|
||||
| `status` | string | Task status \(complete or incomplete\) |
|
||||
| `body` | string | Task body content in storage format |
|
||||
| `createdBy` | string | Creator account ID |
|
||||
| `assignedTo` | string | Assignee account ID |
|
||||
| `completedBy` | string | Completer account ID |
|
||||
| `createdAt` | string | Creation timestamp |
|
||||
| `updatedAt` | string | Last update timestamp |
|
||||
| `dueAt` | string | Due date |
|
||||
| `completedAt` | string | Completion timestamp |
|
||||
|
||||
### `confluence_update_task`
|
||||
|
||||
Update the status of a Confluence inline task (complete or incomplete).
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `taskId` | string | Yes | The ID of the task to update |
|
||||
| `status` | string | Yes | New status for the task \(complete or incomplete\) |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `id` | string | Task ID |
|
||||
| `localId` | string | Local task ID |
|
||||
| `spaceId` | string | Space ID |
|
||||
| `pageId` | string | Page ID |
|
||||
| `blogPostId` | string | Blog post ID |
|
||||
| `status` | string | Updated task status |
|
||||
| `body` | string | Task body content in storage format |
|
||||
| `createdBy` | string | Creator account ID |
|
||||
| `assignedTo` | string | Assignee account ID |
|
||||
| `completedBy` | string | Completer account ID |
|
||||
| `createdAt` | string | Creation timestamp |
|
||||
| `updatedAt` | string | Last update timestamp |
|
||||
| `dueAt` | string | Due date |
|
||||
| `completedAt` | string | Completion timestamp |
|
||||
|
||||
### `confluence_update_blogpost`
|
||||
|
||||
Update an existing Confluence blog post title and/or content.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `blogPostId` | string | Yes | The ID of the blog post to update |
|
||||
| `title` | string | No | New title for the blog post |
|
||||
| `content` | string | No | New content for the blog post in storage format |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `blogPostId` | string | Updated blog post ID |
|
||||
| `title` | string | Blog post title |
|
||||
| `status` | string | Blog post status |
|
||||
| `spaceId` | string | Space ID |
|
||||
| `version` | json | Version information |
|
||||
| `url` | string | URL to view the blog post |
|
||||
|
||||
### `confluence_delete_blogpost`
|
||||
|
||||
Delete a Confluence blog post.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `blogPostId` | string | Yes | The ID of the blog post to delete |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `blogPostId` | string | Deleted blog post ID |
|
||||
| `deleted` | boolean | Deletion status |
|
||||
|
||||
### `confluence_get_user`
|
||||
|
||||
Get display name and profile info for a Confluence user by account ID.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Confluence domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `accountId` | string | Yes | The Atlassian account ID of the user to look up |
|
||||
| `cloudId` | string | No | Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `accountId` | string | Atlassian account ID of the user |
|
||||
| `displayName` | string | Display name of the user |
|
||||
| `email` | string | Email address of the user |
|
||||
| `accountType` | string | Account type \(e.g., atlassian, app, customer\) |
|
||||
| `profilePicture` | string | Path to the user profile picture |
|
||||
| `publicName` | string | Public name of the user |
|
||||
|
||||
|
||||
|
||||
@@ -147,4 +147,4 @@
|
||||
"zep",
|
||||
"zoom"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -283,3 +283,165 @@ export async function POST(request: NextRequest) {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a blog post
|
||||
*/
|
||||
export async function PUT(request: NextRequest) {
|
||||
try {
|
||||
const auth = await checkSessionOrInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const { domain, accessToken, blogPostId, title, content, cloudId: providedCloudId } = body
|
||||
|
||||
if (!domain || !accessToken || !blogPostId) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Domain, access token, and blog post ID are required' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const blogPostIdValidation = validateAlphanumericId(blogPostId, 'blogPostId', 255)
|
||||
if (!blogPostIdValidation.isValid) {
|
||||
return NextResponse.json({ error: blogPostIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const cloudId = providedCloudId || (await getConfluenceCloudId(domain, accessToken))
|
||||
|
||||
const cloudIdValidation = validateJiraCloudId(cloudId, 'cloudId')
|
||||
if (!cloudIdValidation.isValid) {
|
||||
return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
// Fetch current blog post to get version number
|
||||
const currentUrl = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/blogposts/${blogPostId}?body-format=storage`
|
||||
const currentResponse = await fetch(currentUrl, {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!currentResponse.ok) {
|
||||
throw new Error(`Failed to fetch current blog post: ${currentResponse.status}`)
|
||||
}
|
||||
|
||||
const currentPost = await currentResponse.json()
|
||||
|
||||
if (!currentPost.version?.number) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Unable to determine current blog post version' },
|
||||
{ status: 422 }
|
||||
)
|
||||
}
|
||||
|
||||
const currentVersion = currentPost.version.number
|
||||
|
||||
const updateBody: Record<string, unknown> = {
|
||||
id: blogPostId,
|
||||
version: { number: currentVersion + 1 },
|
||||
status: 'current',
|
||||
title: title || currentPost.title,
|
||||
body: {
|
||||
representation: 'storage',
|
||||
value: content || currentPost.body?.storage?.value || '',
|
||||
},
|
||||
}
|
||||
|
||||
const response = await fetch(currentUrl, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
body: JSON.stringify(updateBody),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage = errorData?.message || `Failed to update blog post (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
logger.error('Error updating blog post:', error)
|
||||
return NextResponse.json(
|
||||
{ error: (error as Error).message || 'Internal server error' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a blog post
|
||||
*/
|
||||
export async function DELETE(request: NextRequest) {
|
||||
try {
|
||||
const auth = await checkSessionOrInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const { domain, accessToken, blogPostId, cloudId: providedCloudId } = body
|
||||
|
||||
if (!domain || !accessToken || !blogPostId) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Domain, access token, and blog post ID are required' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const blogPostIdValidation = validateAlphanumericId(blogPostId, 'blogPostId', 255)
|
||||
if (!blogPostIdValidation.isValid) {
|
||||
return NextResponse.json({ error: blogPostIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const cloudId = providedCloudId || (await getConfluenceCloudId(domain, accessToken))
|
||||
|
||||
const cloudIdValidation = validateJiraCloudId(cloudId, 'cloudId')
|
||||
if (!cloudIdValidation.isValid) {
|
||||
return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const url = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/blogposts/${blogPostId}`
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage = errorData?.message || `Failed to delete blog post (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
return NextResponse.json({ blogPostId, deleted: true })
|
||||
} catch (error) {
|
||||
logger.error('Error deleting blog post:', error)
|
||||
return NextResponse.json(
|
||||
{ error: (error as Error).message || 'Internal server error' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
107
apps/sim/app/api/tools/confluence/page-descendants/route.ts
Normal file
107
apps/sim/app/api/tools/confluence/page-descendants/route.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { validateAlphanumericId, validateJiraCloudId } from '@/lib/core/security/input-validation'
|
||||
import { getConfluenceCloudId } from '@/tools/confluence/utils'
|
||||
|
||||
const logger = createLogger('ConfluencePageDescendantsAPI')
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
/**
|
||||
* Get all descendants of a Confluence page recursively.
|
||||
* Uses GET /wiki/api/v2/pages/{id}/descendants
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const auth = await checkSessionOrInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const { domain, accessToken, pageId, cloudId: providedCloudId, limit = 50, cursor } = body
|
||||
|
||||
if (!domain) {
|
||||
return NextResponse.json({ error: 'Domain is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!accessToken) {
|
||||
return NextResponse.json({ error: 'Access token is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!pageId) {
|
||||
return NextResponse.json({ error: 'Page ID is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
const pageIdValidation = validateAlphanumericId(pageId, 'pageId', 255)
|
||||
if (!pageIdValidation.isValid) {
|
||||
return NextResponse.json({ error: pageIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const cloudId = providedCloudId || (await getConfluenceCloudId(domain, accessToken))
|
||||
|
||||
const cloudIdValidation = validateJiraCloudId(cloudId, 'cloudId')
|
||||
if (!cloudIdValidation.isValid) {
|
||||
return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const queryParams = new URLSearchParams()
|
||||
queryParams.append('limit', String(Math.min(limit, 250)))
|
||||
|
||||
if (cursor) {
|
||||
queryParams.append('cursor', cursor)
|
||||
}
|
||||
|
||||
const url = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/pages/${pageId}/descendants?${queryParams.toString()}`
|
||||
|
||||
logger.info(`Fetching descendants for page ${pageId}`)
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage =
|
||||
errorData?.message || `Failed to get page descendants (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
const descendants = (data.results || []).map((page: any) => ({
|
||||
id: page.id,
|
||||
title: page.title,
|
||||
type: page.type ?? null,
|
||||
status: page.status ?? null,
|
||||
spaceId: page.spaceId ?? null,
|
||||
parentId: page.parentId ?? null,
|
||||
childPosition: page.childPosition ?? null,
|
||||
depth: page.depth ?? null,
|
||||
}))
|
||||
|
||||
return NextResponse.json({
|
||||
descendants,
|
||||
pageId,
|
||||
nextCursor: data._links?.next
|
||||
? new URL(data._links.next, 'https://placeholder').searchParams.get('cursor')
|
||||
: null,
|
||||
})
|
||||
} catch (error) {
|
||||
logger.error('Error getting page descendants:', error)
|
||||
return NextResponse.json(
|
||||
{ error: (error as Error).message || 'Internal server error' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -185,7 +185,7 @@ export async function PUT(request: NextRequest) {
|
||||
return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const currentPageUrl = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/pages/${pageId}`
|
||||
const currentPageUrl = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/pages/${pageId}?body-format=storage`
|
||||
const currentPageResponse = await fetch(currentPageUrl, {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
|
||||
106
apps/sim/app/api/tools/confluence/space-permissions/route.ts
Normal file
106
apps/sim/app/api/tools/confluence/space-permissions/route.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { validateAlphanumericId, validateJiraCloudId } from '@/lib/core/security/input-validation'
|
||||
import { getConfluenceCloudId } from '@/tools/confluence/utils'
|
||||
|
||||
const logger = createLogger('ConfluenceSpacePermissionsAPI')
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
/**
|
||||
* List permissions for a Confluence space.
|
||||
* Uses GET /wiki/api/v2/spaces/{id}/permissions
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const auth = await checkSessionOrInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const { domain, accessToken, spaceId, cloudId: providedCloudId, limit = 50, cursor } = body
|
||||
|
||||
if (!domain) {
|
||||
return NextResponse.json({ error: 'Domain is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!accessToken) {
|
||||
return NextResponse.json({ error: 'Access token is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!spaceId) {
|
||||
return NextResponse.json({ error: 'Space ID is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
const spaceIdValidation = validateAlphanumericId(spaceId, 'spaceId', 255)
|
||||
if (!spaceIdValidation.isValid) {
|
||||
return NextResponse.json({ error: spaceIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const cloudId = providedCloudId || (await getConfluenceCloudId(domain, accessToken))
|
||||
|
||||
const cloudIdValidation = validateJiraCloudId(cloudId, 'cloudId')
|
||||
if (!cloudIdValidation.isValid) {
|
||||
return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const queryParams = new URLSearchParams()
|
||||
queryParams.append('limit', String(Math.min(limit, 250)))
|
||||
|
||||
if (cursor) {
|
||||
queryParams.append('cursor', cursor)
|
||||
}
|
||||
|
||||
const url = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/spaces/${spaceId}/permissions?${queryParams.toString()}`
|
||||
|
||||
logger.info(`Fetching permissions for space ${spaceId}`)
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage =
|
||||
errorData?.message || `Failed to list space permissions (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
const permissions = (data.results || []).map((perm: any) => ({
|
||||
id: perm.id,
|
||||
principalType: perm.principal?.type ?? null,
|
||||
principalId: perm.principal?.id ?? null,
|
||||
operationKey: perm.operation?.key ?? null,
|
||||
operationTargetType: perm.operation?.targetType ?? null,
|
||||
anonymousAccess: perm.anonymousAccess ?? false,
|
||||
unlicensedAccess: perm.unlicensedAccess ?? false,
|
||||
}))
|
||||
|
||||
return NextResponse.json({
|
||||
permissions,
|
||||
spaceId,
|
||||
nextCursor: data._links?.next
|
||||
? new URL(data._links.next, 'https://placeholder').searchParams.get('cursor')
|
||||
: null,
|
||||
})
|
||||
} catch (error) {
|
||||
logger.error('Error listing space permissions:', error)
|
||||
return NextResponse.json(
|
||||
{ error: (error as Error).message || 'Internal server error' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
199
apps/sim/app/api/tools/confluence/space-properties/route.ts
Normal file
199
apps/sim/app/api/tools/confluence/space-properties/route.ts
Normal file
@@ -0,0 +1,199 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { validateAlphanumericId, validateJiraCloudId } from '@/lib/core/security/input-validation'
|
||||
import { getConfluenceCloudId } from '@/tools/confluence/utils'
|
||||
|
||||
const logger = createLogger('ConfluenceSpacePropertiesAPI')
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
/**
|
||||
* List, create, or delete space properties.
|
||||
* Uses GET/POST /wiki/api/v2/spaces/{id}/properties
|
||||
* and DELETE /wiki/api/v2/spaces/{id}/properties/{propertyId}
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const auth = await checkSessionOrInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const {
|
||||
domain,
|
||||
accessToken,
|
||||
spaceId,
|
||||
cloudId: providedCloudId,
|
||||
action,
|
||||
key,
|
||||
value,
|
||||
propertyId,
|
||||
limit = 50,
|
||||
cursor,
|
||||
} = body
|
||||
|
||||
if (!domain) {
|
||||
return NextResponse.json({ error: 'Domain is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!accessToken) {
|
||||
return NextResponse.json({ error: 'Access token is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!spaceId) {
|
||||
return NextResponse.json({ error: 'Space ID is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
const spaceIdValidation = validateAlphanumericId(spaceId, 'spaceId', 255)
|
||||
if (!spaceIdValidation.isValid) {
|
||||
return NextResponse.json({ error: spaceIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const cloudId = providedCloudId || (await getConfluenceCloudId(domain, accessToken))
|
||||
|
||||
const cloudIdValidation = validateJiraCloudId(cloudId, 'cloudId')
|
||||
if (!cloudIdValidation.isValid) {
|
||||
return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const baseUrl = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/spaces/${spaceId}/properties`
|
||||
|
||||
// Validate required params for specific actions
|
||||
if (action === 'delete' && !propertyId) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Property ID is required for delete action' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
if (action === 'create' && !key) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Property key is required for create action' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Delete a property
|
||||
if (action === 'delete' && propertyId) {
|
||||
const propertyIdValidation = validateAlphanumericId(propertyId, 'propertyId', 255)
|
||||
if (!propertyIdValidation.isValid) {
|
||||
return NextResponse.json({ error: propertyIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const url = `${baseUrl}/${propertyId}`
|
||||
|
||||
logger.info(`Deleting space property ${propertyId} from space ${spaceId}`)
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage =
|
||||
errorData?.message || `Failed to delete space property (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
return NextResponse.json({ spaceId, propertyId, deleted: true })
|
||||
}
|
||||
|
||||
// Create a property
|
||||
if (action === 'create' && key) {
|
||||
logger.info(`Creating space property '${key}' on space ${spaceId}`)
|
||||
|
||||
const response = await fetch(baseUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
body: JSON.stringify({ key, value: value ?? {} }),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage =
|
||||
errorData?.message || `Failed to create space property (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json({
|
||||
propertyId: data.id,
|
||||
key: data.key,
|
||||
value: data.value ?? null,
|
||||
spaceId,
|
||||
})
|
||||
}
|
||||
|
||||
// List properties
|
||||
const queryParams = new URLSearchParams()
|
||||
queryParams.append('limit', String(Math.min(limit, 250)))
|
||||
|
||||
if (cursor) queryParams.append('cursor', cursor)
|
||||
|
||||
const url = `${baseUrl}?${queryParams.toString()}`
|
||||
|
||||
logger.info(`Fetching properties for space ${spaceId}`)
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage =
|
||||
errorData?.message || `Failed to list space properties (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
const properties = (data.results || []).map((prop: any) => ({
|
||||
id: prop.id,
|
||||
key: prop.key,
|
||||
value: prop.value ?? null,
|
||||
}))
|
||||
|
||||
return NextResponse.json({
|
||||
properties,
|
||||
spaceId,
|
||||
nextCursor: data._links?.next
|
||||
? new URL(data._links.next, 'https://placeholder').searchParams.get('cursor')
|
||||
: null,
|
||||
})
|
||||
} catch (error) {
|
||||
logger.error('Error with space properties:', error)
|
||||
return NextResponse.json(
|
||||
{ error: (error as Error).message || 'Internal server error' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -78,3 +78,258 @@ export async function GET(request: NextRequest) {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Confluence space.
|
||||
* Uses POST /wiki/api/v2/spaces
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const auth = await checkSessionOrInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const { domain, accessToken, name, key, description, cloudId: providedCloudId } = body
|
||||
|
||||
if (!domain) {
|
||||
return NextResponse.json({ error: 'Domain is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!accessToken) {
|
||||
return NextResponse.json({ error: 'Access token is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
return NextResponse.json({ error: 'Space name is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
return NextResponse.json({ error: 'Space key is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
const cloudId = providedCloudId || (await getConfluenceCloudId(domain, accessToken))
|
||||
|
||||
const cloudIdValidation = validateJiraCloudId(cloudId, 'cloudId')
|
||||
if (!cloudIdValidation.isValid) {
|
||||
return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const url = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/spaces`
|
||||
|
||||
const createBody: Record<string, unknown> = { name, key }
|
||||
if (description) {
|
||||
createBody.description = { value: description, representation: 'plain' }
|
||||
}
|
||||
|
||||
logger.info(`Creating space with key ${key}`)
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
body: JSON.stringify(createBody),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage = errorData?.message || `Failed to create space (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
logger.error('Error creating Confluence space:', error)
|
||||
return NextResponse.json(
|
||||
{ error: (error as Error).message || 'Internal server error' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a Confluence space.
|
||||
* Uses PUT /wiki/api/v2/spaces/{id}
|
||||
*/
|
||||
export async function PUT(request: NextRequest) {
|
||||
try {
|
||||
const auth = await checkSessionOrInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const { domain, accessToken, spaceId, name, description, cloudId: providedCloudId } = body
|
||||
|
||||
if (!domain) {
|
||||
return NextResponse.json({ error: 'Domain is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!accessToken) {
|
||||
return NextResponse.json({ error: 'Access token is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!spaceId) {
|
||||
return NextResponse.json({ error: 'Space ID is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
const spaceIdValidation = validateAlphanumericId(spaceId, 'spaceId', 255)
|
||||
if (!spaceIdValidation.isValid) {
|
||||
return NextResponse.json({ error: spaceIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const cloudId = providedCloudId || (await getConfluenceCloudId(domain, accessToken))
|
||||
|
||||
const cloudIdValidation = validateJiraCloudId(cloudId, 'cloudId')
|
||||
if (!cloudIdValidation.isValid) {
|
||||
return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const url = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/spaces/${spaceId}`
|
||||
|
||||
if (!name && description === undefined) {
|
||||
return NextResponse.json(
|
||||
{ error: 'At least one of name or description is required for update' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const updateBody: Record<string, unknown> = {}
|
||||
|
||||
if (name) {
|
||||
updateBody.name = name
|
||||
} else {
|
||||
const currentResponse = await fetch(url, {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
if (!currentResponse.ok) {
|
||||
return NextResponse.json(
|
||||
{ error: `Failed to fetch current space: ${currentResponse.status}` },
|
||||
{ status: currentResponse.status }
|
||||
)
|
||||
}
|
||||
const currentSpace = await currentResponse.json()
|
||||
updateBody.name = currentSpace.name
|
||||
}
|
||||
|
||||
if (description !== undefined) {
|
||||
updateBody.description = { value: description, representation: 'plain' }
|
||||
}
|
||||
|
||||
logger.info(`Updating space ${spaceId}`)
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
body: JSON.stringify(updateBody),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage = errorData?.message || `Failed to update space (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
logger.error('Error updating Confluence space:', error)
|
||||
return NextResponse.json(
|
||||
{ error: (error as Error).message || 'Internal server error' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a Confluence space.
|
||||
* Uses DELETE /wiki/api/v2/spaces/{id}
|
||||
*/
|
||||
export async function DELETE(request: NextRequest) {
|
||||
try {
|
||||
const auth = await checkSessionOrInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const { domain, accessToken, spaceId, cloudId: providedCloudId } = body
|
||||
|
||||
if (!domain) {
|
||||
return NextResponse.json({ error: 'Domain is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!accessToken) {
|
||||
return NextResponse.json({ error: 'Access token is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!spaceId) {
|
||||
return NextResponse.json({ error: 'Space ID is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
const spaceIdValidation = validateAlphanumericId(spaceId, 'spaceId', 255)
|
||||
if (!spaceIdValidation.isValid) {
|
||||
return NextResponse.json({ error: spaceIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const cloudId = providedCloudId || (await getConfluenceCloudId(domain, accessToken))
|
||||
|
||||
const cloudIdValidation = validateJiraCloudId(cloudId, 'cloudId')
|
||||
if (!cloudIdValidation.isValid) {
|
||||
return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const url = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/spaces/${spaceId}`
|
||||
|
||||
logger.info(`Deleting space ${spaceId}`)
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage = errorData?.message || `Failed to delete space (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
return NextResponse.json({ spaceId, deleted: true })
|
||||
} catch (error) {
|
||||
logger.error('Error deleting Confluence space:', error)
|
||||
return NextResponse.json(
|
||||
{ error: (error as Error).message || 'Internal server error' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
244
apps/sim/app/api/tools/confluence/tasks/route.ts
Normal file
244
apps/sim/app/api/tools/confluence/tasks/route.ts
Normal file
@@ -0,0 +1,244 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { validateAlphanumericId, validateJiraCloudId } from '@/lib/core/security/input-validation'
|
||||
import { getConfluenceCloudId } from '@/tools/confluence/utils'
|
||||
|
||||
const logger = createLogger('ConfluenceTasksAPI')
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
/**
|
||||
* List, get, or update Confluence inline tasks.
|
||||
* Uses GET /wiki/api/v2/tasks, GET /wiki/api/v2/tasks/{id}, PUT /wiki/api/v2/tasks/{id}
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const auth = await checkSessionOrInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const {
|
||||
domain,
|
||||
accessToken,
|
||||
cloudId: providedCloudId,
|
||||
action,
|
||||
taskId,
|
||||
status: taskStatus,
|
||||
pageId,
|
||||
spaceId,
|
||||
assignedTo,
|
||||
limit = 50,
|
||||
cursor,
|
||||
} = body
|
||||
|
||||
if (!domain) {
|
||||
return NextResponse.json({ error: 'Domain is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!accessToken) {
|
||||
return NextResponse.json({ error: 'Access token is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
const cloudId = providedCloudId || (await getConfluenceCloudId(domain, accessToken))
|
||||
|
||||
const cloudIdValidation = validateJiraCloudId(cloudId, 'cloudId')
|
||||
if (!cloudIdValidation.isValid) {
|
||||
return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
// Update a task
|
||||
if (action === 'update' && taskId) {
|
||||
const taskIdValidation = validateAlphanumericId(taskId, 'taskId', 255)
|
||||
if (!taskIdValidation.isValid) {
|
||||
return NextResponse.json({ error: taskIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
// First fetch the current task to get required fields
|
||||
const getUrl = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/tasks/${taskId}`
|
||||
const getResponse = await fetch(getUrl, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!getResponse.ok) {
|
||||
const errorData = await getResponse.json().catch(() => null)
|
||||
const errorMessage = errorData?.message || `Failed to fetch task (${getResponse.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: getResponse.status })
|
||||
}
|
||||
|
||||
const currentTask = await getResponse.json()
|
||||
|
||||
const updateBody: Record<string, unknown> = {
|
||||
id: taskId,
|
||||
status: taskStatus || currentTask.status,
|
||||
}
|
||||
|
||||
const url = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/tasks/${taskId}`
|
||||
|
||||
logger.info(`Updating task ${taskId}`)
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
body: JSON.stringify(updateBody),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage = errorData?.message || `Failed to update task (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json({
|
||||
task: {
|
||||
id: data.id,
|
||||
localId: data.localId ?? null,
|
||||
spaceId: data.spaceId ?? null,
|
||||
pageId: data.pageId ?? null,
|
||||
blogPostId: data.blogPostId ?? null,
|
||||
status: data.status,
|
||||
body: data.body?.storage?.value ?? null,
|
||||
createdBy: data.createdBy ?? null,
|
||||
assignedTo: data.assignedTo ?? null,
|
||||
completedBy: data.completedBy ?? null,
|
||||
createdAt: data.createdAt ?? null,
|
||||
updatedAt: data.updatedAt ?? null,
|
||||
dueAt: data.dueAt ?? null,
|
||||
completedAt: data.completedAt ?? null,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Get a specific task
|
||||
if (taskId) {
|
||||
const taskIdValidation = validateAlphanumericId(taskId, 'taskId', 255)
|
||||
if (!taskIdValidation.isValid) {
|
||||
return NextResponse.json({ error: taskIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const url = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/tasks/${taskId}`
|
||||
|
||||
logger.info(`Fetching task ${taskId}`)
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage = errorData?.message || `Failed to get task (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json({
|
||||
task: {
|
||||
id: data.id,
|
||||
localId: data.localId ?? null,
|
||||
spaceId: data.spaceId ?? null,
|
||||
pageId: data.pageId ?? null,
|
||||
blogPostId: data.blogPostId ?? null,
|
||||
status: data.status,
|
||||
body: data.body?.storage?.value ?? null,
|
||||
createdBy: data.createdBy ?? null,
|
||||
assignedTo: data.assignedTo ?? null,
|
||||
completedBy: data.completedBy ?? null,
|
||||
createdAt: data.createdAt ?? null,
|
||||
updatedAt: data.updatedAt ?? null,
|
||||
dueAt: data.dueAt ?? null,
|
||||
completedAt: data.completedAt ?? null,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// List tasks
|
||||
const queryParams = new URLSearchParams()
|
||||
queryParams.append('limit', String(Math.min(limit, 250)))
|
||||
|
||||
if (cursor) queryParams.append('cursor', cursor)
|
||||
if (taskStatus) queryParams.append('status', taskStatus)
|
||||
if (pageId) queryParams.append('page-id', pageId)
|
||||
if (spaceId) queryParams.append('space-id', spaceId)
|
||||
if (assignedTo) queryParams.append('assigned-to', assignedTo)
|
||||
|
||||
const url = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/tasks?${queryParams.toString()}`
|
||||
|
||||
logger.info('Fetching tasks')
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage = errorData?.message || `Failed to list tasks (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
const tasks = (data.results || []).map((task: any) => ({
|
||||
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?.storage?.value ?? 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,
|
||||
}))
|
||||
|
||||
return NextResponse.json({
|
||||
tasks,
|
||||
nextCursor: data._links?.next
|
||||
? new URL(data._links.next, 'https://placeholder').searchParams.get('cursor')
|
||||
: null,
|
||||
})
|
||||
} catch (error) {
|
||||
logger.error('Error with tasks:', error)
|
||||
return NextResponse.json(
|
||||
{ error: (error as Error).message || 'Internal server error' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
85
apps/sim/app/api/tools/confluence/user/route.ts
Normal file
85
apps/sim/app/api/tools/confluence/user/route.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { validateJiraCloudId, validatePathSegment } from '@/lib/core/security/input-validation'
|
||||
import { getConfluenceCloudId } from '@/tools/confluence/utils'
|
||||
|
||||
const logger = createLogger('ConfluenceUserAPI')
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
/**
|
||||
* Get a Confluence user by account ID.
|
||||
* Uses GET /wiki/rest/api/user?accountId={accountId}
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const auth = await checkSessionOrInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const { domain, accessToken, accountId, cloudId: providedCloudId } = body
|
||||
|
||||
if (!domain) {
|
||||
return NextResponse.json({ error: 'Domain is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!accessToken) {
|
||||
return NextResponse.json({ error: 'Access token is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!accountId) {
|
||||
return NextResponse.json({ error: 'Account ID is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
// Atlassian account IDs use format like 557058:6b9c9931-4693-49c1-8b3a-931f1af98134
|
||||
const accountIdValidation = validatePathSegment(accountId, {
|
||||
paramName: 'accountId',
|
||||
maxLength: 255,
|
||||
customPattern: /^[a-zA-Z0-9:-]+$/,
|
||||
})
|
||||
if (!accountIdValidation.isValid) {
|
||||
return NextResponse.json({ error: accountIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const cloudId = providedCloudId || (await getConfluenceCloudId(domain, accessToken))
|
||||
|
||||
const cloudIdValidation = validateJiraCloudId(cloudId, 'cloudId')
|
||||
if (!cloudIdValidation.isValid) {
|
||||
return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const url = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/rest/api/user?accountId=${encodeURIComponent(accountId)}`
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null)
|
||||
logger.error('Confluence API error response:', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: JSON.stringify(errorData, null, 2),
|
||||
})
|
||||
const errorMessage =
|
||||
errorData?.message || `Failed to get Confluence user (${response.status})`
|
||||
return NextResponse.json({ error: errorMessage }, { status: response.status })
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
logger.error('Error getting Confluence user:', error)
|
||||
return NextResponse.json(
|
||||
{ error: (error as Error).message || 'Internal server error' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,15 @@ const SCOPE_DESCRIPTIONS: Record<string, string> = {
|
||||
'write:content.property:confluence': 'Create and manage content properties',
|
||||
'read:hierarchical-content:confluence': 'View page hierarchy (children and ancestors)',
|
||||
'read:content.metadata:confluence': 'View content metadata (required for ancestors)',
|
||||
'read:user:confluence': 'View Confluence user profiles',
|
||||
'read:task:confluence': 'View Confluence inline tasks',
|
||||
'write:task:confluence': 'Update Confluence inline tasks',
|
||||
'delete:blogpost:confluence': 'Delete Confluence blog posts',
|
||||
'write:space:confluence': 'Create and update Confluence spaces',
|
||||
'delete:space:confluence': 'Delete Confluence spaces',
|
||||
'read:space.property:confluence': 'View Confluence space properties',
|
||||
'write:space.property:confluence': 'Create and manage space properties',
|
||||
'read:space.permission:confluence': 'View Confluence space permissions',
|
||||
'read:me': 'Read profile information',
|
||||
'database.read': 'Read database',
|
||||
'database.write': 'Write to database',
|
||||
|
||||
@@ -84,6 +84,7 @@ export const ConfluenceBlock: BlockConfig<ConfluenceResponse> = {
|
||||
'write:content.property:confluence',
|
||||
'read:hierarchical-content:confluence',
|
||||
'read:content.metadata:confluence',
|
||||
'read:user:confluence',
|
||||
],
|
||||
placeholder: 'Select Confluence account',
|
||||
required: true,
|
||||
@@ -414,6 +415,8 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
{ label: 'List Blog Posts', id: 'list_blogposts' },
|
||||
{ label: 'Get Blog Post', id: 'get_blogpost' },
|
||||
{ label: 'Create Blog Post', id: 'create_blogpost' },
|
||||
{ label: 'Update Blog Post', id: 'update_blogpost' },
|
||||
{ label: 'Delete Blog Post', id: 'delete_blogpost' },
|
||||
{ label: 'List Blog Posts in Space', id: 'list_blogposts_in_space' },
|
||||
// Comment Operations
|
||||
{ label: 'Create Comment', id: 'create_comment' },
|
||||
@@ -432,7 +435,24 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
{ label: 'List Space Labels', id: 'list_space_labels' },
|
||||
// Space Operations
|
||||
{ label: 'Get Space', id: 'get_space' },
|
||||
{ label: 'Create Space', id: 'create_space' },
|
||||
{ label: 'Update Space', id: 'update_space' },
|
||||
{ label: 'Delete Space', id: 'delete_space' },
|
||||
{ label: 'List Spaces', id: 'list_spaces' },
|
||||
// Space Property Operations
|
||||
{ label: 'List Space Properties', id: 'list_space_properties' },
|
||||
{ label: 'Create Space Property', id: 'create_space_property' },
|
||||
{ label: 'Delete Space Property', id: 'delete_space_property' },
|
||||
// Space Permission Operations
|
||||
{ label: 'List Space Permissions', id: 'list_space_permissions' },
|
||||
// Page Descendant Operations
|
||||
{ label: 'Get Page Descendants', id: 'get_page_descendants' },
|
||||
// Task Operations
|
||||
{ label: 'List Tasks', id: 'list_tasks' },
|
||||
{ label: 'Get Task', id: 'get_task' },
|
||||
{ label: 'Update Task', id: 'update_task' },
|
||||
// User Operations
|
||||
{ label: 'Get User', id: 'get_user' },
|
||||
],
|
||||
value: () => 'read',
|
||||
},
|
||||
@@ -472,6 +492,15 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
'write:content.property:confluence',
|
||||
'read:hierarchical-content:confluence',
|
||||
'read:content.metadata:confluence',
|
||||
'read:user:confluence',
|
||||
'read:task:confluence',
|
||||
'write:task:confluence',
|
||||
'delete:blogpost:confluence',
|
||||
'write:space:confluence',
|
||||
'delete:space:confluence',
|
||||
'read:space.property:confluence',
|
||||
'write:space.property:confluence',
|
||||
'read:space.permission:confluence',
|
||||
],
|
||||
placeholder: 'Select Confluence account',
|
||||
required: true,
|
||||
@@ -507,13 +536,26 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
'list_pages_in_space',
|
||||
'list_blogposts',
|
||||
'get_blogpost',
|
||||
'update_blogpost',
|
||||
'delete_blogpost',
|
||||
'list_blogposts_in_space',
|
||||
'search',
|
||||
'search_in_space',
|
||||
'get_space',
|
||||
'create_space',
|
||||
'update_space',
|
||||
'delete_space',
|
||||
'list_spaces',
|
||||
'get_pages_by_label',
|
||||
'list_space_labels',
|
||||
'list_space_permissions',
|
||||
'list_space_properties',
|
||||
'create_space_property',
|
||||
'delete_space_property',
|
||||
'list_tasks',
|
||||
'get_task',
|
||||
'update_task',
|
||||
'get_user',
|
||||
],
|
||||
not: true,
|
||||
},
|
||||
@@ -537,6 +579,7 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
'get_page_version',
|
||||
'list_page_properties',
|
||||
'create_page_property',
|
||||
'get_page_descendants',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -553,13 +596,26 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
'list_pages_in_space',
|
||||
'list_blogposts',
|
||||
'get_blogpost',
|
||||
'update_blogpost',
|
||||
'delete_blogpost',
|
||||
'list_blogposts_in_space',
|
||||
'search',
|
||||
'search_in_space',
|
||||
'get_space',
|
||||
'create_space',
|
||||
'update_space',
|
||||
'delete_space',
|
||||
'list_spaces',
|
||||
'get_pages_by_label',
|
||||
'list_space_labels',
|
||||
'list_space_permissions',
|
||||
'list_space_properties',
|
||||
'create_space_property',
|
||||
'delete_space_property',
|
||||
'list_tasks',
|
||||
'get_task',
|
||||
'update_task',
|
||||
'get_user',
|
||||
],
|
||||
not: true,
|
||||
},
|
||||
@@ -583,6 +639,7 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
'get_page_version',
|
||||
'list_page_properties',
|
||||
'create_page_property',
|
||||
'get_page_descendants',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -597,11 +654,17 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
value: [
|
||||
'create',
|
||||
'get_space',
|
||||
'update_space',
|
||||
'delete_space',
|
||||
'list_pages_in_space',
|
||||
'search_in_space',
|
||||
'create_blogpost',
|
||||
'list_blogposts_in_space',
|
||||
'list_space_labels',
|
||||
'list_space_permissions',
|
||||
'list_space_properties',
|
||||
'create_space_property',
|
||||
'delete_space_property',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -611,7 +674,10 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter blog post ID',
|
||||
required: true,
|
||||
condition: { field: 'operation', value: 'get_blogpost' },
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['get_blogpost', 'update_blogpost', 'delete_blogpost'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'versionNumber',
|
||||
@@ -621,6 +687,86 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
required: true,
|
||||
condition: { field: 'operation', value: 'get_page_version' },
|
||||
},
|
||||
{
|
||||
id: 'accountId',
|
||||
title: 'Account ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter Atlassian account ID',
|
||||
required: true,
|
||||
condition: { field: 'operation', value: 'get_user' },
|
||||
},
|
||||
{
|
||||
id: 'taskId',
|
||||
title: 'Task ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter task ID',
|
||||
required: true,
|
||||
condition: { field: 'operation', value: ['get_task', 'update_task'] },
|
||||
},
|
||||
{
|
||||
id: 'taskStatus',
|
||||
title: 'Task Status',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Complete', id: 'complete' },
|
||||
{ label: 'Incomplete', id: 'incomplete' },
|
||||
],
|
||||
value: () => 'complete',
|
||||
condition: { field: 'operation', value: 'update_task' },
|
||||
},
|
||||
{
|
||||
id: 'taskAssignedTo',
|
||||
title: 'Assigned To',
|
||||
type: 'short-input',
|
||||
placeholder: 'Filter by assignee account ID (optional)',
|
||||
condition: { field: 'operation', value: 'list_tasks' },
|
||||
},
|
||||
{
|
||||
id: 'spaceName',
|
||||
title: 'Space Name',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter space name',
|
||||
required: true,
|
||||
condition: { field: 'operation', value: 'create_space' },
|
||||
},
|
||||
{
|
||||
id: 'spaceKey',
|
||||
title: 'Space Key',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter space key (e.g., MYSPACE)',
|
||||
required: true,
|
||||
condition: { field: 'operation', value: 'create_space' },
|
||||
},
|
||||
{
|
||||
id: 'spaceDescription',
|
||||
title: 'Description',
|
||||
type: 'long-input',
|
||||
placeholder: 'Enter space description (optional)',
|
||||
condition: { field: 'operation', value: ['create_space', 'update_space'] },
|
||||
},
|
||||
{
|
||||
id: 'spacePropertyKey',
|
||||
title: 'Property Key',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter property key/name',
|
||||
required: true,
|
||||
condition: { field: 'operation', value: 'create_space_property' },
|
||||
},
|
||||
{
|
||||
id: 'spacePropertyValue',
|
||||
title: 'Property Value',
|
||||
type: 'long-input',
|
||||
placeholder: 'Enter property value (JSON supported)',
|
||||
condition: { field: 'operation', value: 'create_space_property' },
|
||||
},
|
||||
{
|
||||
id: 'spacePropertyId',
|
||||
title: 'Property ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter property ID to delete',
|
||||
required: true,
|
||||
condition: { field: 'operation', value: 'delete_space_property' },
|
||||
},
|
||||
{
|
||||
id: 'propertyKey',
|
||||
title: 'Property Key',
|
||||
@@ -650,14 +796,20 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
title: 'Title',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter title',
|
||||
condition: { field: 'operation', value: ['create', 'update', 'create_blogpost'] },
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['create', 'update', 'create_blogpost', 'update_blogpost', 'update_space'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'content',
|
||||
title: 'Content',
|
||||
type: 'long-input',
|
||||
placeholder: 'Enter content',
|
||||
condition: { field: 'operation', value: ['create', 'update', 'create_blogpost'] },
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['create', 'update', 'create_blogpost', 'update_blogpost'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'parentId',
|
||||
@@ -813,6 +965,10 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
'list_labels',
|
||||
'get_pages_by_label',
|
||||
'list_space_labels',
|
||||
'get_page_descendants',
|
||||
'list_space_permissions',
|
||||
'list_space_properties',
|
||||
'list_tasks',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -836,6 +992,10 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
'list_labels',
|
||||
'get_pages_by_label',
|
||||
'list_space_labels',
|
||||
'get_page_descendants',
|
||||
'list_space_permissions',
|
||||
'list_space_properties',
|
||||
'list_tasks',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -921,7 +1081,27 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
'confluence_list_space_labels',
|
||||
// Space Tools
|
||||
'confluence_get_space',
|
||||
'confluence_create_space',
|
||||
'confluence_update_space',
|
||||
'confluence_delete_space',
|
||||
'confluence_list_spaces',
|
||||
// Space Property Tools
|
||||
'confluence_list_space_properties',
|
||||
'confluence_create_space_property',
|
||||
'confluence_delete_space_property',
|
||||
// Space Permission Tools
|
||||
'confluence_list_space_permissions',
|
||||
// Page Descendant Tools
|
||||
'confluence_get_page_descendants',
|
||||
// Task Tools
|
||||
'confluence_list_tasks',
|
||||
'confluence_get_task',
|
||||
'confluence_update_task',
|
||||
// Blog Post Update/Delete
|
||||
'confluence_update_blogpost',
|
||||
'confluence_delete_blogpost',
|
||||
// User Tools
|
||||
'confluence_get_user',
|
||||
],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
@@ -965,6 +1145,10 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
return 'confluence_get_blogpost'
|
||||
case 'create_blogpost':
|
||||
return 'confluence_create_blogpost'
|
||||
case 'update_blogpost':
|
||||
return 'confluence_update_blogpost'
|
||||
case 'delete_blogpost':
|
||||
return 'confluence_delete_blogpost'
|
||||
case 'list_blogposts_in_space':
|
||||
return 'confluence_list_blogposts_in_space'
|
||||
// Comment Operations
|
||||
@@ -997,8 +1181,37 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
// Space Operations
|
||||
case 'get_space':
|
||||
return 'confluence_get_space'
|
||||
case 'create_space':
|
||||
return 'confluence_create_space'
|
||||
case 'update_space':
|
||||
return 'confluence_update_space'
|
||||
case 'delete_space':
|
||||
return 'confluence_delete_space'
|
||||
case 'list_spaces':
|
||||
return 'confluence_list_spaces'
|
||||
// Space Property Operations
|
||||
case 'list_space_properties':
|
||||
return 'confluence_list_space_properties'
|
||||
case 'create_space_property':
|
||||
return 'confluence_create_space_property'
|
||||
case 'delete_space_property':
|
||||
return 'confluence_delete_space_property'
|
||||
// Space Permission Operations
|
||||
case 'list_space_permissions':
|
||||
return 'confluence_list_space_permissions'
|
||||
// Page Descendant Operations
|
||||
case 'get_page_descendants':
|
||||
return 'confluence_get_page_descendants'
|
||||
// Task Operations
|
||||
case 'list_tasks':
|
||||
return 'confluence_list_tasks'
|
||||
case 'get_task':
|
||||
return 'confluence_get_task'
|
||||
case 'update_task':
|
||||
return 'confluence_update_task'
|
||||
// User Operations
|
||||
case 'get_user':
|
||||
return 'confluence_get_user'
|
||||
default:
|
||||
return 'confluence_retrieve'
|
||||
}
|
||||
@@ -1013,6 +1226,7 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
attachmentComment,
|
||||
blogPostId,
|
||||
versionNumber,
|
||||
accountId,
|
||||
propertyKey,
|
||||
propertyValue,
|
||||
propertyId,
|
||||
@@ -1022,6 +1236,15 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
purge,
|
||||
bodyFormat,
|
||||
cursor,
|
||||
taskId,
|
||||
taskStatus,
|
||||
taskAssignedTo,
|
||||
spaceName,
|
||||
spaceKey,
|
||||
spaceDescription,
|
||||
spacePropertyKey,
|
||||
spacePropertyValue,
|
||||
spacePropertyId,
|
||||
...rest
|
||||
} = params
|
||||
|
||||
@@ -1069,8 +1292,8 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
}
|
||||
|
||||
// Operations that support generic cursor pagination.
|
||||
// get_pages_by_label and list_space_labels have dedicated handlers
|
||||
// below that pass cursor along with their required params (labelId, spaceId).
|
||||
// get_pages_by_label, list_space_labels, and list_tasks have dedicated handlers
|
||||
// below that pass cursor along with their required params.
|
||||
const supportsCursor = [
|
||||
'list_attachments',
|
||||
'list_spaces',
|
||||
@@ -1081,6 +1304,9 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
'list_page_versions',
|
||||
'list_page_properties',
|
||||
'list_labels',
|
||||
'get_page_descendants',
|
||||
'list_space_permissions',
|
||||
'list_space_properties',
|
||||
]
|
||||
|
||||
if (supportsCursor.includes(operation) && cursor) {
|
||||
@@ -1152,6 +1378,122 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'get_user') {
|
||||
return {
|
||||
credential: oauthCredential,
|
||||
operation,
|
||||
accountId: accountId ? String(accountId).trim() : undefined,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'update_blogpost' || operation === 'delete_blogpost') {
|
||||
return {
|
||||
credential: oauthCredential,
|
||||
operation,
|
||||
blogPostId: blogPostId || undefined,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'create_space') {
|
||||
return {
|
||||
credential: oauthCredential,
|
||||
operation,
|
||||
name: spaceName,
|
||||
key: spaceKey,
|
||||
description: spaceDescription,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'update_space') {
|
||||
return {
|
||||
credential: oauthCredential,
|
||||
operation,
|
||||
name: spaceName || rest.title,
|
||||
description: spaceDescription,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'delete_space') {
|
||||
return {
|
||||
credential: oauthCredential,
|
||||
operation,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'create_space_property') {
|
||||
return {
|
||||
credential: oauthCredential,
|
||||
operation,
|
||||
key: spacePropertyKey,
|
||||
value: spacePropertyValue,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'delete_space_property') {
|
||||
return {
|
||||
credential: oauthCredential,
|
||||
operation,
|
||||
propertyId: spacePropertyId,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'list_space_permissions' || operation === 'list_space_properties') {
|
||||
return {
|
||||
credential: oauthCredential,
|
||||
operation,
|
||||
cursor: cursor || undefined,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'get_page_descendants') {
|
||||
return {
|
||||
credential: oauthCredential,
|
||||
pageId: effectivePageId,
|
||||
operation,
|
||||
cursor: cursor || undefined,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'get_task') {
|
||||
return {
|
||||
credential: oauthCredential,
|
||||
operation,
|
||||
taskId,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'update_task') {
|
||||
return {
|
||||
credential: oauthCredential,
|
||||
operation,
|
||||
taskId,
|
||||
status: taskStatus,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'list_tasks') {
|
||||
return {
|
||||
credential: oauthCredential,
|
||||
operation,
|
||||
pageId: effectivePageId || undefined,
|
||||
assignedTo: taskAssignedTo || undefined,
|
||||
status: taskStatus || undefined,
|
||||
cursor: cursor || undefined,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
credential: oauthCredential,
|
||||
pageId: effectivePageId || undefined,
|
||||
@@ -1171,6 +1513,7 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
spaceId: { type: 'string', description: 'Space identifier' },
|
||||
blogPostId: { type: 'string', description: 'Blog post identifier' },
|
||||
versionNumber: { type: 'number', description: 'Page version number' },
|
||||
accountId: { type: 'string', description: 'Atlassian account ID' },
|
||||
propertyKey: { type: 'string', description: 'Property key/name' },
|
||||
propertyValue: { type: 'json', description: 'Property value (JSON)' },
|
||||
title: { type: 'string', description: 'Page or blog post title' },
|
||||
@@ -1192,6 +1535,15 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
bodyFormat: { type: 'string', description: 'Body format for comments' },
|
||||
limit: { type: 'number', description: 'Maximum number of results' },
|
||||
cursor: { type: 'string', description: 'Pagination cursor from previous response' },
|
||||
taskId: { type: 'string', description: 'Task identifier' },
|
||||
taskStatus: { type: 'string', description: 'Task status (complete or incomplete)' },
|
||||
taskAssignedTo: { type: 'string', description: 'Filter tasks by assignee account ID' },
|
||||
spaceName: { type: 'string', description: 'Space name for create/update' },
|
||||
spaceKey: { type: 'string', description: 'Space key for create' },
|
||||
spaceDescription: { type: 'string', description: 'Space description' },
|
||||
spacePropertyKey: { type: 'string', description: 'Space property key' },
|
||||
spacePropertyValue: { type: 'json', description: 'Space property value' },
|
||||
spacePropertyId: { type: 'string', description: 'Space property identifier' },
|
||||
},
|
||||
outputs: {
|
||||
ts: { type: 'string', description: 'Timestamp' },
|
||||
@@ -1242,6 +1594,23 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
propertyId: { type: 'string', description: 'Property identifier' },
|
||||
propertyKey: { type: 'string', description: 'Property key' },
|
||||
propertyValue: { type: 'json', description: 'Property value' },
|
||||
// User Results
|
||||
accountId: { type: 'string', description: 'Atlassian account ID' },
|
||||
displayName: { type: 'string', description: 'User display name' },
|
||||
email: { type: 'string', description: 'User email address' },
|
||||
accountType: { type: 'string', description: 'Account type (atlassian, app, customer)' },
|
||||
profilePicture: { type: 'string', description: 'Path to user profile picture' },
|
||||
publicName: { type: 'string', description: 'User public name' },
|
||||
// Task Results
|
||||
tasks: { type: 'array', description: 'List of tasks' },
|
||||
taskId: { type: 'string', description: 'Task identifier' },
|
||||
// Descendant Results
|
||||
descendants: { type: 'array', description: 'List of descendant pages' },
|
||||
// Permission Results
|
||||
permissions: { type: 'array', description: 'List of space permissions' },
|
||||
// Space Property Results
|
||||
homepageId: { type: 'string', description: 'Space homepage ID' },
|
||||
description: { type: 'json', description: 'Space description' },
|
||||
// Pagination
|
||||
nextCursor: { type: 'string', description: 'Cursor for fetching next page of results' },
|
||||
},
|
||||
|
||||
@@ -1846,6 +1846,15 @@ export const auth = betterAuth({
|
||||
'write:content.property:confluence',
|
||||
'read:hierarchical-content:confluence',
|
||||
'read:content.metadata:confluence',
|
||||
'read:user:confluence',
|
||||
'read:task:confluence',
|
||||
'write:task:confluence',
|
||||
'delete:blogpost:confluence',
|
||||
'write:space:confluence',
|
||||
'delete:space:confluence',
|
||||
'read:space.property:confluence',
|
||||
'write:space.property:confluence',
|
||||
'read:space.permission:confluence',
|
||||
],
|
||||
responseType: 'code',
|
||||
pkce: true,
|
||||
|
||||
@@ -330,6 +330,21 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
'search:confluence',
|
||||
'read:me',
|
||||
'offline_access',
|
||||
'read:blogpost:confluence',
|
||||
'write:blogpost:confluence',
|
||||
'delete:blogpost:confluence',
|
||||
'read:content.property:confluence',
|
||||
'write:content.property:confluence',
|
||||
'read:hierarchical-content:confluence',
|
||||
'read:content.metadata:confluence',
|
||||
'read:user:confluence',
|
||||
'read:task:confluence',
|
||||
'write:task:confluence',
|
||||
'write:space:confluence',
|
||||
'delete:space:confluence',
|
||||
'read:space.property:confluence',
|
||||
'write:space.property:confluence',
|
||||
'read:space.permission:confluence',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -270,9 +270,7 @@ async function auditWorkflowLockToggle(workflowId: string, actorId: string): Pro
|
||||
resourceType: AuditResourceType.WORKFLOW,
|
||||
resourceId: workflowId,
|
||||
resourceName: wf.name,
|
||||
description: allLocked
|
||||
? `Locked workflow "${wf.name}"`
|
||||
: `Unlocked workflow "${wf.name}"`,
|
||||
description: allLocked ? `Locked workflow "${wf.name}"` : `Unlocked workflow "${wf.name}"`,
|
||||
metadata: { blockCount: blocks.length },
|
||||
})
|
||||
}
|
||||
|
||||
134
apps/sim/tools/confluence/create_space.ts
Normal file
134
apps/sim/tools/confluence/create_space.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
import { SPACE_DESCRIPTION_OUTPUT_PROPERTIES, TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface ConfluenceCreateSpaceParams {
|
||||
accessToken: string
|
||||
domain: string
|
||||
name: string
|
||||
key: string
|
||||
description?: string
|
||||
cloudId?: string
|
||||
}
|
||||
|
||||
export interface ConfluenceCreateSpaceResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
ts: string
|
||||
spaceId: string
|
||||
name: string
|
||||
key: string
|
||||
type: string
|
||||
status: string
|
||||
url: string
|
||||
homepageId: string | null
|
||||
description: { value: string; representation: string } | null
|
||||
}
|
||||
}
|
||||
|
||||
export const confluenceCreateSpaceTool: ToolConfig<
|
||||
ConfluenceCreateSpaceParams,
|
||||
ConfluenceCreateSpaceResponse
|
||||
> = {
|
||||
id: 'confluence_create_space',
|
||||
name: 'Confluence Create Space',
|
||||
description: 'Create a new Confluence space.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'confluence',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'OAuth access token for Confluence',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name for the new space',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Unique key for the space (uppercase, no spaces)',
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Description for the new space',
|
||||
},
|
||||
cloudId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description:
|
||||
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => '/api/tools/confluence/space',
|
||||
method: 'POST',
|
||||
headers: (params: ConfluenceCreateSpaceParams) => ({
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params: ConfluenceCreateSpaceParams) => ({
|
||||
domain: params.domain,
|
||||
accessToken: params.accessToken,
|
||||
cloudId: params.cloudId,
|
||||
name: params.name,
|
||||
key: params.key,
|
||||
description: params.description,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
ts: new Date().toISOString(),
|
||||
spaceId: data.id ?? '',
|
||||
name: data.name ?? '',
|
||||
key: data.key ?? '',
|
||||
type: data.type ?? '',
|
||||
status: data.status ?? '',
|
||||
url: data._links?.webui ?? '',
|
||||
homepageId: data.homepageId ?? null,
|
||||
description: data.description ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ts: TIMESTAMP_OUTPUT,
|
||||
spaceId: { type: 'string', description: 'Created space ID' },
|
||||
name: { type: 'string', description: 'Space name' },
|
||||
key: { type: 'string', description: 'Space key' },
|
||||
type: { type: 'string', description: 'Space type' },
|
||||
status: { type: 'string', description: 'Space status' },
|
||||
url: { type: 'string', description: 'URL to view the space' },
|
||||
homepageId: { type: 'string', description: 'Homepage ID', optional: true },
|
||||
description: {
|
||||
type: 'object',
|
||||
description: 'Space description',
|
||||
properties: SPACE_DESCRIPTION_OUTPUT_PROPERTIES,
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
118
apps/sim/tools/confluence/create_space_property.ts
Normal file
118
apps/sim/tools/confluence/create_space_property.ts
Normal file
@@ -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' },
|
||||
},
|
||||
}
|
||||
95
apps/sim/tools/confluence/delete_blogpost.ts
Normal file
95
apps/sim/tools/confluence/delete_blogpost.ts
Normal file
@@ -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' },
|
||||
},
|
||||
}
|
||||
95
apps/sim/tools/confluence/delete_space.ts
Normal file
95
apps/sim/tools/confluence/delete_space.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ts: TIMESTAMP_OUTPUT,
|
||||
spaceId: { type: 'string', description: 'Deleted space ID' },
|
||||
deleted: { type: 'boolean', description: 'Deletion status' },
|
||||
},
|
||||
}
|
||||
107
apps/sim/tools/confluence/delete_space_property.ts
Normal file
107
apps/sim/tools/confluence/delete_space_property.ts
Normal file
@@ -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' },
|
||||
},
|
||||
}
|
||||
147
apps/sim/tools/confluence/get_page_descendants.ts
Normal file
147
apps/sim/tools/confluence/get_page_descendants.ts
Normal file
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
130
apps/sim/tools/confluence/get_task.ts
Normal file
130
apps/sim/tools/confluence/get_task.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface ConfluenceGetTaskParams {
|
||||
accessToken: string
|
||||
domain: string
|
||||
taskId: string
|
||||
cloudId?: string
|
||||
}
|
||||
|
||||
export interface ConfluenceGetTaskResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
ts: string
|
||||
id: string
|
||||
localId: string | null
|
||||
spaceId: string | null
|
||||
pageId: string | null
|
||||
blogPostId: string | null
|
||||
status: string
|
||||
body: string | null
|
||||
createdBy: string | null
|
||||
assignedTo: string | null
|
||||
completedBy: string | null
|
||||
createdAt: string | null
|
||||
updatedAt: string | null
|
||||
dueAt: string | null
|
||||
completedAt: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export const confluenceGetTaskTool: ToolConfig<ConfluenceGetTaskParams, ConfluenceGetTaskResponse> =
|
||||
{
|
||||
id: 'confluence_get_task',
|
||||
name: 'Confluence Get Task',
|
||||
description: 'Get a specific Confluence inline task by ID.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'confluence',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'OAuth access token for Confluence',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
|
||||
},
|
||||
taskId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the task to retrieve',
|
||||
},
|
||||
cloudId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description:
|
||||
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => '/api/tools/confluence/tasks',
|
||||
method: 'POST',
|
||||
headers: (params: ConfluenceGetTaskParams) => ({
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params: ConfluenceGetTaskParams) => ({
|
||||
domain: params.domain,
|
||||
accessToken: params.accessToken,
|
||||
cloudId: params.cloudId,
|
||||
taskId: params.taskId,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const task = data.task || data
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
ts: new Date().toISOString(),
|
||||
id: task.id ?? '',
|
||||
localId: task.localId ?? null,
|
||||
spaceId: task.spaceId ?? null,
|
||||
pageId: task.pageId ?? null,
|
||||
blogPostId: task.blogPostId ?? null,
|
||||
status: task.status ?? '',
|
||||
body: task.body ?? null,
|
||||
createdBy: task.createdBy ?? null,
|
||||
assignedTo: task.assignedTo ?? null,
|
||||
completedBy: task.completedBy ?? null,
|
||||
createdAt: task.createdAt ?? null,
|
||||
updatedAt: task.updatedAt ?? null,
|
||||
dueAt: task.dueAt ?? null,
|
||||
completedAt: task.completedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ts: TIMESTAMP_OUTPUT,
|
||||
id: { type: 'string', description: 'Task ID' },
|
||||
localId: { type: 'string', description: 'Local task ID', optional: true },
|
||||
spaceId: { type: 'string', description: 'Space ID', optional: true },
|
||||
pageId: { type: 'string', description: 'Page ID', optional: true },
|
||||
blogPostId: { type: 'string', description: 'Blog post ID', optional: true },
|
||||
status: { type: 'string', description: 'Task status (complete or incomplete)' },
|
||||
body: { type: 'string', description: 'Task body content in storage format', optional: true },
|
||||
createdBy: { type: 'string', description: 'Creator account ID', optional: true },
|
||||
assignedTo: { type: 'string', description: 'Assignee account ID', optional: true },
|
||||
completedBy: { type: 'string', description: 'Completer account ID', optional: true },
|
||||
createdAt: { type: 'string', description: 'Creation timestamp', optional: true },
|
||||
updatedAt: { type: 'string', description: 'Last update timestamp', optional: true },
|
||||
dueAt: { type: 'string', description: 'Due date', optional: true },
|
||||
completedAt: { type: 'string', description: 'Completion timestamp', optional: true },
|
||||
},
|
||||
}
|
||||
113
apps/sim/tools/confluence/get_user.ts
Normal file
113
apps/sim/tools/confluence/get_user.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface ConfluenceGetUserParams {
|
||||
accessToken: string
|
||||
domain: string
|
||||
accountId: string
|
||||
cloudId?: string
|
||||
}
|
||||
|
||||
export interface ConfluenceGetUserResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
ts: string
|
||||
accountId: string
|
||||
displayName: string
|
||||
email: string | null
|
||||
accountType: string | null
|
||||
profilePicture: string | null
|
||||
publicName: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export const confluenceGetUserTool: ToolConfig<ConfluenceGetUserParams, ConfluenceGetUserResponse> =
|
||||
{
|
||||
id: 'confluence_get_user',
|
||||
name: 'Confluence Get User',
|
||||
description: 'Get display name and profile info for a Confluence user by account ID.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'confluence',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'OAuth access token for Confluence',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
|
||||
},
|
||||
accountId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The Atlassian account ID of the user to look up',
|
||||
},
|
||||
cloudId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description:
|
||||
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => '/api/tools/confluence/user',
|
||||
method: 'POST',
|
||||
headers: (params: ConfluenceGetUserParams) => ({
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params: ConfluenceGetUserParams) => ({
|
||||
domain: params.domain,
|
||||
accessToken: params.accessToken,
|
||||
accountId: params.accountId?.trim(),
|
||||
cloudId: params.cloudId,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
ts: new Date().toISOString(),
|
||||
accountId: data.accountId ?? '',
|
||||
displayName: data.displayName ?? '',
|
||||
email: data.email ?? null,
|
||||
accountType: data.accountType ?? null,
|
||||
profilePicture: data.profilePicture?.path ?? null,
|
||||
publicName: data.publicName ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ts: TIMESTAMP_OUTPUT,
|
||||
accountId: { type: 'string', description: 'Atlassian account ID of the user' },
|
||||
displayName: { type: 'string', description: 'Display name of the user' },
|
||||
email: { type: 'string', description: 'Email address of the user', optional: true },
|
||||
accountType: {
|
||||
type: 'string',
|
||||
description: 'Account type (e.g., atlassian, app, customer)',
|
||||
optional: true,
|
||||
},
|
||||
profilePicture: {
|
||||
type: 'string',
|
||||
description: 'Path to the user profile picture',
|
||||
optional: true,
|
||||
},
|
||||
publicName: { type: 'string', description: 'Public name of the user', optional: true },
|
||||
},
|
||||
}
|
||||
@@ -3,17 +3,25 @@ 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'
|
||||
@@ -23,7 +31,10 @@ import { confluenceListPagePropertiesTool } from '@/tools/confluence/list_page_p
|
||||
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'
|
||||
@@ -64,7 +75,10 @@ import {
|
||||
VERSION_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/confluence/types'
|
||||
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 {
|
||||
@@ -76,6 +90,7 @@ export {
|
||||
confluenceListPagesInSpaceTool,
|
||||
confluenceGetPageChildrenTool,
|
||||
confluenceGetPageAncestorsTool,
|
||||
confluenceGetPageDescendantsTool,
|
||||
// Page Version Tools
|
||||
confluenceListPageVersionsTool,
|
||||
confluenceGetPageVersionTool,
|
||||
@@ -87,6 +102,8 @@ export {
|
||||
confluenceListBlogPostsTool,
|
||||
confluenceGetBlogPostTool,
|
||||
confluenceCreateBlogPostTool,
|
||||
confluenceUpdateBlogPostTool,
|
||||
confluenceDeleteBlogPostTool,
|
||||
confluenceListBlogPostsInSpaceTool,
|
||||
// Search Tools
|
||||
confluenceSearchTool,
|
||||
@@ -106,9 +123,24 @@ export {
|
||||
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,
|
||||
// Item property constants (for use in outputs)
|
||||
ATTACHMENT_ITEM_PROPERTIES,
|
||||
COMMENT_ITEM_PROPERTIES,
|
||||
|
||||
156
apps/sim/tools/confluence/list_space_permissions.ts
Normal file
156
apps/sim/tools/confluence/list_space_permissions.ts
Normal file
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
133
apps/sim/tools/confluence/list_space_properties.ts
Normal file
133
apps/sim/tools/confluence/list_space_properties.ts
Normal file
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
181
apps/sim/tools/confluence/list_tasks.ts
Normal file
181
apps/sim/tools/confluence/list_tasks.ts
Normal file
@@ -0,0 +1,181 @@
|
||||
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface ConfluenceListTasksParams {
|
||||
accessToken: string
|
||||
domain: string
|
||||
pageId?: string
|
||||
spaceId?: string
|
||||
assignedTo?: string
|
||||
status?: string
|
||||
limit?: number
|
||||
cursor?: string
|
||||
cloudId?: string
|
||||
}
|
||||
|
||||
export interface ConfluenceListTasksResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
ts: string
|
||||
tasks: Array<{
|
||||
id: string
|
||||
localId: string | null
|
||||
spaceId: string | null
|
||||
pageId: string | null
|
||||
blogPostId: string | null
|
||||
status: string
|
||||
body: string | null
|
||||
createdBy: string | null
|
||||
assignedTo: string | null
|
||||
completedBy: string | null
|
||||
createdAt: string | null
|
||||
updatedAt: string | null
|
||||
dueAt: string | null
|
||||
completedAt: string | null
|
||||
}>
|
||||
nextCursor: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export const confluenceListTasksTool: ToolConfig<
|
||||
ConfluenceListTasksParams,
|
||||
ConfluenceListTasksResponse
|
||||
> = {
|
||||
id: 'confluence_list_tasks',
|
||||
name: 'Confluence List Tasks',
|
||||
description:
|
||||
'List inline tasks from Confluence. Optionally filter by page, space, assignee, or status.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'confluence',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'OAuth access token for Confluence',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
|
||||
},
|
||||
pageId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter tasks by page ID',
|
||||
},
|
||||
spaceId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter tasks by space ID',
|
||||
},
|
||||
assignedTo: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter tasks by assignee account ID',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter tasks by status (complete or incomplete)',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of tasks to return (default: 50, max: 250)',
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Pagination cursor from previous response',
|
||||
},
|
||||
cloudId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description:
|
||||
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => '/api/tools/confluence/tasks',
|
||||
method: 'POST',
|
||||
headers: (params: ConfluenceListTasksParams) => ({
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params: ConfluenceListTasksParams) => ({
|
||||
domain: params.domain,
|
||||
accessToken: params.accessToken,
|
||||
cloudId: params.cloudId,
|
||||
pageId: params.pageId,
|
||||
spaceId: params.spaceId,
|
||||
assignedTo: params.assignedTo,
|
||||
status: params.status,
|
||||
limit: params.limit,
|
||||
cursor: params.cursor,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
ts: new Date().toISOString(),
|
||||
tasks: data.tasks || [],
|
||||
nextCursor: data.nextCursor ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ts: TIMESTAMP_OUTPUT,
|
||||
tasks: {
|
||||
type: 'array',
|
||||
description: 'Array of Confluence tasks',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Task ID' },
|
||||
localId: { type: 'string', description: 'Local task ID', optional: true },
|
||||
spaceId: { type: 'string', description: 'Space ID', optional: true },
|
||||
pageId: { type: 'string', description: 'Page ID', optional: true },
|
||||
blogPostId: { type: 'string', description: 'Blog post ID', optional: true },
|
||||
status: { type: 'string', description: 'Task status (complete or incomplete)' },
|
||||
body: {
|
||||
type: 'string',
|
||||
description: 'Task body content in storage format',
|
||||
optional: true,
|
||||
},
|
||||
createdBy: { type: 'string', description: 'Creator account ID', optional: true },
|
||||
assignedTo: { type: 'string', description: 'Assignee account ID', optional: true },
|
||||
completedBy: { type: 'string', description: 'Completer account ID', optional: true },
|
||||
createdAt: { type: 'string', description: 'Creation timestamp', optional: true },
|
||||
updatedAt: { type: 'string', description: 'Last update timestamp', optional: true },
|
||||
dueAt: { type: 'string', description: 'Due date', optional: true },
|
||||
completedAt: { type: 'string', description: 'Completion timestamp', optional: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
nextCursor: {
|
||||
type: 'string',
|
||||
description: 'Cursor for fetching the next page of results',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
123
apps/sim/tools/confluence/update_blogpost.ts
Normal file
123
apps/sim/tools/confluence/update_blogpost.ts
Normal file
@@ -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' },
|
||||
},
|
||||
}
|
||||
131
apps/sim/tools/confluence/update_space.ts
Normal file
131
apps/sim/tools/confluence/update_space.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import { SPACE_DESCRIPTION_OUTPUT_PROPERTIES, TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface ConfluenceUpdateSpaceParams {
|
||||
accessToken: string
|
||||
domain: string
|
||||
spaceId: string
|
||||
name?: string
|
||||
description?: string
|
||||
cloudId?: string
|
||||
}
|
||||
|
||||
export interface ConfluenceUpdateSpaceResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
ts: string
|
||||
spaceId: string
|
||||
name: string
|
||||
key: string
|
||||
type: string
|
||||
status: string
|
||||
url: string
|
||||
description: { value: string; representation: string } | null
|
||||
}
|
||||
}
|
||||
|
||||
export const confluenceUpdateSpaceTool: ToolConfig<
|
||||
ConfluenceUpdateSpaceParams,
|
||||
ConfluenceUpdateSpaceResponse
|
||||
> = {
|
||||
id: 'confluence_update_space',
|
||||
name: 'Confluence Update Space',
|
||||
description: 'Update a Confluence space name or description.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'confluence',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'OAuth access token for Confluence',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
|
||||
},
|
||||
spaceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'ID of the space to update',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'New name for the space',
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'New description for the space',
|
||||
},
|
||||
cloudId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description:
|
||||
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => '/api/tools/confluence/space',
|
||||
method: 'PUT',
|
||||
headers: (params: ConfluenceUpdateSpaceParams) => ({
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params: ConfluenceUpdateSpaceParams) => ({
|
||||
domain: params.domain,
|
||||
accessToken: params.accessToken,
|
||||
cloudId: params.cloudId,
|
||||
spaceId: params.spaceId,
|
||||
name: params.name,
|
||||
description: params.description,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
ts: new Date().toISOString(),
|
||||
spaceId: data.id ?? '',
|
||||
name: data.name ?? '',
|
||||
key: data.key ?? '',
|
||||
type: data.type ?? '',
|
||||
status: data.status ?? '',
|
||||
url: data._links?.webui ?? '',
|
||||
description: data.description ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ts: TIMESTAMP_OUTPUT,
|
||||
spaceId: { type: 'string', description: 'Updated space ID' },
|
||||
name: { type: 'string', description: 'Space name' },
|
||||
key: { type: 'string', description: 'Space key' },
|
||||
type: { type: 'string', description: 'Space type' },
|
||||
status: { type: 'string', description: 'Space status' },
|
||||
url: { type: 'string', description: 'URL to view the space' },
|
||||
description: {
|
||||
type: 'object',
|
||||
description: 'Space description',
|
||||
properties: SPACE_DESCRIPTION_OUTPUT_PROPERTIES,
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
141
apps/sim/tools/confluence/update_task.ts
Normal file
141
apps/sim/tools/confluence/update_task.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import { TIMESTAMP_OUTPUT } from '@/tools/confluence/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface ConfluenceUpdateTaskParams {
|
||||
accessToken: string
|
||||
domain: string
|
||||
taskId: string
|
||||
status: string
|
||||
cloudId?: string
|
||||
}
|
||||
|
||||
export interface ConfluenceUpdateTaskResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
ts: string
|
||||
id: string
|
||||
localId: string | null
|
||||
spaceId: string | null
|
||||
pageId: string | null
|
||||
blogPostId: string | null
|
||||
status: string
|
||||
body: string | null
|
||||
createdBy: string | null
|
||||
assignedTo: string | null
|
||||
completedBy: string | null
|
||||
createdAt: string | null
|
||||
updatedAt: string | null
|
||||
dueAt: string | null
|
||||
completedAt: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export const confluenceUpdateTaskTool: ToolConfig<
|
||||
ConfluenceUpdateTaskParams,
|
||||
ConfluenceUpdateTaskResponse
|
||||
> = {
|
||||
id: 'confluence_update_task',
|
||||
name: 'Confluence Update Task',
|
||||
description: 'Update the status of a Confluence inline task (complete or incomplete).',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'confluence',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'OAuth access token for Confluence',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Your Confluence domain (e.g., yourcompany.atlassian.net)',
|
||||
},
|
||||
taskId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the task to update',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'New status for the task (complete or incomplete)',
|
||||
},
|
||||
cloudId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description:
|
||||
'Confluence Cloud ID for the instance. If not provided, it will be fetched using the domain.',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => '/api/tools/confluence/tasks',
|
||||
method: 'POST',
|
||||
headers: (params: ConfluenceUpdateTaskParams) => ({
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params: ConfluenceUpdateTaskParams) => ({
|
||||
domain: params.domain,
|
||||
accessToken: params.accessToken,
|
||||
cloudId: params.cloudId,
|
||||
action: 'update',
|
||||
taskId: params.taskId,
|
||||
status: params.status,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const task = data.task || data
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
ts: new Date().toISOString(),
|
||||
id: task.id ?? '',
|
||||
localId: task.localId ?? null,
|
||||
spaceId: task.spaceId ?? null,
|
||||
pageId: task.pageId ?? null,
|
||||
blogPostId: task.blogPostId ?? null,
|
||||
status: task.status ?? '',
|
||||
body: task.body ?? null,
|
||||
createdBy: task.createdBy ?? null,
|
||||
assignedTo: task.assignedTo ?? null,
|
||||
completedBy: task.completedBy ?? null,
|
||||
createdAt: task.createdAt ?? null,
|
||||
updatedAt: task.updatedAt ?? null,
|
||||
dueAt: task.dueAt ?? null,
|
||||
completedAt: task.completedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ts: TIMESTAMP_OUTPUT,
|
||||
id: { type: 'string', description: 'Task ID' },
|
||||
localId: { type: 'string', description: 'Local task ID', optional: true },
|
||||
spaceId: { type: 'string', description: 'Space ID', optional: true },
|
||||
pageId: { type: 'string', description: 'Page ID', optional: true },
|
||||
blogPostId: { type: 'string', description: 'Blog post ID', optional: true },
|
||||
status: { type: 'string', description: 'Updated task status' },
|
||||
body: { type: 'string', description: 'Task body content in storage format', optional: true },
|
||||
createdBy: { type: 'string', description: 'Creator account ID', optional: true },
|
||||
assignedTo: { type: 'string', description: 'Assignee account ID', optional: true },
|
||||
completedBy: { type: 'string', description: 'Completer account ID', optional: true },
|
||||
createdAt: { type: 'string', description: 'Creation timestamp', optional: true },
|
||||
updatedAt: { type: 'string', description: 'Last update timestamp', optional: true },
|
||||
dueAt: { type: 'string', description: 'Due date', optional: true },
|
||||
completedAt: { type: 'string', description: 'Completion timestamp', optional: true },
|
||||
},
|
||||
}
|
||||
@@ -190,17 +190,25 @@ import {
|
||||
confluenceCreateCommentTool,
|
||||
confluenceCreatePagePropertyTool,
|
||||
confluenceCreatePageTool,
|
||||
confluenceCreateSpacePropertyTool,
|
||||
confluenceCreateSpaceTool,
|
||||
confluenceDeleteAttachmentTool,
|
||||
confluenceDeleteBlogPostTool,
|
||||
confluenceDeleteCommentTool,
|
||||
confluenceDeleteLabelTool,
|
||||
confluenceDeletePagePropertyTool,
|
||||
confluenceDeletePageTool,
|
||||
confluenceDeleteSpacePropertyTool,
|
||||
confluenceDeleteSpaceTool,
|
||||
confluenceGetBlogPostTool,
|
||||
confluenceGetPageAncestorsTool,
|
||||
confluenceGetPageChildrenTool,
|
||||
confluenceGetPageDescendantsTool,
|
||||
confluenceGetPagesByLabelTool,
|
||||
confluenceGetPageVersionTool,
|
||||
confluenceGetSpaceTool,
|
||||
confluenceGetTaskTool,
|
||||
confluenceGetUserTool,
|
||||
confluenceListAttachmentsTool,
|
||||
confluenceListBlogPostsInSpaceTool,
|
||||
confluenceListBlogPostsTool,
|
||||
@@ -210,11 +218,17 @@ import {
|
||||
confluenceListPagesInSpaceTool,
|
||||
confluenceListPageVersionsTool,
|
||||
confluenceListSpaceLabelsTool,
|
||||
confluenceListSpacePermissionsTool,
|
||||
confluenceListSpacePropertiesTool,
|
||||
confluenceListSpacesTool,
|
||||
confluenceListTasksTool,
|
||||
confluenceRetrieveTool,
|
||||
confluenceSearchInSpaceTool,
|
||||
confluenceSearchTool,
|
||||
confluenceUpdateBlogPostTool,
|
||||
confluenceUpdateCommentTool,
|
||||
confluenceUpdateSpaceTool,
|
||||
confluenceUpdateTaskTool,
|
||||
confluenceUpdateTool,
|
||||
confluenceUploadAttachmentTool,
|
||||
} from '@/tools/confluence'
|
||||
@@ -3032,8 +3046,22 @@ export const tools: Record<string, ToolConfig> = {
|
||||
confluence_list_space_labels: confluenceListSpaceLabelsTool,
|
||||
confluence_delete_label: confluenceDeleteLabelTool,
|
||||
confluence_delete_page_property: confluenceDeletePagePropertyTool,
|
||||
confluence_get_page_descendants: confluenceGetPageDescendantsTool,
|
||||
confluence_get_space: confluenceGetSpaceTool,
|
||||
confluence_create_space: confluenceCreateSpaceTool,
|
||||
confluence_update_space: confluenceUpdateSpaceTool,
|
||||
confluence_delete_space: confluenceDeleteSpaceTool,
|
||||
confluence_get_user: confluenceGetUserTool,
|
||||
confluence_list_spaces: confluenceListSpacesTool,
|
||||
confluence_update_blogpost: confluenceUpdateBlogPostTool,
|
||||
confluence_delete_blogpost: confluenceDeleteBlogPostTool,
|
||||
confluence_list_tasks: confluenceListTasksTool,
|
||||
confluence_get_task: confluenceGetTaskTool,
|
||||
confluence_update_task: confluenceUpdateTaskTool,
|
||||
confluence_list_space_permissions: confluenceListSpacePermissionsTool,
|
||||
confluence_list_space_properties: confluenceListSpacePropertiesTool,
|
||||
confluence_create_space_property: confluenceCreateSpacePropertyTool,
|
||||
confluence_delete_space_property: confluenceDeleteSpacePropertyTool,
|
||||
cursor_list_agents: cursorListAgentsTool,
|
||||
cursor_list_agents_v2: cursorListAgentsV2Tool,
|
||||
cursor_get_agent: cursorGetAgentTool,
|
||||
|
||||
16
bun.lock
16
bun.lock
@@ -13,7 +13,7 @@
|
||||
"glob": "13.0.0",
|
||||
"husky": "9.1.7",
|
||||
"lint-staged": "16.0.0",
|
||||
"turbo": "2.8.10",
|
||||
"turbo": "2.8.11",
|
||||
},
|
||||
},
|
||||
"apps/docs": {
|
||||
@@ -3437,19 +3437,19 @@
|
||||
|
||||
"tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="],
|
||||
|
||||
"turbo": ["turbo@2.8.10", "", { "optionalDependencies": { "turbo-darwin-64": "2.8.10", "turbo-darwin-arm64": "2.8.10", "turbo-linux-64": "2.8.10", "turbo-linux-arm64": "2.8.10", "turbo-windows-64": "2.8.10", "turbo-windows-arm64": "2.8.10" }, "bin": { "turbo": "bin/turbo" } }, "sha512-OxbzDES66+x7nnKGg2MwBA1ypVsZoDTLHpeaP4giyiHSixbsiTaMyeJqbEyvBdp5Cm28fc+8GG6RdQtic0ijwQ=="],
|
||||
"turbo": ["turbo@2.8.11", "", { "optionalDependencies": { "turbo-darwin-64": "2.8.11", "turbo-darwin-arm64": "2.8.11", "turbo-linux-64": "2.8.11", "turbo-linux-arm64": "2.8.11", "turbo-windows-64": "2.8.11", "turbo-windows-arm64": "2.8.11" }, "bin": { "turbo": "bin/turbo" } }, "sha512-H+rwSHHPLoyPOSoHdmI1zY0zy0GGj1Dmr7SeJW+nZiWLz2nex8EJ+fkdVabxXFMNEux+aywI4Sae8EqhmnOv4A=="],
|
||||
|
||||
"turbo-darwin-64": ["turbo-darwin-64@2.8.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-A03fXh+B7S8mL3PbdhTd+0UsaGrhfyPkODvzBDpKRY7bbeac4MDFpJ7I+Slf2oSkCEeSvHKR7Z4U71uKRUfX7g=="],
|
||||
"turbo-darwin-64": ["turbo-darwin-64@2.8.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-XKaCWaz4OCt77oYYvGCIRpvYD4c/aNaKjRkUpv+e8rN3RZb+5Xsyew4yRO+gaHdMIUhQznXNXfHlhs+/p7lIhA=="],
|
||||
|
||||
"turbo-darwin-arm64": ["turbo-darwin-arm64@2.8.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-sidzowgWL3s5xCHLeqwC9M3s9M0i16W1nuQF3Mc7fPHpZ+YPohvcbVFBB2uoRRHYZg6yBnwD4gyUHKTeXfwtXA=="],
|
||||
"turbo-darwin-arm64": ["turbo-darwin-arm64@2.8.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VvynLHGUNvQ9k7GZjRPSsRcK4VkioTfFb7O7liAk4nHKjEcMdls7GqxzjVWgJiKz3hWmQGaP9hRa9UUnhVWCxA=="],
|
||||
|
||||
"turbo-linux-64": ["turbo-linux-64@2.8.10", "", { "os": "linux", "cpu": "x64" }, "sha512-YK9vcpL3TVtqonB021XwgaQhY9hJJbKKUhLv16osxV0HkcQASQWUqR56yMge7puh6nxU67rQlTq1b7ksR1T3KA=="],
|
||||
"turbo-linux-64": ["turbo-linux-64@2.8.11", "", { "os": "linux", "cpu": "x64" }, "sha512-cbSn37dcm+EmkQ7DD0euy7xV7o2el4GAOr1XujvkAyKjjNvQ+6QIUeDgQcwAx3D17zPpDvfDMJY2dLQadWnkmQ=="],
|
||||
|
||||
"turbo-linux-arm64": ["turbo-linux-arm64@2.8.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-3+j2tL0sG95iBJTm+6J8/45JsETQABPqtFyYjVjBbi6eVGdtNTiBmHNKrbvXRlQ3ZbUG75bKLaSSDHSEEN+btQ=="],
|
||||
"turbo-linux-arm64": ["turbo-linux-arm64@2.8.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-+trymp2s2aBrhS04l6qFxcExzZ8ffndevuUB9c5RCeqsVpZeiWuGQlWNm5XjOmzoMayxRARZ5ma7yiWbGMiLqQ=="],
|
||||
|
||||
"turbo-windows-64": ["turbo-windows-64@2.8.10", "", { "os": "win32", "cpu": "x64" }, "sha512-hdeF5qmVY/NFgiucf8FW0CWJWtyT2QPm5mIsX0W1DXAVzqKVXGq+Zf+dg4EUngAFKjDzoBeN6ec2Fhajwfztkw=="],
|
||||
"turbo-windows-64": ["turbo-windows-64@2.8.11", "", { "os": "win32", "cpu": "x64" }, "sha512-3kJjFSM4yw1n9Uzmi+XkAUgCae19l/bH6RJ442xo7mnZm0tpOjo33F+FYHoSVpIWVMd0HG0LDccyafPSdylQbA=="],
|
||||
|
||||
"turbo-windows-arm64": ["turbo-windows-arm64@2.8.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-QGdr/Q8LWmj+ITMkSvfiz2glf0d7JG0oXVzGL3jxkGqiBI1zXFj20oqVY0qWi+112LO9SVrYdpHS0E/oGFrMbQ=="],
|
||||
"turbo-windows-arm64": ["turbo-windows-arm64@2.8.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-JOM4uF2vuLsJUvibdR6X9QqdZr6BhC6Nhlrw4LKFPsXZZI/9HHLoqAiYRpE4MuzIwldCH/jVySnWXrI1SKto0g=="],
|
||||
|
||||
"tweetnacl": ["tweetnacl@0.14.5", "", {}, "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="],
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"glob": "13.0.0",
|
||||
"husky": "9.1.7",
|
||||
"lint-staged": "16.0.0",
|
||||
"turbo": "2.8.10"
|
||||
"turbo": "2.8.11"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx,json,css,scss}": [
|
||||
|
||||
@@ -86,6 +86,8 @@ export const auditMock = {
|
||||
WORKFLOW_DEPLOYED: 'workflow.deployed',
|
||||
WORKFLOW_UNDEPLOYED: 'workflow.undeployed',
|
||||
WORKFLOW_DUPLICATED: 'workflow.duplicated',
|
||||
WORKFLOW_LOCKED: 'workflow.locked',
|
||||
WORKFLOW_UNLOCKED: 'workflow.unlocked',
|
||||
WORKFLOW_DEPLOYMENT_ACTIVATED: 'workflow.deployment_activated',
|
||||
WORKFLOW_DEPLOYMENT_REVERTED: 'workflow.deployment_reverted',
|
||||
WORKFLOW_VARIABLES_UPDATED: 'workflow.variables_updated',
|
||||
|
||||
Reference in New Issue
Block a user