Bladeren bron

add yuqye(https://www.yuque.com)tools (#8960)

Co-authored-by: 佐井 <chengwu.lcw@alibaba-inc.com>
Oliver Lee 6 maanden geleden
bovenliggende
commit
424a7da470
21 gewijzigde bestanden met toevoegingen van 939 en 0 verwijderingen
  1. 1 0
      api/core/tools/provider/_position.yaml
  2. 12 0
      api/core/tools/provider/builtin/aliyuque/_assets/icon.svg
  3. 19 0
      api/core/tools/provider/builtin/aliyuque/aliyuque.py
  4. 29 0
      api/core/tools/provider/builtin/aliyuque/aliyuque.yaml
  5. 50 0
      api/core/tools/provider/builtin/aliyuque/tools/base.py
  6. 22 0
      api/core/tools/provider/builtin/aliyuque/tools/create_document.py
  7. 99 0
      api/core/tools/provider/builtin/aliyuque/tools/create_document.yaml
  8. 25 0
      api/core/tools/provider/builtin/aliyuque/tools/delete_document.py
  9. 37 0
      api/core/tools/provider/builtin/aliyuque/tools/delete_document.yaml
  10. 24 0
      api/core/tools/provider/builtin/aliyuque/tools/describe_book_index_page.py
  11. 38 0
      api/core/tools/provider/builtin/aliyuque/tools/describe_book_index_page.yaml
  12. 23 0
      api/core/tools/provider/builtin/aliyuque/tools/describe_book_table_of_contents.py
  13. 25 0
      api/core/tools/provider/builtin/aliyuque/tools/describe_book_table_of_contents.yaml
  14. 61 0
      api/core/tools/provider/builtin/aliyuque/tools/describe_document_content.py
  15. 50 0
      api/core/tools/provider/builtin/aliyuque/tools/describe_document_content.yaml
  16. 24 0
      api/core/tools/provider/builtin/aliyuque/tools/describe_documents.py
  17. 38 0
      api/core/tools/provider/builtin/aliyuque/tools/describe_documents.yaml
  18. 29 0
      api/core/tools/provider/builtin/aliyuque/tools/update_book_table_of_contents.py
  19. 222 0
      api/core/tools/provider/builtin/aliyuque/tools/update_book_table_of_contents.yaml
  20. 24 0
      api/core/tools/provider/builtin/aliyuque/tools/update_document.py
  21. 87 0
      api/core/tools/provider/builtin/aliyuque/tools/update_document.yaml

+ 1 - 0
api/core/tools/provider/_position.yaml

@@ -61,6 +61,7 @@
 - vectorizer
 - qrcode
 - tianditu
+- aliyuque
 - google_translate
 - hap
 - json_process

File diff suppressed because it is too large
+ 12 - 0
api/core/tools/provider/builtin/aliyuque/_assets/icon.svg


+ 19 - 0
api/core/tools/provider/builtin/aliyuque/aliyuque.py

@@ -0,0 +1,19 @@
+from core.tools.errors import ToolProviderCredentialValidationError
+from core.tools.provider.builtin.aliyuque.tools.base import AliYuqueTool
+from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
+
+
+class AliYuqueProvider(BuiltinToolProviderController):
+    def _validate_credentials(self, credentials: dict) -> None:
+        token = credentials.get("token")
+        if not token:
+            raise ToolProviderCredentialValidationError("token is required")
+
+        try:
+            resp = AliYuqueTool.auth(token)
+            if resp and resp.get("data", {}).get("id"):
+                return
+
+            raise ToolProviderCredentialValidationError(resp)
+        except Exception as e:
+            raise ToolProviderCredentialValidationError(str(e))

+ 29 - 0
api/core/tools/provider/builtin/aliyuque/aliyuque.yaml

@@ -0,0 +1,29 @@
+identity:
+  author: 佐井
+  name: aliyuque
+  label:
+    en_US: yuque
+    zh_Hans: 语雀
+    pt_BR: yuque
+  description:
+    en_US: Yuque, https://www.yuque.com.
+    zh_Hans: 语雀,https://www.yuque.com。
+    pt_BR: Yuque, https://www.yuque.com.
+  icon: icon.svg
+  tags:
+    - productivity
+    - search
+credentials_for_provider:
+  token:
+    type: secret-input
+    required: true
+    label:
+      en_US: Yuque Team Token
+      zh_Hans: 语雀团队Token
+    placeholder:
+      en_US: Please input your Yuque team token
+      zh_Hans: 请输入你的语雀团队Token
+    help:
+      en_US: Get Alibaba Yuque team token
+      zh_Hans: 先获取语雀团队Token
+    url: https://www.yuque.com/settings/tokens

+ 50 - 0
api/core/tools/provider/builtin/aliyuque/tools/base.py

@@ -0,0 +1,50 @@
+"""
+语雀客户端
+"""
+
+__author__ = "佐井"
+__created__ = "2024-06-01 09:45:20"
+
+from typing import Any
+
+import requests
+
+
+class AliYuqueTool:
+    # yuque service url
+    server_url = "https://www.yuque.com"
+
+    @staticmethod
+    def auth(token):
+        session = requests.Session()
+        session.headers.update({"Accept": "application/json", "X-Auth-Token": token})
+        login = session.request("GET", AliYuqueTool.server_url + "/api/v2/user")
+        login.raise_for_status()
+        resp = login.json()
+        return resp
+
+    def request(self, method: str, token, tool_parameters: dict[str, Any], path: str) -> str:
+        if not token:
+            raise Exception("token is required")
+        session = requests.Session()
+        session.headers.update({"accept": "application/json", "X-Auth-Token": token})
+        new_params = {**tool_parameters}
+        # 找出需要替换的变量
+        replacements = {k: v for k, v in new_params.items() if f"{{{k}}}" in path}
+
+        # 替换 path 中的变量
+        for key, value in replacements.items():
+            path = path.replace(f"{{{key}}}", str(value))
+            del new_params[key]  # 从 kwargs 中删除已经替换的变量
+        # 请求接口
+        if method.upper() in {"POST", "PUT"}:
+            session.headers.update(
+                {
+                    "Content-Type": "application/json",
+                }
+            )
+            response = session.request(method.upper(), self.server_url + path, json=new_params)
+        else:
+            response = session.request(method, self.server_url + path, params=new_params)
+        response.raise_for_status()
+        return response.text

+ 22 - 0
api/core/tools/provider/builtin/aliyuque/tools/create_document.py

@@ -0,0 +1,22 @@
+"""
+创建文档
+"""
+
+__author__ = "佐井"
+__created__ = "2024-06-01 10:45:20"
+
+from typing import Any, Union
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.provider.builtin.aliyuque.tools.base import AliYuqueTool
+from core.tools.tool.builtin_tool import BuiltinTool
+
+
+class AliYuqueCreateDocumentTool(AliYuqueTool, BuiltinTool):
+    def _invoke(
+        self, user_id: str, tool_parameters: dict[str, Any]
+    ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
+        token = self.runtime.credentials.get("token", None)
+        if not token:
+            raise Exception("token is required")
+        return self.create_text_message(self.request("POST", token, tool_parameters, "/api/v2/repos/{book_id}/docs"))

+ 99 - 0
api/core/tools/provider/builtin/aliyuque/tools/create_document.yaml

@@ -0,0 +1,99 @@
+identity:
+  name: aliyuque_create_document
+  author: 佐井
+  label:
+    en_US: Create Document
+    zh_Hans: 创建文档
+  icon: icon.svg
+description:
+  human:
+    en_US: Creates a new document within a knowledge base without automatic addition to the table of contents. Requires a subsequent call to the "knowledge base directory update API". Supports setting visibility, format, and content. # 接口英文描述
+    zh_Hans: 在知识库中创建新文档,但不会自动加入目录,需额外调用“知识库目录更新接口”。允许设置公开性、格式及正文内容。
+  llm: Creates docs in a KB.
+
+parameters:
+  - name: book_id
+    type: number
+    required: true
+    form: llm
+    label:
+      en_US: Knowledge Base ID
+      zh_Hans: 知识库ID
+    human_description:
+      en_US: The unique identifier of the knowledge base where the document will be created.
+      zh_Hans: 文档将被创建的知识库的唯一标识。
+    llm_description: ID of the target knowledge base.
+
+  - name: title
+    type: string
+    required: false
+    form: llm
+    label:
+      en_US: Title
+      zh_Hans: 标题
+    human_description:
+      en_US: The title of the document, defaults to 'Untitled' if not provided.
+      zh_Hans: 文档标题,默认为'无标题'如未提供。
+    llm_description: Title of the document, defaults to 'Untitled'.
+
+  - name: public
+    type: select
+    required: false
+    form: llm
+    options:
+      - value: 0
+        label:
+          en_US: Private
+          zh_Hans: 私密
+      - value: 1
+        label:
+          en_US: Public
+          zh_Hans: 公开
+      - value: 2
+        label:
+          en_US: Enterprise-only
+          zh_Hans: 企业内公开
+    label:
+      en_US: Visibility
+      zh_Hans: 公开性
+    human_description:
+      en_US: Document visibility (0 Private, 1 Public, 2 Enterprise-only).
+      zh_Hans: 文档可见性(0 私密, 1 公开, 2 企业内公开)。
+    llm_description: Doc visibility options, 0-private, 1-public, 2-enterprise.
+
+  - name: format
+    type: select
+    required: false
+    form: llm
+    options:
+      - value: markdown
+        label:
+          en_US: markdown
+          zh_Hans: markdown
+      - value: html
+        label:
+          en_US: html
+          zh_Hans: html
+      - value: lake
+        label:
+          en_US: lake
+          zh_Hans: lake
+    label:
+      en_US: Content Format
+      zh_Hans: 内容格式
+    human_description:
+      en_US: Format of the document content (markdown, HTML, Lake).
+      zh_Hans: 文档内容格式(markdown, HTML, Lake)。
+    llm_description: Content format choices, markdown, HTML, Lake.
+
+  - name: body
+    type: string
+    required: true
+    form: llm
+    label:
+      en_US: Body Content
+      zh_Hans: 正文内容
+    human_description:
+      en_US: The actual content of the document.
+      zh_Hans: 文档的实际内容。
+    llm_description: Content of the document.

+ 25 - 0
api/core/tools/provider/builtin/aliyuque/tools/delete_document.py

@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+"""
+删除文档
+"""
+
+__author__ = "佐井"
+__created__ = "2024-09-17 22:04"
+
+from typing import Any, Union
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.provider.builtin.aliyuque.tools.base import AliYuqueTool
+from core.tools.tool.builtin_tool import BuiltinTool
+
+
+class AliYuqueDeleteDocumentTool(AliYuqueTool, BuiltinTool):
+    def _invoke(
+        self, user_id: str, tool_parameters: dict[str, Any]
+    ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
+        token = self.runtime.credentials.get("token", None)
+        if not token:
+            raise Exception("token is required")
+        return self.create_text_message(
+            self.request("DELETE", token, tool_parameters, "/api/v2/repos/{book_id}/docs/{id}")
+        )

+ 37 - 0
api/core/tools/provider/builtin/aliyuque/tools/delete_document.yaml

@@ -0,0 +1,37 @@
+identity:
+  name: aliyuque_delete_document
+  author: 佐井
+  label:
+    en_US: Delete Document
+    zh_Hans: 删除文档
+  icon: icon.svg
+description:
+  human:
+    en_US: Delete Document
+    zh_Hans: 根据id删除文档
+  llm: Delete document.
+
+parameters:
+  - name: book_id
+    type: number
+    required: true
+    form: llm
+    label:
+      en_US: Knowledge Base ID
+      zh_Hans: 知识库ID
+    human_description:
+      en_US: The unique identifier of the knowledge base where the document will be created.
+      zh_Hans: 文档将被创建的知识库的唯一标识。
+    llm_description: ID of the target knowledge base.
+
+  - name: id
+    type: string
+    required: true
+    form: llm
+    label:
+      en_US: Document ID or Path
+      zh_Hans: 文档 ID or 路径
+    human_description:
+      en_US: Document ID or path.
+      zh_Hans: 文档 ID or 路径。
+    llm_description: Document ID or path.

+ 24 - 0
api/core/tools/provider/builtin/aliyuque/tools/describe_book_index_page.py

@@ -0,0 +1,24 @@
+"""
+获取知识库首页
+"""
+
+__author__ = "佐井"
+__created__ = "2024-06-01 22:57:14"
+
+from typing import Any, Union
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.provider.builtin.aliyuque.tools.base import AliYuqueTool
+from core.tools.tool.builtin_tool import BuiltinTool
+
+
+class AliYuqueDescribeBookIndexPageTool(AliYuqueTool, BuiltinTool):
+    def _invoke(
+        self, user_id: str, tool_parameters: dict[str, Any]
+    ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
+        token = self.runtime.credentials.get("token", None)
+        if not token:
+            raise Exception("token is required")
+        return self.create_text_message(
+            self.request("GET", token, tool_parameters, "/api/v2/repos/{group_login}/{book_slug}/index_page")
+        )

+ 38 - 0
api/core/tools/provider/builtin/aliyuque/tools/describe_book_index_page.yaml

@@ -0,0 +1,38 @@
+identity:
+  name: aliyuque_describe_book_index_page
+  author: 佐井
+  label:
+    en_US: Get Repo Index Page
+    zh_Hans: 获取知识库首页
+  icon: icon.svg
+
+description:
+  human:
+    en_US: Retrieves the homepage of a knowledge base within a group, supporting both book ID and group login with book slug access.
+    zh_Hans: 获取团队中知识库的首页信息,可通过书籍ID或团队登录名与书籍路径访问。
+  llm: Fetches the knowledge base homepage using group and book identifiers with support for alternate access paths.
+
+parameters:
+  - name: group_login
+    type: string
+    required: true
+    form: llm
+    label:
+      en_US: Group Login
+      zh_Hans: 团队登录名
+    human_description:
+      en_US: The login name of the group that owns the knowledge base.
+      zh_Hans: 拥有该知识库的团队登录名。
+    llm_description: Team login identifier for the knowledge base owner.
+
+  - name: book_slug
+    type: string
+    required: true
+    form: llm
+    label:
+      en_US: Book Slug
+      zh_Hans: 知识库路径
+    human_description:
+      en_US: The unique slug representing the path of the knowledge base.
+      zh_Hans: 知识库的唯一路径标识。
+    llm_description: Unique path identifier for the knowledge base.

+ 23 - 0
api/core/tools/provider/builtin/aliyuque/tools/describe_book_table_of_contents.py

@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+"""
+获取知识库目录
+"""
+
+__author__ = "佐井"
+__created__ = "2024-09-17 15:17:11"
+
+from typing import Any, Union
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.provider.builtin.aliyuque.tools.base import AliYuqueTool
+from core.tools.tool.builtin_tool import BuiltinTool
+
+
+class YuqueDescribeBookTableOfContentsTool(AliYuqueTool, BuiltinTool):
+    def _invoke(
+        self, user_id: str, tool_parameters: dict[str, Any]
+    ) -> (Union)[ToolInvokeMessage, list[ToolInvokeMessage]]:
+        token = self.runtime.credentials.get("token", None)
+        if not token:
+            raise Exception("token is required")
+        return self.create_text_message(self.request("GET", token, tool_parameters, "/api/v2/repos/{book_id}/toc"))

+ 25 - 0
api/core/tools/provider/builtin/aliyuque/tools/describe_book_table_of_contents.yaml

@@ -0,0 +1,25 @@
+identity:
+  name: aliyuque_describe_book_table_of_contents
+  author: 佐井
+  label:
+    en_US: Get Book's Table of Contents
+    zh_Hans: 获取知识库的目录
+  icon: icon.svg
+description:
+  human:
+    en_US: Get Book's Table of Contents.
+    zh_Hans: 获取知识库的目录。
+  llm: Get Book's Table of Contents.
+
+parameters:
+  - name: book_id
+    type: number
+    required: true
+    form: llm
+    label:
+      en_US: Book ID
+      zh_Hans: 知识库 ID
+    human_description:
+      en_US: Book ID.
+      zh_Hans: 知识库 ID。
+    llm_description: Book ID.

+ 61 - 0
api/core/tools/provider/builtin/aliyuque/tools/describe_document_content.py

@@ -0,0 +1,61 @@
+"""
+获取文档
+"""
+
+__author__ = "佐井"
+__created__ = "2024-06-02 07:11:45"
+
+import json
+from typing import Any, Union
+from urllib.parse import urlparse
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.provider.builtin.aliyuque.tools.base import AliYuqueTool
+from core.tools.tool.builtin_tool import BuiltinTool
+
+
+class AliYuqueDescribeDocumentContentTool(AliYuqueTool, BuiltinTool):
+    def _invoke(
+        self, user_id: str, tool_parameters: dict[str, Any]
+    ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
+        new_params = {**tool_parameters}
+        token = new_params.pop("token")
+        if not token or token.lower() == "none":
+            token = self.runtime.credentials.get("token", None)
+        if not token:
+            raise Exception("token is required")
+        new_params = {**tool_parameters}
+        url = new_params.pop("url")
+        if not url or not url.startswith("http"):
+            raise Exception("url is not valid")
+
+        parsed_url = urlparse(url)
+        path_parts = parsed_url.path.strip("/").split("/")
+        if len(path_parts) < 3:
+            raise Exception("url is not correct")
+        doc_id = path_parts[-1]
+        book_slug = path_parts[-2]
+        group_id = path_parts[-3]
+
+        # 1. 请求首页信息,获取book_id
+        new_params["group_login"] = group_id
+        new_params["book_slug"] = book_slug
+        index_page = json.loads(
+            self.request("GET", token, new_params, "/api/v2/repos/{group_login}/{book_slug}/index_page")
+        )
+        book_id = index_page.get("data", {}).get("book", {}).get("id")
+        if not book_id:
+            raise Exception(f"can not parse book_id from {index_page}")
+        # 2. 获取文档内容
+        new_params["book_id"] = book_id
+        new_params["id"] = doc_id
+        data = self.request("GET", token, new_params, "/api/v2/repos/{book_id}/docs/{id}")
+        data = json.loads(data)
+        body_only = tool_parameters.get("body_only") or ""
+        if body_only.lower() == "true":
+            return self.create_text_message(data.get("data").get("body"))
+        else:
+            raw = data.get("data")
+            del raw["body_lake"]
+            del raw["body_html"]
+            return self.create_text_message(json.dumps(data))

+ 50 - 0
api/core/tools/provider/builtin/aliyuque/tools/describe_document_content.yaml

@@ -0,0 +1,50 @@
+identity:
+  name: aliyuque_describe_document_content
+  author: 佐井
+  label:
+    en_US: Fetch Document Content
+    zh_Hans: 获取文档内容
+  icon: icon.svg
+
+description:
+  human:
+    en_US: Retrieves document content from Yuque based on the provided document URL, which can be a normal or shared link.
+    zh_Hans: 根据提供的语雀文档地址(支持正常链接或分享链接)获取文档内容。
+  llm: Fetches Yuque document content given a URL.
+
+parameters:
+  - name: url
+    type: string
+    required: true
+    form: llm
+    label:
+      en_US: Document URL
+      zh_Hans: 文档地址
+    human_description:
+      en_US: The URL of the document to retrieve content from, can be normal or shared.
+      zh_Hans: 需要获取内容的文档地址,可以是正常链接或分享链接。
+    llm_description: URL of the Yuque document to fetch content.
+
+  - name: body_only
+    type: string
+    required: false
+    form: llm
+    label:
+      en_US: return body content only
+      zh_Hans: 仅返回body内容
+    human_description:
+      en_US: true:Body content only, false:Full response with metadata.
+      zh_Hans: true:仅返回body内容,不返回其他元数据,false:返回所有元数据。
+    llm_description: true:Body content only, false:Full response with metadata.
+
+  - name: token
+    type: secret-input
+    required: false
+    form: llm
+    label:
+      en_US: Yuque API Token
+      zh_Hans: 语雀接口Token
+    human_description:
+      en_US: The token for calling the Yuque API defaults to the Yuque token bound to the current tool if not provided.
+      zh_Hans: 调用语雀接口的token,如果不传则默认为当前工具绑定的语雀Token。
+    llm_description: If the token for calling the Yuque API is not provided, it will default to the Yuque token bound to the current tool.

+ 24 - 0
api/core/tools/provider/builtin/aliyuque/tools/describe_documents.py

@@ -0,0 +1,24 @@
+"""
+获取文档
+"""
+
+__author__ = "佐井"
+__created__ = "2024-06-01 10:45:20"
+
+from typing import Any, Union
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.provider.builtin.aliyuque.tools.base import AliYuqueTool
+from core.tools.tool.builtin_tool import BuiltinTool
+
+
+class AliYuqueDescribeDocumentsTool(AliYuqueTool, BuiltinTool):
+    def _invoke(
+        self, user_id: str, tool_parameters: dict[str, Any]
+    ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
+        token = self.runtime.credentials.get("token", None)
+        if not token:
+            raise Exception("token is required")
+        return self.create_text_message(
+            self.request("GET", token, tool_parameters, "/api/v2/repos/{book_id}/docs/{id}")
+        )

+ 38 - 0
api/core/tools/provider/builtin/aliyuque/tools/describe_documents.yaml

@@ -0,0 +1,38 @@
+identity:
+  name: aliyuque_describe_documents
+  author: 佐井
+  label:
+    en_US: Get Doc Detail
+    zh_Hans: 获取文档详情
+  icon: icon.svg
+
+description:
+  human:
+    en_US: Retrieves detailed information of a specific document identified by its ID or path within a knowledge base.
+    zh_Hans: 根据知识库ID和文档ID或路径获取文档详细信息。
+  llm: Fetches detailed doc info using ID/path from a knowledge base; supports doc lookup in Yuque.
+
+parameters:
+  - name: book_id
+    type: number
+    required: true
+    form: llm
+    label:
+      en_US: Knowledge Base ID
+      zh_Hans: 知识库 ID
+    human_description:
+      en_US: Identifier for the knowledge base where the document resides.
+      zh_Hans: 文档所属知识库的唯一标识。
+    llm_description: ID of the knowledge base holding the document.
+
+  - name: id
+    type: string
+    required: true
+    form: llm
+    label:
+      en_US: Document ID or Path
+      zh_Hans: 文档 ID 或路径
+    human_description:
+      en_US: The unique identifier or path of the document to retrieve.
+      zh_Hans: 需要获取的文档的ID或其在知识库中的路径。
+    llm_description: Unique doc ID or its path for retrieval.

+ 29 - 0
api/core/tools/provider/builtin/aliyuque/tools/update_book_table_of_contents.py

@@ -0,0 +1,29 @@
+#!/usr/bin/env python3
+"""
+获取知识库目录
+"""
+
+__author__ = "佐井"
+__created__ = "2024-09-17 15:17:11"
+
+from typing import Any, Union
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.provider.builtin.aliyuque.tools.base import AliYuqueTool
+from core.tools.tool.builtin_tool import BuiltinTool
+
+
+class YuqueDescribeBookTableOfContentsTool(AliYuqueTool, BuiltinTool):
+    def _invoke(
+        self, user_id: str, tool_parameters: dict[str, Any]
+    ) -> (Union)[ToolInvokeMessage, list[ToolInvokeMessage]]:
+        token = self.runtime.credentials.get("token", None)
+        if not token:
+            raise Exception("token is required")
+
+        doc_ids = tool_parameters.get("doc_ids")
+        if doc_ids:
+            doc_ids = [int(doc_id.strip()) for doc_id in doc_ids.split(",")]
+            tool_parameters["doc_ids"] = doc_ids
+
+        return self.create_text_message(self.request("PUT", token, tool_parameters, "/api/v2/repos/{book_id}/toc"))

+ 222 - 0
api/core/tools/provider/builtin/aliyuque/tools/update_book_table_of_contents.yaml

@@ -0,0 +1,222 @@
+identity:
+  name: aliyuque_update_book_table_of_contents
+  author: 佐井
+  label:
+    en_US: Update Book's Table of Contents
+    zh_Hans: 更新知识库目录
+  icon: icon.svg
+description:
+  human:
+    en_US: Update Book's Table of Contents.
+    zh_Hans: 更新知识库目录。
+  llm: Update Book's Table of Contents.
+
+parameters:
+  - name: book_id
+    type: number
+    required: true
+    form: llm
+    label:
+      en_US: Book ID
+      zh_Hans: 知识库 ID
+    human_description:
+      en_US: Book ID.
+      zh_Hans: 知识库 ID。
+    llm_description: Book ID.
+
+  - name: action
+    type: select
+    required: true
+    form: llm
+    options:
+      - value: appendNode
+        label:
+          en_US: appendNode
+          zh_Hans: appendNode
+          pt_BR: appendNode
+      - value: prependNode
+        label:
+          en_US: prependNode
+          zh_Hans: prependNode
+          pt_BR: prependNode
+      - value: editNode
+        label:
+          en_US: editNode
+          zh_Hans: editNode
+          pt_BR: editNode
+      - value: editNode
+        label:
+          en_US: removeNode
+          zh_Hans: removeNode
+          pt_BR: removeNode
+    label:
+      en_US: Action Type
+      zh_Hans: 操作
+    human_description:
+      en_US: In the operation scenario, sibling node prepending is not supported, deleting a node doesn't remove associated documents, and node deletion has two modes, 'sibling' (delete current node) and 'child' (delete current node and its children).
+      zh_Hans: 操作,创建场景下不支持同级头插 prependNode,删除节点不会删除关联文档,删除节点时action_mode=sibling (删除当前节点), action_mode=child (删除当前节点及子节点)
+    llm_description: In the operation scenario, sibling node prepending is not supported, deleting a node doesn't remove associated documents, and node deletion has two modes, 'sibling' (delete current node) and 'child' (delete current node and its children).
+
+
+  - name: action_mode
+    type: select
+    required: false
+    form: llm
+    options:
+      - value: sibling
+        label:
+          en_US: sibling
+          zh_Hans: 同级
+          pt_BR: sibling
+      - value: child
+        label:
+          en_US: child
+          zh_Hans: 子集
+          pt_BR: child
+    label:
+      en_US: Action Type
+      zh_Hans: 操作
+    human_description:
+      en_US: Operation mode (sibling:same level, child:child level).
+      zh_Hans: 操作模式 (sibling:同级, child:子级)。
+    llm_description: Operation mode (sibling:same level, child:child level).
+
+  - name: target_uuid
+    type: string
+    required: false
+    form: llm
+    label:
+      en_US: Target node UUID
+      zh_Hans: 目标节点 UUID
+    human_description:
+      en_US: Target node UUID, defaults to root node if left empty.
+      zh_Hans: 目标节点 UUID, 不填默认为根节点。
+    llm_description: Target node UUID, defaults to root node if left empty.
+
+  - name: node_uuid
+    type: string
+    required: false
+    form: llm
+    label:
+      en_US: Node UUID
+      zh_Hans: 操作节点 UUID
+    human_description:
+      en_US: Operation node UUID [required for move/update/delete].
+      zh_Hans: 操作节点 UUID [移动/更新/删除必填]。
+    llm_description: Operation node UUID [required for move/update/delete].
+
+  - name: doc_ids
+    type: string
+    required: false
+    form: llm
+    label:
+      en_US: Document IDs
+      zh_Hans: 文档id列表
+    human_description:
+      en_US: Document IDs [required for creating documents], separate multiple IDs with ','.
+      zh_Hans: 文档 IDs [创建文档必填],多个用','分隔。
+    llm_description: Document IDs [required for creating documents], separate multiple IDs with ','.
+
+
+  - name: type
+    type: select
+    required: false
+    form: llm
+    default: DOC
+    options:
+      - value: DOC
+        label:
+          en_US: DOC
+          zh_Hans: 文档
+          pt_BR: DOC
+      - value: LINK
+        label:
+          en_US: LINK
+          zh_Hans: 链接
+          pt_BR: LINK
+      - value: TITLE
+        label:
+          en_US: TITLE
+          zh_Hans: 分组
+          pt_BR: TITLE
+    label:
+      en_US: Node type
+      zh_Hans: 操节点类型
+    human_description:
+      en_US: Node type [required for creation] (DOC:document, LINK:external link, TITLE:group).
+      zh_Hans: 操节点类型 [创建必填] (DOC:文档, LINK:外链, TITLE:分组)。
+    llm_description: Node type [required for creation] (DOC:document, LINK:external link, TITLE:group).
+
+  - name: title
+    type: string
+    required: false
+    form: llm
+    label:
+      en_US: Node Name
+      zh_Hans: 节点名称
+    human_description:
+      en_US: Node name [required for creating groups/external links].
+      zh_Hans: 节点名称 [创建分组/外链必填]。
+    llm_description: Node name [required for creating groups/external links].
+
+  - name: url
+    type: string
+    required: false
+    form: llm
+    label:
+      en_US: Node URL
+      zh_Hans: 节点URL
+    human_description:
+      en_US: Node URL [required for creating external links].
+      zh_Hans: 节点 URL [创建外链必填]。
+    llm_description: Node URL [required for creating external links].
+
+
+  - name: open_window
+    type: select
+    required: false
+    form: llm
+    default: 0
+    options:
+      - value: 0
+        label:
+          en_US: DOC
+          zh_Hans: Current Page
+          pt_BR: DOC
+      - value: 1
+        label:
+          en_US: LINK
+          zh_Hans: New Page
+          pt_BR: LINK
+    label:
+      en_US: Open in new window
+      zh_Hans: 是否新窗口打开
+    human_description:
+      en_US: Open in new window [optional for external links] (0:open in current page, 1:open in new window).
+      zh_Hans: 是否新窗口打开 [外链选填] (0:当前页打开, 1:新窗口打开)。
+    llm_description: Open in new window [optional for external links] (0:open in current page, 1:open in new window).
+
+
+  - name: visible
+    type: select
+    required: false
+    form: llm
+    default: 1
+    options:
+      - value: 0
+        label:
+          en_US: Invisible
+          zh_Hans: 隐藏
+          pt_BR: Invisible
+      - value: 1
+        label:
+          en_US: Visible
+          zh_Hans: 可见
+          pt_BR: Visible
+    label:
+      en_US: Visibility
+      zh_Hans: 是否可见
+    human_description:
+      en_US: Visibility (0:invisible, 1:visible).
+      zh_Hans: 是否可见 (0:不可见, 1:可见)。
+    llm_description: Visibility (0:invisible, 1:visible).

+ 24 - 0
api/core/tools/provider/builtin/aliyuque/tools/update_document.py

@@ -0,0 +1,24 @@
+"""
+更新文档
+"""
+
+__author__ = "佐井"
+__created__ = "2024-06-19 16:50:07"
+
+from typing import Any, Union
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.provider.builtin.aliyuque.tools.base import AliYuqueTool
+from core.tools.tool.builtin_tool import BuiltinTool
+
+
+class AliYuqueUpdateDocumentTool(AliYuqueTool, BuiltinTool):
+    def _invoke(
+        self, user_id: str, tool_parameters: dict[str, Any]
+    ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
+        token = self.runtime.credentials.get("token", None)
+        if not token:
+            raise Exception("token is required")
+        return self.create_text_message(
+            self.request("PUT", token, tool_parameters, "/api/v2/repos/{book_id}/docs/{id}")
+        )

+ 87 - 0
api/core/tools/provider/builtin/aliyuque/tools/update_document.yaml

@@ -0,0 +1,87 @@
+identity:
+  name: aliyuque_update_document
+  author: 佐井
+  label:
+    en_US: Update Document
+    zh_Hans: 更新文档
+  icon: icon.svg
+description:
+  human:
+    en_US: Update an existing document within a specified knowledge base by providing the document ID or path.
+    zh_Hans: 通过提供文档ID或路径,更新指定知识库中的现有文档。
+  llm: Update doc in a knowledge base via ID/path.
+parameters:
+  - name: book_id
+    type: number
+    required: true
+    form: llm
+    label:
+      en_US: Knowledge Base ID
+      zh_Hans: 知识库 ID
+    human_description:
+      en_US: The unique identifier of the knowledge base where the document resides.
+      zh_Hans: 文档所属知识库的ID。
+    llm_description: ID of the knowledge base holding the doc.
+  - name: id
+    type: string
+    required: true
+    form: llm
+    label:
+      en_US: Document ID or Path
+      zh_Hans: 文档 ID 或 路径
+    human_description:
+      en_US: The unique identifier or the path of the document to be updated.
+      zh_Hans: 要更新的文档的唯一ID或路径。
+    llm_description: Doc's ID or path for update.
+
+  - name: title
+    type: string
+    required: false
+    form: llm
+    label:
+      en_US: Title
+      zh_Hans: 标题
+    human_description:
+      en_US: The title of the document, defaults to 'Untitled' if not provided.
+      zh_Hans: 文档标题,默认为'无标题'如未提供。
+    llm_description: Title of the document, defaults to 'Untitled'.
+
+  - name: format
+    type: select
+    required: false
+    form: llm
+    options:
+      - value: markdown
+        label:
+          en_US: markdown
+          zh_Hans: markdown
+          pt_BR: markdown
+      - value: html
+        label:
+          en_US: html
+          zh_Hans: html
+          pt_BR: html
+      - value: lake
+        label:
+          en_US: lake
+          zh_Hans: lake
+          pt_BR: lake
+    label:
+      en_US: Content Format
+      zh_Hans: 内容格式
+    human_description:
+      en_US: Format of the document content (markdown, HTML, Lake).
+      zh_Hans: 文档内容格式(markdown, HTML, Lake)。
+    llm_description: Content format choices, markdown, HTML, Lake.
+
+  - name: body
+    type: string
+    required: true
+    form: llm
+    label:
+      en_US: Body Content
+      zh_Hans: 正文内容
+    human_description:
+      en_US: The actual content of the document.
+      zh_Hans: 文档的实际内容。
+    llm_description: Content of the document.

Some files were not shown because too many files changed in this diff