chat

package
v1.0.54 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 21, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Package chat provides declarative shortcuts for the DingTalk chat service (群聊 / 会话 / 消息 / 机器人). Tool names and parameter keys are copied verbatim from internal/helpers/chat.go, the single source of truth for the real MCP tools. Shortcuts route to the correct MCP server via each Shortcut.Product:

  • "chat" (default): tools invoked via the plain helper callMCPTool path
  • "im": tools invoked via callMCPToolOnServer("im", ...)
  • "bot": tools invoked via callMCPToolOnServer("bot", ...)

Index

Constants

This section is empty.

Variables

View Source
var BotFind = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+bot-find",
	Product:     "bot",
	Description: "搜索全部可用机器人(含他人/官方,返回 openDingTalkId 可发单聊)",
	Intent:      "当你想找到平台上任意可用机器人(含他人创建或官方助手,例如某个日报/审批机器人)以便与其发起单聊时使用;输入关键词,返回含 openDingTalkId 的机器人列表。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "query", Type: shortcut.FlagString, Desc: "搜索关键词"},
		{Name: "keyword", Type: shortcut.FlagString, Desc: "--query 的别名", Hidden: true},
		{Name: "limit", Type: shortcut.FlagInt, Default: "20", Desc: "每页返回数量"},
		{Name: "cursor", Type: shortcut.FlagString, Desc: "分页游标,翻页传 nextCursor"},
	},
	Constraints: []shortcut.Constraint{
		{Kind: shortcut.ConstraintAtLeastOne, Flags: []string{"query", "keyword"}},
	},
	Tips: []string{`dws chat +bot-find --query "日报"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{"keyword": rt.StrFirst("query", "keyword")}
		if rt.Int("limit") > 0 {
			params["limit"] = rt.Int("limit")
		}
		if rt.Str("cursor") != "" {
			params["cursor"] = rt.Str("cursor")
		}
		data, err := rt.CallMCPData("bot", "search_bots", params)
		if err != nil {
			return err
		}
		bots := botFindProject(data)
		return rt.Output(map[string]any{"count": len(bots), "bots": bots})
	},
}

BotFind searches all available robots (search_bots, bot).

View Source
var BotSearch = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+bot-search",
	Product:     "bot",
	Description: "搜索当前用户自己创建的机器人",
	Intent:      "当你要管理或复用自己创建的机器人(比如查到其 robotCode 以便让它进群或发消息)时使用;按机器人名称模糊搜索,只返回当前用户名下创建的机器人列表。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "page", Type: shortcut.FlagInt, Default: "1", Desc: "页码"},
		{Name: "size", Type: shortcut.FlagInt, Desc: "每页数量"},
		{Name: "name", Type: shortcut.FlagString, Desc: "robotName 模糊匹配"},
	},
	Tips: []string{`dws chat +bot-search --page 1 --name "日报"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{"currentPage": rt.Int("page")}
		if rt.Int("size") > 0 {
			params["pageSize"] = rt.Int("size")
		}
		if rt.Str("name") != "" {
			params["robotName"] = rt.Str("name")
		}
		data, err := rt.CallMCPData("bot", "search_my_robots", params)
		if err != nil {
			return err
		}
		robots := botSearchProject(data)
		return rt.Output(map[string]any{"count": len(robots), "robots": robots})
	},
}

BotSearch searches robots created by the current user (search_my_robots, bot).

View Source
var CategoryAddConversation = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+category-add-conversation",
	Product:     "im",
	Description: "将会话移动到指定的自定义分组中",
	Intent:      "当你想把某个会话归入一个或多个自定义分组时使用;会实际把会话加入指定分组,需传会话 openConversationId 和目标分组 ID 列表。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "category-ids", Type: shortcut.FlagStringSlice, Desc: "目标分组 ID 列表", Required: true},
	},
	Tips: []string{`dws chat +category-add-conversation --group <openConversationId> --category-ids 123,456`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		ids, err := toInt64Slice(rt.StrSlice("category-ids"))
		if err != nil {
			return fmt.Errorf("--category-ids: %w", err)
		}
		return rt.CallMCP("add_conv_to_categories", map[string]any{
			"openConversationId": rt.Str("group"),
			"categoryIds":        ids,
		})
	},
}

CategoryAddConversation adds a conversation to categories (add_conv_to_categories, im).

View Source
var CategoryCreate = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+category-create",
	Product:     "im",
	Description: "创建用户自定义会话分组",
	Intent:      "当你想新建一个会话分组来归类会话时使用;会实际创建分组并返回其 ID,需传分组名称 --title。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "title", Type: shortcut.FlagString, Desc: "分组名称", Required: true},
	},
	Tips: []string{`dws chat +category-create --title "工作群"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("create_conv_category", map[string]any{"title": rt.Str("title")})
	},
}

CategoryCreate creates a conversation category (create_conv_category, im).

View Source
var CategoryDelete = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+category-delete",
	Product:     "im",
	Description: "删除用户自定义会话分组",
	Intent:      "当你想删除某个自定义会话分组时使用;会实际删除分组(不影响其中会话本身),不可逆,需传 categoryId。",
	Risk:        shortcut.RiskHighWrite,
	Flags: []shortcut.Flag{
		{Name: "category-id", Type: shortcut.FlagInt, Desc: "会话分组 ID", Required: true},
	},
	Tips: []string{`dws chat +category-delete --category-id <分组ID>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("delete_conv_category", map[string]any{"categoryId": rt.Int("category-id")})
	},
}

CategoryDelete deletes a conversation category (delete_conv_category, im).

View Source
var CategoryList = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+category-list",
	Product:     "im",
	Description: "获取用户自定义会话分组",
	Intent:      "当你想查看当前用户自建了哪些会话分组(如'工作群''项目群')时使用;只读返回分组列表及其 categoryId,供后续按分组拉会话或增删。",
	Risk:        shortcut.RiskRead,
	Tips:        []string{`dws chat +category-list`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		data, err := rt.CallMCPData("im", "list_user_define_conv_categories", map[string]any{})
		if err != nil {
			return err
		}
		categories := categoryListProject(data)
		return rt.Output(map[string]any{"count": len(categories), "categories": categories})
	},
}

CategoryList lists user-defined conversation categories (list_user_define_conv_categories, im).

View Source
var CategoryListConversations = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+category-list-conversations",
	Product:     "im",
	Description: "拉取指定自定义会话分组下的会话",
	Intent:      "当你想查看某个自定义会话分组里都归入了哪些会话时使用;只读,需传 categoryId,可用 --exclude-muted 排除已免打扰会话。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "category-id", Type: shortcut.FlagInt, Desc: "会话分组 ID", Required: true},
		{Name: "exclude-muted", Type: shortcut.FlagBool, Desc: "排除已免打扰会话"},
	},
	Tips: []string{`dws chat +category-list-conversations --category-id <分组ID>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{"categoryId": rt.Int("category-id")}
		if rt.Bool("exclude-muted") {
			params["excludeMuted"] = true
		}
		data, err := rt.CallMCPData("im", "list_conversations_by_category", params)
		if err != nil {
			return err
		}
		convs := categoryConversationsProject(data)
		payload := map[string]any{"count": len(convs), "conversations": convs}
		if v, ok := categoryConversationsFirst(data, "nextCursor", "cursor"); ok {
			payload["nextCursor"] = v
		}
		if v, ok := categoryConversationsFirst(data, "hasMore", "has_more"); ok {
			payload["hasMore"] = v
		}
		return rt.Output(payload)
	},
}

CategoryListConversations lists conversations in a category (list_conversations_by_category, im).

View Source
var CategoryRemoveConversation = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+category-remove-conversation",
	Product:     "im",
	Description: "将会话从指定的自定义分组中移出",
	Intent:      "当你想把某个会话从指定自定义分组中移出时使用;会实际从分组移除该会话(不删除会话本身),需传会话 openConversationId 和分组 ID 列表。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "category-ids", Type: shortcut.FlagStringSlice, Desc: "目标分组 ID 列表", Required: true},
	},
	Tips: []string{`dws chat +category-remove-conversation --group <openConversationId> --category-ids 123,456`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		ids, err := toInt64Slice(rt.StrSlice("category-ids"))
		if err != nil {
			return fmt.Errorf("--category-ids: %w", err)
		}
		return rt.CallMCP("remove_conv_from_categories", map[string]any{
			"openConversationId": rt.Str("group"),
			"categoryIds":        ids,
		})
	},
}

CategoryRemoveConversation removes a conversation from categories (remove_conv_from_categories, im).

View Source
var CategoryRename = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+category-rename",
	Product:     "im",
	Description: "更新用户自定义会话分组的名称",
	Intent:      "当你想重命名已有的自定义会话分组时使用;会实际更新分组名称,需传 categoryId 和新名称 --title。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "category-id", Type: shortcut.FlagInt, Desc: "会话分组 ID", Required: true},
		{Name: "title", Type: shortcut.FlagString, Desc: "新的分组名称", Required: true},
	},
	Tips: []string{`dws chat +category-rename --category-id <分组ID> --title "新名称"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("rename_conv_category", map[string]any{
			"categoryId": rt.Int("category-id"),
			"title":      rt.Str("title"),
		})
	},
}

CategoryRename renames a conversation category (rename_conv_category, im).

