12 tools for the new Confluence toolkit. | Name | Description | |----------------------------------|------------------------------------------------------------------------------------| | Confluence.CreatePage | Create a new page at the root of the given space. | | Confluence.UpdatePageContent | Update a page's content. | | Confluence.RenamePage | Rename a page by changing its title. | | Confluence.GetPage | Retrieve a SINGLE page's content by its ID or title. | | Confluence.GetPagesById | Get the content of MULTIPLE pages by their ID in a single efficient request. | | Confluence.ListPages | Get the content of multiple pages by their ID. | | Confluence.ListAttachments | List attachments in a workspace. | | Confluence.GetAttachmentsForPage | Get attachments for a page by its ID or title. | | Confluence.SearchContent | Search for content in Confluence. | | Confluence.GetSpace | Get the details of a space by its ID or key. | | Confluence.ListSpaces | List all spaces sorted by name in ascending order. | | Confluence.GetSpaceHierarchy | Retrieve the full hierarchical structure of a Confluence space as a tree structure.| ### Confluence Clients Confluence has deprecated most of their V1 endpoints, so most of the tools use V2. However, we still need a V1 client to support search. The V1 search API has not been deprecated yet, because there is no V2 equivalent. But we need to be aware in the future for when this deprecation happens. ### Future work * Content of pages are returned in the Confluence `storage` format. This is the format that Confluence uses to store pages internally. We should understand the storage format more deeply, and write utility function to transform this format into plain text. * Better protections against extremely large pages. I've tested up to 6,000 word pages. * Tools for blog posts * Tool for getting the children of a page. (`get_space_hierarchy` will suffice for now) * Allow for numerical titles
53 lines
2.4 KiB
Python
53 lines
2.4 KiB
Python
from typing import Annotated
|
|
|
|
from arcade.sdk import ToolContext, tool
|
|
from arcade.sdk.auth import Atlassian
|
|
|
|
from arcade_confluence.client import ConfluenceClientV1
|
|
|
|
|
|
@tool(
|
|
requires_auth=Atlassian(
|
|
scopes=["search:confluence"],
|
|
)
|
|
)
|
|
async def search_content(
|
|
context: ToolContext,
|
|
must_contain_all: Annotated[
|
|
list[str] | None,
|
|
"Words/phrases that content MUST contain (AND logic). Each item can be:\n"
|
|
"- Single word: 'banana' - content must contain this word\n"
|
|
"- Multi-word phrase: 'How to' - content must contain all these words (in any order)\n"
|
|
"- All items in this list must be present for content to match\n"
|
|
"- Example: ['banana', 'apple'] finds content containing BOTH 'banana' AND 'apple'",
|
|
] = None,
|
|
can_contain_any: Annotated[
|
|
list[str] | None,
|
|
"Words/phrases where content can contain ANY of these (OR logic). Each item can be:\n"
|
|
"- Single word: 'project' - content containing this word will match\n"
|
|
"- Multi-word phrase: 'pen & paper' - content containing all these words will match\n"
|
|
"- Content matching ANY item in this list will be included\n"
|
|
"- Example: ['project', 'documentation'] finds content with 'project' OR 'documentation'",
|
|
] = None,
|
|
enable_fuzzy: Annotated[
|
|
bool,
|
|
"Enable fuzzy matching to find similar terms (e.g. 'roam' will find 'foam'). "
|
|
"Defaults to True",
|
|
] = True,
|
|
limit: Annotated[int, "Maximum number of results to return (1-100). Defaults to 25"] = 25,
|
|
) -> Annotated[dict, "Search results containing content items matching the criteria"]:
|
|
"""Search for content in Confluence.
|
|
|
|
The search is performed across all content in the authenticated user's Confluence workspace.
|
|
All search terms in Confluence are case insensitive.
|
|
|
|
You can use the parameters in different ways:
|
|
- must_contain_all: For AND logic - content must contain ALL of these
|
|
- can_contain_any: For OR logic - content can contain ANY of these
|
|
- Combine them: must_contain_all=['banana'] AND can_contain_any=['database', 'guide']
|
|
"""
|
|
client = ConfluenceClientV1(context.get_auth_token_or_empty())
|
|
cql = client.construct_cql(must_contain_all, can_contain_any, enable_fuzzy)
|
|
response = await client.get("search", params={"cql": cql, "limit": max(1, min(limit, 100))})
|
|
|
|
return client.transform_search_content_response(response)
|