mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-09-30 21:36:47 +08:00
fix(operation-trace): record uninstalls and deletes, drop assistant chatter
- Split the route rules on the HTTP method so a DELETE is classified as a destructive action instead of falling into the read/write bucket. Uninstalling a plugin or skill and deleting a knowledge base or MCP server were recorded as a view/update and left no readable trace. - Add plugin_uninstall, skill_uninstall, knowledge_base_delete and mcp_delete. - Skip the assistant's own conversation traffic: a chat session produced opaque create/resource rows that answered nothing. - Localize the new actions and the assistant_conversation resource type in all locales. - Sync the assistant tool action list and apply ruff formatting.
This commit is contained in:
@@ -173,17 +173,34 @@ class CreateKnowledgeBase(CreatePipeline):
|
||||
#: further (e.g. the audit surface needs ``audit.view``, which only the owner
|
||||
#: and admin hold) and both are enforced identically when listing and calling.
|
||||
TOOLS = {
|
||||
'list_resources': (ListResources, 'List existing Workspace resources. Discover IDs before using them.', False, None),
|
||||
'list_resources': (
|
||||
ListResources,
|
||||
'List existing Workspace resources. Discover IDs before using them.',
|
||||
False,
|
||||
None,
|
||||
),
|
||||
'get_pipeline': (PipelineID, 'Read a Pipeline configuration with secrets redacted.', False, None),
|
||||
'get_knowledge_schema': (EngineID, 'Get the engine creation and retrieval configuration schemas.', False, None),
|
||||
'list_operation_logs': (
|
||||
ListOperationLogs,
|
||||
'Read the Workspace operation trace (who changed or viewed what, with before/after fields). '
|
||||
'Owner and admin only. Use it to answer "who did what" questions about this Workspace.',
|
||||
'Search the Workspace operation trace (who changed or viewed what, with before/after fields). '
|
||||
'Owner and admin only. Always pass a narrow filter instead of dumping everything: use "search" '
|
||||
'for a substring such as a plugin name, an account or a verb (e.g. search="LangTARS" or '
|
||||
'search="install"); use the exact "action" key only when known - valid keys include '
|
||||
'plugin_install, plugin_uninstall, plugin_config, plugin_view, plugin_upgrade, skill_install, '
|
||||
'skill_uninstall, create, update, delete, view, export, execute, debug, publish, member_invite, '
|
||||
'member_role_update, member_remove, member_view, settings_update, settings_view, audit_log_view, '
|
||||
'pipeline_extensions_update, knowledge_base_update, knowledge_base_delete, mcp_config, mcp_delete. '
|
||||
'Combine resource_type and actor to answer "who installed X".',
|
||||
False,
|
||||
Permission.AUDIT_VIEW,
|
||||
),
|
||||
'create_pipeline': (CreatePipeline, 'Create an unconnected Pipeline draft. Requires user confirmation.', True, None),
|
||||
'create_pipeline': (
|
||||
CreatePipeline,
|
||||
'Create an unconnected Pipeline draft. Requires user confirmation.',
|
||||
True,
|
||||
None,
|
||||
),
|
||||
'configure_pipeline': (
|
||||
ConfigurePipeline,
|
||||
'Set the local-agent model, system prompt and complete knowledge-base binding list. Requires confirmation.',
|
||||
|
||||
@@ -360,6 +360,15 @@ ACTION_RULE_TABLE: typing.Final[tuple[ActionRule, ...]] = (
|
||||
bucket='write',
|
||||
resource_type='plugin',
|
||||
),
|
||||
# Uninstalling is a mutation with its own verb. Without it the DELETE on the
|
||||
# shared ``/plugins/<author>/<name>`` route falls through to the read rule
|
||||
# and an uninstall is mislabelled as a view.
|
||||
ActionRule(
|
||||
action='plugin_uninstall',
|
||||
category='extension',
|
||||
bucket='write',
|
||||
resource_type='plugin',
|
||||
),
|
||||
ActionRule(
|
||||
action='plugin_upgrade',
|
||||
category='extension',
|
||||
@@ -384,6 +393,12 @@ ACTION_RULE_TABLE: typing.Final[tuple[ActionRule, ...]] = (
|
||||
bucket='write',
|
||||
resource_type='skill',
|
||||
),
|
||||
ActionRule(
|
||||
action='skill_uninstall',
|
||||
category='extension',
|
||||
bucket='write',
|
||||
resource_type='skill',
|
||||
),
|
||||
# --- Knowledge & MCP -------------------------------------------------
|
||||
ActionRule(
|
||||
action='knowledge_base_view',
|
||||
@@ -397,6 +412,12 @@ ACTION_RULE_TABLE: typing.Final[tuple[ActionRule, ...]] = (
|
||||
bucket='write',
|
||||
resource_type='knowledge_base',
|
||||
),
|
||||
ActionRule(
|
||||
action='knowledge_base_delete',
|
||||
category='knowledge',
|
||||
bucket='write',
|
||||
resource_type='knowledge_base',
|
||||
),
|
||||
ActionRule(
|
||||
action='mcp_view',
|
||||
category='integration',
|
||||
@@ -409,6 +430,12 @@ ACTION_RULE_TABLE: typing.Final[tuple[ActionRule, ...]] = (
|
||||
bucket='write',
|
||||
resource_type='mcp_server',
|
||||
),
|
||||
ActionRule(
|
||||
action='mcp_delete',
|
||||
category='integration',
|
||||
bucket='write',
|
||||
resource_type='mcp_server',
|
||||
),
|
||||
# --- Pipelines -------------------------------------------------------
|
||||
ActionRule(
|
||||
action='pipeline_extensions_update',
|
||||
@@ -471,6 +498,16 @@ ACTION_RULE_TABLE: typing.Final[tuple[ActionRule, ...]] = (
|
||||
bucket='read',
|
||||
resource_type='system',
|
||||
),
|
||||
# A management-assistant chat session is not a Workspace resource change:
|
||||
# creating a conversation and sending a turn produce one opaque
|
||||
# ``create/resource`` row each. They carry no "what changed" answer, so the
|
||||
# whole family is dropped rather than cluttering the log with noise.
|
||||
ActionRule(
|
||||
action='assistant_session',
|
||||
category='runtime',
|
||||
bucket='skip',
|
||||
resource_type='assistant_conversation',
|
||||
),
|
||||
)
|
||||
|
||||
ACTION_RULES_BY_ACTION: typing.Final[dict[str, ActionRule]] = {rule.action: rule for rule in ACTION_RULE_TABLE}
|
||||
@@ -479,45 +516,57 @@ _READ_METHODS: typing.Final = frozenset({'GET', 'HEAD', 'OPTIONS'})
|
||||
|
||||
# Route rules evaluated in order; the first match wins, so the most specific
|
||||
# rule must precede its prefix. Each rule is ``(fragments, read_action,
|
||||
# write_action)``: every fragment must appear in the lowered route (a tuple
|
||||
# expresses an AND, which lets ``/plugins/<author>/<name>/config`` be told
|
||||
# apart from ``/plugins/<author>/<name>``), and the action is selected by
|
||||
# whether the method is a read verb.
|
||||
_ROUTE_RULES: typing.Final[tuple[tuple[tuple[str, ...], str, str], ...]] = (
|
||||
# write_action, delete_action)``: every fragment must appear in the lowered
|
||||
# route (a tuple expresses an AND, which lets ``/plugins/<author>/<name>/config``
|
||||
# be told apart from ``/plugins/<author>/<name>``), and the action is selected by
|
||||
# the method bucket -- read verb, ``DELETE``, or any other verb.
|
||||
#
|
||||
# ``delete_action`` is distinct because several resources register their read
|
||||
# and their destroy on the *same* path (``GET``/``DELETE /plugins/<author>/<name>``,
|
||||
# ``/knowledge/...``, ``/mcp/servers/<name>``). Keying only on fragments made a
|
||||
# ``DELETE`` fall into the write bucket and record an uninstall as a view or an
|
||||
# update, so the destructive operation left no readable trace.
|
||||
_ROUTE_RULES: typing.Final[tuple[tuple[tuple[str, ...], str, str, str | None], ...]] = (
|
||||
# --- Audit surface itself -------------------------------------------
|
||||
(('/settings/operation-logs/export',), 'export', 'export'),
|
||||
(('/settings/operation-logs',), 'audit_log_view', 'audit_log_view'),
|
||||
(('/settings/operation-level',), 'settings_view', 'settings_update'),
|
||||
(('/settings/governance',), 'settings_view', 'settings_update'),
|
||||
(('/settings/limits',), 'settings_view', 'settings_update'),
|
||||
(('/settings/operation-logs/export',), 'export', 'export', None),
|
||||
(('/settings/operation-logs',), 'audit_log_view', 'audit_log_view', None),
|
||||
(('/settings/operation-level',), 'settings_view', 'settings_update', None),
|
||||
(('/settings/governance',), 'settings_view', 'settings_update', None),
|
||||
(('/settings/limits',), 'settings_view', 'settings_update', None),
|
||||
# --- Extension lifecycle: plugins -----------------------------------
|
||||
(('/plugins/install',), 'plugin_view', 'plugin_install'),
|
||||
(('/plugins/github',), 'plugin_view', 'plugin_view'),
|
||||
(('/plugins/', '/config'), 'plugin_view', 'plugin_config'),
|
||||
(('/plugins/', '/page-api'), 'page_view', 'page_view'),
|
||||
(('/plugins/', '/upgrade'), 'plugin_view', 'plugin_upgrade'),
|
||||
(('/plugins/', '/logs'), 'plugin_view', 'plugin_view'),
|
||||
(('/plugins',), 'plugin_view', 'plugin_view'),
|
||||
# ``/plugins/install`` is an install; the bare ``/plugins/<author>/<name>``
|
||||
# is a read when fetched and an uninstall when deleted.
|
||||
(('/plugins/install',), 'plugin_view', 'plugin_install', None),
|
||||
(('/plugins/github',), 'plugin_view', 'plugin_view', None),
|
||||
(('/plugins/', '/config'), 'plugin_view', 'plugin_config', None),
|
||||
(('/plugins/', '/page-api'), 'page_view', 'page_view', None),
|
||||
(('/plugins/', '/upgrade'), 'plugin_view', 'plugin_upgrade', None),
|
||||
(('/plugins/', '/logs'), 'plugin_view', 'plugin_view', None),
|
||||
(('/plugins',), 'plugin_view', 'plugin_view', 'plugin_uninstall'),
|
||||
# The pipeline extension bindings (plugins / MCP servers / skills) live on
|
||||
# ``/pipelines/<uuid>/extensions``, not on a plugin. Without this rule the
|
||||
# generic fragment below would classify the change as a plugin config edit.
|
||||
# The read keeps the generic ``view`` for backwards-compatible labelling.
|
||||
(('/extensions',), 'view', 'pipeline_extensions_update'),
|
||||
(('/extensions',), 'view', 'pipeline_extensions_update', None),
|
||||
# --- Extension lifecycle: skills ------------------------------------
|
||||
(('/skills/', '/install'), 'skill_view', 'skill_install'),
|
||||
(('/skills',), 'skill_view', 'skill_view'),
|
||||
(('/skills/', '/install'), 'skill_view', 'skill_install', None),
|
||||
(('/skills',), 'skill_view', 'skill_view', 'skill_uninstall'),
|
||||
# --- Knowledge bases & MCP servers ----------------------------------
|
||||
(('/knowledge/',), 'knowledge_base_view', 'knowledge_base_update'),
|
||||
(('/mcp/', '/config'), 'mcp_view', 'mcp_config'),
|
||||
(('/mcp',), 'mcp_view', 'mcp_config'),
|
||||
(('/knowledge/',), 'knowledge_base_view', 'knowledge_base_update', 'knowledge_base_delete'),
|
||||
(('/mcp/', '/config'), 'mcp_view', 'mcp_config', None),
|
||||
(('/mcp',), 'mcp_view', 'mcp_config', 'mcp_delete'),
|
||||
# --- Member management ----------------------------------------------
|
||||
(('/members',), 'member_view', 'member_role_update'),
|
||||
(('/invitations',), 'member_view', 'member_invite'),
|
||||
(('/members',), 'member_view', 'member_role_update', None),
|
||||
(('/invitations',), 'member_view', 'member_invite', None),
|
||||
# --- Agent-assistant session chatter (never traced) ------------------
|
||||
# Placed before the generic verbs so a conversation turn is not recorded as
|
||||
# an opaque ``create`` on a nameless resource.
|
||||
(('/assistant',), 'assistant_session', 'assistant_session', 'assistant_session'),
|
||||
# --- Generic resource verbs -----------------------------------------
|
||||
(('/export',), 'export', 'export'),
|
||||
(('/debug',), 'debug', 'debug'),
|
||||
(('/execute',), 'execute', 'execute'),
|
||||
(('/publish',), 'publish', 'publish'),
|
||||
(('/export',), 'export', 'export', None),
|
||||
(('/debug',), 'debug', 'debug', None),
|
||||
(('/execute',), 'execute', 'execute', None),
|
||||
(('/publish',), 'publish', 'publish', None),
|
||||
)
|
||||
|
||||
#: Refines the resource family for the generic verb rules. The route rules above
|
||||
@@ -583,19 +632,28 @@ def classify(method: str, route: str) -> ActionRule:
|
||||
upper_method = (method or 'GET').upper()
|
||||
lowered_route = (route or '').lower()
|
||||
is_read = upper_method in _READ_METHODS
|
||||
is_delete = upper_method == 'DELETE'
|
||||
|
||||
for fragments, read_action, write_action in _ROUTE_RULES:
|
||||
for fragments, read_action, write_action, delete_action in _ROUTE_RULES:
|
||||
if all(fragment in lowered_route for fragment in fragments):
|
||||
return _with_resource_type(ACTION_RULES_BY_ACTION[read_action if is_read else write_action], route)
|
||||
if is_read:
|
||||
action = read_action
|
||||
elif is_delete:
|
||||
# Fall back to the generic delete verb when a rule has no
|
||||
# dedicated destroy action (still a mutation, never a view).
|
||||
action = delete_action or 'delete'
|
||||
else:
|
||||
action = write_action
|
||||
return _with_resource_type(ACTION_RULES_BY_ACTION[action], route)
|
||||
|
||||
if is_read:
|
||||
return _with_resource_type(ACTION_RULES_BY_ACTION['view'], route)
|
||||
if is_delete:
|
||||
return _with_resource_type(ACTION_RULES_BY_ACTION['delete'], route)
|
||||
if upper_method == 'POST':
|
||||
return _with_resource_type(ACTION_RULES_BY_ACTION['create'], route)
|
||||
if upper_method in {'PUT', 'PATCH'}:
|
||||
return _with_resource_type(ACTION_RULES_BY_ACTION['update'], route)
|
||||
if upper_method == 'DELETE':
|
||||
return _with_resource_type(ACTION_RULES_BY_ACTION['delete'], route)
|
||||
return _with_resource_type(ACTION_RULES_BY_ACTION['probe'], route)
|
||||
|
||||
|
||||
@@ -620,9 +678,13 @@ def bucket_allows(bucket: str, effective_level: int) -> bool:
|
||||
and ``audit`` are both *observation* buckets: viewing a resource and
|
||||
viewing the audit surface itself are reads, so a mutation-level Workspace
|
||||
must not fill its log with page views. They are only persisted once the
|
||||
Workspace opts into the read level.
|
||||
Workspace opts into the read level. ``skip`` is charter noise a Workspace
|
||||
never needs traced (an assistant chat session's own turn traffic), so it is
|
||||
dropped at every level instead of being mislabelled as a resource change.
|
||||
"""
|
||||
|
||||
if bucket == 'skip':
|
||||
return False
|
||||
if effective_level <= OPERATION_LEVEL_NONE:
|
||||
return False
|
||||
if bucket in ('read', 'audit'):
|
||||
|
||||
@@ -2797,6 +2797,7 @@ const enUS = {
|
||||
member: 'Member',
|
||||
member_invitation: 'Member invitation',
|
||||
operation_log: 'Operation log',
|
||||
assistant_conversation: 'Assistant conversation',
|
||||
plugin: 'Extension',
|
||||
plugin_page: 'Extension page',
|
||||
skill: 'Skill',
|
||||
@@ -2822,14 +2823,18 @@ const enUS = {
|
||||
plugin_view: 'View extension pages',
|
||||
plugin_config: 'Change extension config',
|
||||
plugin_install: 'Install extension',
|
||||
plugin_uninstall: 'Uninstall extension',
|
||||
plugin_upgrade: 'Upgrade extension',
|
||||
page_view: 'View extension page',
|
||||
skill_view: 'View skill',
|
||||
skill_install: 'Install skill',
|
||||
skill_uninstall: 'Uninstall skill',
|
||||
knowledge_base_view: 'View knowledge base',
|
||||
knowledge_base_update: 'Change knowledge base',
|
||||
knowledge_base_delete: 'Delete knowledge base',
|
||||
mcp_view: 'View MCP server',
|
||||
mcp_config: 'Change MCP server',
|
||||
mcp_delete: 'Delete MCP server',
|
||||
pipeline_extensions_update: 'Update pipeline extension bindings',
|
||||
export: 'Export data',
|
||||
execute: 'Execute task',
|
||||
|
||||
@@ -2852,6 +2852,7 @@ const esES = {
|
||||
member: 'Miembro',
|
||||
member_invitation: 'Invitación de miembro',
|
||||
operation_log: 'Registro de operaciones',
|
||||
assistant_conversation: 'Conversación del asistente',
|
||||
plugin: 'Extensión',
|
||||
plugin_page: 'Página de extensión',
|
||||
skill: 'Habilidad',
|
||||
@@ -2877,14 +2878,18 @@ const esES = {
|
||||
plugin_view: 'Ver páginas de extensión',
|
||||
plugin_config: 'Cambiar configuración de extensión',
|
||||
plugin_install: 'Instalar extensión',
|
||||
plugin_uninstall: 'Desinstalar extensión',
|
||||
plugin_upgrade: 'Actualizar extensión',
|
||||
page_view: 'Ver página de extensión',
|
||||
skill_view: 'Ver habilidad',
|
||||
skill_install: 'Instalar habilidad',
|
||||
skill_uninstall: 'Desinstalar habilidad',
|
||||
knowledge_base_view: 'Ver base de conocimiento',
|
||||
knowledge_base_update: 'Cambiar base de conocimiento',
|
||||
knowledge_base_delete: 'Eliminar base de conocimiento',
|
||||
mcp_view: 'Ver servidor MCP',
|
||||
mcp_config: 'Cambiar servidor MCP',
|
||||
mcp_delete: 'Eliminar servidor MCP',
|
||||
pipeline_extensions_update:
|
||||
'Actualizar vinculaciones de extensiones del pipeline',
|
||||
export: 'Exportar datos',
|
||||
|
||||
@@ -2815,6 +2815,7 @@ const jaJP = {
|
||||
member: 'メンバー',
|
||||
member_invitation: 'メンバー招待',
|
||||
operation_log: '操作ログ',
|
||||
assistant_conversation: 'アシスタント会話',
|
||||
plugin: '拡張機能',
|
||||
plugin_page: '拡張ページ',
|
||||
skill: 'スキル',
|
||||
@@ -2840,14 +2841,18 @@ const jaJP = {
|
||||
plugin_view: '拡張ページを閲覧',
|
||||
plugin_config: '拡張設定を変更',
|
||||
plugin_install: '拡張をインストール',
|
||||
plugin_uninstall: '拡張をアンインストール',
|
||||
plugin_upgrade: '拡張をアップグレード',
|
||||
page_view: '拡張ページを閲覧',
|
||||
skill_view: 'スキルを閲覧',
|
||||
skill_install: 'スキルをインストール',
|
||||
skill_uninstall: 'スキルをアンインストール',
|
||||
knowledge_base_view: 'ナレッジベースを閲覧',
|
||||
knowledge_base_update: 'ナレッジベースを変更',
|
||||
knowledge_base_delete: 'ナレッジベースを削除',
|
||||
mcp_view: 'MCP サーバーを閲覧',
|
||||
mcp_config: 'MCP サーバーを変更',
|
||||
mcp_delete: 'MCP サーバーを削除',
|
||||
pipeline_extensions_update: 'パイプライン拡張の紐付けを変更',
|
||||
export: 'データをエクスポート',
|
||||
execute: 'タスクを実行',
|
||||
|
||||
@@ -2822,6 +2822,7 @@ const ruRU = {
|
||||
member: 'Участник',
|
||||
member_invitation: 'Приглашение участника',
|
||||
operation_log: 'Журнал операций',
|
||||
assistant_conversation: 'Сессия ассистента',
|
||||
plugin: 'Расширение',
|
||||
plugin_page: 'Страница расширения',
|
||||
skill: 'Навык',
|
||||
@@ -2847,14 +2848,18 @@ const ruRU = {
|
||||
plugin_view: 'Просмотр страниц расширения',
|
||||
plugin_config: 'Изменение настроек расширения',
|
||||
plugin_install: 'Установка расширения',
|
||||
plugin_uninstall: 'Удаление расширения',
|
||||
plugin_upgrade: 'Обновление расширения',
|
||||
page_view: 'Просмотр страницы расширения',
|
||||
skill_view: 'Просмотр навыка',
|
||||
skill_install: 'Установка навыка',
|
||||
skill_uninstall: 'Удаление навыка',
|
||||
knowledge_base_view: 'Просмотр базы знаний',
|
||||
knowledge_base_update: 'Изменение базы знаний',
|
||||
knowledge_base_delete: 'Удаление базы знаний',
|
||||
mcp_view: 'Просмотр сервера MCP',
|
||||
mcp_config: 'Изменение сервера MCP',
|
||||
mcp_delete: 'Удаление сервера MCP',
|
||||
pipeline_extensions_update: 'Изменение привязок расширений конвейера',
|
||||
export: 'Экспорт данных',
|
||||
execute: 'Выполнение задачи',
|
||||
|
||||
@@ -2749,6 +2749,7 @@ const thTH = {
|
||||
member: 'สมาชิก',
|
||||
member_invitation: 'คำเชิญสมาชิก',
|
||||
operation_log: 'บันทึกการดำเนินการ',
|
||||
assistant_conversation: 'บทสนทนาผู้ช่วย',
|
||||
plugin: 'ส่วนขยาย',
|
||||
plugin_page: 'หน้าส่วนขยาย',
|
||||
skill: 'ทักษะ',
|
||||
@@ -2774,14 +2775,18 @@ const thTH = {
|
||||
plugin_view: 'ดูหน้าส่วนขยาย',
|
||||
plugin_config: 'แก้ไขการตั้งค่าส่วนขยาย',
|
||||
plugin_install: 'ติดตั้งส่วนขยาย',
|
||||
plugin_uninstall: 'ถอนการติดตั้งส่วนขยาย',
|
||||
plugin_upgrade: 'อัปเกรดส่วนขยาย',
|
||||
page_view: 'ดูหน้าส่วนขยาย',
|
||||
skill_view: 'ดูทักษะ',
|
||||
skill_install: 'ติดตั้งทักษะ',
|
||||
skill_uninstall: 'ถอนการติดตั้งทักษะ',
|
||||
knowledge_base_view: 'ดูฐานความรู้',
|
||||
knowledge_base_update: 'แก้ไขฐานความรู้',
|
||||
knowledge_base_delete: 'ลบฐานความรู้',
|
||||
mcp_view: 'ดูเซิร์ฟเวอร์ MCP',
|
||||
mcp_config: 'แก้ไขเซิร์ฟเวอร์ MCP',
|
||||
mcp_delete: 'ลบเซิร์ฟเวอร์ MCP',
|
||||
pipeline_extensions_update: 'แก้ไขการผูกส่วนขยายของไปป์ไลน์',
|
||||
export: 'ส่งออกข้อมูล',
|
||||
execute: 'รันงาน',
|
||||
|
||||
@@ -2784,6 +2784,7 @@ const viVN = {
|
||||
member: 'Thành viên',
|
||||
member_invitation: 'Lời mời thành viên',
|
||||
operation_log: 'Nhật ký thao tác',
|
||||
assistant_conversation: 'Phiên trợ lý',
|
||||
plugin: 'Tiện ích mở rộng',
|
||||
plugin_page: 'Trang tiện ích',
|
||||
skill: 'Kỹ năng',
|
||||
@@ -2809,14 +2810,18 @@ const viVN = {
|
||||
plugin_view: 'Xem trang tiện ích',
|
||||
plugin_config: 'Thay đổi cấu hình tiện ích',
|
||||
plugin_install: 'Cài đặt tiện ích',
|
||||
plugin_uninstall: 'Gỡ cài đặt tiện ích',
|
||||
plugin_upgrade: 'Nâng cấp tiện ích',
|
||||
page_view: 'Xem trang tiện ích',
|
||||
skill_view: 'Xem kỹ năng',
|
||||
skill_install: 'Cài đặt kỹ năng',
|
||||
skill_uninstall: 'Gỡ cài đặt kỹ năng',
|
||||
knowledge_base_view: 'Xem cơ sở tri thức',
|
||||
knowledge_base_update: 'Thay đổi cơ sở tri thức',
|
||||
knowledge_base_delete: 'Xóa cơ sở tri thức',
|
||||
mcp_view: 'Xem máy chủ MCP',
|
||||
mcp_config: 'Thay đổi máy chủ MCP',
|
||||
mcp_delete: 'Xóa máy chủ MCP',
|
||||
pipeline_extensions_update: 'Cập nhật liên kết tiện ích của pipeline',
|
||||
export: 'Xuất dữ liệu',
|
||||
execute: 'Chạy tác vụ',
|
||||
|
||||
@@ -2647,6 +2647,7 @@ const zhHans = {
|
||||
member: '成员',
|
||||
member_invitation: '成员邀请',
|
||||
operation_log: '操作日志',
|
||||
assistant_conversation: '助手会话',
|
||||
plugin: '扩展',
|
||||
plugin_page: '扩展页面',
|
||||
skill: '技能',
|
||||
@@ -2672,14 +2673,18 @@ const zhHans = {
|
||||
plugin_view: '查看扩展页面',
|
||||
plugin_config: '修改扩展配置',
|
||||
plugin_install: '安装扩展',
|
||||
plugin_uninstall: '卸载扩展',
|
||||
plugin_upgrade: '升级扩展',
|
||||
page_view: '查看扩展页面',
|
||||
skill_view: '查看技能',
|
||||
skill_install: '安装技能',
|
||||
skill_uninstall: '卸载技能',
|
||||
knowledge_base_view: '查看知识库',
|
||||
knowledge_base_update: '修改知识库',
|
||||
knowledge_base_delete: '删除知识库',
|
||||
mcp_view: '查看 MCP 服务器',
|
||||
mcp_config: '修改 MCP 服务器',
|
||||
mcp_delete: '删除 MCP 服务器',
|
||||
pipeline_extensions_update: '修改管道扩展绑定',
|
||||
export: '导出数据',
|
||||
execute: '执行任务',
|
||||
|
||||
@@ -2648,6 +2648,7 @@ const zhHant = {
|
||||
member: '成員',
|
||||
member_invitation: '成員邀請',
|
||||
operation_log: '操作日誌',
|
||||
assistant_conversation: '助手會話',
|
||||
plugin: '擴充',
|
||||
plugin_page: '擴充頁面',
|
||||
skill: '技能',
|
||||
@@ -2673,14 +2674,18 @@ const zhHant = {
|
||||
plugin_view: '查看擴充頁面',
|
||||
plugin_config: '修改擴充設定',
|
||||
plugin_install: '安裝擴充',
|
||||
plugin_uninstall: '解除安裝擴充',
|
||||
plugin_upgrade: '升級擴充',
|
||||
page_view: '查看擴充頁面',
|
||||
skill_view: '查看技能',
|
||||
skill_install: '安裝技能',
|
||||
skill_uninstall: '解除安裝技能',
|
||||
knowledge_base_view: '查看知識庫',
|
||||
knowledge_base_update: '修改知識庫',
|
||||
knowledge_base_delete: '刪除知識庫',
|
||||
mcp_view: '查看 MCP 伺服器',
|
||||
mcp_config: '修改 MCP 伺服器',
|
||||
mcp_delete: '刪除 MCP 伺服器',
|
||||
pipeline_extensions_update: '修改管道擴展綁定',
|
||||
export: '匯出資料',
|
||||
execute: '執行任務',
|
||||
|
||||
Reference in New Issue
Block a user