fix(im): close shortcut review gaps
This commit is contained in:
@@ -37,14 +37,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "available",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -73,14 +73,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "not_required",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -89,14 +89,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "read",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -127,14 +127,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "idempotent",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -143,14 +143,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "composite",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -159,14 +159,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "Reviewed built-in shortcut adapter: the executable CLI owns validation, optional multi-step orchestration, output projection, and confirmation; the complete command contract is not represented by one pinned MCP interface_ref.",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -191,14 +191,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": true,
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
},
|
||||
{
|
||||
"value": true,
|
||||
@@ -214,20 +214,20 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "low",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
"use_when": {
|
||||
"value": [
|
||||
"当你想快速看回最近谁在群里或单聊里 @了你、但不想手动把起止时间换算成毫秒、也不想记 list-mentions 的一堆参数时使用;内部按本地时区算出「最近 N 天」(默认 7 天,可用 --days 调整回溯天数)的时间窗,搜索这段时间内 @我 的消息,再在本地把每条消息投影成发送人、时间、内容、所在会话四个关键字段。默认只读且不会发送、撤回或标记任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你想快速看回最近谁在群里或单聊里 @了你、但不想手动把起止时间换算成毫秒、也不想记 list-mentions 的一堆参数时使用;内部按本地时区算出「最近 N 天」(默认 7 天,可用 --days 调整回溯天数)的时间窗,搜索这段时间内 @我 的消息,再在本地把每条消息投影成发送人、时间、内容、所在会话四个关键字段。默认只读且不会发送、撤回或标记任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -236,7 +236,7 @@
|
||||
"candidates": [
|
||||
{
|
||||
"value": [
|
||||
"当你想快速看回最近谁在群里或单聊里 @了你、但不想手动把起止时间换算成毫秒、也不想记 list-mentions 的一堆参数时使用;内部按本地时区算出「最近 N 天」(默认 7 天,可用 --days 调整回溯天数)的时间窗,搜索这段时间内 @我 的消息,再在本地把每条消息投影成发送人、时间、内容、所在会话四个关键字段。默认只读且不会发送、撤回或标记任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你想快速看回最近谁在群里或单聊里 @了你、但不想手动把起止时间换算成毫秒、也不想记 list-mentions 的一堆参数时使用;内部按本地时区算出「最近 N 天」(默认 7 天,可用 --days 调整回溯天数)的时间窗,搜索这段时间内 @我 的消息,再在本地把每条消息投影成发送人、时间、内容、所在会话四个关键字段。默认只读且不会发送、撤回或标记任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -260,7 +260,7 @@
|
||||
"skills/mono/references/intent-guide.md"
|
||||
],
|
||||
"use_when": [
|
||||
"当你想快速看回最近谁在群里或单聊里 @了你、但不想手动把起止时间换算成毫秒、也不想记 list-mentions 的一堆参数时使用;内部按本地时区算出「最近 N 天」(默认 7 天,可用 --days 调整回溯天数)的时间窗,搜索这段时间内 @我 的消息,再在本地把每条消息投影成发送人、时间、内容、所在会话四个关键字段。默认只读且不会发送、撤回或标记任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你想快速看回最近谁在群里或单聊里 @了你、但不想手动把起止时间换算成毫秒、也不想记 list-mentions 的一堆参数时使用;内部按本地时区算出「最近 N 天」(默认 7 天,可用 --days 调整回溯天数)的时间窗,搜索这段时间内 @我 的消息,再在本地把每条消息投影成发送人、时间、内容、所在会话四个关键字段。默认只读且不会发送、撤回或标记任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
]
|
||||
},
|
||||
"chat +bot-find": {
|
||||
@@ -3653,14 +3653,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "available",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3689,14 +3689,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "not_required",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3705,14 +3705,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "read",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3743,14 +3743,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "idempotent",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3759,14 +3759,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "composite",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3775,14 +3775,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "Reviewed built-in Shortcut adapter: it routes group or direct-message history reads, projects a stable message shape, and optionally orchestrates safe resource downloads with a failure ledger.",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3807,14 +3807,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": true,
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication."
|
||||
},
|
||||
{
|
||||
"value": true,
|
||||
@@ -3830,20 +3830,20 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "low",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication."
|
||||
}
|
||||
]
|
||||
},
|
||||
"use_when": {
|
||||
"value": [
|
||||
"当你想快速看某个会话里的消息(谁在什么时间说了什么),而不想拿到一大坨原始消息字段时使用;群聊传 --group(群会话 ID,openConversationId),单聊传 --user(对方 userId),两者互斥且必须二选一。省略 --time 时默认从当前时间向前读取最近消息;也可指定时间边界并用 --direction newer/older 控制方向。内部据此调用群聊或单聊的消息列表接口,再在本地投影出每条消息的发言人、文本和时间。默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你想快速看某个会话里的消息(谁在什么时间说了什么),而不想拿到一大坨原始消息字段时使用;群聊传 --group(群会话 ID,openConversationId),单聊传 --user(对方 userId),两者互斥且必须二选一。省略 --time 时默认从当前时间向前读取最近消息;也可指定时间边界并用 --direction newer/older 控制方向。内部据此调用群聊或单聊的消息列表接口,再在本地投影出每条消息的发言人、文本和时间。默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -3852,7 +3852,7 @@
|
||||
"candidates": [
|
||||
{
|
||||
"value": [
|
||||
"当你想快速看某个会话里的消息(谁在什么时间说了什么),而不想拿到一大坨原始消息字段时使用;群聊传 --group(群会话 ID,openConversationId),单聊传 --user(对方 userId),两者互斥且必须二选一。省略 --time 时默认从当前时间向前读取最近消息;也可指定时间边界并用 --direction newer/older 控制方向。内部据此调用群聊或单聊的消息列表接口,再在本地投影出每条消息的发言人、文本和时间。默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你想快速看某个会话里的消息(谁在什么时间说了什么),而不想拿到一大坨原始消息字段时使用;群聊传 --group(群会话 ID,openConversationId),单聊传 --user(对方 userId),两者互斥且必须二选一。省略 --time 时默认从当前时间向前读取最近消息;也可指定时间边界并用 --direction newer/older 控制方向。内部据此调用群聊或单聊的消息列表接口,再在本地投影出每条消息的发言人、文本和时间。默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -3876,7 +3876,7 @@
|
||||
"skills/mono/references/intent-guide.md"
|
||||
],
|
||||
"use_when": [
|
||||
"当你想快速看某个会话里的消息(谁在什么时间说了什么),而不想拿到一大坨原始消息字段时使用;群聊传 --group(群会话 ID,openConversationId),单聊传 --user(对方 userId),两者互斥且必须二选一。省略 --time 时默认从当前时间向前读取最近消息;也可指定时间边界并用 --direction newer/older 控制方向。内部据此调用群聊或单聊的消息列表接口,再在本地投影出每条消息的发言人、文本和时间。默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你想快速看某个会话里的消息(谁在什么时间说了什么),而不想拿到一大坨原始消息字段时使用;群聊传 --group(群会话 ID,openConversationId),单聊传 --user(对方 userId),两者互斥且必须二选一。省略 --time 时默认从当前时间向前读取最近消息;也可指定时间边界并用 --direction newer/older 控制方向。内部据此调用群聊或单聊的消息列表接口,再在本地投影出每条消息的发言人、文本和时间。默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
]
|
||||
},
|
||||
"chat +chat-mute": {
|
||||
@@ -9077,14 +9077,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "available",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -9113,14 +9113,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "not_required",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -9129,14 +9129,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "read",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -9165,14 +9165,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "idempotent",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -9181,14 +9181,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "composite",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -9197,14 +9197,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "Reviewed built-in shortcut adapter: the executable CLI owns validation, optional multi-step orchestration, output projection, and confirmation; the complete command contract is not represented by one pinned MCP interface_ref.",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -9229,14 +9229,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": true,
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
},
|
||||
{
|
||||
"value": true,
|
||||
@@ -9252,20 +9252,20 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "low",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
"use_when": {
|
||||
"value": [
|
||||
"当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger。默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger;本地下载路径受限于工作目录、默认不覆盖同名文件,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -9274,7 +9274,7 @@
|
||||
"candidates": [
|
||||
{
|
||||
"value": [
|
||||
"当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger。默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger;本地下载路径受限于工作目录、默认不覆盖同名文件,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -9297,7 +9297,7 @@
|
||||
"internal/cli/schema_hints/selection/chat.json"
|
||||
],
|
||||
"use_when": [
|
||||
"当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger。默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger;本地下载路径受限于工作目录、默认不覆盖同名文件,按既有安全下载约定无需交互确认。"
|
||||
]
|
||||
},
|
||||
"chat +messages-query-send-status": {
|
||||
@@ -10066,7 +10066,7 @@
|
||||
},
|
||||
"use_when": {
|
||||
"value": [
|
||||
"当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。"
|
||||
"当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;--user 传 userId 时包括在 --dry-run 中也会先只读解析为 openDingTalkId。bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -10075,7 +10075,7 @@
|
||||
"candidates": [
|
||||
{
|
||||
"value": [
|
||||
"当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。"
|
||||
"当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;--user 传 userId 时包括在 --dry-run 中也会先只读解析为 openDingTalkId。bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -10099,7 +10099,7 @@
|
||||
"skills/mono/references/intent-guide.md"
|
||||
],
|
||||
"use_when": [
|
||||
"当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。"
|
||||
"当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;--user 传 userId 时包括在 --dry-run 中也会先只读解析为 openDingTalkId。bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。"
|
||||
]
|
||||
},
|
||||
"chat +messages-send-by-webhook": {
|
||||
@@ -10586,7 +10586,7 @@
|
||||
},
|
||||
"use_when": {
|
||||
"value": [
|
||||
"当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId 二选一。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。"
|
||||
"当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId/openDingTalkId 二选一。单聊目标会统一解析后以 receiverOpenDingTalkId 传给下层;userId 包括在 --dry-run 时也会先做只读通讯录解析。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -10595,7 +10595,7 @@
|
||||
"candidates": [
|
||||
{
|
||||
"value": [
|
||||
"当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId 二选一。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。"
|
||||
"当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId/openDingTalkId 二选一。单聊目标会统一解析后以 receiverOpenDingTalkId 传给下层;userId 包括在 --dry-run 时也会先做只读通讯录解析。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -10618,7 +10618,7 @@
|
||||
"internal/cli/schema_hints/selection/chat.json"
|
||||
],
|
||||
"use_when": [
|
||||
"当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId 二选一。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。"
|
||||
"当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId/openDingTalkId 二选一。单聊目标会统一解析后以 receiverOpenDingTalkId 传给下层;userId 包括在 --dry-run 时也会先做只读通讯录解析。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。"
|
||||
]
|
||||
},
|
||||
"chat +messages-update-card": {
|
||||
@@ -11176,14 +11176,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "available",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -11212,14 +11212,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "not_required",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -11228,14 +11228,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "read",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -11266,14 +11266,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "idempotent",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -11282,14 +11282,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "composite",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -11298,14 +11298,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "Reviewed search adapter: it combines filters, cursor pagination, batched mget enrichment, stable projection, completeness accounting, and optional safe resource downloads.",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -11330,14 +11330,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": true,
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
},
|
||||
{
|
||||
"value": true,
|
||||
@@ -11353,20 +11353,20 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "low",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
"use_when": {
|
||||
"value": [
|
||||
"当你要按关键词、发送者、@对象、会话、消息类型或机器人来源组合搜索 IM 消息时使用;默认查询近 7 天,也可指定精确起止时间。--page-all 会连续拉取游标页,默认再按消息 ID 分批富化详情;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger,绝不把截断结果标成完整。默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你要按关键词、发送者、@对象、会话、消息类型或机器人来源组合搜索 IM 消息时使用;默认查询近 7 天,也可指定精确起止时间。--page-all 会连续拉取游标页,默认再按消息 ID 分批富化详情;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger,绝不把截断结果标成完整。--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -11375,7 +11375,7 @@
|
||||
"candidates": [
|
||||
{
|
||||
"value": [
|
||||
"当你要按关键词、发送者、@对象、会话、消息类型或机器人来源组合搜索 IM 消息时使用;默认查询近 7 天,也可指定精确起止时间。--page-all 会连续拉取游标页,默认再按消息 ID 分批富化详情;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger,绝不把截断结果标成完整。默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你要按关键词、发送者、@对象、会话、消息类型或机器人来源组合搜索 IM 消息时使用;默认查询近 7 天,也可指定精确起止时间。--page-all 会连续拉取游标页,默认再按消息 ID 分批富化详情;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger,绝不把截断结果标成完整。--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -11399,7 +11399,7 @@
|
||||
"skills/mono/references/intent-guide.md"
|
||||
],
|
||||
"use_when": [
|
||||
"当你要按关键词、发送者、@对象、会话、消息类型或机器人来源组合搜索 IM 消息时使用;默认查询近 7 天,也可指定精确起止时间。--page-all 会连续拉取游标页,默认再按消息 ID 分批富化详情;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger,绝不把截断结果标成完整。默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你要按关键词、发送者、@对象、会话、消息类型或机器人来源组合搜索 IM 消息时使用;默认查询近 7 天,也可指定精确起止时间。--page-all 会连续拉取游标页,默认再按消息 ID 分批富化详情;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger,绝不把截断结果标成完整。--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
]
|
||||
},
|
||||
"chat +send-to-group": {
|
||||
@@ -11696,14 +11696,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "available",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -11732,14 +11732,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "not_required",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -11748,14 +11748,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "read",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -11786,14 +11786,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "idempotent",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -11802,14 +11802,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "composite",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -11818,14 +11818,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "Reviewed thread reader adapter: it accepts threadId/topicId, reads lower topic replies, projects stable message fields, and optionally downloads reply resources safely.",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -11850,14 +11850,14 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": true,
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
},
|
||||
{
|
||||
"value": true,
|
||||
@@ -11873,20 +11873,20 @@
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"resolution": "highest_precedence",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"candidates": [
|
||||
{
|
||||
"value": "low",
|
||||
"source": "internal/cli/schema_hints/metadata/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
"selected": true,
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes."
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op."
|
||||
}
|
||||
]
|
||||
},
|
||||
"use_when": {
|
||||
"value": [
|
||||
"当你已经拿到某个群里一条「话题消息」的 threadId/topicId、想快速看这条话题下的全部回复(谁在什么时间回复了什么),而不想拿到一大坨原始消息字段时使用;内部按 --group(群会话 ID)和 --thread-id(兼容 --topic-id)拉取该话题的回复列表,可选 --time 指定起始时间、--limit 指定每页条数,再在本地投影出每条回复的发言人、文本和回复时间。默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你已经拿到某个群里一条「话题消息」的 threadId/topicId、想快速看这条话题下的全部回复(谁在什么时间回复了什么),而不想拿到一大坨原始消息字段时使用;内部按 --group(群会话 ID)和 --thread-id(兼容 --topic-id)拉取该话题的回复列表,可选 --time 指定起始时间、--limit 指定每页条数,再在本地投影出每条回复的发言人、文本和回复时间。默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -11895,7 +11895,7 @@
|
||||
"candidates": [
|
||||
{
|
||||
"value": [
|
||||
"当你已经拿到某个群里一条「话题消息」的 threadId/topicId、想快速看这条话题下的全部回复(谁在什么时间回复了什么),而不想拿到一大坨原始消息字段时使用;内部按 --group(群会话 ID)和 --thread-id(兼容 --topic-id)拉取该话题的回复列表,可选 --time 指定起始时间、--limit 指定每页条数,再在本地投影出每条回复的发言人、文本和回复时间。默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你已经拿到某个群里一条「话题消息」的 threadId/topicId、想快速看这条话题下的全部回复(谁在什么时间回复了什么),而不想拿到一大坨原始消息字段时使用;内部按 --group(群会话 ID)和 --thread-id(兼容 --topic-id)拉取该话题的回复列表,可选 --time 指定起始时间、--limit 指定每页条数,再在本地投影出每条回复的发言人、文本和回复时间。默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"source": "internal/cli/schema_hints/selection/chat.json",
|
||||
"precedence": "reviewed_explicit",
|
||||
@@ -11919,7 +11919,7 @@
|
||||
"skills/mono/references/intent-guide.md"
|
||||
],
|
||||
"use_when": [
|
||||
"当你已经拿到某个群里一条「话题消息」的 threadId/topicId、想快速看这条话题下的全部回复(谁在什么时间回复了什么),而不想拿到一大坨原始消息字段时使用;内部按 --group(群会话 ID)和 --thread-id(兼容 --topic-id)拉取该话题的回复列表,可选 --time 指定起始时间、--limit 指定每页条数,再在本地投影出每条回复的发言人、文本和回复时间。默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你已经拿到某个群里一条「话题消息」的 threadId/topicId、想快速看这条话题下的全部回复(谁在什么时间回复了什么),而不想拿到一大坨原始消息字段时使用;内部按 --group(群会话 ID)和 --thread-id(兼容 --topic-id)拉取该话题的回复列表,可选 --time 指定起始时间、--limit 指定每页条数,再在本地投影出每条回复的发言人、文本和回复时间。默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
]
|
||||
},
|
||||
"chat +unread-chats": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": 1,
|
||||
"source_hash": "sha256:e3c1325f5de1ca98fb3f501f40c9da5cba3f18f3b0a4a3d8024e0e6b98db9728",
|
||||
"source_hash": "sha256:f48d04b4c2f9494460cba8d38ef6b6b8dd5a0172450f6f06123f1b696aaef497",
|
||||
"surface_hash": "sha256:60eee8e2f37d6d9d60689efce85082798eb9ad38b7ba7c0b471c3de676a85a16",
|
||||
"coverage": {
|
||||
"surface_products": 26,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": 1,
|
||||
"source_hash": "sha256:e3c1325f5de1ca98fb3f501f40c9da5cba3f18f3b0a4a3d8024e0e6b98db9728",
|
||||
"source_hash": "sha256:f48d04b4c2f9494460cba8d38ef6b6b8dd5a0172450f6f06123f1b696aaef497",
|
||||
"surface_hash": "sha256:60eee8e2f37d6d9d60689efce85082798eb9ad38b7ba7c0b471c3de676a85a16",
|
||||
"source_files": 160,
|
||||
"hint_files": 54,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"version": 1,
|
||||
"surface_hash": "sha256:60eee8e2f37d6d9d60689efce85082798eb9ad38b7ba7c0b471c3de676a85a16",
|
||||
"source_hash": "sha256:47e91a68c4dc191042873c29a3738e3de45633421dd75c9c7671f4d2d7f18e37",
|
||||
"source_hash": "sha256:46e9ac44ad12175deac0891886039e6a0a2436208b29b6393fd39452ba285a25",
|
||||
"catalog": {
|
||||
"agent_metadata": {
|
||||
"products_with_metadata": 26,
|
||||
"source": "embedded-skill-metadata",
|
||||
"source_hash": "sha256:e3c1325f5de1ca98fb3f501f40c9da5cba3f18f3b0a4a3d8024e0e6b98db9728",
|
||||
"source_hash": "sha256:f48d04b4c2f9494460cba8d38ef6b6b8dd5a0172450f6f06123f1b696aaef497",
|
||||
"surface_hash": "sha256:60eee8e2f37d6d9d60689efce85082798eb9ad38b7ba7c0b471c3de676a85a16",
|
||||
"surface_products": 26,
|
||||
"surface_tools": 845,
|
||||
@@ -9800,7 +9800,7 @@
|
||||
"cli_name": "+at-me",
|
||||
"cli_path": "chat +at-me",
|
||||
"confirmation": "not_required",
|
||||
"description": "当你想快速看回最近谁在群里或单聊里 @了你、但不想手动把起止时间换算成毫秒、也不想记 list-mentions 的一堆参数时使用;内部按本地时区算出「最近 N 天」(默认 7 天,可用 --days 调整回溯天数)的时间窗,搜索这段时间内 @我 的消息,再在本地把每条消息投影成发送人、时间、内容、所在会话四个关键字段。默认只读且不会发送、撤回或标记任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。\n\n参数约束:\n - --output-dir 必须是工作目录内的相对路径,不允许绝对路径或 .. 逃逸",
|
||||
"description": "当你想快速看回最近谁在群里或单聊里 @了你、但不想手动把起止时间换算成毫秒、也不想记 list-mentions 的一堆参数时使用;内部按本地时区算出「最近 N 天」(默认 7 天,可用 --days 调整回溯天数)的时间窗,搜索这段时间内 @我 的消息,再在本地把每条消息投影成发送人、时间、内容、所在会话四个关键字段。默认只读且不会发送、撤回或标记任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。\n\n参数约束:\n - --output-dir 必须是工作目录内的相对路径,不允许绝对路径或 .. 逃逸",
|
||||
"effect": "read",
|
||||
"idempotency": "idempotent",
|
||||
"interface_mode": "composite",
|
||||
@@ -9811,7 +9811,7 @@
|
||||
"risk": "low",
|
||||
"title": "查最近 @我 的消息(自动算时间窗,投影发送人/时间/内容/会话)",
|
||||
"use_when": [
|
||||
"当你想快速看回最近谁在群里或单聊里 @了你、但不想手动把起止时间换算成毫秒、也不想记 list-mentions 的一堆参数时使用;内部按本地时区算出「最近 N 天」(默认 7 天,可用 --days 调整回溯天数)的时间窗,搜索这段时间内 @我 的消息,再在本地把每条消息投影成发送人、时间、内容、所在会话四个关键字段。默认只读且不会发送、撤回或标记任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你想快速看回最近谁在群里或单聊里 @了你、但不想手动把起止时间换算成毫秒、也不想记 list-mentions 的一堆参数时使用;内部按本地时区算出「最近 N 天」(默认 7 天,可用 --days 调整回溯天数)的时间窗,搜索这段时间内 @我 的消息,再在本地把每条消息投影成发送人、时间、内容、所在会话四个关键字段。默认只读且不会发送、撤回或标记任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -10164,7 +10164,7 @@
|
||||
"cli_name": "+chat-messages",
|
||||
"cli_path": "chat +chat-messages",
|
||||
"confirmation": "not_required",
|
||||
"description": "当你想快速看某个会话里的消息(谁在什么时间说了什么),而不想拿到一大坨原始消息字段时使用;群聊传 --group(群会话 ID,openConversationId),单聊传 --user(对方 userId),两者互斥且必须二选一。省略 --time 时默认从当前时间向前读取最近消息;也可指定时间边界并用 --direction newer/older 控制方向。内部据此调用群聊或单聊的消息列表接口,再在本地投影出每条消息的发言人、文本和时间。默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。\n\n参数约束:\n - --group、--conversation-id、--id、--user、--open-dingtalk-id 必须且只能指定一个\n - --output-dir 必须是工作目录内的相对路径,不允许绝对路径或 .. 逃逸",
|
||||
"description": "当你想快速看某个会话里的消息(谁在什么时间说了什么),而不想拿到一大坨原始消息字段时使用;群聊传 --group(群会话 ID,openConversationId),单聊传 --user(对方 userId),两者互斥且必须二选一。省略 --time 时默认从当前时间向前读取最近消息;也可指定时间边界并用 --direction newer/older 控制方向。内部据此调用群聊或单聊的消息列表接口,再在本地投影出每条消息的发言人、文本和时间。默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。\n\n参数约束:\n - --group、--conversation-id、--id、--user、--open-dingtalk-id 必须且只能指定一个\n - --output-dir 必须是工作目录内的相对路径,不允许绝对路径或 .. 逃逸",
|
||||
"effect": "read",
|
||||
"idempotency": "idempotent",
|
||||
"interface_mode": "composite",
|
||||
@@ -10175,7 +10175,7 @@
|
||||
"risk": "low",
|
||||
"title": "拉取某个会话(群聊或单聊)的消息列表并投影出发言人/文本/时间",
|
||||
"use_when": [
|
||||
"当你想快速看某个会话里的消息(谁在什么时间说了什么),而不想拿到一大坨原始消息字段时使用;群聊传 --group(群会话 ID,openConversationId),单聊传 --user(对方 userId),两者互斥且必须二选一。省略 --time 时默认从当前时间向前读取最近消息;也可指定时间边界并用 --direction newer/older 控制方向。内部据此调用群聊或单聊的消息列表接口,再在本地投影出每条消息的发言人、文本和时间。默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你想快速看某个会话里的消息(谁在什么时间说了什么),而不想拿到一大坨原始消息字段时使用;群聊传 --group(群会话 ID,openConversationId),单聊传 --user(对方 userId),两者互斥且必须二选一。省略 --time 时默认从当前时间向前读取最近消息;也可指定时间边界并用 --direction newer/older 控制方向。内部据此调用群聊或单聊的消息列表接口,再在本地投影出每条消息的发言人、文本和时间。默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -10710,7 +10710,7 @@
|
||||
"cli_name": "+messages-mget",
|
||||
"cli_path": "chat +messages-mget",
|
||||
"confirmation": "not_required",
|
||||
"description": "当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger。默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。\n\n参数约束:\n - --msg-ids 去重后必须包含 1-50 条消息 ID\n - --output-dir 必须是工作目录内的相对路径,不允许绝对路径或 .. 逃逸",
|
||||
"description": "当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger;本地下载路径受限于工作目录、默认不覆盖同名文件,按既有安全下载约定无需交互确认。\n\n参数约束:\n - --msg-ids 去重后必须包含 1-50 条消息 ID\n - --output-dir 必须是工作目录内的相对路径,不允许绝对路径或 .. 逃逸",
|
||||
"effect": "read",
|
||||
"idempotency": "idempotent",
|
||||
"interface_mode": "composite",
|
||||
@@ -10721,7 +10721,7 @@
|
||||
"risk": "low",
|
||||
"title": "根据消息 ID 批量查询消息(最多 50 条)",
|
||||
"use_when": [
|
||||
"当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger。默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger;本地下载路径受限于工作目录、默认不覆盖同名文件,按既有安全下载约定无需交互确认。"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -10788,7 +10788,7 @@
|
||||
"cli_name": "+messages-send",
|
||||
"cli_path": "chat +messages-send",
|
||||
"confirmation": "user_required",
|
||||
"description": "当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。\n\n参数约束:\n - --text、--markdown、--media-id、--file、--file-path 至少指定一个\n - --text、--markdown、--media-id、--file、--file-path 互斥,最多指定一个\n - --identity、--as 互斥,最多指定一个\n - --group、--chat-id 互斥,最多指定一个\n - --user、--open-dingtalk-id 互斥,最多指定一个\n - --uuid、--idempotency-key 互斥,最多指定一个\n - 目标、凭据和幂等参数受发送身份能力矩阵约束:user 必须指定一个群聊或单聊目标;bot 必须指定 robot-code 和一类目标;webhook 必须指定 webhook-token;幂等键仅 user 支持",
|
||||
"description": "当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;--user 传 userId 时包括在 --dry-run 中也会先只读解析为 openDingTalkId。bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。\n\n参数约束:\n - --text、--markdown、--media-id、--file、--file-path 至少指定一个\n - --text、--markdown、--media-id、--file、--file-path 互斥,最多指定一个\n - --identity、--as 互斥,最多指定一个\n - --group、--chat-id 互斥,最多指定一个\n - --user、--open-dingtalk-id 互斥,最多指定一个\n - --uuid、--idempotency-key 互斥,最多指定一个\n - 目标、凭据和幂等参数受发送身份能力矩阵约束:user 必须指定一个群聊或单聊目标;bot 必须指定 robot-code 和一类目标;webhook 必须指定 webhook-token;幂等键仅 user 支持",
|
||||
"effect": "write",
|
||||
"idempotency": "unknown",
|
||||
"interface_mode": "composite",
|
||||
@@ -10799,7 +10799,7 @@
|
||||
"risk": "medium",
|
||||
"title": "统一发送文本、Markdown、当前用户文件或已有 mediaId 图片",
|
||||
"use_when": [
|
||||
"当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。"
|
||||
"当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;--user 传 userId 时包括在 --dry-run 中也会先只读解析为 openDingTalkId。bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -10840,7 +10840,7 @@
|
||||
"cli_name": "+messages-send-card",
|
||||
"cli_path": "chat +messages-send-card",
|
||||
"confirmation": "user_required",
|
||||
"description": "当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId 二选一。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。\n\n参数约束:\n - --group、--receiver 必须且只能指定一个\n - --flow-status 必须在 1-5 之间,且显式指定时必须同时提供 --content",
|
||||
"description": "当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId/openDingTalkId 二选一。单聊目标会统一解析后以 receiverOpenDingTalkId 传给下层;userId 包括在 --dry-run 时也会先做只读通讯录解析。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。\n\n参数约束:\n - --group、--receiver 必须且只能指定一个\n - --flow-status 必须在 1-5 之间,且显式指定时必须同时提供 --content",
|
||||
"effect": "write",
|
||||
"idempotency": "unknown",
|
||||
"interface_mode": "composite",
|
||||
@@ -10851,7 +10851,7 @@
|
||||
"risk": "medium",
|
||||
"title": "创建流式卡片,可在同一次调用中写入内容并结束",
|
||||
"use_when": [
|
||||
"当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId 二选一。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。"
|
||||
"当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId/openDingTalkId 二选一。单聊目标会统一解析后以 receiverOpenDingTalkId 传给下层;userId 包括在 --dry-run 时也会先做只读通讯录解析。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -10918,7 +10918,7 @@
|
||||
"cli_name": "+search-msg",
|
||||
"cli_path": "chat +search-msg",
|
||||
"confirmation": "not_required",
|
||||
"description": "当你要按关键词、发送者、@对象、会话、消息类型或机器人来源组合搜索 IM 消息时使用;默认查询近 7 天,也可指定精确起止时间。--page-all 会连续拉取游标页,默认再按消息 ID 分批富化详情;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger,绝不把截断结果标成完整。默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。\n\n参数约束:\n - 至少指定一个内容、身份、会话或消息类型过滤条件\n - 需与 --end 一起传\n - 需与 --start 一起传\n - --groups、--chat-id 互斥,最多指定一个\n - --senders、--sender 互斥,最多指定一个\n - --at-me、--is-at-me 互斥,最多指定一个\n - --conversation-type、--chat-type 互斥,最多指定一个\n - --limit、--page-size 互斥,最多指定一个\n - --cursor、--page-token 互斥,最多指定一个\n - --output-dir 必须是工作目录内的相对路径,不允许绝对路径或 .. 逃逸",
|
||||
"description": "当你要按关键词、发送者、@对象、会话、消息类型或机器人来源组合搜索 IM 消息时使用;默认查询近 7 天,也可指定精确起止时间。--page-all 会连续拉取游标页,默认再按消息 ID 分批富化详情;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger,绝不把截断结果标成完整。--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。\n\n参数约束:\n - 至少指定一个内容、身份、会话或消息类型过滤条件\n - 需与 --end 一起传\n - 需与 --start 一起传\n - --groups、--chat-id 互斥,最多指定一个\n - --senders、--sender 互斥,最多指定一个\n - --at-me、--is-at-me 互斥,最多指定一个\n - --conversation-type、--chat-type 互斥,最多指定一个\n - --limit、--page-size 互斥,最多指定一个\n - --cursor、--page-token 互斥,最多指定一个\n - --output-dir 必须是工作目录内的相对路径,不允许绝对路径或 .. 逃逸",
|
||||
"effect": "read",
|
||||
"idempotency": "idempotent",
|
||||
"interface_mode": "composite",
|
||||
@@ -10929,7 +10929,7 @@
|
||||
"risk": "low",
|
||||
"title": "多维搜索消息,可全量翻页并批量富化详情",
|
||||
"use_when": [
|
||||
"当你要按关键词、发送者、@对象、会话、消息类型或机器人来源组合搜索 IM 消息时使用;默认查询近 7 天,也可指定精确起止时间。--page-all 会连续拉取游标页,默认再按消息 ID 分批富化详情;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger,绝不把截断结果标成完整。默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你要按关键词、发送者、@对象、会话、消息类型或机器人来源组合搜索 IM 消息时使用;默认查询近 7 天,也可指定精确起止时间。--page-all 会连续拉取游标页,默认再按消息 ID 分批富化详情;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger,绝不把截断结果标成完整。--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -10970,7 +10970,7 @@
|
||||
"cli_name": "+thread-replies",
|
||||
"cli_path": "chat +thread-replies",
|
||||
"confirmation": "not_required",
|
||||
"description": "当你已经拿到某个群里一条「话题消息」的 threadId/topicId、想快速看这条话题下的全部回复(谁在什么时间回复了什么),而不想拿到一大坨原始消息字段时使用;内部按 --group(群会话 ID)和 --thread-id(兼容 --topic-id)拉取该话题的回复列表,可选 --time 指定起始时间、--limit 指定每页条数,再在本地投影出每条回复的发言人、文本和回复时间。默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。\n\n参数约束:\n - --thread-id 与兼容参数 --topic-id 必须且只能指定一个\n - --output-dir 必须是工作目录内的相对路径,不允许绝对路径或 .. 逃逸",
|
||||
"description": "当你已经拿到某个群里一条「话题消息」的 threadId/topicId、想快速看这条话题下的全部回复(谁在什么时间回复了什么),而不想拿到一大坨原始消息字段时使用;内部按 --group(群会话 ID)和 --thread-id(兼容 --topic-id)拉取该话题的回复列表,可选 --time 指定起始时间、--limit 指定每页条数,再在本地投影出每条回复的发言人、文本和回复时间。默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。\n\n参数约束:\n - --thread-id 与兼容参数 --topic-id 必须且只能指定一个\n - --output-dir 必须是工作目录内的相对路径,不允许绝对路径或 .. 逃逸",
|
||||
"effect": "read",
|
||||
"idempotency": "idempotent",
|
||||
"interface_mode": "composite",
|
||||
@@ -10981,7 +10981,7 @@
|
||||
"risk": "low",
|
||||
"title": "拉取某条话题消息的全部回复并投影出发言人/文本/时间",
|
||||
"use_when": [
|
||||
"当你已经拿到某个群里一条「话题消息」的 threadId/topicId、想快速看这条话题下的全部回复(谁在什么时间回复了什么),而不想拿到一大坨原始消息字段时使用;内部按 --group(群会话 ID)和 --thread-id(兼容 --topic-id)拉取该话题的回复列表,可选 --time 指定起始时间、--limit 指定每页条数,再在本地投影出每条回复的发言人、文本和回复时间。默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你已经拿到某个群里一条「话题消息」的 threadId/topicId、想快速看这条话题下的全部回复(谁在什么时间回复了什么),而不想拿到一大坨原始消息字段时使用;内部按 --group(群会话 ID)和 --thread-id(兼容 --topic-id)拉取该话题的回复列表,可选 --time 指定起始时间、--limit 指定每页条数,再在本地投影出每条回复的发言人、文本和回复时间。默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1161,7 +1161,7 @@
|
||||
"availability": "available",
|
||||
"interface_reason": "Reviewed built-in Shortcut adapter: it routes group or direct-message history reads, projects a stable message shape, and optionally orchestrates safe resource downloads with a failure ledger.",
|
||||
"reviewed": true,
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable Shortcut and group/direct lower read tools. Optional downloads stay read/not_required under the existing safe local-download convention: workspace-relative paths, no overwrite by default, and atomic publication.",
|
||||
"cli_path": "chat +chat-messages",
|
||||
"runtime_gate": "none"
|
||||
},
|
||||
@@ -1239,7 +1239,7 @@
|
||||
"availability": "available",
|
||||
"interface_reason": "Reviewed built-in shortcut adapter: the executable CLI owns validation, optional multi-step orchestration, output projection, and confirmation; the complete command contract is not represented by one pinned MCP interface_ref.",
|
||||
"reviewed": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"cli_path": "chat +messages-mget",
|
||||
"runtime_gate": "none"
|
||||
},
|
||||
@@ -1304,7 +1304,7 @@
|
||||
"availability": "available",
|
||||
"interface_reason": "Reviewed built-in shortcut adapter: the executable CLI owns validation, optional multi-step orchestration, output projection, and confirmation; the complete command contract is not represented by one pinned MCP interface_ref.",
|
||||
"reviewed": true,
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. The published default remains read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the built-in Shortcut registry and mounted Cobra command. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"cli_path": "chat +at-me",
|
||||
"runtime_gate": "none"
|
||||
},
|
||||
@@ -1369,7 +1369,7 @@
|
||||
"availability": "available",
|
||||
"interface_reason": "Reviewed search adapter: it combines filters, cursor pagination, batched mget enrichment, stable projection, completeness accounting, and optional safe resource downloads.",
|
||||
"reviewed": true,
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable advanced-search flags plus page and enrichment ledgers. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"cli_path": "chat +search-msg",
|
||||
"runtime_gate": "none"
|
||||
},
|
||||
@@ -1395,7 +1395,7 @@
|
||||
"availability": "available",
|
||||
"interface_reason": "Reviewed thread reader adapter: it accepts threadId/topicId, reads lower topic replies, projects stable message fields, and optionally downloads reply resources safely.",
|
||||
"reviewed": true,
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. The published default is read-only; runtime risk escalates to write when --download-resources opts into local file writes.",
|
||||
"review_reason": "Reviewed against the executable thread/topic alias contract and real list_topic_replies mapping. Optional downloads stay read/not_required under the existing safe local-download convention and therefore do not create a non-interactive confirmation no-op.",
|
||||
"cli_path": "chat +thread-replies",
|
||||
"runtime_gate": "none"
|
||||
},
|
||||
|
||||
@@ -2113,7 +2113,7 @@
|
||||
"chat.shortcut_chat_messages": {
|
||||
"agent_summary": "拉取某个会话(群聊或单聊)的消息列表并投影出发言人/文本/时间",
|
||||
"use_when": [
|
||||
"当你想快速看某个会话里的消息(谁在什么时间说了什么),而不想拿到一大坨原始消息字段时使用;群聊传 --group(群会话 ID,openConversationId),单聊传 --user(对方 userId),两者互斥且必须二选一。省略 --time 时默认从当前时间向前读取最近消息;也可指定时间边界并用 --direction newer/older 控制方向。内部据此调用群聊或单聊的消息列表接口,再在本地投影出每条消息的发言人、文本和时间。默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你想快速看某个会话里的消息(谁在什么时间说了什么),而不想拿到一大坨原始消息字段时使用;群聊传 --group(群会话 ID,openConversationId),单聊传 --user(对方 userId),两者互斥且必须二选一。省略 --time 时默认从当前时间向前读取最近消息;也可指定时间边界并用 --direction newer/older 控制方向。内部据此调用群聊或单聊的消息列表接口,再在本地投影出每条消息的发言人、文本和时间。默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"avoid_when": [
|
||||
"要跨多个会话按关键词、发送者或消息类型检索时使用 +search-msg;已有一批精确消息 ID 时使用 +messages-mget"
|
||||
@@ -2133,7 +2133,7 @@
|
||||
"chat.shortcut_messages_send": {
|
||||
"agent_summary": "统一发送文本、Markdown、当前用户文件或已有 mediaId 图片",
|
||||
"use_when": [
|
||||
"当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。"
|
||||
"当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;--user 传 userId 时包括在 --dry-run 中也会先只读解析为 openDingTalkId。bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。"
|
||||
],
|
||||
"avoid_when": [
|
||||
"需要 bot/webhook 发送媒体、卡片或 thread 回复时不要假设等价支持;改用真实存在的专用下层命令,缺少下层能力时停止"
|
||||
@@ -2172,7 +2172,7 @@
|
||||
"chat.shortcut_messages_send_card": {
|
||||
"agent_summary": "创建流式卡片,可在同一次调用中写入内容并结束",
|
||||
"use_when": [
|
||||
"当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId 二选一。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。"
|
||||
"当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId/openDingTalkId 二选一。单聊目标会统一解析后以 receiverOpenDingTalkId 传给下层;userId 包括在 --dry-run 时也会先做只读通讯录解析。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。"
|
||||
],
|
||||
"avoid_when": [
|
||||
"已有 bizId、只需要追加或更新现有卡片内容时使用 +messages-update-card"
|
||||
@@ -2230,7 +2230,7 @@
|
||||
"chat.shortcut_messages_mget": {
|
||||
"agent_summary": "根据消息 ID 批量查询消息(最多 50 条)",
|
||||
"use_when": [
|
||||
"当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger。默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger;本地下载路径受限于工作目录、默认不覆盖同名文件,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"avoid_when": [
|
||||
"需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令"
|
||||
@@ -2325,7 +2325,7 @@
|
||||
"chat.shortcut_at_me": {
|
||||
"agent_summary": "查最近 @我 的消息(自动算时间窗,投影发送人/时间/内容/会话)",
|
||||
"use_when": [
|
||||
"当你想快速看回最近谁在群里或单聊里 @了你、但不想手动把起止时间换算成毫秒、也不想记 list-mentions 的一堆参数时使用;内部按本地时区算出「最近 N 天」(默认 7 天,可用 --days 调整回溯天数)的时间窗,搜索这段时间内 @我 的消息,再在本地把每条消息投影成发送人、时间、内容、所在会话四个关键字段。默认只读且不会发送、撤回或标记任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你想快速看回最近谁在群里或单聊里 @了你、但不想手动把起止时间换算成毫秒、也不想记 list-mentions 的一堆参数时使用;内部按本地时区算出「最近 N 天」(默认 7 天,可用 --days 调整回溯天数)的时间窗,搜索这段时间内 @我 的消息,再在本地把每条消息投影成发送人、时间、内容、所在会话四个关键字段。默认只读且不会发送、撤回或标记任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"avoid_when": [
|
||||
"需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令"
|
||||
@@ -2422,7 +2422,7 @@
|
||||
"chat.shortcut_search_msg": {
|
||||
"agent_summary": "多维搜索消息,可全量翻页并批量富化详情",
|
||||
"use_when": [
|
||||
"当你要按关键词、发送者、@对象、会话、消息类型或机器人来源组合搜索 IM 消息时使用;默认查询近 7 天,也可指定精确起止时间。--page-all 会连续拉取游标页,默认再按消息 ID 分批富化详情;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger,绝不把截断结果标成完整。默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你要按关键词、发送者、@对象、会话、消息类型或机器人来源组合搜索 IM 消息时使用;默认查询近 7 天,也可指定精确起止时间。--page-all 会连续拉取游标页,默认再按消息 ID 分批富化详情;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger,绝不把截断结果标成完整。--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"avoid_when": [
|
||||
"只想读取一个已知会话的连续历史时使用 +chat-messages;已有精确消息 ID 时使用 +messages-mget"
|
||||
@@ -2461,7 +2461,7 @@
|
||||
"chat.shortcut_thread_replies": {
|
||||
"agent_summary": "拉取某条话题消息的全部回复并投影出发言人/文本/时间",
|
||||
"use_when": [
|
||||
"当你已经拿到某个群里一条「话题消息」的 threadId/topicId、想快速看这条话题下的全部回复(谁在什么时间回复了什么),而不想拿到一大坨原始消息字段时使用;内部按 --group(群会话 ID)和 --thread-id(兼容 --topic-id)拉取该话题的回复列表,可选 --time 指定起始时间、--limit 指定每页条数,再在本地投影出每条回复的发言人、文本和回复时间。默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。"
|
||||
"当你已经拿到某个群里一条「话题消息」的 threadId/topicId、想快速看这条话题下的全部回复(谁在什么时间回复了什么),而不想拿到一大坨原始消息字段时使用;内部按 --group(群会话 ID)和 --thread-id(兼容 --topic-id)拉取该话题的回复列表,可选 --time 指定起始时间、--limit 指定每页条数,再在本地投影出每条回复的发言人、文本和回复时间。默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。"
|
||||
],
|
||||
"avoid_when": [
|
||||
"要回复 Thread 或发送新回复时不要使用此读取入口;当前没有经过验证的 thread writer Shortcut"
|
||||
|
||||
@@ -16,7 +16,6 @@ package chat
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -527,9 +526,8 @@ var MessagesMget = shortcut.Shortcut{
|
||||
Command: "+messages-mget",
|
||||
Product: "im",
|
||||
Description: "根据消息 ID 批量查询消息(最多 50 条)",
|
||||
Intent: "当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger。默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。",
|
||||
Intent: "当你已有一批消息 openMsgId、需要批量取回完整详情、reaction 和可执行资源引用时使用;一次最多 50 条。--download-resources 可把所有可识别 mediaId/fileId 安全下载到工作目录内,并逐资源返回成功/失败 ledger;本地下载路径受限于工作目录、默认不覆盖同名文件,按既有安全下载约定无需交互确认。",
|
||||
Risk: shortcut.RiskRead,
|
||||
RiskWhen: MessageResourceDownloadRisk,
|
||||
Flags: append([]shortcut.Flag{
|
||||
{Name: "msg-ids", Type: shortcut.FlagStringSlice, Desc: "消息 openMsgId 列表;--msg-ids 去重后必须包含 1-50 条消息 ID", Required: true},
|
||||
{Name: "no-reactions", Type: shortcut.FlagBool, Desc: "不输出消息 reaction(默认输出)"},
|
||||
@@ -611,15 +609,6 @@ func ValidateMessageResourceDownload(rt *shortcut.RuntimeContext) error {
|
||||
return validateResourceDownloadOutputFlag(rt.Str("output-dir"), "--output-dir")
|
||||
}
|
||||
|
||||
// MessageResourceDownloadRisk keeps read-only invocations prompt-free while
|
||||
// requiring confirmation for the opt-in local file writes.
|
||||
func MessageResourceDownloadRisk(rt *shortcut.RuntimeContext) shortcut.Risk {
|
||||
if rt.Bool("download-resources") {
|
||||
return shortcut.RiskWrite
|
||||
}
|
||||
return shortcut.RiskRead
|
||||
}
|
||||
|
||||
// DownloadMessageResources downloads every unique message resource reference
|
||||
// and returns a per-resource success/failure ledger. A fallback conversation
|
||||
// ID lets group/thread list commands supply context when a mediaId item's lower
|
||||
@@ -681,18 +670,19 @@ func DownloadMessageResources(
|
||||
"requestedCount": len(resources),
|
||||
"deduplicatedCount": discoveredCount - len(resources),
|
||||
"downloadedCount": 0,
|
||||
"failedCount": 1,
|
||||
"failedCount": len(resources),
|
||||
"downloads": []map[string]any{},
|
||||
"failures": []map[string]any{{
|
||||
"stage": "output-directory",
|
||||
"error": fmt.Sprintf("读取工作目录失败: %v", err),
|
||||
"stage": "output-directory",
|
||||
"affectedCount": len(resources),
|
||||
"error": fmt.Sprintf("读取工作目录失败: %v", err),
|
||||
}},
|
||||
}
|
||||
}
|
||||
outputDir := strings.TrimRight(rt.Str("output-dir"), `/\`) + string(os.PathSeparator)
|
||||
outputDir := strings.TrimRight(rt.Str("output-dir"), `/\`)
|
||||
downloads := make([]map[string]any, 0, len(resources))
|
||||
failures := make([]map[string]any, 0)
|
||||
plannedNames := map[string]int{}
|
||||
downloadedNames := map[string]bool{}
|
||||
for _, resource := range resources {
|
||||
resourceType := strings.TrimSpace(fmt.Sprint(resource["type"]))
|
||||
if canonicalType, ok := canonicalMessageResourceType(resourceType); ok {
|
||||
@@ -744,18 +734,9 @@ func DownloadMessageResources(
|
||||
continue
|
||||
}
|
||||
preferredName := resourceDownloadPreferredName(data)
|
||||
output := outputDir
|
||||
filename := resourceDownloadFilename(resourceURL, preferredName)
|
||||
filenameKey := strings.ToLower(filename)
|
||||
plannedNames[filenameKey]++
|
||||
if plannedNames[filenameKey] > 1 {
|
||||
extension := filepath.Ext(filename)
|
||||
output = filepath.Join(
|
||||
strings.TrimRight(outputDir, `/\`),
|
||||
strings.TrimSuffix(filename, extension)+
|
||||
fmt.Sprintf(" (%d)", plannedNames[filenameKey])+extension,
|
||||
)
|
||||
}
|
||||
filename = disambiguateResourceDownloadFilename(filename, downloadedNames)
|
||||
output := filepath.Join(outputDir, filename)
|
||||
destPath, relativePath, pathErr := resolveResourceDownloadPath(
|
||||
cwd,
|
||||
output,
|
||||
@@ -783,6 +764,7 @@ func DownloadMessageResources(
|
||||
})
|
||||
continue
|
||||
}
|
||||
downloadedNames[strings.ToLower(filepath.Base(relativePath))] = true
|
||||
downloads = append(downloads, map[string]any{
|
||||
"resourceType": resourceType,
|
||||
"resourceId": resourceID,
|
||||
@@ -804,6 +786,20 @@ func DownloadMessageResources(
|
||||
}
|
||||
}
|
||||
|
||||
func disambiguateResourceDownloadFilename(filename string, used map[string]bool) string {
|
||||
if !used[strings.ToLower(filename)] {
|
||||
return filename
|
||||
}
|
||||
extension := filepath.Ext(filename)
|
||||
stem := strings.TrimSuffix(filename, extension)
|
||||
for sequence := 2; ; sequence++ {
|
||||
candidate := fmt.Sprintf("%s (%d)%s", stem, sequence, extension)
|
||||
if !used[strings.ToLower(candidate)] {
|
||||
return candidate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func uniqueShortcutStrings(values []string) []string {
|
||||
out := make([]string, 0, len(values))
|
||||
for _, value := range values {
|
||||
@@ -1006,11 +1002,11 @@ var MessagesSendCard = shortcut.Shortcut{
|
||||
Command: "+messages-send-card",
|
||||
Product: "im",
|
||||
Description: "创建流式卡片,可在同一次调用中写入内容并结束",
|
||||
Intent: "当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId 二选一。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。",
|
||||
Intent: "当你要发送一张流式卡片消息时使用;群 openConversationId 或单聊接收者 userId/openDingTalkId 二选一。单聊目标会统一解析后以 receiverOpenDingTalkId 传给下层;userId 包括在 --dry-run 时也会先做只读通讯录解析。只传目标时创建卡片并返回 bizId,供后续 messages-update-card 流式更新;同时传 --content 时会自动串联创建和更新,默认以 flowStatus=3 完成,避免卡片停留在加载中。",
|
||||
Risk: shortcut.RiskWrite,
|
||||
Flags: []shortcut.Flag{
|
||||
{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId(与 --receiver 互斥)"},
|
||||
{Name: "receiver", Type: shortcut.FlagString, Desc: "单聊接收者 userId(与 --group 互斥)"},
|
||||
{Name: "receiver", Type: shortcut.FlagString, Desc: "单聊接收者 userId 或 openDingTalkId(与 --group 互斥);userId 包括在 --dry-run 时也会先只读解析"},
|
||||
{Name: "content", Type: shortcut.FlagString, Desc: "创建后立即写入的卡片内容;省略时仅创建并返回 bizId"},
|
||||
{Name: "flow-status", Type: shortcut.FlagInt, Default: "3", Desc: "自动更新状态:1处理中/2输入中/3完成/4执行中/5错误;--flow-status 必须在 1-5 之间,且显式指定时必须同时提供 --content"},
|
||||
},
|
||||
@@ -1048,7 +1044,11 @@ var MessagesSendCard = shortcut.Shortcut{
|
||||
if group != "" {
|
||||
params["openConversationId"] = group
|
||||
} else {
|
||||
params["receiverUid"] = receiver
|
||||
openID, err := resolveUserOpenDingTalkID(rt, receiver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params["receiverOpenDingTalkId"] = openID
|
||||
}
|
||||
content := rt.Str("content")
|
||||
if content == "" {
|
||||
@@ -1109,7 +1109,8 @@ func findCardBizID(value any) string {
|
||||
case map[string]any:
|
||||
directKeys := []string{"bizId", "bizID", "biz_id"}
|
||||
for _, key := range directKeys {
|
||||
if candidate := strings.TrimSpace(fmt.Sprint(typed[key])); candidate != "" && candidate != "<nil>" {
|
||||
if candidate, ok := typed[key].(string); ok && strings.TrimSpace(candidate) != "" {
|
||||
candidate = strings.TrimSpace(candidate)
|
||||
return candidate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
package chat
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"testing"
|
||||
@@ -71,10 +73,21 @@ func TestCrossPlatformCoverageMgetResourceDownloadOutcomes(t *testing.T) {
|
||||
"im/list_messages_by_ids": readyMget,
|
||||
}})
|
||||
root := newPlatformCoverageRoot()
|
||||
var output bytes.Buffer
|
||||
root.SetOut(&output)
|
||||
root.SetArgs(baseArgs)
|
||||
if err := root.Execute(); err != nil {
|
||||
t.Fatalf("getwd ledger error = %v", err)
|
||||
}
|
||||
var payload map[string]any
|
||||
if err := json.Unmarshal(output.Bytes(), &payload); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ledger, _ := payload["resourceDownloads"].(map[string]any)
|
||||
if ledger["requestedCount"] != float64(1) ||
|
||||
ledger["failedCount"] != ledger["requestedCount"] {
|
||||
t.Fatalf("getwd ledger = %#v", ledger)
|
||||
}
|
||||
})
|
||||
|
||||
cases := []struct {
|
||||
@@ -129,3 +142,48 @@ func TestCrossPlatformCoverageMgetResourceDownloadOutcomes(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCrossPlatformCoverageMgetDownloadRunsWithoutConfirmation(t *testing.T) {
|
||||
resetResourceDownloadHooks(t)
|
||||
t.Chdir(t.TempDir())
|
||||
resourceDownload = func(
|
||||
_ context.Context,
|
||||
_ *http.Client,
|
||||
_ string,
|
||||
_ map[string]string,
|
||||
dest string,
|
||||
_ bool,
|
||||
) (int64, error) {
|
||||
return 7, nil
|
||||
}
|
||||
fake := &larkAlignmentCaller{responses: map[string]string{
|
||||
"im/list_messages_by_ids": `{"result":[{"openMessageId":"msg","openConversationId":"cid","content":"{\"mediaId\":\"@file\"}"}]}`,
|
||||
"im/get_resource_download_url": `{"result":{"resourceUrl":"https://download.dingtalk.com/resource.bin"}}`,
|
||||
}}
|
||||
helpers.InitDeps(fake)
|
||||
root := newPlatformCoverageRoot()
|
||||
var output bytes.Buffer
|
||||
root.SetOut(&output)
|
||||
root.SetIn(bytes.NewBuffer(nil))
|
||||
root.SetArgs([]string{
|
||||
"chat", "+messages-mget",
|
||||
"--msg-ids", "msg",
|
||||
"--download-resources",
|
||||
})
|
||||
if err := root.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(fake.calls) != 2 ||
|
||||
fake.calls[0].tool != "list_messages_by_ids" ||
|
||||
fake.calls[1].tool != "get_resource_download_url" {
|
||||
t.Fatalf("download calls = %#v", fake.calls)
|
||||
}
|
||||
var payload map[string]any
|
||||
if err := json.Unmarshal(output.Bytes(), &payload); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ledger, _ := payload["resourceDownloads"].(map[string]any)
|
||||
if ledger["downloadedCount"] != float64(1) || ledger["failedCount"] != float64(0) {
|
||||
t.Fatalf("download ledger = %#v", ledger)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -47,6 +48,17 @@ func TestMessagesSendPublishesCompleteIdentityConstraintInputs(t *testing.T) {
|
||||
if !strings.Contains(flag.Desc, "能力矩阵") {
|
||||
t.Errorf("--%s does not publish identity matrix semantics: %q", flag.Name, flag.Desc)
|
||||
}
|
||||
if flag.Name == "user" && !strings.Contains(flag.Desc, "--dry-run") {
|
||||
t.Errorf("--user does not publish dry-run contact resolution: %q", flag.Desc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCrossPlatformCoverageSafeResourceDownloadsStayReadOnly(t *testing.T) {
|
||||
for _, command := range []shortcut.Shortcut{MessagesMget, MessagesResourceDownload} {
|
||||
if command.Risk != shortcut.RiskRead || command.RiskWhen != nil {
|
||||
t.Errorf("%s risk contract = %q, dynamic=%v", command.Command, command.Risk, command.RiskWhen != nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,6 +380,55 @@ func TestCrossPlatformCoverageMessagesSendCardOneCallLifecycle(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCrossPlatformCoverageMessagesSendCardResolvesReceiverForLowerTool(t *testing.T) {
|
||||
fake := &larkAlignmentCaller{}
|
||||
helpers.InitDeps(fake)
|
||||
root := newPlatformCoverageRoot()
|
||||
root.SetArgs([]string{
|
||||
"chat", "+messages-send-card",
|
||||
"--receiver", "user-id",
|
||||
"--yes",
|
||||
})
|
||||
if err := root.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(fake.calls) != 2 ||
|
||||
fake.calls[0].product != "contact" ||
|
||||
fake.calls[0].tool != "get_user_info_by_user_ids" ||
|
||||
fake.calls[1].product != "im" ||
|
||||
fake.calls[1].tool != "create_and_send_card" {
|
||||
t.Fatalf("card receiver calls = %#v", fake.calls)
|
||||
}
|
||||
if got := fake.calls[1].args["receiverOpenDingTalkId"]; got != "D-resolved" {
|
||||
t.Fatalf("receiverOpenDingTalkId = %#v, want D-resolved", got)
|
||||
}
|
||||
if _, exists := fake.calls[1].args["receiverUid"]; exists {
|
||||
t.Fatalf("obsolete receiverUid leaked to lower tool: %#v", fake.calls[1].args)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCrossPlatformCoverageMessagesSendCardKeepsOpenReceiver(t *testing.T) {
|
||||
fake := &larkAlignmentCaller{}
|
||||
helpers.InitDeps(fake)
|
||||
root := newPlatformCoverageRoot()
|
||||
root.SetArgs([]string{
|
||||
"chat", "+messages-send-card",
|
||||
"--receiver", "D-direct",
|
||||
"--yes",
|
||||
})
|
||||
if err := root.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(fake.calls) != 1 ||
|
||||
fake.calls[0].product != "im" ||
|
||||
fake.calls[0].tool != "create_and_send_card" {
|
||||
t.Fatalf("card open receiver calls = %#v", fake.calls)
|
||||
}
|
||||
if got := fake.calls[0].args["receiverOpenDingTalkId"]; got != "D-direct" {
|
||||
t.Fatalf("receiverOpenDingTalkId = %#v, want D-direct", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCrossPlatformCoverageMessagesSendCardDryRunAndFailureBoundaries(t *testing.T) {
|
||||
t.Run("create only", func(t *testing.T) {
|
||||
fake := &larkAlignmentCaller{}
|
||||
@@ -403,18 +464,42 @@ func TestCrossPlatformCoverageMessagesSendCardDryRunAndFailureBoundaries(t *test
|
||||
if err := root.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(fake.calls) != 0 {
|
||||
t.Fatalf("card dry-run made lower calls: %#v", fake.calls)
|
||||
if len(fake.calls) != 1 ||
|
||||
fake.calls[0].product != "contact" ||
|
||||
fake.calls[0].tool != "get_user_info_by_user_ids" {
|
||||
t.Fatalf("card dry-run receiver resolution calls = %#v", fake.calls)
|
||||
}
|
||||
var payload map[string]any
|
||||
if err := json.Unmarshal(output.Bytes(), &payload); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if payload["actionCount"] != float64(2) {
|
||||
actions, _ := payload["actions"].([]any)
|
||||
create, _ := actions[0].(map[string]any)
|
||||
arguments, _ := create["arguments"].(map[string]any)
|
||||
if payload["actionCount"] != float64(2) ||
|
||||
arguments["receiverOpenDingTalkId"] != "D-resolved" {
|
||||
t.Fatalf("card plan = %#v", payload)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("receiver resolution error", func(t *testing.T) {
|
||||
fake := &larkAlignmentCaller{failProductTool: "contact/get_user_info_by_user_ids"}
|
||||
helpers.InitDeps(fake)
|
||||
root := newPlatformCoverageRoot()
|
||||
root.SetArgs([]string{
|
||||
"chat", "+messages-send-card",
|
||||
"--receiver", "user-id",
|
||||
"--yes",
|
||||
})
|
||||
err := root.Execute()
|
||||
if err == nil || !strings.Contains(err.Error(), "解析为 openDingTalkId 失败") {
|
||||
t.Fatalf("receiver resolution error = %v", err)
|
||||
}
|
||||
if len(fake.calls) != 1 || fake.calls[0].tool != "get_user_info_by_user_ids" {
|
||||
t.Fatalf("receiver resolution calls = %#v", fake.calls)
|
||||
}
|
||||
})
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
fake *larkAlignmentCaller
|
||||
@@ -488,6 +573,11 @@ func TestCrossPlatformCoverageFindCardBizIDResponseShapes(t *testing.T) {
|
||||
{map[string]any{
|
||||
"extension": map[string]any{"bizId": "fallback"},
|
||||
}, "fallback"},
|
||||
{map[string]any{
|
||||
"bizId": map[string]any{"x": 1},
|
||||
"result": map[string]any{"bizId": "typed"},
|
||||
}, "typed"},
|
||||
{map[string]any{"bizId": map[string]any{"x": 1}}, ""},
|
||||
{`{"result":{"bizId":"json"}}`, "json"},
|
||||
{`[{"bizId":"array-json"}]`, "array-json"},
|
||||
{`{"bizId":`, ""},
|
||||
@@ -684,6 +774,68 @@ func TestCrossPlatformCoverageMessageResourceDownloadDisambiguatesSameNames(t *t
|
||||
}
|
||||
}
|
||||
|
||||
func TestCrossPlatformCoverageResourceDownloadFilenameCollisionSequence(t *testing.T) {
|
||||
used := map[string]bool{}
|
||||
first := disambiguateResourceDownloadFilename("a.txt", used)
|
||||
used[strings.ToLower(first)] = true
|
||||
second := disambiguateResourceDownloadFilename("a.txt", used)
|
||||
used[strings.ToLower(second)] = true
|
||||
third := disambiguateResourceDownloadFilename("a (2).txt", used)
|
||||
if first != "a.txt" || second != "a (2).txt" || third != "a (2) (2).txt" {
|
||||
t.Fatalf("collision sequence = %q, %q, %q", first, second, third)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCrossPlatformCoverageFailedResourceDownloadDoesNotConsumeFilename(t *testing.T) {
|
||||
resetResourceDownloadHooks(t)
|
||||
t.Chdir(t.TempDir())
|
||||
destinations := make([]string, 0, 2)
|
||||
attempt := 0
|
||||
resourceDownload = func(
|
||||
_ context.Context,
|
||||
_ *http.Client,
|
||||
_ string,
|
||||
_ map[string]string,
|
||||
dest string,
|
||||
_ bool,
|
||||
) (int64, error) {
|
||||
destinations = append(destinations, filepath.Base(dest))
|
||||
attempt++
|
||||
if attempt == 1 {
|
||||
return 0, errors.New("fixture download failed")
|
||||
}
|
||||
return 1, nil
|
||||
}
|
||||
helpers.InitDeps(&larkAlignmentCaller{responses: map[string]string{
|
||||
"drive/download_file": `{"result":{"downloadUrl":"https://download.dingtalk.com/opaque","fileName":"fixture.txt"}}`,
|
||||
}})
|
||||
|
||||
var ledger map[string]any
|
||||
shortcut.Register(shortcut.Shortcut{
|
||||
Service: "chat",
|
||||
Command: "+gap-failed-colliding-resource-download",
|
||||
Flags: MessageResourceDownloadFlags(),
|
||||
Execute: func(rt *shortcut.RuntimeContext) error {
|
||||
ledger = DownloadMessageResources(rt, []map[string]any{
|
||||
{"fileId": "file-a"},
|
||||
{"fileId": "file-b"},
|
||||
}, "")
|
||||
return nil
|
||||
},
|
||||
})
|
||||
root := newPlatformCoverageRoot()
|
||||
root.SetArgs([]string{"chat", "+gap-failed-colliding-resource-download", "--output-dir", "./downloads"})
|
||||
if err := root.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(destinations, []string{"fixture.txt", "fixture.txt"}) {
|
||||
t.Fatalf("failed download consumed a filename: %#v", destinations)
|
||||
}
|
||||
if ledger["downloadedCount"] != 1 || ledger["failedCount"] != 1 {
|
||||
t.Fatalf("download ledger = %#v", ledger)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCrossPlatformCoverageMessageResourceDownloadRequiresMediaContextOnly(t *testing.T) {
|
||||
helpers.InitDeps(&larkAlignmentCaller{})
|
||||
root := newPlatformCoverageRoot()
|
||||
|
||||
@@ -58,8 +58,8 @@ var MessagesResourceDownload = shortcut.Shortcut{
|
||||
Description: "安全下载消息资源(图片/视频/语音/文件)到本地",
|
||||
Intent: "当你需要拿到消息里的实际图片、视频、语音或钉盘文件,而不只是资源 ID 时使用;" +
|
||||
"mediaId 用消息和会话身份换取下载地址,fileId 复用钉盘下载能力,再安全写入工作目录内的相对路径。" +
|
||||
"默认不覆盖已有文件,只有显式传 --overwrite 才覆盖。",
|
||||
Risk: shortcut.RiskWrite,
|
||||
"默认不覆盖已有文件,只有显式传 --overwrite 才覆盖;按既有安全本地下载约定无需交互确认。",
|
||||
Risk: shortcut.RiskRead,
|
||||
Flags: []shortcut.Flag{
|
||||
{Name: "type", Type: shortcut.FlagString, Default: "mediaId", Desc: "资源类型", Enum: []string{"mediaId", "fileId"}},
|
||||
{Name: "resource-id", Type: shortcut.FlagString, Desc: "消息中的 mediaId 或 fileId", Required: true},
|
||||
|
||||
@@ -28,14 +28,14 @@ var MessagesSend = shortcut.Shortcut{
|
||||
Command: "+messages-send",
|
||||
Product: "chat",
|
||||
Description: "统一发送文本、Markdown、当前用户文件或已有 mediaId 图片",
|
||||
Intent: "当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。",
|
||||
Intent: "当你希望用同一个入口选择 current-user、bot 或 webhook 身份发送消息时使用;命令会按身份校验目标、内容和凭据并路由到真实下层。current-user 支持文本/Markdown、已有 mediaId 图片、安全相对路径文件上传和幂等键;--user 传 userId 时包括在 --dry-run 中也会先只读解析为 openDingTalkId。bot 支持群聊或批量单聊文本/Markdown;webhook 的目标由 token 所在群决定。不会把 user 文件能力伪装成 bot/webhook 等价能力。",
|
||||
Risk: shortcut.RiskWrite,
|
||||
Flags: []shortcut.Flag{
|
||||
{Name: "identity", Type: shortcut.FlagString, Default: "user", Enum: []string{"user", "bot", "webhook"}, Desc: "发送身份;目标、凭据和幂等参数受发送身份能力矩阵约束"},
|
||||
{Name: "as", Type: shortcut.FlagString, Enum: []string{"user", "bot", "webhook"}, Desc: "--identity 的 lark-cli 对齐别名;受发送身份能力矩阵约束"},
|
||||
{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId(user/bot 群聊);受发送身份能力矩阵约束"},
|
||||
{Name: "chat-id", Type: shortcut.FlagString, Desc: "--group 的 lark-cli 对齐别名;受发送身份能力矩阵约束"},
|
||||
{Name: "user", Type: shortcut.FlagString, Desc: "单聊接收者 userId(user;自动解析 openDingTalkId);受发送身份能力矩阵约束"},
|
||||
{Name: "user", Type: shortcut.FlagString, Desc: "单聊接收者 userId(user;包括 --dry-run 也会先只读解析 openDingTalkId);受发送身份能力矩阵约束"},
|
||||
{Name: "open-dingtalk-id", Type: shortcut.FlagString, Desc: "单聊接收者 openDingTalkId(user);受发送身份能力矩阵约束"},
|
||||
{Name: "users", Type: shortcut.FlagStringSlice, Desc: "批量单聊接收者 userId(bot);受发送身份能力矩阵约束"},
|
||||
{Name: "open-dingtalk-ids", Type: shortcut.FlagStringSlice, Desc: "批量单聊接收者 openDingTalkId(bot);受发送身份能力矩阵约束"},
|
||||
@@ -359,18 +359,29 @@ func messagesSendUserTarget(rt *shortcut.RuntimeContext) (group, openID string,
|
||||
if openID != "" || group != "" {
|
||||
return group, openID, nil
|
||||
}
|
||||
userID := rt.Str("user")
|
||||
openID, err = resolveUserOpenDingTalkID(rt, rt.Str("user"))
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return "", openID, nil
|
||||
}
|
||||
|
||||
func resolveUserOpenDingTalkID(rt *shortcut.RuntimeContext, userID string) (string, error) {
|
||||
userID = strings.TrimSpace(userID)
|
||||
if isOpenID(userID) {
|
||||
return userID, nil
|
||||
}
|
||||
data, err := rt.CallMCPData("contact", "get_user_info_by_user_ids", map[string]any{
|
||||
"user_id_list": []string{userID},
|
||||
})
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("把 --user 解析为 openDingTalkId 失败: %w", err)
|
||||
return "", fmt.Errorf("把 userId 解析为 openDingTalkId 失败: %w", err)
|
||||
}
|
||||
openID = findOpenDingTalkID(data)
|
||||
openID := findOpenDingTalkID(data)
|
||||
if openID == "" {
|
||||
return "", "", apperrors.NewValidation("无法把 --user 解析为 openDingTalkId;请改传 --open-dingtalk-id")
|
||||
return "", apperrors.NewValidation("无法把 userId 解析为 openDingTalkId;请改传 openDingTalkId")
|
||||
}
|
||||
return "", openID, nil
|
||||
return openID, nil
|
||||
}
|
||||
|
||||
func executeMessagesSendUserFile(
|
||||
|
||||
@@ -322,7 +322,7 @@ func resourcesDeep(m map[string]any, inheritedConversationID string, depth int)
|
||||
return out
|
||||
}
|
||||
|
||||
var mediaIDTextRE = regexp.MustCompile(`(?i)media[_-]?id\s*[:=]\s*["']?([^"'\s)\]}>,]+)`)
|
||||
var mediaIDTextRE = regexp.MustCompile(`(?i)\bmedia[_-]?id\s*[:=]\s*["']?([^"'\s)\]}>,]+)`)
|
||||
var fileIDTextRE = regexp.MustCompile(`(?i)\bfile[_-]?id\s*[:=]\s*["']?([^"'\s)\]}>,]+)`)
|
||||
|
||||
func collectResourceIDs(value any, targetKey string, textPattern *regexp.Regexp, out *[]string) {
|
||||
|
||||
@@ -431,6 +431,17 @@ func TestResourcesReportsMissingDownloadContext(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourcesTextMediaIDRequiresWordBoundary(t *testing.T) {
|
||||
resources := Resources(map[string]any{
|
||||
"openMessageId": "msg-1",
|
||||
"openConversationId": "cid-1",
|
||||
"content": `notmediaId=@false mediaId=@real`,
|
||||
})
|
||||
if len(resources) != 1 || resources[0]["resourceId"] != "@real" {
|
||||
t.Fatalf("resources = %#v, want only the bounded mediaId", resources)
|
||||
}
|
||||
}
|
||||
|
||||
func TestForwarded(t *testing.T) {
|
||||
var project func(m map[string]any) map[string]any
|
||||
project = func(m map[string]any) map[string]any {
|
||||
|
||||
@@ -487,7 +487,7 @@
|
||||
},
|
||||
"+messages-mget": {
|
||||
"disposition": "semantic_adapter",
|
||||
"semantic_delta": "按最多 50 个消息 ID 批量读取并输出稳定消息投影、reaction 与 resourceRefs;可用 --download-resources 统一下载 mediaId 与 fileId,复用受信任下载域、相对路径、无覆盖和原子落盘防护,对重复资源去重并逐资源返回下载失败 ledger;默认只读,启用下载时运行时风险升级为 write。",
|
||||
"semantic_delta": "按最多 50 个消息 ID 批量读取并输出稳定消息投影、reaction 与 resourceRefs;可用 --download-resources 统一下载 mediaId 与 fileId,复用受信任下载域、相对路径、无覆盖和原子落盘防护,对重复资源去重并逐资源返回下载失败 ledger;安全本地下载沿用 read/not_required 契约,不产生非交互确认盲区。",
|
||||
"risk": "read",
|
||||
"public": true,
|
||||
"reviewed": true
|
||||
@@ -565,7 +565,7 @@
|
||||
"+messages-resource-download": {
|
||||
"disposition": "primary_smart",
|
||||
"semantic_delta": "统一承接消息 mediaId 与钉盘 fileId:分别复用 IM 临时资源 URL 和 drive.download_file,只允许钉钉/OSS HTTPS 下载域且重定向复验并隔离跨域凭据,再通过工作目录内安全路径、默认不覆盖、临时文件下载和原子发布输出结构化结果。",
|
||||
"risk": "write",
|
||||
"risk": "read",
|
||||
"public": true,
|
||||
"reviewed": true
|
||||
},
|
||||
|
||||
@@ -52,9 +52,8 @@ var AtMe = shortcut.Shortcut{
|
||||
Intent: "当你想快速看回最近谁在群里或单聊里 @了你、但不想手动把起止时间换算成毫秒、也不想记 list-mentions 的一堆参数时使用;" +
|
||||
"内部按本地时区算出「最近 N 天」(默认 7 天,可用 --days 调整回溯天数)的时间窗,搜索这段时间内 @我 的消息," +
|
||||
"再在本地把每条消息投影成发送人、时间、内容、所在会话四个关键字段。" +
|
||||
"默认只读且不会发送、撤回或标记任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。",
|
||||
Risk: shortcut.RiskRead,
|
||||
RiskWhen: chatshortcut.MessageResourceDownloadRisk,
|
||||
"默认只读且不会发送、撤回或标记任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。",
|
||||
Risk: shortcut.RiskRead,
|
||||
Flags: append([]shortcut.Flag{
|
||||
{Name: "days", Type: shortcut.FlagInt, Desc: "回溯天数(可选,默认 7)", Default: "7", Required: false},
|
||||
{Name: "limit", Type: shortcut.FlagInt, Desc: "每页返回数量(默认 50)", Default: "50"},
|
||||
|
||||
@@ -57,9 +57,8 @@ var ChatMessages = shortcut.Shortcut{
|
||||
"群聊传 --group(群会话 ID,openConversationId),单聊传 --user(对方 userId),两者互斥且必须二选一。" +
|
||||
"省略 --time 时默认从当前时间向前读取最近消息;也可指定时间边界并用 --direction newer/older 控制方向。" +
|
||||
"内部据此调用群聊或单聊的消息列表接口,再在本地投影出每条消息的发言人、文本和时间。" +
|
||||
"默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。",
|
||||
Risk: shortcut.RiskRead,
|
||||
RiskWhen: chatshortcut.MessageResourceDownloadRisk,
|
||||
"默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。",
|
||||
Risk: shortcut.RiskRead,
|
||||
Flags: append([]shortcut.Flag{
|
||||
{Name: "group", Type: shortcut.FlagString, Desc: "群会话 ID(openConversationId),与 --user 互斥"},
|
||||
{Name: "conversation-id", Type: shortcut.FlagString, Desc: "--group 的别名", Hidden: true},
|
||||
|
||||
@@ -10,8 +10,17 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/helpers"
|
||||
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/shortcut"
|
||||
)
|
||||
|
||||
func TestCrossPlatformCoverageSafeResourceQueryDownloadsStayReadOnly(t *testing.T) {
|
||||
for _, command := range []shortcut.Shortcut{AtMe, ChatMessages, SearchMsg, ThreadReplies} {
|
||||
if command.Risk != shortcut.RiskRead || command.RiskWhen != nil {
|
||||
t.Errorf("%s risk contract = %q, dynamic=%v", command.Command, command.Risk, command.RiskWhen != nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCrossPlatformCoverageMessageReadShortcutsPublishResourceDownloadPlans(t *testing.T) {
|
||||
message := `{"openMessageId":"msg","openConversationId":"cid","content":"{\"mediaId\":\"@image\"}","quotedMessage":{"openMessageId":"quoted","content":"{\"fileId\":\"@quoted-file\"}"}}`
|
||||
tests := []struct {
|
||||
|
||||
@@ -37,9 +37,8 @@ var SearchMsg = shortcut.Shortcut{
|
||||
Description: "多维搜索消息,可全量翻页并批量富化详情",
|
||||
Intent: "当你要按关键词、发送者、@对象、会话、消息类型或机器人来源组合搜索 IM 消息时使用;默认查询近 7 天," +
|
||||
"也可指定精确起止时间。--page-all 会连续拉取游标页,默认再按消息 ID 分批富化详情;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger,绝不把截断结果标成完整。" +
|
||||
"默认只读;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。",
|
||||
Risk: shortcut.RiskRead,
|
||||
RiskWhen: chatshortcut.MessageResourceDownloadRisk,
|
||||
"--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。",
|
||||
Risk: shortcut.RiskRead,
|
||||
Flags: append([]shortcut.Flag{
|
||||
{Name: "query", Type: shortcut.FlagString, Desc: "搜索关键词"},
|
||||
{Name: "keyword", Type: shortcut.FlagString, Desc: "--query 的别名", Hidden: true},
|
||||
|
||||
@@ -42,9 +42,8 @@ var ThreadReplies = shortcut.Shortcut{
|
||||
Intent: "当你已经拿到某个群里一条「话题消息」的 threadId/topicId、想快速看这条话题下的全部回复(谁在什么时间回复了什么)," +
|
||||
"而不想拿到一大坨原始消息字段时使用;内部按 --group(群会话 ID)和 --thread-id(兼容 --topic-id)拉取该话题的回复列表," +
|
||||
"可选 --time 指定起始时间、--limit 指定每页条数,再在本地投影出每条回复的发言人、文本和回复时间。" +
|
||||
"默认只读且不会发送或修改任何消息;传 --download-resources 时会在工作目录写文件,因此命令按本地写入操作确认。",
|
||||
Risk: shortcut.RiskRead,
|
||||
RiskWhen: chatshortcut.MessageResourceDownloadRisk,
|
||||
"默认只读且不会发送或修改任何消息;--download-resources 使用工作目录内安全路径、默认不覆盖和原子落盘,按既有安全下载约定无需交互确认。",
|
||||
Risk: shortcut.RiskRead,
|
||||
Flags: append([]shortcut.Flag{
|
||||
{Name: "group", Type: shortcut.FlagString, Desc: "群会话 ID(openConversationId,必填)", Required: true},
|
||||
{Name: "thread-id", Type: shortcut.FlagString, Desc: "话题/线程 ID(可直接使用消息列表返回的 threadId)"},
|
||||
|
||||
@@ -315,7 +315,7 @@ dws chat +messages-send --as user --open-dingtalk-id <openDingTalkId> --msg-type
|
||||
|
||||
资源读取优先在 `+at-me`、`+chat-messages`、`+messages-mget`、`+search-msg`、`+thread-replies` 上加 `--download-resources`。引用、回复或合并转发里的资源使用结果 `resourceRefs` 自带的子消息 `messageId`;子消息没有会话 ID 时才继承父消息会话。单独下载一个资源时用 `+messages-resource-download`,输出必须是工作目录内的相对路径,默认拒绝覆盖。
|
||||
|
||||
上述五个查询 Shortcut 的默认 leaf Schema 契约是 `read/not_required`;仅显式传 `--download-resources` 时,运行时风险升级为 `write` 并要求确认。确认输出目录和覆盖策略、获得用户确认后才加 `--yes`。
|
||||
上述五个查询 Shortcut 与 `+messages-resource-download` 都沿用安全本地下载的 `read/not_required` 契约,不应添加 `--yes` 或触发交互确认。输出只允许工作目录内相对路径、默认不覆盖并原子落盘;需要覆盖时必须由用户显式传 `--overwrite`。
|
||||
|
||||
**不支持的场景**:
|
||||
- "撤回我刚发的消息"(但不知道消息 ID) — 需先通过消息拉取或搜索接口(如 `chat message list`、`chat message search-advanced` 等)获取 openMessageId,再调用 `chat message recall`
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
- `+messages-send` 会自动规范化并补齐 @ 占位符。user 使用 `<@id>` / `<@all>`;bot/webhook 使用 `@id` / `@手机号` / `@all`。声明 `--at-*` / `--at-all` 即可,不要为统一 Shortcut 手工拼 `@10`。
|
||||
- `+search-msg --page-all` 连续翻页并默认按消息 ID 批量富化;任何续页或富化失败都会保留已取得结果并返回逐项失败 ledger。
|
||||
- `+at-me`、`+chat-messages`、`+messages-mget`、`+search-msg`、`+thread-replies` 可用 `--download-resources` 下载资源。引用、回复、合并转发中的资源使用结果 `resourceRefs` 自带的子消息 `messageId`;仅当子消息缺会话 ID 时继承父消息 `openConversationId`。
|
||||
- 上述五个查询 Shortcut 的默认 Schema 契约是 `read/not_required`;仅显式传 `--download-resources` 时,运行时风险升级为 `write` 并要求确认。`+messages-resource-download` 始终写本地。确认相对输出目录和覆盖策略后才加 `--yes`,默认拒绝覆盖已有文件。
|
||||
- 上述五个查询 Shortcut 与 `+messages-resource-download` 都沿用安全本地下载的 `read/not_required` 契约,不应添加 `--yes` 或触发交互确认。下载只允许工作目录内相对路径、默认不覆盖并原子落盘;需要覆盖时必须由用户显式传 `--overwrite`。
|
||||
- 下载器仅接受经审查的钉钉与公网 OSS HTTPS 地址并逐跳校验重定向;跨主机时不会转发下层提供的请求头。新官方域名被拒绝时记录错误中的 host 供审查,不要放宽为任意 HTTPS。
|
||||
|
||||
### group (群组管理)
|
||||
|
||||
@@ -128,7 +128,7 @@ metadata:
|
||||
- 统一发送优先用 `chat +messages-send`:通过 `--as user|bot|webhook` 选择身份,并只传该身份真实支持的目标、内容和凭据。仅在需要原子命令的特定返回结构或兼容参数时,才降级到 `chat message send` / `send-by-bot` / `send-by-webhook`。
|
||||
- 消息查询按意图选择:指定会话用 `+chat-messages`,跨维度过滤/全量翻页用 `+search-msg`,@我用 `+at-me`,已知消息 ID 批量富化用 `+messages-mget`,已知 thread/topic ID 读取回复用 `+thread-replies`。
|
||||
- 查询结果中的 `resourceRefs` 是可继续执行的资源上下文。引用、回复或合并转发中的子消息必须使用该子消息返回的 `messageId`;子消息缺会话 ID 时才继承父消息的 `openConversationId`。
|
||||
- 上述五个查询 Shortcut 默认按 `read/not_required` 执行;仅显式传 `--download-resources` 时,运行时风险升级为 `write` 并要求确认。`+messages-resource-download` 始终是写操作。确认目标目录和覆盖策略后才加 `--yes`。
|
||||
- 上述五个查询 Shortcut 与 `+messages-resource-download` 都沿用安全本地下载的 `read/not_required` 契约,不应添加 `--yes` 或触发交互确认。下载只允许工作目录内相对路径、默认不覆盖并原子落盘;需要覆盖时必须由用户显式传 `--overwrite`。
|
||||
- `+messages-send` 会按身份规范化 @ 占位符:user 使用 `<@id>` / `<@all>`,bot/webhook 使用 `@id` / `@手机号` / `@all`;只需声明 `--at-*` / `--at-all`,缺失占位符会自动补齐。
|
||||
|
||||
## 意图表
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
|
||||
- `+messages-send` 只暴露下层真实支持的身份能力,并自动规范化、补齐对应身份的 @ 占位符。
|
||||
- `+search-msg --page-all` 连续翻页并默认按消息 ID 批量富化;续页或富化失败会保留已取得结果并返回逐项失败 ledger。
|
||||
- 五个查询 Shortcut 默认纯只读;显式传 `--download-resources` 时才在运行时升级为 `write` 并要求确认。引用、回复、合并转发中的资源使用 `resourceRefs` 自带的子消息 `messageId`;仅当子消息缺会话 ID 时继承父消息 `openConversationId`。
|
||||
- `+messages-resource-download` 始终写本地。确认相对输出目录和覆盖策略后才加 `--yes`,默认拒绝覆盖已有文件。
|
||||
- 五个查询 Shortcut 的 `--download-resources` 沿用安全本地下载的 `read/not_required` 契约,不应添加 `--yes` 或触发交互确认。引用、回复、合并转发中的资源使用 `resourceRefs` 自带的子消息 `messageId`;仅当子消息缺会话 ID 时继承父消息 `openConversationId`。
|
||||
- `+messages-resource-download` 同样无需交互确认,但只允许工作目录内相对路径、默认拒绝覆盖并原子落盘;需要覆盖时必须由用户显式传 `--overwrite`。
|
||||
- 下载器只接受经审查的钉钉与公网 OSS HTTPS 地址并逐跳校验重定向;跨主机时不会转发下层提供的请求头。
|
||||
|
||||
## 适用范围与安全硬约束
|
||||
|
||||
Reference in New Issue
Block a user