Files
2026Technology-Competition/docs/superpowers/specs/implementation-steps/01-phase1-base-layer.md
T
范智鹏 805737fcfc feat: 设置面板 + Provider 扩展 + 构建脚本
- 设置面板:三步引导 / AI 配置 / API Key / 规则管理 / 连接测试
- Provider 重构:统一 OpenAICompatibleProvider 基类,新增 Gemini/Claude/混元/智谱等
- 审查面板 Webview:三 Tab、统计卡片、问题列表、postMessage 通信
- esbuild 构建脚本 + 生产打包 + PMD 下载
- 保存文件自动静态分析(500ms debounce)
2026-07-16 22:20:30 +08:00

5.4 KiB
Raw Blame History

Step 01 — Phase 1: 基础层

依赖: 无
参考设计: §3.2, §6.4, §13.2

目标

建立公共类型定义和配置管理,为所有上层模块提供基础能力。

新建文件

# 文件 说明
1 src/types.ts 公共类型定义
2 src/config/ai.ts AI 配置 getter
3 src/config/linter.ts Linter 配置 getter
4 src/config/fixer.ts 修复器配置 getter
5 src/config/secret.ts API Key SecretStorage
6 src/config/index.ts 统一导出

1. src/types.ts

import * as vscode from 'vscode';

export type Severity = 'error' | 'warning' | 'info';

export type AdapterStatus = 'ok' | 'tool-unavailable' | 'execution-failed';

export interface LinterDiagnostic {
  severity: Severity;
  ruleId: string;
  message: string;
  range: vscode.Range;
  suggestion?: string;
}

export interface AdapterResult {
  diagnostics: LinterDiagnostic[];
  status: AdapterStatus;
  errorMessage?: string;
}

export interface LinterAdapter {
  id: string;
  supportedLanguages: string[];
  check(document: vscode.TextDocument, workingDir: string): Promise<AdapterResult>;
  isAvailable(): boolean;
}

2. src/config/ai.ts

import * as vscode from 'vscode';

export interface AIConfig {
  provider: string;
  model: string;
  baseUrl: string;
  temperature: number;
  timeout: number;
  outputLanguage: string;
}

export function getAIConfig(): AIConfig {
  const config = vscode.workspace.getConfiguration('vscode-code-reviewer');
  return {
    provider: config.get<string>('ai.provider', 'deepseek'),
    model: config.get<string>('ai.model', 'deepseek-chat'),
    baseUrl: config.get<string>('ai.baseUrl', 'https://api.deepseek.com/v1'),
    temperature: config.get<number>('ai.temperature', 0.2),
    timeout: config.get<number>('ai.timeout', 300),
    outputLanguage: config.get<string>('ai.outputLanguage', 'zh-CN'),
  };
}

配置 Key(前缀 vscode-code-reviewer.:

Key 类型 默认值
ai.provider enum deepseek
ai.model string deepseek-chat
ai.baseUrl string https://api.deepseek.com/v1
ai.temperature number 0.2
ai.timeout number 300
ai.outputLanguage string zh-CN

3. src/config/linter.ts

import * as vscode from 'vscode';

export interface LinterConfig {
  languageMap: Record<string, string>;
  pmdJarPath: string;
  pmdRulesetPath: string;
  pmdJspRulesetPath: string;
  sqlLintConfigFile: string;
}

export function getLinterConfig(): LinterConfig {
  const config = vscode.workspace.getConfiguration('vscode-code-reviewer');
  return {
    languageMap: {
      javascript: config.get<string>('linters.javascript', 'eslint'),
      typescript: config.get<string>('linters.typescript', 'eslint'),
      java: config.get<string>('linters.java', 'pmd'),
      jsp: config.get<string>('linters.jsp', 'jsp'),
      css: config.get<string>('linters.css', 'stylelint'),
      sql: config.get<string>('linters.sql', 'sql-lint'),
      plsql: config.get<string>('linters.plsql', 'sql-lint'),
    },
    pmdJarPath: config.get<string>('pmd.jarPath', ''),
    pmdRulesetPath: config.get<string>('pmd.rulesetPath', ''),
    pmdJspRulesetPath: config.get<string>('pmd.jspRulesetPath', ''),
    sqlLintConfigFile: config.get<string>('sql-lint.configFile', ''),
  };
}
Key 类型 默认值 enum
linters.javascript enum eslint "" / eslint
linters.typescript enum eslint "" / eslint
linters.java enum pmd "" / pmd
linters.jsp enum jsp "" / jsp
linters.css enum stylelint "" / stylelint
linters.sql enum sql-lint "" / sql-lint
linters.plsql enum sql-lint "" / sql-lint
pmd.jarPath string ""
pmd.rulesetPath string ""
pmd.jspRulesetPath string ""
sql-lint.configFile string ""

4. src/config/fixer.ts

import * as vscode from 'vscode';

export interface FixerConfig {
  contextLines: number;
}

export function getFixerConfig(): FixerConfig {
  const config = vscode.workspace.getConfiguration('vscode-code-reviewer');
  return {
    contextLines: config.get<number>('fixer.contextLines', 5),
  };
}

5. src/config/secret.ts

import * as vscode from 'vscode';

const SECRET_KEY = 'vscode-code-reviewer.apiKey';

export async function getApiKey(context: vscode.ExtensionContext): Promise<string | undefined> {
  return context.secrets.get(SECRET_KEY);
}

export async function setApiKey(context: vscode.ExtensionContext, key: string): Promise<void> {
  await context.secrets.store(SECRET_KEY, key);
}

export async function deleteApiKey(context: vscode.ExtensionContext): Promise<void> {
  await context.secrets.delete(SECRET_KEY);
}

export async function isApiKeyConfigured(context: vscode.ExtensionContext): Promise<boolean> {
  const key = await getApiKey(context);
  return !!key;
}

6. src/config/index.ts

export { getAIConfig, AIConfig } from './ai';
export { getLinterConfig, LinterConfig } from './linter';
export { getFixerConfig, FixerConfig } from './fixer';
export { getApiKey, setApiKey, deleteApiKey, isApiKeyConfigured } from './secret';

验收

  • 6 个文件创建完成
  • npm run compile 通过
  • npm run lint 通过