View Source
var ChatAddBot = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-add-bot",
	Product:     "bot",
	Description: "将机器人添加到群中",
	Intent:      "当你想把某个机器人添加进群(比如让日报机器人进群播报)时使用;会实际把机器人加入群聊,需传机器人 robotCode 和群 openConversationId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "robot-code", Type: shortcut.FlagString, Desc: "机器人 Code", Required: true},
		{Name: "id", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
	},
	Tips: []string{`dws chat +chat-add-bot --robot-code <robotCode> --id <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("add_robot_to_group", map[string]any{
			"robotCode":          rt.Str("robot-code"),
			"openConversationId": rt.Str("id"),
		})
	},
}

ChatAddBot adds a custom robot to a group (add_robot_to_group, bot).

View Source
var ChatAuditJoin = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-audit-join",
	Product:     "im",
	Description: "审批入群验证(通过/拒绝/删除/忽略/拉黑)",
	Intent:      "当你要处理某条入群申请时使用;会实际执行通过/拒绝/删除/忽略/拉黑动作,需传群 openConversationId、recordId、申请人与邀请人 userId 及 status。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "record-id", Type: shortcut.FlagInt, Desc: "申请记录 ID", Required: true},
		{Name: "applicant", Type: shortcut.FlagString, Desc: "申请人 userId", Required: true},
		{Name: "inviter", Type: shortcut.FlagString, Desc: "邀请人 userId", Required: true},
		{Name: "status", Type: shortcut.FlagString, Desc: "审批动作", Required: true, Enum: []string{"AuditApprove", "AuditDelete", "AuditIgnore", "AuditRefuse", "AuditBlock"}},
		{Name: "description", Type: shortcut.FlagString, Desc: "审批说明"},
	},
	Tips: []string{`dws chat +chat-audit-join --group <openConversationId> --record-id 123 --applicant <userId> --inviter <userId> --status AuditApprove`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{
			"openConversationId": rt.Str("group"),
			"applyRecordId":      rt.Int("record-id"),
			"applicantUid":       rt.Str("applicant"),
			"inviterUid":         rt.Str("inviter"),
			"status":             rt.Str("status"),
		}
		if rt.Changed("description") {
			params["auditDescription"] = rt.Str("description")
		}
		return rt.CallMCP("audit_join_group", params)
	},
}

ChatAuditJoin audits a join-validation record (audit_join_group, im).

View Source
var ChatBots = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-bots",
	Product:     "bot",
	Description: "查看群内所有机器人",
	Intent:      "当你想查看某个群里已添加了哪些机器人时使用;需传群 openConversationId,只读返回群内机器人列表(含 openBotId,供后续移除)。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
	},
	Tips: []string{`dws chat +chat-bots --group <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		data, err := rt.CallMCPData("bot", "list_group_bots", map[string]any{"openConversationId": rt.Str("group")})
		if err != nil {
			return err
		}
		bots := chatBotsProject(data)
		return rt.Output(map[string]any{"count": len(bots), "bots": bots})
	},
}

ChatBots lists robots in a group (list_group_bots, bot).

View Source
var ChatDismiss = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-dismiss",
	Product:     "im",
	Description: "解散群聊(不可逆,需群主权限)",
	Intent:      "当你要彻底解散一个群时使用;会实际销毁群聊,不可逆且需群主权限,仅需传群 openConversationId,操作前务必确认。",
	Risk:        shortcut.RiskHighWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
	},
	Tips: []string{`dws chat +chat-dismiss --group <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("dismiss_group", map[string]any{"openConversationId": rt.Str("group")})
	},
}

ChatDismiss dismisses (destroys) a group (dismiss_group, im).

View Source
var ChatGetByID = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-get-by-id",
	Product:     "im",
	Description: "根据群号获取群聊信息",
	Intent:      "当你只知道群号(数字)、需要换取群 openConversationId 及群信息时使用;只读,需传 --group-id。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "group-id", Type: shortcut.FlagInt, Desc: "群号(数字类型)", Required: true},
	},
	Tips: []string{`dws chat +chat-get-by-id --group-id 12345678`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("get_conv_info_by_group_id", map[string]any{"groupId": rt.Int("group-id")})
	},
}

ChatGetByID looks up a group by numeric group id (get_conv_info_by_group_id, im).

View Source
var ChatInviteURL = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-invite-url",
	Product:     "im",
	Description: "获取群邀请链接",
	Intent:      "当你想拿到一条群邀请链接分享给别人加群时使用;只读生成链接,需传群 openConversationId,可用 --expires-seconds 设置有效期(0 表示永久)。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "expires-seconds", Type: shortcut.FlagInt, Desc: "链接有效期(秒),0 表示永久"},
	},
	Tips: []string{`dws chat +chat-invite-url --group <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{
			"openConversationId": rt.Str("group"),
			"cid":                rt.Str("group"),
		}
		if rt.Changed("expires-seconds") {
			params["expiresSeconds"] = rt.Int("expires-seconds")
		}
		return rt.CallMCP("get_group_invite_url", params)
	},
}

ChatInviteURL gets the group invite url (get_group_invite_url, im).

View Source
var ChatListAll = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-list-all",
	Product:     "im",
	Description: "分页拉取我加入的所有群列表",
	Intent:      "当你想遍历当前用户加入的所有群做统计或批量操作时使用;只读分页返回全部已加入的群列表。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "limit", Type: shortcut.FlagInt, Default: "100", Desc: "每页返回数量(最大 200)"},
		{Name: "cursor", Type: shortcut.FlagString, Desc: "分页游标,翻页传 nextCursor"},
	},
	Tips: []string{`dws chat +chat-list-all --limit 50`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{}
		if rt.Int("limit") > 0 {
			params["limit"] = rt.Int("limit")
		}
		if c := rt.Str("cursor"); c != "" && c != "0" {
			params["cursor"] = c
		}
		data, err := rt.CallMCPData("im", "list_my_groups_pagination", params)
		if err != nil {
			return err
		}
		groups := chatListAllProject(data)
		payload := map[string]any{"count": len(groups), "groups": groups}
		if v, ok := chatGroupFirst(data, "nextCursor", "next_cursor", "cursor"); ok {
			payload["nextCursor"] = v
		}
		if v, ok := chatGroupFirst(data, "hasMore", "has_more"); ok {
			payload["hasMore"] = v
		}
		return rt.Output(payload)
	},
}

ChatListAll paginates all groups the caller joined (list_my_groups_pagination, im).

View Source
var ChatListJoinRequests = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-list-join-requests",
	Product:     "im",
	Description: "分页拉取入群验证记录",
	Intent:      "当你作为群主/管理员想查看待处理的入群申请时使用;只读分页返回入群验证记录(含 recordId、申请人与邀请人 ID),供后续用 chat-audit-join 审批。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "limit", Type: shortcut.FlagInt, Default: "20", Desc: "单页数量(最大 50)"},
		{Name: "cursor", Type: shortcut.FlagString, Desc: "分页游标,翻页传 nextCursor"},
	},
	Tips: []string{`dws chat +chat-list-join-requests --limit 30`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{}
		if rt.Int("limit") > 0 {
			params["limit"] = rt.Int("limit")
		}
		if rt.Changed("cursor") {
			params["cursor"] = rt.Str("cursor")
		}
		return rt.CallMCP("list_apply_join_group_records", params)
	},
}

ChatListJoinRequests paginates join-validation records (list_apply_join_group_records, im).

View Source
var ChatListMine = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-list-mine",
	Product:     "im",
	Description: "拉取我创建/管理的群",
	Intent:      "当你想查看自己作为群主或管理员在管理哪些群时使用;只读分页返回,可用 --role OWNER/ADMIN 按角色过滤。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "role", Type: shortcut.FlagString, Desc: "角色过滤", Enum: []string{"OWNER", "ADMIN"}},
		{Name: "limit", Type: shortcut.FlagInt, Desc: "最多返回群数量,不传返回全部"},
		{Name: "exclude-muted", Type: shortcut.FlagBool, Desc: "排除已设置免打扰的群聊"},
	},
	Tips: []string{`dws chat +chat-list-mine --role OWNER`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{}
		if rt.Changed("role") {
			params["roleFilter"] = rt.Str("role")
		}
		if rt.Int("limit") > 0 {
			params["limit"] = rt.Int("limit")
		}
		if rt.Bool("exclude-muted") {
			params["excludeMuted"] = true
		}
		data, err := rt.CallMCPData("im", "list_owned_or_admin_groups", params)
		if err != nil {
			return err
		}
		groups := chatListMineProject(data)
		return rt.Output(map[string]any{"count": len(groups), "groups": groups})
	},
}

ChatListMine lists groups the caller owns/administers (list_owned_or_admin_groups, im).

View Source
var ChatMembersGet = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-members-get",
	Product:     "im",
	Description: "根据成员 openDingTalkId 批量查询群成员详情",
	Intent:      "当你已有若干成员的 openDingTalkId、需要批量获取他们在该群内的详情(群昵称、角色等)时使用;只读,需传群 openConversationId 和成员 openDingTalkId 列表。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "id", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "users", Type: shortcut.FlagStringSlice, Desc: "成员 openDingTalkId 列表", Required: true},
	},
	Tips: []string{`dws chat +chat-members-get --id <openConversationId> --users odid1,odid2`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("list_group_member_by_ids", map[string]any{
			"openConversationId":    rt.Str("id"),
			"cid":                   rt.Str("id"),
			"memberOpenDingTalkIds": rt.StrSlice("users"),
		})
	},
}

ChatMembersList lists members of a group (get_group_members, chat server). ChatMembersGet batch-queries member detail by ids (list_group_member_by_ids, im).

View Source
var ChatMute = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-mute",
	Product:     "im",
	Description: "全员禁言 / 取消全员禁言",
	Intent:      "当你想对整个群开启或取消全员禁言时使用;会实际切换群的全员禁言状态,需传群 openConversationId,加 --off 取消禁言。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "off", Type: shortcut.FlagBool, Desc: "取消全员禁言(不传则开启禁言)"},
	},
	Tips: []string{`dws chat +chat-mute --group <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("set_group_mute", map[string]any{
			"openConversationId": rt.Str("group"),
			"mute":               !rt.Bool("off"),
		})
	},
}

ChatMute mutes/unmutes the whole group (set_group_mute, im).

View Source
var ChatMuteMember = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-mute-member",
	Product:     "im",
	Description: "指定群成员禁言 / 取消禁言",
	Intent:      "当你想只禁言或解禁群里的指定成员时使用;会实际把成员加入或移出禁言名单,需传群 openConversationId 和成员列表,禁言时还需 --mute-time(毫秒)。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "users", Type: shortcut.FlagStringSlice, Desc: "成员 userId 或 openDingTalkId 列表", Required: true},
		{Name: "mute-time", Type: shortcut.FlagInt, Desc: "禁言时长(毫秒),如 300000/3600000/86400000/604800000/2592000000"},
		{Name: "off", Type: shortcut.FlagBool, Desc: "移出禁言名单(不传则加入禁言名单)"},
	},
	Tips: []string{`dws chat +chat-mute-member --group <openConversationId> --users userId1 --mute-time 3600000`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		userIDs, openIDs := splitIDs(rt.StrSlice("users"))
		off := rt.Bool("off")
		params := map[string]any{
			"openConversationId": rt.Str("group"),
			"cid":                rt.Str("group"),
			"mute":               !off,
		}
		if len(userIDs) > 0 {
			params["uids"] = userIDs
		}
		if len(openIDs) > 0 {
			params["openDingTalkIds"] = openIDs
		}
		if !off {
			if rt.Int("mute-time") <= 0 {
				return fmt.Errorf("--mute-time 为禁言时必填(毫秒)")
			}
			params["muteTime"] = rt.Int("mute-time")
		}
		return rt.CallMCP("set_group_member_mute_list", params)
	},
}

ChatMuteMember mutes/unmutes specific members (set_group_member_mute_list, im).

View Source
var ChatQuit = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-quit",
	Product:     "im",
	Description: "退出群聊",
	Intent:      "当你想让当前用户主动退出某个群时使用;会实际退群,需传群 openConversationId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
	},
	Tips: []string{`dws chat +chat-quit --group <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("quit_group", map[string]any{"openConversationId": rt.Str("group")})
	},
}

