mirror of
https://github.com/langgenius/dify-plugin-sdks.git
synced 2026-08-26 18:56:41 -04:00
feat(oauth): implement OAuth
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
INSTALL_METHOD=remote
|
||||
REMOTE_INSTALL_HOST=debug-plugin.dify.dev
|
||||
REMOTE_INSTALL_PORT=5003
|
||||
REMOTE_INSTALL_KEY=********-****-****-****-************
|
||||
@@ -0,0 +1,37 @@
|
||||
# GitHub
|
||||
|
||||
## Overview
|
||||
|
||||
GitHub is a web-based platform for version control and collaboration, primarily used for software development. As a tool in Dify, it provides users the ability to search repositories by keywords.
|
||||
|
||||
## Configuration
|
||||
|
||||
### 1. Apply for API Key and Version
|
||||
|
||||
Please apply for an [API Key](https://github.com/settings/personal-access-tokens) and the [API version](https://docs.github.com/en/rest/about-the-rest-api/api-versions?apiVersion=2022-11-28).
|
||||
|
||||
### 2. Get GitHub tools from Plugin Marketplace
|
||||
|
||||
The GitHub tools can be found in the Plugin Marketplace. Please install it first.
|
||||
|
||||
### 3. Fill in the configuration in Dify
|
||||
|
||||
On the Dify navigation page, click `Tools > GitHub > Authorize` and fill in the API Key.
|
||||
|
||||

|
||||
|
||||
### 4. Using the tool
|
||||
|
||||
You can use the GitHub tool in the following application types:
|
||||
|
||||
#### Chatflow / Workflow applications
|
||||
|
||||
Both Chatflow and Workflow applications support adding a GitHub tool node.
|
||||
|
||||

|
||||
|
||||
#### Agent applications
|
||||
|
||||
Add the GitHub tool in the Agent application, then enter repository search instructions to call this tool.
|
||||
|
||||

|
||||
Binary file not shown.
|
After Width: | Height: | Size: 193 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 163 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 279 KiB |
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="800px" height="800px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>github [#142]</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
</defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Dribbble-Light-Preview" transform="translate(-140.000000, -7559.000000)" fill="#000000">
|
||||
<g id="icons" transform="translate(56.000000, 160.000000)">
|
||||
<path d="M94,7399 C99.523,7399 104,7403.59 104,7409.253 C104,7413.782 101.138,7417.624 97.167,7418.981 C96.66,7419.082 96.48,7418.762 96.48,7418.489 C96.48,7418.151 96.492,7417.047 96.492,7415.675 C96.492,7414.719 96.172,7414.095 95.813,7413.777 C98.04,7413.523 100.38,7412.656 100.38,7408.718 C100.38,7407.598 99.992,7406.684 99.35,7405.966 C99.454,7405.707 99.797,7404.664 99.252,7403.252 C99.252,7403.252 98.414,7402.977 96.505,7404.303 C95.706,7404.076 94.85,7403.962 94,7403.958 C93.15,7403.962 92.295,7404.076 91.497,7404.303 C89.586,7402.977 88.746,7403.252 88.746,7403.252 C88.203,7404.664 88.546,7405.707 88.649,7405.966 C88.01,7406.684 87.619,7407.598 87.619,7408.718 C87.619,7412.646 89.954,7413.526 92.175,7413.785 C91.889,7414.041 91.63,7414.493 91.54,7415.156 C90.97,7415.418 89.522,7415.871 88.63,7414.304 C88.63,7414.304 88.101,7413.319 87.097,7413.247 C87.097,7413.247 86.122,7413.234 87.029,7413.87 C87.029,7413.87 87.684,7414.185 88.139,7415.37 C88.139,7415.37 88.726,7417.2 91.508,7416.58 C91.513,7417.437 91.522,7418.245 91.522,7418.489 C91.522,7418.76 91.338,7419.077 90.839,7418.982 C86.865,7417.627 84,7413.783 84,7409.253 C84,7403.59 88.478,7399 94,7399"
|
||||
id="github-[#142]">
|
||||
</path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,6 @@
|
||||
from dify_plugin import DifyPluginEnv, Plugin
|
||||
|
||||
plugin = Plugin(DifyPluginEnv(MAX_REQUEST_TIMEOUT=120))
|
||||
|
||||
if __name__ == "__main__":
|
||||
plugin.run()
|
||||
@@ -0,0 +1,37 @@
|
||||
author: langgenius
|
||||
created_at: '2024-09-20T08:03:44.658609186Z'
|
||||
description:
|
||||
en_US: GitHub is an online software source code hosting service.
|
||||
pt_BR: GitHub é uma plataforma online para serviços de hospedagem de código fonte
|
||||
de software.
|
||||
zh_Hans: GitHub是一个在线软件源代码托管服务平台。
|
||||
icon: icon.svg
|
||||
label:
|
||||
en_US: GitHub
|
||||
pt_BR: GitHub
|
||||
zh_Hans: GitHub
|
||||
meta:
|
||||
arch:
|
||||
- amd64
|
||||
- arm64
|
||||
runner:
|
||||
entrypoint: main
|
||||
language: python
|
||||
version: '3.12'
|
||||
version: 0.0.1
|
||||
name: github
|
||||
plugins:
|
||||
tools:
|
||||
- provider/github.yaml
|
||||
resource:
|
||||
memory: 1048576
|
||||
permission:
|
||||
model:
|
||||
enabled: true
|
||||
llm: true
|
||||
tool:
|
||||
enabled: true
|
||||
tags:
|
||||
- utilities
|
||||
type: plugin
|
||||
version: 0.0.5
|
||||
@@ -0,0 +1,69 @@
|
||||
import secrets
|
||||
import urllib.parse
|
||||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
|
||||
import requests
|
||||
from werkzeug import Request
|
||||
|
||||
from dify_plugin import ToolProvider
|
||||
from dify_plugin.errors.tool import ToolProviderCredentialValidationError
|
||||
|
||||
|
||||
class GithubProvider(ToolProvider):
|
||||
_AUTH_URL = "https://github.com/login/oauth/authorize"
|
||||
_TOKEN_URL = "https://github.com/login/oauth/access_token"
|
||||
_API_USER_URL = "https://api.github.com/user"
|
||||
|
||||
def _oauth_get_authorization_url(self, redirect_uri: str, system_credentials: Mapping[str, Any]) -> str:
|
||||
"""
|
||||
Generate the authorization URL for the Github OAuth.
|
||||
"""
|
||||
state = secrets.token_urlsafe(16)
|
||||
params = {
|
||||
"client_id": system_credentials["client_id"],
|
||||
"redirect_uri": redirect_uri,
|
||||
"scope": system_credentials.get("scope", "read:user"),
|
||||
"state": state,
|
||||
# Optionally: allow_signup, login, etc.
|
||||
}
|
||||
return f"{self._AUTH_URL}?{urllib.parse.urlencode(params)}"
|
||||
|
||||
def _oauth_get_credentials(
|
||||
self, redirect_uri: str, system_credentials: Mapping[str, Any], request: Request
|
||||
) -> Mapping[str, Any]:
|
||||
"""
|
||||
Exchange code for access_token.
|
||||
"""
|
||||
code = request.args.get("code")
|
||||
if not code:
|
||||
raise ValueError("No code provided")
|
||||
# Optionally: validate state here
|
||||
|
||||
data = {
|
||||
"client_id": system_credentials["client_id"],
|
||||
"client_secret": system_credentials["client_secret"],
|
||||
"code": code,
|
||||
"redirect_uri": redirect_uri,
|
||||
}
|
||||
headers = {"Accept": "application/json"}
|
||||
response = requests.post(self._TOKEN_URL, data=data, headers=headers, timeout=10)
|
||||
response_json = response.json()
|
||||
access_token = response_json.get("access_token")
|
||||
if not access_token:
|
||||
raise ValueError(f"Error in GitHub OAuth: {response_json}")
|
||||
return {"access_token": access_token}
|
||||
|
||||
def _validate_credentials(self, credentials: dict) -> None:
|
||||
try:
|
||||
if "access_tokens" not in credentials or not credentials.get("access_tokens"):
|
||||
raise ToolProviderCredentialValidationError("GitHub API Access Token is required.")
|
||||
headers = {
|
||||
"Authorization": f"Bearer {credentials['access_tokens']}",
|
||||
"Accept": "application/vnd.github+json",
|
||||
}
|
||||
response = requests.get(self._API_USER_URL, headers=headers, timeout=10)
|
||||
if response.status_code != 200:
|
||||
raise ToolProviderCredentialValidationError(response.json().get("message"))
|
||||
except Exception as e:
|
||||
raise ToolProviderCredentialValidationError(str(e)) from e
|
||||
@@ -0,0 +1,80 @@
|
||||
credentials_for_provider:
|
||||
access_tokens:
|
||||
help:
|
||||
en_US: Get your Access Tokens from GitHub
|
||||
pt_BR: Obtenha sua chave da API do Google no Google
|
||||
zh_Hans: 从 GitHub 获取您的 Access Tokens
|
||||
label:
|
||||
en_US: Access Tokens
|
||||
pt_BR: Tokens de acesso
|
||||
zh_Hans: Access Tokens
|
||||
placeholder:
|
||||
en_US: Please input your GitHub Access Tokens
|
||||
pt_BR: Insira seus Tokens de Acesso do GitHub
|
||||
zh_Hans: 请输入你的 GitHub Access Tokens
|
||||
required: true
|
||||
type: secret-input
|
||||
url: https://github.com/settings/tokens?type=beta
|
||||
api_version:
|
||||
default: '2022-11-28'
|
||||
help:
|
||||
en_US: Get your API Version from GitHub
|
||||
pt_BR: Obtenha sua versão da API do GitHub
|
||||
zh_Hans: 从 GitHub 获取您的 API Version
|
||||
label:
|
||||
en_US: API Version
|
||||
pt_BR: Versão da API
|
||||
zh_Hans: API Version
|
||||
placeholder:
|
||||
en_US: Please input your GitHub API Version
|
||||
pt_BR: Insira sua versão da API do GitHub
|
||||
zh_Hans: 请输入你的 GitHub API Version
|
||||
required: false
|
||||
type: text-input
|
||||
url: https://docs.github.com/en/rest/about-the-rest-api/api-versions?apiVersion=2022-11-28
|
||||
|
||||
oauth_schema:
|
||||
client_schema:
|
||||
- name: "client_id"
|
||||
type: "secret-input"
|
||||
label:
|
||||
zh_Hans: "Client ID"
|
||||
en_US: "Client ID"
|
||||
- name: "client_secret"
|
||||
type: "secret-input"
|
||||
label:
|
||||
zh_Hans: "Client Secret"
|
||||
en_US: "Client Secret"
|
||||
- name: "redirect_uri"
|
||||
type: "text-input"
|
||||
label:
|
||||
zh_Hans: "Redirect URI"
|
||||
en_US: "Redirect URI"
|
||||
credentials_schema:
|
||||
- name: "access_token"
|
||||
type: "secret-input"
|
||||
label:
|
||||
zh_Hans: "Access Token"
|
||||
en_US: "Access Token"
|
||||
|
||||
extra:
|
||||
python:
|
||||
source: provider/github.py
|
||||
identity:
|
||||
author: CharlieWei
|
||||
description:
|
||||
en_US: GitHub is an online software source code hosting service.
|
||||
pt_BR: GitHub é uma plataforma online para serviços de hospedagem de código fonte
|
||||
de software.
|
||||
zh_Hans: GitHub 是一个在线软件源代码托管服务平台。
|
||||
icon: icon.svg
|
||||
label:
|
||||
en_US: GitHub
|
||||
pt_BR: GitHub
|
||||
zh_Hans: GitHub
|
||||
name: github
|
||||
tags:
|
||||
- utilities
|
||||
tools:
|
||||
- tools/github_repositories.yaml
|
||||
- tools/github_repository_readme.yaml
|
||||
@@ -0,0 +1 @@
|
||||
dify_plugin==0.5.0b3
|
||||
@@ -0,0 +1,86 @@
|
||||
import json
|
||||
from collections.abc import Generator
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
from urllib.parse import quote
|
||||
|
||||
import requests
|
||||
|
||||
from dify_plugin import Tool
|
||||
from dify_plugin.entities.provider_config import CredentialType
|
||||
from dify_plugin.entities.tool import ToolInvokeMessage
|
||||
|
||||
|
||||
class GithubRepositoriesTool(Tool):
|
||||
def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage, None, None]:
|
||||
"""
|
||||
invoke tools
|
||||
"""
|
||||
top_n = tool_parameters.get("top_n", 5)
|
||||
query = tool_parameters.get("query", "")
|
||||
credential_type = self.runtime.credential_type
|
||||
if not query:
|
||||
yield self.create_text_message("Please input symbol")
|
||||
if (
|
||||
credential_type == CredentialType.API_KEY and "access_tokens" not in self.runtime.credentials
|
||||
) or not self.runtime.credentials.get("access_tokens"):
|
||||
yield self.create_text_message("GitHub API Access Tokens is required.")
|
||||
|
||||
if (
|
||||
credential_type == CredentialType.OAUTH and "access_tokens" not in self.runtime.credentials
|
||||
) or not self.runtime.credentials.get("access_tokens"):
|
||||
yield self.create_text_message("GitHub OAuth Access Tokens is required.")
|
||||
|
||||
if "api_version" not in self.runtime.credentials or not self.runtime.credentials.get("api_version"):
|
||||
api_version = "2022-11-28"
|
||||
else:
|
||||
api_version = self.runtime.credentials.get("api_version")
|
||||
|
||||
try:
|
||||
headers = {
|
||||
"Content-Type": "application/vnd.github+json",
|
||||
"Authorization": f"Bearer {self.runtime.credentials.get('access_tokens')}",
|
||||
"X-GitHub-Api-Version": api_version,
|
||||
}
|
||||
s = requests.session()
|
||||
api_domain = "https://api.github.com"
|
||||
response = s.request(
|
||||
method="GET",
|
||||
headers=headers,
|
||||
url=f"{api_domain}/search/repositories?q={quote(query)}&sort=stars&per_page={top_n}&order=desc",
|
||||
)
|
||||
response_data = response.json()
|
||||
if response.status_code == 200 and isinstance(response_data.get("items"), list):
|
||||
contents = []
|
||||
if len(response_data.get("items")) > 0:
|
||||
for item in response_data.get("items"):
|
||||
content = {}
|
||||
updated_at_object = datetime.strptime(item["updated_at"], "%Y-%m-%dT%H:%M:%SZ")
|
||||
content["owner"] = item["owner"]["login"]
|
||||
content["name"] = item["name"]
|
||||
if item["description"] is not None:
|
||||
content["description"] = (
|
||||
item["description"][:100] + "..."
|
||||
if len(item["description"]) > 100
|
||||
else item["description"]
|
||||
)
|
||||
else:
|
||||
content["description"] = ""
|
||||
content["url"] = item["html_url"]
|
||||
content["star"] = item["watchers"]
|
||||
content["forks"] = item["forks"]
|
||||
content["updated"] = updated_at_object.strftime("%Y-%m-%d")
|
||||
contents.append(content)
|
||||
s.close()
|
||||
yield self.create_text_message(
|
||||
self.session.model.summary.invoke(
|
||||
text=json.dumps(contents, ensure_ascii=False),
|
||||
instruction="Summarize the text",
|
||||
)
|
||||
)
|
||||
else:
|
||||
yield self.create_text_message(f"No items related to {query} were found.")
|
||||
else:
|
||||
yield self.create_text_message(response.json().get("message"))
|
||||
except Exception as e:
|
||||
yield self.create_text_message(f"GitHub API Key and Api Version is invalid. {e}")
|
||||
@@ -0,0 +1,54 @@
|
||||
description:
|
||||
human:
|
||||
en_US: Search the GitHub repository to retrieve the open source projects you need
|
||||
pt_BR: Pesquise o repositório do GitHub para recuperar os projetos de código aberto
|
||||
necessários.
|
||||
zh_Hans: 搜索GitHub仓库,检索你需要的开源项目。
|
||||
llm: A tool when you wants to search for popular warehouses or open source projects
|
||||
for any keyword. format query condition like "keywords+language:js", language
|
||||
can be other dev languages.
|
||||
extra:
|
||||
python:
|
||||
source: tools/github_repositories.py
|
||||
identity:
|
||||
author: CharlieWei
|
||||
icon: icon.svg
|
||||
label:
|
||||
en_US: Search Repositories
|
||||
pt_BR: Pesquisar Repositórios
|
||||
zh_Hans: 仓库搜索
|
||||
name: github_repositories
|
||||
parameters:
|
||||
- form: llm
|
||||
human_description:
|
||||
en_US: You want to find the project development language, keywords, For example.
|
||||
Find 10 Python developed PDF document parsing projects.
|
||||
pt_BR: Você deseja encontrar a linguagem de desenvolvimento do projeto, palavras-chave,
|
||||
Por exemplo. Encontre 10 projetos de análise de documentos PDF desenvolvidos
|
||||
em Python.
|
||||
zh_Hans: 你想要找的项目开发语言、关键字,如:找10个Python开发的PDF文档解析项目。
|
||||
label:
|
||||
en_US: query
|
||||
pt_BR: consulta
|
||||
zh_Hans: 关键字
|
||||
llm_description: The query of you want to search, format query condition like "keywords+language:js",
|
||||
language can be other dev languages.
|
||||
name: query
|
||||
required: true
|
||||
type: string
|
||||
- default: 5
|
||||
form: llm
|
||||
human_description:
|
||||
en_US: Number of records returned by sorting based on stars. 5 is returned by
|
||||
default.
|
||||
pt_BR: Número de registros retornados por classificação com base em estrelas.
|
||||
5 é retornado por padrão.
|
||||
zh_Hans: 基于stars排序返回的记录数, 默认返回5条。
|
||||
label:
|
||||
en_US: Top N
|
||||
pt_BR: Topo N
|
||||
zh_Hans: Top N
|
||||
llm_description: Extract the first N records from the returned result.
|
||||
name: top_n
|
||||
required: true
|
||||
type: number
|
||||
@@ -0,0 +1,66 @@
|
||||
import base64
|
||||
from collections.abc import Generator
|
||||
from typing import Any
|
||||
|
||||
import requests
|
||||
|
||||
from dify_plugin import Tool
|
||||
from dify_plugin.entities.tool import ToolInvokeMessage
|
||||
from dify_plugin.errors.model import InvokeError
|
||||
|
||||
|
||||
class GithubRepositoryReadmeTool(Tool):
|
||||
def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage, None, None]:
|
||||
"""
|
||||
invoke tools
|
||||
"""
|
||||
owner = tool_parameters.get("owner", "")
|
||||
repo = tool_parameters.get("repo", "")
|
||||
ref = tool_parameters.get("ref", "")
|
||||
dir_path = tool_parameters.get("dir", "")
|
||||
if not owner:
|
||||
yield self.create_text_message("Please input owner")
|
||||
if not repo:
|
||||
yield self.create_text_message("Please input repo")
|
||||
if "access_tokens" not in self.runtime.credentials or not self.runtime.credentials.get("access_tokens"):
|
||||
yield self.create_text_message("GitHub API Access Tokens is required.")
|
||||
if "api_version" not in self.runtime.credentials or not self.runtime.credentials.get("api_version"):
|
||||
api_version = "2022-11-28"
|
||||
else:
|
||||
api_version = self.runtime.credentials.get("api_version")
|
||||
try:
|
||||
headers = {
|
||||
"Content-Type": "application/vnd.github+json",
|
||||
"Authorization": f"Bearer {self.runtime.credentials.get('access_tokens')}",
|
||||
"X-GitHub-Api-Version": api_version,
|
||||
}
|
||||
s = requests.session()
|
||||
api_domain = "https://api.github.com"
|
||||
url = f"{api_domain}/repos/{owner}/{repo}/readme"
|
||||
if dir_path:
|
||||
url = f"{url}/{dir_path}"
|
||||
if ref:
|
||||
url = f"{url}?ref={ref}"
|
||||
response = s.request(
|
||||
method="GET",
|
||||
headers=headers,
|
||||
url=url,
|
||||
)
|
||||
response_data = response.json()
|
||||
if response.status_code == 200:
|
||||
if response_data.get("encoding") != "base64":
|
||||
raise InvokeError(
|
||||
f"Can not get base64 encoded readme, response encoding is {response_data.get('encoding')}"
|
||||
)
|
||||
content = response_data.get("content")
|
||||
if not content:
|
||||
raise InvokeError("README content is empty")
|
||||
decoded_bytes = base64.b64decode(content)
|
||||
decoded_str = decoded_bytes.decode("utf-8")
|
||||
yield self.create_text_message(decoded_str)
|
||||
else:
|
||||
raise InvokeError(f"Request failed: {response.status_code} {response_data.get('message')}")
|
||||
except InvokeError as e:
|
||||
raise e
|
||||
except Exception as e:
|
||||
raise InvokeError(f"Request failed: {e}") from e
|
||||
@@ -0,0 +1,70 @@
|
||||
description:
|
||||
human:
|
||||
en_US: Gets the README from a repository directory.
|
||||
pt_BR: Obter o README de um diretório do repositório.
|
||||
zh_Hans: 从存储库某个目录中获取README
|
||||
llm: A tool when you wants to gets the README content from a repository directory.
|
||||
extra:
|
||||
python:
|
||||
source: tools/github_repository_readme.py
|
||||
identity:
|
||||
author: itning
|
||||
icon: icon.svg
|
||||
label:
|
||||
en_US: Get README content
|
||||
pt_BR: Obter conteúdo do README
|
||||
zh_Hans: 获取README内容
|
||||
name: github_repository_readme
|
||||
parameters:
|
||||
- form: llm
|
||||
human_description:
|
||||
en_US: The account owner of the repository. The name is not case sensitive.
|
||||
pt_BR: Proprietário da conta do repositório. O nome não diferencia maiúsculas de minúsculas.
|
||||
zh_Hans: 仓库的账户所有者。名称不区分大小写。
|
||||
label:
|
||||
en_US: owner
|
||||
pt_BR: owner
|
||||
zh_Hans: owner
|
||||
llm_description: The account owner of the repository. The name is not case sensitive.
|
||||
name: owner
|
||||
required: true
|
||||
type: string
|
||||
- form: llm
|
||||
human_description:
|
||||
en_US: The name of the repository without the .git extension. The name is not case sensitive.
|
||||
pt_BR: O nome do repositório sem a extensão .git. O nome não diferencia maiúsculas de minúsculas.
|
||||
zh_Hans: 仓库名称不带.git扩展名。名称不区分大小写。
|
||||
label:
|
||||
en_US: repo
|
||||
pt_BR: repo
|
||||
zh_Hans: repo
|
||||
llm_description: The name of the repository without the .git extension. The name is not case sensitive.
|
||||
name: repo
|
||||
required: true
|
||||
type: string
|
||||
- form: llm
|
||||
human_description:
|
||||
en_US: "The name of the commit/branch/tag. Default: the repository’s default branch."
|
||||
pt_BR: "O nome do commit/branch/tag. Valor padrão: a branch padrão do repositório."
|
||||
zh_Hans: commit/branch/tag的名称。默认值:仓库的默认分支。
|
||||
label:
|
||||
en_US: ref
|
||||
pt_BR: ref
|
||||
zh_Hans: ref
|
||||
llm_description: "The name of the commit/branch/tag. Default: the repository’s default branch."
|
||||
name: ref
|
||||
required: false
|
||||
type: string
|
||||
- form: llm
|
||||
human_description:
|
||||
en_US: The alternate path to look for a README file
|
||||
pt_BR: O caminho alternativo para encontrar o arquivo README
|
||||
zh_Hans: 查找README文件的备用路径。
|
||||
label:
|
||||
en_US: dir
|
||||
pt_BR: dir
|
||||
zh_Hans: dir
|
||||
llm_description: The alternate path to look for a README file
|
||||
name: dir
|
||||
required: false
|
||||
type: string
|
||||
Reference in New Issue
Block a user