Agent 通常以 三种角色 融入前端项目框架

AI 时代程序员必备技能

Codex、Claude Code、Cursor、Hermes Agent、OpenClaw等工程化实战专栏 ,讲透 AI 如何接管脏活累活

在 Vue3 + Vite + Codex + TypeScript + Ant Design Vue 技术栈中,Agent 通常以 三种角色 融入项目框架:

角色定位触发时机
生成 Agent基于规范/需求生成代码开发阶段(写代码时)
审查 Agent自动 Review、找 Bug、规范检查提交前 / CI 阶段
运行时 Agent应用内智能交互、动态 UI用户使用时

以下是每种角色的完整落地配置和案例。


一、生成 Agent(Spec → Vue3 代码)

核心: 用 Codex CLI / 自定义脚本,将 .spec.md 或 OpenAPI 规范转换为 Vue3 + TS + AntD Vue 组件。

1. 项目结构

my-vue-project/
├── specs/                          # 规范目录(Agent 的输入)
│   ├── components/
│   │   └── UserForm.spec.md        # 组件规范
│   └── api/
│       └── user.api.yaml           # OpenAPI 规范
├── src/
│   ├── components/                 # Agent 生成(只读)
│   │   └── UserForm/
│   │       ├── index.vue
│   │       ├── types.ts
│   │       └── schema.ts
│   ├── api/                        # 生成的 API SDK
│   └── views/                      # 生成的页面
├── .codex/                         # Codex Agent 配置
│   ├── instructions.md             # 系统提示词
│   └── templates/                  # 生成模板
├── scripts/
│   └── agent-generate.ts           # 生成脚本
└── codex.yaml                      # Codex 项目配置

2. Codex 配置 .codex/instructions.md

# Vue3 + TS + AntD Vue 代码生成规范

## 技术约束
- 使用 Vue3 Composition API + `<script setup lang="ts">`
- 使用 TypeScript,所有 props/emits 必须显式类型化
- UI 组件统一使用 `ant-design-vue`
- 表单使用 `a-form` + `zod` 做校验
- API 调用使用生成的 `@/api` SDK + TanStack Vue Query

## 代码风格
- 组件名使用 PascalCase
- Props 接口名:`{ComponentName}Props`
- Emits 接口名:`{ComponentName}Emits`
- 样式使用 Scoped CSS + CSS Variables

## 禁止
- 不要使用 Options API
- 不要使用 `any` 类型
- 不要直接调用 `fetch/axios`,必须使用生成的 SDK

3. 组件规范示例 specs/components/UserForm.spec.md

---
name: UserForm
type: component
framework: vue3
ui: ant-design-vue
---

## 功能
用户编辑表单,包含:用户名、邮箱、角色、状态

## Props
- user: UserDTO | undefined — 编辑时传入,新增时为 undefined
- loading: boolean — 提交加载状态

## Emits
- submit: (values: UserFormValues) => void
- cancel: () => void

## 校验规则
- username: 必填,3-20 字符,仅字母数字下划线
- email: 必填,邮箱格式
- role: 必填,枚举 ['admin', 'editor', 'viewer']
- status: 必填,枚举 ['active', 'inactive']

## UI 要求
- 使用 a-form 布局,label 宽度 100px
- 底部有「保存」「取消」按钮
- 加载时按钮禁用并显示 Spin

4. 生成脚本 scripts/agent-generate.ts

import { execSync } from 'child_process';
import { readFileSync, writeFileSync, mkdirSync } from 'fs';
import matter from 'gray-matter';

interface Spec {
  name: string;
  type: string;
  framework: string;
  ui: string;
}

function generateComponent(specPath: string) {
  const content = readFileSync(specPath, 'utf-8');
  const { data, content: body } = matter(content) as { data: Spec; content: string };
  
  const prompt = `
基于以下规范生成 Vue3 + TypeScript + Ant Design Vue 组件代码。

规范文件:${specPath}
组件名:${data.name}

${body}

要求:
1. 使用 <script setup lang="ts">
2. Props 和 Emits 使用类型化定义
3. 表单校验使用 zod + ant-design-vue 的 validate
4. 导出组件和类型
5. 添加 JSDoc 注释

请生成完整的 index.vue 文件内容。
`;

  // 调用 Codex CLI 生成代码
  const result = execSync(`codex -p "${prompt.replace(/"/g, '\\"')}"`, {
    encoding: 'utf-8',
    cwd: process.cwd(),
  });

  const outputDir = `src/components/${data.name}`;
  mkdirSync(outputDir, { recursive: true });
  writeFileSync(`${outputDir}/index.vue`, result);
  
  console.log(`✅ Generated: ${outputDir}/index.vue`);
}

