From df28021698611a9a37260db5c9576cdf999c64b4 Mon Sep 17 00:00:00 2001 From: Mickey <951203214@qq.com> Date: Fri, 17 Apr 2026 15:12:50 +0800 Subject: [PATCH 1/7] chore: changelog of 2.6.0 --- CHANGELOG.en-US.md | 23 +++++++++++++++++++ CHANGELOG.zh-CN.md | 23 +++++++++++++++++++ package.json | 2 +- packages/x-card/package.json | 2 +- packages/x-card/src/version.ts | 2 +- packages/x-markdown/package.json | 2 +- packages/x-sdk/package.json | 2 +- .../x-skill/.claude-plugin/marketplace.json | 2 +- packages/x-skill/package.json | 2 +- .../x-skill/skills-zh/use-x-chat/SKILL.md | 2 +- packages/x-skill/skills-zh/x-card/SKILL.md | 2 +- .../skills-zh/x-chat-provider/SKILL.md | 2 +- .../x-skill/skills-zh/x-components/SKILL.md | 2 +- .../x-skill/skills-zh/x-markdown/SKILL.md | 2 +- packages/x-skill/skills-zh/x-request/SKILL.md | 2 +- packages/x-skill/skills/use-x-chat/SKILL.md | 2 +- packages/x-skill/skills/x-card/SKILL.md | 2 +- .../x-skill/skills/x-chat-provider/SKILL.md | 2 +- packages/x-skill/skills/x-components/SKILL.md | 2 +- packages/x-skill/skills/x-markdown/SKILL.md | 2 +- packages/x-skill/skills/x-request/SKILL.md | 2 +- packages/x/package.json | 2 +- 22 files changed, 66 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index 6302962df..6e7158b94 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -16,6 +16,29 @@ tag: vVERSION --- +## 2.6.0 + +`2026-04-17` + +### @ant-design/x + +- 🐛 Fix duplicate `className` passed to the root element of `ThoughtChain`, and default `contentOpen` to `false` to prevent `undefined` when `expandedKeys` is not provided. [#1851](https://github.com/ant-design/x/pull/1851) by [feoyang](https://github.com/feoyang) +- 🐛 Fix Folder component title display bug. [#1855](https://github.com/ant-design/x/pull/1855) by [kimteayon](https://github.com/kimteayon) + +### @ant-design/x-markdown + +- 🆕 Support rendering block-level LaTeX formulas inside paragraphs, using `` instead of `
` to be compatible with inline contexts. [#1859](https://github.com/ant-design/x/pull/1859) by [Div627](https://github.com/Div627) + +### @ant-design/x-skill + +- 🆕 Added `x-components` skill, providing full API documentation, usage patterns, and best practices for all `@ant-design/x` components. [#1862](https://github.com/ant-design/x/pull/1862) by [kimteayon](https://github.com/kimteayon) +- 🆕 Added `x-card` skill, providing complete API reference, data binding, Actions, and Commands documentation for `@ant-design/x-card`. [#1865](https://github.com/ant-design/x/pull/1865) by [kimteayon](https://github.com/kimteayon) +- 🛠 Updated `use-x-chat`, `x-chat-provider`, and `x-request` skill content to sync with the latest APIs and examples. [#1862](https://github.com/ant-design/x/pull/1862) by [kimteayon](https://github.com/kimteayon) + +### Others + +- 📖 Fix broken documentation link in the X SDK usage guide. [#1856](https://github.com/ant-design/x/pull/1856) by [xiaohp](https://github.com/xiaohp) + ## 2.5.0 `2026-03-31` diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index df51c7dd2..0e5cc9c69 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -15,6 +15,29 @@ tag: vVERSION --- +## 2.6.0 + +`2026-04-17` + +### @ant-design/x + +- 🐛 修复 ThoughtChain 组件根元素重复传入 `className` 的问题,并将 `contentOpen` 默认值修正为 `false`,避免未传 `expandedKeys` 时出现 `undefined`。[#1851](https://github.com/ant-design/x/pull/1851) 由 [feoyang](https://github.com/feoyang) 提交 +- 🐛 修复 Folder 组件标题展示异常的问题。[#1855](https://github.com/ant-design/x/pull/1855) 由 [kimteayon](https://github.com/kimteayon) 提交 + +### @ant-design/x-markdown + +- 🆕 支持在段落(paragraph)中渲染块级 LaTeX 公式,使用 `` 替代 `
` 以兼容行内上下文。[#1859](https://github.com/ant-design/x/pull/1859) 由 [Div627](https://github.com/Div627) 提交 + +### @ant-design/x-skill + +- 🆕 新增 `x-components` skill,提供 `@ant-design/x` 全组件 API 文档、使用模式与最佳实践参考。[#1862](https://github.com/ant-design/x/pull/1862) 由 [kimteayon](https://github.com/kimteayon) 提交 +- 🆕 新增 `x-card` skill,提供 `@ant-design/x-card` 动态卡片组件的完整 API、数据绑定、Actions 与 Commands 参考文档。[#1865](https://github.com/ant-design/x/pull/1865) 由 [kimteayon](https://github.com/kimteayon) 提交 +- 🛠 更新 `use-x-chat`、`x-chat-provider`、`x-request` skill 内容,同步最新 API 与示例。[#1862](https://github.com/ant-design/x/pull/1862) 由 [kimteayon](https://github.com/kimteayon) 提交 + +### 其他 + +- 📖 修复 X SDK 使用文档中的链接错误。[#1856](https://github.com/ant-design/x/pull/1856) 由 [xiaohp](https://github.com/xiaohp) 提交 + ## 2.5.0 `2026-03-31` diff --git a/package.json b/package.json index 6c0633501..7cda87761 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "x-mono", - "version": "2.5.0", + "version": "2.6.0", "private": true, "scripts": { "presite": "npm run prestart --workspaces", diff --git a/packages/x-card/package.json b/packages/x-card/package.json index 710a98f49..ea7e9d9ba 100644 --- a/packages/x-card/package.json +++ b/packages/x-card/package.json @@ -1,6 +1,6 @@ { "name": "@ant-design/x-card", - "version": "2.5.0", + "version": "2.6.0", "description": "React card loader for dynamic content loading and management", "keywords": [ "A2UI", diff --git a/packages/x-card/src/version.ts b/packages/x-card/src/version.ts index cd3b87818..b28255779 100644 --- a/packages/x-card/src/version.ts +++ b/packages/x-card/src/version.ts @@ -1,2 +1,2 @@ // This file is auto generated by npm run version -export default '2.5.0'; +export default '2.6.0'; diff --git a/packages/x-markdown/package.json b/packages/x-markdown/package.json index 885401ee6..4e431d9e5 100644 --- a/packages/x-markdown/package.json +++ b/packages/x-markdown/package.json @@ -1,6 +1,6 @@ { "name": "@ant-design/x-markdown", - "version": "2.5.0", + "version": "2.6.0", "scripts": { "compile": "father build", "tsc": "tsc --noEmit", diff --git a/packages/x-sdk/package.json b/packages/x-sdk/package.json index 7b80881cf..15ca214c9 100644 --- a/packages/x-sdk/package.json +++ b/packages/x-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@ant-design/x-sdk", - "version": "2.5.0", + "version": "2.6.0", "homepage": "https://x.ant.design/x-sdks/introduce", "bugs": { "url": "https://github.com/ant-design/x/issues" diff --git a/packages/x-skill/.claude-plugin/marketplace.json b/packages/x-skill/.claude-plugin/marketplace.json index 9dd4254b8..b28b1f036 100644 --- a/packages/x-skill/.claude-plugin/marketplace.json +++ b/packages/x-skill/.claude-plugin/marketplace.json @@ -3,7 +3,7 @@ "metadata": { "description": "Ant Design X intelligent agent skills collection", "descriptionZh": "Ant Design X 智能技能库,提供完整的 AI 对话应用开发技能", - "version": "2.5.0", + "version": "2.6.0", "author": "Ant Design X Team", "homepage": "https://github.com/ant-design/x", "repository": { diff --git a/packages/x-skill/package.json b/packages/x-skill/package.json index 6a15cb9cc..671e5b41a 100644 --- a/packages/x-skill/package.json +++ b/packages/x-skill/package.json @@ -1,6 +1,6 @@ { "name": "@ant-design/x-skill", - "version": "2.5.0", + "version": "2.6.0", "description": "CLI tool for installing AI skills to development tools like Claude, Cursor, etc.", "homepage": "https://x.ant.design/x-skills/introduce", "bugs": { diff --git a/packages/x-skill/skills-zh/use-x-chat/SKILL.md b/packages/x-skill/skills-zh/use-x-chat/SKILL.md index 3268f3fef..84f8342a2 100644 --- a/packages/x-skill/skills-zh/use-x-chat/SKILL.md +++ b/packages/x-skill/skills-zh/use-x-chat/SKILL.md @@ -1,6 +1,6 @@ --- name: use-x-chat -version: 2.5.0 +version: 2.6.0 description: 专注讲解如何使用 useXChat Hook,包括自定义 Provider 的集成、消息管理、错误处理、多会话管理等 --- diff --git a/packages/x-skill/skills-zh/x-card/SKILL.md b/packages/x-skill/skills-zh/x-card/SKILL.md index 27dc965f6..dd28ad476 100644 --- a/packages/x-skill/skills-zh/x-card/SKILL.md +++ b/packages/x-skill/skills-zh/x-card/SKILL.md @@ -1,6 +1,6 @@ --- name: x-card -version: 2.5.0 +version: 2.6.0 description: 当需要用 @ant-design/x-card 让 AI Agent 动态渲染富交互 UI 时使用——涵盖 XCard.Box、XCard.Card、A2UI v0.9 命令、数据绑定、Catalog、Actions 和流式渲染模式。 --- diff --git a/packages/x-skill/skills-zh/x-chat-provider/SKILL.md b/packages/x-skill/skills-zh/x-chat-provider/SKILL.md index e74bfd706..1c1229b7f 100644 --- a/packages/x-skill/skills-zh/x-chat-provider/SKILL.md +++ b/packages/x-skill/skills-zh/x-chat-provider/SKILL.md @@ -1,6 +1,6 @@ --- name: x-chat-provider -version: 2.5.0 +version: 2.6.0 description: 专注于自定义 Chat Provider 的实现,帮助将任意流式接口适配为 Ant Design X 标准格式 --- diff --git a/packages/x-skill/skills-zh/x-components/SKILL.md b/packages/x-skill/skills-zh/x-components/SKILL.md index 70563985e..576589d32 100644 --- a/packages/x-skill/skills-zh/x-components/SKILL.md +++ b/packages/x-skill/skills-zh/x-components/SKILL.md @@ -1,6 +1,6 @@ --- name: x-components -version: 2.5.0 +version: 2.6.0 description: 使用 @ant-design/x 组件库构建 AI 对话 UI 时使用 —— 涵盖 Bubble、Sender、Conversations、Prompts、ThoughtChain、Actions、Welcome、Attachments、Sources、Suggestion、Think、FileCard、CodeHighlighter、Mermaid、Folder、XProvider 和 Notification。 --- diff --git a/packages/x-skill/skills-zh/x-markdown/SKILL.md b/packages/x-skill/skills-zh/x-markdown/SKILL.md index 7d2c6493e..288d28d67 100644 --- a/packages/x-skill/skills-zh/x-markdown/SKILL.md +++ b/packages/x-skill/skills-zh/x-markdown/SKILL.md @@ -1,6 +1,6 @@ --- name: x-markdown -version: 2.5.0 +version: 2.6.0 description: 当任务涉及 @ant-design/x-markdown 的 Markdown 渲染、流式输出、自定义组件映射、插件、主题或聊天富内容展示时使用。 --- diff --git a/packages/x-skill/skills-zh/x-request/SKILL.md b/packages/x-skill/skills-zh/x-request/SKILL.md index 82cff72e5..a5abb4d88 100644 --- a/packages/x-skill/skills-zh/x-request/SKILL.md +++ b/packages/x-skill/skills-zh/x-request/SKILL.md @@ -1,6 +1,6 @@ --- name: x-request -version: 2.5.0 +version: 2.6.0 description: 专注讲解 XRequest 的实际配置和使用,基于官方文档提供准确的配置说明 --- diff --git a/packages/x-skill/skills/use-x-chat/SKILL.md b/packages/x-skill/skills/use-x-chat/SKILL.md index a281ea8c7..7ae9a0e7b 100644 --- a/packages/x-skill/skills/use-x-chat/SKILL.md +++ b/packages/x-skill/skills/use-x-chat/SKILL.md @@ -1,6 +1,6 @@ --- name: use-x-chat -version: 2.5.0 +version: 2.6.0 description: Focus on explaining how to use the useXChat Hook, including custom Provider integration, message management, error handling, multi-conversation management, and more --- diff --git a/packages/x-skill/skills/x-card/SKILL.md b/packages/x-skill/skills/x-card/SKILL.md index 57ffb631c..f463b0cf5 100644 --- a/packages/x-skill/skills/x-card/SKILL.md +++ b/packages/x-skill/skills/x-card/SKILL.md @@ -1,6 +1,6 @@ --- name: x-card -version: 2.5.0 +version: 2.6.0 description: Use when building AI-driven UIs with @ant-design/x-card — covers XCard.Box, XCard.Card, A2UI v0.9 commands, data binding, catalogs, actions, and streaming patterns. --- diff --git a/packages/x-skill/skills/x-chat-provider/SKILL.md b/packages/x-skill/skills/x-chat-provider/SKILL.md index 5a3eb0d17..c534cbc9b 100644 --- a/packages/x-skill/skills/x-chat-provider/SKILL.md +++ b/packages/x-skill/skills/x-chat-provider/SKILL.md @@ -1,6 +1,6 @@ --- name: x-chat-provider -version: 2.5.0 +version: 2.6.0 description: Focus on implementing custom Chat Provider, helping to adapt any streaming interface to Ant Design X standard format --- diff --git a/packages/x-skill/skills/x-components/SKILL.md b/packages/x-skill/skills/x-components/SKILL.md index 341dcc547..0449da22a 100644 --- a/packages/x-skill/skills/x-components/SKILL.md +++ b/packages/x-skill/skills/x-components/SKILL.md @@ -1,6 +1,6 @@ --- name: x-components -version: 2.5.0 +version: 2.6.0 description: Use when building AI chat UIs with @ant-design/x components — covers Bubble, Sender, Conversations, Prompts, ThoughtChain, Actions, Welcome, Attachments, Sources, Suggestion, Think, FileCard, CodeHighlighter, Mermaid, Folder, XProvider, and Notification. --- diff --git a/packages/x-skill/skills/x-markdown/SKILL.md b/packages/x-skill/skills/x-markdown/SKILL.md index 4a13a65aa..55b706f02 100644 --- a/packages/x-skill/skills/x-markdown/SKILL.md +++ b/packages/x-skill/skills/x-markdown/SKILL.md @@ -1,6 +1,6 @@ --- name: x-markdown -version: 2.5.0 +version: 2.6.0 description: Use when building or reviewing Markdown rendering with @ant-design/x-markdown, including streaming Markdown, custom component mapping, plugins, themes, and chat-oriented rich content. --- diff --git a/packages/x-skill/skills/x-request/SKILL.md b/packages/x-skill/skills/x-request/SKILL.md index d4b24cc87..349623dfe 100644 --- a/packages/x-skill/skills/x-request/SKILL.md +++ b/packages/x-skill/skills/x-request/SKILL.md @@ -1,6 +1,6 @@ --- name: x-request -version: 2.5.0 +version: 2.6.0 description: Focus on explaining the practical configuration and usage of XRequest, providing accurate configuration instructions based on official documentation --- diff --git a/packages/x/package.json b/packages/x/package.json index f8c2abb9c..df19657e4 100644 --- a/packages/x/package.json +++ b/packages/x/package.json @@ -1,6 +1,6 @@ { "name": "@ant-design/x", - "version": "2.5.0", + "version": "2.6.0", "description": "Craft AI-driven interfaces effortlessly", "keywords": [ "AI", From 45fef5d3b530de9c3a9a9acea785e3254bb86aad Mon Sep 17 00:00:00 2001 From: Mickey <951203214@qq.com> Date: Fri, 17 Apr 2026 16:38:38 +0800 Subject: [PATCH 2/7] chore: changelog of 2.6.0 --- packages/x/.dumi/hooks/useLocale.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x/.dumi/hooks/useLocale.ts b/packages/x/.dumi/hooks/useLocale.ts index 20bb5f5b9..ad271ec16 100644 --- a/packages/x/.dumi/hooks/useLocale.ts +++ b/packages/x/.dumi/hooks/useLocale.ts @@ -1,4 +1,4 @@ -import { useIntl } from 'dumi'; +import { useIntl } from 'dumi/dist/client/theme-api'; export interface LocaleMap< K extends PropertyKey = PropertyKey, From c6ee8302559df0518103a8ecca74ed79dea40914 Mon Sep 17 00:00:00 2001 From: Mickey <951203214@qq.com> Date: Thu, 30 Apr 2026 00:37:21 +0800 Subject: [PATCH 3/7] feat: test --- CHANGELOG.zh-CN.md | 12 +++ packages/x-card/src/A2UI/Card.tsx | 15 +++- packages/x-card/src/A2UI/Card.v0.8.ts | 26 +++++- packages/x-card/src/A2UI/Card.v0.9.ts | 21 ++++- .../src/A2UI/__tests__/Card.coverage.test.tsx | 82 +++++++++++++++++++ 5 files changed, 147 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index 0e5cc9c69..d253ccfe0 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -15,6 +15,18 @@ tag: vVERSION --- +## 2.7.0 + +`2026-04-30` + +### @ant-design/x + +- 🆕 XProvider 新增 `zeroRuntime` 属性,支持 Zero Runtime CSS-in-JS 模式,在构建时提取样式,避免运行时样式注入,提升性能。[#1737](https://github.com/ant-design/x/pull/1737) 由 [seanparmelee](https://github.com/seanparmelee) 提交 + +### 其他 + +- 📖 官网新增搜索栏,提升文档检索体验。[#1831](https://github.com/ant-design/x/pull/1831) 由 [1uokun](https://github.com/1uokun) 提交 + ## 2.6.0 `2026-04-17` diff --git a/packages/x-card/src/A2UI/Card.tsx b/packages/x-card/src/A2UI/Card.tsx index c80842a31..04cc7fb3f 100644 --- a/packages/x-card/src/A2UI/Card.tsx +++ b/packages/x-card/src/A2UI/Card.tsx @@ -6,9 +6,11 @@ import type { Catalog } from './catalog'; // v0.8 specific logic import { resolvePropsV08, extractDataUpdatesV08, applyDataModelUpdateV08 } from './Card.v0.8'; +import type { ActionConfigV08 } from './Card.v0.8'; // v0.9 specific logic import { resolvePropsV09, extractDataUpdatesV09, applyDataModelUpdateV09 } from './Card.v0.9'; +import type { ActionConfigV09 } from './Card.v0.9'; // Shared logic import { setValueByPath, validateComponentAgainstCatalog } from './utils'; @@ -17,13 +19,16 @@ export interface CardProps { id: string; } +/** actionConfig 联合类型,兼容 v0.8 和 v0.9 格式 */ +type ActionConfig = ActionConfigV08 | ActionConfigV09; + /** Recursively render a single node, child nodes are found via getById */ function renderNode( nodeId: string, transformer: ComponentTransformer, components: Record>, dataModel: Record, - onAction?: (name: string, context: Record, actionConfig?: any) => void, + onAction?: (name: string, context: Record, actionConfig?: ActionConfig) => void, onDataChange?: (path: string, value: any) => void, catalog?: Catalog, commandVersion?: 'v0.8' | 'v0.9', @@ -51,7 +56,7 @@ interface NodeRendererProps { transformer: ComponentTransformer; components: Record>; dataModel: Record; - onAction?: (name: string, context: Record, actionConfig?: any) => void; + onAction?: (name: string, context: Record, actionConfig?: ActionConfig) => void; /** Callback when component writes back to dataModel via onChange, path is the binding path */ onDataChange?: (path: string, value: any) => void; /** catalog for component validation */ @@ -324,7 +329,11 @@ const Card: React.FC = ({ id }) => { * Handler when action is triggered * Use different extractDataUpdates and resolveActionContext based on version */ - const handleAction = (name: string, context: Record, actionConfig?: any) => { + const handleAction = ( + name: string, + context: Record, + actionConfig?: ActionConfig, + ) => { // Use different extractDataUpdates based on version const dataUpdates = commandVersion === 'v0.9' diff --git a/packages/x-card/src/A2UI/Card.v0.8.ts b/packages/x-card/src/A2UI/Card.v0.8.ts index fd15571cf..abb526c84 100644 --- a/packages/x-card/src/A2UI/Card.v0.8.ts +++ b/packages/x-card/src/A2UI/Card.v0.8.ts @@ -23,9 +23,27 @@ import { validateComponentAgainstCatalog, } from './utils'; +/** v0.8 action.context 中单个条目的类型(正常格式) */ +export interface ActionContextItemV08 { + key: string; + value: { path: string } | { literalString: string } | unknown; +} + +/** v0.8 action 配置类型 */ +export interface ActionConfigV08 { + name?: string; + /** 运行时可能收到非法值,函数内部通过 Array.isArray 防御 */ + context?: ActionContextItemV08[] | unknown; + [key: string]: unknown; +} + /** 判断一个值是否为 { literalString: string } 形式的字面字符串对象 */ -export function isLiteralStringObject(val: any): val is { literalString: string } { - return val !== null && typeof val === 'object' && typeof val.literalString === 'string'; +export function isLiteralStringObject(val: unknown): val is { literalString: string } { + return ( + val !== null && + typeof val === 'object' && + typeof (val as Record).literalString === 'string' + ); } /** 将 props 中的路径值替换为 dataModel 中的真实值(v0.8 版本) */ @@ -93,7 +111,7 @@ function resolveValueV08(val: any, dataModel: Record, isActionConte * v0.8 格式: action.context 是数组 [{ key, value: { path: string } | literal }] */ export function resolveActionContextV08( - action: any, + action: ActionConfigV08 | undefined, dataModel: Record, ): Record | undefined { const context = action?.context; @@ -133,7 +151,7 @@ export function resolveActionContextV08( * @returns 需要更新的数据路径和值的数组 */ export function extractDataUpdatesV08( - action: any, + action: ActionConfigV08 | undefined, componentContext: Record, ): Array<{ path: string; value: any }> { const context = action?.context; diff --git a/packages/x-card/src/A2UI/Card.v0.9.ts b/packages/x-card/src/A2UI/Card.v0.9.ts index c81e532ae..35beed4df 100644 --- a/packages/x-card/src/A2UI/Card.v0.9.ts +++ b/packages/x-card/src/A2UI/Card.v0.9.ts @@ -20,6 +20,23 @@ import { validateComponentAgainstCatalog, } from './utils'; +/** v0.9 action.event.context 中单个值的类型 */ +export type ActionContextValueV09 = { path: string } | unknown; + +/** v0.9 action.event 类型 */ +export interface ActionEventV09 { + name?: string; + /** 运行时可能收到非法值(数组、字符串、null),函数内部通过类型守卫防御 */ + context?: Record | unknown; + [key: string]: unknown; +} + +/** v0.9 action 配置类型 */ +export interface ActionConfigV09 { + event?: ActionEventV09; + [key: string]: unknown; +} + /** 将 props 中的路径值替换为 dataModel 中的真实值 */ export function resolvePropsV09( props: Record, @@ -117,7 +134,7 @@ function resolveValueV09(val: any, dataModel: Record): any { * v0.9 格式: action.event.context 是对象 { key: { path: string } | literal } */ export function resolveActionContextV09( - action: any, + action: ActionConfigV09 | undefined, dataModel: Record, ): Record | undefined { const context = action?.event?.context; @@ -147,7 +164,7 @@ export function resolveActionContextV09( * @returns 需要更新的数据路径和值的数组 */ export function extractDataUpdatesV09( - action: any, + action: ActionConfigV09 | undefined, componentContext: Record, ): Array<{ path: string; value: any }> { const context = action?.event?.context; diff --git a/packages/x-card/src/A2UI/__tests__/Card.coverage.test.tsx b/packages/x-card/src/A2UI/__tests__/Card.coverage.test.tsx index de3012543..5b98ce728 100644 --- a/packages/x-card/src/A2UI/__tests__/Card.coverage.test.tsx +++ b/packages/x-card/src/A2UI/__tests__/Card.coverage.test.tsx @@ -726,4 +726,86 @@ describe('Card.tsx coverage', () => { }); }); }); + + describe('v0.9 action context literal value', () => { + it('should report component runtime context, not config literal values', async () => { + // 验证 v0.9 的行为:上报的 context 来自组件运行时传入,而非配置侧字面量。 + // 配置侧的 { path } 绑定仅用于写回 dataModel,字面量不会被合并到上报 context。 + const onAction = jest.fn(); + + const ClickableComponent: React.FC<{ + onAction?: (name: string, ctx: Record) => void; + }> = ({ onAction: componentOnAction }) => ( + + ); + + render( + + + , + ); + + fireEvent.click(screen.getByTestId('click-btn')); + + await waitFor(() => { + expect(onAction).toHaveBeenCalledWith( + expect.objectContaining({ + name: 'click', + surfaceId: 'card1', + // 上报的 context 只包含组件运行时传入的值 + context: expect.objectContaining({ + value: 'runtime-value', + }), + }), + ); + // 配置侧字面量 label 不会出现在上报 context 中 + expect(onAction).toHaveBeenCalledWith( + expect.objectContaining({ + context: expect.not.objectContaining({ + label: 'static-label', + }), + }), + ); + }); + }); + }); }); From c70f708648a485e15659c0c267abf9aa0049ee40 Mon Sep 17 00:00:00 2001 From: Mickey <951203214@qq.com> Date: Thu, 30 Apr 2026 00:47:46 +0800 Subject: [PATCH 4/7] feat: test --- packages/x-card/src/A2UI/Card.tsx | 3 +- .../src/A2UI/__tests__/Card.coverage.test.tsx | 73 ++++++++++++++----- .../skills-zh/x-card/reference/ACTIONS.md | 11 ++- .../skills/x-card/reference/ACTIONS.md | 9 ++- 4 files changed, 72 insertions(+), 24 deletions(-) diff --git a/packages/x-card/src/A2UI/Card.tsx b/packages/x-card/src/A2UI/Card.tsx index 3a6a867c3..5b8061bbe 100644 --- a/packages/x-card/src/A2UI/Card.tsx +++ b/packages/x-card/src/A2UI/Card.tsx @@ -397,9 +397,10 @@ const Card: React.FC = ({ id }) => { for (const [key, val] of Object.entries(v09Context)) { if (isPathObject(val)) { // 从 dataModel 读取实际值,保留其他属性(如 label),将 path 替换为 value + // 注意:value: actualValue 必须放在 ...rest 之后,防止 rest 中残留的 value 字段覆盖解析结果 const actualValue = getValueByPath(dataModel, (val as { path: string }).path); const { path, ...rest } = val as { path: string; [key: string]: any }; - resolvedFromConfig[key] = { value: actualValue, ...rest }; + resolvedFromConfig[key] = { ...rest, value: actualValue }; } else { resolvedFromConfig[key] = val; } diff --git a/packages/x-card/src/A2UI/__tests__/Card.coverage.test.tsx b/packages/x-card/src/A2UI/__tests__/Card.coverage.test.tsx index 8818dd8c8..c68cefc76 100644 --- a/packages/x-card/src/A2UI/__tests__/Card.coverage.test.tsx +++ b/packages/x-card/src/A2UI/__tests__/Card.coverage.test.tsx @@ -849,6 +849,9 @@ describe('Card.tsx additional branch coverage', () => { describe('resolveActionContextPathRefs v0.9 non-path-object branch (Card.tsx line 390-393)', () => { it('should pass through non-path-object values in v0.9 context', async () => { // 测试覆盖 Card.tsx 行 394-396: v0.9 context 中值不是 path 对象时直接保留 + // 修复说明:组件运行时不传与配置侧同名的 key(label), + // 只传 value,确保断言真正验证运行时传入的值, + // 并额外断言配置侧字面量 static-label 不会出现在上报 context 中。 const onAction = jest.fn(); const ClickableComponent: React.FC<{ @@ -859,10 +862,9 @@ describe('Card.tsx additional branch coverage', () => { data-testid="click-btn" onClick={() => componentOnAction?.('click', { - // 传递一个普通字符串值(非 path 对象) - label: 'hello', - // 传递一个 path 对象(会被解析) - value: { path: '/data/value' }, + // 只传 value(对应配置侧 path 绑定),不传 label + // 这样可以验证配置侧字面量 label 不会出现在上报 context 中 + value: 'runtime-value', }) } > @@ -892,9 +894,11 @@ describe('Card.tsx additional branch coverage', () => { action: { event: { name: 'click', - // context 中包含 path 对象和非 path 对象 + // context 中包含 path 对象和非 path 对象(字面量) context: { + // 字面量:不会出现在上报 context 中 label: 'static-label', + // path 绑定:用于将组件传入的 value 写回 dataModel value: { path: '/data/value' }, }, }, @@ -914,13 +918,21 @@ describe('Card.tsx additional branch coverage', () => { fireEvent.click(screen.getByTestId('click-btn')); await waitFor(() => { + // 上报的 context 只包含组件运行时传入的值 expect(onAction).toHaveBeenCalledWith( expect.objectContaining({ name: 'click', surfaceId: 'card1', context: expect.objectContaining({ - // 非 path 对象的 label 应该直接保留 - label: 'hello', + value: 'runtime-value', + }), + }), + ); + // 配置侧字面量 label 不会出现在上报 context 中 + expect(onAction).toHaveBeenCalledWith( + expect.objectContaining({ + context: expect.not.objectContaining({ + label: 'static-label', }), }), ); @@ -931,6 +943,9 @@ describe('Card.tsx additional branch coverage', () => { describe('resolveActionContextPathRefs v0.8 non-path-object branch (Card.tsx line 409-410)', () => { it('should pass through non-path-object values in v0.8 context', async () => { // 测试覆盖 Card.tsx 行 411-413: v0.8 context 中值不是 path 对象时直接保留 + // 修复说明:组件运行时不传与配置侧同名的 key(staticKey), + // 只传 dynamicKey(对应配置侧 path 绑定),确保断言真正验证运行时传入的值, + // 并额外断言配置侧字面量 literal-value 不会出现在上报 context 中。 const onAction = jest.fn(); const ClickableComponent: React.FC<{ @@ -941,10 +956,9 @@ describe('Card.tsx additional branch coverage', () => { data-testid="click-btn-v08" onClick={() => componentOnAction?.('click', { - // 传递一个普通字符串值(非 path 对象) - staticKey: 'static-value', - // 传递一个 path 对象(会被解析) - dynamicKey: { path: '/data/dynamic' }, + // 只传 dynamicKey(对应配置侧 path 绑定),不传 staticKey + // 这样可以验证配置侧字面量 literal-value 不会出现在上报 context 中 + dynamicKey: 'runtime-dynamic', }) } > @@ -968,11 +982,12 @@ describe('Card.tsx additional branch coverage', () => { context: [ { key: 'staticKey', - // 非 path 对象,直接是字面值 + // 非 path 对象,直接是字面值:不会出现在上报 context 中 value: 'literal-value', }, { key: 'dynamicKey', + // path 绑定:用于将组件传入的 dynamicKey 写回 dataModel value: { path: '/data/dynamic' }, }, ], @@ -1000,13 +1015,21 @@ describe('Card.tsx additional branch coverage', () => { fireEvent.click(screen.getByTestId('click-btn-v08')); await waitFor(() => { + // 上报的 context 只包含组件运行时传入的值 expect(onAction).toHaveBeenCalledWith( expect.objectContaining({ name: 'click', surfaceId: 'card1', - // v0.8 中非 path 对象的值应该直接保留 context: expect.objectContaining({ - staticKey: 'static-value', + dynamicKey: 'runtime-dynamic', + }), + }), + ); + // 配置侧字面量 literal-value 不会出现在上报 context 中 + expect(onAction).toHaveBeenCalledWith( + expect.objectContaining({ + context: expect.not.objectContaining({ + staticKey: 'literal-value', }), }), ); @@ -1149,7 +1172,9 @@ describe('Card.tsx additional branch coverage', () => { describe('v0.8 resolveActionContextPathRefs with empty resolvedContext (Card.tsx line 418)', () => { it('should return original componentContext when v0.8 context has no path objects', async () => { - // 测试 v0.8 格式下 resolvedContext 为空时返回原始 componentContext + // 测试 v0.8 格式下 context 数组中只有字面量(无 path 对象)时的行为: + // extractDataUpdatesV08 只处理 { path } 绑定,字面量会被跳过(dataUpdates 为空); + // handleAction 上报时 context 只包含组件运行时传入的值,配置侧字面量不会出现。 const onAction = jest.fn(); const ClickableComponent: React.FC<{ @@ -1180,11 +1205,11 @@ describe('Card.tsx additional branch coverage', () => { component: { ClickableComponent: { action: { - // v0.8 格式: context 是数组,但没有 path 对象 + // v0.8 格式: context 是数组,但没有 path 对象,只有字面量 context: [ { key: 'literalKey', - value: 'literal-value', // 非 path 对象 + value: 'literal-value', // 非 path 对象,会被 extractDataUpdatesV08 跳过 }, ], }, @@ -1211,10 +1236,22 @@ describe('Card.tsx additional branch coverage', () => { fireEvent.click(screen.getByTestId('click-v08-empty')); await waitFor(() => { + // 上报的 context 只包含组件运行时传入的值 expect(onAction).toHaveBeenCalledWith( expect.objectContaining({ name: 'click', surfaceId: 'card1', + context: expect.objectContaining({ + someValue: 'test', + }), + }), + ); + // 配置侧字面量不会出现在上报 context 中 + expect(onAction).toHaveBeenCalledWith( + expect.objectContaining({ + context: expect.not.objectContaining({ + literalKey: 'literal-value', + }), }), ); }); @@ -1323,6 +1360,8 @@ describe('Card.tsx additional branch coverage', () => { await waitFor(() => { expect(screen.getByTestId('strict')).toBeInTheDocument(); + // 验证开发模式下 validation.errors.forEach 确实被执行,并输出了包含字段名的警告 + expect(console.warn).toHaveBeenCalledWith(expect.stringContaining('requiredProp')); }); process.env.NODE_ENV = originalEnv; diff --git a/packages/x-skill/skills-zh/x-card/reference/ACTIONS.md b/packages/x-skill/skills-zh/x-card/reference/ACTIONS.md index 46c48731c..5780dc5d7 100644 --- a/packages/x-skill/skills-zh/x-card/reference/ACTIONS.md +++ b/packages/x-skill/skills-zh/x-card/reference/ACTIONS.md @@ -148,8 +148,9 @@ v0.8 使用数组格式定义路径绑定: ```tsx const handleAction = (payload: ActionPayload) => { if (payload.name === 'submit_form') { - // context 是完整的 dataModel 快照,按数据模型结构取值 - const { email, name } = payload.context.form; + // context 中每个 key 对应配置里的 path 绑定,已解析为 { value, ...rest } 格式 + const email = payload.context.email?.value; + const name = payload.context.name?.value; // 1. 调用 Agent API // 2. 追加新命令作为响应 setCmdQueue(prev => [ @@ -210,16 +211,18 @@ const formCommands: XAgentCommand_v0_9[] = [ { version: 'v0.9', updateDataModel: { surfaceId: 'form', path: '/form', value: { email: '' } } }, ]; -// 2. 处理提交(context 是完整 dataModel 快照) +// 2. 处理提交 +// context 中每个 key 对应配置里的 path 绑定,已解析为 { value, ...rest } 格式 const handleAction = async (payload: ActionPayload) => { if (payload.name === 'submit') { + const email = payload.context.email?.value; // 显示加载状态 setCmdQueue((prev) => [ ...prev, { version: 'v0.9', updateDataModel: { surfaceId: 'form', path: '/ui/loading', value: true } }, ]); // 调用 Agent 处理,返回后展示结果 - const result = await callAgent(payload.context); + const result = await callAgent({ email }); setCmdQueue((prev) => [ ...prev, { diff --git a/packages/x-skill/skills/x-card/reference/ACTIONS.md b/packages/x-skill/skills/x-card/reference/ACTIONS.md index 00bf5bb82..e7639ec55 100644 --- a/packages/x-skill/skills/x-card/reference/ACTIONS.md +++ b/packages/x-skill/skills/x-card/reference/ACTIONS.md @@ -148,7 +148,10 @@ When the user clicks the button, `onAction` receives: ```tsx const handleAction = (payload: ActionPayload) => { if (payload.name === 'submit_form') { - const { email, name } = payload.context; + // Each key in context corresponds to a path binding in the config, + // resolved to { value, ...rest } format + const email = payload.context.email?.value; + const name = payload.context.name?.value; // 1. Call your agent API // 2. Push new commands in response setCmdQueue(prev => [ @@ -218,15 +221,17 @@ const formCommands: XAgentCommand_v0_9[] = [ ]; // 2. Handle submission +// Each key in context is resolved to { value, ...rest } format const handleAction = async (payload: ActionPayload) => { if (payload.name === 'submit') { + const email = payload.context.email?.value; // Show loading setCmdQueue((prev) => [ ...prev, { version: 'v0.9', updateDataModel: { surfaceId: 'form', path: '/ui/loading', value: true } }, ]); // Process with agent, then show result - const result = await callAgent(payload.context); + const result = await callAgent({ email }); setCmdQueue((prev) => [ ...prev, { From a25c693c178efab2fe03342a43447a25c9bfa2e2 Mon Sep 17 00:00:00 2001 From: Mickey <951203214@qq.com> Date: Thu, 30 Apr 2026 00:49:37 +0800 Subject: [PATCH 5/7] feat: test --- CHANGELOG.en-US.md | 21 +++++++++++++++++++++ CHANGELOG.zh-CN.md | 9 +++++++++ 2 files changed, 30 insertions(+) diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index 6e7158b94..962a51485 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -16,6 +16,27 @@ tag: vVERSION --- +## 2.7.0 + +`2026-04-30` + +### @ant-design/x + +- 🆕 `XProvider` adds `zeroRuntime` prop to support Zero Runtime CSS-in-JS mode, extracting styles at build time to avoid runtime style injection and improve performance. [#1737](https://github.com/ant-design/x/pull/1737) by [seanparmelee](https://github.com/seanparmelee) + +### @ant-design/x-card + +- 🆕 Added `resolveActionContextPathRefs` for automatic action context path resolution. Supports both v0.9 and v0.8 formats — when an action is triggered, `{ path }` references in `context` are automatically resolved to actual values from the dataModel and merged with the component's runtime context. [#1887](https://github.com/ant-design/x/pull/1887) by [kimteayon](https://github.com/kimteayon) +- 📖 Added `action-context-resolve` demo documentation for both v0.8 and v0.9 formats. [#1887](https://github.com/ant-design/x/pull/1887) by [kimteayon](https://github.com/kimteayon) + +### @ant-design/x-skill + +- 🛠 Updated `x-card` skill ACTIONS reference documentation with path reference resolution details and corrected React usage examples. [#1887](https://github.com/ant-design/x/pull/1887) by [kimteayon](https://github.com/kimteayon) + +### Others + +- 📖 Added search bar to the official website to improve documentation discoverability. [#1831](https://github.com/ant-design/x/pull/1831) by [1uokun](https://github.com/1uokun) + ## 2.6.0 `2026-04-17` diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index d253ccfe0..ef7c859ed 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -23,6 +23,15 @@ tag: vVERSION - 🆕 XProvider 新增 `zeroRuntime` 属性,支持 Zero Runtime CSS-in-JS 模式,在构建时提取样式,避免运行时样式注入,提升性能。[#1737](https://github.com/ant-design/x/pull/1737) 由 [seanparmelee](https://github.com/seanparmelee) 提交 +### @ant-design/x-card + +- 🆕 新增 Action 上下文路径自动解析能力(`resolveActionContextPathRefs`),支持 v0.9 和 v0.8 两种格式,触发 action 时自动将 `context` 中的 `{ path }` 引用解析为 dataModel 中的实际值,并与组件运行时传入的 context 合并上报。[#1887](https://github.com/ant-design/x/pull/1887) 由 [kimteayon](https://github.com/kimteayon) 提交 +- 📖 新增 v0.8 / v0.9 Action Context 解析示例文档(`action-context-resolve`)。[#1887](https://github.com/ant-design/x/pull/1887) 由 [kimteayon](https://github.com/kimteayon) 提交 + +### @ant-design/x-skill + +- 🛠 更新 `x-card` skill 的 ACTIONS 参考文档,补充 Path 引用自动解析说明及正确的 React 使用示例。[#1887](https://github.com/ant-design/x/pull/1887) 由 [kimteayon](https://github.com/kimteayon) 提交 + ### 其他 - 📖 官网新增搜索栏,提升文档检索体验。[#1831](https://github.com/ant-design/x/pull/1831) 由 [1uokun](https://github.com/1uokun) 提交 From e1b50679511f2f4591d190f36e4c4bf9e1933bc7 Mon Sep 17 00:00:00 2001 From: Mickey <951203214@qq.com> Date: Thu, 30 Apr 2026 00:50:45 +0800 Subject: [PATCH 6/7] chore: changelog --- package.json | 2 +- packages/x-card/package.json | 2 +- packages/x-card/src/version.ts | 2 +- packages/x-markdown/package.json | 2 +- packages/x-sdk/package.json | 2 +- packages/x-skill/.claude-plugin/marketplace.json | 2 +- packages/x-skill/package.json | 2 +- packages/x-skill/skills-zh/use-x-chat/SKILL.md | 2 +- packages/x-skill/skills-zh/x-card/SKILL.md | 2 +- packages/x-skill/skills-zh/x-chat-provider/SKILL.md | 2 +- packages/x-skill/skills-zh/x-components/SKILL.md | 2 +- packages/x-skill/skills-zh/x-markdown/SKILL.md | 2 +- packages/x-skill/skills-zh/x-request/SKILL.md | 2 +- packages/x-skill/skills/use-x-chat/SKILL.md | 2 +- packages/x-skill/skills/x-card/SKILL.md | 2 +- packages/x-skill/skills/x-chat-provider/SKILL.md | 2 +- packages/x-skill/skills/x-components/SKILL.md | 2 +- packages/x-skill/skills/x-markdown/SKILL.md | 2 +- packages/x-skill/skills/x-request/SKILL.md | 2 +- packages/x/package.json | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index 7cda87761..b949e1c04 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "x-mono", - "version": "2.6.0", + "version": "2.7.0", "private": true, "scripts": { "presite": "npm run prestart --workspaces", diff --git a/packages/x-card/package.json b/packages/x-card/package.json index ea7e9d9ba..294a43bb8 100644 --- a/packages/x-card/package.json +++ b/packages/x-card/package.json @@ -1,6 +1,6 @@ { "name": "@ant-design/x-card", - "version": "2.6.0", + "version": "2.7.0", "description": "React card loader for dynamic content loading and management", "keywords": [ "A2UI", diff --git a/packages/x-card/src/version.ts b/packages/x-card/src/version.ts index b28255779..b02cb2c4a 100644 --- a/packages/x-card/src/version.ts +++ b/packages/x-card/src/version.ts @@ -1,2 +1,2 @@ // This file is auto generated by npm run version -export default '2.6.0'; +export default '2.7.0'; diff --git a/packages/x-markdown/package.json b/packages/x-markdown/package.json index 4e431d9e5..fdb2512ba 100644 --- a/packages/x-markdown/package.json +++ b/packages/x-markdown/package.json @@ -1,6 +1,6 @@ { "name": "@ant-design/x-markdown", - "version": "2.6.0", + "version": "2.7.0", "scripts": { "compile": "father build", "tsc": "tsc --noEmit", diff --git a/packages/x-sdk/package.json b/packages/x-sdk/package.json index 15ca214c9..cd0f2b634 100644 --- a/packages/x-sdk/package.json +++ b/packages/x-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@ant-design/x-sdk", - "version": "2.6.0", + "version": "2.7.0", "homepage": "https://x.ant.design/x-sdks/introduce", "bugs": { "url": "https://github.com/ant-design/x/issues" diff --git a/packages/x-skill/.claude-plugin/marketplace.json b/packages/x-skill/.claude-plugin/marketplace.json index b28b1f036..3830d2324 100644 --- a/packages/x-skill/.claude-plugin/marketplace.json +++ b/packages/x-skill/.claude-plugin/marketplace.json @@ -3,7 +3,7 @@ "metadata": { "description": "Ant Design X intelligent agent skills collection", "descriptionZh": "Ant Design X 智能技能库,提供完整的 AI 对话应用开发技能", - "version": "2.6.0", + "version": "2.7.0", "author": "Ant Design X Team", "homepage": "https://github.com/ant-design/x", "repository": { diff --git a/packages/x-skill/package.json b/packages/x-skill/package.json index 671e5b41a..649874536 100644 --- a/packages/x-skill/package.json +++ b/packages/x-skill/package.json @@ -1,6 +1,6 @@ { "name": "@ant-design/x-skill", - "version": "2.6.0", + "version": "2.7.0", "description": "CLI tool for installing AI skills to development tools like Claude, Cursor, etc.", "homepage": "https://x.ant.design/x-skills/introduce", "bugs": { diff --git a/packages/x-skill/skills-zh/use-x-chat/SKILL.md b/packages/x-skill/skills-zh/use-x-chat/SKILL.md index 84f8342a2..a5c9d91d9 100644 --- a/packages/x-skill/skills-zh/use-x-chat/SKILL.md +++ b/packages/x-skill/skills-zh/use-x-chat/SKILL.md @@ -1,6 +1,6 @@ --- name: use-x-chat -version: 2.6.0 +version: 2.7.0 description: 专注讲解如何使用 useXChat Hook,包括自定义 Provider 的集成、消息管理、错误处理、多会话管理等 --- diff --git a/packages/x-skill/skills-zh/x-card/SKILL.md b/packages/x-skill/skills-zh/x-card/SKILL.md index d1a183305..7621a95bb 100644 --- a/packages/x-skill/skills-zh/x-card/SKILL.md +++ b/packages/x-skill/skills-zh/x-card/SKILL.md @@ -1,6 +1,6 @@ --- name: x-card -version: 2.6.0 +version: 2.7.0 description: 当需要用 @ant-design/x-card 让 AI Agent 动态渲染富交互 UI 时使用——涵盖 XCard.Box、XCard.Card、A2UI v0.9 命令、数据绑定、Catalog、Actions 和流式渲染模式。 --- diff --git a/packages/x-skill/skills-zh/x-chat-provider/SKILL.md b/packages/x-skill/skills-zh/x-chat-provider/SKILL.md index 1c1229b7f..4e670c577 100644 --- a/packages/x-skill/skills-zh/x-chat-provider/SKILL.md +++ b/packages/x-skill/skills-zh/x-chat-provider/SKILL.md @@ -1,6 +1,6 @@ --- name: x-chat-provider -version: 2.6.0 +version: 2.7.0 description: 专注于自定义 Chat Provider 的实现,帮助将任意流式接口适配为 Ant Design X 标准格式 --- diff --git a/packages/x-skill/skills-zh/x-components/SKILL.md b/packages/x-skill/skills-zh/x-components/SKILL.md index 576589d32..d016ecbfd 100644 --- a/packages/x-skill/skills-zh/x-components/SKILL.md +++ b/packages/x-skill/skills-zh/x-components/SKILL.md @@ -1,6 +1,6 @@ --- name: x-components -version: 2.6.0 +version: 2.7.0 description: 使用 @ant-design/x 组件库构建 AI 对话 UI 时使用 —— 涵盖 Bubble、Sender、Conversations、Prompts、ThoughtChain、Actions、Welcome、Attachments、Sources、Suggestion、Think、FileCard、CodeHighlighter、Mermaid、Folder、XProvider 和 Notification。 --- diff --git a/packages/x-skill/skills-zh/x-markdown/SKILL.md b/packages/x-skill/skills-zh/x-markdown/SKILL.md index 288d28d67..e148e4e55 100644 --- a/packages/x-skill/skills-zh/x-markdown/SKILL.md +++ b/packages/x-skill/skills-zh/x-markdown/SKILL.md @@ -1,6 +1,6 @@ --- name: x-markdown -version: 2.6.0 +version: 2.7.0 description: 当任务涉及 @ant-design/x-markdown 的 Markdown 渲染、流式输出、自定义组件映射、插件、主题或聊天富内容展示时使用。 --- diff --git a/packages/x-skill/skills-zh/x-request/SKILL.md b/packages/x-skill/skills-zh/x-request/SKILL.md index a5abb4d88..b99b65c9d 100644 --- a/packages/x-skill/skills-zh/x-request/SKILL.md +++ b/packages/x-skill/skills-zh/x-request/SKILL.md @@ -1,6 +1,6 @@ --- name: x-request -version: 2.6.0 +version: 2.7.0 description: 专注讲解 XRequest 的实际配置和使用,基于官方文档提供准确的配置说明 --- diff --git a/packages/x-skill/skills/use-x-chat/SKILL.md b/packages/x-skill/skills/use-x-chat/SKILL.md index 7ae9a0e7b..6f43b33d4 100644 --- a/packages/x-skill/skills/use-x-chat/SKILL.md +++ b/packages/x-skill/skills/use-x-chat/SKILL.md @@ -1,6 +1,6 @@ --- name: use-x-chat -version: 2.6.0 +version: 2.7.0 description: Focus on explaining how to use the useXChat Hook, including custom Provider integration, message management, error handling, multi-conversation management, and more --- diff --git a/packages/x-skill/skills/x-card/SKILL.md b/packages/x-skill/skills/x-card/SKILL.md index 46f5817f2..62f0bb394 100644 --- a/packages/x-skill/skills/x-card/SKILL.md +++ b/packages/x-skill/skills/x-card/SKILL.md @@ -1,6 +1,6 @@ --- name: x-card -version: 2.6.0 +version: 2.7.0 description: Use when building AI-driven UIs with @ant-design/x-card — covers XCard.Box, XCard.Card, A2UI v0.9 commands, data binding, catalogs, actions, and streaming patterns. --- diff --git a/packages/x-skill/skills/x-chat-provider/SKILL.md b/packages/x-skill/skills/x-chat-provider/SKILL.md index c534cbc9b..3d36a118d 100644 --- a/packages/x-skill/skills/x-chat-provider/SKILL.md +++ b/packages/x-skill/skills/x-chat-provider/SKILL.md @@ -1,6 +1,6 @@ --- name: x-chat-provider -version: 2.6.0 +version: 2.7.0 description: Focus on implementing custom Chat Provider, helping to adapt any streaming interface to Ant Design X standard format --- diff --git a/packages/x-skill/skills/x-components/SKILL.md b/packages/x-skill/skills/x-components/SKILL.md index 0449da22a..fb558100f 100644 --- a/packages/x-skill/skills/x-components/SKILL.md +++ b/packages/x-skill/skills/x-components/SKILL.md @@ -1,6 +1,6 @@ --- name: x-components -version: 2.6.0 +version: 2.7.0 description: Use when building AI chat UIs with @ant-design/x components — covers Bubble, Sender, Conversations, Prompts, ThoughtChain, Actions, Welcome, Attachments, Sources, Suggestion, Think, FileCard, CodeHighlighter, Mermaid, Folder, XProvider, and Notification. --- diff --git a/packages/x-skill/skills/x-markdown/SKILL.md b/packages/x-skill/skills/x-markdown/SKILL.md index 55b706f02..981b412ea 100644 --- a/packages/x-skill/skills/x-markdown/SKILL.md +++ b/packages/x-skill/skills/x-markdown/SKILL.md @@ -1,6 +1,6 @@ --- name: x-markdown -version: 2.6.0 +version: 2.7.0 description: Use when building or reviewing Markdown rendering with @ant-design/x-markdown, including streaming Markdown, custom component mapping, plugins, themes, and chat-oriented rich content. --- diff --git a/packages/x-skill/skills/x-request/SKILL.md b/packages/x-skill/skills/x-request/SKILL.md index 349623dfe..69d728548 100644 --- a/packages/x-skill/skills/x-request/SKILL.md +++ b/packages/x-skill/skills/x-request/SKILL.md @@ -1,6 +1,6 @@ --- name: x-request -version: 2.6.0 +version: 2.7.0 description: Focus on explaining the practical configuration and usage of XRequest, providing accurate configuration instructions based on official documentation --- diff --git a/packages/x/package.json b/packages/x/package.json index df19657e4..23f7bf5b3 100644 --- a/packages/x/package.json +++ b/packages/x/package.json @@ -1,6 +1,6 @@ { "name": "@ant-design/x", - "version": "2.6.0", + "version": "2.7.0", "description": "Craft AI-driven interfaces effortlessly", "keywords": [ "AI", From 3c4019e0e779a7a1056c9abe23be6525028cb201 Mon Sep 17 00:00:00 2001 From: Mickey <951203214@qq.com> Date: Thu, 30 Apr 2026 10:07:54 +0800 Subject: [PATCH 7/7] chore: changelog --- .../src/A2UI/__tests__/Card.coverage.test.tsx | 88 +++++++------------ .../skills-zh/x-card/reference/ACTIONS.md | 6 +- .../skills/x-card/reference/ACTIONS.md | 7 +- 3 files changed, 41 insertions(+), 60 deletions(-) diff --git a/packages/x-card/src/A2UI/__tests__/Card.coverage.test.tsx b/packages/x-card/src/A2UI/__tests__/Card.coverage.test.tsx index c68cefc76..bfb2eb9b0 100644 --- a/packages/x-card/src/A2UI/__tests__/Card.coverage.test.tsx +++ b/packages/x-card/src/A2UI/__tests__/Card.coverage.test.tsx @@ -728,9 +728,10 @@ describe('Card.tsx coverage', () => { }); describe('v0.9 action context literal value', () => { - it('should report component runtime context, not config literal values', async () => { - // 验证 v0.9 的行为:上报的 context 来自组件运行时传入,而非配置侧字面量。 - // 配置侧的 { path } 绑定仅用于写回 dataModel,字面量不会被合并到上报 context。 + it('should include config literal values in reported context', async () => { + // 验证 v0.9 的行为:resolveActionContextPathRefs 会将配置侧字面量合并到上报 context 中。 + // 配置侧非 { path } 字面量(如 label: 'static-label')会出现在上报 context 里; + // 组件运行时传入的同名 key 优先级更高,会覆盖配置侧的值。 const onAction = jest.fn(); const ClickableComponent: React.FC<{ @@ -741,7 +742,7 @@ describe('Card.tsx coverage', () => { data-testid="click-btn" onClick={() => componentOnAction?.('click', { - // 只传 value,不传 label,以验证配置侧字面量不会出现在上报 context 中 + // 只传 value,不传 label,让 label 完全来自配置侧字面量 value: 'runtime-value', }) } @@ -765,9 +766,9 @@ describe('Card.tsx coverage', () => { event: { name: 'click', context: { - // 配置侧字面量:不会出现在上报 context 中 + // 配置侧字面量:会被合并到上报 context 中 label: 'static-label', - // 配置侧 path 绑定:用于将组件传入的 value 写回 dataModel + // 配置侧 path 绑定:解析后以 { value } 格式合并 value: { path: '/data/value' }, }, }, @@ -791,16 +792,10 @@ describe('Card.tsx coverage', () => { expect.objectContaining({ name: 'click', surfaceId: 'card1', - // 上报的 context 只包含组件运行时传入的值 context: expect.objectContaining({ + // 组件运行时传入的 value 优先 value: 'runtime-value', - }), - }), - ); - // 配置侧字面量 label 不会出现在上报 context 中 - expect(onAction).toHaveBeenCalledWith( - expect.objectContaining({ - context: expect.not.objectContaining({ + // 配置侧字面量 label 被合并到上报 context 中 label: 'static-label', }), }), @@ -848,10 +843,10 @@ describe('Card.tsx additional branch coverage', () => { describe('resolveActionContextPathRefs v0.9 non-path-object branch (Card.tsx line 390-393)', () => { it('should pass through non-path-object values in v0.9 context', async () => { - // 测试覆盖 Card.tsx 行 394-396: v0.9 context 中值不是 path 对象时直接保留 - // 修复说明:组件运行时不传与配置侧同名的 key(label), - // 只传 value,确保断言真正验证运行时传入的值, - // 并额外断言配置侧字面量 static-label 不会出现在上报 context 中。 + // 测试覆盖 Card.tsx 行 394-396: v0.9 context 中值不是 path 对象时直接保留并合并到上报 context。 + // resolveActionContextPathRefs 会将配置侧字面量(如 label: 'static-label')放入 resolvedFromConfig, + // 再与组件运行时 context 合并(运行时值优先)。 + // 组件运行时只传 value,不传 label,因此 label 完全来自配置侧字面量。 const onAction = jest.fn(); const ClickableComponent: React.FC<{ @@ -863,7 +858,7 @@ describe('Card.tsx additional branch coverage', () => { onClick={() => componentOnAction?.('click', { // 只传 value(对应配置侧 path 绑定),不传 label - // 这样可以验证配置侧字面量 label 不会出现在上报 context 中 + // label 完全来自配置侧字面量,验证字面量被正确合并到上报 context value: 'runtime-value', }) } @@ -896,9 +891,9 @@ describe('Card.tsx additional branch coverage', () => { name: 'click', // context 中包含 path 对象和非 path 对象(字面量) context: { - // 字面量:不会出现在上报 context 中 + // 字面量:会被合并到上报 context 中 label: 'static-label', - // path 绑定:用于将组件传入的 value 写回 dataModel + // path 绑定:解析后以 { value } 格式合并 value: { path: '/data/value' }, }, }, @@ -918,20 +913,14 @@ describe('Card.tsx additional branch coverage', () => { fireEvent.click(screen.getByTestId('click-btn')); await waitFor(() => { - // 上报的 context 只包含组件运行时传入的值 expect(onAction).toHaveBeenCalledWith( expect.objectContaining({ name: 'click', surfaceId: 'card1', context: expect.objectContaining({ + // 组件运行时传入的 value 优先 value: 'runtime-value', - }), - }), - ); - // 配置侧字面量 label 不会出现在上报 context 中 - expect(onAction).toHaveBeenCalledWith( - expect.objectContaining({ - context: expect.not.objectContaining({ + // 配置侧字面量 label 被合并到上报 context 中 label: 'static-label', }), }), @@ -942,10 +931,10 @@ describe('Card.tsx additional branch coverage', () => { describe('resolveActionContextPathRefs v0.8 non-path-object branch (Card.tsx line 409-410)', () => { it('should pass through non-path-object values in v0.8 context', async () => { - // 测试覆盖 Card.tsx 行 411-413: v0.8 context 中值不是 path 对象时直接保留 - // 修复说明:组件运行时不传与配置侧同名的 key(staticKey), - // 只传 dynamicKey(对应配置侧 path 绑定),确保断言真正验证运行时传入的值, - // 并额外断言配置侧字面量 literal-value 不会出现在上报 context 中。 + // 测试覆盖 Card.tsx 行 411-413: v0.8 context 中值不是 path 对象时直接保留并合并到上报 context。 + // resolveActionContextPathRefs 会将配置侧字面量(如 staticKey: 'literal-value')放入 resolvedFromConfig, + // 再与组件运行时 context 合并(运行时值优先)。 + // 组件运行时只传 dynamicKey,不传 staticKey,因此 staticKey 完全来自配置侧字面量。 const onAction = jest.fn(); const ClickableComponent: React.FC<{ @@ -957,7 +946,7 @@ describe('Card.tsx additional branch coverage', () => { onClick={() => componentOnAction?.('click', { // 只传 dynamicKey(对应配置侧 path 绑定),不传 staticKey - // 这样可以验证配置侧字面量 literal-value 不会出现在上报 context 中 + // staticKey 完全来自配置侧字面量,验证字面量被正确合并到上报 context dynamicKey: 'runtime-dynamic', }) } @@ -982,12 +971,12 @@ describe('Card.tsx additional branch coverage', () => { context: [ { key: 'staticKey', - // 非 path 对象,直接是字面值:不会出现在上报 context 中 + // 非 path 对象,直接是字面值:会被合并到上报 context 中 value: 'literal-value', }, { key: 'dynamicKey', - // path 绑定:用于将组件传入的 dynamicKey 写回 dataModel + // path 绑定:解析后以 { value } 格式合并 value: { path: '/data/dynamic' }, }, ], @@ -1015,20 +1004,14 @@ describe('Card.tsx additional branch coverage', () => { fireEvent.click(screen.getByTestId('click-btn-v08')); await waitFor(() => { - // 上报的 context 只包含组件运行时传入的值 expect(onAction).toHaveBeenCalledWith( expect.objectContaining({ name: 'click', surfaceId: 'card1', context: expect.objectContaining({ + // 组件运行时传入的 dynamicKey 优先 dynamicKey: 'runtime-dynamic', - }), - }), - ); - // 配置侧字面量 literal-value 不会出现在上报 context 中 - expect(onAction).toHaveBeenCalledWith( - expect.objectContaining({ - context: expect.not.objectContaining({ + // 配置侧字面量 staticKey 被合并到上报 context 中 staticKey: 'literal-value', }), }), @@ -1171,10 +1154,11 @@ describe('Card.tsx additional branch coverage', () => { }); describe('v0.8 resolveActionContextPathRefs with empty resolvedContext (Card.tsx line 418)', () => { - it('should return original componentContext when v0.8 context has no path objects', async () => { + it('should merge config literal values into reported context when v0.8 context has no path objects', async () => { // 测试 v0.8 格式下 context 数组中只有字面量(无 path 对象)时的行为: - // extractDataUpdatesV08 只处理 { path } 绑定,字面量会被跳过(dataUpdates 为空); - // handleAction 上报时 context 只包含组件运行时传入的值,配置侧字面量不会出现。 + // resolveActionContextPathRefs 会将配置侧字面量(literalKey: 'literal-value')放入 resolvedFromConfig, + // 再与组件运行时 context 合并(运行时值优先)。 + // 因此上报的 context 同时包含运行时传入的值和配置侧字面量。 const onAction = jest.fn(); const ClickableComponent: React.FC<{ @@ -1236,20 +1220,14 @@ describe('Card.tsx additional branch coverage', () => { fireEvent.click(screen.getByTestId('click-v08-empty')); await waitFor(() => { - // 上报的 context 只包含组件运行时传入的值 expect(onAction).toHaveBeenCalledWith( expect.objectContaining({ name: 'click', surfaceId: 'card1', context: expect.objectContaining({ + // 组件运行时传入的值 someValue: 'test', - }), - }), - ); - // 配置侧字面量不会出现在上报 context 中 - expect(onAction).toHaveBeenCalledWith( - expect.objectContaining({ - context: expect.not.objectContaining({ + // 配置侧字面量被合并到上报 context 中 literalKey: 'literal-value', }), }), diff --git a/packages/x-skill/skills-zh/x-card/reference/ACTIONS.md b/packages/x-skill/skills-zh/x-card/reference/ACTIONS.md index 5780dc5d7..3af01e025 100644 --- a/packages/x-skill/skills-zh/x-card/reference/ACTIONS.md +++ b/packages/x-skill/skills-zh/x-card/reference/ACTIONS.md @@ -148,7 +148,8 @@ v0.8 使用数组格式定义路径绑定: ```tsx const handleAction = (payload: ActionPayload) => { if (payload.name === 'submit_form') { - // context 中每个 key 对应配置里的 path 绑定,已解析为 { value, ...rest } 格式 + // 配置中使用 { path } 绑定的 key 会被解析为 { value, ...rest } 格式; + // 配置侧字面量和组件运行时传入的值保持原样。 const email = payload.context.email?.value; const name = payload.context.name?.value; // 1. 调用 Agent API @@ -212,7 +213,8 @@ const formCommands: XAgentCommand_v0_9[] = [ ]; // 2. 处理提交 -// context 中每个 key 对应配置里的 path 绑定,已解析为 { value, ...rest } 格式 +// 配置中使用 { path } 绑定的 key 会被解析为 { value, ...rest } 格式; +// 配置侧字面量和组件运行时传入的值保持原样。 const handleAction = async (payload: ActionPayload) => { if (payload.name === 'submit') { const email = payload.context.email?.value; diff --git a/packages/x-skill/skills/x-card/reference/ACTIONS.md b/packages/x-skill/skills/x-card/reference/ACTIONS.md index e7639ec55..7182af1f9 100644 --- a/packages/x-skill/skills/x-card/reference/ACTIONS.md +++ b/packages/x-skill/skills/x-card/reference/ACTIONS.md @@ -148,8 +148,8 @@ When the user clicks the button, `onAction` receives: ```tsx const handleAction = (payload: ActionPayload) => { if (payload.name === 'submit_form') { - // Each key in context corresponds to a path binding in the config, - // resolved to { value, ...rest } format + // Keys using { path } bindings in the config are resolved to { value, ...rest } format. + // Literal values from the config and runtime values from the component are preserved as-is. const email = payload.context.email?.value; const name = payload.context.name?.value; // 1. Call your agent API @@ -221,7 +221,8 @@ const formCommands: XAgentCommand_v0_9[] = [ ]; // 2. Handle submission -// Each key in context is resolved to { value, ...rest } format +// Keys using { path } bindings in the config are resolved to { value, ...rest } format. +// Literal values from the config and runtime values from the component are preserved as-is. const handleAction = async (payload: ActionPayload) => { if (payload.name === 'submit') { const email = payload.context.email?.value;