把 .vue 组件变成 AI 可调用的“技能“:前端能力可调用化的工程实践
当 AI Agent 成为软件系统的新型"用户",传统 .vue 组件的封装范式正面临根本性挑战——组件的能力"藏"在 DOM 结构里,AI 无从调用。"前端能力可调用化(Front-end Capability as Skill)"是一种新范式:将 .vue 组件抽象为具名、类型化、可被 AI 发现与调用的 Skill,让前端能力以标准化接口的形式参与 AI 驱动的智能应用。本文结合 SPARK
摘要:当 AI Agent 成为软件系统的新型"用户",传统 .vue 组件的封装范式正面临根本性挑战——组件的能力"藏"在 DOM 结构里,AI 无从调用。"前端能力可调用化(Front-end Capability as Skill)"是一种新范式:将 .vue 组件抽象为具名、类型化、可被 AI 发现与调用的 Skill,让前端能力以标准化接口的形式参与 AI 驱动的智能应用。本文结合 SPARK 框架的能力系统(Capability System)与组件注册表(Registry),深入讲解这一范式的原理、实现路径与工程实践,并横向对比 MCP、OpenAI Function Calling 等主流 AI 工具协议,帮你看懂前端开发下一个十年的核心演化方向。
关键字:前端能力可调用化、Vue组件Skill化、AI Agent集成、SPARK能力系统、组件注册表、智能前端
一、时代的提问:AI 来了,你的组件它"看得懂"吗?
2025 年以来,AI Agent 正从"对话助手"进化为"任务执行者"——它不只是回答问题,而是主动调用工具、操控界面、完成端到端任务。
但绝大多数前端组件,都是为"人"设计的:
人 → 看到界面 → 点击按钮 → 触发事件 → 更新数据
AI → 看到什么?→ 如何调用?→ 不知道
一个 Vue 组件有多少"能力"?它能做什么?需要什么输入?会产生什么输出?
对人来说,看一眼 UI 就知道了。
对 AI 来说——这些信息根本不存在于任何可机器读取的结构中。
这就是问题的根源,也是"前端能力可调用化"要解决的核心命题:
🎯 让 .vue 组件的"能力",以 AI 可理解、可发现、可调用的形式暴露出来。
二、从"组件"到"技能":认知范式的升级
2.1 什么是 Skill(技能)?
在 AI 领域,Skill(技能/工具)的定义已相当成熟:
| AI 框架 | 术语 | 核心要素 |
|---|---|---|
| OpenAI Function Calling | Function / Tool | 函数名、参数 Schema(JSON Schema)、描述 |
| Microsoft Copilot | Skill | 函数签名、触发意图、输入输出类型 |
| Semantic Kernel | Plugin / Skill | 函数集合、KernelFunction 装饰器 |
| LangChain | Tool | name、description、args_schema |
| MCP (Model Context Protocol) | Tool | name、description、inputSchema |
共同本质:
Skill = 名称(可被发现)
+ 输入描述(AI 知道该传什么)
+ 输出描述(AI 知道会得到什么)
+ 执行逻辑(实际做事情)
2.2 .vue 组件距离 Skill 有多远?
一个典型的 .vue 组件拥有:
组件 Skill 需要什么 差距
─────────────────────────────────────────────────────────────
type="spark-ej2-grid" ← 名称 ✅ 有名称
props: { config } ← 输入 ⚠️ 类型在 TS 里,运行时不可查
provide(DATA_SOURCE) ← 输出能力 ❌ 隐式,AI 不可见
emit('row-click', row) ← 事件输出 ❌ 无结构化描述
差距本质:组件的"接口"散落在 TypeScript 类型、Props 定义、事件文档里——人可读,机器不可查,AI 不可调用。
2.3 Skill 化的三个核心动作
把 .vue 组件变成 Skill,本质上是做三件事:
┌──────────────────────────────────────────────┐
│ .vue 组件 → Skill 化三步走 │
│ │
.vue 组件 │ ① 命名化 → kebab-case + Registry 注册 │
│ │
│ ② 接口化 → ComponentConfig 类型 + │
│ 能力键声明(provide/consume) │
│ │
│ ③ 可发现 → meta 元数据 + AI 可读描述 │
│ │
└──────────────────────────────────────────────┘
↓
前端 Skill(AI 可调用)
三、SPARK 能力系统:Skill 的运行时基础设施
SPARK 框架的能力系统(packages/spark-utils/src/capability/symbols.ts)不是偶然为之,它从架构上就为 Skill 化奠定了基础。
3.1 能力键(Capability Key)= Skill 接口的类型标签
// 定义一个类型安全的能力键——这就是 Skill 的"接口声明"
import { defineCapability } from '@spark-view/spark-utils'
// 声明 Skill 的输出类型
export const DATA_SOURCE = defineCapability<IDataSource>('spark:capability:data-source')
// 声明时机:组件注册时
// 语义:凡是 provide(DATA_SOURCE, xxx) 的组件,
// 就具备"提供数据视图"这个能力(Skill)
每一个能力键,对应一种可调用的前端能力:
| 能力键 | 对应的 Skill 语义 | 典型 Provider |
|---|---|---|
PAGE_DATASET |
“提供页面级数据空间” | PageRenderer |
DATA_SOURCE |
“提供数据视图(可读写行数据)” | r-table / r-form |
APP_SERVICES |
“提供路由/日志/租户服务” | SparkPlugin |
PAGE_SERVICE |
“提供 UI 消息/确认框/导航” | RendererContainer |
FIELD_CONTEXT |
“声明当前渲染上下文” | 各容器组件 |
LOGGER |
“提供自定义日志实现” | 任意组件 |
3.2 provide / consume = Skill 的发布与调用
// ✅ 组件"发布"自己的能力(把自己变成 Skill Provider)
const { provide } = useSparkComponent(props.config)
provide(DATA_SOURCE, dataView) // 声明:我具备"数据视图"能力
// ✅ 子组件"调用"祖先的能力(消费 Skill)
const { consume } = useSparkComponent(props.config)
const source = consume(DATA_SOURCE) // 调用:获取最近祖先的"数据视图"能力
这与 OpenAI Function Calling 的调用模型高度同构:
OpenAI Function Calling SPARK 能力系统
───────────────────────────────────────────────────────────
function_name: "get_data" 能力键: DATA_SOURCE
parameters: { query: string } consume(DATA_SOURCE) 返回 IDataSource
return: DataResult source.rows / source.currentRow
💡 关键洞见:
provide/consume不只是依赖注入——它是组件能力的发布/订阅协议,是 .vue 组件面向 AI 调用的铰链点。
3.3 parent 链查找 = Skill 的作用域感知
SPARK 的 lookup() 沿 parent 链向上遍历,就近匹配能力:
根上下文(APP_SERVICES)
└── PageRenderer(PAGE_DATASET)
└── r-table(DATA_SOURCE)
└── r-text-col → consume(DATA_SOURCE) → 取最近的 r-table 的数据
└── r-number-col → consume(DATA_SOURCE) → 同上
这实现了 Skill 的作用域隔离——多个 r-table 嵌套时,每个的子组件只能访问它自己的数据视图,不会跨树污染。
这与 Copilot Skill 的"上下文隔离"、MCP 的"会话隔离"设计思想如出一辙。
四、组件注册表:Skill 的发现协议
4.1 Registry = Skill Catalog(技能目录)
SPARK 的 ComponentRegistry(packages/spark-component/src/registry/ComponentRegistry.ts)就是前端 Skill 目录:
import { Spark } from '@spark-view/spark-component'
// 注册 Skill(发布到目录)
Spark.register('spark-ej2-grid', SparkEJ2Grid)
Spark.register('r-table', RendererTable)
Spark.register('r-form', RendererForm)
// 带元数据注册(Skill 的描述信息)
Spark.register('spark-ej2-grid', SparkEJ2Grid, {
dataKey: 'self-resolve', // 声明 dataKey 解析行为
description: '高性能数据表格,支持排序/过滤/分页',
capabilities: {
provides: ['spark:capability:data-source', 'spark:capability:selection'],
consumes: ['spark:capability:page-dataset'],
}
})
// 批量注册(生产推荐,懒加载)
const reg = Spark.createRegister(import.meta.glob('./components/*.vue'))
reg.registerAll({
'user-grid': './UserGrid.vue',
'user-form': './UserForm.vue',
'dept-tree': './DeptTree.vue',
})
Registry 本质上就是一个 Skill Catalog——AI 可以查询这个目录,发现有哪些可用的前端技能。
4.2 isComponentRegistered = Skill 的存在性检测
const { isComponentRegistered, getComponent } = useSparkComponent(props.config)
// AI 在执行任务前,先检测所需技能是否可用
if (isComponentRegistered('spark-ej2-grid')) {
// 组件已注册,可以安全使用
const GridComponent = getComponent('spark-ej2-grid')
} else {
// 技能不存在,走降级路径
logger.warn('spark-ej2-grid 未注册,使用原生 el-table 替代')
}
4.3 编译时注册 vs 运行时注册:Skill 的加载策略
| 策略 | 实现方式 | Skill 类比 | 适用场景 |
|---|---|---|---|
| 编译时注册(Smart 模式) | Vite 插件生成 virtual:spark-components |
静态 Skill 目录,编译时固化 | 生产环境,首屏性能优先 |
| 运行时懒加载 | defineAsyncComponent + 动态 import |
按需加载 Skill,调用时才下载 | 开发环境,大型项目 |
| 热插拔注册 | Spark.register() 运行时调用 |
动态 Skill 插件,像 npm 包一样扩展 | 微前端/插件平台 |
编译时(生产) 运行时(开发/微前端)
────────────────── ──────────────────────────
Vite 构建时扫描 运行时动态扫描
↓ ↓
virtual:spark-components Spark.register('type', loader)
↓ ↓
Tree Shaking 优化 按需 import()
↓ ↓
首屏快 32% 灵活无限扩展
五、ComponentConfig:Skill 的调用契约
5.1 从 Props 到 Config:统一调用接口
所有 SPARK 组件都通过 ComponentConfig 接收配置,这是 Skill 调用的统一入口:
// packages/spark-component/src/core/types.ts
export interface ComponentConfig {
type: string // Skill 名称(注册表 key)
id?: string // 实例 ID
visible?: boolean // 能力:可见性控制
disabled?: boolean // 能力:禁用状态控制
children?: ComponentConfig[] // 能力:嵌套子 Skill
dataKey?: string // 能力:数据绑定
props?: Record<string, unknown> // Skill 的具体参数
on?: Record<string, unknown> // Skill 的事件钩子
meta?: Record<string, unknown> // Skill 的元数据
}
与 AI 工具协议的映射:
ComponentConfig OpenAI Tool Call
────────────────────────────────────────────────────
type: "spark-ej2-grid" ←→ function: "spark_ej2_grid"
props: { border: true } ←→ arguments: { border: true }
dataKey: "Orders@rows" ←→ arguments: { dataKey: "Orders@rows" }
children: [{ type: "col" }] ←→ (嵌套 tool call,MCP 支持)
5.2 扩展 ComponentConfig:声明 Skill 的专属参数
// 定义一个表格 Skill 的调用契约
interface SparkEJ2GridConfig extends ComponentConfig {
type: 'spark-ej2-grid'
// Skill 专属参数
dataKey: string // 必须:数据绑定键
allowPaging?: boolean // 可选:是否分页
pageSize?: number // 可选:每页行数
allowSorting?: boolean // 可选:是否排序
allowFiltering?: boolean // 可选:是否过滤
// 子 Skill(列定义)
children?: SparkEJ2ColumnConfig[]
}
interface SparkEJ2ColumnConfig extends ComponentConfig {
type: 'spark-ej2-column'
name: string // 绑定的数据字段
props: {
headerText: string // 列标题
width?: string // 列宽
textAlign?: 'Left' | 'Center' | 'Right'
}
}
// AI 生成的 rule.json 就是对这套契约的"调用"
const ruleJson = [
{
"type": "spark-ej2-grid",
"dataKey": "Orders@rows",
"props": { "allowPaging": true, "pageSize": 20 },
"children": [
{ "type": "spark-ej2-column", "name": "orderId",
"props": { "headerText": "订单号", "width": "160" } }
]
}
]
六、AI 调用 Skill 的完整链路
6.1 rule.json:AI 生成的 Skill 调用脚本
在 SPARK 框架中,rule.json 就是 AI 对前端 Skill 的调用序列:
AI 理解需求
│
▼
AI 查询 Registry(Skill 目录)
│
▼
AI 选择合适的 Skill 组合
│
▼
AI 生成 rule.json(Skill 调用参数)
│
▼
SPARK bindRules 解析 rule.json
│
▼
getComponent(type) 从 Registry 解析组件
│
▼
SparkComponentRenderer 递归渲染
│
▼
useSparkComponent → ComponentContext 树构建
│
▼
provide/consume 能力链接通
│
▼
UI 渲染完成(Skill 执行完毕)
6.2 能力链的建立过程(Skill 的运行时组装)
// 这是 SPARK 最核心的运行时流程(简化)
// Step 1:AI 生成的 rule.json 被解析为 ComponentConfig 树
const config = {
type: 'r-table',
dataKey: 'Orders@rows',
children: [
{ type: 'el-table-column', props: { prop: 'orderId', label: '订单号' } }
]
}
// Step 2:SparkComponentRenderer 取出组件实例
const TableComponent = registry.get('r-table')
// Step 3:r-table 内部 useSparkComponent 建立上下文
// → consume(PAGE_DATASET) 拿到 DataSet
// → resolveDataKeyBinding('Orders@rows', ds) → DataView
// → provide(DATA_SOURCE, dataView) 发布自己的数据能力
// Step 4:子组件 el-table-column 通过 DATA_SOURCE 获取数据
// → consume(DATA_SOURCE) → dataView.rows → 渲染列数据
// 整个过程:AI 写配置,框架拼接能力链——人无需干预
6.3 AI 发现前端 Skill 的三种方式
方式一:virtual:spark-skill-catalog(✅ 当前已实现,推荐)
┌─────────────────────────────────────────────────────┐
│ .vue 文件加 @skill JSDoc 注解 │
│ ↓ │
│ vite-plugin-spark-components scan() 自动提取 │
│ ↓ │
│ virtual:spark-skill-catalog 虚拟模块 │
│ export const skillCatalog: SkillMeta[] │
│ export function buildSkillPrompt( │
│ header?, mode?, types? │
│ ): string │
│ ↓ │
│ 三档精度输出(index / compact / full) │
│ + 按 type 过滤,token 完全可控 │
└─────────────────────────────────────────────────────┘
方式二:运行时 Registry 查询
┌─────────────────────────────────────────────────────┐
│ AI 调用 GET /api/spark/skills │
│ → 后端从 ComponentRegistry 导出所有已注册类型 │
│ → 返回 { type, meta, description }[] 列表 │
│ → AI 据此选择合适的 Skill 填入 rule.json │
└─────────────────────────────────────────────────────┘
方式三:提示词静态内嵌(快速启动)
┌─────────────────────────────────────────────────────┐
│ SPARK_COMPONENT_PROMPT.md 手写 Skill 目录 │
│ → 作为系统提示词发给 LLM │
│ → AI 根据自然语言需求,从已知 Skill 中选择并组合 │
│ → 生成符合约束的 rule.json │
└─────────────────────────────────────────────────────┘
七、使用场景全景图
🏗️ 场景 1:AI 驱动的页面自动生成
传统场景(组件化):
产品需求 → UI 设计稿 → 工程师手写 .vue → Review → 上线
(2~5 天)
Skill 化场景(AI 调用):
产品需求(自然语言)
│
▼
AI 查 Skill 目录:有 r-table、r-form、dept-tree 等
│
▼
AI 组合 Skill 生成 rule.json + pagedata.json
│
▼
SPARK 渲染:Skill 链自动组装
│
▼
Logger 日志上报 → AI 自动迭代修正
│
▼
可交付页面(< 30 分钟)
实际 rule.json 示例(AI 的 Skill 调用脚本):
[
{
"type": "el-container",
"children": [
{
"type": "el-aside",
"props": { "width": "260px" },
"children": [
{
"type": "r-tree",
"dataKey": "Departments@rows",
"props": { "nodeKey": "id", "defaultExpandAll": true }
}
]
},
{
"type": "el-main",
"children": [
{
"type": "r-table",
"dataKey": "Employees@rows",
"props": { "border": true, "stripe": true, "highlightCurrentRow": true },
"children": [
{ "type": "el-table-column", "props": { "prop": "name", "label": "姓名" } },
{ "type": "el-table-column", "props": { "prop": "dept", "label": "部门" } },
{ "type": "el-table-column", "props": { "prop": "salary", "label": "薪资" } }
]
}
]
}
]
}
]
这不是人写的 Vue 模板——这是 AI 对前端 Skill 的一次声明式调用。
🔌 场景 2:微前端的 Skill 热插拔
在微前端架构中,Skill 化的组件可以像 npm 包一样被动态加载和卸载:
// 主应用:定义 Skill 热插拔接口
interface SkillPlugin {
name: string
skills: Record<string, () => Promise<{ default: unknown }>>
}
// 微应用 A 注册自己的 Skill
const pluginA: SkillPlugin = {
name: 'hr-module',
skills: {
'hr-org-chart': () => import('./OrgChart.vue'),
'hr-salary-table': () => import('./SalaryTable.vue'),
}
}
// 运行时安装(热插拔)
function installSkillPlugin(plugin: SkillPlugin) {
for (const [type, loader] of Object.entries(plugin.skills)) {
Spark.register(type, loader) // 动态注入到全局 Skill 目录
}
}
installSkillPlugin(pluginA)
// AI 立即可用新 Skill,无需重启
// rule.json 中写 { "type": "hr-org-chart" } 即可渲染
🤖 场景 3:AI Agent 主动调用前端 Skill
这是"前端能力可调用化"的终极形态——AI Agent 不是"生成静态配置",而是实时、动态地组合和调用前端 Skill:
// AI Agent 的前端 Skill 调用适配器(概念示意)
class SparkSkillAdapter {
private registry = Spark.getRegistry()
// 暴露给 AI 的"查询可用技能"接口
listSkills(): SkillDescriptor[] {
return [...this.registry.getAll().values()].map(def => ({
name: def.type,
description: def.meta?.description as string,
inputSchema: def.meta?.inputSchema,
capabilities: def.meta?.capabilities,
}))
}
// 暴露给 AI 的"执行技能"接口
async invokeSkill(type: string, config: ComponentConfig): Promise<void> {
if (!this.registry.has(type)) {
throw new Error(`Skill not found: ${type}`)
}
// 将 config 写入 rule.json → SPARK 渲染
await writePageFiles(currentPageId, {
'rule.json': JSON.stringify([config], null, 2)
})
}
}
// AI Agent 的一次 Skill 调用(伪代码)
const adapter = new SparkSkillAdapter()
const skills = adapter.listSkills()
// 选择 r-table Skill,填入调用参数
await adapter.invokeSkill('r-table', {
type: 'r-table',
dataKey: 'Orders@rows',
props: { border: true }
})
🛡️ 场景 4:权限感知的 Skill 降级
Skill 化的组件可以内置权限感知能力,AI 调用时无需额外处理权限逻辑:
// 一个权限感知的 Skill 实现
export default defineComponent({
setup(props) {
const { consume, logger } = useSparkComponent(props.config)
const services = consume(APP_SERVICES)
// Skill 内部自主处理权限
const hasPermission = computed(() => {
const perm = services?.auth?.checkPermission(props.config.type)
if (!perm) logger.warn(`Skill ${props.config.type} 权限不足,自动降级`)
return perm
})
return { hasPermission }
}
})
AI 生成 rule.json 时不需要知道权限规则——Skill 自己处理,对 AI 透明。
🧪 场景 5:Storybook + Skill 驱动的组件演示
Skill 化的组件元数据可以驱动自动化的 Storybook:
// FCPageRenderer.stories.ts(项目中实际存在)
// 通过 ComponentConfig 直接驱动 Story,无需手写 args
export default {
title: 'SPARK/Skills/r-table',
component: SparkComponentRenderer,
}
// 每个 Story = 一种 Skill 调用场景
export const BasicTable = {
args: {
config: {
type: 'r-table',
dataKey: 'Orders@rows',
props: { border: true }
}
}
}
export const WithAggregates = {
args: {
config: {
type: 'r-table',
dataKey: 'Orders@summaryRow', // 聚合行 Skill
props: { stripe: true }
}
}
}
八、工程实践:一步步把 .vue 组件封装为标准 Skill
Step 1:命名规范化(Skill 的唯一标识)
❌ 传统命名 ✅ Skill 命名
───────────────────────────────────────────────
OrderTable.vue spark-order-table
UserFormPanel.vue spark-user-form
DeptTreeView.vue dept-tree
命名规则:
- 全小写 kebab-case
- 业务模块前缀(dept-, hr-, finance-)
- 能力描述后缀(-table, -form, -tree, -chart)
- 避免 UI 框架名(不叫 el-xxx,叫 spark-xxx)
Step 2:接口声明(Skill 的调用契约)
// ✅ 正确:为 Skill 定义明确的配置接口
interface DeptTreeConfig extends ComponentConfig {
type: 'dept-tree'
dataKey: string // 必须:树数据绑定
props?: {
nodeKey?: string // 节点唯一标识字段(默认 'id')
defaultExpandAll?: boolean // 默认展开全部(默认 false)
draggable?: boolean // 是否可拖拽(默认 false)
}
}
// ❌ 错误:不声明接口,props 用 any/unknown
interface BadConfig extends ComponentConfig {
props?: Record<string, unknown> // AI 和 TS 都不知道能传什么
}
Step 3:能力声明(Skill 的输入输出)
// DeptTree.vue 的 setup
const { provide, consume, logger } = useSparkComponent(props.config as DeptTreeConfig)
// ① 声明"消费"的能力——Skill 的输入依赖
const dataSet = consume(PAGE_DATASET) // 需要:页面数据空间
const appSvc = consume(APP_SERVICES) // 需要:应用服务(路由等)
// ② 声明"提供"的能力——Skill 的输出
provide(DATA_SOURCE, treeDataView) // 提供:树数据视图(供子组件消费)
provide(FIELD_CONTEXT, 'tree') // 提供:渲染上下文标识
// ③ 记录 Skill 执行日志(AI 迭代的关键数据)
logger.info('DeptTree Skill 初始化', {
nodeCount: treeDataView?.rows?.length ?? 0,
dataKey: (props.config as DeptTreeConfig).dataKey,
})
Step 4:Skill 注解(自动注册到 Skill 目录)
这是比「在 Spark.register() 手动传 meta」更优的方案:注解写在 .vue 文件顶部注释里,构建时 Vite 插件自动提取,无需在 main.ts 维护任何额外代码。
<!--
/**
* @skill dept-tree
* @description 部门组织树,支持懒加载、拖拽排序、节点点击联动子表
* @provides DATA_SOURCE
* @provides FIELD_CONTEXT
* @consumes PAGE_DATASET
* @consumes APP_SERVICES
* @input { dataKey: string, props: { nodeKey?: string, defaultExpandAll?: boolean, draggable?: boolean } }
* @example { "type": "dept-tree", "dataKey": "Departments@rows", "props": { "nodeKey": "id" } }
*/
-->
<template>...</template>
注解标签说明:
| 标签 | 说明 | 必填 |
|---|---|---|
@skill |
Skill 类型名(= 注册名,kebab-case) | ✅ |
@description |
一句话描述,AI 用于 Skill 选择 | 推荐 |
@provides |
该组件 provide 的能力键(可多行) | 推荐 |
@consumes |
该组件 consume 的能力键(可多行) | 推荐 |
@input |
参数 Schema(JSON 字符串) | 可选 |
@example |
rule.json 调用示例(JSON 字符串) | 可选 |
💡 零注册开销:Vite 插件
parseSkillMeta()只读文件前 60 行,与组件注册共用同一次scan()——一个注解,同时完成「组件注册」和「Skill 目录收录」两件事。构建日志:✅ 扫描完成: 13 个组件 (同步: 11, 异步: 2, Skill: 5)
Step 5:AI 提示词集成(三档精度,按需输出)
组件加了 @skill 注解后,构建产物中自动生成 virtual:spark-skill-catalog 虚拟模块,直接 import 即用——无需手动遍历 Registry:
import { skillCatalog, buildSkillPrompt } from 'virtual:spark-skill-catalog'
// 📋 场景 A:system prompt 常驻——只告诉 AI「有哪些组件」
// index 模式:仅 type + 描述,约 20 tokens/组件,200 个组件 ≈ 4000 tokens
const systemPrompt = buildSkillPrompt('## 可用 Skill 索引', 'index')
// 🔗 场景 B:AI 决定组合方式——需要知道依赖关系(默认)
// compact 模式:type + 描述 + provides/consumes,约 50 tokens/组件
const withCapabilities = buildSkillPrompt()
// 📖 场景 C:AI 准备生成具体 rule.json——只看目标组件完整细节
// full 模式 + types 过滤:含 inputSchema + example,仅指定组件
const detailPrompt = buildSkillPrompt('## 组件详情', 'full', ['r-table', 'dept-tree'])
// 🗂️ 也可直接使用结构化数据(序列化后发给 AI)
console.log(skillCatalog) // SkillMeta[]
推荐的两轮对话策略(token 预算可控 + 高准确率):
第一轮:index 模式注入 system prompt(全量索引)
AI:"我需要用 r-table 和 dept-tree"
第二轮:full 模式 + types 过滤(仅目标组件)
buildSkillPrompt('', 'full', ['r-table', 'dept-tree'])
AI 生成精确的 rule.json
| 模式 | Token 估算(10组件) | 适合场景 |
|---|---|---|
'index' |
~200 tokens | system prompt 常驻 |
'compact'(默认) |
~500 tokens | 多数对话轮次 |
'full' + 过滤 |
~300 tokens/个 | 生成具体配置前 |
九、横向对比:前端 Skill 与主流 AI 工具协议
| 维度 | OpenAI Function Calling | MCP Tool | SPARK Skill |
|---|---|---|---|
| 定义方式 | JSON Schema | JSON Schema | TypeScript 接口 + Registry meta |
| 调用方式 | AI 生成 JSON → 后端执行函数 | AI 生成 JSON → MCP server 执行 | AI 生成 rule.json → SPARK 渲染组件 |
| 输出类型 | 函数返回值(文本/JSON) | 工具结果(文本/图片) | UI 组件渲染 + 能力链接通 |
| 作用域 | 单次调用,无状态 | 会话级,有状态 | 组件树级,有上下文(parent 链) |
| 可组合性 | 可顺序调用(Chain) | 支持资源引用 | 天然嵌套(children + 能力链) |
| 反馈机制 | 函数返回值 | 工具结果 | Logger 日志上报 → AI 迭代修正 |
| 运行环境 | 后端 / 服务端 | MCP Server | 浏览器前端,Vue 运行时 |
| Skill 发现 | 在 API 请求中声明 | list_tools 接口 |
Registry + 提示词内嵌 |
SPARK Skill 的独特优势:
1. 可视化输出:Skill 执行结果是可交互的 UI,不只是文本
2. 状态持久:组件实例持续存在,能力链保持激活
3. 自然嵌套:组件树 = Skill 调用树,无需额外 Chain 框架
4. 反馈闭环:Logger → AI → 修正配置 → 自动重渲(AI Page Loop)
十、前端能力可调用化的终极形态
10.1 从 MVC 到 Skill Graph
软件架构的演化有清晰的脉络:
MVC(逻辑分层)
↓
组件化(UI 复用)
↓
微前端(跨团队协作)
↓
Skill 化(AI 可调用) ← 我们现在
↓
Skill Graph(AI 自主编排) ← 下一站
Skill Graph 的概念:每个前端组件是一个节点(Skill),节点间的依赖关系(能力 provide/consume)是有向边,整个组件树是一个可被 AI 动态编排的图结构。
AI 的任务变成:在 Skill Graph 中找到满足用户需求的最优子图,并激活它。
10.2 CapabilityTypeMap:Skill 的类型系统扩展
SPARK 已经通过模块增强(Declaration Merging)为 Skill 提供了开放的类型注册机制:
// 为自定义 Skill 扩展类型系统
declare module '@spark-view/spark-utils' {
interface CapabilityTypeMap {
// 注册新 Skill 的接口类型
'my-org:skill:approval-flow': IApprovalFlowCapability
'my-org:skill:signature-pad': ISignaturePadCapability
'my-org:skill:geo-picker': IGeoPickerCapability
}
}
// 使用——完全类型安全,IDE 全程智能提示
const approval = consume('my-org:skill:approval-flow')
// approval: IApprovalFlowCapability | null
这让每个业务团队都能向 Skill 生态贡献自己的能力,且完全类型安全。
10.3 AI + Skill 的协作模式演化
| 阶段 | 模式 | 描述 |
|---|---|---|
| 当前(2025~2026) | AI 生成 + 人验收 | AI 生成 rule.json,人工 review 后部署 |
| 近期规划 | AI 生成 + 自动测试 | Logger + 视觉回归验收,减少人工介入 |
| 中期目标 | AI 主导 + 人设意图 | 人只描述"想要什么",AI 自主选 Skill、组装、验收 |
| 远期愿景 | AI 自主进化 | AI 发现现有 Skill 不满足需求,自动生成新的 .vue Skill 并注册 |
十一、总结
“把 .vue 组件抽象为 Skill”,不是一次代码重构,而是一次开发范式的跃迁:
| 旧范式(组件化) | 新范式(Skill 化) |
|---|---|
| 组件是给人用的 UI 单元 | Skill 是给 AI/人共同调用的能力单元 |
| 能力隐含在 DOM 和逻辑里 | 能力通过 capability 键显式声明 |
| 组件靠 Props 通信 | Skill 靠 provide/consume 建立能力链 |
| 复用靠 copy-paste 或 npm | 复用靠 Registry 按名发现和调用 |
| 调试靠 console.log | 调试靠 Logger 全量上报 + AI 自动分析 |
| 页面由人手写 | 页面由 AI 选 Skill + 声明调用参数 |
SPARK 框架的四件套——能力键系统、组件注册表、ComponentConfig 契约、Logger 闭环——共同构成了"前端能力可调用化"的完整基础设施。
这不是遥远的未来,这是正在发生的工程实践。
🚀 下一步行动:
- 给现有
.vue组件顶部加@skillJSDoc 注解(4 个标签起步即生效)import { buildSkillPrompt } from 'virtual:spark-skill-catalog',用'index'模式注入 AI system prompt- 对话时按需切换
'full'模式 +types过滤,获取目标组件的完整 example- 接入
AIPageLoop,开启"提示词 → Skill 调用 → 渲染 → 日志反馈 → 迭代"的完整闭环
从今天开始,你写的每一个 .vue 文件,都有机会成为 AI 可调用的前端技能。
📌 项目参考:本文所有示例均基于 SPARK View 项目实际代码
模块 路径 能力系统定义 packages/spark-utils/src/capability/symbols.ts组件注册表 packages/spark-component/src/registry/ComponentRegistry.tsSpark 命名空间 packages/spark-component/src/spark.tsuseSparkComponent packages/spark-component/src/composables/useSparkComponent.ts核心类型 packages/spark-component/src/core/types.tsVite Skill 插件 tools/vite-plugin-spark-components.ts(parseSkillMeta/generateSkillCatalog)虚拟模块类型声明 src/env.d.ts(virtual:spark-skill-catalog)AI 闭环服务 src/services/ai-loop.ts组件开发指南 docs/guides/COMPONENT_DEVELOPMENT.md组件注册指南 docs/guides/COMPONENT_REGISTRATION.md
作者:SPARK Team | 发布:2026-03
更多推荐


所有评论(0)