// 遍历 specs 目录生成
const specs = process.argv.slice(2);
if (specs.length === 0) {
  console.log('Usage: tsx scripts/agent-generate.ts specs/components/*.md');
}

specs.forEach(generateComponent);

5. package.json Scripts

{
  "scripts": {
    "agent:gen": "tsx scripts/agent-generate.ts",
    "agent:gen:all": "tsx scripts/agent-generate.ts specs/components/*.md specs/views/*.md",
    "agent:gen:watch": "chokidar 'specs/**/*.md' -c 'npm run agent:gen -- {path}'"
  }
}

6. 生成的组件示例 src/components/UserForm/index.vue

<template>
  <a-form
    :model="formState"
    :rules="rules"
    @finish="handleSubmit"
    label-align="right"
    :label-col="{ style: { width: '100px' } }"
  >
    <a-form-item label="用户名" name="username">
      <a-input v-model:value="formState.username" placeholder="请输入用户名" />
    </a-form-item>

    <a-form-item label="邮箱" name="email">
      <a-input v-model:value="formState.email" placeholder="请输入邮箱" />
    </a-form-item>

    <a-form-item label="角色" name="role">
      <a-select v-model:value="formState.role" placeholder="请选择角色">
        <a-select-option value="admin">管理员</a-select-option>
        <a-select-option value="editor">编辑</a-select-option>
        <a-select-option value="viewer">访客</a-select-option>
      </a-select>
    </a-form-item>

    <a-form-item label="状态" name="status">
      <a-radio-group v-model:value="formState.status">
        <a-radio value="active">启用</a-radio>
        <a-radio value="inactive">禁用</a-radio>
      </a-radio-group>
    </a-form-item>

    <a-form-item>
      <a-space>
        <a-button type="primary" html-type="submit" :loading="props.loading">
          保存
        </a-button>
        <a-button @click="handleCancel">取消</a-button>
      </a-space>
    </a-form-item>
  </a-form>
</template>

<script setup lang="ts">
import { reactive, watch } from 'vue';
import type { FormInstance } from 'ant-design-vue';
import { z } from 'zod';

export interface UserFormValues {
  username: string;
  email: string;
  role: 'admin' | 'editor' | 'viewer';
  status: 'active' | 'inactive';
}

export interface UserFormProps {
  initialValues?: Partial<UserFormValues>;
  loading?: boolean;
}

export interface UserFormEmits {
  (e: 'submit', values: UserFormValues): void;
  (e: 'cancel'): void;
}

const props = withDefaults(defineProps<UserFormProps>(), {
  loading: false,
});

const emit = defineEmits<UserFormEmits>();

const formState = reactive<UserFormValues>({
  username: '',
  email: '',
  role: 'viewer',
  status: 'active',
});

// 同步初始值
watch(
  () => props.initialValues,
  (val) => {
    if (val) {
      Object.assign(formState, val);
    }
  },
  { immediate: true }
);

const rules = {
  username: [
    { required: true, message: '请输入用户名' },
    { min: 3, max: 20, message: '长度 3-20 字符' },
    { pattern: /^[a-zA-Z0-9_]+$/, message: '仅允许字母数字下划线' },
  ],
  email: [
    { required: true, message: '请输入邮箱' },
    { type: 'email', message: '邮箱格式不正确' },
  ],
  role: [{ required: true, message: '请选择角色' }],
  status: [{ required: true, message: '请选择状态' }],
};

const handleSubmit = () => {
  emit('submit', { ...formState });
};

const handleCancel = () => {
  emit('cancel');
};
</script>

二、审查 Agent(Git Hook + CI)

核心:pre-commit 和 CI 中运行 Agent,自动 Review 代码质量、类型安全、AntD Vue 使用规范。

1. 本地审查脚本 scripts/agent-review.ts

import { execSync } from 'child_process';
import { readFileSync } from 'fs';

function getStagedFiles(): string[] {
  return execSync('git diff --cached --name-only --diff-filter=ACM')
    .toString()
    .split('\n')
    .filter(f => f.endsWith('.vue') || f.endsWith('.ts'));
}

function reviewFile(filePath: string): string {
  const code = readFileSync(filePath, 'utf-8');
  
  const prompt = `
你是一名资深 Vue3 + TypeScript 代码审查员。请审查以下代码,按规则检查:

## 检查项
1. 是否使用 Composition API(<script setup>)
2. Props 是否有显式类型定义
3. 是否使用了 any 类型
4. AntD Vue 组件使用是否正确(如 a-form 的 model 绑定)
5. 是否有未使用的导入或变量
6. 是否有潜在的空值/类型错误
7. 是否符合团队命名规范

## 输出格式
对每个问题,输出:
- [严重/警告/建议] 行号: 问题描述 → 修复建议

如果无问题,输出:✅ 通过

## 代码文件:${filePath}
\`\`\`vue
${code}
\`\`\`
`;

  try {
    const result = execSync(`codex --no-interactive -p "${prompt.replace(/"/g, '\\"')}"`, {
      encoding: 'utf-8',
      timeout: 30000,
    });
    return result;
  } catch (e) {
    return `⚠️ 审查超时: ${filePath}`;
  }
}