ChatQuit quits a group (quit_group, im).

View Source
var ChatRemoveBot = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-remove-bot",
	Product:     "bot",
	Description: "从群内移除机器人",
	Intent:      "当你想把某个机器人从群里移除时使用;会实际移除机器人,不可逆,需传群 openConversationId 和机器人 openBotId。",
	Risk:        shortcut.RiskHighWrite,
	Flags: []shortcut.Flag{
		{Name: "id", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "bot-id", Type: shortcut.FlagString, Desc: "机器人 openBotId", Required: true},
	},
	Tips: []string{`dws chat +chat-remove-bot --id <openConversationId> --bot-id <openBotId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("remove_robot_in_group", map[string]any{
			"openConversationId": rt.Str("id"),
			"openBotId":          rt.Str("bot-id"),
		})
	},
}

ChatRemoveBot removes a robot from a group (remove_robot_in_group, bot).

View Source
var ChatRoleAdd = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-role-add",
	Product:     "im",
	Description: "添加群身份",
	Intent:      "当你想在群里新增一个自定义群身份/头衔时使用;会实际创建群身份,需传群 openConversationId 和身份名称。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "name", Type: shortcut.FlagString, Desc: "群身份名称", Required: true},
	},
	Tips: []string{`dws chat +chat-role-add --group <openConversationId> --name "管理员"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("add_custom_group_role", map[string]any{
			"openConversationId": rt.Str("group"),
			"name":               rt.Str("name"),
		})
	},
}

ChatRoleAdd adds a custom group role (add_custom_group_role, im).

View Source
var ChatRoleList = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-role-list",
	Product:     "im",
	Description: "拉取会话的群身份列表",
	Intent:      "当你想查看某群自定义的群身份(如'班长''值日')都有哪些时使用;需传群 openConversationId,只读返回群身份列表及 openRoleId。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
	},
	Tips: []string{`dws chat +chat-role-list --group <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		data, err := rt.CallMCPData("im", "list_custom_group_roles", map[string]any{"openConversationId": rt.Str("group")})
		if err != nil {
			return err
		}
		roles := chatRoleListProject(data)
		return rt.Output(map[string]any{"count": len(roles), "roles": roles})
	},
}

ChatRoleList lists custom group roles (list_custom_group_roles, im).

View Source
var ChatRoleQueryUser = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-role-query-user",
	Product:     "im",
	Description: "查询群成员的群身份",
	Intent:      "当你想查看某个群成员当前拥有哪些群身份时使用;只读,需传群 openConversationId 和用户 userId 或 openDingTalkId。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "user", Type: shortcut.FlagString, Desc: "用户 userId 或 openDingTalkId", Required: true},
	},
	Tips: []string{`dws chat +chat-role-query-user --group <openConversationId> --user <userId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		user := rt.Str("user")
		params := map[string]any{"openConversationId": rt.Str("group")}
		if isOpenID(user) {
			params["openDingTalkId"] = user
		} else {
			params["userId"] = user
		}
		return rt.CallMCP("query_custom_user_roles", params)
	},
}

ChatRoleQueryUser queries a member's group roles (query_custom_user_roles, im).

View Source
var ChatRoleRemove = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-role-remove",
	Product:     "im",
	Description: "删除群身份",
	Intent:      "当你想删除某个自定义群身份时使用;会实际删除群身份,不可逆,需传群 openConversationId 和身份 openRoleId。",
	Risk:        shortcut.RiskHighWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "role-id", Type: shortcut.FlagString, Desc: "群身份 openRoleId", Required: true},
	},
	Tips: []string{`dws chat +chat-role-remove --group <openConversationId> --role-id <openRoleId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("remove_custom_group_role", map[string]any{
			"openConversationId": rt.Str("group"),
			"openRoleId":         rt.Str("role-id"),
		})
	},
}

ChatRoleRemove deletes a custom group role (remove_custom_group_role, im).

View Source
var ChatRoleRemoveUser = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-role-remove-user",
	Product:     "im",
	Description: "移除用户的指定群身份",
	Intent:      "当你只想撤销某成员的部分群身份、保留其余时使用;会实际移除指定的群身份,需传群、用户和要移除的 openRoleId 列表。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "user", Type: shortcut.FlagString, Desc: "用户 userId 或 openDingTalkId", Required: true},
		{Name: "role-ids", Type: shortcut.FlagStringSlice, Desc: "要移除的群身份 openRoleId 列表", Required: true},
	},
	Tips: []string{`dws chat +chat-role-remove-user --group <openConversationId> --user <userId> --role-ids roleId1`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		user := rt.Str("user")
		params := map[string]any{
			"openConversationId": rt.Str("group"),
			"openRoleIds":        rt.StrSlice("role-ids"),
		}
		if isOpenID(user) {
			params["openDingTalkId"] = user
		} else {
			params["userId"] = user
		}
		return rt.CallMCP("remove_custom_user_roles", params)
	},
}

ChatRoleRemoveUser removes specific roles from a user (remove_custom_user_roles, im).

View Source
var ChatRoleSetUser = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-role-set-user",
	Product:     "im",
	Description: "设置用户的群身份(覆盖该用户的全部群身份)",
	Intent:      "当你想为某成员整体设定其在群内的身份时使用;会实际改写该用户的群身份集合(覆盖其原有全部身份),需传群、用户和 openRoleId 列表(传空则清除全部)。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "user", Type: shortcut.FlagString, Desc: "用户 userId 或 openDingTalkId", Required: true},
		{Name: "role-ids", Type: shortcut.FlagStringSlice, Desc: "群身份 openRoleId 列表(空则清除全部)", Required: true},
	},
	Tips: []string{`dws chat +chat-role-set-user --group <openConversationId> --user <userId> --role-ids roleId1,roleId2`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		user := rt.Str("user")
		params := map[string]any{
			"openConversationId": rt.Str("group"),
			"openRoleIds":        rt.StrSlice("role-ids"),
		}
		if isOpenID(user) {
			params["openDingTalkId"] = user
		} else {
			params["userId"] = user
		}
		return rt.CallMCP("set_custom_user_roles", params)
	},
}

ChatRoleSetUser overwrites a user's group roles (set_custom_user_roles, im).

View Source
var ChatRoleUpdate = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-role-update",
	Product:     "im",
	Description: "更新群身份名称",
	Intent:      "当你想重命名已有的群身份时使用;会实际更新身份名称,需传群 openConversationId、身份 openRoleId 和新名称。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "role-id", Type: shortcut.FlagString, Desc: "群身份 openRoleId", Required: true},
		{Name: "name", Type: shortcut.FlagString, Desc: "群身份新名称", Required: true},
	},
	Tips: []string{`dws chat +chat-role-update --group <openConversationId> --role-id <openRoleId> --name "新名称"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("update_custom_group_role", map[string]any{
			"openConversationId": rt.Str("group"),
			"openRoleId":         rt.Str("role-id"),
			"name":               rt.Str("name"),
		})
	},
}

ChatRoleUpdate renames a custom group role (update_custom_group_role, im).

