Forráskód Böngészése

feat(Tools): add feishu tools (#8800)

Co-authored-by: 黎斌 <libin.23@bytedance.com>
走在修行的大街上 6 hónapja
szülő
commit
c828a5dfdf
71 módosított fájl, 2755 hozzáadás és 132 törlés
  1. 4 0
      api/core/tools/provider/_position.yaml
  2. BIN
      api/core/tools/provider/builtin/feishu_calendar/_assets/icon.png
  3. 7 0
      api/core/tools/provider/builtin/feishu_calendar/feishu_calendar.py
  4. 36 0
      api/core/tools/provider/builtin/feishu_calendar/feishu_calendar.yaml
  5. 20 0
      api/core/tools/provider/builtin/feishu_calendar/tools/add_event_attendees.py
  6. 54 0
      api/core/tools/provider/builtin/feishu_calendar/tools/add_event_attendees.yaml
  7. 26 0
      api/core/tools/provider/builtin/feishu_calendar/tools/create_event.py
  8. 119 0
      api/core/tools/provider/builtin/feishu_calendar/tools/create_event.yaml
  9. 19 0
      api/core/tools/provider/builtin/feishu_calendar/tools/delete_event.py
  10. 38 0
      api/core/tools/provider/builtin/feishu_calendar/tools/delete_event.yaml
  11. 18 0
      api/core/tools/provider/builtin/feishu_calendar/tools/get_primary_calendar.py
  12. 37 0
      api/core/tools/provider/builtin/feishu_calendar/tools/get_primary_calendar.yaml
  13. 21 0
      api/core/tools/provider/builtin/feishu_calendar/tools/list_events.py
  14. 62 0
      api/core/tools/provider/builtin/feishu_calendar/tools/list_events.yaml
  15. 23 0
      api/core/tools/provider/builtin/feishu_calendar/tools/search_events.py
  16. 100 0
      api/core/tools/provider/builtin/feishu_calendar/tools/search_events.yaml
  17. 24 0
      api/core/tools/provider/builtin/feishu_calendar/tools/update_event.py
  18. 100 0
      api/core/tools/provider/builtin/feishu_calendar/tools/update_event.yaml
  19. 2 10
      api/core/tools/provider/builtin/feishu_document/feishu_document.py
  20. 5 3
      api/core/tools/provider/builtin/feishu_document/feishu_document.yaml
  21. 5 4
      api/core/tools/provider/builtin/feishu_document/tools/create_document.yaml
  22. 2 2
      api/core/tools/provider/builtin/feishu_document/tools/get_document_content.py
  23. 28 7
      api/core/tools/provider/builtin/feishu_document/tools/get_document_content.yaml
  24. 3 2
      api/core/tools/provider/builtin/feishu_document/tools/list_document_blocks.py
  25. 2 2
      api/core/tools/provider/builtin/feishu_document/tools/list_document_blocks.yaml
  26. 1 1
      api/core/tools/provider/builtin/feishu_document/tools/write_document.py
  27. 14 16
      api/core/tools/provider/builtin/feishu_document/tools/write_document.yaml
  28. 2 10
      api/core/tools/provider/builtin/feishu_message/feishu_message.py
  29. 5 3
      api/core/tools/provider/builtin/feishu_message/feishu_message.yaml
  30. 23 0
      api/core/tools/provider/builtin/feishu_message/tools/get_chat_messages.py
  31. 96 0
      api/core/tools/provider/builtin/feishu_message/tools/get_chat_messages.yaml
  32. 21 0
      api/core/tools/provider/builtin/feishu_message/tools/get_thread_messages.py
  33. 72 0
      api/core/tools/provider/builtin/feishu_message/tools/get_thread_messages.yaml
  34. 74 40
      api/core/tools/provider/builtin/feishu_message/tools/send_bot_message.yaml
  35. 28 18
      api/core/tools/provider/builtin/feishu_message/tools/send_webhook_message.yaml
  36. BIN
      api/core/tools/provider/builtin/feishu_spreadsheet/_assets/icon.png
  37. 7 0
      api/core/tools/provider/builtin/feishu_spreadsheet/feishu_spreadsheet.py
  38. 36 0
      api/core/tools/provider/builtin/feishu_spreadsheet/feishu_spreadsheet.yaml
  39. 22 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_cols.py
  40. 72 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_cols.yaml
  41. 22 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_rows.py
  42. 72 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_rows.yaml
  43. 19 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/create_spreadsheet.py
  44. 35 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/create_spreadsheet.yaml
  45. 19 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/get_spreadsheet.py
  46. 49 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/get_spreadsheet.yaml
  47. 18 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/list_spreadsheet_sheets.py
  48. 23 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/list_spreadsheet_sheets.yaml
  49. 23 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_cols.py
  50. 97 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_cols.yaml
  51. 23 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_rows.py
  52. 97 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_rows.yaml
  53. 23 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_table.py
  54. 122 0
      api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_table.yaml
  55. BIN
      api/core/tools/provider/builtin/feishu_task/_assets/icon.png
  56. 7 0
      api/core/tools/provider/builtin/feishu_task/feishu_task.py
  57. 36 0
      api/core/tools/provider/builtin/feishu_task/feishu_task.yaml
  58. 20 0
      api/core/tools/provider/builtin/feishu_task/tools/add_members.py
  59. 58 0
      api/core/tools/provider/builtin/feishu_task/tools/add_members.yaml
  60. 22 0
      api/core/tools/provider/builtin/feishu_task/tools/create_task.py
  61. 74 0
      api/core/tools/provider/builtin/feishu_task/tools/create_task.yaml
  62. 18 0
      api/core/tools/provider/builtin/feishu_task/tools/delete_task.py
  63. 24 0
      api/core/tools/provider/builtin/feishu_task/tools/delete_task.yaml
  64. 23 0
      api/core/tools/provider/builtin/feishu_task/tools/update_task.py
  65. 89 0
      api/core/tools/provider/builtin/feishu_task/tools/update_task.yaml
  66. BIN
      api/core/tools/provider/builtin/feishu_wiki/_assets/icon.png
  67. 7 0
      api/core/tools/provider/builtin/feishu_wiki/feishu_wiki.py
  68. 36 0
      api/core/tools/provider/builtin/feishu_wiki/feishu_wiki.yaml
  69. 21 0
      api/core/tools/provider/builtin/feishu_wiki/tools/get_wiki_nodes.py
  70. 63 0
      api/core/tools/provider/builtin/feishu_wiki/tools/get_wiki_nodes.yaml
  71. 387 14
      api/core/tools/utils/feishu_api_utils.py

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

@@ -34,5 +34,9 @@
 - feishu_base
 - feishu_document
 - feishu_message
+- feishu_wiki
+- feishu_task
+- feishu_calendar
+- feishu_spreadsheet
 - slack
 - tianditu

BIN
api/core/tools/provider/builtin/feishu_calendar/_assets/icon.png


+ 7 - 0
api/core/tools/provider/builtin/feishu_calendar/feishu_calendar.py

@@ -0,0 +1,7 @@
+from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
+from core.tools.utils.feishu_api_utils import auth
+
+
+class FeishuCalendarProvider(BuiltinToolProviderController):
+    def _validate_credentials(self, credentials: dict) -> None:
+        auth(credentials)

+ 36 - 0
api/core/tools/provider/builtin/feishu_calendar/feishu_calendar.yaml

@@ -0,0 +1,36 @@
+identity:
+  author: Doug Lea
+  name: feishu_calendar
+  label:
+    en_US: Feishu Calendar
+    zh_Hans: 飞书日历
+  description:
+    en_US: |
+      Feishu calendar, requires the following permissions: calendar:calendar:read、calendar:calendar、contact:user.id:readonly.
+    zh_Hans: |
+      飞书日历,需要开通以下权限: calendar:calendar:read、calendar:calendar、contact:user.id:readonly。
+  icon: icon.png
+  tags:
+    - social
+    - productivity
+credentials_for_provider:
+  app_id:
+    type: text-input
+    required: true
+    label:
+      en_US: APP ID
+    placeholder:
+      en_US: Please input your feishu app id
+      zh_Hans: 请输入你的飞书 app id
+    help:
+      en_US: Get your app_id and app_secret from Feishu
+      zh_Hans: 从飞书获取您的 app_id 和 app_secret
+    url: https://open.larkoffice.com/app
+  app_secret:
+    type: secret-input
+    required: true
+    label:
+      en_US: APP Secret
+    placeholder:
+      en_US: Please input your app secret
+      zh_Hans: 请输入你的飞书 app secret

+ 20 - 0
api/core/tools/provider/builtin/feishu_calendar/tools/add_event_attendees.py

@@ -0,0 +1,20 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class AddEventAttendeesTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        event_id = tool_parameters.get("event_id")
+        attendee_phone_or_email = tool_parameters.get("attendee_phone_or_email")
+        need_notification = tool_parameters.get("need_notification", True)
+
+        res = client.add_event_attendees(event_id, attendee_phone_or_email, need_notification)
+
+        return self.create_json_message(res)

+ 54 - 0
api/core/tools/provider/builtin/feishu_calendar/tools/add_event_attendees.yaml

@@ -0,0 +1,54 @@
+identity:
+  name: add_event_attendees
+  author: Doug Lea
+  label:
+    en_US: Add Event Attendees
+    zh_Hans: 添加日程参会人
+description:
+  human:
+    en_US: Add Event Attendees
+    zh_Hans: 添加日程参会人
+  llm: A tool for adding attendees to events in Feishu. (在飞书中添加日程参会人)
+parameters:
+  - name: event_id
+    type: string
+    required: true
+    label:
+      en_US: Event ID
+      zh_Hans: 日程 ID
+    human_description:
+      en_US: |
+        The ID of the event, which will be returned when the event is created. For example: fb2a6406-26d6-4c8d-a487-6f0246c94d2f_0.
+      zh_Hans: |
+        创建日程时会返回日程 ID。例如: fb2a6406-26d6-4c8d-a487-6f0246c94d2f_0。
+    llm_description: |
+      日程 ID,创建日程时会返回日程 ID。例如: fb2a6406-26d6-4c8d-a487-6f0246c94d2f_0。
+    form: llm
+
+  - name: need_notification
+    type: boolean
+    required: false
+    default: true
+    label:
+      en_US: Need Notification
+      zh_Hans: 是否需要通知
+    human_description:
+      en_US: |
+        Whether to send a Bot notification to attendees. true: send, false: do not send.
+      zh_Hans: |
+        是否给参与人发送 Bot 通知,true: 发送,false: 不发送。
+    llm_description: |
+      是否给参与人发送 Bot 通知,true: 发送,false: 不发送。
+    form: form
+
+  - name: attendee_phone_or_email
+    type: string
+    required: true
+    label:
+      en_US: Attendee Phone or Email
+      zh_Hans: 参会人电话或邮箱
+    human_description:
+      en_US: The list of attendee emails or phone numbers, separated by commas.
+      zh_Hans: 日程参会人邮箱或者手机号列表,使用逗号分隔。
+    llm_description: 日程参会人邮箱或者手机号列表,使用逗号分隔。
+    form: llm

+ 26 - 0
api/core/tools/provider/builtin/feishu_calendar/tools/create_event.py

@@ -0,0 +1,26 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class CreateEventTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        summary = tool_parameters.get("summary")
+        description = tool_parameters.get("description")
+        start_time = tool_parameters.get("start_time")
+        end_time = tool_parameters.get("end_time")
+        attendee_ability = tool_parameters.get("attendee_ability")
+        need_notification = tool_parameters.get("need_notification", True)
+        auto_record = tool_parameters.get("auto_record", False)
+
+        res = client.create_event(
+            summary, description, start_time, end_time, attendee_ability, need_notification, auto_record
+        )
+
+        return self.create_json_message(res)

+ 119 - 0
api/core/tools/provider/builtin/feishu_calendar/tools/create_event.yaml

@@ -0,0 +1,119 @@
+identity:
+  name: create_event
+  author: Doug Lea
+  label:
+    en_US: Create Event
+    zh_Hans: 创建日程
+description:
+  human:
+    en_US: Create Event
+    zh_Hans: 创建日程
+  llm: A tool for creating events in Feishu.(创建飞书日程)
+parameters:
+  - name: summary
+    type: string
+    required: false
+    label:
+      en_US: Summary
+      zh_Hans: 日程标题
+    human_description:
+      en_US: The title of the event. If not filled, the event title will display (No Subject).
+      zh_Hans: 日程标题,若不填则日程标题显示 (无主题)。
+    llm_description: 日程标题,若不填则日程标题显示 (无主题)。
+    form: llm
+
+  - name: description
+    type: string
+    required: false
+    label:
+      en_US: Description
+      zh_Hans: 日程描述
+    human_description:
+      en_US: The description of the event.
+      zh_Hans: 日程描述。
+    llm_description: 日程描述。
+    form: llm
+
+  - name: need_notification
+    type: boolean
+    required: false
+    default: true
+    label:
+      en_US: Need Notification
+      zh_Hans: 是否发送通知
+    human_description:
+      en_US: |
+        Whether to send a bot message when the event is created, true: send, false: do not send.
+      zh_Hans: 创建日程时是否发送 bot 消息,true:发送,false:不发送。
+    llm_description: 创建日程时是否发送 bot 消息,true:发送,false:不发送。
+    form: form
+
+  - name: start_time
+    type: string
+    required: true
+    label:
+      en_US: Start Time
+      zh_Hans: 开始时间
+    human_description:
+      en_US: |
+        The start time of the event, format: 2006-01-02 15:04:05.
+      zh_Hans: 日程开始时间,格式:2006-01-02 15:04:05。
+    llm_description: 日程开始时间,格式:2006-01-02 15:04:05。
+    form: llm
+
+  - name: end_time
+    type: string
+    required: true
+    label:
+      en_US: End Time
+      zh_Hans: 结束时间
+    human_description:
+      en_US: |
+        The end time of the event, format: 2006-01-02 15:04:05.
+      zh_Hans: 日程结束时间,格式:2006-01-02 15:04:05。
+    llm_description: 日程结束时间,格式:2006-01-02 15:04:05。
+    form: llm
+
+  - name: attendee_ability
+    type: select
+    required: false
+    options:
+      - value: none
+        label:
+          en_US: none
+          zh_Hans: 无
+      - value: can_see_others
+        label:
+          en_US: can_see_others
+          zh_Hans: 可以查看参与人列表
+      - value: can_invite_others
+        label:
+          en_US: can_invite_others
+          zh_Hans: 可以邀请其它参与人
+      - value: can_modify_event
+        label:
+          en_US: can_modify_event
+          zh_Hans: 可以编辑日程
+    default: "none"
+    label:
+      en_US: attendee_ability
+      zh_Hans: 参会人权限
+    human_description:
+      en_US: Attendee ability, optional values are none, can_see_others, can_invite_others, can_modify_event, with a default value of none.
+      zh_Hans: 参会人权限,可选值有无、可以查看参与人列表、可以邀请其它参与人、可以编辑日程,默认值为无。
+    llm_description: 参会人权限,可选值有无、可以查看参与人列表、可以邀请其它参与人、可以编辑日程,默认值为无。
+    form: form
+
+  - name: auto_record
+    type: boolean
+    required: false
+    default: false
+    label:
+      en_US: Auto Record
+      zh_Hans: 自动录制
+    human_description:
+      en_US: |
+        Whether to enable automatic recording, true: enabled, automatically record when the meeting starts; false: not enabled.
+      zh_Hans: 是否开启自动录制,true:开启,会议开始后自动录制;false:不开启。
+    llm_description: 是否开启自动录制,true:开启,会议开始后自动录制;false:不开启。
+    form: form

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

@@ -0,0 +1,19 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class DeleteEventTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        event_id = tool_parameters.get("event_id")
+        need_notification = tool_parameters.get("need_notification", True)
+
+        res = client.delete_event(event_id, need_notification)
+
+        return self.create_json_message(res)

+ 38 - 0
api/core/tools/provider/builtin/feishu_calendar/tools/delete_event.yaml

@@ -0,0 +1,38 @@
+identity:
+  name: delete_event
+  author: Doug Lea
+  label:
+    en_US: Delete Event
+    zh_Hans: 删除日程
+description:
+  human:
+    en_US: Delete Event
+    zh_Hans: 删除日程
+  llm: A tool for deleting events in Feishu.(在飞书中删除日程)
+parameters:
+  - name: event_id
+    type: string
+    required: true
+    label:
+      en_US: Event ID
+      zh_Hans: 日程 ID
+    human_description:
+      en_US: |
+        The ID of the event, for example: e8b9791c-39ae-4908-8ad8-66b13159b9fb_0.
+      zh_Hans: 日程 ID,例如:e8b9791c-39ae-4908-8ad8-66b13159b9fb_0。
+    llm_description: 日程 ID,例如:e8b9791c-39ae-4908-8ad8-66b13159b9fb_0。
+    form: llm
+
+  - name: need_notification
+    type: boolean
+    required: false
+    default: true
+    label:
+      en_US: Need Notification
+      zh_Hans: 是否需要通知
+    human_description:
+      en_US: |
+        Indicates whether to send bot notifications to event participants upon deletion. true: send, false: do not send.
+      zh_Hans: 删除日程是否给日程参与人发送 bot 通知,true:发送,false:不发送。
+    llm_description: 删除日程是否给日程参与人发送 bot 通知,true:发送,false:不发送。
+    form: form

+ 18 - 0
api/core/tools/provider/builtin/feishu_calendar/tools/get_primary_calendar.py

@@ -0,0 +1,18 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class GetPrimaryCalendarTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        user_id_type = tool_parameters.get("user_id_type", "open_id")
+
+        res = client.get_primary_calendar(user_id_type)
+
+        return self.create_json_message(res)

+ 37 - 0
api/core/tools/provider/builtin/feishu_calendar/tools/get_primary_calendar.yaml

@@ -0,0 +1,37 @@
+identity:
+  name: get_primary_calendar
+  author: Doug Lea
+  label:
+    en_US: Get Primary Calendar
+    zh_Hans: 查询主日历信息
+description:
+  human:
+    en_US: Get Primary Calendar
+    zh_Hans: 查询主日历信息
+  llm: A tool for querying primary calendar information in Feishu.(在飞书中查询主日历信息)
+parameters:
+  - name: user_id_type
+    type: select
+    required: false
+    options:
+      - value: open_id
+        label:
+          en_US: open_id
+          zh_Hans: open_id
+      - value: union_id
+        label:
+          en_US: union_id
+          zh_Hans: union_id
+      - value: user_id
+        label:
+          en_US: user_id
+          zh_Hans: user_id
+    default: "open_id"
+    label:
+      en_US: user_id_type
+      zh_Hans: 用户 ID 类型
+    human_description:
+      en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id.
+      zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
+    llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
+    form: form

+ 21 - 0
api/core/tools/provider/builtin/feishu_calendar/tools/list_events.py

@@ -0,0 +1,21 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class ListEventsTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        start_time = tool_parameters.get("start_time")
+        end_time = tool_parameters.get("end_time")
+        page_token = tool_parameters.get("page_token")
+        page_size = tool_parameters.get("page_size")
+
+        res = client.list_events(start_time, end_time, page_token, page_size)
+
+        return self.create_json_message(res)

+ 62 - 0
api/core/tools/provider/builtin/feishu_calendar/tools/list_events.yaml

@@ -0,0 +1,62 @@
+identity:
+  name: list_events
+  author: Doug Lea
+  label:
+    en_US: List Events
+    zh_Hans: 获取日程列表
+description:
+  human:
+    en_US: List Events
+    zh_Hans: 获取日程列表
+  llm: A tool for listing events in Feishu.(在飞书中获取日程列表)
+parameters:
+  - name: start_time
+    type: string
+    required: false
+    label:
+      en_US: Start Time
+      zh_Hans: 开始时间
+    human_description:
+      en_US: |
+        The start time, defaults to 0:00 of the current day if not provided, format: 2006-01-02 15:04:05.
+      zh_Hans: 开始时间,不传值时默认当天 0 点时间,格式为:2006-01-02 15:04:05。
+    llm_description: 开始时间,不传值时默认当天 0 点时间,格式为:2006-01-02 15:04:05。
+    form: llm
+
+  - name: end_time
+    type: string
+    required: false
+    label:
+      en_US: End Time
+      zh_Hans: 结束时间
+    human_description:
+      en_US: |
+        The end time, defaults to 23:59 of the current day if not provided, format: 2006-01-02 15:04:05.
+      zh_Hans: 结束时间,不传值时默认当天 23:59 分时间,格式为:2006-01-02 15:04:05。
+    llm_description: 结束时间,不传值时默认当天 23:59 分时间,格式为:2006-01-02 15:04:05。
+    form: llm
+
+  - name: page_size
+    type: number
+    required: false
+    default: 50
+    label:
+      en_US: Page Size
+      zh_Hans: 分页大小
+    human_description:
+      en_US: The page size, i.e., the number of data entries returned in a single request. The default value is 50, and the value range is [50,1000].
+      zh_Hans: 分页大小,即单次请求所返回的数据条目数。默认值为 50,取值范围为 [50,1000]。
+    llm_description: 分页大小,即单次请求所返回的数据条目数。默认值为 50,取值范围为 [50,1000]。
+    form: llm
+
+  - name: page_token
+    type: string
+    required: false
+    label:
+      en_US: Page Token
+      zh_Hans: 分页标记
+    human_description:
+      en_US: The pagination token. Leave it blank for the first request, indicating to start traversing from the beginning; when the pagination query result has more items, a new page_token will be returned simultaneously, which can be used to obtain the query result in the next traversal.
+      zh_Hans: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。
+    llm_description: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。
+    form: llm

+ 23 - 0
api/core/tools/provider/builtin/feishu_calendar/tools/search_events.py

@@ -0,0 +1,23 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class SearchEventsTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        query = tool_parameters.get("query")
+        start_time = tool_parameters.get("start_time")
+        end_time = tool_parameters.get("end_time")
+        page_token = tool_parameters.get("page_token")
+        user_id_type = tool_parameters.get("user_id_type", "open_id")
+        page_size = tool_parameters.get("page_size", 20)
+
+        res = client.search_events(query, start_time, end_time, page_token, user_id_type, page_size)
+
+        return self.create_json_message(res)

+ 100 - 0
api/core/tools/provider/builtin/feishu_calendar/tools/search_events.yaml

@@ -0,0 +1,100 @@
+identity:
+  name: search_events
+  author: Doug Lea
+  label:
+    en_US: Search Events
+    zh_Hans: 搜索日程
+description:
+  human:
+    en_US: Search Events
+    zh_Hans: 搜索日程
+  llm: A tool for searching events in Feishu.(在飞书中搜索日程)
+parameters:
+  - name: user_id_type
+    type: select
+    required: false
+    options:
+      - value: open_id
+        label:
+          en_US: open_id
+          zh_Hans: open_id
+      - value: union_id
+        label:
+          en_US: union_id
+          zh_Hans: union_id
+      - value: user_id
+        label:
+          en_US: user_id
+          zh_Hans: user_id
+    default: "open_id"
+    label:
+      en_US: user_id_type
+      zh_Hans: 用户 ID 类型
+    human_description:
+      en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id.
+      zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
+    llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
+    form: form
+
+  - name: query
+    type: string
+    required: true
+    label:
+      en_US: Query
+      zh_Hans: 搜索关键字
+    human_description:
+      en_US: The search keyword used for fuzzy searching event names, with a maximum input of 200 characters.
+      zh_Hans: 用于模糊查询日程名称的搜索关键字,最大输入 200 字符。
+    llm_description: 用于模糊查询日程名称的搜索关键字,最大输入 200 字符。
+    form: llm
+
+  - name: start_time
+    type: string
+    required: false
+    label:
+      en_US: Start Time
+      zh_Hans: 开始时间
+    human_description:
+      en_US: |
+        The start time, defaults to 0:00 of the current day if not provided, format: 2006-01-02 15:04:05.
+      zh_Hans: 开始时间,不传值时默认当天 0 点时间,格式为:2006-01-02 15:04:05。
+    llm_description: 开始时间,不传值时默认当天 0 点时间,格式为:2006-01-02 15:04:05。
+    form: llm
+
+  - name: end_time
+    type: string
+    required: false
+    label:
+      en_US: End Time
+      zh_Hans: 结束时间
+    human_description:
+      en_US: |
+        The end time, defaults to 23:59 of the current day if not provided, format: 2006-01-02 15:04:05.
+      zh_Hans: 结束时间,不传值时默认当天 23:59 分时间,格式为:2006-01-02 15:04:05。
+    llm_description: 结束时间,不传值时默认当天 23:59 分时间,格式为:2006-01-02 15:04:05。
+    form: llm
+
+  - name: page_size
+    type: number
+    required: false
+    default: 20
+    label:
+      en_US: Page Size
+      zh_Hans: 分页大小
+    human_description:
+      en_US: The page size, i.e., the number of data entries returned in a single request. The default value is 20, and the value range is [10,100].
+      zh_Hans: 分页大小,即单次请求所返回的数据条目数。默认值为 20,取值范围为 [10,100]。
+    llm_description: 分页大小,即单次请求所返回的数据条目数。默认值为 20,取值范围为 [10,100]。
+    form: llm
+
+  - name: page_token
+    type: string
+    required: false
+    label:
+      en_US: Page Token
+      zh_Hans: 分页标记
+    human_description:
+      en_US: The pagination token. Leave it blank for the first request, indicating to start traversing from the beginning; when the pagination query result has more items, a new page_token will be returned simultaneously, which can be used to obtain the query result in the next traversal.
+      zh_Hans: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。
+    llm_description: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。
+    form: llm

+ 24 - 0
api/core/tools/provider/builtin/feishu_calendar/tools/update_event.py

@@ -0,0 +1,24 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class UpdateEventTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        event_id = tool_parameters.get("event_id")
+        summary = tool_parameters.get("summary")
+        description = tool_parameters.get("description")
+        need_notification = tool_parameters.get("need_notification", True)
+        start_time = tool_parameters.get("start_time")
+        end_time = tool_parameters.get("end_time")
+        auto_record = tool_parameters.get("auto_record", False)
+
+        res = client.update_event(event_id, summary, description, need_notification, start_time, end_time, auto_record)
+
+        return self.create_json_message(res)

+ 100 - 0
api/core/tools/provider/builtin/feishu_calendar/tools/update_event.yaml

@@ -0,0 +1,100 @@
+identity:
+  name: update_event
+  author: Doug Lea
+  label:
+    en_US: Update Event
+    zh_Hans: 更新日程
+description:
+  human:
+    en_US: Update Event
+    zh_Hans: 更新日程
+  llm: A tool for updating events in Feishu.(更新飞书中的日程)
+parameters:
+  - name: event_id
+    type: string
+    required: true
+    label:
+      en_US: Event ID
+      zh_Hans: 日程 ID
+    human_description:
+      en_US: |
+        The ID of the event, for example: e8b9791c-39ae-4908-8ad8-66b13159b9fb_0.
+      zh_Hans: 日程 ID,例如:e8b9791c-39ae-4908-8ad8-66b13159b9fb_0。
+    llm_description: 日程 ID,例如:e8b9791c-39ae-4908-8ad8-66b13159b9fb_0。
+    form: llm
+
+  - name: summary
+    type: string
+    required: false
+    label:
+      en_US: Summary
+      zh_Hans: 日程标题
+    human_description:
+      en_US: The title of the event.
+      zh_Hans: 日程标题。
+    llm_description: 日程标题。
+    form: llm
+
+  - name: description
+    type: string
+    required: false
+    label:
+      en_US: Description
+      zh_Hans: 日程描述
+    human_description:
+      en_US: The description of the event.
+      zh_Hans: 日程描述。
+    llm_description: 日程描述。
+    form: llm
+
+  - name: need_notification
+    type: boolean
+    required: false
+    label:
+      en_US: Need Notification
+      zh_Hans: 是否发送通知
+    human_description:
+      en_US: |
+        Whether to send a bot message when the event is updated, true: send, false: do not send.
+      zh_Hans: 更新日程时是否发送 bot 消息,true:发送,false:不发送。
+    llm_description: 更新日程时是否发送 bot 消息,true:发送,false:不发送。
+    form: form
+
+  - name: start_time
+    type: string
+    required: false
+    label:
+      en_US: Start Time
+      zh_Hans: 开始时间
+    human_description:
+      en_US: |
+        The start time of the event, format: 2006-01-02 15:04:05.
+      zh_Hans: 日程开始时间,格式:2006-01-02 15:04:05。
+    llm_description: 日程开始时间,格式:2006-01-02 15:04:05。
+    form: llm
+
+  - name: end_time
+    type: string
+    required: false
+    label:
+      en_US: End Time
+      zh_Hans: 结束时间
+    human_description:
+      en_US: |
+        The end time of the event, format: 2006-01-02 15:04:05.
+      zh_Hans: 日程结束时间,格式:2006-01-02 15:04:05。
+    llm_description: 日程结束时间,格式:2006-01-02 15:04:05。
+    form: llm
+
+  - name: auto_record
+    type: boolean
+    required: false
+    label:
+      en_US: Auto Record
+      zh_Hans: 自动录制
+    human_description:
+      en_US: |
+        Whether to enable automatic recording, true: enabled, automatically record when the meeting starts; false: not enabled.
+      zh_Hans: 是否开启自动录制,true:开启,会议开始后自动录制;false:不开启。
+    llm_description: 是否开启自动录制,true:开启,会议开始后自动录制;false:不开启。
+    form: form

+ 2 - 10
api/core/tools/provider/builtin/feishu_document/feishu_document.py

@@ -1,15 +1,7 @@
-from core.tools.errors import ToolProviderCredentialValidationError
 from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
-from core.tools.utils.feishu_api_utils import FeishuRequest
+from core.tools.utils.feishu_api_utils import auth
 
 
 class FeishuDocumentProvider(BuiltinToolProviderController):
     def _validate_credentials(self, credentials: dict) -> None:
-        app_id = credentials.get("app_id")
-        app_secret = credentials.get("app_secret")
-        if not app_id or not app_secret:
-            raise ToolProviderCredentialValidationError("app_id and app_secret is required")
-        try:
-            assert FeishuRequest(app_id, app_secret).tenant_access_token is not None
-        except Exception as e:
-            raise ToolProviderCredentialValidationError(str(e))
+        auth(credentials)

+ 5 - 3
api/core/tools/provider/builtin/feishu_document/feishu_document.yaml

@@ -5,8 +5,10 @@ identity:
     en_US: Lark Cloud Document
     zh_Hans: 飞书云文档
   description:
-    en_US: Lark Cloud Document
-    zh_Hans: 飞书云文档
+    en_US: |
+      Lark cloud document, requires the following permissions: docx:document、drive:drive、docs:document.content:read.
+    zh_Hans: |
+      飞书云文档,需要开通以下权限: docx:document、drive:drive、docs:document.content:read。
   icon: icon.svg
   tags:
     - social
@@ -23,7 +25,7 @@ credentials_for_provider:
     help:
       en_US: Get your app_id and app_secret from Feishu
       zh_Hans: 从飞书获取您的 app_id 和 app_secret
-    url: https://open.feishu.cn
+    url: https://open.larkoffice.com/app
   app_secret:
     type: secret-input
     required: true

+ 5 - 4
api/core/tools/provider/builtin/feishu_document/tools/create_document.yaml

@@ -7,7 +7,7 @@ identity:
 description:
   human:
     en_US: Create Lark document
-    zh_Hans: 创建飞书文档,支持创建空文档和带内容的文档,支持 markdown 语法创建。
+    zh_Hans: 创建飞书文档,支持创建空文档和带内容的文档,支持 markdown 语法创建。应用需要开启机器人能力(https://open.feishu.cn/document/faq/trouble-shooting/how-to-enable-bot-ability)。
   llm: A tool for creating Feishu documents.
 parameters:
   - name: title
@@ -41,7 +41,8 @@ parameters:
       en_US: folder_token
       zh_Hans: 文档所在文件夹的 Token
     human_description:
-      en_US: The token of the folder where the document is located. If it is not passed or is empty, it means the root directory.
-      zh_Hans: 文档所在文件夹的 Token,不传或传空表示根目录。
-    llm_description: 文档所在文件夹的 Token,不传或传空表示根目录。
+      en_US: |
+        The token of the folder where the document is located. If it is not passed or is empty, it means the root directory. For Example: https://svi136aogf123.feishu.cn/drive/folder/JgR9fiG9AlPt8EdsSNpcGjIInbf
+      zh_Hans: 文档所在文件夹的 Token,不传或传空表示根目录。例如:https://svi136aogf123.feishu.cn/drive/folder/JgR9fiG9AlPt8EdsSNpcGjIInbf。
+    llm_description: 文档所在文件夹的 Token,不传或传空表示根目录。例如:https://svi136aogf123.feishu.cn/drive/folder/JgR9fiG9AlPt8EdsSNpcGjIInbf。
     form: llm

+ 2 - 2
api/core/tools/provider/builtin/feishu_document/tools/get_document_content.py

@@ -12,8 +12,8 @@ class GetDocumentRawContentTool(BuiltinTool):
         client = FeishuRequest(app_id, app_secret)
 
         document_id = tool_parameters.get("document_id")
-        mode = tool_parameters.get("mode")
-        lang = tool_parameters.get("lang", 0)
+        mode = tool_parameters.get("mode", "markdown")
+        lang = tool_parameters.get("lang", "0")
 
         res = client.get_document_content(document_id, mode, lang)
         return self.create_json_message(res)

+ 28 - 7
api/core/tools/provider/builtin/feishu_document/tools/get_document_content.yaml

@@ -23,8 +23,18 @@ parameters:
     form: llm
 
   - name: mode
-    type: string
+    type: select
     required: false
+    options:
+      - value: text
+        label:
+          en_US: text
+          zh_Hans: text
+      - value: markdown
+        label:
+          en_US: markdown
+          zh_Hans: markdown
+    default: "markdown"
     label:
       en_US: mode
       zh_Hans: 文档返回格式
@@ -32,18 +42,29 @@ parameters:
       en_US: Format of the document return, optional values are text, markdown, can be empty, default is markdown.
       zh_Hans: 文档返回格式,可选值有 text、markdown,可以为空,默认值为 markdown。
     llm_description: 文档返回格式,可选值有 text、markdown,可以为空,默认值为 markdown。
-    form: llm
+    form: form
 
   - name: lang
-    type: number
+    type: select
     required: false
-    default: 0
+    options:
+      - value: "0"
+        label:
+          en_US: User's default name
+          zh_Hans: 用户的默认名称
+      - value: "1"
+        label:
+          en_US: User's English name
+          zh_Hans: 用户的英文名称
+    default: "0"
     label:
       en_US: lang
       zh_Hans: 指定@用户的语言
     human_description:
       en_US: |
         Specifies the language for MentionUser, optional values are [0, 1]. 0: User's default name, 1: User's English name, default is 0.
-      zh_Hans: 指定返回的 MentionUser,即 @用户 的语言,可选值有 [0,1]。0:该用户的默认名称,1:该用户的英文名称,默认值为 0。
-    llm_description: 指定返回的 MentionUser,即 @用户 的语言,可选值有 [0,1]。0:该用户的默认名称,1:该用户的英文名称,默认值为 0。
-    form: llm
+      zh_Hans: |
+        指定返回的 MentionUser,即@用户的语言,可选值有 [0,1]。0: 该用户的默认名称,1: 该用户的英文名称,默认值为 0。
+    llm_description: |
+      指定返回的 MentionUser,即@用户的语言,可选值有 [0,1]。0: 该用户的默认名称,1: 该用户的英文名称,默认值为 0。
+    form: form

+ 3 - 2
api/core/tools/provider/builtin/feishu_document/tools/list_document_blocks.py

@@ -12,8 +12,9 @@ class ListDocumentBlockTool(BuiltinTool):
         client = FeishuRequest(app_id, app_secret)
 
         document_id = tool_parameters.get("document_id")
-        page_size = tool_parameters.get("page_size", 500)
         page_token = tool_parameters.get("page_token", "")
+        user_id_type = tool_parameters.get("user_id_type", "open_id")
+        page_size = tool_parameters.get("page_size", 500)
 
-        res = client.list_document_blocks(document_id, page_token, page_size)
+        res = client.list_document_blocks(document_id, page_token, user_id_type, page_size)
         return self.create_json_message(res)

+ 2 - 2
api/core/tools/provider/builtin/feishu_document/tools/list_document_blocks.yaml

@@ -46,12 +46,12 @@ parameters:
       en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id.
       zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
     llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
-    form: llm
+    form: form
 
   - name: page_size
     type: number
     required: false
-    default: "500"
+    default: 500
     label:
       en_US: page_size
       zh_Hans: 分页大小

+ 1 - 1
api/core/tools/provider/builtin/feishu_document/tools/write_document.py

@@ -13,7 +13,7 @@ class CreateDocumentTool(BuiltinTool):
 
         document_id = tool_parameters.get("document_id")
         content = tool_parameters.get("content")
-        position = tool_parameters.get("position")
+        position = tool_parameters.get("position", "end")
 
         res = client.write_document(document_id, content, position)
         return self.create_json_message(res)

+ 14 - 16
api/core/tools/provider/builtin/feishu_document/tools/write_document.yaml

@@ -35,25 +35,23 @@ parameters:
     form: llm
 
   - name: position
-    type: string
+    type: select
     required: false
-    label:
-      en_US: position
-      zh_Hans: 添加位置
-    human_description:
-      en_US: |
-        Enumeration values: start or end. Use 'start' to add content at the beginning of the document, and 'end' to add content at the end. The default value is 'end'.
-      zh_Hans: 枚举值:start 或 end。使用 'start' 在文档开头添加内容,使用 'end' 在文档结尾添加内容,默认值为 'end'。
-    llm_description: |
-      枚举值 start、end,start: 在文档开头添加内容;end: 在文档结尾添加内容,默认值为 end。
-    form: llm
     options:
       - value: start
         label:
-          en_US: start
-          zh_Hans: 在文档开头添加内容
+          en_US: document start
+          zh_Hans: 文档开始
       - value: end
         label:
-          en_US: end
-          zh_Hans: 在文档结尾添加内容
-    default: start
+          en_US: document end
+          zh_Hans: 文档结束
+    default: "end"
+    label:
+      en_US: position
+      zh_Hans: 内容添加位置
+    human_description:
+      en_US: Content insertion position, optional values are start, end. 'start' means adding content at the beginning of the document; 'end' means adding content at the end of the document. The default value is end.
+      zh_Hans: 内容添加位置,可选值有 start、end。start 表示在文档开头添加内容;end 表示在文档结尾添加内容,默认值为 end。
+    llm_description: 内容添加位置,可选值有 start、end。start 表示在文档开头添加内容;end 表示在文档结尾添加内容,默认值为 end。
+    form: form

+ 2 - 10
api/core/tools/provider/builtin/feishu_message/feishu_message.py

@@ -1,15 +1,7 @@
-from core.tools.errors import ToolProviderCredentialValidationError
 from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
-from core.tools.utils.feishu_api_utils import FeishuRequest
+from core.tools.utils.feishu_api_utils import auth
 
 
 class FeishuMessageProvider(BuiltinToolProviderController):
     def _validate_credentials(self, credentials: dict) -> None:
-        app_id = credentials.get("app_id")
-        app_secret = credentials.get("app_secret")
-        if not app_id or not app_secret:
-            raise ToolProviderCredentialValidationError("app_id and app_secret is required")
-        try:
-            assert FeishuRequest(app_id, app_secret).tenant_access_token is not None
-        except Exception as e:
-            raise ToolProviderCredentialValidationError(str(e))
+        auth(credentials)

+ 5 - 3
api/core/tools/provider/builtin/feishu_message/feishu_message.yaml

@@ -5,8 +5,10 @@ identity:
     en_US: Lark Message
     zh_Hans: 飞书消息
   description:
-    en_US: Lark Message
-    zh_Hans: 飞书消息
+    en_US: |
+      Lark message, requires the following permissions: im:message、im:message.group_msg.
+    zh_Hans: |
+      飞书消息,需要开通以下权限: im:message、im:message.group_msg。
   icon: icon.svg
   tags:
     - social
@@ -23,7 +25,7 @@ credentials_for_provider:
     help:
       en_US: Get your app_id and app_secret from Feishu
       zh_Hans: 从飞书获取您的 app_id 和 app_secret
-    url: https://open.feishu.cn
+    url: https://open.larkoffice.com/app
   app_secret:
     type: secret-input
     required: true

+ 23 - 0
api/core/tools/provider/builtin/feishu_message/tools/get_chat_messages.py

@@ -0,0 +1,23 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class GetChatMessagesTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        container_id = tool_parameters.get("container_id")
+        start_time = tool_parameters.get("start_time")
+        end_time = tool_parameters.get("end_time")
+        page_token = tool_parameters.get("page_token")
+        sort_type = tool_parameters.get("sort_type", "ByCreateTimeAsc")
+        page_size = tool_parameters.get("page_size", 20)
+
+        res = client.get_chat_messages(container_id, start_time, end_time, page_token, sort_type, page_size)
+
+        return self.create_json_message(res)

+ 96 - 0
api/core/tools/provider/builtin/feishu_message/tools/get_chat_messages.yaml

@@ -0,0 +1,96 @@
+identity:
+  name: get_chat_messages
+  author: Doug Lea
+  label:
+    en_US: Get Chat Messages
+    zh_Hans: 获取指定单聊、群聊的消息历史
+description:
+  human:
+    en_US: Get Chat Messages
+    zh_Hans: 获取指定单聊、群聊的消息历史
+  llm: A tool for getting chat messages from specific one-on-one chats or group chats.(获取指定单聊、群聊的消息历史)
+parameters:
+  - name: container_id
+    type: string
+    required: true
+    label:
+      en_US: Container Id
+      zh_Hans: 群聊或单聊的 ID
+    human_description:
+      en_US: The ID of the group chat or single chat. Refer to the group ID description for how to obtain it. https://open.feishu.cn/document/server-docs/group/chat/chat-id-description
+      zh_Hans: 群聊或单聊的 ID,获取方式参见群 ID 说明。https://open.feishu.cn/document/server-docs/group/chat/chat-id-description
+    llm_description: 群聊或单聊的 ID,获取方式参见群 ID 说明。https://open.feishu.cn/document/server-docs/group/chat/chat-id-description
+    form: llm
+
+  - name: start_time
+    type: string
+    required: false
+    label:
+      en_US: Start Time
+      zh_Hans: 起始时间
+    human_description:
+      en_US: The start time for querying historical messages, formatted as "2006-01-02 15:04:05".
+      zh_Hans: 待查询历史信息的起始时间,格式为 "2006-01-02 15:04:05"。
+    llm_description: 待查询历史信息的起始时间,格式为 "2006-01-02 15:04:05"。
+    form: llm
+
+  - name: end_time
+    type: string
+    required: false
+    label:
+      en_US: End Time
+      zh_Hans: 结束时间
+    human_description:
+      en_US: The end time for querying historical messages, formatted as "2006-01-02 15:04:05".
+      zh_Hans: 待查询历史信息的结束时间,格式为 "2006-01-02 15:04:05"。
+    llm_description: 待查询历史信息的结束时间,格式为 "2006-01-02 15:04:05"。
+    form: llm
+
+  - name: sort_type
+    type: select
+    required: false
+    options:
+      - value: ByCreateTimeAsc
+        label:
+          en_US: ByCreateTimeAsc
+          zh_Hans: ByCreateTimeAsc
+      - value: ByCreateTimeDesc
+        label:
+          en_US: ByCreateTimeDesc
+          zh_Hans: ByCreateTimeDesc
+    default: "ByCreateTimeAsc"
+    label:
+      en_US: Sort Type
+      zh_Hans: 排序方式
+    human_description:
+      en_US: |
+        The message sorting method. Optional values are ByCreateTimeAsc: sorted in ascending order by message creation time; ByCreateTimeDesc: sorted in descending order by message creation time. The default value is ByCreateTimeAsc. Note: When using page_token for pagination requests, the sorting method (sort_type) is consistent with the first request and cannot be changed midway.
+      zh_Hans: |
+        消息排序方式,可选值有 ByCreateTimeAsc:按消息创建时间升序排列;ByCreateTimeDesc:按消息创建时间降序排列。默认值为:ByCreateTimeAsc。注意:使用 page_token 分页请求时,排序方式(sort_type)均与第一次请求一致,不支持中途改换排序方式。
+    llm_description: 消息排序方式,可选值有 ByCreateTimeAsc:按消息创建时间升序排列;ByCreateTimeDesc:按消息创建时间降序排列。默认值为:ByCreateTimeAsc。注意:使用 page_token 分页请求时,排序方式(sort_type)均与第一次请求一致,不支持中途改换排序方式。
+    form: form
+
+  - name: page_size
+    type: number
+    required: false
+    default: 20
+    label:
+      en_US: Page Size
+      zh_Hans: 分页大小
+    human_description:
+      en_US: The page size, i.e., the number of data entries returned in a single request. The default value is 20, and the value range is [1,50].
+      zh_Hans: 分页大小,即单次请求所返回的数据条目数。默认值为 20,取值范围为 [1,50]。
+    llm_description: 分页大小,即单次请求所返回的数据条目数。默认值为 20,取值范围为 [1,50]。
+    form: llm
+
+  - name: page_token
+    type: string
+    required: false
+    label:
+      en_US: Page Token
+      zh_Hans: 分页标记
+    human_description:
+      en_US: The pagination token. Leave it blank for the first request, indicating to start traversing from the beginning; when the pagination query result has more items, a new page_token will be returned simultaneously, which can be used to obtain the query result in the next traversal.
+      zh_Hans: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。
+    llm_description: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。
+    form: llm

+ 21 - 0
api/core/tools/provider/builtin/feishu_message/tools/get_thread_messages.py

@@ -0,0 +1,21 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class GetChatMessagesTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        container_id = tool_parameters.get("container_id")
+        page_token = tool_parameters.get("page_token")
+        sort_type = tool_parameters.get("sort_type", "ByCreateTimeAsc")
+        page_size = tool_parameters.get("page_size", 20)
+
+        res = client.get_thread_messages(container_id, page_token, sort_type, page_size)
+
+        return self.create_json_message(res)

+ 72 - 0
api/core/tools/provider/builtin/feishu_message/tools/get_thread_messages.yaml

@@ -0,0 +1,72 @@
+identity:
+  name: get_thread_messages
+  author: Doug Lea
+  label:
+    en_US: Get Thread Messages
+    zh_Hans: 获取指定话题的消息历史
+description:
+  human:
+    en_US: Get Thread Messages
+    zh_Hans: 获取指定话题的消息历史
+  llm: A tool for getting chat messages from specific threads.(获取指定话题的消息历史)
+parameters:
+  - name: container_id
+    type: string
+    required: true
+    label:
+      en_US: Thread Id
+      zh_Hans: 话题 ID
+    human_description:
+      en_US: The ID of the thread. Refer to the thread overview on how to obtain the thread_id. https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/thread-introduction
+      zh_Hans: 话题 ID,获取方式参见话题概述的如何获取 thread_id 章节。https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/thread-introduction
+    llm_description: 话题 ID,获取方式参见话题概述的如何获取 thread_id 章节。https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/thread-introduction
+    form: llm
+
+  - name: sort_type
+    type: select
+    required: false
+    options:
+      - value: ByCreateTimeAsc
+        label:
+          en_US: ByCreateTimeAsc
+          zh_Hans: ByCreateTimeAsc
+      - value: ByCreateTimeDesc
+        label:
+          en_US: ByCreateTimeDesc
+          zh_Hans: ByCreateTimeDesc
+    default: "ByCreateTimeAsc"
+    label:
+      en_US: Sort Type
+      zh_Hans: 排序方式
+    human_description:
+      en_US: |
+        The message sorting method. Optional values are ByCreateTimeAsc: sorted in ascending order by message creation time; ByCreateTimeDesc: sorted in descending order by message creation time. The default value is ByCreateTimeAsc. Note: When using page_token for pagination requests, the sorting method (sort_type) is consistent with the first request and cannot be changed midway.
+      zh_Hans: |
+        消息排序方式,可选值有 ByCreateTimeAsc:按消息创建时间升序排列;ByCreateTimeDesc:按消息创建时间降序排列。默认值为:ByCreateTimeAsc。注意:使用 page_token 分页请求时,排序方式(sort_type)均与第一次请求一致,不支持中途改换排序方式。
+    llm_description: 消息排序方式,可选值有 ByCreateTimeAsc:按消息创建时间升序排列;ByCreateTimeDesc:按消息创建时间降序排列。默认值为:ByCreateTimeAsc。注意:使用 page_token 分页请求时,排序方式(sort_type)均与第一次请求一致,不支持中途改换排序方式。
+    form: form
+
+  - name: page_size
+    type: number
+    required: false
+    default: 20
+    label:
+      en_US: Page Size
+      zh_Hans: 分页大小
+    human_description:
+      en_US: The page size, i.e., the number of data entries returned in a single request. The default value is 20, and the value range is [1,50].
+      zh_Hans: 分页大小,即单次请求所返回的数据条目数。默认值为 20,取值范围为 [1,50]。
+    llm_description: 分页大小,即单次请求所返回的数据条目数。默认值为 20,取值范围为 [1,50]。
+    form: llm
+
+  - name: page_token
+    type: string
+    required: false
+    label:
+      en_US: Page Token
+      zh_Hans: 分页标记
+    human_description:
+      en_US: The pagination token. Leave it blank for the first request, indicating to start traversing from the beginning; when the pagination query result has more items, a new page_token will be returned simultaneously, which can be used to obtain the query result in the next traversal.
+      zh_Hans: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。
+    llm_description: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。
+    form: llm

+ 74 - 40
api/core/tools/provider/builtin/feishu_message/tools/send_bot_message.yaml

@@ -10,53 +10,53 @@ description:
     zh_Hans: 发送飞书应用消息
   llm: A tool for sending Feishu application messages.
 parameters:
+  - name: receive_id
+    type: string
+    required: true
+    label:
+      en_US: receive_id
+      zh_Hans: 消息接收者的 ID
+    human_description:
+      en_US: The ID of the message receiver, the ID type is consistent with the value of the query parameter receive_id_type.
+      zh_Hans: 消息接收者的 ID,ID 类型与查询参数 receive_id_type 的取值一致。
+    llm_description: 消息接收者的 ID,ID 类型与查询参数 receive_id_type 的取值一致。
+    form: llm
+
   - name: receive_id_type
     type: select
     required: true
     options:
       - value: open_id
         label:
-          en_US: open id
-          zh_Hans: open id
+          en_US: open_id
+          zh_Hans: open_id
       - value: union_id
         label:
-          en_US: union id
-          zh_Hans: union id
+          en_US: union_id
+          zh_Hans: union_id
       - value: user_id
         label:
-          en_US: user id
-          zh_Hans: user id
+          en_US: user_id
+          zh_Hans: user_id
       - value: email
         label:
           en_US: email
           zh_Hans: email
       - value: chat_id
         label:
-          en_US: chat id
-          zh_Hans: chat id
+          en_US: chat_id
+          zh_Hans: chat_id
     label:
-      en_US: User ID Type
-      zh_Hans: 用户 ID 类型
+      en_US: receive_id_type
+      zh_Hans: 消息接收者的 ID 类型
     human_description:
-      en_US: User ID Type
-      zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id、email、chat_id。
-    llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id、email、chat_id。
-    form: llm
-
-  - name: receive_id
-    type: string
-    required: true
-    label:
-      en_US: Receive Id
-      zh_Hans: 消息接收者的 ID
-    human_description:
-      en_US: The ID of the message receiver. The ID type should correspond to the query parameter receive_id_type.
-      zh_Hans: 消息接收者的 ID,ID 类型应与查询参数 receive_id_type 对应。
-    llm_description: 消息接收者的 ID,ID 类型应与查询参数 receive_id_type 对应。
-    form: llm
+      en_US: The ID type of the message receiver, optional values are open_id, union_id, user_id, email, chat_id, with a default value of open_id.
+      zh_Hans: 消息接收者的 ID 类型,可选值有 open_id、union_id、user_id、email、chat_id,默认值为 open_id。
+    llm_description: 消息接收者的 ID 类型,可选值有 open_id、union_id、user_id、email、chat_id,默认值为 open_id。
+    form: form
 
   - name: msg_type
-    type: string
+    type: select
     required: true
     options:
       - value: text
@@ -65,27 +65,61 @@ parameters:
           zh_Hans: 文本
       - value: interactive
         label:
-          en_US: message card
-          zh_Hans: 消息卡片
+          en_US: interactive
+          zh_Hans: 卡片
+      - value: post
+        label:
+          en_US: post
+          zh_Hans: 富文本
+      - value: image
+        label:
+          en_US: image
+          zh_Hans: 图片
+      - value: file
+        label:
+          en_US: file
+          zh_Hans: 文件
+      - value: audio
+        label:
+          en_US: audio
+          zh_Hans: 语音
+      - value: media
+        label:
+          en_US: media
+          zh_Hans: 视频
+      - value: sticker
+        label:
+          en_US: sticker
+          zh_Hans: 表情包
+      - value: share_chat
+        label:
+          en_US: share_chat
+          zh_Hans: 分享群名片
+      - value: share_user
+        label:
+          en_US: share_user
+          zh_Hans: 分享个人名片
+      - value: system
+        label:
+          en_US: system
+          zh_Hans: 系统消息
     label:
-      en_US: Message type
+      en_US: msg_type
       zh_Hans: 消息类型
     human_description:
-      en_US: Message type, optional values are, text (text), interactive (message card).
-      zh_Hans: 消息类型,可选值有:text(文本)、interactive(消息卡片)。
-    llm_description: 消息类型,可选值有:text(文本)、interactive(消息卡片)。
-    form: llm
+      en_US: Message type. Optional values are text, post, image, file, audio, media, sticker, interactive, share_chat, share_user, system. For detailed introduction of different message types, refer to the message content(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json).
+      zh_Hans: 消息类型。可选值有:text、post、image、file、audio、media、sticker、interactive、share_chat、share_user、system。不同消息类型的详细介绍,参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。
+    llm_description: 消息类型。可选值有:text、post、image、file、audio、media、sticker、interactive、share_chat、share_user、system。不同消息类型的详细介绍,参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。
+    form: form
 
   - name: content
     type: string
     required: true
     label:
-      en_US: Message content
+      en_US: content
       zh_Hans: 消息内容
     human_description:
-      en_US: Message content
-      zh_Hans: |
-        消息内容,JSON 结构序列化后的字符串。不同 msg_type 对应不同内容,
-        具体格式说明参考:https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json
-    llm_description: 消息内容,JSON 结构序列化后的字符串。不同 msg_type 对应不同内容。
+      en_US: Message content, a JSON structure serialized string. The value of this parameter corresponds to msg_type. For example, if msg_type is text, this parameter needs to pass in text type content. To understand the format and usage limitations of different message types, refer to the message content(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json).
+      zh_Hans: 消息内容,JSON 结构序列化后的字符串。该参数的取值与 msg_type 对应,例如 msg_type 取值为 text,则该参数需要传入文本类型的内容。了解不同类型的消息内容格式、使用限制,可参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。
+    llm_description: 消息内容,JSON 结构序列化后的字符串。该参数的取值与 msg_type 对应,例如 msg_type 取值为 text,则该参数需要传入文本类型的内容。了解不同类型的消息内容格式、使用限制,可参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。
     form: llm

+ 28 - 18
api/core/tools/provider/builtin/feishu_message/tools/send_webhook_message.yaml

@@ -15,15 +15,18 @@ parameters:
     required: true
     label:
       en_US: webhook
-      zh_Hans: webhook 的地址
+      zh_Hans: webhook
     human_description:
-      en_US: The address of the webhook
-      zh_Hans: webhook 的地址
-    llm_description: webhook 的地址
+      en_US: |
+        The address of the webhook, the format of the webhook address corresponding to the bot is as follows: https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxxx. For details, please refer to: Feishu Custom Bot Usage Guide(https://open.larkoffice.com/document/client-docs/bot-v3/add-custom-bot)
+      zh_Hans: |
+        webhook 的地址,机器人对应的 webhook 地址格式如下: https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxxx,详情可参考: 飞书自定义机器人使用指南(https://open.larkoffice.com/document/client-docs/bot-v3/add-custom-bot)
+    llm_description: |
+      webhook 的地址,机器人对应的 webhook 地址格式如下: https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxxx,详情可参考: 飞书自定义机器人使用指南(https://open.larkoffice.com/document/client-docs/bot-v3/add-custom-bot)
     form: llm
 
   - name: msg_type
-    type: string
+    type: select
     required: true
     options:
       - value: text
@@ -32,27 +35,34 @@ parameters:
           zh_Hans: 文本
       - value: interactive
         label:
-          en_US: message card
-          zh_Hans: 消息卡片
+          en_US: interactive
+          zh_Hans: 卡片
+      - value: image
+        label:
+          en_US: image
+          zh_Hans: 图片
+      - value: share_chat
+        label:
+          en_US: share_chat
+          zh_Hans: 分享群名片
     label:
-      en_US: Message type
+      en_US: msg_type
       zh_Hans: 消息类型
     human_description:
-      en_US: Message type, optional values are, text (text), interactive (message card).
-      zh_Hans: 消息类型,可选值有:text(文本)、interactive(消息卡片)。
-    llm_description: 消息类型,可选值有:text(文本)、interactive(消息卡片)。
-    form: llm
+      en_US: Message type. Optional values are text, image, interactive, share_chat. For detailed introduction of different message types, refer to the message content(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json).
+      zh_Hans: 消息类型。可选值有:text、image、interactive、share_chat。不同消息类型的详细介绍,参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。
+    llm_description: 消息类型。可选值有:text、image、interactive、share_chat。不同消息类型的详细介绍,参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。
+    form: form
+
 
   - name: content
     type: string
     required: true
     label:
-      en_US: Message content
+      en_US: content
       zh_Hans: 消息内容
     human_description:
-      en_US: Message content
-      zh_Hans: |
-        消息内容,JSON 结构序列化后的字符串。不同 msg_type 对应不同内容,
-        具体格式说明参考:https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json
-    llm_description: 消息内容,JSON 结构序列化后的字符串。不同 msg_type 对应不同内容。
+      en_US: Message content, a JSON structure serialized string. The value of this parameter corresponds to msg_type. For example, if msg_type is text, this parameter needs to pass in text type content. To understand the format and usage limitations of different message types, refer to the message content(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json).
+      zh_Hans: 消息内容,JSON 结构序列化后的字符串。该参数的取值与 msg_type 对应,例如 msg_type 取值为 text,则该参数需要传入文本类型的内容。了解不同类型的消息内容格式、使用限制,可参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。
+    llm_description: 消息内容,JSON 结构序列化后的字符串。该参数的取值与 msg_type 对应,例如 msg_type 取值为 text,则该参数需要传入文本类型的内容。了解不同类型的消息内容格式、使用限制,可参见发送消息内容(https://open.larkoffice.com/document/server-docs/im-v1/message-content-description/create_json)。
     form: llm

BIN
api/core/tools/provider/builtin/feishu_spreadsheet/_assets/icon.png


+ 7 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/feishu_spreadsheet.py

@@ -0,0 +1,7 @@
+from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
+from core.tools.utils.feishu_api_utils import auth
+
+
+class FeishuMessageProvider(BuiltinToolProviderController):
+    def _validate_credentials(self, credentials: dict) -> None:
+        auth(credentials)

+ 36 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/feishu_spreadsheet.yaml

@@ -0,0 +1,36 @@
+identity:
+  author: Doug Lea
+  name: feishu_spreadsheet
+  label:
+    en_US: Feishu Spreadsheet
+    zh_Hans: 飞书电子表格
+  description:
+    en_US: |
+      Feishu Spreadsheet, requires the following permissions: sheets:spreadsheet.
+    zh_Hans: |
+      飞书电子表格,需要开通以下权限: sheets:spreadsheet。
+  icon: icon.png
+  tags:
+    - social
+    - productivity
+credentials_for_provider:
+  app_id:
+    type: text-input
+    required: true
+    label:
+      en_US: APP ID
+    placeholder:
+      en_US: Please input your feishu app id
+      zh_Hans: 请输入你的飞书 app id
+    help:
+      en_US: Get your app_id and app_secret from Feishu
+      zh_Hans: 从飞书获取您的 app_id 和 app_secret
+    url: https://open.larkoffice.com/app
+  app_secret:
+    type: secret-input
+    required: true
+    label:
+      en_US: APP Secret
+    placeholder:
+      en_US: Please input your app secret
+      zh_Hans: 请输入你的飞书 app secret

+ 22 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_cols.py

@@ -0,0 +1,22 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class AddColsTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        spreadsheet_token = tool_parameters.get("spreadsheet_token")
+        sheet_id = tool_parameters.get("sheet_id")
+        sheet_name = tool_parameters.get("sheet_name")
+        length = tool_parameters.get("length")
+        values = tool_parameters.get("values")
+
+        res = client.add_cols(spreadsheet_token, sheet_id, sheet_name, length, values)
+
+        return self.create_json_message(res)

+ 72 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_cols.yaml

@@ -0,0 +1,72 @@
+identity:
+  name: add_cols
+  author: Doug Lea
+  label:
+    en_US: Add Cols
+    zh_Hans: 新增多列至工作表最后
+description:
+  human:
+    en_US: Add Cols
+    zh_Hans: 新增多列至工作表最后
+  llm: A tool for adding multiple columns to the end of a spreadsheet. (新增多列至工作表最后)
+parameters:
+  - name: spreadsheet_token
+    type: string
+    required: true
+    label:
+      en_US: spreadsheet_token
+      zh_Hans: 电子表格 token
+    human_description:
+      en_US: Spreadsheet token, supports input of spreadsheet URL.
+      zh_Hans: 电子表格 token,支持输入电子表格 url。
+    llm_description: 电子表格 token,支持输入电子表格 url。
+    form: llm
+
+  - name: sheet_id
+    type: string
+    required: false
+    label:
+      en_US: sheet_id
+      zh_Hans: 工作表 ID
+    human_description:
+      en_US: Sheet ID, either sheet_id or sheet_name must be filled.
+      zh_Hans: 工作表 ID,与 sheet_name 二者其一必填。
+    llm_description: 工作表 ID,与 sheet_name 二者其一必填。
+    form: llm
+
+  - name: sheet_name
+    type: string
+    required: false
+    label:
+      en_US: sheet_name
+      zh_Hans: 工作表名称
+    human_description:
+      en_US: Sheet name, either sheet_id or sheet_name must be filled.
+      zh_Hans: 工作表名称,与 sheet_id 二者其一必填。
+    llm_description: 工作表名称,与 sheet_id 二者其一必填。
+    form: llm
+
+  - name: length
+    type: number
+    required: true
+    label:
+      en_US: length
+      zh_Hans: 要增加的列数
+    human_description:
+      en_US: Number of columns to add, range (0-5000].
+      zh_Hans: 要增加的列数,范围(0-5000]。
+    llm_description: 要增加的列数,范围(0-5000]。
+    form: llm
+
+  - name: values
+    type: string
+    required: false
+    label:
+      en_US: values
+      zh_Hans: 新增列的单元格内容
+    human_description:
+      en_US: |
+        Content of the new columns, array of objects in string format, each array represents a row of table data, format like: [ [ "ID","Name","Age" ],[ 1,"Zhang San",10 ],[ 2,"Li Si",11 ] ].
+      zh_Hans: 新增列的单元格内容,数组对象字符串,每个数组一行表格数据,格式:[["编号","姓名","年龄"],[1,"张三",10],[2,"李四",11]]。
+    llm_description: 新增列的单元格内容,数组对象字符串,每个数组一行表格数据,格式:[["编号","姓名","年龄"],[1,"张三",10],[2,"李四",11]]。
+    form: llm

+ 22 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_rows.py

@@ -0,0 +1,22 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class AddRowsTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        spreadsheet_token = tool_parameters.get("spreadsheet_token")
+        sheet_id = tool_parameters.get("sheet_id")
+        sheet_name = tool_parameters.get("sheet_name")
+        length = tool_parameters.get("length")
+        values = tool_parameters.get("values")
+
+        res = client.add_rows(spreadsheet_token, sheet_id, sheet_name, length, values)
+
+        return self.create_json_message(res)

+ 72 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/add_rows.yaml

@@ -0,0 +1,72 @@
+identity:
+  name: add_rows
+  author: Doug Lea
+  label:
+    en_US: Add Rows
+    zh_Hans: 新增多行至工作表最后
+description:
+  human:
+    en_US: Add Rows
+    zh_Hans: 新增多行至工作表最后
+  llm: A tool for adding multiple rows to the end of a spreadsheet. (新增多行至工作表最后)
+parameters:
+  - name: spreadsheet_token
+    type: string
+    required: true
+    label:
+      en_US: spreadsheet_token
+      zh_Hans: 电子表格 token
+    human_description:
+      en_US: Spreadsheet token, supports input of spreadsheet URL.
+      zh_Hans: 电子表格 token,支持输入电子表格 url。
+    llm_description: 电子表格 token,支持输入电子表格 url。
+    form: llm
+
+  - name: sheet_id
+    type: string
+    required: false
+    label:
+      en_US: sheet_id
+      zh_Hans: 工作表 ID
+    human_description:
+      en_US: Sheet ID, either sheet_id or sheet_name must be filled.
+      zh_Hans: 工作表 ID,与 sheet_name 二者其一必填。
+    llm_description: 工作表 ID,与 sheet_name 二者其一必填。
+    form: llm
+
+  - name: sheet_name
+    type: string
+    required: false
+    label:
+      en_US: sheet_name
+      zh_Hans: 工作表名称
+    human_description:
+      en_US: Sheet name, either sheet_id or sheet_name must be filled.
+      zh_Hans: 工作表名称,与 sheet_id 二者其一必填。
+    llm_description: 工作表名称,与 sheet_id 二者其一必填。
+    form: llm
+
+  - name: length
+    type: number
+    required: true
+    label:
+      en_US: length
+      zh_Hans: 要增加行数
+    human_description:
+      en_US: Number of rows to add, range (0-5000].
+      zh_Hans: 要增加行数,范围(0-5000]。
+    llm_description: 要增加行数,范围(0-5000]。
+    form: llm
+
+  - name: values
+    type: string
+    required: false
+    label:
+      en_US: values
+      zh_Hans: 新增行的表格内容
+    human_description:
+      en_US: |
+        Content of the new rows, array of objects in string format, each array represents a row of table data, format like: [ [ "ID","Name","Age" ],[ 1,"Zhang San",10 ],[ 2,"Li Si",11 ] ].
+      zh_Hans: 新增行的表格内容,数组对象字符串,每个数组一行表格数据,格式,如:[["编号","姓名","年龄"],[1,"张三",10],[2,"李四",11]]。
+    llm_description: 新增行的表格内容,数组对象字符串,每个数组一行表格数据,格式,如:[["编号","姓名","年龄"],[1,"张三",10],[2,"李四",11]]。
+    form: llm

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

@@ -0,0 +1,19 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class CreateSpreadsheetTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        title = tool_parameters.get("title")
+        folder_token = tool_parameters.get("folder_token")
+
+        res = client.create_spreadsheet(title, folder_token)
+
+        return self.create_json_message(res)

+ 35 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/create_spreadsheet.yaml

@@ -0,0 +1,35 @@
+identity:
+  name: create_spreadsheet
+  author: Doug Lea
+  label:
+    en_US: Create Spreadsheet
+    zh_Hans: 创建电子表格
+description:
+  human:
+    en_US: Create Spreadsheet
+    zh_Hans: 创建电子表格
+  llm: A tool for creating spreadsheets. (创建电子表格)
+parameters:
+  - name: title
+    type: string
+    required: false
+    label:
+      en_US: Spreadsheet Title
+      zh_Hans: 电子表格标题
+    human_description:
+      en_US: The title of the spreadsheet
+      zh_Hans: 电子表格的标题
+    llm_description: 电子表格的标题
+    form: llm
+
+  - name: folder_token
+    type: string
+    required: false
+    label:
+      en_US: Folder Token
+      zh_Hans: 文件夹 token
+    human_description:
+      en_US: The token of the folder, supports folder URL input, e.g., https://bytedance.larkoffice.com/drive/folder/CxHEf4DCSlNkL2dUTCJcPRgentg
+      zh_Hans: 文件夹 token,支持文件夹 URL 输入,如:https://bytedance.larkoffice.com/drive/folder/CxHEf4DCSlNkL2dUTCJcPRgentg
+    llm_description: 文件夹 token,支持文件夹 URL 输入,如:https://bytedance.larkoffice.com/drive/folder/CxHEf4DCSlNkL2dUTCJcPRgentg
+    form: llm

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

@@ -0,0 +1,19 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class GetSpreadsheetTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        spreadsheet_token = tool_parameters.get("spreadsheet_token")
+        user_id_type = tool_parameters.get("user_id_type", "open_id")
+
+        res = client.get_spreadsheet(spreadsheet_token, user_id_type)
+
+        return self.create_json_message(res)

+ 49 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/get_spreadsheet.yaml

@@ -0,0 +1,49 @@
+identity:
+  name: get_spreadsheet
+  author: Doug Lea
+  label:
+    en_US: Get Spreadsheet
+    zh_Hans: 获取电子表格信息
+description:
+  human:
+    en_US: Get Spreadsheet
+    zh_Hans: 获取电子表格信息
+  llm: A tool for getting information from spreadsheets. (获取电子表格信息)
+parameters:
+  - name: spreadsheet_token
+    type: string
+    required: true
+    label:
+      en_US: Spreadsheet Token
+      zh_Hans: 电子表格 token
+    human_description:
+      en_US: Spreadsheet token, supports input of spreadsheet URL.
+      zh_Hans: 电子表格 token,支持输入电子表格 URL。
+    llm_description: 电子表格 token,支持输入电子表格 URL。
+    form: llm
+
+  - name: user_id_type
+    type: select
+    required: false
+    options:
+      - value: open_id
+        label:
+          en_US: open_id
+          zh_Hans: open_id
+      - value: union_id
+        label:
+          en_US: union_id
+          zh_Hans: union_id
+      - value: user_id
+        label:
+          en_US: user_id
+          zh_Hans: user_id
+    default: "open_id"
+    label:
+      en_US: user_id_type
+      zh_Hans: 用户 ID 类型
+    human_description:
+      en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id.
+      zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
+    llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
+    form: form

+ 18 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/list_spreadsheet_sheets.py

@@ -0,0 +1,18 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class ListSpreadsheetSheetsTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        spreadsheet_token = tool_parameters.get("spreadsheet_token")
+
+        res = client.list_spreadsheet_sheets(spreadsheet_token)
+
+        return self.create_json_message(res)

+ 23 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/list_spreadsheet_sheets.yaml

@@ -0,0 +1,23 @@
+identity:
+  name: list_spreadsheet_sheets
+  author: Doug Lea
+  label:
+    en_US: List Spreadsheet Sheets
+    zh_Hans: 列出电子表格所有工作表
+description:
+  human:
+    en_US: List Spreadsheet Sheets
+    zh_Hans: 列出电子表格所有工作表
+  llm: A tool for listing all sheets in a spreadsheet. (列出电子表格所有工作表)
+parameters:
+  - name: spreadsheet_token
+    type: string
+    required: true
+    label:
+      en_US: Spreadsheet Token
+      zh_Hans: 电子表格 token
+    human_description:
+      en_US: Spreadsheet token, supports input of spreadsheet URL.
+      zh_Hans: 电子表格 token,支持输入电子表格 URL。
+    llm_description: 电子表格 token,支持输入电子表格 URL。
+    form: llm

+ 23 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_cols.py

@@ -0,0 +1,23 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class ReadColsTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        spreadsheet_token = tool_parameters.get("spreadsheet_token")
+        sheet_id = tool_parameters.get("sheet_id")
+        sheet_name = tool_parameters.get("sheet_name")
+        start_col = tool_parameters.get("start_col")
+        num_cols = tool_parameters.get("num_cols")
+        user_id_type = tool_parameters.get("user_id_type", "open_id")
+
+        res = client.read_cols(spreadsheet_token, sheet_id, sheet_name, start_col, num_cols, user_id_type)
+
+        return self.create_json_message(res)

+ 97 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_cols.yaml

@@ -0,0 +1,97 @@
+identity:
+  name: read_cols
+  author: Doug Lea
+  label:
+    en_US: Read Cols
+    zh_Hans: 读取工作表列数据
+description:
+  human:
+    en_US: Read Cols
+    zh_Hans: 读取工作表列数据
+  llm: A tool for reading column data from a spreadsheet. (读取工作表列数据)
+parameters:
+  - name: spreadsheet_token
+    type: string
+    required: true
+    label:
+      en_US: spreadsheet_token
+      zh_Hans: 电子表格 token
+    human_description:
+      en_US: Spreadsheet token, supports input of spreadsheet URL.
+      zh_Hans: 电子表格 token,支持输入电子表格 url。
+    llm_description: 电子表格 token,支持输入电子表格 url。
+    form: llm
+
+  - name: sheet_id
+    type: string
+    required: false
+    label:
+      en_US: sheet_id
+      zh_Hans: 工作表 ID
+    human_description:
+      en_US: Sheet ID, either sheet_id or sheet_name must be filled.
+      zh_Hans: 工作表 ID,与 sheet_name 二者其一必填。
+    llm_description: 工作表 ID,与 sheet_name 二者其一必填。
+    form: llm
+
+  - name: sheet_name
+    type: string
+    required: false
+    label:
+      en_US: sheet_name
+      zh_Hans: 工作表名称
+    human_description:
+      en_US: Sheet name, either sheet_id or sheet_name must be filled.
+      zh_Hans: 工作表名称,与 sheet_id 二者其一必填。
+    llm_description: 工作表名称,与 sheet_id 二者其一必填。
+    form: llm
+
+  - name: user_id_type
+    type: select
+    required: false
+    options:
+      - value: open_id
+        label:
+          en_US: open_id
+          zh_Hans: open_id
+      - value: union_id
+        label:
+          en_US: union_id
+          zh_Hans: union_id
+      - value: user_id
+        label:
+          en_US: user_id
+          zh_Hans: user_id
+    default: "open_id"
+    label:
+      en_US: user_id_type
+      zh_Hans: 用户 ID 类型
+    human_description:
+      en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id.
+      zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
+    llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
+    form: form
+
+  - name: start_col
+    type: number
+    required: false
+    label:
+      en_US: start_col
+      zh_Hans: 起始列号
+    human_description:
+      en_US: Starting column number, starting from 1.
+      zh_Hans: 起始列号,从 1 开始。
+    llm_description: 起始列号,从 1 开始。
+    form: llm
+
+  - name: num_cols
+    type: number
+    required: true
+    label:
+      en_US: num_cols
+      zh_Hans: 读取列数
+    human_description:
+      en_US: Number of columns to read.
+      zh_Hans: 读取列数
+    llm_description: 读取列数
+    form: llm

+ 23 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_rows.py

@@ -0,0 +1,23 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class ReadRowsTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        spreadsheet_token = tool_parameters.get("spreadsheet_token")
+        sheet_id = tool_parameters.get("sheet_id")
+        sheet_name = tool_parameters.get("sheet_name")
+        start_row = tool_parameters.get("start_row")
+        num_rows = tool_parameters.get("num_rows")
+        user_id_type = tool_parameters.get("user_id_type", "open_id")
+
+        res = client.read_rows(spreadsheet_token, sheet_id, sheet_name, start_row, num_rows, user_id_type)
+
+        return self.create_json_message(res)

+ 97 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_rows.yaml

@@ -0,0 +1,97 @@
+identity:
+  name: read_rows
+  author: Doug Lea
+  label:
+    en_US: Read Rows
+    zh_Hans: 读取工作表行数据
+description:
+  human:
+    en_US: Read Rows
+    zh_Hans: 读取工作表行数据
+  llm: A tool for reading row data from a spreadsheet. (读取工作表行数据)
+parameters:
+  - name: spreadsheet_token
+    type: string
+    required: true
+    label:
+      en_US: spreadsheet_token
+      zh_Hans: 电子表格 token
+    human_description:
+      en_US: Spreadsheet token, supports input of spreadsheet URL.
+      zh_Hans: 电子表格 token,支持输入电子表格 url。
+    llm_description: 电子表格 token,支持输入电子表格 url。
+    form: llm
+
+  - name: sheet_id
+    type: string
+    required: false
+    label:
+      en_US: sheet_id
+      zh_Hans: 工作表 ID
+    human_description:
+      en_US: Sheet ID, either sheet_id or sheet_name must be filled.
+      zh_Hans: 工作表 ID,与 sheet_name 二者其一必填。
+    llm_description: 工作表 ID,与 sheet_name 二者其一必填。
+    form: llm
+
+  - name: sheet_name
+    type: string
+    required: false
+    label:
+      en_US: sheet_name
+      zh_Hans: 工作表名称
+    human_description:
+      en_US: Sheet name, either sheet_id or sheet_name must be filled.
+      zh_Hans: 工作表名称,与 sheet_id 二者其一必填。
+    llm_description: 工作表名称,与 sheet_id 二者其一必填。
+    form: llm
+
+  - name: user_id_type
+    type: select
+    required: false
+    options:
+      - value: open_id
+        label:
+          en_US: open_id
+          zh_Hans: open_id
+      - value: union_id
+        label:
+          en_US: union_id
+          zh_Hans: union_id
+      - value: user_id
+        label:
+          en_US: user_id
+          zh_Hans: user_id
+    default: "open_id"
+    label:
+      en_US: user_id_type
+      zh_Hans: 用户 ID 类型
+    human_description:
+      en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id.
+      zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
+    llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
+    form: form
+
+  - name: start_row
+    type: number
+    required: false
+    label:
+      en_US: start_row
+      zh_Hans: 起始行号
+    human_description:
+      en_US: Starting row number, starting from 1.
+      zh_Hans: 起始行号,从 1 开始。
+    llm_description: 起始行号,从 1 开始。
+    form: llm
+
+  - name: num_rows
+    type: number
+    required: true
+    label:
+      en_US: num_rows
+      zh_Hans: 读取行数
+    human_description:
+      en_US: Number of rows to read.
+      zh_Hans: 读取行数
+    llm_description: 读取行数
+    form: llm

+ 23 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_table.py

@@ -0,0 +1,23 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class ReadTableTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        spreadsheet_token = tool_parameters.get("spreadsheet_token")
+        sheet_id = tool_parameters.get("sheet_id")
+        sheet_name = tool_parameters.get("sheet_name")
+        num_range = tool_parameters.get("num_range")
+        query = tool_parameters.get("query")
+        user_id_type = tool_parameters.get("user_id_type", "open_id")
+
+        res = client.read_table(spreadsheet_token, sheet_id, sheet_name, num_range, query, user_id_type)
+
+        return self.create_json_message(res)

+ 122 - 0
api/core/tools/provider/builtin/feishu_spreadsheet/tools/read_table.yaml

@@ -0,0 +1,122 @@
+identity:
+  name: read_table
+  author: Doug Lea
+  label:
+    en_US: Read Table
+    zh_Hans: 自定义读取电子表格行列数据
+description:
+  human:
+    en_US: Read Table
+    zh_Hans: 自定义读取电子表格行列数据
+  llm: A tool for custom reading of row and column data from a spreadsheet. (自定义读取电子表格行列数据)
+parameters:
+  - name: spreadsheet_token
+    type: string
+    required: true
+    label:
+      en_US: spreadsheet_token
+      zh_Hans: 电子表格 token
+    human_description:
+      en_US: Spreadsheet token, supports input of spreadsheet URL.
+      zh_Hans: 电子表格 token,支持输入电子表格 url。
+    llm_description: 电子表格 token,支持输入电子表格 url。
+    form: llm
+
+  - name: sheet_id
+    type: string
+    required: false
+    label:
+      en_US: sheet_id
+      zh_Hans: 工作表 ID
+    human_description:
+      en_US: Sheet ID, either sheet_id or sheet_name must be filled.
+      zh_Hans: 工作表 ID,与 sheet_name 二者其一必填。
+    llm_description: 工作表 ID,与 sheet_name 二者其一必填。
+    form: llm
+
+  - name: sheet_name
+    type: string
+    required: false
+    label:
+      en_US: sheet_name
+      zh_Hans: 工作表名称
+    human_description:
+      en_US: Sheet name, either sheet_id or sheet_name must be filled.
+      zh_Hans: 工作表名称,与 sheet_id 二者其一必填。
+    llm_description: 工作表名称,与 sheet_id 二者其一必填。
+    form: llm
+
+  - name: user_id_type
+    type: select
+    required: false
+    options:
+      - value: open_id
+        label:
+          en_US: open_id
+          zh_Hans: open_id
+      - value: union_id
+        label:
+          en_US: union_id
+          zh_Hans: union_id
+      - value: user_id
+        label:
+          en_US: user_id
+          zh_Hans: user_id
+    default: "open_id"
+    label:
+      en_US: user_id_type
+      zh_Hans: 用户 ID 类型
+    human_description:
+      en_US: User ID type, optional values are open_id, union_id, user_id, with a default value of open_id.
+      zh_Hans: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
+    llm_description: 用户 ID 类型,可选值有 open_id、union_id、user_id,默认值为 open_id。
+    form: form
+
+  - name: start_row
+    type: number
+    required: false
+    label:
+      en_US: start_row
+      zh_Hans: 起始行号
+    human_description:
+      en_US: Starting row number, starting from 1.
+      zh_Hans: 起始行号,从 1 开始。
+    llm_description: 起始行号,从 1 开始。
+    form: llm
+
+  - name: num_rows
+    type: number
+    required: false
+    label:
+      en_US: num_rows
+      zh_Hans: 读取行数
+    human_description:
+      en_US: Number of rows to read.
+      zh_Hans: 读取行数
+    llm_description: 读取行数
+    form: llm
+
+  - name: range
+    type: string
+    required: false
+    label:
+      en_US: range
+      zh_Hans: 取数范围
+    human_description:
+      en_US: |
+        Data range, format like: A1:B2, can be empty when query=all.
+      zh_Hans: 取数范围,格式如:A1:B2,query=all 时可为空。
+    llm_description: 取数范围,格式如:A1:B2,query=all 时可为空。
+    form: llm
+
+  - name: query
+    type: string
+    required: false
+    label:
+      en_US: query
+      zh_Hans: 查询
+    human_description:
+      en_US: Pass "all" to query all data in the table, but no more than 100 columns.
+      zh_Hans: 传 all,表示查询表格所有数据,但最多查询 100 列数据。
+    llm_description: 传 all,表示查询表格所有数据,但最多查询 100 列数据。
+    form: llm

BIN
api/core/tools/provider/builtin/feishu_task/_assets/icon.png


+ 7 - 0
api/core/tools/provider/builtin/feishu_task/feishu_task.py

@@ -0,0 +1,7 @@
+from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
+from core.tools.utils.feishu_api_utils import auth
+
+
+class FeishuTaskProvider(BuiltinToolProviderController):
+    def _validate_credentials(self, credentials: dict) -> None:
+        auth(credentials)

+ 36 - 0
api/core/tools/provider/builtin/feishu_task/feishu_task.yaml

@@ -0,0 +1,36 @@
+identity:
+  author: Doug Lea
+  name: feishu_task
+  label:
+    en_US: Feishu Task
+    zh_Hans: 飞书任务
+  description:
+    en_US: |
+      Feishu Task, requires the following permissions: task:task:write、contact:user.id:readonly.
+    zh_Hans: |
+      飞书任务,需要开通以下权限: task:task:write、contact:user.id:readonly。
+  icon: icon.png
+  tags:
+    - social
+    - productivity
+credentials_for_provider:
+  app_id:
+    type: text-input
+    required: true
+    label:
+      en_US: APP ID
+    placeholder:
+      en_US: Please input your feishu app id
+      zh_Hans: 请输入你的飞书 app id
+    help:
+      en_US: Get your app_id and app_secret from Feishu
+      zh_Hans: 从飞书获取您的 app_id 和 app_secret
+    url: https://open.larkoffice.com/app
+  app_secret:
+    type: secret-input
+    required: true
+    label:
+      en_US: APP Secret
+    placeholder:
+      en_US: Please input your app secret
+      zh_Hans: 请输入你的飞书 app secret

+ 20 - 0
api/core/tools/provider/builtin/feishu_task/tools/add_members.py

@@ -0,0 +1,20 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class AddMembersTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        task_guid = tool_parameters.get("task_guid")
+        member_phone_or_email = tool_parameters.get("member_phone_or_email")
+        member_role = tool_parameters.get("member_role", "follower")
+
+        res = client.add_members(task_guid, member_phone_or_email, member_role)
+
+        return self.create_json_message(res)

+ 58 - 0
api/core/tools/provider/builtin/feishu_task/tools/add_members.yaml

@@ -0,0 +1,58 @@
+identity:
+  name: add_members
+  author: Doug Lea
+  label:
+    en_US: Add Members
+    zh_Hans: 添加任务成员
+description:
+  human:
+    en_US: Add Members
+    zh_Hans: 添加任务成员
+  llm: A tool for adding members to a Feishu task.(添加任务成员)
+parameters:
+  - name: task_guid
+    type: string
+    required: true
+    label:
+      en_US: Task GUID
+      zh_Hans: 任务 GUID
+    human_description:
+      en_US: |
+        The GUID of the task to be added, supports passing either the Task ID or the Task link URL. Example of Task ID: 8b5425ec-9f2a-43bd-a3ab-01912f50282b; Example of Task link URL: https://applink.feishu-pre.net/client/todo/detail?guid=8c6bf822-e4da-449a-b82a-dc44020f9be9&suite_entity_num=t21587362
+      zh_Hans: 要添加的任务的 GUID,支持传任务 ID 和任务链接 URL。任务 ID 示例:8b5425ec-9f2a-43bd-a3ab-01912f50282b;任务链接 URL 示例:https://applink.feishu-pre.net/client/todo/detail?guid=8c6bf822-e4da-449a-b82a-dc44020f9be9&suite_entity_num=t21587362
+    llm_description: 要添加的任务的 GUID,支持传任务 ID 和任务链接 URL。任务 ID 示例:8b5425ec-9f2a-43bd-a3ab-01912f50282b;任务链接 URL 示例:https://applink.feishu-pre.net/client/todo/detail?guid=8c6bf822-e4da-449a-b82a-dc44020f9be9&suite_entity_num=t21587362
+    form: llm
+
+  - name: member_phone_or_email
+    type: string
+    required: true
+    label:
+      en_US: Task Member Phone Or Email
+      zh_Hans: 任务成员的电话或邮箱
+    human_description:
+      en_US: A list of member emails or phone numbers, separated by commas.
+      zh_Hans: 任务成员邮箱或者手机号列表,使用逗号分隔。
+    llm_description: 任务成员邮箱或者手机号列表,使用逗号分隔。
+    form: llm
+
+  - name: member_role
+    type: select
+    required: true
+    options:
+      - value: assignee
+        label:
+          en_US: assignee
+          zh_Hans: 负责人
+      - value: follower
+        label:
+          en_US: follower
+          zh_Hans: 关注人
+    default: "follower"
+    label:
+      en_US: member_role
+      zh_Hans: 成员的角色
+    human_description:
+      en_US: Member role, optional values are "assignee" (responsible person) and "follower" (observer), with a default value of "assignee".
+      zh_Hans: 成员的角色,可选值有 "assignee"(负责人)和 "follower"(关注人),默认值为 "assignee"。
+    llm_description: 成员的角色,可选值有 "assignee"(负责人)和 "follower"(关注人),默认值为 "assignee"。
+    form: form

+ 22 - 0
api/core/tools/provider/builtin/feishu_task/tools/create_task.py

@@ -0,0 +1,22 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class CreateTaskTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        summary = tool_parameters.get("summary")
+        start_time = tool_parameters.get("start_time")
+        end_time = tool_parameters.get("end_time")
+        completed_time = tool_parameters.get("completed_time")
+        description = tool_parameters.get("description")
+
+        res = client.create_task(summary, start_time, end_time, completed_time, description)
+
+        return self.create_json_message(res)

+ 74 - 0
api/core/tools/provider/builtin/feishu_task/tools/create_task.yaml

@@ -0,0 +1,74 @@
+identity:
+  name: create_task
+  author: Doug Lea
+  label:
+    en_US: Create Task
+    zh_Hans: 创建飞书任务
+description:
+  human:
+    en_US: Create Feishu Task
+    zh_Hans: 创建飞书任务
+  llm: A tool for creating tasks in Feishu.(创建飞书任务)
+parameters:
+  - name: summary
+    type: string
+    required: true
+    label:
+      en_US: Task Title
+      zh_Hans: 任务标题
+    human_description:
+      en_US: The title of the task.
+      zh_Hans: 任务标题
+    llm_description: 任务标题
+    form: llm
+
+  - name: description
+    type: string
+    required: false
+    label:
+      en_US: Task Description
+      zh_Hans: 任务备注
+    human_description:
+      en_US: The description or notes for the task.
+      zh_Hans: 任务备注
+    llm_description: 任务备注
+    form: llm
+
+  - name: start_time
+    type: string
+    required: false
+    label:
+      en_US: Start Time
+      zh_Hans: 任务开始时间
+    human_description:
+      en_US: |
+        The start time of the task, in the format: 2006-01-02 15:04:05
+      zh_Hans: 任务开始时间,格式为:2006-01-02 15:04:05
+    llm_description: 任务开始时间,格式为:2006-01-02 15:04:05
+    form: llm
+
+  - name: end_time
+    type: string
+    required: false
+    label:
+      en_US: End Time
+      zh_Hans: 任务结束时间
+    human_description:
+      en_US: |
+        The end time of the task, in the format: 2006-01-02 15:04:05
+      zh_Hans: 任务结束时间,格式为:2006-01-02 15:04:05
+    llm_description: 任务结束时间,格式为:2006-01-02 15:04:05
+    form: llm
+
+  - name: completed_time
+    type: string
+    required: false
+    label:
+      en_US: Completed Time
+      zh_Hans: 任务完成时间
+    human_description:
+      en_US: |
+        The completion time of the task, in the format: 2006-01-02 15:04:05. Leave empty to create an incomplete task; fill in a specific time to create a completed task.
+      zh_Hans: 任务完成时间,格式为:2006-01-02 15:04:05,不填写表示创建一个未完成任务;填写一个具体的时间表示创建一个已完成任务。
+    llm_description: 任务完成时间,格式为:2006-01-02 15:04:05,不填写表示创建一个未完成任务;填写一个具体的时间表示创建一个已完成任务。
+    form: llm

+ 18 - 0
api/core/tools/provider/builtin/feishu_task/tools/delete_task.py

@@ -0,0 +1,18 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class UpdateTaskTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        task_guid = tool_parameters.get("task_guid")
+
+        res = client.delete_task(task_guid)
+
+        return self.create_json_message(res)

+ 24 - 0
api/core/tools/provider/builtin/feishu_task/tools/delete_task.yaml

@@ -0,0 +1,24 @@
+identity:
+  name: delete_task
+  author: Doug Lea
+  label:
+    en_US: Delete Task
+    zh_Hans: 删除飞书任务
+description:
+  human:
+    en_US: Delete Task
+    zh_Hans: 删除飞书任务
+  llm: A tool for deleting tasks in Feishu.(删除飞书任务)
+parameters:
+  - name: task_guid
+    type: string
+    required: true
+    label:
+      en_US: Task GUID
+      zh_Hans: 任务 GUID
+    human_description:
+      en_US: |
+        The GUID of the task to be deleted, supports passing either the Task ID or the Task link URL. Example of Task ID: 8b5425ec-9f2a-43bd-a3ab-01912f50282b; Example of Task link URL: https://applink.feishu-pre.net/client/todo/detail?guid=8c6bf822-e4da-449a-b82a-dc44020f9be9&suite_entity_num=t21587362
+      zh_Hans: 要删除的任务的 GUID,支持传任务 ID 和任务链接 URL。任务 ID 示例:8b5425ec-9f2a-43bd-a3ab-01912f50282b;任务链接 URL 示例:https://applink.feishu-pre.net/client/todo/detail?guid=8c6bf822-e4da-449a-b82a-dc44020f9be9&suite_entity_num=t21587362
+    llm_description: 要删除的任务的 GUID,支持传任务 ID 和任务链接 URL。任务 ID 示例:8b5425ec-9f2a-43bd-a3ab-01912f50282b;任务链接 URL 示例:https://applink.feishu-pre.net/client/todo/detail?guid=8c6bf822-e4da-449a-b82a-dc44020f9be9&suite_entity_num=t21587362
+    form: llm

+ 23 - 0
api/core/tools/provider/builtin/feishu_task/tools/update_task.py

@@ -0,0 +1,23 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class UpdateTaskTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        task_guid = tool_parameters.get("task_guid")
+        summary = tool_parameters.get("summary")
+        start_time = tool_parameters.get("start_time")
+        end_time = tool_parameters.get("end_time")
+        completed_time = tool_parameters.get("completed_time")
+        description = tool_parameters.get("description")
+
+        res = client.update_task(task_guid, summary, start_time, end_time, completed_time, description)
+
+        return self.create_json_message(res)

+ 89 - 0
api/core/tools/provider/builtin/feishu_task/tools/update_task.yaml

@@ -0,0 +1,89 @@
+identity:
+  name: update_task
+  author: Doug Lea
+  label:
+    en_US: Update Task
+    zh_Hans: 更新飞书任务
+description:
+  human:
+    en_US: Update Feishu Task
+    zh_Hans: 更新飞书任务
+  llm: A tool for updating tasks in Feishu.(更新飞书任务)
+parameters:
+  - name: task_guid
+    type: string
+    required: true
+    label:
+      en_US: Task GUID
+      zh_Hans: 任务 GUID
+    human_description:
+      en_US: |
+        The task ID, supports inputting either the Task ID or the Task link URL. Example of Task ID: 42cad8a0-f8c8-4344-9be2-d1d7e8e91b64; Example of Task link URL: https://applink.feishu-pre.net/client/todo/detail?guid=42cad8a0-f8c8-4344-9be2-d1d7e8e91b64&suite_entity_num=t21700217
+      zh_Hans: |
+        任务ID,支持传入任务 ID 和任务链接 URL。任务 ID 示例: 42cad8a0-f8c8-4344-9be2-d1d7e8e91b64;任务链接 URL 示例: https://applink.feishu-pre.net/client/todo/detail?guid=42cad8a0-f8c8-4344-9be2-d1d7e8e91b64&suite_entity_num=t21700217
+    llm_description: |
+      任务ID,支持传入任务 ID 和任务链接 URL。任务 ID 示例: 42cad8a0-f8c8-4344-9be2-d1d7e8e91b64;任务链接 URL 示例: https://applink.feishu-pre.net/client/todo/detail?guid=42cad8a0-f8c8-4344-9be2-d1d7e8e91b64&suite_entity_num=t21700217
+    form: llm
+
+  - name: summary
+    type: string
+    required: true
+    label:
+      en_US: Task Title
+      zh_Hans: 任务标题
+    human_description:
+      en_US: The title of the task.
+      zh_Hans: 任务标题
+    llm_description: 任务标题
+    form: llm
+
+  - name: description
+    type: string
+    required: false
+    label:
+      en_US: Task Description
+      zh_Hans: 任务备注
+    human_description:
+      en_US: The description or notes for the task.
+      zh_Hans: 任务备注
+    llm_description: 任务备注
+    form: llm
+
+  - name: start_time
+    type: string
+    required: false
+    label:
+      en_US: Start Time
+      zh_Hans: 任务开始时间
+    human_description:
+      en_US: |
+        The start time of the task, in the format: 2006-01-02 15:04:05
+      zh_Hans: 任务开始时间,格式为:2006-01-02 15:04:05
+    llm_description: 任务开始时间,格式为:2006-01-02 15:04:05
+    form: llm
+
+  - name: end_time
+    type: string
+    required: false
+    label:
+      en_US: End Time
+      zh_Hans: 任务结束时间
+    human_description:
+      en_US: |
+        The end time of the task, in the format: 2006-01-02 15:04:05
+      zh_Hans: 任务结束时间,格式为:2006-01-02 15:04:05
+    llm_description: 任务结束时间,格式为:2006-01-02 15:04:05
+    form: llm
+
+  - name: completed_time
+    type: string
+    required: false
+    label:
+      en_US: Completed Time
+      zh_Hans: 任务完成时间
+    human_description:
+      en_US: |
+        The completion time of the task, in the format: 2006-01-02 15:04:05
+      zh_Hans: 任务完成时间,格式为:2006-01-02 15:04:05
+    llm_description: 任务完成时间,格式为:2006-01-02 15:04:05
+    form: llm

BIN
api/core/tools/provider/builtin/feishu_wiki/_assets/icon.png


+ 7 - 0
api/core/tools/provider/builtin/feishu_wiki/feishu_wiki.py

@@ -0,0 +1,7 @@
+from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
+from core.tools.utils.feishu_api_utils import auth
+
+
+class FeishuWikiProvider(BuiltinToolProviderController):
+    def _validate_credentials(self, credentials: dict) -> None:
+        auth(credentials)

+ 36 - 0
api/core/tools/provider/builtin/feishu_wiki/feishu_wiki.yaml

@@ -0,0 +1,36 @@
+identity:
+  author: Doug Lea
+  name: feishu_wiki
+  label:
+    en_US: Feishu Wiki
+    zh_Hans: 飞书知识库
+  description:
+    en_US: |
+      Feishu Wiki, requires the following permissions: wiki:wiki:readonly.
+    zh_Hans: |
+      飞书知识库,需要开通以下权限: wiki:wiki:readonly。
+  icon: icon.png
+  tags:
+    - social
+    - productivity
+credentials_for_provider:
+  app_id:
+    type: text-input
+    required: true
+    label:
+      en_US: APP ID
+    placeholder:
+      en_US: Please input your feishu app id
+      zh_Hans: 请输入你的飞书 app id
+    help:
+      en_US: Get your app_id and app_secret from Feishu
+      zh_Hans: 从飞书获取您的 app_id 和 app_secret
+    url: https://open.larkoffice.com/app
+  app_secret:
+    type: secret-input
+    required: true
+    label:
+      en_US: APP Secret
+    placeholder:
+      en_US: Please input your app secret
+      zh_Hans: 请输入你的飞书 app secret

+ 21 - 0
api/core/tools/provider/builtin/feishu_wiki/tools/get_wiki_nodes.py

@@ -0,0 +1,21 @@
+from typing import Any
+
+from core.tools.entities.tool_entities import ToolInvokeMessage
+from core.tools.tool.builtin_tool import BuiltinTool
+from core.tools.utils.feishu_api_utils import FeishuRequest
+
+
+class GetWikiNodesTool(BuiltinTool):
+    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
+        app_id = self.runtime.credentials.get("app_id")
+        app_secret = self.runtime.credentials.get("app_secret")
+        client = FeishuRequest(app_id, app_secret)
+
+        space_id = tool_parameters.get("space_id")
+        parent_node_token = tool_parameters.get("parent_node_token")
+        page_token = tool_parameters.get("page_token")
+        page_size = tool_parameters.get("page_size")
+
+        res = client.get_wiki_nodes(space_id, parent_node_token, page_token, page_size)
+
+        return self.create_json_message(res)

+ 63 - 0
api/core/tools/provider/builtin/feishu_wiki/tools/get_wiki_nodes.yaml

@@ -0,0 +1,63 @@
+identity:
+  name: get_wiki_nodes
+  author: Doug Lea
+  label:
+    en_US: Get Wiki Nodes
+    zh_Hans: 获取知识空间子节点列表
+description:
+  human:
+    en_US: |
+      Get the list of child nodes in Wiki, make sure the app/bot is a member of the wiki space. See How to add an app as a wiki base administrator (member). https://open.feishu.cn/document/server-docs/docs/wiki-v2/wiki-qa
+    zh_Hans: |
+      获取知识库全部子节点列表,请确保应用/机器人为知识空间成员。参阅如何将应用添加为知识库管理员(成员)。https://open.feishu.cn/document/server-docs/docs/wiki-v2/wiki-qa
+  llm: A tool for getting all sub-nodes of a knowledge base.(获取知识空间子节点列表)
+parameters:
+  - name: space_id
+    type: string
+    required: true
+    label:
+      en_US: Space Id
+      zh_Hans: 知识空间 ID
+    human_description:
+      en_US: |
+        The ID of the knowledge space. Supports space link URL, for example: https://svi136aogf123.feishu.cn/wiki/settings/7166950623940706332
+      zh_Hans: 知识空间 ID,支持空间链接 URL,例如:https://svi136aogf123.feishu.cn/wiki/settings/7166950623940706332
+    llm_description: 知识空间 ID,支持空间链接 URL,例如:https://svi136aogf123.feishu.cn/wiki/settings/7166950623940706332
+    form: llm
+
+  - name: page_size
+    type: number
+    required: false
+    default: 10
+    label:
+      en_US: Page Size
+      zh_Hans: 分页大小
+    human_description:
+      en_US: The size of each page, with a maximum value of 50.
+      zh_Hans: 分页大小,最大值 50。
+    llm_description: 分页大小,最大值 50。
+    form: llm
+
+  - name: page_token
+    type: string
+    required: false
+    label:
+      en_US: Page Token
+      zh_Hans: 分页标记
+    human_description:
+      en_US: The pagination token. Leave empty for the first request to start from the beginning; if the paginated query result has more items, a new page_token will be returned, which can be used to get the next set of results.
+      zh_Hans: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。
+    llm_description: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token,下次遍历可采用该 page_token 获取查询结果。
+    form: llm
+
+  - name: parent_node_token
+    type: string
+    required: false
+    label:
+      en_US: Parent Node Token
+      zh_Hans: 父节点 token
+    human_description:
+      en_US: The token of the parent node.
+      zh_Hans: 父节点 token
+    llm_description: 父节点 token
+    form: llm

+ 387 - 14
api/core/tools/utils/feishu_api_utils.py

@@ -1,9 +1,23 @@
 import httpx
 
+from core.tools.errors import ToolProviderCredentialValidationError
 from extensions.ext_redis import redis_client
 
 
+def auth(credentials):
+    app_id = credentials.get("app_id")
+    app_secret = credentials.get("app_secret")
+    if not app_id or not app_secret:
+        raise ToolProviderCredentialValidationError("app_id and app_secret is required")
+    try:
+        assert FeishuRequest(app_id, app_secret).tenant_access_token is not None
+    except Exception as e:
+        raise ToolProviderCredentialValidationError(str(e))
+
+
 class FeishuRequest:
+    API_BASE_URL = "https://lark-plugin-api.solutionsuite.cn/lark-plugin"
+
     def __init__(self, app_id: str, app_secret: str):
         self.app_id = app_id
         self.app_secret = app_secret
@@ -42,7 +56,7 @@ class FeishuRequest:
             "expire": 7200
         }
         """
-        url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/access_token/get_tenant_access_token"
+        url = f"{self.API_BASE_URL}/access_token/get_tenant_access_token"
         payload = {"app_id": app_id, "app_secret": app_secret}
         res = self._send_request(url, require_token=False, payload=payload)
         return res
@@ -63,7 +77,7 @@ class FeishuRequest:
             "msg": "创建飞书文档成功,请查看"
         }
         """
-        url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/document/create_document"
+        url = f"{self.API_BASE_URL}/document/create_document"
         payload = {
             "title": title,
             "content": content,
@@ -72,13 +86,13 @@ class FeishuRequest:
         res = self._send_request(url, payload=payload)
         return res.get("data")
 
-    def write_document(self, document_id: str, content: str, position: str = "start") -> dict:
-        url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/document/write_document"
+    def write_document(self, document_id: str, content: str, position: str = "end") -> dict:
+        url = f"{self.API_BASE_URL}/document/write_document"
         payload = {"document_id": document_id, "content": content, "position": position}
         res = self._send_request(url, payload=payload)
         return res
 
-    def get_document_content(self, document_id: str, mode: str, lang: int = 0) -> dict:
+    def get_document_content(self, document_id: str, mode: str = "markdown", lang: str = "0") -> dict:
         """
         API url: https://open.larkoffice.com/document/server-docs/docs/docs/docx-v1/document/raw_content
         Example Response:
@@ -95,45 +109,404 @@ class FeishuRequest:
             "mode": mode,
             "lang": lang,
         }
-        url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/document/get_document_content"
-        res = self._send_request(url, method="get", params=params)
+        url = f"{self.API_BASE_URL}/document/get_document_content"
+        res = self._send_request(url, method="GET", params=params)
         return res.get("data").get("content")
 
-    def list_document_blocks(self, document_id: str, page_token: str, page_size: int = 500) -> dict:
+    def list_document_blocks(
+        self, document_id: str, page_token: str, user_id_type: str = "open_id", page_size: int = 500
+    ) -> dict:
         """
         API url: https://open.larkoffice.com/document/server-docs/docs/docs/docx-v1/document/list
         """
-        url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/document/list_document_blocks"
         params = {
+            "user_id_type": user_id_type,
             "document_id": document_id,
             "page_size": page_size,
             "page_token": page_token,
         }
-        res = self._send_request(url, method="get", params=params)
+        url = f"{self.API_BASE_URL}/document/list_document_blocks"
+        res = self._send_request(url, method="GET", params=params)
         return res.get("data")
 
     def send_bot_message(self, receive_id_type: str, receive_id: str, msg_type: str, content: str) -> dict:
         """
         API url: https://open.larkoffice.com/document/server-docs/im-v1/message/create
         """
-        url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/message/send_bot_message"
+        url = f"{self.API_BASE_URL}/message/send_bot_message"
         params = {
             "receive_id_type": receive_id_type,
         }
         payload = {
             "receive_id": receive_id,
             "msg_type": msg_type,
-            "content": content,
+            "content": content.strip('"').replace(r"\"", '"').replace(r"\\", "\\"),
         }
         res = self._send_request(url, params=params, payload=payload)
         return res.get("data")
 
     def send_webhook_message(self, webhook: str, msg_type: str, content: str) -> dict:
-        url = "https://lark-plugin-api.solutionsuite.cn/lark-plugin/message/send_webhook_message"
+        url = f"{self.API_BASE_URL}/message/send_webhook_message"
         payload = {
             "webhook": webhook,
             "msg_type": msg_type,
-            "content": content,
+            "content": content.strip('"').replace(r"\"", '"').replace(r"\\", "\\"),
         }
         res = self._send_request(url, require_token=False, payload=payload)
         return res
+
+    def get_chat_messages(
+        self,
+        container_id: str,
+        start_time: str,
+        end_time: str,
+        page_token: str,
+        sort_type: str = "ByCreateTimeAsc",
+        page_size: int = 20,
+    ) -> dict:
+        """
+        API url: https://open.larkoffice.com/document/server-docs/im-v1/message/list
+        """
+        url = f"{self.API_BASE_URL}/message/get_chat_messages"
+        params = {
+            "container_id": container_id,
+            "start_time": start_time,
+            "end_time": end_time,
+            "sort_type": sort_type,
+            "page_token": page_token,
+            "page_size": page_size,
+        }
+        res = self._send_request(url, method="GET", params=params)
+        return res.get("data")
+
+    def get_thread_messages(
+        self, container_id: str, page_token: str, sort_type: str = "ByCreateTimeAsc", page_size: int = 20
+    ) -> dict:
+        """
+        API url: https://open.larkoffice.com/document/server-docs/im-v1/message/list
+        """
+        url = f"{self.API_BASE_URL}/message/get_thread_messages"
+        params = {
+            "container_id": container_id,
+            "sort_type": sort_type,
+            "page_token": page_token,
+            "page_size": page_size,
+        }
+        res = self._send_request(url, method="GET", params=params)
+        return res.get("data")
+
+    def create_task(self, summary: str, start_time: str, end_time: str, completed_time: str, description: str) -> dict:
+        # 创建任务
+        url = f"{self.API_BASE_URL}/task/create_task"
+        payload = {
+            "summary": summary,
+            "start_time": start_time,
+            "end_time": end_time,
+            "completed_at": completed_time,
+            "description": description,
+        }
+        res = self._send_request(url, payload=payload)
+        return res.get("data")
+
+    def update_task(
+        self, task_guid: str, summary: str, start_time: str, end_time: str, completed_time: str, description: str
+    ) -> dict:
+        # 更新任务
+        url = f"{self.API_BASE_URL}/task/update_task"
+        payload = {
+            "task_guid": task_guid,
+            "summary": summary,
+            "start_time": start_time,
+            "end_time": end_time,
+            "completed_time": completed_time,
+            "description": description,
+        }
+        res = self._send_request(url, method="PATCH", payload=payload)
+        return res.get("data")
+
+    def delete_task(self, task_guid: str) -> dict:
+        # 删除任务
+        url = f"{self.API_BASE_URL}/task/delete_task"
+        payload = {
+            "task_guid": task_guid,
+        }
+        res = self._send_request(url, method="DELETE", payload=payload)
+        return res
+
+    def add_members(self, task_guid: str, member_phone_or_email: str, member_role: str) -> dict:
+        # 删除任务
+        url = f"{self.API_BASE_URL}/task/add_members"
+        payload = {
+            "task_guid": task_guid,
+            "member_phone_or_email": member_phone_or_email,
+            "member_role": member_role,
+        }
+        res = self._send_request(url, payload=payload)
+        return res
+
+    def get_wiki_nodes(self, space_id: str, parent_node_token: str, page_token: str, page_size: int = 20) -> dict:
+        # 获取知识库全部子节点列表
+        url = f"{self.API_BASE_URL}/wiki/get_wiki_nodes"
+        payload = {
+            "space_id": space_id,
+            "parent_node_token": parent_node_token,
+            "page_token": page_token,
+            "page_size": page_size,
+        }
+        res = self._send_request(url, payload=payload)
+        return res.get("data")
+
+    def get_primary_calendar(self, user_id_type: str = "open_id") -> dict:
+        url = f"{self.API_BASE_URL}/calendar/get_primary_calendar"
+        params = {
+            "user_id_type": user_id_type,
+        }
+        res = self._send_request(url, method="GET", params=params)
+        return res.get("data")
+
+    def create_event(
+        self,
+        summary: str,
+        description: str,
+        start_time: str,
+        end_time: str,
+        attendee_ability: str,
+        need_notification: bool = True,
+        auto_record: bool = False,
+    ) -> dict:
+        url = f"{self.API_BASE_URL}/calendar/create_event"
+        payload = {
+            "summary": summary,
+            "description": description,
+            "need_notification": need_notification,
+            "start_time": start_time,
+            "end_time": end_time,
+            "auto_record": auto_record,
+            "attendee_ability": attendee_ability,
+        }
+        res = self._send_request(url, payload=payload)
+        return res.get("data")
+
+    def update_event(
+        self,
+        event_id: str,
+        summary: str,
+        description: str,
+        need_notification: bool,
+        start_time: str,
+        end_time: str,
+        auto_record: bool,
+    ) -> dict:
+        url = f"{self.API_BASE_URL}/calendar/update_event/{event_id}"
+        payload = {}
+        if summary:
+            payload["summary"] = summary
+        if description:
+            payload["description"] = description
+        if start_time:
+            payload["start_time"] = start_time
+        if end_time:
+            payload["end_time"] = end_time
+        if need_notification:
+            payload["need_notification"] = need_notification
+        if auto_record:
+            payload["auto_record"] = auto_record
+        res = self._send_request(url, method="PATCH", payload=payload)
+        return res
+
+    def delete_event(self, event_id: str, need_notification: bool = True) -> dict:
+        url = f"{self.API_BASE_URL}/calendar/delete_event/{event_id}"
+        params = {
+            "need_notification": need_notification,
+        }
+        res = self._send_request(url, method="DELETE", params=params)
+        return res
+
+    def list_events(self, start_time: str, end_time: str, page_token: str, page_size: int = 50) -> dict:
+        url = f"{self.API_BASE_URL}/calendar/list_events"
+        params = {
+            "start_time": start_time,
+            "end_time": end_time,
+            "page_token": page_token,
+            "page_size": page_size,
+        }
+        res = self._send_request(url, method="GET", params=params)
+        return res.get("data")
+
+    def search_events(
+        self,
+        query: str,
+        start_time: str,
+        end_time: str,
+        page_token: str,
+        user_id_type: str = "open_id",
+        page_size: int = 20,
+    ) -> dict:
+        url = f"{self.API_BASE_URL}/calendar/search_events"
+        payload = {
+            "query": query,
+            "start_time": start_time,
+            "end_time": end_time,
+            "page_token": page_token,
+            "user_id_type": user_id_type,
+            "page_size": page_size,
+        }
+        res = self._send_request(url, payload=payload)
+        return res.get("data")
+
+    def add_event_attendees(self, event_id: str, attendee_phone_or_email: str, need_notification: bool = True) -> dict:
+        # 参加日程参会人
+        url = f"{self.API_BASE_URL}/calendar/add_event_attendees"
+        payload = {
+            "event_id": event_id,
+            "attendee_phone_or_email": attendee_phone_or_email,
+            "need_notification": need_notification,
+        }
+        res = self._send_request(url, payload=payload)
+        return res.get("data")
+
+    def create_spreadsheet(
+        self,
+        title: str,
+        folder_token: str,
+    ) -> dict:
+        # 创建电子表格
+        url = f"{self.API_BASE_URL}/spreadsheet/create_spreadsheet"
+        payload = {
+            "title": title,
+            "folder_token": folder_token,
+        }
+        res = self._send_request(url, payload=payload)
+        return res.get("data")
+
+    def get_spreadsheet(
+        self,
+        spreadsheet_token: str,
+        user_id_type: str = "open_id",
+    ) -> dict:
+        # 获取电子表格信息
+        url = f"{self.API_BASE_URL}/spreadsheet/get_spreadsheet"
+        params = {
+            "spreadsheet_token": spreadsheet_token,
+            "user_id_type": user_id_type,
+        }
+        res = self._send_request(url, method="GET", params=params)
+        return res.get("data")
+
+    def list_spreadsheet_sheets(
+        self,
+        spreadsheet_token: str,
+    ) -> dict:
+        # 列出电子表格的所有工作表
+        url = f"{self.API_BASE_URL}/spreadsheet/list_spreadsheet_sheets"
+        params = {
+            "spreadsheet_token": spreadsheet_token,
+        }
+        res = self._send_request(url, method="GET", params=params)
+        return res.get("data")
+
+    def add_rows(
+        self,
+        spreadsheet_token: str,
+        sheet_id: str,
+        sheet_name: str,
+        length: int,
+        values: str,
+    ) -> dict:
+        # 增加行,在工作表最后添加
+        url = f"{self.API_BASE_URL}/spreadsheet/add_rows"
+        payload = {
+            "spreadsheet_token": spreadsheet_token,
+            "sheet_id": sheet_id,
+            "sheet_name": sheet_name,
+            "length": length,
+            "values": values,
+        }
+        res = self._send_request(url, payload=payload)
+        return res.get("data")
+
+    def add_cols(
+        self,
+        spreadsheet_token: str,
+        sheet_id: str,
+        sheet_name: str,
+        length: int,
+        values: str,
+    ) -> dict:
+        #  增加列,在工作表最后添加
+        url = f"{self.API_BASE_URL}/spreadsheet/add_cols"
+        payload = {
+            "spreadsheet_token": spreadsheet_token,
+            "sheet_id": sheet_id,
+            "sheet_name": sheet_name,
+            "length": length,
+            "values": values,
+        }
+        res = self._send_request(url, payload=payload)
+        return res.get("data")
+
+    def read_rows(
+        self,
+        spreadsheet_token: str,
+        sheet_id: str,
+        sheet_name: str,
+        start_row: int,
+        num_rows: int,
+        user_id_type: str = "open_id",
+    ) -> dict:
+        # 读取工作表行数据
+        url = f"{self.API_BASE_URL}/spreadsheet/read_rows"
+        params = {
+            "spreadsheet_token": spreadsheet_token,
+            "sheet_id": sheet_id,
+            "sheet_name": sheet_name,
+            "start_row": start_row,
+            "num_rows": num_rows,
+            "user_id_type": user_id_type,
+        }
+        res = self._send_request(url, method="GET", params=params)
+        return res.get("data")
+
+    def read_cols(
+        self,
+        spreadsheet_token: str,
+        sheet_id: str,
+        sheet_name: str,
+        start_col: int,
+        num_cols: int,
+        user_id_type: str = "open_id",
+    ) -> dict:
+        # 读取工作表列数据
+        url = f"{self.API_BASE_URL}/spreadsheet/read_cols"
+        params = {
+            "spreadsheet_token": spreadsheet_token,
+            "sheet_id": sheet_id,
+            "sheet_name": sheet_name,
+            "start_col": start_col,
+            "num_cols": num_cols,
+            "user_id_type": user_id_type,
+        }
+        res = self._send_request(url, method="GET", params=params)
+        return res.get("data")
+
+    def read_table(
+        self,
+        spreadsheet_token: str,
+        sheet_id: str,
+        sheet_name: str,
+        num_range: str,
+        query: str,
+        user_id_type: str = "open_id",
+    ) -> dict:
+        # 自定义读取行列数据
+        url = f"{self.API_BASE_URL}/spreadsheet/read_table"
+        params = {
+            "spreadsheet_token": spreadsheet_token,
+            "sheet_id": sheet_id,
+            "sheet_name": sheet_name,
+            "range": num_range,
+            "query": query,
+            "user_id_type": user_id_type,
+        }
+        res = self._send_request(url, method="GET", params=params)
+        return res.get("data")