const files = getStagedFiles();
if (files.length === 0) {
  console.log('No staged files to review.');
  process.exit(0);
}

let hasError = false;

for (const file of files) {
  console.log(`\n🔍 Reviewing: ${file}`);
  const report = reviewFile(file);
  console.log(report);
  
  if (report.includes('[严重]')) {
    hasError = true;
  }
}

if (hasError) {
  console.error('\n❌ 审查发现严重问题,提交被拒绝。');
  console.error('如需强制提交,使用: git commit --no-verify');
  process.exit(1);
} else {
  console.log('\n✅ 审查通过');
}

2. Git Hook 配置 .husky/pre-commit

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# 先跑 ESLint
npx lint-staged

# 再跑 Agent 审查
npx tsx scripts/agent-review.ts

3. CI 中的批量审查 .github/workflows/agent-review.yml

name: Agent Code Review

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Get changed files
        id: changed
        run: |
          echo "files=$(git diff --name-only origin/${{ github.base_ref }} | grep -E '\.(vue|ts)$' | tr '\n' ' ')" >> $GITHUB_OUTPUT

      - name: Run Agent Review
        if: steps.changed.outputs.files != ''
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          for file in ${{ steps.changed.outputs.files }}; do
            echo "🔍 Reviewing $file"
            npx tsx scripts/agent-review.ts "$file"
          done

三、运行时 Agent(应用内 AI 助手)

核心: 在 Vue3 应用内嵌入 AI Agent,提供智能表单填充、页面导航、代码辅助等功能。

1. 运行时 Agent 组件 src/components/AIAgent/AgentPanel.vue

<template>
  <div class="ai-agent-panel">
    <a-float-button
      type="primary"
      :style="{ right: '24px', bottom: '24px' }"
      @click="togglePanel"
    >
      <template #icon>🤖</template>
    </a-float-button>

    <a-drawer
      v-model:open="visible"
      title="AI 助手"
      placement="right"
      :width="480"
    >
      <div class="chat-container">
        <div v-for="(msg, idx) in messages" :key="idx" :class="['msg', msg.role]">
          <a-avatar v-if="msg.role === 'assistant'" style="background-color: #1890ff">AI</a-avatar>
          <div class="bubble">{{ msg.content }}</div>
        </div>
        <div v-if="loading" class="msg assistant">
          <a-spin size="small" />
        </div>
      </div>

      <div class="input-area">
        <a-textarea
          v-model:value="input"
          :rows="3"
          placeholder="描述你的需求,例如:帮我生成一个用户查询表单"
          @pressEnter="handleSend"
        />
        <a-button type="primary" :loading="loading" @click="handleSend">
          发送
        </a-button>
      </div>
    </a-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref, nextTick } from 'vue';
import { useAgent } from './useAgent';

const visible = ref(false);
const input = ref('');
const { messages, loading, sendMessage } = useAgent();

const togglePanel = () => {
  visible.value = !visible.value;
};

const handleSend = async () => {
  if (!input.value.trim() || loading.value) return;
  const text = input.value;
  input.value = '';
  await sendMessage(text);
};
</script>

<style scoped>
.chat-container {
  height: calc(100% - 120px);
  overflow-y: auto;
  padding: 16px 0;
}
.msg {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}
.msg.user {
  flex-direction: row-reverse;
}
.msg.user .bubble {
  background: #1890ff;
  color: white;
  border-radius: 12px 12px 0 12px;
}
.msg.assistant .bubble {
  background: #f0f0f0;
  border-radius: 12px 12px 12px 0;
}
.bubble {
  padding: 8px 12px;
  max-width: 80%;
  word-break: break-word;
}
.input-area {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 16px;
  border-top: 1px solid #f0f0f0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
</style>

2. Agent 逻辑 Hook src/components/AIAgent/useAgent.ts

import { ref } from 'vue';

interface Message {
  role: 'user' | 'assistant';
  content: string;
}

export function useAgent() {
  const messages = ref<Message[]>([
    { role: 'assistant', content: '你好!我是你的开发助手。你可以让我:\n1. 生成组件代码\n2. 解释现有代码\n3. 优化表单逻辑' }
  ]);
  const loading = ref(false);

  const sendMessage = async (text: string) => {
    messages.value.push({ role: 'user', content: text });
    loading.value = true;

    try {
      // 调用后端 Agent API 或 Codex CLI
      const response = await fetch('/api/agent/chat', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          messages: messages.value,
          context: {
            framework: 'vue3',
            ui: 'ant-design-vue',
            project: 'my-vue-project'
          }
        }),
      });

      const data = await response.json();
      messages.value.push({ role: 'assistant', content: data.reply });
    } catch (e) {
      messages.value.push({ role: 'assistant', content: '请求失败,请稍后重试' });
    } finally {
      loading.value = false;
    }
  };

  return { messages, loading, sendMessage };
}