View Source
var ChatSearch = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-search",
	Product:     "im",
	Description: "按关键词搜索群聊",
	Intent:      "当你只记得群名称关键词、需要拿到群 openConversationId 以便发消息或管理该群时使用;按群名模糊搜索,只读分页返回匹配的群列表。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "query", Type: shortcut.FlagString, Desc: "群名称关键词"},
		{Name: "keyword", Type: shortcut.FlagString, Desc: "--query 的别名", Hidden: true},
		{Name: "limit", Type: shortcut.FlagInt, Default: "20", Desc: "每页返回数量"},
		{Name: "size", Type: shortcut.FlagInt, Desc: "--limit 的旧版别名", Hidden: true},
		{Name: "cursor", Type: shortcut.FlagString, Default: "0", Desc: "分页游标,翻页传 nextCursor"},
		{Name: "exclude-muted", Type: shortcut.FlagBool, Desc: "排除已设置免打扰的群聊"},
	},
	Constraints: []shortcut.Constraint{
		{Kind: shortcut.ConstraintAtLeastOne, Flags: []string{"query", "keyword"}},
	},
	Tips: []string{`dws chat +chat-search --query "项目冲刺"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		query := rt.Str("query")
		if query == "" {
			query = rt.Str("keyword")
		}
		params := map[string]any{
			"keyword": query,
			"limit":   rt.IntFirst("limit", "size"),
			"cursor":  rt.Str("cursor"),
		}
		if rt.Bool("exclude-muted") {
			params["excludeMuted"] = true
		}
		return rt.CallMCP("search_groups", params)
	},
}

ChatSearch searches groups by keyword (search_groups on the im server).

View Source
var ChatSetAdmin = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-set-admin",
	Product:     "im",
	Description: "设置 / 取消群管理员",
	Intent:      "当你想把某些成员设为或取消群管理员时使用;会实际变更成员角色,需传群 openConversationId 和成员 userId/openDingTalkId 列表,加 --off 取消管理员。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "users", Type: shortcut.FlagStringSlice, Desc: "成员 userId 或 openDingTalkId 列表", Required: true},
		{Name: "off", Type: shortcut.FlagBool, Desc: "取消管理员(不传则设为管理员)"},
	},
	Tips: []string{`dws chat +chat-set-admin --group <openConversationId> --users userId1,userId2`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		userIDs, openIDs := splitIDs(rt.StrSlice("users"))
		params := map[string]any{
			"openConversationId": rt.Str("group"),
			"admin":              !rt.Bool("off"),
		}
		if len(userIDs) > 0 {
			params["uids"] = userIDs
		}
		if len(openIDs) > 0 {
			params["openDingTalkIds"] = openIDs
		}
		return rt.CallMCP("update_conv_member_roles", params)
	},
}

ChatSetAdmin sets/unsets group admins (update_conv_member_roles, im).

View Source
var ChatSetHistory = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-set-history",
	Product:     "im",
	Description: "设置新成员入群可查看历史消息范围",
	Intent:      "当你想控制新成员入群后能看到多少历史消息时使用;会实际修改群配置,需传群 openConversationId 和范围(FORBIDDEN 不可见 / RECENT_100 最近100条 / ALL 全部)。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "option", Type: shortcut.FlagString, Desc: "可见范围", Required: true, Enum: []string{"FORBIDDEN", "RECENT_100", "ALL"}},
	},
	Tips: []string{`dws chat +chat-set-history --group <openConversationId> --option RECENT_100`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("update_show_history_msg_option", map[string]any{
			"openConversationId": rt.Str("group"),
			"option":             rt.Str("option"),
		})
	},
}

ChatSetHistory sets new-member history visibility (update_show_history_msg_option, im).

View Source
var ChatTransferOwner = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-transfer-owner",
	Product:     "im",
	Description: "转让群主",
	Intent:      "当你要把群主身份转让给他人时使用;会实际变更群主(自己不再是群主),需传群 openConversationId 和新群主的 userId 或 openDingTalkId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "new-owner", Type: shortcut.FlagString, Desc: "新群主 userId 或 openDingTalkId", Required: true},
	},
	Tips: []string{`dws chat +chat-transfer-owner --group <openConversationId> --new-owner <openDingTalkId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		newOwner := rt.Str("new-owner")
		params := map[string]any{
			"openConversationId": rt.Str("group"),
			"cid":                rt.Str("group"),
		}
		if isOpenID(newOwner) {
			params["newOwnerOpenDingTalkId"] = newOwner
		} else {
			params["newOwnerUid"] = newOwner
		}
		return rt.CallMCP("transfer_group_owner", params)
	},
}

ChatMemberAdd adds members to a group (add_group_member, chat server). ChatMemberRemove removes members from a group (remove_group_member, chat server). ChatUpdateName renames a group (update_group_name, chat server). ChatTransferOwner transfers group ownership (transfer_group_owner, im).

View Source
var ChatUpdateAlias = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-update-alias",
	Product:     "im",
	Description: "设置群备注(仅自己可见)",
	Intent:      "当你想给某个群设置仅自己可见的备注名以便区分同名群时使用;会实际保存本人对该群的备注,需传群 openConversationId 和备注标题。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "alias-title", Type: shortcut.FlagString, Desc: "群备注标题", Required: true},
	},
	Tips: []string{`dws chat +chat-update-alias --group <openConversationId> --alias-title "项目A群"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("update_user_group_alias", map[string]any{
			"openConversationId": rt.Str("group"),
			"aliasTitle":         rt.Str("alias-title"),
		})
	},
}

ChatUpdateAlias sets the caller's private alias for a group (update_user_group_alias, im).

View Source
var ChatUpdateIcon = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-update-icon",
	Product:     "im",
	Description: "更新群头像",
	Intent:      "当你想更换群头像时使用;会实际更新群头像,需传群 openConversationId 和已上传头像的 mediaId(以 @ 开头)。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "icon-media-id", Type: shortcut.FlagString, Desc: "群头像 mediaId(以 @ 开头)", Required: true},
	},
	Tips: []string{`dws chat +chat-update-icon --group <openConversationId> --icon-media-id <mediaId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("update_group_icon", map[string]any{
			"openConversationId": rt.Str("group"),
			"iconMediaId":        rt.Str("icon-media-id"),
		})
	},
}

ChatUpdateIcon updates the group icon (update_group_icon, im).

View Source
var ChatUpdateNick = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-update-nick",
	Product:     "im",
	Description: "设置当前用户在群内的群昵称",
	Intent:      "当你想设置当前用户在某个群里显示的群昵称时使用;会实际更新本人在该群的昵称,需传群 openConversationId 和昵称。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "nick", Type: shortcut.FlagString, Desc: "个人群昵称", Required: true},
	},
	Tips: []string{`dws chat +chat-update-nick --group <openConversationId> --nick "我的群昵称"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("update_group_nick", map[string]any{
			"openConversationId": rt.Str("group"),
			"nick":               rt.Str("nick"),
		})
	},
}

ChatUpdateNick sets the caller's in-group nickname (update_group_nick, im).

View Source
var ChatUpdateSettings = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+chat-update-settings",
	Product:     "im",
	Description: "更新群设置(settingKey + status)",
	Intent:      "当你想调整群的某项开关设置(如是否可被搜索 searchable、是否仅管理员可@所有人 onlyAdminCanAtAll)时使用;会实际修改群设置,需传 settingKey 和 status(0关/1开)。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "setting-key", Type: shortcut.FlagString, Desc: "群设置项 key,如 searchable / onlyAdminCanAtAll", Required: true},
		{Name: "status", Type: shortcut.FlagInt, Desc: "设置值:0=关闭,1=开启", Required: true},
	},
	Tips: []string{`dws chat +chat-update-settings --group <openConversationId> --setting-key searchable --status 1`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("update_group_settings", map[string]any{
			"openConversationId": rt.Str("group"),
			"settingKey":         rt.Str("setting-key"),
			"status":             rt.Int("status"),
		})
	},
}

ChatUpdateSettings updates a group setting (update_group_settings, im).

View Source
var ConversationClearAllRedPoint = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+conversation-clear-all-red-point",
	Product:     "im",
	Description: "清除所有会话红点(全部已读)",
	Intent:      "当你想一键把全部会话标记为已读、清空所有红点时使用;会实际清除当前用户所有会话的红点,无需任何参数。",
	Risk:        shortcut.RiskWrite,
	Tips:        []string{`dws chat +conversation-clear-all-red-point`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("clear_all_red_point", map[string]any{})
	},
}

ConversationClearAllRedPoint clears all red points (clear_all_red_point, im).

View Source
var ConversationClearMessages = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+conversation-clear-messages",
	Product:     "im",
	Description: "清空当前用户指定会话的聊天记录(仅本人视角,不可逆)",
	Intent:      "当你要清空自己在某个会话里的聊天记录时使用;仅影响本人视角,但会实际删除且不可逆,需传 openConversationId,务必谨慎操作。",
	Risk:        shortcut.RiskHighWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
	},
	Tips: []string{`dws chat +conversation-clear-messages --conversation-id <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("clear_conversation_messages", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"cid":                rt.Str("conversation-id"),
		})
	},
}

ConversationClearMessages clears a conversation's chat records (clear_conversation_messages, im).

View Source
var ConversationClearRedPoint = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+conversation-clear-red-point",
	Product:     "im",
	Description: "清除会话红点",
	Intent:      "当你想消除某个会话上的未读红点(小圆点)时使用;会实际清除该会话红点,需传 openConversationId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
	},
	Tips: []string{`dws chat +conversation-clear-red-point --conversation-id <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("clear_conversation_red_point", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"cid":                rt.Str("conversation-id"),
		})
	},
}

ConversationClearRedPoint clears a conversation red point (clear_conversation_red_point, im).

View Source
var ConversationHide = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+conversation-hide",
	Product:     "im",
	Description: "会话列表中隐藏会话(收到新消息会重新出现)",
	Intent:      "当你想把某个会话从会话列表中暂时隐藏、让列表更清爽时使用;会实际隐藏该会话(收到新消息会自动重新出现),需传 openConversationId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
	},
	Tips: []string{`dws chat +conversation-hide --conversation-id <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("hide_conversation", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"cid":                rt.Str("conversation-id"),
		})
	},
}

ConversationHide hides a conversation from the list (hide_conversation, im).

