merge main

This commit is contained in:
Joel 2024-11-08 13:55:39 +08:00
commit a9de7f24a2
175 changed files with 5472 additions and 303 deletions

View File

@ -6,6 +6,7 @@ on:
- main
paths:
- api/migrations/**
- .github/workflows/db-migration-test.yml
concurrency:
group: db-migration-test-${{ github.ref }}

View File

@ -285,8 +285,9 @@ UPLOAD_IMAGE_FILE_SIZE_LIMIT=10
UPLOAD_VIDEO_FILE_SIZE_LIMIT=100
UPLOAD_AUDIO_FILE_SIZE_LIMIT=50
# Model Configuration
# Model configuration
MULTIMODAL_SEND_IMAGE_FORMAT=base64
MULTIMODAL_SEND_VIDEO_FORMAT=base64
PROMPT_GENERATION_MAX_TOKENS=512
CODE_GENERATION_MAX_TOKENS=1024
@ -324,10 +325,10 @@ UNSTRUCTURED_API_KEY=
SSRF_PROXY_HTTP_URL=
SSRF_PROXY_HTTPS_URL=
SSRF_DEFAULT_MAX_RETRIES=3
SSRF_DEFAULT_TIME_OUT=
SSRF_DEFAULT_CONNECT_TIME_OUT=
SSRF_DEFAULT_READ_TIME_OUT=
SSRF_DEFAULT_WRITE_TIME_OUT=
SSRF_DEFAULT_TIME_OUT=5
SSRF_DEFAULT_CONNECT_TIME_OUT=5
SSRF_DEFAULT_READ_TIME_OUT=5
SSRF_DEFAULT_WRITE_TIME_OUT=5
BATCH_UPLOAD_LIMIT=10
KEYWORD_DATA_SOURCE_TYPE=database

View File

@ -2,7 +2,7 @@ import os
from configs import dify_config
if os.environ.get("DEBUG", "false").lower() != "true":
if not dify_config.DEBUG:
from gevent import monkey
monkey.patch_all()

View File

@ -1,6 +1,8 @@
import os
if os.environ.get("DEBUG", "false").lower() != "true":
from configs import dify_config
if not dify_config.DEBUG:
from gevent import monkey
monkey.patch_all()

View File

@ -276,6 +276,16 @@ class HttpConfig(BaseSettings):
default=1 * 1024 * 1024,
)
SSRF_DEFAULT_MAX_RETRIES: PositiveInt = Field(
description="Maximum number of retries for network requests (SSRF)",
default=3,
)
SSRF_PROXY_ALL_URL: Optional[str] = Field(
description="Proxy URL for HTTP or HTTPS requests to prevent Server-Side Request Forgery (SSRF)",
default=None,
)
SSRF_PROXY_HTTP_URL: Optional[str] = Field(
description="Proxy URL for HTTP requests to prevent Server-Side Request Forgery (SSRF)",
default=None,
@ -624,12 +634,17 @@ class IndexingConfig(BaseSettings):
)
class ImageFormatConfig(BaseSettings):
class VisionFormatConfig(BaseSettings):
MULTIMODAL_SEND_IMAGE_FORMAT: Literal["base64", "url"] = Field(
description="Format for sending images in multimodal contexts ('base64' or 'url'), default is base64",
default="base64",
)
MULTIMODAL_SEND_VIDEO_FORMAT: Literal["base64", "url"] = Field(
description="Format for sending videos in multimodal contexts ('base64' or 'url'), default is base64",
default="base64",
)
class CeleryBeatConfig(BaseSettings):
CELERY_BEAT_SCHEDULER_TIME: int = Field(
@ -732,7 +747,7 @@ class FeatureConfig(
FileAccessConfig,
FileUploadConfig,
HttpConfig,
ImageFormatConfig,
VisionFormatConfig,
InnerAPIConfig,
IndexingConfig,
LoggingConfig,

View File

@ -945,7 +945,7 @@ class DocumentRetryApi(DocumentResource):
raise DocumentAlreadyFinishedError()
retry_documents.append(document)
except Exception as e:
logging.error(f"Document {document_id} retry failed: {str(e)}")
logging.exception(f"Document {document_id} retry failed: {str(e)}")
continue
# retry document
DocumentService.retry_document(dataset_id, retry_documents)

View File

@ -7,7 +7,11 @@ from controllers.service_api import api
from controllers.service_api.app.error import NotChatAppError
from controllers.service_api.wraps import FetchUserArg, WhereisUserArg, validate_app_token
from core.app.entities.app_invoke_entities import InvokeFrom
from fields.conversation_fields import conversation_infinite_scroll_pagination_fields, simple_conversation_fields
from fields.conversation_fields import (
conversation_delete_fields,
conversation_infinite_scroll_pagination_fields,
simple_conversation_fields,
)
from libs.helper import uuid_value
from models.model import App, AppMode, EndUser
from services.conversation_service import ConversationService
@ -49,7 +53,7 @@ class ConversationApi(Resource):
class ConversationDetailApi(Resource):
@validate_app_token(fetch_user_arg=FetchUserArg(fetch_from=WhereisUserArg.JSON))
@marshal_with(simple_conversation_fields)
@marshal_with(conversation_delete_fields)
def delete(self, app_model: App, end_user: EndUser, c_id):
app_mode = AppMode.value_of(app_model.mode)
if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}:
@ -58,10 +62,9 @@ class ConversationDetailApi(Resource):
conversation_id = str(c_id)
try:
ConversationService.delete(app_model, conversation_id, end_user)
return ConversationService.delete(app_model, conversation_id, end_user)
except services.errors.conversation.ConversationNotExistsError:
raise NotFound("Conversation Not Exists.")
return {"result": "success"}, 200
class ConversationRenameApi(Resource):

View File

@ -1,6 +1,5 @@
import contextvars
import logging
import os
import threading
import uuid
from collections.abc import Generator
@ -10,6 +9,7 @@ from flask import Flask, current_app
from pydantic import ValidationError
import contexts
from configs import dify_config
from constants import UUID_NIL
from core.app.app_config.features.file_upload.manager import FileUploadConfigManager
from core.app.apps.advanced_chat.app_config_manager import AdvancedChatAppConfigManager
@ -317,7 +317,7 @@ class AdvancedChatAppGenerator(MessageBasedAppGenerator):
logger.exception("Validation Error when generating")
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
except (ValueError, InvokeError) as e:
if os.environ.get("DEBUG", "false").lower() == "true":
if dify_config.DEBUG:
logger.exception("Error when generating")
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
except Exception as e:

View File

@ -242,7 +242,7 @@ class AdvancedChatAppGenerateTaskPipeline(BasedGenerateTaskPipeline, WorkflowCyc
start_listener_time = time.time()
yield MessageAudioStreamResponse(audio=audio_trunk.audio, task_id=task_id)
except Exception as e:
logger.error(e)
logger.exception(e)
break
if tts_publisher:
yield MessageAudioEndStreamResponse(audio="", task_id=task_id)

View File

@ -1,5 +1,4 @@
import logging
import os
import threading
import uuid
from collections.abc import Generator
@ -8,6 +7,7 @@ from typing import Any, Literal, Union, overload
from flask import Flask, current_app
from pydantic import ValidationError
from configs import dify_config
from constants import UUID_NIL
from core.app.app_config.easy_ui_based_app.model_config.converter import ModelConfigConverter
from core.app.app_config.features.file_upload.manager import FileUploadConfigManager
@ -230,7 +230,7 @@ class AgentChatAppGenerator(MessageBasedAppGenerator):
logger.exception("Validation Error when generating")
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
except (ValueError, InvokeError) as e:
if os.environ.get("DEBUG") and os.environ.get("DEBUG").lower() == "true":
if dify_config.DEBUG:
logger.exception("Error when generating")
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
except Exception as e:

View File

@ -1,5 +1,4 @@
import logging
import os
import threading
import uuid
from collections.abc import Generator
@ -8,6 +7,7 @@ from typing import Any, Literal, Union, overload
from flask import Flask, current_app
from pydantic import ValidationError
from configs import dify_config
from constants import UUID_NIL
from core.app.app_config.easy_ui_based_app.model_config.converter import ModelConfigConverter
from core.app.app_config.features.file_upload.manager import FileUploadConfigManager
@ -227,7 +227,7 @@ class ChatAppGenerator(MessageBasedAppGenerator):
logger.exception("Validation Error when generating")
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
except (ValueError, InvokeError) as e:
if os.environ.get("DEBUG") and os.environ.get("DEBUG").lower() == "true":
if dify_config.DEBUG:
logger.exception("Error when generating")
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
except Exception as e:

View File

@ -1,5 +1,4 @@
import logging
import os
import threading
import uuid
from collections.abc import Generator
@ -8,6 +7,7 @@ from typing import Any, Literal, Union, overload
from flask import Flask, current_app
from pydantic import ValidationError
from configs import dify_config
from core.app.app_config.easy_ui_based_app.model_config.converter import ModelConfigConverter
from core.app.app_config.features.file_upload.manager import FileUploadConfigManager
from core.app.apps.base_app_queue_manager import AppQueueManager, GenerateTaskStoppedError, PublishFrom
@ -203,7 +203,7 @@ class CompletionAppGenerator(MessageBasedAppGenerator):
logger.exception("Validation Error when generating")
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
except (ValueError, InvokeError) as e:
if os.environ.get("DEBUG") and os.environ.get("DEBUG").lower() == "true":
if dify_config.DEBUG:
logger.exception("Error when generating")
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
except Exception as e:

View File

@ -1,6 +1,5 @@
import contextvars
import logging
import os
import threading
import uuid
from collections.abc import Generator, Mapping, Sequence
@ -10,6 +9,7 @@ from flask import Flask, current_app
from pydantic import ValidationError
import contexts
from configs import dify_config
from core.app.app_config.features.file_upload.manager import FileUploadConfigManager
from core.app.apps.base_app_generator import BaseAppGenerator
from core.app.apps.base_app_queue_manager import AppQueueManager, GenerateTaskStoppedError, PublishFrom
@ -261,7 +261,7 @@ class WorkflowAppGenerator(BaseAppGenerator):
logger.exception("Validation Error when generating")
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
except (ValueError, InvokeError) as e:
if os.environ.get("DEBUG") and os.environ.get("DEBUG", "false").lower() == "true":
if dify_config.DEBUG:
logger.exception("Error when generating")
queue_manager.publish_error(e, PublishFrom.APPLICATION_MANAGER)
except Exception as e:

View File

@ -216,7 +216,7 @@ class WorkflowAppGenerateTaskPipeline(BasedGenerateTaskPipeline, WorkflowCycleMa
else:
yield MessageAudioStreamResponse(audio=audio_trunk.audio, task_id=task_id)
except Exception as e:
logger.error(e)
logger.exception(e)
break
if tts_publisher:
yield MessageAudioEndStreamResponse(audio="", task_id=task_id)

View File

@ -3,7 +3,7 @@ import base64
from configs import dify_config
from core.file import file_repository
from core.helper import ssrf_proxy
from core.model_runtime.entities import AudioPromptMessageContent, ImagePromptMessageContent
from core.model_runtime.entities import AudioPromptMessageContent, ImagePromptMessageContent, VideoPromptMessageContent
from extensions.ext_database import db
from extensions.ext_storage import storage
@ -71,6 +71,12 @@ def to_prompt_message_content(f: File, /):
if f.extension is None:
raise ValueError("Missing file extension")
return AudioPromptMessageContent(data=encoded_string, format=f.extension.lstrip("."))
case FileType.VIDEO:
if dify_config.MULTIMODAL_SEND_VIDEO_FORMAT == "url":
data = _to_url(f)
else:
data = _to_base64_data_string(f)
return VideoPromptMessageContent(data=data, format=f.extension.lstrip("."))
case _:
raise ValueError(f"file type {f.type} is not supported")
@ -112,7 +118,7 @@ def _download_file_content(path: str, /):
def _get_encoded_string(f: File, /):
match f.transfer_method:
case FileTransferMethod.REMOTE_URL:
response = ssrf_proxy.get(f.remote_url)
response = ssrf_proxy.get(f.remote_url, follow_redirects=True)
response.raise_for_status()
content = response.content
encoded_string = base64.b64encode(content).decode("utf-8")
@ -140,6 +146,8 @@ def _file_to_encoded_string(f: File, /):
match f.type:
case FileType.IMAGE:
return _to_base64_data_string(f)
case FileType.VIDEO:
return _to_base64_data_string(f)
case FileType.AUDIO:
return _get_encoded_string(f)
case _:

View File

@ -3,26 +3,20 @@ Proxy requests to avoid SSRF
"""
import logging
import os
import time
import httpx
SSRF_PROXY_ALL_URL = os.getenv("SSRF_PROXY_ALL_URL", "")
SSRF_PROXY_HTTP_URL = os.getenv("SSRF_PROXY_HTTP_URL", "")
SSRF_PROXY_HTTPS_URL = os.getenv("SSRF_PROXY_HTTPS_URL", "")
SSRF_DEFAULT_MAX_RETRIES = int(os.getenv("SSRF_DEFAULT_MAX_RETRIES", "3"))
SSRF_DEFAULT_TIME_OUT = float(os.getenv("SSRF_DEFAULT_TIME_OUT", "5"))
SSRF_DEFAULT_CONNECT_TIME_OUT = float(os.getenv("SSRF_DEFAULT_CONNECT_TIME_OUT", "5"))
SSRF_DEFAULT_READ_TIME_OUT = float(os.getenv("SSRF_DEFAULT_READ_TIME_OUT", "5"))
SSRF_DEFAULT_WRITE_TIME_OUT = float(os.getenv("SSRF_DEFAULT_WRITE_TIME_OUT", "5"))
from configs import dify_config
SSRF_DEFAULT_MAX_RETRIES = dify_config.SSRF_DEFAULT_MAX_RETRIES
proxy_mounts = (
{
"http://": httpx.HTTPTransport(proxy=SSRF_PROXY_HTTP_URL),
"https://": httpx.HTTPTransport(proxy=SSRF_PROXY_HTTPS_URL),
"http://": httpx.HTTPTransport(proxy=dify_config.SSRF_PROXY_HTTP_URL),
"https://": httpx.HTTPTransport(proxy=dify_config.SSRF_PROXY_HTTPS_URL),
}
if SSRF_PROXY_HTTP_URL and SSRF_PROXY_HTTPS_URL
if dify_config.SSRF_PROXY_HTTP_URL and dify_config.SSRF_PROXY_HTTPS_URL
else None
)
@ -38,17 +32,17 @@ def make_request(method, url, max_retries=SSRF_DEFAULT_MAX_RETRIES, **kwargs):
if "timeout" not in kwargs:
kwargs["timeout"] = httpx.Timeout(
SSRF_DEFAULT_TIME_OUT,
connect=SSRF_DEFAULT_CONNECT_TIME_OUT,
read=SSRF_DEFAULT_READ_TIME_OUT,
write=SSRF_DEFAULT_WRITE_TIME_OUT,
timeout=dify_config.SSRF_DEFAULT_TIME_OUT,
connect=dify_config.SSRF_DEFAULT_CONNECT_TIME_OUT,
read=dify_config.SSRF_DEFAULT_READ_TIME_OUT,
write=dify_config.SSRF_DEFAULT_WRITE_TIME_OUT,
)
retries = 0
while retries <= max_retries:
try:
if SSRF_PROXY_ALL_URL:
with httpx.Client(proxy=SSRF_PROXY_ALL_URL) as client:
if dify_config.SSRF_PROXY_ALL_URL:
with httpx.Client(proxy=dify_config.SSRF_PROXY_ALL_URL) as client:
response = client.request(method=method, url=url, **kwargs)
elif proxy_mounts:
with httpx.Client(mounts=proxy_mounts) as client:
@ -60,10 +54,12 @@ def make_request(method, url, max_retries=SSRF_DEFAULT_MAX_RETRIES, **kwargs):
if response.status_code not in STATUS_FORCELIST:
return response
else:
logging.warning(f"Received status code {response.status_code} for URL {url} which is in the force list")
logging.warning(
f"Received status code {response.status_code} for URL {url} which is in the force list")
except httpx.RequestError as e:
logging.warning(f"Request to URL {url} failed on attempt {retries + 1}: {e}")
logging.warning(
f"Request to URL {url} failed on attempt {retries + 1}: {e}")
retries += 1
if retries <= max_retries:

View File

@ -1,8 +1,8 @@
import logging
import os
from collections.abc import Callable, Generator, Iterable, Sequence
from typing import IO, Any, Optional, Union, cast
from configs import dify_config
from core.entities.embedding_type import EmbeddingInputType
from core.entities.provider_configuration import ProviderConfiguration, ProviderModelBundle
from core.entities.provider_entities import ModelLoadBalancingConfiguration
@ -473,7 +473,7 @@ class LBModelManager:
continue
if bool(os.environ.get("DEBUG", "False").lower() == "true"):
if dify_config.DEBUG:
logger.info(
f"Model LB\nid: {config.id}\nname:{config.name}\n"
f"tenant_id: {self._tenant_id}\nprovider: {self._provider}\n"

View File

@ -12,11 +12,13 @@ from .message_entities import (
TextPromptMessageContent,
ToolPromptMessage,
UserPromptMessage,
VideoPromptMessageContent,
)
from .model_entities import ModelPropertyKey
__all__ = [
"ImagePromptMessageContent",
"VideoPromptMessageContent",
"PromptMessage",
"PromptMessageRole",
"LLMUsage",

View File

@ -56,6 +56,7 @@ class PromptMessageContentType(Enum):
TEXT = "text"
IMAGE = "image"
AUDIO = "audio"
VIDEO = "video"
class PromptMessageContent(BaseModel):
@ -75,6 +76,12 @@ class TextPromptMessageContent(PromptMessageContent):
type: PromptMessageContentType = PromptMessageContentType.TEXT
class VideoPromptMessageContent(PromptMessageContent):
type: PromptMessageContentType = PromptMessageContentType.VIDEO
data: str = Field(..., description="Base64 encoded video data")
format: str = Field(..., description="Video format")
class AudioPromptMessageContent(PromptMessageContent):
type: PromptMessageContentType = PromptMessageContentType.AUDIO
data: str = Field(..., description="Base64 encoded audio data")

View File

@ -47,9 +47,9 @@ class AzureRerankModel(RerankModel):
result = response.read()
return json.loads(result)
except urllib.error.HTTPError as error:
logger.error(f"The request failed with status code: {error.code}")
logger.error(error.info())
logger.error(error.read().decode("utf8", "ignore"))
logger.exception(f"The request failed with status code: {error.code}")
logger.exception(error.info())
logger.exception(error.read().decode("utf8", "ignore"))
raise
def _invoke(

View File

@ -29,6 +29,7 @@ from core.model_runtime.entities.message_entities import (
TextPromptMessageContent,
ToolPromptMessage,
UserPromptMessage,
VideoPromptMessageContent,
)
from core.model_runtime.entities.model_entities import (
AIModelEntity,
@ -431,6 +432,14 @@ class TongyiLargeLanguageModel(LargeLanguageModel):
sub_message_dict = {"image": image_url}
sub_messages.append(sub_message_dict)
elif message_content.type == PromptMessageContentType.VIDEO:
message_content = cast(VideoPromptMessageContent, message_content)
video_url = message_content.data
if message_content.data.startswith("data:"):
raise InvokeError("not support base64, please set MULTIMODAL_SEND_VIDEO_FORMAT to url")
sub_message_dict = {"video": video_url}
sub_messages.append(sub_message_dict)
# resort sub_messages to ensure text is always at last
sub_messages = sorted(sub_messages, key=lambda x: "text" in x)

View File

@ -313,21 +313,35 @@ class ZhipuAILargeLanguageModel(_CommonZhipuaiAI, LargeLanguageModel):
return params
def _construct_glm_4v_messages(self, prompt_message: Union[str, list[PromptMessageContent]]) -> list[dict]:
if isinstance(prompt_message, str):
if isinstance(prompt_message, list):
sub_messages = []
for item in prompt_message:
if item.type == PromptMessageContentType.IMAGE:
sub_messages.append(
{
"type": "image_url",
"image_url": {"url": self._remove_base64_header(item.data)},
}
)
elif item.type == PromptMessageContentType.VIDEO:
sub_messages.append(
{
"type": "video_url",
"video_url": {"url": self._remove_base64_header(item.data)},
}
)
else:
sub_messages.append({"type": "text", "text": item.data})
return sub_messages
else:
return [{"type": "text", "text": prompt_message}]
return [
{"type": "image_url", "image_url": {"url": self._remove_image_header(item.data)}}
if item.type == PromptMessageContentType.IMAGE
else {"type": "text", "text": item.data}
for item in prompt_message
]
def _remove_base64_header(self, file_content: str) -> str:
if file_content.startswith("data:"):
data_split = file_content.split(";base64,")
return data_split[1]
def _remove_image_header(self, image: str) -> str:
if image.startswith("data:image"):
return image.split(",")[1]
return image
return file_content
def _handle_generate_response(
self,

View File

@ -126,6 +126,6 @@ class OutputModeration(BaseModel):
result: ModerationOutputsResult = moderation_factory.moderation_for_outputs(moderation_buffer)
return result
except Exception as e:
logger.error("Moderation Output error: %s", e)
logger.exception("Moderation Output error: %s", e)
return None

View File

@ -708,7 +708,7 @@ class TraceQueueManager:
trace_task.app_id = self.app_id
trace_manager_queue.put(trace_task)
except Exception as e:
logging.error(f"Error adding trace task: {e}")
logging.exception(f"Error adding trace task: {e}")
finally:
self.start_timer()
@ -727,7 +727,7 @@ class TraceQueueManager:
if tasks:
self.send_to_celery(tasks)
except Exception as e:
logging.error(f"Error processing trace tasks: {e}")
logging.exception(f"Error processing trace tasks: {e}")
def start_timer(self):
global trace_manager_timer

View File

@ -242,7 +242,7 @@ class CouchbaseVector(BaseVector):
try:
self._cluster.query(query, named_parameters={"doc_ids": ids}).execute()
except Exception as e:
logger.error(e)
logger.exception(e)
def delete_by_document_id(self, document_id: str):
query = f"""

View File

@ -20,7 +20,8 @@ from extensions.ext_redis import redis_client
from models.dataset import Dataset
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logging.basicConfig(level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s")
logging.getLogger("lindorm").setLevel(logging.WARN)
@ -76,10 +77,11 @@ class LindormVectorStore(BaseVector):
@retry(stop=stop_after_attempt(3), wait=wait_fixed(60))
def __fetch_existing_ids(batch_ids: list[str]) -> set[str]:
try:
existing_docs = self._client.mget(index=self._collection_name, body={"ids": batch_ids}, _source=False)
existing_docs = self._client.mget(index=self._collection_name, body={
"ids": batch_ids}, _source=False)
return {doc["_id"] for doc in existing_docs["docs"] if doc["found"]}
except Exception as e:
logger.error(f"Error fetching batch {batch_ids}: {e}")
logger.exception(f"Error fetching batch {batch_ids}: {e}")
return set()
@retry(stop=stop_after_attempt(3), wait=wait_fixed(60))
@ -88,7 +90,8 @@ class LindormVectorStore(BaseVector):
existing_docs = self._client.mget(
body={
"docs": [
{"_index": self._collection_name, "_id": id, "routing": routing}
{"_index": self._collection_name,
"_id": id, "routing": routing}
for id, routing in zip(batch_ids, route_ids)
]
},
@ -96,7 +99,7 @@ class LindormVectorStore(BaseVector):
)
return {doc["_id"] for doc in existing_docs["docs"] if doc["found"]}
except Exception as e:
logger.error(f"Error fetching batch {batch_ids}: {e}")
logger.exception(f"Error fetching batch {batch_ids}: {e}")
return set()
if ids is None:
@ -112,12 +115,13 @@ class LindormVectorStore(BaseVector):
def batch(iterable, n):
length = len(iterable)
for idx in range(0, length, n):
yield iterable[idx : min(idx + n, length)]
yield iterable[idx: min(idx + n, length)]
for ids_batch, texts_batch, metadatas_batch in zip(
batch(ids, bulk_size),
batch(texts, bulk_size),
batch(metadatas, bulk_size) if metadatas is not None else batch([None] * len(ids), bulk_size),
batch(metadatas, bulk_size) if metadatas is not None else batch(
[None] * len(ids), bulk_size),
):
existing_ids_set = __fetch_existing_ids(ids_batch)
for text, metadata, doc_id in zip(texts_batch, metadatas_batch, ids_batch):
@ -139,7 +143,8 @@ class LindormVectorStore(BaseVector):
"_id": uuids[i],
"_source": {
Field.CONTENT_KEY.value: documents[i].page_content,
Field.VECTOR.value: embeddings[i], # Make sure you pass an array here
# Make sure you pass an array here
Field.VECTOR.value: embeddings[i],
Field.METADATA_KEY.value: documents[i].metadata,
},
}
@ -148,7 +153,8 @@ class LindormVectorStore(BaseVector):
self.refresh()
def get_ids_by_metadata_field(self, key: str, value: str):
query = {"query": {"term": {f"{Field.METADATA_KEY.value}.{key}.keyword": value}}}
query = {
"query": {"term": {f"{Field.METADATA_KEY.value}.{key}.keyword": value}}}
response = self._client.search(index=self._collection_name, body=query)
if response["hits"]["hits"]:
return [hit["_id"] for hit in response["hits"]["hits"]]
@ -157,7 +163,8 @@ class LindormVectorStore(BaseVector):
def delete_by_metadata_field(self, key: str, value: str):
query_str = {"query": {"match": {f"metadata.{key}": f"{value}"}}}
results = self._client.search(index=self._collection_name, body=query_str)
results = self._client.search(
index=self._collection_name, body=query_str)
ids = [hit["_id"] for hit in results["hits"]["hits"]]
if ids:
self.delete_by_ids(ids)
@ -167,17 +174,20 @@ class LindormVectorStore(BaseVector):
if self._client.exists(index=self._collection_name, id=id):
self._client.delete(index=self._collection_name, id=id)
else:
logger.warning(f"DELETE BY ID: ID {id} does not exist in the index.")
logger.warning(
f"DELETE BY ID: ID {id} does not exist in the index.")
def delete(self) -> None:
try:
if self._client.indices.exists(index=self._collection_name):
self._client.indices.delete(index=self._collection_name, params={"timeout": 60})
self._client.indices.delete(
index=self._collection_name, params={"timeout": 60})
logger.info("Delete index success")
else:
logger.warning(f"Index '{self._collection_name}' does not exist. No deletion performed.")
logger.warning(
f"Index '{self._collection_name}' does not exist. No deletion performed.")
except Exception as e:
logger.error(f"Error occurred while deleting the index: {e}")
logger.exception(f"Error occurred while deleting the index: {e}")
raise e
def text_exists(self, id: str) -> bool:
@ -197,11 +207,13 @@ class LindormVectorStore(BaseVector):
raise ValueError("All elements in query_vector should be floats")
top_k = kwargs.get("top_k", 10)
query = default_vector_search_query(query_vector=query_vector, k=top_k, **kwargs)
query = default_vector_search_query(
query_vector=query_vector, k=top_k, **kwargs)
try:
response = self._client.search(index=self._collection_name, body=query)
response = self._client.search(
index=self._collection_name, body=query)
except Exception as e:
logger.error(f"Error executing search: {e}")
logger.exception(f"Error executing search: {e}")
raise
docs_and_scores = []
@ -244,7 +256,8 @@ class LindormVectorStore(BaseVector):
filters=filters,
routing=routing,
)
response = self._client.search(index=self._collection_name, body=full_text_query)
response = self._client.search(
index=self._collection_name, body=full_text_query)
docs = []
for hit in response["hits"]["hits"]:
docs.append(
@ -262,7 +275,8 @@ class LindormVectorStore(BaseVector):
with redis_client.lock(lock_name, timeout=20):
collection_exist_cache_key = f"vector_indexing_{self._collection_name}"
if redis_client.get(collection_exist_cache_key):
logger.info(f"Collection {self._collection_name} already exists.")
logger.info(
f"Collection {self._collection_name} already exists.")
return
if self._client.indices.exists(index=self._collection_name):
logger.info("{self._collection_name.lower()} already exists.")
@ -281,10 +295,13 @@ class LindormVectorStore(BaseVector):
hnsw_ef_construction = kwargs.pop("hnsw_ef_construction", 500)
ivfpq_m = kwargs.pop("ivfpq_m", dimension)
nlist = kwargs.pop("nlist", 1000)
centroids_use_hnsw = kwargs.pop("centroids_use_hnsw", True if nlist >= 5000 else False)
centroids_use_hnsw = kwargs.pop(
"centroids_use_hnsw", True if nlist >= 5000 else False)
centroids_hnsw_m = kwargs.pop("centroids_hnsw_m", 24)
centroids_hnsw_ef_construct = kwargs.pop("centroids_hnsw_ef_construct", 500)
centroids_hnsw_ef_search = kwargs.pop("centroids_hnsw_ef_search", 100)
centroids_hnsw_ef_construct = kwargs.pop(
"centroids_hnsw_ef_construct", 500)
centroids_hnsw_ef_search = kwargs.pop(
"centroids_hnsw_ef_search", 100)
mapping = default_text_mapping(
dimension,
method_name,
@ -303,7 +320,8 @@ class LindormVectorStore(BaseVector):
centroids_hnsw_ef_search=centroids_hnsw_ef_search,
**kwargs,
)
self._client.indices.create(index=self._collection_name.lower(), body=mapping)
self._client.indices.create(
index=self._collection_name.lower(), body=mapping)
redis_client.set(collection_exist_cache_key, 1, ex=3600)
# logger.info(f"create index success: {self._collection_name}")
@ -364,7 +382,8 @@ def default_text_mapping(dimension: int, method_name: str, **kwargs: Any) -> dic
}
if excludes_from_source:
mapping["mappings"]["_source"] = {"excludes": excludes_from_source} # e.g. {"excludes": ["vector_field"]}
# e.g. {"excludes": ["vector_field"]}
mapping["mappings"]["_source"] = {"excludes": excludes_from_source}
if method_name == "ivfpq" and routing_field is not None:
mapping["settings"]["index"]["knn_routing"] = True
@ -405,7 +424,8 @@ def default_text_search_query(
# build complex search_query when either of must/must_not/should/filter is specified
if must:
if not isinstance(must, list):
raise RuntimeError(f"unexpected [must] clause with {type(filters)}")
raise RuntimeError(
f"unexpected [must] clause with {type(filters)}")
if query_clause not in must:
must.append(query_clause)
else:
@ -415,19 +435,22 @@ def default_text_search_query(
if must_not:
if not isinstance(must_not, list):
raise RuntimeError(f"unexpected [must_not] clause with {type(filters)}")
raise RuntimeError(
f"unexpected [must_not] clause with {type(filters)}")
boolean_query["must_not"] = must_not
if should:
if not isinstance(should, list):
raise RuntimeError(f"unexpected [should] clause with {type(filters)}")
raise RuntimeError(
f"unexpected [should] clause with {type(filters)}")
boolean_query["should"] = should
if minimum_should_match != 0:
boolean_query["minimum_should_match"] = minimum_should_match
if filters:
if not isinstance(filters, list):
raise RuntimeError(f"unexpected [filter] clause with {type(filters)}")
raise RuntimeError(
f"unexpected [filter] clause with {type(filters)}")
boolean_query["filter"] = filters
search_query = {"size": k, "query": {"bool": boolean_query}}
@ -471,8 +494,10 @@ def default_vector_search_query(
if filters is not None:
# when using filter, transform filter from List[Dict] to Dict as valid format
filters = {"bool": {"must": filters}} if len(filters) > 1 else filters[0]
search_query["query"]["knn"][vector_field]["filter"] = filters # filter should be Dict
filters = {"bool": {"must": filters}} if len(
filters) > 1 else filters[0]
# filter should be Dict
search_query["query"]["knn"][vector_field]["filter"] = filters
if filter_type:
final_ext["lvector"]["filter_type"] = filter_type
@ -489,7 +514,8 @@ class LindormVectorStoreFactory(AbstractVectorFactory):
else:
dataset_id = dataset.id
collection_name = Dataset.gen_collection_name_by_id(dataset_id)
dataset.index_struct = json.dumps(self.gen_index_struct_dict(VectorType.LINDORM, collection_name))
dataset.index_struct = json.dumps(
self.gen_index_struct_dict(VectorType.LINDORM, collection_name))
lindorm_config = LindormVectorStoreConfig(
hosts=dify_config.LINDORM_URL,
username=dify_config.LINDORM_USERNAME,

View File

@ -86,7 +86,7 @@ class MilvusVector(BaseVector):
ids = self._client.insert(collection_name=self._collection_name, data=batch_insert_list)
pks.extend(ids)
except MilvusException as e:
logger.error("Failed to insert batch starting at entity: %s/%s", i, total_count)
logger.exception("Failed to insert batch starting at entity: %s/%s", i, total_count)
raise e
return pks

View File

@ -142,7 +142,7 @@ class MyScaleVector(BaseVector):
for r in self._client.query(sql).named_results()
]
except Exception as e:
logging.error(f"\033[91m\033[1m{type(e)}\033[0m \033[95m{str(e)}\033[0m")
logging.exception(f"\033[91m\033[1m{type(e)}\033[0m \033[95m{str(e)}\033[0m")
return []
def delete(self) -> None:

View File

@ -129,7 +129,7 @@ class OpenSearchVector(BaseVector):
if status == 404:
logger.warning(f"Document not found for deletion: {doc_id}")
else:
logger.error(f"Error deleting document: {error}")
logger.exception(f"Error deleting document: {error}")
def delete(self) -> None:
self._client.indices.delete(index=self._collection_name.lower())
@ -158,7 +158,7 @@ class OpenSearchVector(BaseVector):
try:
response = self._client.search(index=self._collection_name.lower(), body=query)
except Exception as e:
logger.error(f"Error executing search: {e}")
logger.exception(f"Error executing search: {e}")
raise
docs = []

View File

@ -89,7 +89,7 @@ class CacheEmbedding(Embeddings):
db.session.rollback()
except Exception as ex:
db.session.rollback()
logger.error("Failed to embed documents: %s", ex)
logger.exception("Failed to embed documents: %s", ex)
raise ex
return text_embeddings

View File

@ -28,7 +28,6 @@ logger = logging.getLogger(__name__)
class WordExtractor(BaseExtractor):
"""Load docx files.
Args:
file_path: Path to the file to load.
"""
@ -51,9 +50,9 @@ class WordExtractor(BaseExtractor):
self.web_path = self.file_path
# TODO: use a better way to handle the file
self.temp_file = tempfile.NamedTemporaryFile() # noqa: SIM115
self.temp_file.write(r.content)
self.file_path = self.temp_file.name
with tempfile.NamedTemporaryFile(delete=False) as self.temp_file:
self.temp_file.write(r.content)
self.file_path = self.temp_file.name
elif not os.path.isfile(self.file_path):
raise ValueError(f"File path {self.file_path} is not a valid file or url")
@ -230,7 +229,7 @@ class WordExtractor(BaseExtractor):
for i in url_pattern.findall(x.text):
hyperlinks_url = str(i)
except Exception as e:
logger.error(e)
logger.exception(e)
def parse_paragraph(paragraph):
paragraph_content = []

View File

@ -48,6 +48,13 @@
- feishu_task
- feishu_calendar
- feishu_spreadsheet
- lark_base
- lark_document
- lark_message_and_group
- lark_wiki
- lark_task
- lark_calendar
- lark_spreadsheet
- slack
- twilio
- wecom

View File

@ -34,7 +34,7 @@ parameters:
Page size, default value: 20, maximum value: 100.
zh_Hans: 分页大小默认值20最大值100。
llm_description: 分页大小默认值20最大值100。
form: llm
form: form
- name: page_token
type: string

View File

@ -147,7 +147,7 @@ parameters:
Page size, default value: 20, maximum value: 500.
zh_Hans: 分页大小默认值20最大值500。
llm_description: 分页大小默认值20最大值500。
form: llm
form: form
- name: page_token
type: string

View File

@ -47,7 +47,7 @@ parameters:
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
form: form
- name: page_token
type: string

View File

@ -85,7 +85,7 @@ parameters:
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
form: form
- name: page_token
type: string

View File

@ -59,7 +59,7 @@ parameters:
en_US: Paging size, the default and maximum value is 500.
zh_Hans: 分页大小, 默认值和最大值为 500。
llm_description: 分页大小, 表示一次请求最多返回多少条数据,默认值和最大值为 500。
form: llm
form: form
- name: page_token
type: string

View File

@ -81,7 +81,7 @@ parameters:
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
form: form
- name: page_token
type: string

View File

@ -57,7 +57,7 @@ parameters:
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
form: form
- name: page_token
type: string

View File

@ -56,7 +56,7 @@ parameters:
en_US: Number of columns to add, range (0-5000].
zh_Hans: 要增加的列数,范围(0-5000]。
llm_description: 要增加的列数,范围(0-5000]。
form: llm
form: form
- name: values
type: string

View File

@ -56,7 +56,7 @@ parameters:
en_US: Number of rows to add, range (0-5000].
zh_Hans: 要增加行数,范围(0-5000]。
llm_description: 要增加行数,范围(0-5000]。
form: llm
form: form
- name: values
type: string

View File

@ -82,7 +82,7 @@ parameters:
en_US: Starting column number, starting from 1.
zh_Hans: 起始列号,从 1 开始。
llm_description: 起始列号,从 1 开始。
form: llm
form: form
- name: num_cols
type: number
@ -94,4 +94,4 @@ parameters:
en_US: Number of columns to read.
zh_Hans: 读取列数
llm_description: 读取列数
form: llm
form: form

View File

@ -82,7 +82,7 @@ parameters:
en_US: Starting row number, starting from 1.
zh_Hans: 起始行号,从 1 开始。
llm_description: 起始行号,从 1 开始。
form: llm
form: form
- name: num_rows
type: number
@ -94,4 +94,4 @@ parameters:
en_US: Number of rows to read.
zh_Hans: 读取行数
llm_description: 读取行数
form: llm
form: form

View File

@ -82,7 +82,7 @@ parameters:
en_US: Starting row number, starting from 1.
zh_Hans: 起始行号,从 1 开始。
llm_description: 起始行号,从 1 开始。
form: llm
form: form
- name: num_rows
type: number
@ -94,7 +94,7 @@ parameters:
en_US: Number of rows to read.
zh_Hans: 读取行数
llm_description: 读取行数
form: llm
form: form
- name: range
type: string

View File

@ -36,7 +36,7 @@ parameters:
en_US: The size of each page, with a maximum value of 50.
zh_Hans: 分页大小,最大值 50。
llm_description: 分页大小,最大值 50。
form: llm
form: form
- name: page_token
type: string

View File

@ -13,15 +13,15 @@ class GitlabCommitsTool(BuiltinTool):
def _invoke(
self, user_id: str, tool_parameters: dict[str, Any]
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
project = tool_parameters.get("project", "")
branch = tool_parameters.get("branch", "")
repository = tool_parameters.get("repository", "")
employee = tool_parameters.get("employee", "")
start_time = tool_parameters.get("start_time", "")
end_time = tool_parameters.get("end_time", "")
change_type = tool_parameters.get("change_type", "all")
if not project and not repository:
return self.create_text_message("Either project or repository is required")
if not repository:
return self.create_text_message("Either repository is required")
if not start_time:
start_time = (datetime.utcnow() - timedelta(days=1)).isoformat()
@ -37,14 +37,9 @@ class GitlabCommitsTool(BuiltinTool):
site_url = "https://gitlab.com"
# Get commit content
if repository:
result = self.fetch_commits(
site_url, access_token, repository, employee, start_time, end_time, change_type, is_repository=True
)
else:
result = self.fetch_commits(
site_url, access_token, project, employee, start_time, end_time, change_type, is_repository=False
)
result = self.fetch_commits(
site_url, access_token, repository, branch, employee, start_time, end_time, change_type, is_repository=True
)
return [self.create_json_message(item) for item in result]
@ -52,7 +47,8 @@ class GitlabCommitsTool(BuiltinTool):
self,
site_url: str,
access_token: str,
identifier: str,
repository: str,
branch: str,
employee: str,
start_time: str,
end_time: str,
@ -64,27 +60,14 @@ class GitlabCommitsTool(BuiltinTool):
results = []
try:
if is_repository:
# URL encode the repository path
encoded_identifier = urllib.parse.quote(identifier, safe="")
commits_url = f"{domain}/api/v4/projects/{encoded_identifier}/repository/commits"
else:
# Get all projects
url = f"{domain}/api/v4/projects"
response = requests.get(url, headers=headers)
response.raise_for_status()
projects = response.json()
filtered_projects = [p for p in projects if identifier == "*" or p["name"] == identifier]
for project in filtered_projects:
project_id = project["id"]
project_name = project["name"]
print(f"Project: {project_name}")
commits_url = f"{domain}/api/v4/projects/{project_id}/repository/commits"
# URL encode the repository path
encoded_repository = urllib.parse.quote(repository, safe="")
commits_url = f"{domain}/api/v4/projects/{encoded_repository}/repository/commits"
# Fetch commits for the repository
params = {"since": start_time, "until": end_time}
if branch:
params["ref_name"] = branch
if employee:
params["author"] = employee
@ -96,10 +79,7 @@ class GitlabCommitsTool(BuiltinTool):
commit_sha = commit["id"]
author_name = commit["author_name"]
if is_repository:
diff_url = f"{domain}/api/v4/projects/{encoded_identifier}/repository/commits/{commit_sha}/diff"
else:
diff_url = f"{domain}/api/v4/projects/{project_id}/repository/commits/{commit_sha}/diff"
diff_url = f"{domain}/api/v4/projects/{encoded_repository}/repository/commits/{commit_sha}/diff"
diff_response = requests.get(diff_url, headers=headers)
diff_response.raise_for_status()
@ -120,7 +100,14 @@ class GitlabCommitsTool(BuiltinTool):
if line.startswith("+") and not line.startswith("+++")
]
)
results.append({"commit_sha": commit_sha, "author_name": author_name, "diff": final_code})
results.append(
{
"diff_url": diff_url,
"commit_sha": commit_sha,
"author_name": author_name,
"diff": final_code,
}
)
else:
if total_changes > 1:
final_code = "".join(
@ -134,7 +121,12 @@ class GitlabCommitsTool(BuiltinTool):
)
final_code_escaped = json.dumps(final_code)[1:-1] # Escape the final code
results.append(
{"commit_sha": commit_sha, "author_name": author_name, "diff": final_code_escaped}
{
"diff_url": diff_url,
"commit_sha": commit_sha,
"author_name": author_name,
"diff": final_code_escaped,
}
)
except requests.RequestException as e:
print(f"Error fetching data from GitLab: {e}")

View File

@ -23,7 +23,7 @@ parameters:
form: llm
- name: repository
type: string
required: false
required: true
label:
en_US: repository
zh_Hans: 仓库路径
@ -32,16 +32,16 @@ parameters:
zh_Hans: 仓库路径以namespace/project_name的形式。
llm_description: Repository path for GitLab, like namespace/project_name.
form: llm
- name: project
- name: branch
type: string
required: false
label:
en_US: project
zh_Hans: 项目
en_US: branch
zh_Hans: 分支
human_description:
en_US: project
zh_Hans: 项目
llm_description: project for GitLab
en_US: branch
zh_Hans: 分支
llm_description: branch for GitLab
form: llm
- name: start_time
type: string

View File

@ -0,0 +1,78 @@
import urllib.parse
from typing import Any, Union
import requests
from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool
class GitlabMergeRequestsTool(BuiltinTool):
def _invoke(
self, user_id: str, tool_parameters: dict[str, Any]
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
repository = tool_parameters.get("repository", "")
branch = tool_parameters.get("branch", "")
start_time = tool_parameters.get("start_time", "")
end_time = tool_parameters.get("end_time", "")
state = tool_parameters.get("state", "opened") # Default to "opened"
if not repository:
return self.create_text_message("Repository is required")
access_token = self.runtime.credentials.get("access_tokens")
site_url = self.runtime.credentials.get("site_url")
if not access_token:
return self.create_text_message("Gitlab API Access Tokens is required.")
if not site_url:
site_url = "https://gitlab.com"
# Get merge requests
result = self.get_merge_requests(site_url, access_token, repository, branch, start_time, end_time, state)
return [self.create_json_message(item) for item in result]
def get_merge_requests(
self, site_url: str, access_token: str, repository: str, branch: str, start_time: str, end_time: str, state: str
) -> list[dict[str, Any]]:
domain = site_url
headers = {"PRIVATE-TOKEN": access_token}
results = []
try:
# URL encode the repository path
encoded_repository = urllib.parse.quote(repository, safe="")
merge_requests_url = f"{domain}/api/v4/projects/{encoded_repository}/merge_requests"
params = {"state": state}
# Add time filters if provided
if start_time:
params["created_after"] = start_time
if end_time:
params["created_before"] = end_time
response = requests.get(merge_requests_url, headers=headers, params=params)
response.raise_for_status()
merge_requests = response.json()
for mr in merge_requests:
# Filter by target branch
if branch and mr["target_branch"] != branch:
continue
results.append(
{
"id": mr["id"],
"title": mr["title"],
"author": mr["author"]["name"],
"web_url": mr["web_url"],
"target_branch": mr["target_branch"],
"created_at": mr["created_at"],
"state": mr["state"],
}
)
except requests.RequestException as e:
print(f"Error fetching merge requests from GitLab: {e}")
return results

View File

@ -0,0 +1,77 @@
identity:
name: gitlab_mergerequests
author: Leo.Wang
label:
en_US: GitLab Merge Requests
zh_Hans: GitLab 合并请求查询
description:
human:
en_US: A tool for query GitLab merge requests, Input should be a exists reposity or branch.
zh_Hans: 一个用于查询 GitLab 代码合并请求的工具,输入的内容应该是一个已存在的仓库名或者分支。
llm: A tool for query GitLab merge requests, Input should be a exists reposity or branch.
parameters:
- name: repository
type: string
required: false
label:
en_US: repository
zh_Hans: 仓库路径
human_description:
en_US: repository
zh_Hans: 仓库路径以namespace/project_name的形式。
llm_description: Repository path for GitLab, like namespace/project_name.
form: llm
- name: branch
type: string
required: false
label:
en_US: branch
zh_Hans: 分支名
human_description:
en_US: branch
zh_Hans: 分支名
llm_description: branch for GitLab
form: llm
- name: start_time
type: string
required: false
label:
en_US: start_time
zh_Hans: 开始时间
human_description:
en_US: start_time
zh_Hans: 开始时间
llm_description: Start time for GitLab
form: llm
- name: end_time
type: string
required: false
label:
en_US: end_time
zh_Hans: 结束时间
human_description:
en_US: end_time
zh_Hans: 结束时间
llm_description: End time for GitLab
form: llm
- name: state
type: select
required: false
options:
- value: opened
label:
en_US: opened
zh_Hans: 打开
- value: closed
label:
en_US: closed
zh_Hans: 关闭
default: opened
label:
en_US: state
zh_Hans: 变更状态
human_description:
en_US: state
zh_Hans: 变更状态
llm_description: Merge request state type for GitLab
form: llm

View File

@ -0,0 +1,81 @@
import urllib.parse
from typing import Any, Union
import requests
from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool
class GitlabProjectsTool(BuiltinTool):
def _invoke(
self, user_id: str, tool_parameters: dict[str, Any]
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
project_name = tool_parameters.get("project_name", "")
page = tool_parameters.get("page", 1)
page_size = tool_parameters.get("page_size", 20)
access_token = self.runtime.credentials.get("access_tokens")
site_url = self.runtime.credentials.get("site_url")
if not access_token:
return self.create_text_message("Gitlab API Access Tokens is required.")
if not site_url:
site_url = "https://gitlab.com"
# Get project content
result = self.fetch_projects(site_url, access_token, project_name, page, page_size)
return [self.create_json_message(item) for item in result]
def fetch_projects(
self,
site_url: str,
access_token: str,
project_name: str,
page: str,
page_size: str,
) -> list[dict[str, Any]]:
domain = site_url
headers = {"PRIVATE-TOKEN": access_token}
results = []
try:
if project_name:
# URL encode the project name for the search query
encoded_project_name = urllib.parse.quote(project_name, safe="")
projects_url = (
f"{domain}/api/v4/projects?search={encoded_project_name}&page={page}&per_page={page_size}"
)
else:
projects_url = f"{domain}/api/v4/projects?page={page}&per_page={page_size}"
response = requests.get(projects_url, headers=headers)
response.raise_for_status()
projects = response.json()
for project in projects:
# Filter projects by exact name match if necessary
if project_name and project["name"].lower() == project_name.lower():
results.append(
{
"id": project["id"],
"name": project["name"],
"description": project.get("description", ""),
"web_url": project["web_url"],
}
)
elif not project_name:
# If no specific project name is provided, add all projects
results.append(
{
"id": project["id"],
"name": project["name"],
"description": project.get("description", ""),
"web_url": project["web_url"],
}
)
except requests.RequestException as e:
print(f"Error fetching data from GitLab: {e}")
return results

View File

@ -0,0 +1,45 @@
identity:
name: gitlab_projects
author: Leo.Wang
label:
en_US: GitLab Projects
zh_Hans: GitLab 项目列表查询
description:
human:
en_US: A tool for query GitLab projects, Input should be a project name.
zh_Hans: 一个用于查询 GitLab 项目列表的工具,输入的内容应该是一个项目名称。
llm: A tool for query GitLab projects, Input should be a project name.
parameters:
- name: project_name
type: string
required: false
label:
en_US: project_name
zh_Hans: 项目名称
human_description:
en_US: project_name
zh_Hans: 项目名称
llm_description: Project name for GitLab
form: llm
- name: page
type: string
required: false
label:
en_US: page
zh_Hans: 页码
human_description:
en_US: page
zh_Hans: 页码
llm_description: Page index for GitLab
form: llm
- name: page_size
type: string
required: false
label:
en_US: page_size
zh_Hans: 每页数量
human_description:
en_US: page_size
zh_Hans: 每页数量
llm_description: Page size for GitLab
form: llm

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

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

View File

@ -0,0 +1,36 @@
identity:
author: Doug Lea
name: lark_base
label:
en_US: Lark Base
zh_Hans: Lark 多维表格
description:
en_US: |
Lark base, requires the following permissions: bitable:app.
zh_Hans: |
Lark 多维表格,需要开通以下权限: bitable:app。
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 Lark app id
zh_Hans: 请输入你的 Lark app id
help:
en_US: Get your app_id and app_secret from Lark
zh_Hans: 从 Lark 获取您的 app_id 和 app_secret
url: https://open.larksuite.com/app
app_secret:
type: secret-input
required: true
label:
en_US: APP Secret
placeholder:
en_US: Please input your app secret
zh_Hans: 请输入你的 Lark app secret

View File

@ -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.lark_api_utils import LarkRequest
class AddRecordsTool(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 = LarkRequest(app_id, app_secret)
app_token = tool_parameters.get("app_token")
table_id = tool_parameters.get("table_id")
table_name = tool_parameters.get("table_name")
records = tool_parameters.get("records")
user_id_type = tool_parameters.get("user_id_type", "open_id")
res = client.add_records(app_token, table_id, table_name, records, user_id_type)
return self.create_json_message(res)

View File

@ -0,0 +1,91 @@
identity:
name: add_records
author: Doug Lea
label:
en_US: Add Records
zh_Hans: 新增多条记录
description:
human:
en_US: Add Multiple Records to Multidimensional Table
zh_Hans: 在多维表格数据表中新增多条记录
llm: A tool for adding multiple records to a multidimensional table. (在多维表格数据表中新增多条记录)
parameters:
- name: app_token
type: string
required: true
label:
en_US: app_token
zh_Hans: app_token
human_description:
en_US: Unique identifier for the multidimensional table, supports inputting document URL.
zh_Hans: 多维表格的唯一标识符,支持输入文档 URL。
llm_description: 多维表格的唯一标识符,支持输入文档 URL。
form: llm
- name: table_id
type: string
required: false
label:
en_US: table_id
zh_Hans: table_id
human_description:
en_US: Unique identifier for the multidimensional table data, either table_id or table_name must be provided, cannot be empty simultaneously.
zh_Hans: 多维表格数据表的唯一标识符table_id 和 table_name 至少需要提供一个,不能同时为空。
llm_description: 多维表格数据表的唯一标识符table_id 和 table_name 至少需要提供一个,不能同时为空。
form: llm
- name: table_name
type: string
required: false
label:
en_US: table_name
zh_Hans: table_name
human_description:
en_US: Name of the multidimensional table data, either table_name or table_id must be provided, cannot be empty simultaneously.
zh_Hans: 多维表格数据表的名称table_name 和 table_id 至少需要提供一个,不能同时为空。
llm_description: 多维表格数据表的名称table_name 和 table_id 至少需要提供一个,不能同时为空。
form: llm
- name: records
type: string
required: true
label:
en_US: records
zh_Hans: 记录列表
human_description:
en_US: |
List of records to be added in this request. Example value: [{"multi-line-text":"text content","single_select":"option 1","date":1674206443000}]
For supported field types, refer to the integration guide (https://open.larkoffice.com/document/server-docs/docs/bitable-v1/notification). For data structures of different field types, refer to the data structure overview (https://open.larkoffice.com/document/server-docs/docs/bitable-v1/bitable-structure).
zh_Hans: |
本次请求将要新增的记录列表,示例值:[{"多行文本":"文本内容","单选":"选项 1","日期":1674206443000}]。
当前接口支持的字段类型请参考接入指南(https://open.larkoffice.com/document/server-docs/docs/bitable-v1/notification),不同类型字段的数据结构请参考数据结构概述(https://open.larkoffice.com/document/server-docs/docs/bitable-v1/bitable-structure)。
llm_description: |
本次请求将要新增的记录列表,示例值:[{"多行文本":"文本内容","单选":"选项 1","日期":1674206443000}]。
当前接口支持的字段类型请参考接入指南(https://open.larkoffice.com/document/server-docs/docs/bitable-v1/notification),不同类型字段的数据结构请参考数据结构概述(https://open.larkoffice.com/document/server-docs/docs/bitable-v1/bitable-structure)。
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

View File

@ -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.lark_api_utils import LarkRequest
class CreateBaseTool(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 = LarkRequest(app_id, app_secret)
name = tool_parameters.get("name")
folder_token = tool_parameters.get("folder_token")
res = client.create_base(name, folder_token)
return self.create_json_message(res)

View File

@ -0,0 +1,42 @@
identity:
name: create_base
author: Doug Lea
label:
en_US: Create Base
zh_Hans: 创建多维表格
description:
human:
en_US: Create Multidimensional Table in Specified Directory
zh_Hans: 在指定目录下创建多维表格
llm: A tool for creating a multidimensional table in a specified directory. (在指定目录下创建多维表格)
parameters:
- name: name
type: string
required: false
label:
en_US: name
zh_Hans: 多维表格 App 名字
human_description:
en_US: |
Name of the multidimensional table App. Example value: "A new multidimensional table".
zh_Hans: 多维表格 App 名字,示例值:"一篇新的多维表格"。
llm_description: 多维表格 App 名字,示例值:"一篇新的多维表格"。
form: llm
- name: folder_token
type: string
required: false
label:
en_US: folder_token
zh_Hans: 多维表格 App 归属文件夹
human_description:
en_US: |
Folder where the multidimensional table App belongs. Default is empty, meaning the table will be created in the root directory of the cloud space. Example values: Lf8uf6BoAlWkUfdGtpMjUV0PpZd or https://lark-japan.jp.larksuite.com/drive/folder/Lf8uf6BoAlWkUfdGtpMjUV0PpZd.
The folder_token must be an existing folder and supports inputting folder token or folder URL.
zh_Hans: |
多维表格 App 归属文件夹。默认为空,表示多维表格将被创建在云空间根目录。示例值: Lf8uf6BoAlWkUfdGtpMjUV0PpZd 或者 https://lark-japan.jp.larksuite.com/drive/folder/Lf8uf6BoAlWkUfdGtpMjUV0PpZd。
folder_token 必须是已存在的文件夹,支持输入文件夹 token 或者文件夹 URL。
llm_description: |
多维表格 App 归属文件夹。默认为空,表示多维表格将被创建在云空间根目录。示例值: Lf8uf6BoAlWkUfdGtpMjUV0PpZd 或者 https://lark-japan.jp.larksuite.com/drive/folder/Lf8uf6BoAlWkUfdGtpMjUV0PpZd。
folder_token 必须是已存在的文件夹,支持输入文件夹 token 或者文件夹 URL。
form: llm

View File

@ -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.lark_api_utils import LarkRequest
class CreateTableTool(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 = LarkRequest(app_id, app_secret)
app_token = tool_parameters.get("app_token")
table_name = tool_parameters.get("table_name")
default_view_name = tool_parameters.get("default_view_name")
fields = tool_parameters.get("fields")
res = client.create_table(app_token, table_name, default_view_name, fields)
return self.create_json_message(res)

View File

@ -0,0 +1,61 @@
identity:
name: create_table
author: Doug Lea
label:
en_US: Create Table
zh_Hans: 新增数据表
description:
human:
en_US: Add a Data Table to Multidimensional Table
zh_Hans: 在多维表格中新增一个数据表
llm: A tool for adding a data table to a multidimensional table. (在多维表格中新增一个数据表)
parameters:
- name: app_token
type: string
required: true
label:
en_US: app_token
zh_Hans: app_token
human_description:
en_US: Unique identifier for the multidimensional table, supports inputting document URL.
zh_Hans: 多维表格的唯一标识符,支持输入文档 URL。
llm_description: 多维表格的唯一标识符,支持输入文档 URL。
form: llm
- name: table_name
type: string
required: true
label:
en_US: Table Name
zh_Hans: 数据表名称
human_description:
en_US: |
The name of the data table, length range: 1 character to 100 characters.
zh_Hans: 数据表名称长度范围1 字符 100 字符。
llm_description: 数据表名称长度范围1 字符 100 字符。
form: llm
- name: default_view_name
type: string
required: false
label:
en_US: Default View Name
zh_Hans: 默认表格视图的名称
human_description:
en_US: The name of the default table view, defaults to "Table" if not filled.
zh_Hans: 默认表格视图的名称,不填则默认为"表格"。
llm_description: 默认表格视图的名称,不填则默认为"表格"。
form: llm
- name: fields
type: string
required: true
label:
en_US: Initial Fields
zh_Hans: 初始字段
human_description:
en_US: |
Initial fields of the data table, format: [ { "field_name": "Multi-line Text","type": 1 },{ "field_name": "Number","type": 2 },{ "field_name": "Single Select","type": 3 },{ "field_name": "Multiple Select","type": 4 },{ "field_name": "Date","type": 5 } ]. For field details, refer to: https://open.larkoffice.com/document/server-docs/docs/bitable-v1/app-table-field/guide
zh_Hans: 数据表的初始字段,格式为:[{"field_name":"多行文本","type":1},{"field_name":"数字","type":2},{"field_name":"单选","type":3},{"field_name":"多选","type":4},{"field_name":"日期","type":5}]。字段详情参考https://open.larkoffice.com/document/server-docs/docs/bitable-v1/app-table-field/guide
llm_description: 数据表的初始字段,格式为:[{"field_name":"多行文本","type":1},{"field_name":"数字","type":2},{"field_name":"单选","type":3},{"field_name":"多选","type":4},{"field_name":"日期","type":5}]。字段详情参考https://open.larkoffice.com/document/server-docs/docs/bitable-v1/app-table-field/guide
form: llm

View File

@ -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.lark_api_utils import LarkRequest
class DeleteRecordsTool(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 = LarkRequest(app_id, app_secret)
app_token = tool_parameters.get("app_token")
table_id = tool_parameters.get("table_id")
table_name = tool_parameters.get("table_name")
record_ids = tool_parameters.get("record_ids")
res = client.delete_records(app_token, table_id, table_name, record_ids)
return self.create_json_message(res)

View File

@ -0,0 +1,86 @@
identity:
name: delete_records
author: Doug Lea
label:
en_US: Delete Records
zh_Hans: 删除多条记录
description:
human:
en_US: Delete Multiple Records from Multidimensional Table
zh_Hans: 删除多维表格数据表中的多条记录
llm: A tool for deleting multiple records from a multidimensional table. (删除多维表格数据表中的多条记录)
parameters:
- name: app_token
type: string
required: true
label:
en_US: app_token
zh_Hans: app_token
human_description:
en_US: Unique identifier for the multidimensional table, supports inputting document URL.
zh_Hans: 多维表格的唯一标识符,支持输入文档 URL。
llm_description: 多维表格的唯一标识符,支持输入文档 URL。
form: llm
- name: table_id
type: string
required: false
label:
en_US: table_id
zh_Hans: table_id
human_description:
en_US: Unique identifier for the multidimensional table data, either table_id or table_name must be provided, cannot be empty simultaneously.
zh_Hans: 多维表格数据表的唯一标识符table_id 和 table_name 至少需要提供一个,不能同时为空。
llm_description: 多维表格数据表的唯一标识符table_id 和 table_name 至少需要提供一个,不能同时为空。
form: llm
- name: table_name
type: string
required: false
label:
en_US: table_name
zh_Hans: table_name
human_description:
en_US: Name of the multidimensional table data, either table_name or table_id must be provided, cannot be empty simultaneously.
zh_Hans: 多维表格数据表的名称table_name 和 table_id 至少需要提供一个,不能同时为空。
llm_description: 多维表格数据表的名称table_name 和 table_id 至少需要提供一个,不能同时为空。
form: llm
- name: record_ids
type: string
required: true
label:
en_US: Record IDs
zh_Hans: 记录 ID 列表
human_description:
en_US: |
List of IDs for the records to be deleted, example value: ["recwNXzPQv"].
zh_Hans: 删除的多条记录 ID 列表,示例值:["recwNXzPQv"]。
llm_description: 删除的多条记录 ID 列表,示例值:["recwNXzPQv"]。
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

View File

@ -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.lark_api_utils import LarkRequest
class DeleteTablesTool(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 = LarkRequest(app_id, app_secret)
app_token = tool_parameters.get("app_token")
table_ids = tool_parameters.get("table_ids")
table_names = tool_parameters.get("table_names")
res = client.delete_tables(app_token, table_ids, table_names)
return self.create_json_message(res)

View File

@ -0,0 +1,49 @@
identity:
name: delete_tables
author: Doug Lea
label:
en_US: Delete Tables
zh_Hans: 删除数据表
description:
human:
en_US: Batch Delete Data Tables from Multidimensional Table
zh_Hans: 批量删除多维表格中的数据表
llm: A tool for batch deleting data tables from a multidimensional table. (批量删除多维表格中的数据表)
parameters:
- name: app_token
type: string
required: true
label:
en_US: app_token
zh_Hans: app_token
human_description:
en_US: Unique identifier for the multidimensional table, supports inputting document URL.
zh_Hans: 多维表格的唯一标识符,支持输入文档 URL。
llm_description: 多维表格的唯一标识符,支持输入文档 URL。
form: llm
- name: table_ids
type: string
required: false
label:
en_US: Table IDs
zh_Hans: 数据表 ID
human_description:
en_US: |
IDs of the tables to be deleted. Each operation supports deleting up to 50 tables. Example: ["tbl1TkhyTWDkSoZ3"]. Ensure that either table_ids or table_names is not empty.
zh_Hans: 待删除的数据表的 ID每次操作最多支持删除 50 个数据表。示例值:["tbl1TkhyTWDkSoZ3"]。请确保 table_ids 和 table_names 至少有一个不为空。
llm_description: 待删除的数据表的 ID每次操作最多支持删除 50 个数据表。示例值:["tbl1TkhyTWDkSoZ3"]。请确保 table_ids 和 table_names 至少有一个不为空。
form: llm
- name: table_names
type: string
required: false
label:
en_US: Table Names
zh_Hans: 数据表名称
human_description:
en_US: |
Names of the tables to be deleted. Each operation supports deleting up to 50 tables. Example: ["Table1", "Table2"]. Ensure that either table_names or table_ids is not empty.
zh_Hans: 待删除的数据表的名称,每次操作最多支持删除 50 个数据表。示例值:["数据表1", "数据表2"]。请确保 table_names 和 table_ids 至少有一个不为空。
llm_description: 待删除的数据表的名称,每次操作最多支持删除 50 个数据表。示例值:["数据表1", "数据表2"]。请确保 table_names 和 table_ids 至少有一个不为空。
form: llm

View File

@ -0,0 +1,17 @@
from typing import Any
from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool
from core.tools.utils.lark_api_utils import LarkRequest
class GetBaseInfoTool(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 = LarkRequest(app_id, app_secret)
app_token = tool_parameters.get("app_token")
res = client.get_base_info(app_token)
return self.create_json_message(res)

View File

@ -0,0 +1,23 @@
identity:
name: get_base_info
author: Doug Lea
label:
en_US: Get Base Info
zh_Hans: 获取多维表格元数据
description:
human:
en_US: Get Metadata Information of Specified Multidimensional Table
zh_Hans: 获取指定多维表格的元数据信息
llm: A tool for getting metadata information of a specified multidimensional table. (获取指定多维表格的元数据信息)
parameters:
- name: app_token
type: string
required: true
label:
en_US: app_token
zh_Hans: app_token
human_description:
en_US: Unique identifier for the multidimensional table, supports inputting document URL.
zh_Hans: 多维表格的唯一标识符,支持输入文档 URL。
llm_description: 多维表格的唯一标识符,支持输入文档 URL。
form: llm

View File

@ -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.lark_api_utils import LarkRequest
class ListTablesTool(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 = LarkRequest(app_id, app_secret)
app_token = tool_parameters.get("app_token")
page_token = tool_parameters.get("page_token")
page_size = tool_parameters.get("page_size", 20)
res = client.list_tables(app_token, page_token, page_size)
return self.create_json_message(res)

View File

@ -0,0 +1,50 @@
identity:
name: list_tables
author: Doug Lea
label:
en_US: List Tables
zh_Hans: 列出数据表
description:
human:
en_US: Get All Data Tables under Multidimensional Table
zh_Hans: 获取多维表格下的所有数据表
llm: A tool for getting all data tables under a multidimensional table. (获取多维表格下的所有数据表)
parameters:
- name: app_token
type: string
required: true
label:
en_US: app_token
zh_Hans: app_token
human_description:
en_US: Unique identifier for the multidimensional table, supports inputting document URL.
zh_Hans: 多维表格的唯一标识符,支持输入文档 URL。
llm_description: 多维表格的唯一标识符,支持输入文档 URL。
form: llm
- name: page_size
type: number
required: false
default: 20
label:
en_US: page_size
zh_Hans: 分页大小
human_description:
en_US: |
Page size, default value: 20, maximum value: 100.
zh_Hans: 分页大小默认值20最大值100。
llm_description: 分页大小默认值20最大值100。
form: form
- name: page_token
type: string
required: false
label:
en_US: page_token
zh_Hans: 分页标记
human_description:
en_US: |
Page token, leave empty for the first request to start from the beginning; a new page_token will be returned if there are more items in the paginated query results, which can be used for the next traversal. Example value: "tblsRc9GRRXKqhvW".
zh_Hans: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token下次遍历可采用该 page_token 获取查询结果。示例值:"tblsRc9GRRXKqhvW"。
llm_description: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token下次遍历可采用该 page_token 获取查询结果。示例值:"tblsRc9GRRXKqhvW"。
form: llm

View File

@ -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.lark_api_utils import LarkRequest
class ReadRecordsTool(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 = LarkRequest(app_id, app_secret)
app_token = tool_parameters.get("app_token")
table_id = tool_parameters.get("table_id")
table_name = tool_parameters.get("table_name")
record_ids = tool_parameters.get("record_ids")
user_id_type = tool_parameters.get("user_id_type", "open_id")
res = client.read_records(app_token, table_id, table_name, record_ids, user_id_type)
return self.create_json_message(res)

View File

@ -0,0 +1,86 @@
identity:
name: read_records
author: Doug Lea
label:
en_US: Read Records
zh_Hans: 批量获取记录
description:
human:
en_US: Batch Retrieve Records from Multidimensional Table
zh_Hans: 批量获取多维表格数据表中的记录信息
llm: A tool for batch retrieving records from a multidimensional table, supporting up to 100 records per call. (批量获取多维表格数据表中的记录信息,单次调用最多支持查询 100 条记录)
parameters:
- name: app_token
type: string
required: true
label:
en_US: app_token
zh_Hans: app_token
human_description:
en_US: Unique identifier for the multidimensional table, supports inputting document URL.
zh_Hans: 多维表格的唯一标识符,支持输入文档 URL。
llm_description: 多维表格的唯一标识符,支持输入文档 URL。
form: llm
- name: table_id
type: string
required: false
label:
en_US: table_id
zh_Hans: table_id
human_description:
en_US: Unique identifier for the multidimensional table data, either table_id or table_name must be provided, cannot be empty simultaneously.
zh_Hans: 多维表格数据表的唯一标识符table_id 和 table_name 至少需要提供一个,不能同时为空。
llm_description: 多维表格数据表的唯一标识符table_id 和 table_name 至少需要提供一个,不能同时为空。
form: llm
- name: table_name
type: string
required: false
label:
en_US: table_name
zh_Hans: table_name
human_description:
en_US: Name of the multidimensional table data, either table_name or table_id must be provided, cannot be empty simultaneously.
zh_Hans: 多维表格数据表的名称table_name 和 table_id 至少需要提供一个,不能同时为空。
llm_description: 多维表格数据表的名称table_name 和 table_id 至少需要提供一个,不能同时为空。
form: llm
- name: record_ids
type: string
required: true
label:
en_US: record_ids
zh_Hans: 记录 ID 列表
human_description:
en_US: List of record IDs, which can be obtained by calling the "Query Records API".
zh_Hans: 记录 ID 列表,可以通过调用"查询记录接口"获取。
llm_description: 记录 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

View File

@ -0,0 +1,39 @@
from typing import Any
from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool
from core.tools.utils.lark_api_utils import LarkRequest
class SearchRecordsTool(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 = LarkRequest(app_id, app_secret)
app_token = tool_parameters.get("app_token")
table_id = tool_parameters.get("table_id")
table_name = tool_parameters.get("table_name")
view_id = tool_parameters.get("view_id")
field_names = tool_parameters.get("field_names")
sort = tool_parameters.get("sort")
filters = tool_parameters.get("filter")
page_token = tool_parameters.get("page_token")
automatic_fields = tool_parameters.get("automatic_fields", False)
user_id_type = tool_parameters.get("user_id_type", "open_id")
page_size = tool_parameters.get("page_size", 20)
res = client.search_record(
app_token,
table_id,
table_name,
view_id,
field_names,
sort,
filters,
page_token,
automatic_fields,
user_id_type,
page_size,
)
return self.create_json_message(res)

View File

@ -0,0 +1,163 @@
identity:
name: search_records
author: Doug Lea
label:
en_US: Search Records
zh_Hans: 查询记录
description:
human:
en_US: Query records in a multidimensional table, up to 500 rows per query.
zh_Hans: 查询多维表格数据表中的记录,单次最多查询 500 行记录。
llm: A tool for querying records in a multidimensional table, up to 500 rows per query. (查询多维表格数据表中的记录,单次最多查询 500 行记录)
parameters:
- name: app_token
type: string
required: true
label:
en_US: app_token
zh_Hans: app_token
human_description:
en_US: Unique identifier for the multidimensional table, supports inputting document URL.
zh_Hans: 多维表格的唯一标识符,支持输入文档 URL。
llm_description: 多维表格的唯一标识符,支持输入文档 URL。
form: llm
- name: table_id
type: string
required: false
label:
en_US: table_id
zh_Hans: table_id
human_description:
en_US: Unique identifier for the multidimensional table data, either table_id or table_name must be provided, cannot be empty simultaneously.
zh_Hans: 多维表格数据表的唯一标识符table_id 和 table_name 至少需要提供一个,不能同时为空。
llm_description: 多维表格数据表的唯一标识符table_id 和 table_name 至少需要提供一个,不能同时为空。
form: llm
- name: table_name
type: string
required: false
label:
en_US: table_name
zh_Hans: table_name
human_description:
en_US: Name of the multidimensional table data, either table_name or table_id must be provided, cannot be empty simultaneously.
zh_Hans: 多维表格数据表的名称table_name 和 table_id 至少需要提供一个,不能同时为空。
llm_description: 多维表格数据表的名称table_name 和 table_id 至少需要提供一个,不能同时为空。
form: llm
- name: view_id
type: string
required: false
label:
en_US: view_id
zh_Hans: 视图唯一标识
human_description:
en_US: |
Unique identifier for a view in a multidimensional table. It can be found in the URL's query parameter with the key 'view'. For example: https://lark-japan.jp.larksuite.com/base/XXX0bfYEraW5OWsbhcFjEqj6pxh?table=tbl5I6jqwz8wBRMv&view=vewW5zXVEU.
zh_Hans: 多维表格中视图的唯一标识,可在多维表格的 URL 地址栏中找到query 参数中 key 为 view 的部分。例如https://lark-japan.jp.larksuite.com/base/XXX0bfYEraW5OWsbhcFjEqj6pxh?table=tbl5I6jqwz8wBRMv&view=vewW5zXVEU。
llm_description: 多维表格中视图的唯一标识,可在多维表格的 URL 地址栏中找到query 参数中 key 为 view 的部分。例如https://lark-japan.jp.larksuite.com/base/XXX0bfYEraW5OWsbhcFjEqj6pxh?table=tbl5I6jqwz8wBRMv&view=vewW5zXVEU。
form: llm
- name: field_names
type: string
required: false
label:
en_US: field_names
zh_Hans: 字段名称
human_description:
en_US: |
Field names to specify which fields to include in the returned records. Example value: ["Field1", "Field2"].
zh_Hans: 字段名称,用于指定本次查询返回记录中包含的字段。示例值:["字段1","字段2"]。
llm_description: 字段名称,用于指定本次查询返回记录中包含的字段。示例值:["字段1","字段2"]。
form: llm
- name: sort
type: string
required: false
label:
en_US: sort
zh_Hans: 排序条件
human_description:
en_US: |
Sorting conditions, for example: [{"field_name":"Multiline Text","desc":true}].
zh_Hans: 排序条件,例如:[{"field_name":"多行文本","desc":true}]。
llm_description: 排序条件,例如:[{"field_name":"多行文本","desc":true}]。
form: llm
- name: filter
type: string
required: false
label:
en_US: filter
zh_Hans: 筛选条件
human_description:
en_US: Object containing filter information. For details on how to fill in the filter, refer to the record filter parameter guide (https://open.larkoffice.com/document/uAjLw4CM/ukTMukTMukTM/reference/bitable-v1/app-table-record/record-filter-guide).
zh_Hans: 包含条件筛选信息的对象。了解如何填写 filter参考记录筛选参数填写指南(https://open.larkoffice.com/document/uAjLw4CM/ukTMukTMukTM/reference/bitable-v1/app-table-record/record-filter-guide)。
llm_description: 包含条件筛选信息的对象。了解如何填写 filter参考记录筛选参数填写指南(https://open.larkoffice.com/document/uAjLw4CM/ukTMukTMukTM/reference/bitable-v1/app-table-record/record-filter-guide)。
form: llm
- name: automatic_fields
type: boolean
required: false
label:
en_US: automatic_fields
zh_Hans: automatic_fields
human_description:
en_US: Whether to return automatically calculated fields. Default is false, meaning they are not returned.
zh_Hans: 是否返回自动计算的字段。默认为 false表示不返回。
llm_description: 是否返回自动计算的字段。默认为 false表示不返回。
form: form
- 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: page_size
type: number
required: false
default: 20
label:
en_US: page_size
zh_Hans: 分页大小
human_description:
en_US: |
Page size, default value: 20, maximum value: 500.
zh_Hans: 分页大小默认值20最大值500。
llm_description: 分页大小默认值20最大值500。
form: form
- name: page_token
type: string
required: false
label:
en_US: page_token
zh_Hans: 分页标记
human_description:
en_US: |
Page token, leave empty for the first request to start from the beginning; a new page_token will be returned if there are more items in the paginated query results, which can be used for the next traversal. Example value: "tblsRc9GRRXKqhvW".
zh_Hans: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token下次遍历可采用该 page_token 获取查询结果。示例值:"tblsRc9GRRXKqhvW"。
llm_description: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token下次遍历可采用该 page_token 获取查询结果。示例值:"tblsRc9GRRXKqhvW"。
form: llm

View File

@ -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.lark_api_utils import LarkRequest
class UpdateRecordsTool(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 = LarkRequest(app_id, app_secret)
app_token = tool_parameters.get("app_token")
table_id = tool_parameters.get("table_id")
table_name = tool_parameters.get("table_name")
records = tool_parameters.get("records")
user_id_type = tool_parameters.get("user_id_type", "open_id")
res = client.update_records(app_token, table_id, table_name, records, user_id_type)
return self.create_json_message(res)

View File

@ -0,0 +1,91 @@
identity:
name: update_records
author: Doug Lea
label:
en_US: Update Records
zh_Hans: 更新多条记录
description:
human:
en_US: Update Multiple Records in Multidimensional Table
zh_Hans: 更新多维表格数据表中的多条记录
llm: A tool for updating multiple records in a multidimensional table. (更新多维表格数据表中的多条记录)
parameters:
- name: app_token
type: string
required: true
label:
en_US: app_token
zh_Hans: app_token
human_description:
en_US: Unique identifier for the multidimensional table, supports inputting document URL.
zh_Hans: 多维表格的唯一标识符,支持输入文档 URL。
llm_description: 多维表格的唯一标识符,支持输入文档 URL。
form: llm
- name: table_id
type: string
required: false
label:
en_US: table_id
zh_Hans: table_id
human_description:
en_US: Unique identifier for the multidimensional table data, either table_id or table_name must be provided, cannot be empty simultaneously.
zh_Hans: 多维表格数据表的唯一标识符table_id 和 table_name 至少需要提供一个,不能同时为空。
llm_description: 多维表格数据表的唯一标识符table_id 和 table_name 至少需要提供一个,不能同时为空。
form: llm
- name: table_name
type: string
required: false
label:
en_US: table_name
zh_Hans: table_name
human_description:
en_US: Name of the multidimensional table data, either table_name or table_id must be provided, cannot be empty simultaneously.
zh_Hans: 多维表格数据表的名称table_name 和 table_id 至少需要提供一个,不能同时为空。
llm_description: 多维表格数据表的名称table_name 和 table_id 至少需要提供一个,不能同时为空。
form: llm
- name: records
type: string
required: true
label:
en_US: records
zh_Hans: 记录列表
human_description:
en_US: |
List of records to be updated in this request. Example value: [{"fields":{"multi-line-text":"text content","single_select":"option 1","date":1674206443000},"record_id":"recupK4f4RM5RX"}].
For supported field types, refer to the integration guide (https://open.larkoffice.com/document/server-docs/docs/bitable-v1/notification). For data structures of different field types, refer to the data structure overview (https://open.larkoffice.com/document/server-docs/docs/bitable-v1/bitable-structure).
zh_Hans: |
本次请求将要更新的记录列表,示例值:[{"fields":{"多行文本":"文本内容","单选":"选项 1","日期":1674206443000},"record_id":"recupK4f4RM5RX"}]。
当前接口支持的字段类型请参考接入指南(https://open.larkoffice.com/document/server-docs/docs/bitable-v1/notification),不同类型字段的数据结构请参考数据结构概述(https://open.larkoffice.com/document/server-docs/docs/bitable-v1/bitable-structure)。
llm_description: |
本次请求将要更新的记录列表,示例值:[{"fields":{"多行文本":"文本内容","单选":"选项 1","日期":1674206443000},"record_id":"recupK4f4RM5RX"}]。
当前接口支持的字段类型请参考接入指南(https://open.larkoffice.com/document/server-docs/docs/bitable-v1/notification),不同类型字段的数据结构请参考数据结构概述(https://open.larkoffice.com/document/server-docs/docs/bitable-v1/bitable-structure)。
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

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

View File

@ -0,0 +1,36 @@
identity:
author: Doug Lea
name: lark_calendar
label:
en_US: Lark Calendar
zh_Hans: Lark 日历
description:
en_US: |
Lark calendar, requires the following permissions: calendar:calendar:read、calendar:calendar、contact:user.id:readonly.
zh_Hans: |
Lark 日历,需要开通以下权限: 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 Lark app id
zh_Hans: 请输入你的 Lark app id
help:
en_US: Get your app_id and app_secret from Lark
zh_Hans: 从 Lark 获取您的 app_id 和 app_secret
url: https://open.larksuite.com/app
app_secret:
type: secret-input
required: true
label:
en_US: APP Secret
placeholder:
en_US: Please input your app secret
zh_Hans: 请输入你的 Lark app secret

View File

@ -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.lark_api_utils import LarkRequest
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 = LarkRequest(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)

View File

@ -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 Lark. (在 Lark 中添加日程参会人)
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

View File

@ -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.lark_api_utils import LarkRequest
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 = LarkRequest(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)

View File

@ -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 Lark.(创建 Lark 日程)
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

View File

@ -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.lark_api_utils import LarkRequest
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 = LarkRequest(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)

View File

@ -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 Lark.(在 Lark 中删除日程)
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

View File

@ -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.lark_api_utils import LarkRequest
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 = LarkRequest(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)

View File

@ -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 Lark.(在 Lark 中查询主日历信息)
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

View File

@ -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.lark_api_utils import LarkRequest
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 = LarkRequest(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)

View File

@ -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 Lark.(在 Lark 中获取日程列表)
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: form
- 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

View File

@ -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.lark_api_utils import LarkRequest
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 = LarkRequest(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)

View File

@ -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 Lark.(在 Lark 中搜索日程)
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: form
- 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

View File

@ -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.lark_api_utils import LarkRequest
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 = LarkRequest(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)

View File

@ -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 Lark.(更新 Lark 中的日程)
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

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="64px" height="64px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
<g><path style="opacity:1" fill="#fefefe" d="M -0.5,-0.5 C 20.8333,-0.5 42.1667,-0.5 63.5,-0.5C 63.5,20.8333 63.5,42.1667 63.5,63.5C 42.1667,63.5 20.8333,63.5 -0.5,63.5C -0.5,42.1667 -0.5,20.8333 -0.5,-0.5 Z"/></g>
<g><path style="opacity:1" fill="#346df3" d="M 47.5,33.5 C 43.3272,29.8779 38.9939,29.7112 34.5,33C 32.682,35.4897 30.3487,37.3231 27.5,38.5C 23.5003,43.5136 24.167,47.847 29.5,51.5C 24.1563,51.666 18.8229,51.4994 13.5,51C 13,50.5 12.5,50 12,49.5C 11.3333,36.8333 11.3333,24.1667 12,11.5C 12.5,11 13,10.5 13.5,10C 24.1667,9.33333 34.8333,9.33333 45.5,10C 46,10.5 46.5,11 47,11.5C 47.4997,18.8258 47.6663,26.1591 47.5,33.5 Z"/></g>
<g><path style="opacity:1" fill="#f9fafe" d="M 20.5,19.5 C 25.1785,19.3342 29.8452,19.5008 34.5,20C 35.8333,21 35.8333,22 34.5,23C 29.8333,23.6667 25.1667,23.6667 20.5,23C 19.3157,21.8545 19.3157,20.6879 20.5,19.5 Z"/></g>
<g><path style="opacity:1" fill="#f3f6fe" d="M 20.5,27.5 C 22.5273,27.3379 24.5273,27.5045 26.5,28C 27.8333,29 27.8333,30 26.5,31C 24.5,31.6667 22.5,31.6667 20.5,31C 19.3157,29.8545 19.3157,28.6879 20.5,27.5 Z"/></g>
<g><path style="opacity:1" fill="#36d4c1" d="M 47.5,33.5 C 48.7298,35.2972 49.3964,37.2972 49.5,39.5C 51.3904,39.2965 52.8904,39.9632 54,41.5C 55.1825,45.2739 54.3492,48.4406 51.5,51C 44.1742,51.4997 36.8409,51.6663 29.5,51.5C 24.167,47.847 23.5003,43.5136 27.5,38.5C 30.3487,37.3231 32.682,35.4897 34.5,33C 38.9939,29.7112 43.3272,29.8779 47.5,33.5 Z"/></g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

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

View File

@ -0,0 +1,36 @@
identity:
author: Doug Lea
name: lark_document
label:
en_US: Lark Cloud Document
zh_Hans: Lark 云文档
description:
en_US: |
Lark cloud document, requires the following permissions: docx:document、drive:drive、docs:document.content:read.
zh_Hans: |
Lark 云文档,需要开通以下权限: docx:document、drive:drive、docs:document.content:read。
icon: icon.svg
tags:
- social
- productivity
credentials_for_provider:
app_id:
type: text-input
required: true
label:
en_US: APP ID
placeholder:
en_US: Please input your Lark app id
zh_Hans: 请输入你的 Lark app id
help:
en_US: Get your app_id and app_secret from Lark
zh_Hans: 从 Lark 获取您的 app_id 和 app_secret
url: https://open.larksuite.com/app
app_secret:
type: secret-input
required: true
label:
en_US: APP Secret
placeholder:
en_US: Please input your app secret
zh_Hans: 请输入你的 Lark app secret

View File

@ -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.lark_api_utils import LarkRequest
class CreateDocumentTool(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 = LarkRequest(app_id, app_secret)
title = tool_parameters.get("title")
content = tool_parameters.get("content")
folder_token = tool_parameters.get("folder_token")
res = client.create_document(title, content, folder_token)
return self.create_json_message(res)

View File

@ -0,0 +1,48 @@
identity:
name: create_document
author: Doug Lea
label:
en_US: Create Lark document
zh_Hans: 创建 Lark 文档
description:
human:
en_US: Create Lark document
zh_Hans: 创建 Lark 文档,支持创建空文档和带内容的文档,支持 markdown 语法创建。应用需要开启机器人能力(https://open.larksuite.com/document/faq/trouble-shooting/how-to-enable-bot-ability)。
llm: A tool for creating Lark documents.
parameters:
- name: title
type: string
required: false
label:
en_US: Document title
zh_Hans: 文档标题
human_description:
en_US: Document title, only supports plain text content.
zh_Hans: 文档标题,只支持纯文本内容。
llm_description: 文档标题,只支持纯文本内容,可以为空。
form: llm
- name: content
type: string
required: false
label:
en_US: Document content
zh_Hans: 文档内容
human_description:
en_US: Document content, supports markdown syntax, can be empty.
zh_Hans: 文档内容,支持 markdown 语法,可以为空。
llm_description: 文档内容,支持 markdown 语法,可以为空。
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 where the document is located. If it is not passed or is empty, it means the root directory. For Example: https://lark-japan.jp.larksuite.com/drive/folder/Lf8uf6BoAlWkUfdGtpMjUV0PpZd
zh_Hans: 文档所在文件夹的 Token不传或传空表示根目录。例如https://lark-japan.jp.larksuite.com/drive/folder/Lf8uf6BoAlWkUfdGtpMjUV0PpZd。
llm_description: 文档所在文件夹的 Token不传或传空表示根目录。例如https://lark-japan.jp.larksuite.com/drive/folder/Lf8uf6BoAlWkUfdGtpMjUV0PpZd。
form: llm

View File

@ -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.lark_api_utils import LarkRequest
class GetDocumentRawContentTool(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 = LarkRequest(app_id, app_secret)
document_id = tool_parameters.get("document_id")
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)

View File

@ -0,0 +1,70 @@
identity:
name: get_document_content
author: Doug Lea
label:
en_US: Get Lark Cloud Document Content
zh_Hans: 获取 Lark 云文档的内容
description:
human:
en_US: Get lark cloud document content
zh_Hans: 获取 Lark 云文档的内容
llm: A tool for retrieving content from Lark cloud documents.
parameters:
- name: document_id
type: string
required: true
label:
en_US: document_id
zh_Hans: Lark 文档的唯一标识
human_description:
en_US: Unique identifier for a Lark document. You can also input the document's URL.
zh_Hans: Lark 文档的唯一标识,支持输入文档的 URL。
llm_description: Lark 文档的唯一标识,支持输入文档的 URL。
form: llm
- name: mode
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: 文档返回格式
human_description:
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: form
- name: lang
type: select
required: false
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: form

View File

@ -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.lark_api_utils import LarkRequest
class ListDocumentBlockTool(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 = LarkRequest(app_id, app_secret)
document_id = tool_parameters.get("document_id")
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, user_id_type, page_size)
return self.create_json_message(res)

View File

@ -0,0 +1,74 @@
identity:
name: list_document_blocks
author: Doug Lea
label:
en_US: List Lark Document Blocks
zh_Hans: 获取 Lark 文档所有块
description:
human:
en_US: List lark document blocks
zh_Hans: 获取 Lark 文档所有块的富文本内容并分页返回
llm: A tool to get all blocks of Lark documents
parameters:
- name: document_id
type: string
required: true
label:
en_US: document_id
zh_Hans: Lark 文档的唯一标识
human_description:
en_US: Unique identifier for a Lark document. You can also input the document's URL.
zh_Hans: Lark 文档的唯一标识,支持输入文档的 URL。
llm_description: Lark 文档的唯一标识,支持输入文档的 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
- name: page_size
type: number
required: false
default: 500
label:
en_US: page_size
zh_Hans: 分页大小
human_description:
en_US: Paging size, the default and maximum value is 500.
zh_Hans: 分页大小, 默认值和最大值为 500。
llm_description: 分页大小, 表示一次请求最多返回多少条数据,默认值和最大值为 500。
form: form
- name: page_token
type: string
required: false
label:
en_US: page_token
zh_Hans: 分页标记
human_description:
en_US: Pagination token used to navigate through query results, allowing retrieval of additional items in subsequent requests.
zh_Hans: 分页标记,用于分页查询结果,以便下次遍历时获取更多项。
llm_description: 分页标记,第一次请求不填,表示从头开始遍历;分页查询结果还有更多项时会同时返回新的 page_token下次遍历可采用该 page_token 获取查询结果。
form: llm

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