3. 后端 Agent API 示例(Node.js)

// server/agent.ts
import { OpenAI } from 'openai';
import { readFileSync } from 'fs';
import { glob } from 'glob';

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

// 加载项目上下文(组件库、类型定义等)
async function loadProjectContext() {
  const components = await glob('src/components/**/*.vue');
  const types = await glob('src/**/*.ts');
  
  const context = {
    components: components.slice(0, 10), // 取前10个作为示例
    typeDefinitions: types.slice(0, 5),
  };
  
  return context;
}

export async function handleAgentChat(req: Request) {
  const { messages, context } = await req.json();
  
  const systemPrompt = `
你是 ${context.project} 项目的 AI 开发助手。

项目技术栈:
- Vue3 + Composition API
- TypeScript
- Ant Design Vue
- Vite

可用组件:
${context.components.join('\n')}

规则:
1. 生成代码时必须使用 <script setup lang="ts">
2. 使用 ant-design-vue 组件,不要引入其他 UI 库
3. 类型必须严格,禁止 any
4. 如果用户要求生成组件,输出完整 .vue 文件内容
`;

  const completion = await openai.chat.completions.create({
    model: 'gpt-4o',
    messages: [
      { role: 'system', content: systemPrompt },
      ...messages.map((m: any) => ({ role: m.role, content: m.content }))
    ],
    temperature: 0.2,
  });

  return new Response(JSON.stringify({
    reply: completion.choices[0].message.content
  }), {
    headers: { 'Content-Type': 'application/json' }
  });
}

四、三种角色的协同工作流

┌─────────────────────────────────────────────────────────────────┐
│                         开发阶段                                 │
├─────────────────────────────────────────────────────────────────┤
│  1. 写规范 specs/components/UserForm.spec.md                    │
│  2. 运行 npm run agent:gen → 生成 Agent 产出 Vue 组件            │
│  3. 人工微调(如需)→ 规范同步回 specs/                           │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│                         提交阶段                                 │
├─────────────────────────────────────────────────────────────────┤
│  git add .                                                      │
│  git commit                                                    │
│    ├─ lint-staged (ESLint + Prettier)                          │
│    └─ agent-review.ts (审查 Agent 检查类型/规范)                  │
│  不通过 → 阻断提交,输出修复建议                                  │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│                         运行阶段                                 │
├─────────────────────────────────────────────────────────────────┤
│  用户打开应用 → 看到右下角 🤖 AI 助手                             │
│  用户说:"帮我生成一个带搜索的用户表格"                            │
│  运行时 Agent → 调用 API → 返回代码 → 用户一键插入到项目            │
└─────────────────────────────────────────────────────────────────┘

五、Vite 配置要点 vite.config.ts

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src'),
      '@specs': resolve(__dirname, 'specs'),
    },
  },
  server: {
    proxy: {
      '/api/agent': {
        target: 'http://localhost:3001',
        changeOrigin: true,
      },
    },
  },
});

六、快速启动模板

如果你要新建项目,可以用这个一键脚本:

# 1. 创建项目
npm create vite@latest my-vue-agent -- --template vue-ts
cd my-vue-agent

# 2. 安装依赖
npm install vue-router@4 pinia ant-design-vue zod
npm install -D @vitejs/plugin-vue typescript tsx husky lint-staged

# 3. 初始化 Agent 工作流
mkdir -p .codex specs/components specs/api scripts
echo 'node_modules/' >> .gitignore
echo 'src/api/' >> .gitignore

# 4. 配置 Husky
npx husky install
npx husky add .husky/pre-commit "npx lint-staged && npx tsx scripts/agent-review.ts"

# 5. 启动
npm run dev

总结: 在 Vue3 + Vite + Codex 项目中,Agent 不是"一个功能",而是贯穿 生成 → 审查 → 运行 三个阶段的基础设施。生成 Agent 把规范变成代码,审查 Agent 守住质量门槛,运行时 Agent 让最终用户也能享受 AI 能力。

AI 时代程序员必备技能

Codex、Claude Code、Cursor、Hermes Agent、OpenClaw等工程化实战专栏 ,讲透 AI 如何接管脏活累活

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值