View Source
var ConversationInfo = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+conversation-info",
	Product:     "chat",
	Description: "获取会话信息(群聊传 --group,单聊传 --open-dingtalk-id)",
	Intent:      "当你已有群 openConversationId 或单聊对方 openDingTalkId、需要查看该会话的名称/类型/成员数等基础信息时使用;只读,群聊传 --group、单聊传 --open-dingtalk-id 二选一。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群聊 openConversationId"},
		{Name: "open-dingtalk-id", Type: shortcut.FlagString, Desc: "单聊对方 openDingTalkId"},
	},
	Tips: []string{`dws chat +conversation-info --group <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{}
		if rt.Str("group") != "" {
			params["openConversationId"] = rt.Str("group")
		}
		if rt.Str("open-dingtalk-id") != "" {
			params["openDingTalkId"] = rt.Str("open-dingtalk-id")
		}
		if len(params) == 0 {
			return fmt.Errorf("--group 或 --open-dingtalk-id 必填其一")
		}
		return rt.CallMCP("get_conversation_info", params)
	},
}

ConversationInfo gets conversation info (get_conversation_info, chat server).

View Source
var ConversationList = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+conversation-list",
	Product:     "im",
	Description: "分页获取当前用户的全部会话列表(单聊+群聊)",
	Intent:      "当你想遍历当前用户的所有会话(单聊+群聊)做统计、清理或批量处理时使用;只读分页返回,可用 --exclude-muted 排除已免打扰会话。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "limit", Type: shortcut.FlagInt, Default: "100", Desc: "每页数量(1-100)"},
		{Name: "cursor", Type: shortcut.FlagInt, Desc: "分页游标(首次不传或 0)"},
		{Name: "exclude-muted", Type: shortcut.FlagBool, Desc: "排除已免打扰会话"},
	},
	Tips: []string{`dws chat +conversation-list --limit 50`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{}
		if rt.Int("limit") > 0 {
			params["limit"] = rt.Int("limit")
		}
		if rt.Int("cursor") > 0 {
			params["cursor"] = rt.Int("cursor")
		}
		if rt.Bool("exclude-muted") {
			params["excludeMuted"] = true
		}
		data, err := rt.CallMCPData("im", "list_all_conversations", params)
		if err != nil {
			return err
		}
		convs := conversationListProject(data)
		payload := map[string]any{"count": len(convs), "conversations": convs}

		if v, ok := conversationListFirst(data, "nextCursor", "cursor"); ok {
			payload["nextCursor"] = v
		}
		if v, ok := conversationListFirst(data, "hasMore", "has_more"); ok {
			payload["hasMore"] = v
		}
		return rt.Output(payload)
	},
}

ConversationList paginates all conversations (list_all_conversations, im).

View Source
var ConversationListTop = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+conversation-list-top",
	Description: "拉取置顶会话列表",
	Intent:      "当你只想查看被置顶的那些会话时使用;只读分页返回置顶会话列表,可用 --exclude-muted 排除已免打扰会话。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "limit", Type: shortcut.FlagInt, Desc: "每页数量"},
		{Name: "cursor", Type: shortcut.FlagInt, Desc: "分页游标(首次不传或 0)"},
		{Name: "exclude-muted", Type: shortcut.FlagBool, Desc: "排除已免打扰会话"},
	},
	Tips: []string{`dws chat +conversation-list-top --limit 1000`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{}
		if rt.Int("limit") > 0 {
			params["limit"] = rt.Int("limit")
		}
		if rt.Int("cursor") > 0 {
			params["cursor"] = rt.Int("cursor")
		}
		if rt.Bool("exclude-muted") {
			params["excludeMuted"] = true
		}
		data, err := rt.CallMCPData("chat", "list_top_conversations", params)
		if err != nil {
			return err
		}
		convs := conversationListTopProject(data)
		payload := map[string]any{"count": len(convs), "conversations": convs}
		if v, ok := conversationListTopFirst(data, "nextCursor", "cursor"); ok {
			payload["nextCursor"] = v
		}
		if v, ok := conversationListTopFirst(data, "hasMore", "has_more"); ok {
			payload["hasMore"] = v
		}
		return rt.Output(payload)
	},
}

ConversationListTop lists pinned conversations (list_top_conversations, chat server).

View Source
var ConversationMarkRead = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+conversation-mark-read",
	Product:     "im",
	Description: "标记消息已读(该消息及之前的消息都标记为已读)",
	Intent:      "当你想把某会话中某条消息及其之前的所有消息都标记为已读时使用;会实际更新已读位置,需传 openConversationId 和该消息 openMessageId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "message-id", Type: shortcut.FlagString, Desc: "消息 openMessageId", Required: true},
	},
	Tips: []string{`dws chat +conversation-mark-read --conversation-id <openConversationId> --message-id <openMessageId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("mark_message_read", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"openMessageId":      rt.Str("message-id"),
		})
	},
}

ConversationMarkRead marks a message read (mark_message_read, im).

View Source
var ConversationMarkUnread = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+conversation-mark-unread",
	Product:     "im",
	Description: "标记会话为未读",
	Intent:      "当你想把某个已读会话重新标记为未读(提醒自己稍后再处理)时使用;会实际改变该会话的未读状态,需传 openConversationId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
	},
	Tips: []string{`dws chat +conversation-mark-unread --conversation-id <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("mark_conversation_unread", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"cid":                rt.Str("conversation-id"),
		})
	},
}

ConversationMarkUnread marks a conversation unread (mark_conversation_unread, im).

View Source
var ConversationMute = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+conversation-mute",
	Product:     "im",
	Description: "会话消息免打扰(支持单聊/群聊)",
	Intent:      "当你想对某个会话开启或关闭消息免打扰时使用;会实际更改该会话的免打扰设置,需传 openConversationId,加 --off 表示关闭免打扰。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "off", Type: shortcut.FlagBool, Desc: "关闭免打扰(不传则开启免打扰)"},
	},
	Tips: []string{`dws chat +conversation-mute --conversation-id <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("update_notification_off", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"cid":                rt.Str("conversation-id"),
			"mute":               !rt.Bool("off"),
		})
	},
}

ConversationMute mutes/unmutes a conversation (update_notification_off, im).

View Source
var ConversationMuteAtAll = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+conversation-mute-at-all",
	Product:     "im",
	Description: "关闭/开启 @所有人消息提醒",
	Intent:      "当你在某个群里不想再被'@所有人'打扰、或想恢复该提醒时使用;会实际修改该会话的@所有人提醒开关,需传 openConversationId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "off", Type: shortcut.FlagBool, Desc: "恢复接收 @所有人通知(不传则关闭通知)"},
	},
	Tips: []string{`dws chat +conversation-mute-at-all --conversation-id <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("update_at_all_notification_off", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"cid":                rt.Str("conversation-id"),
			"mute":               !rt.Bool("off"),
		})
	},
}

ConversationMuteAtAll toggles @all notification (update_at_all_notification_off, im).

View Source
var ConversationMuteRedEnvelope = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+conversation-mute-red-envelope",
	Product:     "im",
	Description: "关闭/开启红包消息提醒",
	Intent:      "当你想在某个会话里关闭或恢复红包消息提醒时使用;会实际修改该会话的红包提醒开关,需传 openConversationId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "off", Type: shortcut.FlagBool, Desc: "恢复接收红包通知(不传则关闭通知)"},
	},
	Tips: []string{`dws chat +conversation-mute-red-envelope --conversation-id <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("update_red_env_notification_off", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"cid":                rt.Str("conversation-id"),
			"mute":               !rt.Bool("off"),
		})
	},
}

ConversationMuteRedEnvelope toggles red-envelope notification (update_red_env_notification_off, im).

View Source
var ConversationSetTop = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+conversation-set-top",
	Product:     "im",
	Description: "会话置顶 / 取消置顶(支持单聊/群聊)",
	Intent:      "当你想把某个单聊或群聊置顶到会话列表顶部、或取消其置顶时使用;会实际修改该会话的置顶状态,需传 openConversationId,加 --off 取消置顶。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "off", Type: shortcut.FlagBool, Desc: "取消置顶(不传则设置置顶)"},
	},
	Tips: []string{`dws chat +conversation-set-top --conversation-id <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("set_top_conversation", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"cid":                rt.Str("conversation-id"),
			"top":                !rt.Bool("off"),
		})
	},
}

ConversationSetTop sets/unsets a conversation top (set_top_conversation, im).

View Source
var MessagesAddEmoji = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-add-emoji",
	Product:     "im",
	Description: "对消息添加 emoji 表情回应",
	Intent:      "当你想给某条消息点一个 emoji 表情回应时使用;会实际添加表情回应,需传会话 openConversationId、消息 openMsgId 和表情名称。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "msg-id", Type: shortcut.FlagString, Desc: "消息 openMsgId", Required: true},
		{Name: "emoji", Type: shortcut.FlagString, Desc: "emoji 表情名称", Required: true},
	},
	Tips: []string{`dws chat +messages-add-emoji --conversation-id <openConversationId> --msg-id <openMsgId> --emoji "赞"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("add_emoji_reaction", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"openMsgId":          rt.Str("msg-id"),
			"emojiName":          rt.Str("emoji"),
		})
	},
}

MessagesAddEmoji adds an emoji reaction (add_emoji_reaction, im).

View Source
var MessagesAddTextEmotion = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-add-text-emotion",
	Product:     "im",
	Description: "对消息添加文字表情回应",
	Intent:      "当你想给某条消息添加自定义文字表情回应时使用;会实际添加文字表情,需传会话、消息 openMsgId 及由 create-text-emotion 得到的 emotionId 等参数。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "msg-id", Type: shortcut.FlagString, Desc: "消息 openMsgId", Required: true},
		{Name: "emotion-id", Type: shortcut.FlagString, Desc: "表情 ID(由 create-text-emotion 获取)", Required: true},
		{Name: "emotion-name", Type: shortcut.FlagString, Desc: "表情名称", Required: true},
		{Name: "text", Type: shortcut.FlagString, Desc: "文字内容", Required: true},
		{Name: "background-id", Type: shortcut.FlagString, Desc: "背景 ID", Required: true},
	},
	Tips: []string{`dws chat +messages-add-text-emotion --conversation-id <openConversationId> --msg-id <openMsgId> --emotion-id <id> --emotion-name "赞" --text "nice" --background-id im_bg_5`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("add_text_emotion", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"openMsgId":          rt.Str("msg-id"),
			"emotionId":          rt.Str("emotion-id"),
			"emotionName":        rt.Str("emotion-name"),
			"text":               rt.Str("text"),
			"backgroundId":       rt.Str("background-id"),
		})
	},
}

MessagesAddTextEmotion adds a text emotion reaction (add_text_emotion, im).

View Source
var MessagesBatchRecallByBot = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-batch-recall-by-bot",
	Product:     "bot",
	Description: "机器人撤回单聊消息",
	Intent:      "当你要批量撤回机器人此前发出的单聊消息时使用;会实际撤回机器人单聊消息,需传 robotCode 和发送时返回的 processQueryKey 列表。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "robot-code", Type: shortcut.FlagString, Desc: "机器人 Code", Required: true},
		{Name: "keys", Type: shortcut.FlagStringSlice, Desc: "发送时返回的 processQueryKey 列表", Required: true},
	},
	Tips: []string{`dws chat +messages-batch-recall-by-bot --robot-code <robotCode> --keys key1,key2`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("batch_recall_robot_users_msg", map[string]any{
			"robotCode":        rt.Str("robot-code"),
			"processQueryKeys": rt.StrSlice("keys"),
		})
	},
}

MessagesBatchRecallByBot recalls robot single-chat messages (batch_recall_robot_users_msg, bot).

