
人工智能AI 应用前端MCP 服务【免费下载链接】json-renderThe Generative UI framework项目地址https://gitcode.com/GitHub_Trending/js/json-render点击查看免费下载json-render/ink是 json-render 的终端Terminal渲染器它把一份 JSON Spec 转换成基于 Ink 的交互式终端组件树支持标准组件、数据绑定、可见性控制、事件与动作系统、动态列表以及 JSONL 流式渲染。本指南以 skills/ink/SKILL.md 为核心脉络结合 packages/ink 的真实源码与 examples/ink-chat 示例完整讲解从 Catalog 定义、Spec 编写、渲染接入到流式生成、状态管理与高阶 API 的端到端实战读完即可在命令行应用中渲染出AI 生成 人工交互的终端 UI。环境与安装json-render/ink以ink ^6.0.0与react ^19.0.0为 peerDependencies见 packages/ink/package.json运行时依赖json-render/core与marked。安装命令npm install json-render/ink json-render/core ink react包提供了 4 个可独立导入的子路径导出见 packages/ink/package.json入口用途json-render/ink组件实现、渲染器、Hooks、Providers 等运行时能力json-render/ink/schemaschema、InkSchema、InkSpec类型json-render/ink/catalogstandardComponentDefinitions、standardActionDefinitions标准目录定义json-render/ink/server服务端安全入口仅重新导出 schema 与 catalog使用import type引入 React 类型运行时无 React 依赖可用于生成 AI system prompt其中schema、catalog、server三个子路径的拆分正是为了区分AI 生成 Spec 的形状、开发者提供的组件/动作定义与服务端 Prompt 生成三种职责从 packages/ink/src/server.ts 可以看到./server只包含 schema 与 catalog 定义不含任何渲染逻辑。快速开始Catalog、Registry 与 Renderer三段式架构是理解json-render/ink的关键Schema定义 SpecAI 生成的 JSON的形状与 Catalog开发者提供的定义的形状见 packages/ink/src/schema.tsCatalog用defineCatalog(schema, ...)声明组件与动作的 props 校验Zod、插槽、描述与示例Registry Renderer注册组件实现并渲染 Spec。import { defineCatalog } from json-render/core; import { schema } from json-render/ink/schema; import { standardComponentDefinitions, standardActionDefinitions, } from json-render/ink/catalog; import { defineRegistry, Renderer, type Components } from json-render/ink; import { z } from zod; // 1. 创建 Catalog标准组件 自定义组件 const catalog defineCatalog(schema, { components: { ...standardComponentDefinitions, CustomWidget: { props: z.object({ title: z.string() }), slots: [], description: Custom widget, }, }, actions: standardActionDefinitions, }); // 2. 注册组件实现标准组件内置只需注册自定义部分 const { registry } defineRegistry(catalog, { components: { CustomWidget: ({ props }) Text{props.title}/Text, } as Componentstypeof catalog, }); // 3. 渲染 function App({ spec }) { return ( JSONUIProvider initialState{{}} Renderer spec{spec} registry{registry} / /JSONUIProvider ); }最简化的真实写法可以参考 examples/ink-chat/src/catalog.ts直接展开standardComponentDefinitions与standardActionDefinitions即可得到一个可用的完整 Catalog。若不想手写 Provider可直接使用 packages/ink/README.md 中基于createRenderer的写法import { render } from ink; import { createRenderer, standardComponents } from json-render/ink; import { catalog } from ./catalog; const InkRenderer createRenderer(catalog, standardComponents); const spec { root: heading, elements: { heading: { type: Heading, props: { text: Hello from the terminal!, level: h1 }, children: [], }, }, }; render(InkRenderer spec{spec} state{{}} /);Spec 结构扁平元素映射Flat Element MapInk 的 schema 采用扁平元素映射 root 键的形式elements是一个以元素 key 为键的 Recordroot指向入口元素。每个元素由type、props、children子元素 key 数组构成并可选携带visible与repeat字段这一定义可以在 packages/ink/src/schema.ts 中看到{ root: main, elements: { main: { type: Box, props: { flexDirection: column, padding: 1 }, children: [heading, content] }, heading: { type: Heading, props: { text: Dashboard, level: h1 }, children: [] }, content: { type: Text, props: { text: Hello from the terminal! }, children: [] } } }父子关系完全通过children数组中的 key 引用建立Spec 本身不含嵌套对象。渲染时Renderer从spec.root取入口元素逐层递归解析 children见 packages/ink/src/renderer.tsx若某个 children key 找不到对应元素会在控制台输出Missing element警告渲染阶段该分支不可见加载中静默、非加载态打印占位符。此外 packages/ink/src/hooks.ts 提供了flatToTree可将{ key, parentKey, props, visible }形式的扁平元素列表转换成{ root, elements }的 Spec 格式并自动处理根元素冲突与孤儿节点告警。值得留意的是schema 中还内置了builtInActionssetState/pushState/removeState与一批defaultRules——这是直接写给 AI 的生成约束例如每个元素必须包含 children 数组visible 与 on 字段必须位于元素对象上而非 props 内当用户要求展示数据时务必在 spec 顶层附带 state 示例数据等见 packages/ink/src/schema.ts。这些规则决定了 AI 生成 Spec 的质量也解释了为什么字段放错位置是终端渲染器最常见的一类生成错误。标准组件库standardComponentDefinitions在 packages/ink/src/catalog.ts 中为每个组件定义了基于 Zod 的 props 校验、事件声明events数组、给 AI 的描述与example示例对应的实现集中在 packages/ink/src/components/standard.tsx。Layout布局组件说明BoxFlexbox 布局容器终端里的div用于分组、间距、边框、对齐默认flexDirection: rowText文本输出支持 color、bold、italic、underline、strikethrough、dimColor、inverse、wrap 等样式Newline插入一个或多个空行必须放在flexDirection: column的 Box 内Spacer沿主轴扩展的弹性空白用于把元素推离Box的 props 覆盖了 Ink 的完整 flex 能力flexDirectionrow/column 及 reverse、alignItems、justifyContent含 space-between/around/evenly、flexGrow、flexShrink、flexWrap、尺寸width/height/minWidth/minHeight、全套 padding/margin含 X/Y/T/B 细分、gap/columnGap/rowGap、borderStylesingle/double/round/bold/singleDouble/doubleSingle/classic、边框控制与backgroundColor。实现上BoxComponent会经过safeBoxProps过滤剥离null值、拦截key/ref/children/dangerouslySetInnerHTML/style/className/id等危险或 Web 专用 props并丢弃在深色终端上不可见的black/#000颜色见 packages/ink/src/components/standard.tsx。Content内容展示组件说明Heading标题h1加粗下划线h2加粗h3加粗暗色h4暗色Divider水平分隔线可带居中标题默认宽度 40 字符Badge彩色行内标签variantdefault/info/success/warning/error分别映射 white/blue/green/yellow/red 底色Spinner动画加载指示器使用盲文动画字符⠋⠙⠹...每 80ms 切换一帧ProgressBar水平进度条progress 取 0–1默认宽度 30 字符自动换算百分比Sparkline基于 Unicode 块字符▁▂▃▄▅▆▇█的行内趋势图支持 min/max 固定刻度、width 降采样BarChart水平条形图每项含 label/value/color可开 showValues 与 showPercentageTable表格columns 定义 header/key/width/alignrows 为 key→字符串的映射列宽未指定时按内容自适应超宽截断加省略号List项目符号或编号列表ListItem结构化列表行title、subtitle、leading、trailing适合配合 repeat 渲染动态列表Card带可选标题的着色容器默认背景#1a1a1a、padding 1KeyValue键值对展示value 支持字符串/数字/数组默认分隔符为冒号Link可点击 URL终端自动识别有 label 时显示label (url)StatusLine带彩色图标的状态行infoℹ、success✔、warning⚠、error✖Markdown用终端样式渲染 Markdown标题、粗斜体、行内代码、代码块、列表、引用、分隔线底层使用marked解析Metric/Callout/Timeline关键指标大数字趋势箭头、高亮提示块info/tip/warning/important 彩色左边框、时间线completed/current/upcoming 三态圆点这三者同样由标准 Catalog 提供并在标准组件中实现Interactive交互组件组件事件交互方式TextInputsubmit、change文本输入方向键移动光标mask设为*即密码输入Selectchange方向键导航、回车确认的单选菜单MultiSelectchange、submit方向键导航、空格切换、回车确认的多选菜单支持 min/max 限制选择数量ConfirmInputconfirm、denyY/N 确认提示用于破坏性操作前Tabschange左右方向键切换的标签栏value 绑定当前活动标签这些交互组件的实现展示了受控组件 双向绑定的典型范式以TextInputComponent为例它调用useBoundProp把绑定路径写回 state见 packages/ink/src/components/standard.tsx并借助useFocus()只在获得焦点时响应useInput光标位置按码点而非 UTF-16 单元计算以正确处理 emoji 等代理对字符。可见性条件Visibility在元素对象上使用visible字段按状态控制显隐注意visible必须放在元素对象上不能放进props。支持的表达式语法{ $state: /path } // 路径有值即显示 { $state: /path, eq: value } // 等于 value 时显示 { $state: /path, not: true } // 取反 { $and: [cond1, cond2] } // 与 { $or: [cond1, cond2] } // 或渲染时ElementRenderer通过evaluateVisibility(element.visible, fullCtx)求值为 false 直接返回null见 packages/ink/src/renderer.tsx。典型场景是与Tabs配合把活动标签绑定到 state子内容用visible条件实现多视图切换这也是 schemadefaultRules中明确推荐的终端多视图模式。动态属性表达式Dynamic Props任何 prop 的值都可以是渲染时求值的数据驱动表达式由resolveElementProps/resolveBindings统一解析{ $state: /state/key }—— 从状态模型读取单向{ $bindState: /path }—— 双向绑定用于表单组件的天然 value prop上{ $bindItem: field }—— 与 repeat 当前项字段双向绑定{ $cond: condition, $then: value, $else: value }—— 条件取值{ $template: Hello, ${/name}! }—— 把状态值插值进字符串。需要强调组件不使用statePathprop 做双向绑定统一用{ $bindState: /path }写在 value 类 prop 上。在实现侧ElementRenderer先解析绑定得到bindingsprop 名 → 绝对 state 路径再解析 props 值组件内通过useBoundProp(value, bindings?.value)拿到[value, setValue]setValue写回绑定路径见 packages/ink/src/hooks.ts。事件系统与内置 Actions组件通过emit抛出命名事件Spec 元素上的on字段把事件映射为动作绑定。实现emit时渲染器会把on[eventName]解析为可能多个的ActionBinding 数组逐条解析参数中的动态表达式后交给execute执行见 packages/ink/src/renderer.tsx。CustomButton: ({ props, emit }) ( Box Text{props.label}/Text {/* emit(press) 触发 Spec 中 on.press 绑定的动作 */} /Box ),{ type: CustomButton, props: { label: Submit }, on: { press: { action: submit } }, children: [] }setState、pushState、removeState三个内置动作自动处理定义见 packages/ink/src/catalog.ts{ action: setState, params: { statePath: /activeTab, value: home } } { action: pushState, params: { statePath: /items, value: { text: New } } } { action: removeState, params: { statePath: /items, index: 0 } }标准动作还包含exit退出终端程序可选退出码与log把消息写到 Ink 渲染之外的 stdout适合输出需要在 UI 更新后仍保留的持久日志。从 packages/core/src/actions.ts 可以看到 ActionBinding 的完整结构除action与params外还支持confirm执行前弹出确认对话框、onSuccess/onError成功/失败后置处理器可 navigate、set 或继续触发动作与preventDefault。其中pushState的 value 支持{ $state: /path }引用与$id自动生成 ID并可用clearStatePath在推送后重置另一个路径。Repeat动态列表在容器元素上用repeat字段从状态数组渲染列表{ type: Box, props: { flexDirection: column }, repeat: { statePath: /items, key: id }, children: [item-row] }重复子元素内部用{ $item: field }读取当前项字段用{ $index: true }获取当前下标。嵌套列表时内层 repeat 可用{ statePath: { $item: children } }遍历外层项的数组字段。实现上RepeatChildren通过useStateStore()读取状态、getByPath取数组为每一项创建RepeatScopeProvider提供 item/index/basePath再用repeat.key作为 React key对象缺 key 时回退到 index见 packages/ink/src/renderer.tsx。$item形式的 statePath 只有在 repeat 作用域内才合法否则会输出$item in repeat.statePath used outside of a repeat scope警告并渲染为空。StreamingJSONL 补丁流式渲染useUIStream从 API 端点流式读取 JSONL 补丁并逐步渲染 Specimport { useUIStream } from json-render/ink; const { spec, send, isStreaming } useUIStream({ api: /api/generate });它是整套终端 AI 场景的核心 Hook实现位于 packages/ink/src/hooks.ts关键机制包括容错解析parsePatchLine跳过空行、注释与 LLM 常见的口语化文本对看起来像 JSON 但解析失败的行会尝试逐个剥离末尾多余的花括号/方括号做恢复最多 8 次这类行错误在 LLM 嵌套 JSON 输出中非常普遍见 packages/ink/src/hooks.ts增量应用每个补丁行经applySpecPatch应用到深拷贝的 Spec 上再setSpec避免 React 拿到被原地修改的旧对象校验与自修复validate开启后流中遇到无法恢复的畸形 JSON 立即中止并构造 repair prompt 继续生成流结束后执行结构校验缺失 children、visible 误放 props 等可本地自动修复的问题用autoFixSpec处理剩余错误触发修复重试maxRetries默认 5流中与流后重试合并计数并发控制requestIdRef保证只有最新一次请求能更新isStreamingAbortController支持stop()与组件卸载时自动中止。返回值为{ spec, isStreaming, error, send, stop, clear }。示例用法const { spec, isStreaming, send } useUIStream({ api: /api/generate-ui, onComplete: (spec) console.log(Done!, spec), }); await send(Create a dashboard with stats); // Renderer spec{spec} loading{isStreaming} /服务端 Prompt 生成Catalog 自带prompt()方法可基于组件/动作定义与 Zod props 自动生成 AI 生成 UI 所需的 system promptimport { catalog } from ./catalog; const systemPrompt catalog.prompt({ system: You are a terminal assistant. });该能力来自json-render/core的 Catalog 抽象json-render/ink/server子路径为此在服务端安全暴露 schema 与 catalog无 React 运行时依赖。注意 server 入口只导出 schema/catalog 及配套类型因此 prompt 生成可以在 Node 服务端独立完成渲染则完全发生在客户端。Providers 与外部状态json-render/ink以一组 Context Provider 组合出完整的终端 UI 运行时Provider职责StateProvider跨组件共享状态JSON Pointer 路径可选storeprop 进入受控模式ActionProvider处理经事件系统派发的动作内置确认对话框管理VisibilityProvider基于状态的条件渲染ValidationProvider表单字段校验useOptionalValidation为不抛异常的变体FocusProvider管理交互组件的焦点JSONUIProvider上述全部上下文的组合 ProviderJSONUIProvider的实际嵌套顺序从 packages/ink/src/renderer.tsx 可以看到StateProvider → VisibilityProvider → ValidationProvider → ActionProvider → FocusProvider并在内部挂载确认对话框管理器。外部 Store受控模式把StateStore传给StateProvider或JSONUIProvider即可使用外部状态管理import { createStateStore, type StateStore } from json-render/ink; const store createStateStore({ count: 0 }); StateProvider store{store}{children}/StateProvider store.set(/count, 1); // React 自动重新渲染createStateStore与StateStore接口均由json-render/core提供并在 packages/ink/src/index.ts 中重新导出一旦传入storeinitialState与onStateChange会被忽略。createRenderer更高阶的接入 APIcreateRenderer(catalog, components)返回一个自带全部 Provider 的渲染组件是快速接入的首选import { createRenderer } from json-render/ink; import { standardComponents } from json-render/ink; import { catalog } from ./catalog; const InkRenderer createRenderer(catalog, { ...standardComponents, // 此处可覆盖自定义组件 }); // InkRenderer 已内置 state、visibility、actions、focus 等 Provider render( InkRenderer spec{spec} state{{ activeTab: overview }} / );其实现packages/ink/src/renderer.tsx把onAction回调包装成Proxy型 handlers任意动作名都会路由到该回调并用JSONUIProvider Renderer组合返回组件props 支持spec、store受控、state非受控初始状态、onAction、onStateChange、loading与fallback。底层Renderer则更灵活registry传入的自定义组件会与标准组件合并同名覆盖includeStandard可关闭内置组件fallback处理未知组件类型。Key Exports 速查Export用途defineRegistry从 Catalog 创建类型安全的组件注册表同时产出 handlers 与 executeActionRenderer用注册表渲染 Spec 的低层组件createRenderer高阶 API创建自带 Provider 的渲染组件JSONUIProvider全部上下文的组合 ProviderschemaInk 扁平元素映射 schema含内置状态动作standardComponentDefinitions全部标准组件的 Catalog 定义standardActionDefinitions标准动作的 Catalog 定义standardComponents预构建的标准组件实现useStateStore访问状态上下文useStateValue从状态取单个值useBoundProp$bindState/$bindItem表达式的双向绑定useActions/useAction访问动作上下文 / 取单个动作派发函数useOptionalValidationuseValidation的不抛异常变体useUIStream从 API 端点流式渲染 SpeccreateStateStore创建框架无关的内存StateStoreStateStore外部状态管理接入接口Components/Actions/ComponentContextCatalog 感知的类型化映射flatToTree把扁平元素列表转换为树形 Spec完整的导出清单可对照 packages/ink/src/index.ts。终端 UI 设计规范在有限宽度下设计终端 UI 时SKILL 与 schemadefaultRules给出了统一建议也对应标准组件的默认实现用Box布局flexDirection、padding、gap默认主轴为 row终端宽度约 80–120 列主体结构优先flexDirection: column行内元素badge、键值对、表格行用 row用borderStyle做视觉分组single/double/round/boldpadding 通常 1 个单位即可颜色使用命名终端色red、green、yellow、blue、magenta、cyan、white、gray谨慎使用十六进制色用Heading做章节标题、Divider分隔区块、Badge表示状态、KeyValue展示标注数据、Card做带边框分组多视图 UI 用Tabs 子内容visible条件Sparkline做行内趋势、BarChart跨类别比较配合KeyValue、ProgressBar组成仪表盘列表数据务必填充 3–5 条真实感样例避免空数据展示数据类 UI 时应在 Spec 顶层附带 state 示例。对照 packages/ink/src/components/standard.tsx 的实现可以看到这些规范如何落地Divider默认 40 字符宽、ProgressBar默认 30 字符、Card默认深色背景#1a1a1a、深色终端上不可见的黑色系颜色被自动过滤所有这些默认值都来自 Catalog 定义中的 zod props 与实现常量是终端渲染开箱即用的保证。小结json-render/ink把 json-render 的JSON Spec → UI范式完整带入了终端世界扁平元素映射让 AI 更容易生成结构正确的 SpecCatalog 用 Zod 约束组件形状并自动产出 PromptRenderer递归解析可见性、动态 props、事件动作与 repeat 列表useUIStream则让 AI 以 JSONL 补丁流的形式逐行构建 UI 并具备自修复能力。若要进一步深入可以阅读 packages/ink/src/renderer.tsx 的ElementRenderer与RepeatChildren实现、packages/ink/src/hooks.ts 的useUIStream重试管线或直接运行 examples/ink-chat 查看一个完整可跑的终端对话应用。赞分享人工智能AI 应用前端MCP 服务【免费下载链接】json-renderThe Generative UI framework项目地址https://gitcode.com/GitHub_Trending/js/json-render点击查看免费下载相关推荐使用 json-render/ink 将 JSON Spec 渲染为交互式终端 UI使用 json render/ink 将 JSON Spec 渲染为交互式终端 UI 导读 json render/ink 是 Generative UI人工智能AI 应用前端MCP 服务用 JSON 驱动终端 UIjson-render/ink 终端渲染器完全指南用 JSON 驱动终端 UIjson render/ink 终端渲染器完全指南 json render/ink 是 json renderGenerat人工智能AI 应用前端MCP 服务json-render/react 实战指南用 JSON Spec 驱动 React UIjson render/react 实战指南用 JSON Spec 驱动 React UI json render/react 是 json render人工智能AI 应用前端MCP 服务上一篇如何把微信朋友圈永久保存下来WechatMoments三步导出实战教程下一篇MinDoc文档管理系统Docker部署教程5 分钟从零跑通第一份文档创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考