From a64fb5a168f2e44358b186265b893c4eec5dd1a5 Mon Sep 17 00:00:00 2001 From: weichen Date: Wed, 30 Sep 2026 15:03:32 +0000 Subject: [PATCH] Add CardID to CardPart for inbox-reference card parts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: 卡流机制(CF1)需要消息部件正式引用收件箱 ActivityCard——submit_card 产卡时卡片为产物权威载体,消息只存引用+锚点渲染(原仅能从 data 字符串里正则抠 card:)。 Evidence: go test ./... 通过;golden message.json 增 card 引用部件锁定 cardId 线格式(-update 重生成后逐字节一致)。 Impact: CardPart 增可选 cardId(omitempty,旧数据零影响);ts/types.ts 同步,镜像经 make contracts 再生成。 Refs: Dev 任务卡 feature/cardflow-r1;提案 cardflow-and-process-split(编制中)。 --- conformance_test.go | 3 ++- model.go | 7 +++++-- testdata/golden/message.json | 13 +++++++++++++ ts/types.ts | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/conformance_test.go b/conformance_test.go index 988a256..4fbebf9 100644 --- a/conformance_test.go +++ b/conformance_test.go @@ -47,6 +47,7 @@ func sampleMessage() Message { {Type: PartToolResult, Process: true, ToolResult: &ToolResultPart{CallID: "call_1", Status: "ok", Summary: "3 条命中"}}, {Type: PartText, Text: "根据历史记录……"}, {Type: PartArtifactRef, Artifact: &ArtifactRef{ArtifactID: "art_abc123def456", Name: "报告.md", Kind: "document"}}, + {Type: PartCard, Card: &CardPart{Kind: "result", Data: []UINode{{Type: "markdown", Markdown: "全文见卡片"}}, CardID: "card_abc123def456"}}, }, } } @@ -176,7 +177,7 @@ func TestGoldenProfileAndTools(t *testing.T) { golden(t, "tool_http", ToolDesc{ Name: "http_translate", Description: "调用翻译 API", Source: SourceUser, Parameters: json.RawMessage(`{"type":"object","properties":{"text":{"type":"string"}},"required":["text"]}`), - HTTP: &HTTPToolSpec{Method: "POST", URL: "https://api.example.com/translate", BodyTemplate: `{"q":"{{param.text}}"}`, TimeoutMs: 10000, ResultPath: "data.0"}, + HTTP: &HTTPToolSpec{Method: "POST", URL: "https://api.example.com/translate", BodyTemplate: `{"q":"{{param.text}}"}`, TimeoutMs: 10000, ResultPath: "data.0"}, }) } diff --git a/model.go b/model.go index 08f028e..ddb4128 100644 --- a/model.go +++ b/model.go @@ -124,9 +124,12 @@ type ErrorPart struct { } // CardPart.Data 是 UI schema 节点(4.6 有限词汇)。 +// CardID 非空 = 收件箱 ActivityCard 的引用部件(如 submit_card 产卡:卡片为产物 +// 权威载体,消息只存引用+锚点渲染);空 = 插件内嵌卡片部件(自包含 Data)。 type CardPart struct { - Kind string `json:"kind"` - Data []UINode `json:"data"` + Kind string `json:"kind"` + Data []UINode `json:"data"` + CardID ID `json:"cardId,omitempty"` } // ---- Run(一切运行皆 Run)---- diff --git a/testdata/golden/message.json b/testdata/golden/message.json index 13b9708..a774ab6 100644 --- a/testdata/golden/message.json +++ b/testdata/golden/message.json @@ -39,6 +39,19 @@ "name": "报告.md", "kind": "document" } + }, + { + "type": "card", + "card": { + "kind": "result", + "data": [ + { + "type": "markdown", + "markdown": "全文见卡片" + } + ], + "cardId": "card_abc123def456" + } } ], "createdAt": "0001-01-01T00:00:00Z" diff --git a/ts/types.ts b/ts/types.ts index ef4927b..bd6b748 100644 --- a/ts/types.ts +++ b/ts/types.ts @@ -32,7 +32,7 @@ export interface Part { artifact?: { artifactId: ID; name: string; kind?: string }; hitl?: { cardId: ID; question: string; resolved: boolean; answer?: string }; plan?: PlanSnapshot; - card?: { kind: string; data: UINode[] }; + card?: { kind: string; data: UINode[]; cardId?: ID }; // cardId 非空 = 收件箱卡片引用部件(submit_card) error?: { code: string; message: string }; process?: boolean; // run 终态后折叠为摘要行 }