View Source
var MessagesBatchSendByBot = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-batch-send-by-bot",
	Product:     "bot",
	Description: "机器人批量向用户发送单聊 Markdown 消息",
	Intent:      "当你要用机器人给多个人分别发单聊 Markdown 消息(如批量提醒交周报)时使用;会实际批量发送单聊消息,需传 robotCode、接收人列表(userId 或 openDingTalkId)及标题正文。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "robot-code", Type: shortcut.FlagString, Desc: "机器人 Code", Required: true},
		{Name: "title", Type: shortcut.FlagString, Desc: "消息标题", Required: true},
		{Name: "text", Type: shortcut.FlagString, Desc: "Markdown 正文", Required: true},
		{Name: "users", Type: shortcut.FlagStringSlice, Desc: "接收人 userId 列表"},
		{Name: "open-dingtalk-ids", Type: shortcut.FlagStringSlice, Desc: "接收人 openDingTalkId 列表"},
		{Name: "at-all", Type: shortcut.FlagBool, Desc: "@ 所有人"},
	},
	Tips: []string{`dws chat +messages-batch-send-by-bot --robot-code <robotCode> --users userId1,userId2 --title "提醒" --text "请提交周报"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{
			"robotCode": rt.Str("robot-code"),
			"title":     rt.Str("title"),
			"markdown":  rt.Str("text"),
		}
		if v := rt.StrSlice("users"); len(v) > 0 {
			params["userIds"] = v
		}
		if v := rt.StrSlice("open-dingtalk-ids"); len(v) > 0 {
			params["openDingtalkIds"] = v
		}
		if rt.Bool("at-all") {
			params["isAtAll"] = "true"
		}
		return rt.CallMCP("batch_send_robot_msg_to_users", params)
	},
}

MessagesBatchSendByBot sends single-chat messages via a robot to users (batch_send_robot_msg_to_users, bot).

View Source
var MessagesCombineForward = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-combine-forward",
	Product:     "im",
	Description: "合并转发多条消息",
	Intent:      "当你想把多条消息合并成一条转发到目标会话时使用;会实际合并转发,需传源会话、源消息 openMessageId 列表和目标会话 openConversationId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "src-conversation-id", Type: shortcut.FlagString, Desc: "源会话 openConversationId", Required: true},
		{Name: "msg-ids", Type: shortcut.FlagStringSlice, Desc: "源消息 openMessageId 列表", Required: true},
		{Name: "dest-conversation-id", Type: shortcut.FlagString, Desc: "目标会话 openConversationId", Required: true},
		{Name: "uuid", Type: shortcut.FlagString, Desc: "幂等键(可选)"},
	},
	Tips: []string{`dws chat +messages-combine-forward --src-conversation-id <srcCid> --msg-ids id1,id2 --dest-conversation-id <destCid>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{
			"srcOpenCid":        rt.Str("src-conversation-id"),
			"srcOpenMessageIds": rt.StrSlice("msg-ids"),
			"destOpenCid":       rt.Str("dest-conversation-id"),
		}
		if rt.Changed("uuid") {
			params["uuid"] = rt.Str("uuid")
		}
		return rt.CallMCP("combine_forward_messages", params)
	},
}

MessagesCombineForward merge-forwards multiple messages (combine_forward_messages, im).

View Source
var MessagesCreateTextEmotion = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-create-text-emotion",
	Product:     "im",
	Description: "创建文字表情(获取 emotionId)",
	Intent:      "当你要先创建一个文字表情模板(拿到 emotionId 供 add-text-emotion 使用)时使用;会实际创建文字表情,需传表情名称和文字内容。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "emotion-name", Type: shortcut.FlagString, Desc: "表情名称", Required: true},
		{Name: "text", Type: shortcut.FlagString, Desc: "文字内容", Required: true},
		{Name: "background-id", Type: shortcut.FlagString, Desc: "背景 ID(可选)"},
	},
	Tips: []string{`dws chat +messages-create-text-emotion --emotion-name "赞" --text "nice"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{
			"emotionName": rt.Str("emotion-name"),
			"text":        rt.Str("text"),
		}
		if rt.Changed("background-id") {
			params["backgroundId"] = rt.Str("background-id")
		}
		return rt.CallMCP("create_text_emotion", params)
	},
}

MessagesCreateTextEmotion creates a text emotion template (create_text_emotion, im).

View Source
var MessagesForward = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-forward",
	Product:     "im",
	Description: "转发单条消息",
	Intent:      "当你想把一条消息转发到另一个会话时使用;会实际转发消息,需传源会话 openConversationId、源消息 openMessageId 和目标会话 openConversationId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "src-conversation-id", Type: shortcut.FlagString, Desc: "源会话 openConversationId", Required: true},
		{Name: "msg-id", Type: shortcut.FlagString, Desc: "源消息 openMessageId", Required: true},
		{Name: "dest-conversation-id", Type: shortcut.FlagString, Desc: "目标会话 openConversationId", Required: true},
		{Name: "uuid", Type: shortcut.FlagString, Desc: "幂等键(可选)"},
	},
	Tips: []string{`dws chat +messages-forward --src-conversation-id <srcCid> --msg-id <msgId> --dest-conversation-id <destCid>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{
			"srcOpenCid":       rt.Str("src-conversation-id"),
			"srcOpenMessageId": rt.Str("msg-id"),
			"destOpenCid":      rt.Str("dest-conversation-id"),
		}
		if rt.Changed("uuid") {
			params["uuid"] = rt.Str("uuid")
		}
		return rt.CallMCP("forward_message", params)
	},
}

MessagesForward forwards one message (forward_message, im).

View Source
var MessagesForwardTopic = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-forward-topic",
	Product:     "im",
	Description: "转发话题消息到目标会话",
	Intent:      "当你要把某条群话题消息转发到目标会话时使用;会实际转发话题消息,需传源消息、源会话、话题 threadId 和目标会话 openConversationId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "src-msg-id", Type: shortcut.FlagString, Desc: "源消息 openMessageId", Required: true},
		{Name: "src-conversation-id", Type: shortcut.FlagString, Desc: "源会话 openConversationId", Required: true},
		{Name: "src-thread-id", Type: shortcut.FlagString, Desc: "话题 ID(convThread + 加密 convThreadId)", Required: true},
		{Name: "dest-conversation-id", Type: shortcut.FlagString, Desc: "目标会话 openConversationId", Required: true},
	},
	Tips: []string{`dws chat +messages-forward-topic --src-msg-id <msgId> --src-conversation-id <srcCid> --src-thread-id <threadId> --dest-conversation-id <destCid>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("forward_topic", map[string]any{
			"srcOpenMessageId":       rt.Str("src-msg-id"),
			"srcOpenConversationId":  rt.Str("src-conversation-id"),
			"srcOpenConvThreadId":    rt.Str("src-thread-id"),
			"destOpenConversationId": rt.Str("dest-conversation-id"),
		})
	},
}

MessagesForwardTopic forwards a topic message (forward_topic, im).

View Source
var MessagesList = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-list",
	Description: "拉取群聊会话消息",
	Intent:      "当你想按时间拉取某个群的历史聊天记录(做回顾或分析)时使用;只读,需传群 openConversationId 和起始时间,--forward 控制往新还是往旧方向翻。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId"},
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "--group 的别名", Hidden: true},
		{Name: "id", Type: shortcut.FlagString, Desc: "--group 的别名", Hidden: true},
		{Name: "time", Type: shortcut.FlagString, Desc: "起始时间,如 \"2025-03-01 00:00:00\"", Required: true},
		{Name: "forward", Type: shortcut.FlagBool, Default: "true", Desc: "true=从给定时间往现在拉,false=往以前拉"},
		{Name: "limit", Type: shortcut.FlagInt, Desc: "每页返回数量"},
		{Name: "size", Type: shortcut.FlagInt, Desc: "--limit 的旧版别名", Hidden: true},
	},
	Constraints: []shortcut.Constraint{
		{Kind: shortcut.ConstraintExactlyOne, Flags: []string{"group", "conversation-id", "id"}},
	},
	Tips: []string{`dws chat +messages-list --group <openConversationId> --time "2025-03-01 00:00:00"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		group := rt.StrFirst("group", "conversation-id", "id")
		params := map[string]any{
			"openconversation_id": group,
			"time":                rt.Str("time"),
			"forward":             rt.Bool("forward"),
		}
		if limit := rt.IntFirst("limit", "size"); limit > 0 {
			params["limit"] = limit
		}
		data, err := rt.CallMCPData("chat", "list_conversation_message_v2", params)
		if err != nil {
			return err
		}
		messages := listMessagesProject(data)
		return rt.Output(map[string]any{"count": len(messages), "messages": messages})
	},
}

MessagesList pulls messages of a group (list_conversation_message_v2, chat server).

View Source
var MessagesListDirect = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-list-direct",
	Description: "拉取单聊会话消息",
	Intent:      "当你想按时间拉取与某人单聊的历史消息时使用;只读,需传对方 userId 或 openDingTalkId 及起始时间,--forward 控制翻页方向。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "user", Type: shortcut.FlagString, Desc: "对方 userId(与 --open-dingtalk-id 二选一)"},
		{Name: "open-dingtalk-id", Type: shortcut.FlagString, Desc: "对方 openDingTalkId(与 --user 二选一)"},
		{Name: "time", Type: shortcut.FlagString, Desc: "起始时间,如 \"2025-03-01 00:00:00\"", Required: true},
		{Name: "forward", Type: shortcut.FlagBool, Default: "true", Desc: "true=往现在拉,false=往以前拉"},
		{Name: "limit", Type: shortcut.FlagInt, Desc: "每页返回数量"},
		{Name: "size", Type: shortcut.FlagInt, Desc: "--limit 的旧版别名", Hidden: true},
	},
	Tips: []string{`dws chat +messages-list-direct --user <userId> --time "2025-03-01 00:00:00"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{
			"time":    rt.Str("time"),
			"forward": rt.Bool("forward"),
		}
		switch {
		case rt.Str("open-dingtalk-id") != "":
			params["openDingTalkId"] = rt.Str("open-dingtalk-id")
		case rt.Str("user") != "":
			params["userId"] = rt.Str("user")
		default:
			return fmt.Errorf("--user 或 --open-dingtalk-id 必填其一")
		}
		if limit := rt.IntFirst("limit", "size"); limit > 0 {
			params["limit"] = limit
		}
		data, err := rt.CallMCPData("chat", "list_individual_chat_message", params)
		if err != nil {
			return err
		}
		messages := listMessagesProject(data)
		return rt.Output(map[string]any{"count": len(messages), "messages": messages})
	},
}

MessagesListDirect pulls messages of a single chat (list_individual_chat_message, chat server).

View Source
var MessagesListPin = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-list-pin",
	Product:     "im",
	Description: "拉取会话中钉住的消息列表",
	Intent:      "当你想查看某会话里当前钉住的消息有哪些时使用;只读分页返回,需传会话 openConversationId。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "open-conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "cursor", Type: shortcut.FlagString, Desc: "分页游标,翻页传 nextCursor"},
		{Name: "size", Type: shortcut.FlagInt, Desc: "一次拉取的消息数量(默认 20,最大 100)"},
	},
	Tips: []string{`dws chat +messages-list-pin --open-conversation-id <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{
			"openConversationId": rt.Str("open-conversation-id"),
			"cid":                rt.Str("open-conversation-id"),
		}
		if rt.Changed("cursor") {
			params["cursor"] = rt.Str("cursor")
		}
		if rt.Int("size") > 0 {
			params["count"] = rt.Int("size")
		}
		data, err := rt.CallMCPData("im", "list_pin_messages", params)
		if err != nil {
			return err
		}
		pins := listPinProject(data)
		return rt.Output(map[string]any{"count": len(pins), "pins": pins})
	},
}

