Kode-cli/next_todo.md
CrazyBoyM 02c7c31a31 feat: Add GPT-5 Responses API support and model adapter system
- Implement model adapter factory for unified API handling
- Add response state manager for conversation continuity
- Support GPT-5 Responses API with continuation tokens
- Add model capabilities type system
- Include deployment guide and test infrastructure
- Enhance error handling and debugging for model interactions
2025-08-22 13:22:48 +08:00

893 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Kode系统 Responses API 支持重构施工文档
## 📋 项目概述
### 目标
将Kode系统从硬编码的GPT-5检测升级为基于能力声明的模型系统支持所有Responses API类模型GPT-5、GPT-6、GLM-5等
### 核心原则
1. **零破坏性**: 100%保留现有功能
2. **渐进式**: 可随时回滚
3. **可扩展**: 新模型只需配置
4. **优雅性**: 消除硬编码,统一处理流程
## 🏗️ 系统架构概览
### 当前架构(问题)
```
用户输入 → REPL → query.ts → queryLLM
[硬编码检测]
if (isGPT5Model()) {...}
if (isGPT4Model()) {...}
不同的API调用路径
```
### 目标架构(解决方案)
```
用户输入 → REPL → query.ts → queryLLM
[能力声明系统]
ModelCapabilities查询
[统一适配器]
ResponsesAPIAdapter / ChatCompletionsAdapter
统一的API调用
```
## 📁 文件结构规划
```
src/
├── types/
│ └── modelCapabilities.ts # 新建:能力类型定义
├── constants/
│ └── modelCapabilities.ts # 新建:模型能力注册表
├── services/
│ ├── adapters/ # 新建目录:适配器
│ │ ├── base.ts # 新建:基础适配器类
│ │ ├── responsesAPI.ts # 新建Responses API适配器
│ │ └── chatCompletions.ts # 新建Chat Completions适配器
│ ├── modelAdapterFactory.ts # 新建:适配器工厂
│ ├── claude.ts # 修改:使用新系统
│ └── openai.ts # 修改:清理硬编码
```
---
## 🚀 Phase 1: 基础设施建设第1-2天
### 目标
创建能力声明系统的基础架构,不影响现有代码运行。
### Step 1.1: 创建模型能力类型定义
**文件**: `src/types/modelCapabilities.ts` (新建)
**任务**: 定义模型能力接口
```typescript
// 完整代码 - 直接复制粘贴
export interface ModelCapabilities {
// API架构类型
apiArchitecture: {
primary: 'chat_completions' | 'responses_api'
fallback?: 'chat_completions' // Responses API模型可降级
}
// 参数映射
parameters: {
maxTokensField: 'max_tokens' | 'max_completion_tokens'
supportsReasoningEffort: boolean
supportsVerbosity: boolean
temperatureMode: 'flexible' | 'fixed_one' | 'restricted'
}
// 工具调用能力
toolCalling: {
mode: 'none' | 'function_calling' | 'custom_tools'
supportsFreeform: boolean
supportsAllowedTools: boolean
supportsParallelCalls: boolean
}
// 状态管理
stateManagement: {
supportsResponseId: boolean
supportsConversationChaining: boolean
supportsPreviousResponseId: boolean
}
// 流式支持
streaming: {
supported: boolean
includesUsage: boolean
}
}
// 统一的请求参数
export interface UnifiedRequestParams {
messages: any[]
systemPrompt: string[]
tools?: any[]
maxTokens: number
stream?: boolean
previousResponseId?: string
reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high'
verbosity?: 'low' | 'medium' | 'high'
temperature?: number
}
// 统一的响应格式
export interface UnifiedResponse {
id: string
content: string
toolCalls?: any[]
usage: {
promptTokens: number
completionTokens: number
reasoningTokens?: number
}
responseId?: string // 用于Responses API状态管理
}
```
### Step 1.2: 创建模型能力注册表
**文件**: `src/constants/modelCapabilities.ts` (新建)
**任务**: 为所有模型定义能力
```typescript
import { ModelCapabilities } from '../types/modelCapabilities'
// GPT-5的标准能力定义
const GPT5_CAPABILITIES: ModelCapabilities = {
apiArchitecture: {
primary: 'responses_api',
fallback: 'chat_completions'
},
parameters: {
maxTokensField: 'max_completion_tokens',
supportsReasoningEffort: true,
supportsVerbosity: true,
temperatureMode: 'fixed_one'
},
toolCalling: {
mode: 'custom_tools',
supportsFreeform: true,
supportsAllowedTools: true,
supportsParallelCalls: true
},
stateManagement: {
supportsResponseId: true,
supportsConversationChaining: true,
supportsPreviousResponseId: true
},
streaming: {
supported: false, // Responses API暂不支持流式
includesUsage: true
}
}
// Chat Completions的标准能力定义
const CHAT_COMPLETIONS_CAPABILITIES: ModelCapabilities = {
apiArchitecture: {
primary: 'chat_completions'
},
parameters: {
maxTokensField: 'max_tokens',
supportsReasoningEffort: false,
supportsVerbosity: false,
temperatureMode: 'flexible'
},
toolCalling: {
mode: 'function_calling',
supportsFreeform: false,
supportsAllowedTools: false,
supportsParallelCalls: true
},
stateManagement: {
supportsResponseId: false,
supportsConversationChaining: false,
supportsPreviousResponseId: false
},
streaming: {
supported: true,
includesUsage: true
}
}
// 完整的模型能力映射表
export const MODEL_CAPABILITIES_REGISTRY: Record<string, ModelCapabilities> = {
// GPT-5系列
'gpt-5': GPT5_CAPABILITIES,
'gpt-5-mini': GPT5_CAPABILITIES,
'gpt-5-nano': GPT5_CAPABILITIES,
'gpt-5-chat-latest': GPT5_CAPABILITIES,
// GPT-4系列
'gpt-4o': CHAT_COMPLETIONS_CAPABILITIES,
'gpt-4o-mini': CHAT_COMPLETIONS_CAPABILITIES,
'gpt-4-turbo': CHAT_COMPLETIONS_CAPABILITIES,
'gpt-4': CHAT_COMPLETIONS_CAPABILITIES,
// Claude系列通过转换层支持
'claude-3-5-sonnet-20241022': CHAT_COMPLETIONS_CAPABILITIES,
'claude-3-5-haiku-20241022': CHAT_COMPLETIONS_CAPABILITIES,
'claude-3-opus-20240229': CHAT_COMPLETIONS_CAPABILITIES,
// O1系列特殊的推理模型
'o1': {
...CHAT_COMPLETIONS_CAPABILITIES,
parameters: {
...CHAT_COMPLETIONS_CAPABILITIES.parameters,
maxTokensField: 'max_completion_tokens',
temperatureMode: 'fixed_one'
}
},
'o1-mini': {
...CHAT_COMPLETIONS_CAPABILITIES,
parameters: {
...CHAT_COMPLETIONS_CAPABILITIES.parameters,
maxTokensField: 'max_completion_tokens',
temperatureMode: 'fixed_one'
}
}
}
// 智能推断未注册模型的能力
export function inferModelCapabilities(modelName: string): ModelCapabilities | null {
if (!modelName) return null
const lowerName = modelName.toLowerCase()
// GPT-5系列
if (lowerName.includes('gpt-5') || lowerName.includes('gpt5')) {
return GPT5_CAPABILITIES
}
// GPT-6系列预留
if (lowerName.includes('gpt-6') || lowerName.includes('gpt6')) {
return {
...GPT5_CAPABILITIES,
streaming: { supported: true, includesUsage: true }
}
}
// GLM系列
if (lowerName.includes('glm-5') || lowerName.includes('glm5')) {
return {
...GPT5_CAPABILITIES,
toolCalling: {
...GPT5_CAPABILITIES.toolCalling,
supportsAllowedTools: false // GLM可能不支持
}
}
}
// O1系列
if (lowerName.startsWith('o1') || lowerName.includes('o1-')) {
return {
...CHAT_COMPLETIONS_CAPABILITIES,
parameters: {
...CHAT_COMPLETIONS_CAPABILITIES.parameters,
maxTokensField: 'max_completion_tokens',
temperatureMode: 'fixed_one'
}
}
}
// 默认返回null让系统使用默认行为
return null
}
// 获取模型能力(带缓存)
const capabilityCache = new Map<string, ModelCapabilities>()
export function getModelCapabilities(modelName: string): ModelCapabilities {
// 检查缓存
if (capabilityCache.has(modelName)) {
return capabilityCache.get(modelName)!
}
// 查找注册表
if (MODEL_CAPABILITIES_REGISTRY[modelName]) {
const capabilities = MODEL_CAPABILITIES_REGISTRY[modelName]
capabilityCache.set(modelName, capabilities)
return capabilities
}
// 尝试推断
const inferred = inferModelCapabilities(modelName)
if (inferred) {
capabilityCache.set(modelName, inferred)
return inferred
}
// 默认为Chat Completions
const defaultCapabilities = CHAT_COMPLETIONS_CAPABILITIES
capabilityCache.set(modelName, defaultCapabilities)
return defaultCapabilities
}
```
### Step 1.3: 创建基础适配器类
**文件**: `src/services/adapters/base.ts` (新建)
**任务**: 创建adapters目录和基础类
```typescript
import { ModelCapabilities, UnifiedRequestParams, UnifiedResponse } from '../../types/modelCapabilities'
import { ModelProfile } from '../../utils/config'
import { Tool } from '../../Tool'
export abstract class ModelAPIAdapter {
constructor(
protected capabilities: ModelCapabilities,
protected modelProfile: ModelProfile
) {}
// 子类必须实现的方法
abstract createRequest(params: UnifiedRequestParams): any
abstract parseResponse(response: any): UnifiedResponse
abstract buildTools(tools: Tool[]): any
// 共享的工具方法
protected getMaxTokensParam(): string {
return this.capabilities.parameters.maxTokensField
}
protected getTemperature(): number {
if (this.capabilities.parameters.temperatureMode === 'fixed_one') {
return 1
}
if (this.capabilities.parameters.temperatureMode === 'restricted') {
return Math.min(1, this.modelProfile.temperature || 0.7)
}
return this.modelProfile.temperature || 0.7
}
protected shouldIncludeReasoningEffort(): boolean {
return this.capabilities.parameters.supportsReasoningEffort
}
protected shouldIncludeVerbosity(): boolean {
return this.capabilities.parameters.supportsVerbosity
}
}
```
### Step 1.4: 创建Responses API适配器
**文件**: `src/services/adapters/responsesAPI.ts` (新建)
**任务**: 实现Responses API适配器
```typescript
import { ModelAPIAdapter } from './base'
import { UnifiedRequestParams, UnifiedResponse } from '../../types/modelCapabilities'
import { Tool } from '../../Tool'
import { zodToJsonSchema } from '../../utils/zodToJsonSchema'
export class ResponsesAPIAdapter extends ModelAPIAdapter {
createRequest(params: UnifiedRequestParams): any {
const { messages, systemPrompt, tools, maxTokens } = params
// 分离系统消息和用户消息
const systemMessages = messages.filter(m => m.role === 'system')
const nonSystemMessages = messages.filter(m => m.role !== 'system')
// 构建基础请求
const request: any = {
model: this.modelProfile.modelName,
input: this.convertMessagesToInput(nonSystemMessages),
instructions: this.buildInstructions(systemPrompt, systemMessages)
}
// 添加token限制
request[this.getMaxTokensParam()] = maxTokens
// 添加温度GPT-5只支持1
if (this.getTemperature() === 1) {
request.temperature = 1
}
// 添加推理控制
if (this.shouldIncludeReasoningEffort()) {
request.reasoning = {
effort: params.reasoningEffort || this.modelProfile.reasoningEffort || 'medium'
}
}
// 添加详细度控制
if (this.shouldIncludeVerbosity()) {
request.text = {
verbosity: params.verbosity || 'high' // 编码任务默认高详细度
}
}
// 添加工具
if (tools && tools.length > 0) {
request.tools = this.buildTools(tools)
// 处理allowed_tools
if (params.allowedTools && this.capabilities.toolCalling.supportsAllowedTools) {
request.tool_choice = {
type: 'allowed_tools',
mode: 'auto',
tools: params.allowedTools
}
}
}
// 添加状态管理
if (params.previousResponseId && this.capabilities.stateManagement.supportsPreviousResponseId) {
request.previous_response_id = params.previousResponseId
}
return request
}
buildTools(tools: Tool[]): any[] {
// 如果不支持freeform使用传统格式
if (!this.capabilities.toolCalling.supportsFreeform) {
return tools.map(tool => ({
type: 'function',
function: {
name: tool.name,
description: tool.description || '',
parameters: tool.inputJSONSchema || zodToJsonSchema(tool.inputSchema)
}
}))
}
// Custom tools格式GPT-5特性
return tools.map(tool => {
const hasSchema = tool.inputJSONSchema || tool.inputSchema
const isCustom = !hasSchema || tool.freeformInput
if (isCustom) {
// Custom tool格式
return {
type: 'custom',
name: tool.name,
description: tool.description || ''
}
} else {
// 传统function格式
return {
type: 'function',
function: {
name: tool.name,
description: tool.description || '',
parameters: tool.inputJSONSchema || zodToJsonSchema(tool.inputSchema)
}
}
}
})
}
parseResponse(response: any): UnifiedResponse {
// 处理基础文本输出
let content = response.output_text || ''
// 处理结构化输出
if (response.output && Array.isArray(response.output)) {
const messageItems = response.output.filter(item => item.type === 'message')
if (messageItems.length > 0) {
content = messageItems
.map(item => {
if (item.content && Array.isArray(item.content)) {
return item.content
.filter(c => c.type === 'text')
.map(c => c.text)
.join('\n')
}
return item.content || ''
})
.filter(Boolean)
.join('\n\n')
}
}
// 解析工具调用
const toolCalls = this.parseToolCalls(response)
// 构建统一响应
return {
id: response.id || `resp_${Date.now()}`,
content,
toolCalls,
usage: {
promptTokens: response.usage?.input_tokens || 0,
completionTokens: response.usage?.output_tokens || 0,
reasoningTokens: response.usage?.output_tokens_details?.reasoning_tokens
},
responseId: response.id // 保存用于状态管理
}
}
private convertMessagesToInput(messages: any[]): any {
// 将消息转换为Responses API的input格式
// 可能需要根据实际API规范调整
return messages
}
private buildInstructions(systemPrompt: string[], systemMessages: any[]): string {
const systemContent = systemMessages.map(m => m.content).join('\n\n')
const promptContent = systemPrompt.join('\n\n')
return [systemContent, promptContent].filter(Boolean).join('\n\n')
}
private parseToolCalls(response: any): any[] {
if (!response.output || !Array.isArray(response.output)) {
return []
}
return response.output
.filter(item => item.type === 'tool_call')
.map(item => ({
id: item.id || `tool_${Date.now()}`,
type: 'tool_call',
name: item.name,
arguments: item.arguments // 可能是文本或JSON
}))
}
}
```
### Step 1.5: 创建Chat Completions适配器
**文件**: `src/services/adapters/chatCompletions.ts` (新建)
**任务**: 实现Chat Completions适配器
```typescript
import { ModelAPIAdapter } from './base'
import { UnifiedRequestParams, UnifiedResponse } from '../../types/modelCapabilities'
import { Tool } from '../../Tool'
import { zodToJsonSchema } from '../../utils/zodToJsonSchema'
export class ChatCompletionsAdapter extends ModelAPIAdapter {
createRequest(params: UnifiedRequestParams): any {
const { messages, systemPrompt, tools, maxTokens, stream } = params
// 构建完整消息列表(包含系统提示)
const fullMessages = this.buildMessages(systemPrompt, messages)
// 构建请求
const request: any = {
model: this.modelProfile.modelName,
messages: fullMessages,
[this.getMaxTokensParam()]: maxTokens,
temperature: this.getTemperature()
}
// 添加工具
if (tools && tools.length > 0) {
request.tools = this.buildTools(tools)
request.tool_choice = 'auto'
}
// 添加流式选项
if (stream) {
request.stream = true
request.stream_options = {
include_usage: true
}
}
// O1模型的特殊处理
if (this.modelProfile.modelName.startsWith('o1')) {
delete request.temperature // O1不支持temperature
delete request.stream // O1不支持流式
delete request.stream_options
}
return request
}
buildTools(tools: Tool[]): any[] {
// Chat Completions只支持传统的function calling
return tools.map(tool => ({
type: 'function',
function: {
name: tool.name,
description: tool.description || '',
parameters: tool.inputJSONSchema || zodToJsonSchema(tool.inputSchema)
}
}))
}
parseResponse(response: any): UnifiedResponse {
const choice = response.choices?.[0]
return {
id: response.id || `chatcmpl_${Date.now()}`,
content: choice?.message?.content || '',
toolCalls: choice?.message?.tool_calls || [],
usage: {
promptTokens: response.usage?.prompt_tokens || 0,
completionTokens: response.usage?.completion_tokens || 0
}
}
}
private buildMessages(systemPrompt: string[], messages: any[]): any[] {
// 合并系统提示和消息
const systemMessages = systemPrompt.map(prompt => ({
role: 'system',
content: prompt
}))
return [...systemMessages, ...messages]
}
}
```
### Step 1.6: 创建适配器工厂
**文件**: `src/services/modelAdapterFactory.ts` (新建)
**任务**: 创建工厂类来选择合适的适配器
```typescript
import { ModelAPIAdapter } from './adapters/base'
import { ResponsesAPIAdapter } from './adapters/responsesAPI'
import { ChatCompletionsAdapter } from './adapters/chatCompletions'
import { getModelCapabilities } from '../constants/modelCapabilities'
import { ModelProfile, getGlobalConfig } from '../utils/config'
import { ModelCapabilities } from '../types/modelCapabilities'
export class ModelAdapterFactory {
/**
* 根据模型配置创建合适的适配器
*/
static createAdapter(modelProfile: ModelProfile): ModelAPIAdapter {
const capabilities = getModelCapabilities(modelProfile.modelName)
// 决定使用哪种API
const apiType = this.determineAPIType(modelProfile, capabilities)
// 创建对应的适配器
switch (apiType) {
case 'responses_api':
return new ResponsesAPIAdapter(capabilities, modelProfile)
case 'chat_completions':
default:
return new ChatCompletionsAdapter(capabilities, modelProfile)
}
}
/**
* 决定应该使用哪种API
*/
private static determineAPIType(
modelProfile: ModelProfile,
capabilities: ModelCapabilities
): 'responses_api' | 'chat_completions' {
// 如果模型不支持Responses API直接使用Chat Completions
if (capabilities.apiArchitecture.primary !== 'responses_api') {
return 'chat_completions'
}
// 检查是否是官方OpenAI端点
const isOfficialOpenAI = !modelProfile.baseURL ||
modelProfile.baseURL.includes('api.openai.com')
// 非官方端点使用Chat Completions即使模型支持Responses API
if (!isOfficialOpenAI) {
// 如果有fallback选项使用fallback
if (capabilities.apiArchitecture.fallback === 'chat_completions') {
return 'chat_completions'
}
// 否则使用primary可能会失败但让它尝试
return capabilities.apiArchitecture.primary
}
// 检查是否需要流式Responses API暂不支持
const config = getGlobalConfig()
if (config.stream && !capabilities.streaming.supported) {
// 需要流式但Responses API不支持降级到Chat Completions
if (capabilities.apiArchitecture.fallback === 'chat_completions') {
return 'chat_completions'
}
}
// 使用主要API类型
return capabilities.apiArchitecture.primary
}
/**
* 检查模型是否应该使用Responses API
*/
static shouldUseResponsesAPI(modelProfile: ModelProfile): boolean {
const capabilities = getModelCapabilities(modelProfile.modelName)
const apiType = this.determineAPIType(modelProfile, capabilities)
return apiType === 'responses_api'
}
}
```
---
## 🔄 Phase 2: 集成与测试第3-4天
### 目标
将新系统集成到现有代码中,与旧系统并行运行。
### Step 2.1: 修改claude.ts使用新系统
**文件**: `src/services/claude.ts` (修改)
**任务**: 在queryLLMWithProfile中添加新的适配器路径
**找到函数**: `queryLLMWithProfile` (约第1182行)
**修改内容**:
```typescript
// 在函数开头添加功能开关
const USE_NEW_ADAPTER_SYSTEM = process.env.USE_NEW_ADAPTERS !== 'false'
// 在获取modelProfile后添加新路径
if (USE_NEW_ADAPTER_SYSTEM) {
// 🚀 新的适配器系统
const adapter = ModelAdapterFactory.createAdapter(modelProfile)
// 构建统一请求参数
const unifiedParams: UnifiedRequestParams = {
messages: openaiMessages, // 使用已转换的OpenAI格式消息
systemPrompt: openaiSystem.map(s => s.content),
tools: toolSchemas,
maxTokens: getMaxTokensFromProfile(modelProfile),
stream: config.stream,
reasoningEffort: modelProfile.reasoningEffort,
temperature: isGPT5Model(model) ? 1 : MAIN_QUERY_TEMPERATURE
}
// 创建请求
const request = adapter.createRequest(unifiedParams)
// 判断使用哪个API端点
if (ModelAdapterFactory.shouldUseResponsesAPI(modelProfile)) {
// 调用Responses API复用现有的callGPT5ResponsesAPI
const response = await callGPT5ResponsesAPI(modelProfile, request, signal)
return adapter.parseResponse(response)
} else {
// 调用Chat Completions复用现有逻辑
// ... 现有的Chat Completions调用代码
}
} else {
// 保留原有逻辑完全不变
// ... 现有的所有代码
}
```
### Step 2.2: 添加测试脚本
**文件**: `src/test/testAdapters.ts` (新建)
**任务**: 创建测试脚本验证新系统
```typescript
import { ModelAdapterFactory } from '../services/modelAdapterFactory'
import { getGlobalConfig } from '../utils/config'
// 测试不同模型的适配器选择
const testModels = [
{ modelName: 'gpt-5', provider: 'openai' },
{ modelName: 'gpt-4o', provider: 'openai' },
{ modelName: 'claude-3-5-sonnet-20241022', provider: 'anthropic' },
{ modelName: 'o1', provider: 'openai' },
{ modelName: 'glm-5', provider: 'custom' }
]
testModels.forEach(model => {
console.log(`Testing ${model.modelName}:`)
const adapter = ModelAdapterFactory.createAdapter(model as any)
console.log(` Adapter type: ${adapter.constructor.name}`)
console.log(` Should use Responses API: ${ModelAdapterFactory.shouldUseResponsesAPI(model as any)}`)
})
```
### Step 2.3: 清理硬编码可选Phase 3再做
**文件**: `src/services/openai.ts` (修改)
**任务**: 标记需要移除的硬编码部分(先不删除)
```typescript
// 在isGPT5Model函数上添加注释
/**
* @deprecated 将被ModelCapabilities系统替代
*/
function isGPT5Model(modelName: string): boolean {
return modelName.startsWith('gpt-5')
}
```
---
## 🚀 Phase 3: 优化与清理第5-6天
### 目标
移除旧代码,完全切换到新系统。
### Step 3.1: 移除功能开关
**文件**: `src/services/claude.ts`
**任务**: 移除USE_NEW_ADAPTER_SYSTEM检查默认使用新系统
### Step 3.2: 清理硬编码函数
**文件列表**:
- `src/services/openai.ts` - 移除isGPT5Model函数
- `src/services/claude.ts` - 移除isGPT5Model函数
- `src/services/openai.ts` - 移除MODEL_FEATURES常量
### Step 3.3: 更新文档
**文件**: `README.md`
**任务**: 添加新模型支持说明
```markdown
## 支持的模型
本系统通过能力声明系统支持以下API类型
- Chat Completions API: GPT-4, Claude等传统模型
- Responses API: GPT-5, GPT-6, GLM-5等新一代模型
添加新模型只需在 `src/constants/modelCapabilities.ts` 中配置即可。
```
---
## ✅ 验证清单
### Phase 1完成标准
- [ ] 所有新文件创建完成
- [ ] 代码可以编译通过
- [ ] 现有功能完全不受影响
### Phase 2完成标准
- [ ] 新旧系统可以通过环境变量切换
- [ ] GPT-5可以正常使用
- [ ] 所有现有模型功能正常
### Phase 3完成标准
- [ ] 完全使用新系统
- [ ] 代码更简洁清晰
- [ ] 新模型可通过配置添加
---
## 🎯 关键注意事项
1. **不要删除任何现有功能代码**直到Phase 3
2. **始终保持向后兼容**
3. **每个Phase结束后都要测试**
4. **如果出现问题可以立即回滚**
## 📝 外包程序员执行指南
1. **严格按照Phase顺序执行**,不要跳步
2. **复制粘贴提供的代码**,不要自己修改
3. **遇到问题立即停止并报告**
4. **每完成一个Step都要git commit**,方便回滚
---
此文档设计为"无脑执行"级别,外包程序员只需要:
1. 创建指定的文件
2. 复制粘贴提供的代码
3. 在指定位置修改代码
4. 运行测试验证
整个过程不需要理解业务逻辑,只需要机械执行即可。