Files
dingtalk-workspace-cli/internal/shortcut/chatmsg/card_ref.go
栩朝 15a2fea0dc fix(chat): split references and harden card updates
Split chat message and group references by task, update intent routing and context budget, distinguish accepted card updates from verified writes, and explain the ambiguous chat --from flag.
2026-08-14 18:38:31 +08:00

70 lines
2.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright 2026 Alibaba Group
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
package chatmsg
import "strings"
// StreamingCardContractVersion identifies the additive card receipt emitted by
// high-level card shortcuts.
const StreamingCardContractVersion = "im.streaming-card.v1"
// ProjectStreamingCardReceipt publishes every server-returned identifier in a
// single cardRef. referencePairAvailable means this response contained both
// the update identifier and the visible message identifiers; it does not claim
// that older messages can be resolved without server-side mapping support.
func ProjectStreamingCardReceipt(created map[string]any, bizID string) map[string]any {
bizID = strings.TrimSpace(bizID)
messageID := firstSendStatusString(created, "openMessageId", "messageId", "msgId")
conversationID := firstSendStatusString(created, "openConversationId", "conversationId", "openCid")
cardRef := map[string]any{}
if bizID != "" {
cardRef["bizId"] = bizID
}
if messageID != "" {
cardRef["openMessageId"] = messageID
}
if conversationID != "" {
cardRef["openConversationId"] = conversationID
}
pairAvailable := bizID != "" && messageID != "" && conversationID != ""
payload := map[string]any{
"contractVersion": StreamingCardContractVersion,
"ok": true,
"cardRef": cardRef,
"referencePairAvailable": pairAvailable,
"created": created,
"nextActions": []map[string]any{},
}
if bizID != "" {
payload["nextActions"] = []map[string]any{{
"cliPath": "chat +messages-update-card",
"arguments": map[string]any{
"biz-id": bizID,
},
"requiredArguments": []string{"content", "flow-status"},
"ready": false,
}}
}
if !pairAvailable {
payload["capabilityGap"] = "服务端尚未同时返回 bizId、openMessageId 和 openConversationId;CLI 只能保留本次响应,不能据此承诺从历史消息反向恢复 bizId"
}
return payload
}
// ProjectStreamingCardUpdate preserves the lower response while making the
// verified target explicit for downstream consumers.
func ProjectStreamingCardUpdate(updated map[string]any, bizID string, verification CardUpdateVerification) map[string]any {
payload := cloneSendStatusMap(updated)
payload["contractVersion"] = StreamingCardContractVersion
payload["cardRef"] = map[string]any{"bizId": strings.TrimSpace(bizID)}
payload["accepted"] = verification.Accepted
payload["verified"] = verification.Verified
payload["verificationEvidence"] = verification.Evidence
if verification.Accepted && !verification.Verified {
payload["warning"] = "服务端已接受卡片更新请求,但未返回可独立证明可见内容已更新的字段;不要重复执行相同更新"
}
return payload
}