MessagesListPin lists pinned messages (list_pin_messages, im).

View Source
var MessagesListUnreadConversations = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-list-unread-conversations",
	Description: "获取有未读消息的会话列表",
	Intent:      "当你想快速定位哪些会话还有未读消息时使用;只读返回有未读的会话列表,可用 --exclude-muted 排除已免打扰会话。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "count", Type: shortcut.FlagInt, Desc: "返回的会话条数"},
		{Name: "exclude-muted", Type: shortcut.FlagBool, Desc: "排除已免打扰会话"},
	},
	Tips: []string{`dws chat +messages-list-unread-conversations --count 20`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{}
		if rt.Int("count") > 0 {
			params["count"] = rt.Int("count")
		}
		if rt.Bool("exclude-muted") {
			params["excludeMuted"] = true
		}
		data, err := rt.CallMCPData("chat", "unread_message_conversation_list", params)
		if err != nil {
			return err
		}
		conversations := listUnreadConversationsProject(data)
		return rt.Output(map[string]any{"count": len(conversations), "conversations": conversations})
	},
}

MessagesListTopicReplies pulls topic replies (list_topic_replies, chat server). MessagesListAll pulls all messages in a time range (search_messages_by_time_range, chat server). MessagesListFocused pulls messages from specially-followed people (list_special_focus_messages, chat server). MessagesListUnreadConversations lists conversations with unread messages (unread_message_conversation_list, chat server).

View Source
var MessagesMget = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-mget",
	Product:     "im",
	Description: "根据消息 ID 批量查询消息(最多 50 条)",
	Intent:      "当你已有一批消息 openMsgId、需要批量取回它们的详细内容时使用;只读,一次最多查询 50 条。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "msg-ids", Type: shortcut.FlagStringSlice, Desc: "消息 openMsgId 列表", Required: true},
	},
	Tips: []string{`dws chat +messages-mget --msg-ids msgId1,msgId2`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("list_messages_by_ids", map[string]any{"openMsgIds": rt.StrSlice("msg-ids")})
	},
}

MessagesMget batch-queries messages by id (list_messages_by_ids, im).

View Source
var MessagesQuerySendStatus = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-query-send-status",
	Product:     "im",
	Description: "查询消息发送状态",
	Intent:      "当你发消息后拿到 openTaskId、想确认这条消息是否发送成功时使用;只读返回发送状态,需传 --open-task-id。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "open-task-id", Type: shortcut.FlagString, Desc: "发送消息时返回的 openTaskId", Required: true},
	},
	Tips: []string{`dws chat +messages-query-send-status --open-task-id <openTaskId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("query_message_send_status", map[string]any{"openTaskId": rt.Str("open-task-id")})
	},
}

MessagesQuerySendStatus queries send status of a message (query_message_send_status, im).

View Source
var MessagesReadStatus = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-read-status",
	Product:     "im",
	Description: "查询消息的已读/未读状态",
	Intent:      "当你想知道自己发出的某条消息有哪些人已读/未读时使用;只读,需传会话 openConversationId 和该消息 openMessageId,可指定目标成员列表。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId"},
		{Name: "group", Type: shortcut.FlagString, Desc: "--conversation-id 的别名", Hidden: true},
		{Name: "id", Type: shortcut.FlagString, Desc: "--conversation-id 的别名", Hidden: true},
		{Name: "message-id", Type: shortcut.FlagString, Desc: "消息 openMessageId(当前用户发送的消息)", Required: true},
		{Name: "users", Type: shortcut.FlagStringSlice, Desc: "目标 userId 或 openDingTalkId 列表(不传返回全部接收者)"},
	},
	Constraints: []shortcut.Constraint{
		{Kind: shortcut.ConstraintExactlyOne, Flags: []string{"conversation-id", "group", "id"}},
	},
	Tips: []string{`dws chat +messages-read-status --conversation-id <openConversationId> --message-id <openMessageId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{
			"openConversationId": rt.StrFirst("conversation-id", "group", "id"),
			"openMessageId":      rt.Str("message-id"),
		}
		if v := rt.StrSlice("users"); len(v) > 0 {
			userIDs, openIDs := splitIDs(v)
			if len(userIDs) > 0 {
				params["targetUserIds"] = userIDs
			}
			if len(openIDs) > 0 {
				params["targetOpenDingTalkIds"] = openIDs
			}
		}
		return rt.CallMCP("query_msg_read_status", params)
	},
}

MessagesReadStatus queries read/unread status of a message (query_msg_read_status, im).

View Source
var MessagesRecall = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-recall",
	Product:     "im",
	Description: "撤回当前用户发送的消息",
	Intent:      "当你想撤回当前用户刚发出的某条消息时使用;会实际撤回消息,需传会话 openConversationId 和消息 openMessageId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "msg-id", Type: shortcut.FlagString, Desc: "消息 openMessageId", Required: true},
	},
	Tips: []string{`dws chat +messages-recall --conversation-id <openConversationId> --msg-id <openMessageId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("recall_message", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"openMessageId":      rt.Str("msg-id"),
		})
	},
}

MessagesRecall recalls a message sent by the current user (recall_message, im).

View Source
var MessagesRecallByBot = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-recall-by-bot",
	Product:     "bot",
	Description: "机器人撤回群消息",
	Intent:      "当你要撤回机器人此前发到群里的消息时使用;会实际撤回机器人群消息,需传 robotCode、群 openConversationId 和发送时返回的 processQueryKey 列表。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "robot-code", Type: shortcut.FlagString, Desc: "机器人 Code", Required: true},
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "keys", Type: shortcut.FlagStringSlice, Desc: "发送时返回的 processQueryKey 列表", Required: true},
	},
	Tips: []string{`dws chat +messages-recall-by-bot --robot-code <robotCode> --group <openConversationId> --keys key1,key2`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("recall_robot_group_message", map[string]any{
			"robotCode":          rt.Str("robot-code"),
			"openConversationId": rt.Str("group"),
			"processQueryKeys":   rt.StrSlice("keys"),
		})
	},
}

MessagesRecallByBot recalls a robot group message (recall_robot_group_message, bot).

View Source
var MessagesRemoveEmoji = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-remove-emoji",
	Product:     "im",
	Description: "移除消息的 emoji 表情回应",
	Intent:      "当你想取消此前给某条消息添加的 emoji 表情回应时使用;会实际移除表情回应,需传会话 openConversationId、消息 openMsgId 和表情名称。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "msg-id", Type: shortcut.FlagString, Desc: "消息 openMsgId", Required: true},
		{Name: "emoji", Type: shortcut.FlagString, Desc: "emoji 表情名称", Required: true},
	},
	Tips: []string{`dws chat +messages-remove-emoji --conversation-id <openConversationId> --msg-id <openMsgId> --emoji "赞"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("remove_emoji_reaction", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"openMsgId":          rt.Str("msg-id"),
			"emojiName":          rt.Str("emoji"),
		})
	},
}

MessagesRemoveEmoji removes an emoji reaction (remove_emoji_reaction, im).

View Source
var MessagesRemoveTextEmotion = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-remove-text-emotion",
	Product:     "im",
	Description: "移除消息的文字表情回应",
	Intent:      "当你想移除此前给某条消息添加的文字表情回应时使用;会实际移除文字表情,需传会话、消息 openMsgId 及对应的表情参数。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "msg-id", Type: shortcut.FlagString, Desc: "消息 openMsgId", Required: true},
		{Name: "emotion-id", Type: shortcut.FlagString, Desc: "表情 ID", Required: true},
		{Name: "emotion-name", Type: shortcut.FlagString, Desc: "表情名称", Required: true},
		{Name: "text", Type: shortcut.FlagString, Desc: "文字内容", Required: true},
		{Name: "background-id", Type: shortcut.FlagString, Desc: "背景 ID", Required: true},
	},
	Tips: []string{`dws chat +messages-remove-text-emotion --conversation-id <openConversationId> --msg-id <openMsgId> --emotion-id <id> --emotion-name "赞" --text "nice" --background-id im_bg_5`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("remove_text_emotion", map[string]any{
			"openConversationId": rt.Str("conversation-id"),
			"openMsgId":          rt.Str("msg-id"),
			"emotionId":          rt.Str("emotion-id"),
			"emotionName":        rt.Str("emotion-name"),
			"text":               rt.Str("text"),
			"backgroundId":       rt.Str("background-id"),
		})
	},
}

MessagesRemoveTextEmotion removes a text emotion reaction (remove_text_emotion, im).

