
Chat Cards为 GitHub Copilot Canvas 构建交互式卡片牌组的扩展实战指南【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilotChat Cards 是 awesome-copilot 仓库中一个面向 GitHub Copilot Canvas 的扩展extensions/chat-cards/README.md它让 Agent 不再输出大段文字而是通过一系列动作指令动态生成「活的」交互卡片牌组——标签页、表格、SVG 图表、表单、折叠区块、编号大纲、渲染后的 Markdown 文档与短视频片段。表单是双向的用户提交表单后字段值会作为 Agent 的下一轮提示词回传到会话卡片既可以呈现信息也能收集上下文并引导对话走向。读完本文你将掌握该扩展的完整动作清单与输入参数、安装方式、从 MCP 服务移植到 Canvas 扩展的架构差异以及底层渲染与安全实现的源码细节。为什么用卡片而不是文本Copilot 会话中「一堵文本墙」往往难以快速消化尤其是涉及教学、研究、方案对比等需要结构化呈现的场景。Chat Cards 把同一主题拆成一组视觉化、可交互的卡片每个卡片是一块独立的信息单元用户可以在牌组中展开、折叠、拖动排序从而按自己的节奏吸收内容。扩展内置的预览图extensions/chat-cards/assets/preview.png展示了两张典型的标签页卡片标题为What Is Rust?的卡片以多个标签页呈现概述、关键统计与 Hello World 代码Ownership, Borrowing Lifetimes卡片则用代码块加标签页解释概念右上角带有「Copy card」「/」等操作按钮。从设计定位上看该扩展适合研究、教育、专业技能与业余爱好等各类主题——凡是「卡片比文字表达得更好」的内容都适用。值得注意的是卡片只在 Canvas 画布中渲染因此扩展在动作返回摘要中会同时要求 Agent 在会话里陈述每张卡片的关键结论以便不支持 Canvas 的表面也能获得核心信息见 extension.mjs 中createCardAction的返回内容。牌组里有哪些卡片扩展通过 Canvas 动作暴露了 11 个操作。下表是完整清单摘自 extensions/chat-cards/README.md动作卡片create_tab_card同一主题的标签页视图每页可为 markdown、文本、HTML 或带复制按钮的代码create_table_card由显式行或松散分隔的原始文本生成的 HTML 表格分隔符自动检测URL 单元格变为链接create_chart_card带图例和可折叠数据表的 SVG 柱状、折线、饼图或环形图create_form_card提交内容成为下一轮会话提示词的表单create_reveal_card带「全部展开/全部收起」控制的折叠显示/隐藏区块create_list_card编号为 1.、1.1.、1.1.1. 的嵌套顺序大纲create_markdown_card将 Markdown 文档渲染为一张卡片H1 成为标题H2 小节折叠为 reveal 区块create_video_card播放短视频片段的 HTML 视频播放器直接文件 URL、data:video/*或blob:update_card就地重新渲染一张已有卡片remove_card/clear_cards将卡片从牌组中移除list_cards查看牌组用户可能已经重排或移除了卡片get_form_responses读取表单提交结果最新的在前在源码层这 12 项动作分别注册在 Canvas 的actions数组中8 个create_*动作由makeCreateAction工厂统一生成update_card、remove_card、clear_cards、list_cards、get_form_responses为单独定义全部挂载在createCanvas({ id: chat-cards, ... })上见 extension.mjs 的actions定义。每个动作都带有严格的inputSchema为 Agent 提供了精确的参数约束这也是扩展能与模型顺畅配合的关键。每张卡片保留的通用交互所有卡片都保留了 MCP 版本的招牌交互extensions/chat-cards/README.mdCopy card把卡片作为独立 HTML 文档复制/切换显示卡片自身的 HTML 源码折叠开关展开/收起卡片拖拽重排在牌组中拖动改变卡片顺序tutor terms术语工具提示悬停片刻后显示术语提示见下方「教学术语」模型定义的右键动作右键菜单动作会把提示词发回会话动作提示中的{{selection}}会被替换为用户选中的文本明暗双主题牌组支持浅色与深色主题SVG 图表通过引用主题 CSS 变量自动跟随cards-core.mjs 中图表颜色使用var(--mcc-border)、var(--mcc-text)等。教学术语tutor termstutorTerms是各卡片的公共参数之一它是{ term, tip }对象数组其中term是卡片文本中的精确术语tip是悬停时显示的简短纯文本定义见 extension.mjs 中TUTOR_TERMS_SCHEMA。实现上wrapTermsInHtml会把可见文本中的术语包成带data-tip属性的.mcc-term标签默认每个术语最多标记 1 次、整卡最多 40 次术语按长度降序匹配以保证「memory safety」优先于「memory」script、style、title等非可见散文区域以及默认的代码块会被跳过tutorTermsInCode可开启代码内标记见 cards-core.mjs 中wrapTermsInHtml的实现。示例动作输入create_table_card{ title: JavaScript array methods, headers: [Method, Purpose], rows: [ [map, Transform each item], [filter, Keep matching items], [reduce, Fold items into one value] ] }表格卡片还支持不显式给出行数据传入text原始文本后扩展会从\t、|、;、,候选分隔符中自动检测出现于大多数非空行阈值约为行数的 60%的分隔符并通过balanceHeaders把表头补齐/截断到与列数一致见 cards-core.mjs 中detectCellDelimiter与textToTable。此外可通过linkColumns从 0 开始的列索引数组指定哪些列渲染为链接autoLinkUrls默认 true控制 URL 形状的单元格是否自动成为链接。create_form_card{ title: Study preferences, promptTemplate: Teach {{topic}} with {{style}} examples., fields: [ { name: topic, label: Topic, required: true }, { name: style, type: select, options: [practical, theoretical] } ] }表单字段支持text、textarea、select、checkbox、radio、number、email、url、date、hidden十种类型见FORM_CARD_PROPERTIES的type枚举options可以是字符串数组或{ label, value }对象数组。当用户提交表单时填好的模板promptTemplate中的{{fieldName}}令牌被替换为字段值会作为下一轮提示词交给 Agent如果交接失败卡片会显示提示文本并附复制按钮而 Agent 仍可随时通过get_form_responses读取提交记录extensions/chat-cards/README.md。在底层/api/submit端点会调用session.send({ prompt })把提示词交给会话同时把提交记录含 id、cardId、cardTitle、values、prompt、是否投递成功与接收时间压入submissions列表列表上限为 50 条超出则丢弃最旧的见 extension.mjs 中MAX_SUBMISSIONS常量与/api/submit处理逻辑。安装与运行环境要求Node.js 18.17 或更新版本以及支持 canvas 扩展的 GitHub Copilot 客户端例如 GitHub Copilot CLIextensions/chat-cards/README.md。安装分两种作用域# 用户作用域放入 ~/.copilot/extensions/chat-cards/ cd ~/.copilot/extensions/chat-cards # 或项目作用域在仓库根目录放入 .github/extensions/chat-cards/ cd .github/extensions/chat-cards npm installnpm install只拉取扩展的唯一运行时依赖github/copilot-sdk见 package.json。随后把extension/文件夹作为本地扩展注册到你的 Copilot 客户端启动一个会话让 Agent 打开 Chat Cards 画布在 GitHub Copilot 应用中重载扩展然后在对话中打开 chat-cards 画布即可。该扩展同时也以插件形式发布可通过copilot plugin install chat-cardsawesome-copilot一键安装见 plugins/chat-cards/README.md。目录结构extension/ extension.mjs Canvas/session 接线、动作、本地 HTTP SSE 服务器 cards-core.mjs 卡片构建与渲染不依赖 SDK可单独单元测试 copilot-extension.json 面向 awesome-copilot 提交的插件清单 package.json 扩展包清单 assets/ canvas.html 画布页面主题、卡片运行时、牌组 UI preview.png 用作扩展 logo/预览的截图从 MCP 服务移植到 Canvas 扩展架构映射Chat Cards 是某个 MCP 服务端口的移植版——两者相似但该扩展把卡片直接渲染在会话对话流中而不是把 HTML 渲染在独立面板中。移植映射关系如下extensions/chat-cards/README.mdMCP 服务器Canvas 扩展MCP 工具create_tab_card、……同名、同输入形状的 Canvas 动作MCP Apps iframe / 内嵌 HTML 资源运行在127.0.0.1上的实时画布页面表单提交向宿主 POSTui/message表单提交调用session.send({ prompt })每个工具结果返回卡片 HTML通过 SSE 把牌组状态推送到页面src/cards/*src/util/*TypeScriptcards-core.mjs无依赖移植版无需 SDK 即可测试从源码结构看extension.mjs 负责全部宿主接线它从github/copilot-sdk/extension导入joinSession与createCanvas在open()时启动一个绑定127.0.0.1的本地 HTTP 服务器并返回带 token 的画布 URL在onClose()时停止服务器与 SSE 连接——没有面板打开时进程不持有任何 socket。而 cards-core.mjs 是纯字符串逻辑的渲染核心不感知 Copilot SDK 或页面服务器因此可以在不加入会话的情况下直接用 Node 运行测试。有意的差异更严格的 HTML 净化。标签页与 reveal 内容可以像 MCP 服务器一样是 markdown、文本、代码或 HTML但 MCP 服务器依赖解析器依赖做净化扩展则是基于严格的标签/属性白名单做「重建式」净化未知或畸形标签渲染为可见的纯文本属性从零开始重新输出闭合标签按栈平衡。没有任何可用内容的标签页或区块会直接报错并点名该部分而不是渲染空面板。白名单标签覆盖a、div、table、details、img、pre、code等常用 HTML 标签属性白名单如a的href必须为 http/https 链接、img的src必须是可显示图片 URL、class不允许以mcc-开头逐项校验见 cards-core.mjs 中SAFE_HTML_TAGS、SAFE_ATTR_RULES与sanitizeHtml。没有文件、归档或网络抓取类动作。read_local_file、unpack_archive、fetch_reference、mirror_web_form、submit_web_form仅保留在 MCP 版本Copilot Agent 本身就能原生读取文件与网页所以它会把内容内联传入例如create_markdown_card接收 Markdown 内容本身而非文件路径。没有多部分拆分。MCP 宿主会限制工具结果大小因此服务器会把大文档拆成多个部分Canvas 直接渲染、无需拆分牌组最多保留 60 张卡片超出时丢弃最旧的见 extension.mjs 中MAX_CARDS 60与createCardAction中的裁剪逻辑裁剪时还会向会话广播一条说明哪张卡片被移除的备注。卡片渲染核心cards-core.mjs 深入cards-core.mjs是本扩展的灵魂模块约 1500 行全部是纯字符串逻辑具备可独立测试性。它导出的CARD_BUILDERS把 8 种卡片类型映射到各自的构建函数buildTabCard、buildTableCard、buildChartCard、buildFormCard、buildRevealCard、buildListCard、buildMarkdownCard、buildVideoCardbuildCard(kind, options)负责按类型分发并抛出「Unknown card kind」错误见 cards-core.mjs 末尾CARD_BUILDERS与buildCard。几个值得展开的实现细节HTML 转义所有文本字段被视为纯文本并统一转义。escapeHtml的特殊之处在于对于已构成合法字符引用的如amp;保持原样避免调用者预转义后出现amp;amp;双重转义但、、、无条件转义因此预转义文本不可能重新打开标签或属性见ESCAPE_PATTERN与escapeHtml。文本转表格textToTable支持cellDelimiter显式指定也支持自动检测无分隔符时按columns默认取表头数或 2把每行切成定宽格子。Markdown 风格的| a | b |行会丢弃空边缘单元格。Markdown 渲染器为保持零依赖扩展自带一个小型渲染器覆盖模型写指南实际会用到的语法——标题、段落、嵌套列表缩进两个以上空格开启子列表、围栏代码带复制按钮与language-*类、管道表格、引用块、分隔线与内联元素行内代码、粗体、斜体、链接、图片。所有文本节点都经过escapeHtml输出不可能携带活动内容见 cards-core.mjs 中renderMarkdownFragment与renderInline。图片仅当源为 http(s) 或data:image/时才渲染为img。Markdown 文档卡片parseMarkdownDocument把第一个 H1 作为卡片标题未显式传title时正文按 H2 切成多个小节renderMarkdownSections默认把 H2 小节折叠进details区块并附「Show all / Hide all」控制splitSections与openFirst参数可分别关闭折叠与首节默认展开见 extension.mjs 中MARKDOWN_CARD_PROPERTIES。SVG 图表柱状、折线、饼图、环形图全部动态生成 SVG。坐标轴刻度由niceScale计算它会挑选「最小可读步长」而非固定等分整数数据强制整数刻度1–5 评分制会显示 0、1、2、3、4、5刻度格式化只保留步长所需的小数位0.25 显示为 0.25整数不显示 .0。X 轴标签通过wrapLabel按单词折行且不拆分单词超出行数时截断加省略号完整文本始终可通过 SVGtitle访问见 cards-core.mjs 中niceScale、wrapLabel、barChartSvg、lineChartSvg、pieChartSvg。视频与媒体校验isPlayableMediaUrl只接受 http(s) 视频/音频 URL、data:video/*或data:audio/*URI 与blob:URL——不接受流媒体平台页面 URLisDisplayableImageUrl用于图片与视频 poster 的校验。安全设计扩展的安全设计在多处做了防御extensions/chat-cards/README.md 的 Security notes卡片服务器绑定127.0.0.1的临时端口实际实现中从 21750 起始的 40 个固定端口槽位中随机选择全部占满才回退到系统临时端口每个请求必须携带 per-canvas 令牌请求体大小上限为 1 MBMAX_BODY_BYTES。所有模型与用户提供的文本在进入卡片标记前都经过 HTML 转义Markdown 渲染器只输出转义后的文本节点。画布页面不加载任何外部脚本、样式表或字体。从画布发出的提示词表单提交与上下文动作有长度上限MAX_PROMPT_CHARS 16000。令牌刻意不持久化每次运行都会生成新令牌open()向页面提供全新 URL从而避免孤儿页面通过复用的端口继续读写旧牌组见 extension.mjs 中handleCanvasRequest的令牌校验与startCanvasServer的端口分配逻辑。牌组持久化与进程生命周期从源码可以推断扩展在进程级做了细致的生命周期管理extension.mjs按实例持久化牌组以「每实例一个 JSON 文件」的形式写入用户状态目录Windows 为%LOCALAPPDATA%\chat-cardsmacOS 为~/Library/Application Support/chat-cardsLinux 为$XDG_STATE_HOME/chat-cards而不是单一共享文档——这样多个并行会话的扩展进程互不覆盖。每个文件记录持有该牌组的进程hostname pid持久化目录最多保留 8 个牌组按 mtime 淘汰时只删除没有运行中进程持有的文件。状态迁移旧版单一文档布局state.json会在启动时一次性迁移到按牌组文件布局并删除旧文件。进程不存活于宿主之外扩展通过stdin的 end/close、disconnect、常见信号与session.shutdown事件统一走shutdown()先释放牌组再退出页面服务器、socket 与持久化定时器全部unref()保证唯一让进程存活的只有与宿主的 stdio 管道。牌组在exit事件上也会兜底写出。开发与测试渲染核心不依赖 SDK可以直接运行验证例如node -e import(./cards-core.mjs).then(m console.log(m.buildTableCard({ title: Demo, rows: [[a, b]] }).summary))运行扩展本身则按上文「安装与运行」执行即可。由于cards-core.mjs是纯字符串函数库你可以在不启动会话的情况下单测escapeHtml、sanitizeHtml、textToTable、niceScale、wrapTermsInHtml等导出函数快速验证卡片渲染、净化与图表刻度行为。小结Chat Cards 把「讲解」从线性文本升级为可交互、可重排、可回流的视觉牌组而它的实现又刻意保持了克制唯一运行时依赖是 Copilot SDK渲染核心零依赖、可独立测试安全上以白名单净化、HTML 转义、令牌鉴权与长度上限层层设防生命周期上则保证进程不拖累宿主、牌组在应用重启后仍然可恢复。对于希望在 GitHub Copilot 中做教学、研究、方案对比等视觉化讲解的开发者这是一份可直接落地、结构清晰、便于二次扩展的参考实现。【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考