View Source
var MessagesResourceURL = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-resource-url",
	Product:     "im",
	Description: "获取消息资源(图片/视频/语音)下载链接",
	Intent:      "当你想下载消息里的图片/视频/语音等资源时使用;只读换取临时下载链接,需传资源 mediaId、消息 openMessageId 和会话 openConversationId。",
	Risk:        shortcut.RiskRead,
	Flags: []shortcut.Flag{
		{Name: "type", Type: shortcut.FlagString, Default: "mediaId", Desc: "资源类型", Enum: []string{"mediaId"}},
		{Name: "resource-id", Type: shortcut.FlagString, Desc: "资源 ID(消息中的 mediaId)", Required: true},
		{Name: "message-id", Type: shortcut.FlagString, Desc: "消息 openMessageId", Required: true},
		{Name: "open-conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
	},
	Tips: []string{`dws chat +messages-resource-url --type mediaId --resource-id <mediaId> --message-id <openMessageId> --open-conversation-id <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("get_resource_download_url", map[string]any{
			"resourceType":       rt.Str("type"),
			"resourceId":         rt.Str("resource-id"),
			"openMessageId":      rt.Str("message-id"),
			"openConversationId": rt.Str("open-conversation-id"),
		})
	},
}

MessagesResourceURL gets a message resource download url (get_resource_download_url, im).

View Source
var MessagesSendByBot = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-send-by-bot",
	Product:     "bot",
	Description: "机器人向群聊发送 Markdown 消息",
	Intent:      "当你要用机器人向某群推送 Markdown 消息(如日报、告警播报)时使用;会实际以机器人身份发群消息,需传 robotCode、群 openConversationId、标题与正文,可 @人或 @所有人。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "robot-code", Type: shortcut.FlagString, Desc: "机器人 Code", Required: true},
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId", Required: true},
		{Name: "title", Type: shortcut.FlagString, Desc: "消息标题", Required: true},
		{Name: "text", Type: shortcut.FlagString, Desc: "Markdown 正文", Required: true},
		{Name: "at-user-ids", Type: shortcut.FlagStringSlice, Desc: "@ 的 userId 列表"},
		{Name: "at-open-dingtalk-ids", Type: shortcut.FlagStringSlice, Desc: "@ 的 openDingTalkId 列表"},
		{Name: "at-all", Type: shortcut.FlagBool, Desc: "@ 所有人"},
	},
	Tips: []string{`dws chat +messages-send-by-bot --robot-code <robotCode> --group <openConversationId> --title "日报" --text "## 今日完成"`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{
			"robotCode":          rt.Str("robot-code"),
			"openConversationId": rt.Str("group"),
			"title":              rt.Str("title"),
			"markdown":           rt.Str("text"),
		}
		if v := rt.StrSlice("at-user-ids"); len(v) > 0 {
			params["atUserIds"] = v
		}
		if v := rt.StrSlice("at-open-dingtalk-ids"); len(v) > 0 {
			params["atOpendingtalkIds"] = v
		}
		if rt.Bool("at-all") {
			params["isAtAll"] = "true"
		}
		return rt.CallMCP("send_robot_group_message", params)
	},
}

MessagesSend sends a text/markdown message as the current user (send_personal_message, chat server). Media/file variants are not covered. MessagesReply quote-replies a message (send_personal_message, chat server). MessagesSendByBot sends a group message via a robot (send_robot_group_message, bot).

View Source
var MessagesSendByWebhook = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-send-by-webhook",
	Product:     "bot",
	Description: "自定义机器人 Webhook 发送群消息",
	Intent:      "当你只有自定义机器人的 Webhook token、想往其所在群推送消息时使用;会实际通过 Webhook 发群消息,需传 token、标题、正文,可 @手机号/userId 或 @所有人。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "token", Type: shortcut.FlagString, Desc: "Webhook token", Required: true},
		{Name: "title", Type: shortcut.FlagString, Desc: "消息标题", Required: true},
		{Name: "text", Type: shortcut.FlagString, Desc: "消息正文", Required: true},
		{Name: "at-all", Type: shortcut.FlagBool, Desc: "@ 所有人"},
		{Name: "at-mobiles", Type: shortcut.FlagStringSlice, Desc: "@ 的手机号列表"},
		{Name: "at-users", Type: shortcut.FlagStringSlice, Desc: "@ 的 userId 列表"},
	},
	Tips: []string{`dws chat +messages-send-by-webhook --token <token> --title "告警" --text "CPU 超 90%" --at-all`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		params := map[string]any{
			"robotToken": rt.Str("token"),
			"title":      rt.Str("title"),
			"text":       rt.Str("text"),
		}
		if rt.Bool("at-all") {
			params["isAtAll"] = true
		}
		if v := rt.StrSlice("at-mobiles"); len(v) > 0 {
			params["atMobiles"] = v
		}
		if v := rt.StrSlice("at-users"); len(v) > 0 {
			params["atUserIds"] = v
		}
		return rt.CallMCP("send_message_by_custom_robot", params)
	},
}

MessagesSendByWebhook sends via a custom robot webhook (send_message_by_custom_robot, bot).

View Source
var MessagesSendCard = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-send-card",
	Product:     "im",
	Description: "创建并推送流式卡片(需配合 messages-update-card)",
	Intent:      "当你要发送一张可后续流式更新的卡片消息(如 AI 逐字输出)时使用;会实际推送卡片并返回 bizId,群 openConversationId 或单聊接收者 userId 二选一,配合 messages-update-card 更新。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "group", Type: shortcut.FlagString, Desc: "群 openConversationId(与 --receiver 互斥)"},
		{Name: "receiver", Type: shortcut.FlagString, Desc: "单聊接收者 userId(与 --group 互斥)"},
	},
	Constraints: []shortcut.Constraint{
		{Kind: shortcut.ConstraintExactlyOne, Flags: []string{"group", "receiver"}},
	},
	Tips: []string{`dws chat +messages-send-card --group <openConversationId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		group := rt.Str("group")
		receiver := rt.Str("receiver")
		if group == "" && receiver == "" {
			return fmt.Errorf("--group 或 --receiver 必填其一")
		}
		if group != "" && receiver != "" {
			return fmt.Errorf("--group 与 --receiver 互斥")
		}
		params := map[string]any{}
		if group != "" {
			params["openConversationId"] = group
		} else {
			params["receiverUid"] = receiver
		}
		return rt.CallMCP("create_and_send_card", params)
	},
}

MessagesSendCard creates and pushes a streaming card (create_and_send_card, im).

View Source
var MessagesSetPin = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-set-pin",
	Product:     "im",
	Description: "钉住消息(Pin)",
	Intent:      "当你想把某条消息钉在会话中(Pin)以便成员随时查看时使用;会实际钉住消息,需传会话 openConversationId 和消息 openMessageId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "open-conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "msg-id", Type: shortcut.FlagString, Desc: "消息 openMessageId", Required: true},
	},
	Tips: []string{`dws chat +messages-set-pin --open-conversation-id <openConversationId> --msg-id <openMessageId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("set_pin_message", map[string]any{
			"openConversationId": rt.Str("open-conversation-id"),
			"cid":                rt.Str("open-conversation-id"),
			"openMessageId":      rt.Str("msg-id"),
		})
	},
}

MessagesSetPin pins a message (set_pin_message, im).

View Source
var MessagesSetTop = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-set-top",
	Product:     "im",
	Description: "置顶消息",
	Intent:      "当你想把某条消息置顶到会话顶部时使用;会实际置顶消息,需传会话 openConversationId 和消息 openMessageId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "open-conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "msg-id", Type: shortcut.FlagString, Desc: "消息 openMessageId", Required: true},
	},
	Tips: []string{`dws chat +messages-set-top --open-conversation-id <openConversationId> --msg-id <openMessageId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("set_top_message", map[string]any{
			"openConversationId": rt.Str("open-conversation-id"),
			"openMessageId":      rt.Str("msg-id"),
		})
	},
}

MessagesSetTop pins a message to the top (set_top_message, im).

View Source
var MessagesUnsetPin = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-unset-pin",
	Product:     "im",
	Description: "取消钉住消息(Unpin)",
	Intent:      "当你想取消此前钉住的消息时使用;会实际取消 Pin,需传会话 openConversationId 和消息 openMessageId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "open-conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "msg-id", Type: shortcut.FlagString, Desc: "消息 openMessageId", Required: true},
	},
	Tips: []string{`dws chat +messages-unset-pin --open-conversation-id <openConversationId> --msg-id <openMessageId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("unset_pin_message", map[string]any{
			"openConversationId": rt.Str("open-conversation-id"),
			"cid":                rt.Str("open-conversation-id"),
			"openMessageId":      rt.Str("msg-id"),
		})
	},
}

MessagesUnsetPin unpins a message (unset_pin_message, im).

View Source
var MessagesUnsetTop = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-unset-top",
	Product:     "im",
	Description: "取消置顶消息",
	Intent:      "当你想取消此前置顶的消息时使用;会实际取消置顶,需传会话 openConversationId 和消息 openMessageId。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "open-conversation-id", Type: shortcut.FlagString, Desc: "会话 openConversationId", Required: true},
		{Name: "msg-id", Type: shortcut.FlagString, Desc: "消息 openMessageId", Required: true},
	},
	Tips: []string{`dws chat +messages-unset-top --open-conversation-id <openConversationId> --msg-id <openMessageId>`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("unset_top_message", map[string]any{
			"openConversationId": rt.Str("open-conversation-id"),
			"openMessageId":      rt.Str("msg-id"),
		})
	},
}

MessagesUnsetTop cancels a message top (unset_top_message, im).

View Source
var MessagesUpdateCard = shortcut.Shortcut{
	Service:     "chat",
	Command:     "+messages-update-card",
	Product:     "im",
	Description: "流式更新卡片内容(最后一次 --flow-status 应为 3)",
	Intent:      "当你要向已发送的流式卡片持续追加/更新内容时使用;会实际更新卡片,需传 send-card 返回的 bizId、新内容及 flowStatus(最后一次应为 3 表示完成)。",
	Risk:        shortcut.RiskWrite,
	Flags: []shortcut.Flag{
		{Name: "biz-id", Type: shortcut.FlagString, Desc: "send-card 返回的卡片业务 ID", Required: true},
		{Name: "content", Type: shortcut.FlagString, Desc: "卡片消息内容", Required: true},
		{Name: "flow-status", Type: shortcut.FlagInt, Desc: "流式状态 1处理中/2输入中/3完成/4执行中/5错误", Required: true},
	},
	Tips: []string{`dws chat +messages-update-card --biz-id <bizId> --content "内容" --flow-status 3`},
	Execute: func(rt *shortcut.RuntimeContext) error {
		return rt.CallMCP("update_streaming_card", map[string]any{
			"bizId":      rt.Str("biz-id"),
			"msgContent": rt.Str("content"),
			"flowStatus": rt.Int("flow-status"),
		})
	},
}

MessagesUpdateCard streams updated card content (update_streaming_card, im).

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL