Skip to content

扩展 API

扩展 API 是 Trae IDE 的核心功能之一,允许开发者创建功能强大的扩展来增强 IDE 的功能。

概述

Trae IDE 扩展系统提供了丰富的 API,让您能够:

  • 添加自定义命令和菜单项
  • 创建自定义编辑器和视图
  • 集成外部工具和服务
  • 扩展语言支持
  • 自定义用户界面
  • 管理工作区和文件
  • 与其他扩展通信

核心接口

Extension

扩展的主要接口定义。

typescript
interface Extension {
  readonly id: string;
  readonly name: string;
  readonly version: string;
  readonly description?: string;
  readonly publisher: string;
  readonly isActive: boolean;
  readonly packageJSON: any;
  readonly extensionPath: string;
  readonly globalState: Memento;
  readonly workspaceState: Memento;
  
  activate(context: ExtensionContext): Promise<any>;
  deactivate?(): Promise<void>;
}

ExtensionContext

扩展上下文提供了扩展运行时的环境信息。

typescript
interface ExtensionContext {
  readonly subscriptions: Disposable[];
  readonly workspaceState: Memento;
  readonly globalState: Memento;
  readonly secrets: SecretStorage;
  readonly extensionUri: Uri;
  readonly extensionPath: string;
  readonly environmentVariableCollection: EnvironmentVariableCollection;
  readonly storageUri?: Uri;
  readonly globalStorageUri: Uri;
  readonly logUri: Uri;
  
  asAbsolutePath(relativePath: string): string;
}

基本扩展结构

typescript
// extension.ts
import * as TraeAPI from 'trae';

export function activate(context: TraeAPI.ExtensionContext) {
  console.log('扩展已激活:', context.extension.id);
  
  // 注册命令
  const disposable = TraeAPI.commands.registerCommand('myExtension.helloWorld', () => {
    TraeAPI.window.showInformationMessage('Hello World from My Extension!');
  });
  
  context.subscriptions.push(disposable);
}

export function deactivate() {
  console.log('扩展已停用');
}

生命周期管理

扩展激活

typescript
// package.json 中的激活事件
{
  "activationEvents": [
    "onCommand:myExtension.activate",
    "onLanguage:typescript",
    "onFileSystem:sftp",
    "workspaceContains:**/*.config.js",
    "onStartupFinished"
  ]
}

// 激活函数
export async function activate(context: TraeAPI.ExtensionContext): Promise<ExtensionAPI> {
  // 初始化扩展
  const extension = new MyExtension(context);
  await extension.initialize();
  
  // 返回公共 API(可选)
  return {
    getVersion: () => extension.version,
    getStatus: () => extension.status,
    performAction: (action: string) => extension.performAction(action)
  };
}

// 停用函数
export async function deactivate(): Promise<void> {
  // 清理资源
  await MyExtension.cleanup();
}

扩展状态管理

typescript
class ExtensionStateManager {
  constructor(private context: TraeAPI.ExtensionContext) {}
  
  // 全局状态(跨工作区)
  getGlobalState<T>(key: string, defaultValue?: T): T {
    return this.context.globalState.get(key, defaultValue!);
  }
  
  async setGlobalState<T>(key: string, value: T): Promise<void> {
    await this.context.globalState.update(key, value);
  }
  
  // 工作区状态(特定于当前工作区)
  getWorkspaceState<T>(key: string, defaultValue?: T): T {
    return this.context.workspaceState.get(key, defaultValue!);
  }
  
  async setWorkspaceState<T>(key: string, value: T): Promise<void> {
    await this.context.workspaceState.update(key, value);
  }
  
  // 密钥存储
  async storeSecret(key: string, value: string): Promise<void> {
    await this.context.secrets.store(key, value);
  }
  
  async getSecret(key: string): Promise<string | undefined> {
    return await this.context.secrets.get(key);
  }
  
  async deleteSecret(key: string): Promise<void> {
    await this.context.secrets.delete(key);
  }
}

// 使用示例
const stateManager = new ExtensionStateManager(context);

// 保存用户偏好
await stateManager.setGlobalState('userPreferences', {
  theme: 'dark',
  fontSize: 14,
  autoSave: true
});

// 获取用户偏好
const preferences = stateManager.getGlobalState('userPreferences', {
  theme: 'light',
  fontSize: 12,
  autoSave: false
});

// 存储 API 密钥
await stateManager.storeSecret('apiKey', 'your-secret-api-key');
const apiKey = await stateManager.getSecret('apiKey');

命令系统

注册命令

typescript
// 简单命令
const simpleCommand = TraeAPI.commands.registerCommand('myExtension.simple', () => {
  TraeAPI.window.showInformationMessage('简单命令执行成功!');
});

// 带参数的命令
const parameterizedCommand = TraeAPI.commands.registerCommand(
  'myExtension.withParams',
  (param1: string, param2: number) => {
    TraeAPI.window.showInformationMessage(`参数: ${param1}, ${param2}`);
  }
);

// 异步命令
const asyncCommand = TraeAPI.commands.registerCommand(
  'myExtension.async',
  async () => {
    const result = await TraeAPI.window.showInputBox({
      prompt: '请输入一些文本',
      placeHolder: '在这里输入...'
    });
    
    if (result) {
      TraeAPI.window.showInformationMessage(`您输入了: ${result}`);
    }
  }
);

// 上下文相关命令
const contextCommand = TraeAPI.commands.registerCommand(
  'myExtension.contextual',
  (uri: TraeAPI.Uri) => {
    if (uri) {
      TraeAPI.window.showInformationMessage(`选中的文件: ${uri.fsPath}`);
    } else {
      const editor = TraeAPI.window.activeTextEditor;
      if (editor) {
        TraeAPI.window.showInformationMessage(`当前文件: ${editor.document.fileName}`);
      }
    }
  }
);

// 添加到订阅
context.subscriptions.push(
  simpleCommand,
  parameterizedCommand,
  asyncCommand,
  contextCommand
);

执行命令

typescript
// 执行内置命令
await TraeAPI.commands.executeCommand('workbench.action.files.save');
await TraeAPI.commands.executeCommand('editor.action.formatDocument');

// 执行自定义命令
await TraeAPI.commands.executeCommand('myExtension.simple');
await TraeAPI.commands.executeCommand('myExtension.withParams', 'hello', 42);

// 获取所有可用命令
const allCommands = await TraeAPI.commands.getCommands();
console.log('可用命令:', allCommands.filter(cmd => cmd.startsWith('myExtension')));

命令面板集成

typescript
// package.json 中的命令贡献
{
  "contributes": {
    "commands": [
      {
        "command": "myExtension.openSettings",
        "title": "打开设置",
        "category": "My Extension",
        "icon": "$(gear)"
      },
      {
        "command": "myExtension.refresh",
        "title": "刷新",
        "category": "My Extension",
        "icon": "$(refresh)"
      }
    ]
  }
}

UI 贡献

菜单贡献

typescript
// package.json 中的菜单贡献
{
  "contributes": {
    "menus": {
      "editor/context": [
        {
          "command": "myExtension.formatCode",
          "when": "editorHasSelection",
          "group": "1_modification"
        }
      ],
      "explorer/context": [
        {
          "command": "myExtension.processFile",
          "when": "resourceExtname == .js",
          "group": "2_workspace"
        }
      ],
      "commandPalette": [
        {
          "command": "myExtension.advancedFeature",
          "when": "workspaceFolderCount > 0"
        }
      ]
    }
  }
}

状态栏项目

typescript
class StatusBarManager {
  private statusBarItem: TraeAPI.StatusBarItem;
  
  constructor() {
    this.statusBarItem = TraeAPI.window.createStatusBarItem(
      TraeAPI.StatusBarAlignment.Right,
      100
    );
    this.statusBarItem.command = 'myExtension.showStatus';
    this.statusBarItem.show();
  }
  
  updateStatus(text: string, tooltip?: string) {
    this.statusBarItem.text = text;
    this.statusBarItem.tooltip = tooltip;
  }
  
  showProgress(message: string) {
    this.statusBarItem.text = `$(sync~spin) ${message}`;
  }
  
  showError(message: string) {
    this.statusBarItem.text = `$(error) ${message}`;
    this.statusBarItem.backgroundColor = new TraeAPI.ThemeColor('statusBarItem.errorBackground');
  }
  
  showSuccess(message: string) {
    this.statusBarItem.text = `$(check) ${message}`;
    this.statusBarItem.backgroundColor = undefined;
  }
  
  dispose() {
    this.statusBarItem.dispose();
  }
}

// 使用示例
const statusBar = new StatusBarManager();
statusBar.updateStatus('$(heart) My Extension', '点击查看状态');

// 注册状态命令
const statusCommand = TraeAPI.commands.registerCommand('myExtension.showStatus', () => {
  TraeAPI.window.showInformationMessage('扩展状态: 正常运行');
});

context.subscriptions.push(statusCommand, statusBar);

自定义视图

typescript
// 树视图提供程序
class MyTreeDataProvider implements TraeAPI.TreeDataProvider<TreeItem> {
  private _onDidChangeTreeData: TraeAPI.EventEmitter<TreeItem | undefined | null | void> = new TraeAPI.EventEmitter<TreeItem | undefined | null | void>();
  readonly onDidChangeTreeData: TraeAPI.Event<TreeItem | undefined | null | void> = this._onDidChangeTreeData.event;
  
  private data: TreeItem[] = [
    new TreeItem('项目 1', TraeAPI.TreeItemCollapsibleState.Collapsed),
    new TreeItem('项目 2', TraeAPI.TreeItemCollapsibleState.Collapsed),
    new TreeItem('项目 3', TraeAPI.TreeItemCollapsibleState.None)
  ];
  
  getTreeItem(element: TreeItem): TraeAPI.TreeItem {
    return element;
  }
  
  getChildren(element?: TreeItem): Thenable<TreeItem[]> {
    if (!element) {
      return Promise.resolve(this.data);
    }
    
    // 返回子项目
    return Promise.resolve([
      new TreeItem(`${element.label} - 子项 1`, TraeAPI.TreeItemCollapsibleState.None),
      new TreeItem(`${element.label} - 子项 2`, TraeAPI.TreeItemCollapsibleState.None)
    ]);
  }
  
  refresh(): void {
    this._onDidChangeTreeData.fire();
  }
  
  addItem(label: string): void {
    this.data.push(new TreeItem(label, TraeAPI.TreeItemCollapsibleState.None));
    this.refresh();
  }
}

class TreeItem extends TraeAPI.TreeItem {
  constructor(
    public readonly label: string,
    public readonly collapsibleState: TraeAPI.TreeItemCollapsibleState,
    public readonly command?: TraeAPI.Command
  ) {
    super(label, collapsibleState);
    this.tooltip = `${this.label} - 自定义树项`;
    this.description = '描述信息';
  }
  
  iconPath = {
    light: path.join(__filename, '..', '..', 'resources', 'light', 'dependency.svg'),
    dark: path.join(__filename, '..', '..', 'resources', 'dark', 'dependency.svg')
  };
  
  contextValue = 'treeItem';
}

// 注册树视图
const treeDataProvider = new MyTreeDataProvider();
const treeView = TraeAPI.window.createTreeView('myExtension.treeView', {
  treeDataProvider,
  showCollapseAll: true
});

// 树视图命令
const refreshCommand = TraeAPI.commands.registerCommand('myExtension.refreshTree', () => {
  treeDataProvider.refresh();
});

const addItemCommand = TraeAPI.commands.registerCommand('myExtension.addTreeItem', async () => {
  const label = await TraeAPI.window.showInputBox({
    prompt: '输入新项目名称'
  });
  
  if (label) {
    treeDataProvider.addItem(label);
  }
});

context.subscriptions.push(treeView, refreshCommand, addItemCommand);

Webview 面板

typescript
class WebviewManager {
  private panels: Map<string, TraeAPI.WebviewPanel> = new Map();
  
  createPanel(id: string, title: string, content: string): TraeAPI.WebviewPanel {
    // 检查是否已存在
    const existingPanel = this.panels.get(id);
    if (existingPanel) {
      existingPanel.reveal();
      return existingPanel;
    }
    
    // 创建新面板
    const panel = TraeAPI.window.createWebviewPanel(
      id,
      title,
      TraeAPI.ViewColumn.One,
      {
        enableScripts: true,
        retainContextWhenHidden: true,
        localResourceRoots: [TraeAPI.Uri.file(path.join(context.extensionPath, 'media'))]
      }
    );
    
    panel.webview.html = this.getWebviewContent(content);
    
    // 处理消息
    panel.webview.onDidReceiveMessage(
      message => this.handleWebviewMessage(panel, message),
      undefined,
      context.subscriptions
    );
    
    // 面板关闭时清理
    panel.onDidDispose(
      () => this.panels.delete(id),
      null,
      context.subscriptions
    );
    
    this.panels.set(id, panel);
    return panel;
  }
  
  private getWebviewContent(content: string): string {
    return `
      <!DOCTYPE html>
      <html lang="zh-CN">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>My Extension</title>
        <style>
          body {
            font-family: var(--vscode-font-family);
            font-size: var(--vscode-font-size);
            color: var(--vscode-foreground);
            background-color: var(--vscode-editor-background);
            padding: 20px;
          }
          
          .container {
            max-width: 800px;
            margin: 0 auto;
          }
          
          button {
            background-color: var(--vscode-button-background);
            color: var(--vscode-button-foreground);
            border: none;
            padding: 8px 16px;
            border-radius: 4px;
            cursor: pointer;
            margin: 4px;
          }
          
          button:hover {
            background-color: var(--vscode-button-hoverBackground);
          }
          
          input {
            background-color: var(--vscode-input-background);
            color: var(--vscode-input-foreground);
            border: 1px solid var(--vscode-input-border);
            padding: 8px;
            border-radius: 4px;
            width: 100%;
            margin: 4px 0;
          }
        </style>
      </head>
      <body>
        <div class="container">
          <h1>My Extension Panel</h1>
          <div id="content">${content}</div>
          
          <div>
            <input type="text" id="messageInput" placeholder="输入消息...">
            <button onclick="sendMessage()">发送消息</button>
            <button onclick="loadData()">加载数据</button>
          </div>
          
          <div id="output"></div>
        </div>
        
        <script>
          const vscode = acquireVsCodeApi();
          
          function sendMessage() {
            const input = document.getElementById('messageInput');
            const message = input.value;
            
            vscode.postMessage({
              command: 'sendMessage',
              text: message
            });
            
            input.value = '';
          }
          
          function loadData() {
            vscode.postMessage({
              command: 'loadData'
            });
          }
          
          window.addEventListener('message', event => {
            const message = event.data;
            const output = document.getElementById('output');
            
            switch (message.command) {
              case 'updateContent':
                document.getElementById('content').innerHTML = message.content;
                break;
              case 'showMessage':
                output.innerHTML += '<p>' + message.text + '</p>';
                break;
            }
          });
        </script>
      </body>
      </html>
    `;
  }
  
  private handleWebviewMessage(panel: TraeAPI.WebviewPanel, message: any) {
    switch (message.command) {
      case 'sendMessage':
        TraeAPI.window.showInformationMessage(`收到消息: ${message.text}`);
        panel.webview.postMessage({
          command: 'showMessage',
          text: `回复: ${message.text}`
        });
        break;
        
      case 'loadData':
        // 模拟加载数据
        setTimeout(() => {
          panel.webview.postMessage({
            command: 'updateContent',
            content: '<p>数据已加载: ' + new Date().toLocaleString() + '</p>'
          });
        }, 1000);
        break;
    }
  }
  
  dispose() {
    this.panels.forEach(panel => panel.dispose());
    this.panels.clear();
  }
}

// 使用示例
const webviewManager = new WebviewManager();

const openPanelCommand = TraeAPI.commands.registerCommand('myExtension.openPanel', () => {
  webviewManager.createPanel(
    'myExtensionPanel',
    'My Extension Panel',
    '<p>欢迎使用我的扩展!</p>'
  );
});

context.subscriptions.push(openPanelCommand, webviewManager);

配置管理

扩展配置

typescript
// package.json 中的配置贡献
{
  "contributes": {
    "configuration": {
      "title": "My Extension",
      "properties": {
        "myExtension.enabled": {
          "type": "boolean",
          "default": true,
          "description": "启用扩展功能"
        },
        "myExtension.apiUrl": {
          "type": "string",
          "default": "https://api.example.com",
          "description": "API 服务器地址"
        },
        "myExtension.timeout": {
          "type": "number",
          "default": 5000,
          "minimum": 1000,
          "maximum": 30000,
          "description": "请求超时时间(毫秒)"
        },
        "myExtension.features": {
          "type": "object",
          "default": {
            "autoSave": true,
            "notifications": true,
            "analytics": false
          },
          "properties": {
            "autoSave": {
              "type": "boolean",
              "description": "自动保存"
            },
            "notifications": {
              "type": "boolean",
              "description": "显示通知"
            },
            "analytics": {
              "type": "boolean",
              "description": "发送分析数据"
            }
          },
          "description": "功能设置"
        }
      }
    }
  }
}

配置访问和监听

typescript
class ConfigurationManager {
  private config: TraeAPI.WorkspaceConfiguration;
  private disposables: TraeAPI.Disposable[] = [];
  
  constructor() {
    this.config = TraeAPI.workspace.getConfiguration('myExtension');
    
    // 监听配置变化
    const configChangeListener = TraeAPI.workspace.onDidChangeConfiguration(e => {
      if (e.affectsConfiguration('myExtension')) {
        this.onConfigurationChanged();
      }
    });
    
    this.disposables.push(configChangeListener);
  }
  
  // 获取配置值
  get<T>(key: string, defaultValue?: T): T {
    return this.config.get<T>(key, defaultValue!);
  }
  
  // 更新配置
  async update<T>(key: string, value: T, target?: TraeAPI.ConfigurationTarget): Promise<void> {
    await this.config.update(key, value, target);
  }
  
  // 获取所有配置
  getAllSettings() {
    return {
      enabled: this.get<boolean>('enabled'),
      apiUrl: this.get<string>('apiUrl'),
      timeout: this.get<number>('timeout'),
      features: this.get<any>('features')
    };
  }
  
  // 重置配置
  async resetToDefaults(): Promise<void> {
    await this.update('enabled', undefined, TraeAPI.ConfigurationTarget.Global);
    await this.update('apiUrl', undefined, TraeAPI.ConfigurationTarget.Global);
    await this.update('timeout', undefined, TraeAPI.ConfigurationTarget.Global);
    await this.update('features', undefined, TraeAPI.ConfigurationTarget.Global);
  }
  
  // 验证配置
  validateConfiguration(): string[] {
    const errors: string[] = [];
    
    const apiUrl = this.get<string>('apiUrl');
    if (!apiUrl || !this.isValidUrl(apiUrl)) {
      errors.push('API URL 格式无效');
    }
    
    const timeout = this.get<number>('timeout');
    if (timeout < 1000 || timeout > 30000) {
      errors.push('超时时间必须在 1000-30000 毫秒之间');
    }
    
    return errors;
  }
  
  private onConfigurationChanged(): void {
    console.log('配置已更改:', this.getAllSettings());
    
    // 验证新配置
    const errors = this.validateConfiguration();
    if (errors.length > 0) {
      TraeAPI.window.showWarningMessage(`配置错误: ${errors.join(', ')}`);
    }
    
    // 重新初始化功能
    this.reinitializeFeatures();
  }
  
  private reinitializeFeatures(): void {
    const settings = this.getAllSettings();
    
    if (settings.enabled) {
      // 启用功能
      console.log('扩展功能已启用');
    } else {
      // 禁用功能
      console.log('扩展功能已禁用');
    }
  }
  
  private isValidUrl(url: string): boolean {
    try {
      new URL(url);
      return true;
    } catch {
      return false;
    }
  }
  
  dispose(): void {
    this.disposables.forEach(d => d.dispose());
  }
}

// 使用示例
const configManager = new ConfigurationManager();

// 获取配置
const isEnabled = configManager.get<boolean>('enabled');
const apiUrl = configManager.get<string>('apiUrl');
const features = configManager.get<any>('features');

console.log('扩展配置:', { isEnabled, apiUrl, features });

// 更新配置
await configManager.update('timeout', 10000, TraeAPI.ConfigurationTarget.Workspace);

context.subscriptions.push(configManager);

状态管理

Memento 存储

typescript
class StateManager {
  constructor(
    private globalState: TraeAPI.Memento,
    private workspaceState: TraeAPI.Memento
  ) {}
  
  // 用户偏好(全局)
  async saveUserPreferences(preferences: UserPreferences): Promise<void> {
    await this.globalState.update('userPreferences', preferences);
  }
  
  getUserPreferences(): UserPreferences {
    return this.globalState.get('userPreferences', {
      theme: 'auto',
      language: 'zh-CN',
      notifications: true
    });
  }
  
  // 项目设置(工作区)
  async saveProjectSettings(settings: ProjectSettings): Promise<void> {
    await this.workspaceState.update('projectSettings', settings);
  }
  
  getProjectSettings(): ProjectSettings {
    return this.workspaceState.get('projectSettings', {
      buildCommand: 'npm run build',
      testCommand: 'npm test',
      lintCommand: 'npm run lint'
    });
  }
  
  // 缓存管理
  async cacheData(key: string, data: any, ttl: number = 3600000): Promise<void> {
    const cacheItem = {
      data,
      timestamp: Date.now(),
      ttl
    };
    await this.globalState.update(`cache_${key}`, cacheItem);
  }
  
  getCachedData<T>(key: string): T | undefined {
    const cacheItem = this.globalState.get<CacheItem>(`cache_${key}`);
    
    if (!cacheItem) {
      return undefined;
    }
    
    // 检查是否过期
    if (Date.now() - cacheItem.timestamp > cacheItem.ttl) {
      this.globalState.update(`cache_${key}`, undefined);
      return undefined;
    }
    
    return cacheItem.data;
  }
  
  // 清理过期缓存
  async cleanExpiredCache(): Promise<void> {
    const keys = this.globalState.keys();
    const cacheKeys = keys.filter(key => key.startsWith('cache_'));
    
    for (const key of cacheKeys) {
      const cacheItem = this.globalState.get<CacheItem>(key);
      if (cacheItem && Date.now() - cacheItem.timestamp > cacheItem.ttl) {
        await this.globalState.update(key, undefined);
      }
    }
  }
  
  // 统计信息
  async incrementUsageCount(feature: string): Promise<void> {
    const currentCount = this.globalState.get<number>(`usage_${feature}`, 0);
    await this.globalState.update(`usage_${feature}`, currentCount + 1);
  }
  
  getUsageCount(feature: string): number {
    return this.globalState.get<number>(`usage_${feature}`, 0);
  }
  
  getAllUsageStats(): Record<string, number> {
    const keys = this.globalState.keys();
    const usageKeys = keys.filter(key => key.startsWith('usage_'));
    const stats: Record<string, number> = {};
    
    for (const key of usageKeys) {
      const feature = key.replace('usage_', '');
      stats[feature] = this.getUsageCount(feature);
    }
    
    return stats;
  }
}

interface UserPreferences {
  theme: 'light' | 'dark' | 'auto';
  language: string;
  notifications: boolean;
}

interface ProjectSettings {
  buildCommand: string;
  testCommand: string;
  lintCommand: string;
}

interface CacheItem {
  data: any;
  timestamp: number;
  ttl: number;
}

// 使用示例
const stateManager = new StateManager(
  context.globalState,
  context.workspaceState
);

// 保存用户偏好
await stateManager.saveUserPreferences({
  theme: 'dark',
  language: 'zh-CN',
  notifications: true
});

// 缓存 API 响应
await stateManager.cacheData('apiResponse', { data: 'some data' }, 1800000); // 30分钟

// 统计功能使用
await stateManager.incrementUsageCount('codeGeneration');

// 定期清理缓存
setInterval(() => {
  stateManager.cleanExpiredCache();
}, 3600000); // 每小时清理一次

扩展间通信

API 导出

typescript
// 定义公共 API 接口
export interface MyExtensionAPI {
  getVersion(): string;
  processData(data: any): Promise<any>;
  registerCallback(callback: (data: any) => void): TraeAPI.Disposable;
  getStatus(): ExtensionStatus;
}

export interface ExtensionStatus {
  isActive: boolean;
  lastUpdate: Date;
  errorCount: number;
}

// 实现 API
class MyExtensionImpl implements MyExtensionAPI {
  private callbacks: ((data: any) => void)[] = [];
  private status: ExtensionStatus = {
    isActive: true,
    lastUpdate: new Date(),
    errorCount: 0
  };
  
  getVersion(): string {
    return '1.0.0';
  }
  
  async processData(data: any): Promise<any> {
    try {
      // 处理数据
      const result = await this.performProcessing(data);
      
      // 通知回调
      this.callbacks.forEach(callback => {
        try {
          callback(result);
        } catch (error) {
          console.error('回调执行错误:', error);
        }
      });
      
      this.status.lastUpdate = new Date();
      return result;
    } catch (error) {
      this.status.errorCount++;
      throw error;
    }
  }
  
  registerCallback(callback: (data: any) => void): TraeAPI.Disposable {
    this.callbacks.push(callback);
    
    return {
      dispose: () => {
        const index = this.callbacks.indexOf(callback);
        if (index >= 0) {
          this.callbacks.splice(index, 1);
        }
      }
    };
  }
  
  getStatus(): ExtensionStatus {
    return { ...this.status };
  }
  
  private async performProcessing(data: any): Promise<any> {
    // 模拟数据处理
    await new Promise(resolve => setTimeout(resolve, 100));
    return { processed: true, original: data, timestamp: Date.now() };
  }
}

// 在 activate 函数中导出 API
export function activate(context: TraeAPI.ExtensionContext): MyExtensionAPI {
  const extensionImpl = new MyExtensionImpl();
  
  // 注册命令等...
  
  return extensionImpl;
}

使用其他扩展的 API

typescript
// 获取其他扩展的 API
async function useOtherExtensionAPI() {
  // 获取扩展
  const otherExtension = TraeAPI.extensions.getExtension<MyExtensionAPI>('publisher.my-extension');
  
  if (!otherExtension) {
    TraeAPI.window.showErrorMessage('未找到依赖的扩展');
    return;
  }
  
  // 激活扩展(如果尚未激活)
  if (!otherExtension.isActive) {
    await otherExtension.activate();
  }
  
  // 使用 API
  const api = otherExtension.exports;
  if (api) {
    console.log('扩展版本:', api.getVersion());
    
    // 注册回调
    const disposable = api.registerCallback((data) => {
      console.log('收到数据:', data);
    });
    
    // 处理数据
    const result = await api.processData({ test: 'data' });
    console.log('处理结果:', result);
    
    // 获取状态
    const status = api.getStatus();
    console.log('扩展状态:', status);
    
    // 清理
    context.subscriptions.push(disposable);
  }
}

// 扩展依赖管理
class ExtensionDependencyManager {
  private dependencies: Map<string, any> = new Map();
  
  async loadDependency<T>(extensionId: string): Promise<T | undefined> {
    // 检查缓存
    if (this.dependencies.has(extensionId)) {
      return this.dependencies.get(extensionId);
    }
    
    // 获取扩展
    const extension = TraeAPI.extensions.getExtension<T>(extensionId);
    if (!extension) {
      console.warn(`扩展 ${extensionId} 未安装`);
      return undefined;
    }
    
    // 激活扩展
    if (!extension.isActive) {
      try {
        await extension.activate();
      } catch (error) {
        console.error(`激活扩展 ${extensionId} 失败:`, error);
        return undefined;
      }
    }
    
    // 缓存 API
    const api = extension.exports;
    this.dependencies.set(extensionId, api);
    
    return api;
  }
  
  getDependency<T>(extensionId: string): T | undefined {
    return this.dependencies.get(extensionId);
  }
  
  async checkDependencies(requiredExtensions: string[]): Promise<string[]> {
    const missing: string[] = [];
    
    for (const extensionId of requiredExtensions) {
      const extension = TraeAPI.extensions.getExtension(extensionId);
      if (!extension) {
        missing.push(extensionId);
      }
    }
    
    return missing;
  }
  
  async promptInstallMissing(missingExtensions: string[]): Promise<void> {
    if (missingExtensions.length === 0) return;
    
    const message = `此扩展需要以下依赖: ${missingExtensions.join(', ')}`;
    const action = await TraeAPI.window.showWarningMessage(
      message,
      '安装依赖',
      '取消'
    );
    
    if (action === '安装依赖') {
      for (const extensionId of missingExtensions) {
        await TraeAPI.commands.executeCommand('workbench.extensions.installExtension', extensionId);
      }
    }
  }
}

// 使用示例
const dependencyManager = new ExtensionDependencyManager();

// 检查依赖
const requiredExtensions = ['ms-python.python', 'ms-vscode.vscode-typescript-next'];
const missing = await dependencyManager.checkDependencies(requiredExtensions);

if (missing.length > 0) {
  await dependencyManager.promptInstallMissing(missing);
} else {
  // 加载依赖
  const pythonApi = await dependencyManager.loadDependency('ms-python.python');
  if (pythonApi) {
    // 使用 Python 扩展 API
  }
}

文件系统访问

文件操作

typescript
class FileSystemManager {
  // 读取文件
  async readFile(uri: TraeAPI.Uri): Promise<string> {
    try {
      const data = await TraeAPI.workspace.fs.readFile(uri);
      return Buffer.from(data).toString('utf8');
    } catch (error) {
      console.error('读取文件失败:', error);
      throw error;
    }
  }
  
  // 写入文件
  async writeFile(uri: TraeAPI.Uri, content: string): Promise<void> {
    try {
      const data = Buffer.from(content, 'utf8');
      await TraeAPI.workspace.fs.writeFile(uri, data);
    } catch (error) {
      console.error('写入文件失败:', error);
      throw error;
    }
  }
  
  // 创建目录
  async createDirectory(uri: TraeAPI.Uri): Promise<void> {
    try {
      await TraeAPI.workspace.fs.createDirectory(uri);
    } catch (error) {
      if (error.code !== 'FileExists') {
        console.error('创建目录失败:', error);
        throw error;
      }
    }
  }
  
  // 删除文件或目录
  async delete(uri: TraeAPI.Uri, options?: { recursive?: boolean; useTrash?: boolean }): Promise<void> {
    try {
      await TraeAPI.workspace.fs.delete(uri, options);
    } catch (error) {
      console.error('删除失败:', error);
      throw error;
    }
  }
  
  // 复制文件
  async copy(source: TraeAPI.Uri, target: TraeAPI.Uri, options?: { overwrite?: boolean }): Promise<void> {
    try {
      await TraeAPI.workspace.fs.copy(source, target, options);
    } catch (error) {
      console.error('复制失败:', error);
      throw error;
    }
  }
  
  // 重命名/移动文件
  async rename(source: TraeAPI.Uri, target: TraeAPI.Uri, options?: { overwrite?: boolean }): Promise<void> {
    try {
      await TraeAPI.workspace.fs.rename(source, target, options);
    } catch (error) {
      console.error('重命名失败:', error);
      throw error;
    }
  }
  
  // 获取文件状态
  async stat(uri: TraeAPI.Uri): Promise<TraeAPI.FileStat> {
    try {
      return await TraeAPI.workspace.fs.stat(uri);
    } catch (error) {
      console.error('获取文件状态失败:', error);
      throw error;
    }
  }
  
  // 读取目录
  async readDirectory(uri: TraeAPI.Uri): Promise<[string, TraeAPI.FileType][]> {
    try {
      return await TraeAPI.workspace.fs.readDirectory(uri);
    } catch (error) {
      console.error('读取目录失败:', error);
      throw error;
    }
  }
  
  // 检查文件是否存在
  async exists(uri: TraeAPI.Uri): Promise<boolean> {
    try {
      await this.stat(uri);
      return true;
    } catch {
      return false;
    }
  }
  
  // 递归读取目录
  async readDirectoryRecursive(uri: TraeAPI.Uri, filter?: (name: string, type: TraeAPI.FileType) => boolean): Promise<TraeAPI.Uri[]> {
    const results: TraeAPI.Uri[] = [];
    
    try {
      const entries = await this.readDirectory(uri);
      
      for (const [name, type] of entries) {
        if (filter && !filter(name, type)) {
          continue;
        }
        
        const childUri = TraeAPI.Uri.joinPath(uri, name);
        results.push(childUri);
        
        if (type === TraeAPI.FileType.Directory) {
          const childResults = await this.readDirectoryRecursive(childUri, filter);
          results.push(...childResults);
        }
      }
    } catch (error) {
      console.error('递归读取目录失败:', error);
    }
    
    return results;
  }
  
  // 查找文件
  async findFiles(pattern: string, exclude?: string): Promise<TraeAPI.Uri[]> {
    return await TraeAPI.workspace.findFiles(pattern, exclude);
  }
  
  // 监听文件变化
  watchFiles(pattern: TraeAPI.GlobPattern, callback: (uri: TraeAPI.Uri) => void): TraeAPI.Disposable {
    const watcher = TraeAPI.workspace.createFileSystemWatcher(pattern);
    
    const disposables = [
      watcher.onDidCreate(callback),
      watcher.onDidChange(callback),
      watcher.onDidDelete(callback),
      watcher
    ];
    
    return {
      dispose: () => {
        disposables.forEach(d => d.dispose());
      }
    };
  }
}

// 使用示例
const fsManager = new FileSystemManager();

// 读取配置文件
const configUri = TraeAPI.Uri.file('/path/to/config.json');
if (await fsManager.exists(configUri)) {
  const configContent = await fsManager.readFile(configUri);
  const config = JSON.parse(configContent);
  console.log('配置:', config);
}

// 创建项目结构
const projectUri = TraeAPI.Uri.file('/path/to/new-project');
await fsManager.createDirectory(projectUri);
await fsManager.createDirectory(TraeAPI.Uri.joinPath(projectUri, 'src'));
await fsManager.createDirectory(TraeAPI.Uri.joinPath(projectUri, 'tests'));

// 创建文件
const packageJsonUri = TraeAPI.Uri.joinPath(projectUri, 'package.json');
const packageJsonContent = JSON.stringify({
  name: 'my-project',
  version: '1.0.0',
  description: 'My awesome project'
}, null, 2);
await fsManager.writeFile(packageJsonUri, packageJsonContent);

// 查找 TypeScript 文件
const tsFiles = await fsManager.findFiles('**/*.ts', '**/node_modules/**');
console.log('TypeScript 文件:', tsFiles.map(uri => uri.fsPath));

// 监听文件变化
const watcher = fsManager.watchFiles('**/*.{js,ts}', (uri) => {
  console.log('文件变化:', uri.fsPath);
});

context.subscriptions.push(watcher);

高级功能

自定义编辑器

typescript
// 自定义编辑器提供程序
class CustomEditorProvider implements TraeAPI.CustomTextEditorProvider {
  public static register(context: TraeAPI.ExtensionContext): TraeAPI.Disposable {
    const provider = new CustomEditorProvider(context);
    const providerRegistration = TraeAPI.window.registerCustomEditorProvider(
      'myExtension.customEditor',
      provider
    );
    return providerRegistration;
  }
  
  constructor(private readonly context: TraeAPI.ExtensionContext) {}
  
  public async resolveCustomTextEditor(
    document: TraeAPI.TextDocument,
    webviewPanel: TraeAPI.WebviewPanel,
    _token: TraeAPI.CancellationToken
  ): Promise<void> {
    // 设置 webview 选项
    webviewPanel.webview.options = {
      enableScripts: true,
    };
    
    // 设置初始内容
    webviewPanel.webview.html = this.getHtmlForWebview(webviewPanel.webview, document);
    
    // 处理来自 webview 的消息
    webviewPanel.webview.onDidReceiveMessage(e => {
      switch (e.type) {
        case 'update':
          this.updateTextDocument(document, e.content);
          return;
        case 'save':
          document.save();
          return;
      }
    });
    
    // 监听文档变化
    const changeDocumentSubscription = TraeAPI.workspace.onDidChangeTextDocument(e => {
      if (e.document.uri.toString() === document.uri.toString()) {
        this.updateWebview(webviewPanel, document);
      }
    });
    
    // 清理
    webviewPanel.onDidDispose(() => {
      changeDocumentSubscription.dispose();
    });
  }
  
  private getHtmlForWebview(webview: TraeAPI.Webview, document: TraeAPI.TextDocument): string {
    const content = document.getText();
    
    return `
      <!DOCTYPE html>
      <html lang="zh-CN">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>自定义编辑器</title>
        <style>
          body {
            font-family: var(--vscode-font-family);
            font-size: var(--vscode-font-size);
            color: var(--vscode-foreground);
            background-color: var(--vscode-editor-background);
            margin: 0;
            padding: 20px;
          }
          
          .editor {
            width: 100%;
            height: 400px;
            border: 1px solid var(--vscode-input-border);
            background-color: var(--vscode-input-background);
            color: var(--vscode-input-foreground);
            padding: 10px;
            font-family: var(--vscode-editor-font-family);
            font-size: var(--vscode-editor-font-size);
            resize: vertical;
          }
          
          .toolbar {
            margin-bottom: 10px;
          }
          
          button {
            background-color: var(--vscode-button-background);
            color: var(--vscode-button-foreground);
            border: none;
            padding: 6px 12px;
            border-radius: 3px;
            cursor: pointer;
            margin-right: 5px;
          }
          
          button:hover {
            background-color: var(--vscode-button-hoverBackground);
          }
        </style>
      </head>
      <body>
        <div class="toolbar">
          <button onclick="save()">保存</button>
          <button onclick="format()">格式化</button>
          <button onclick="validate()">验证</button>
        </div>
        
        <textarea class="editor" id="editor">${content}</textarea>
        
        <script>
          const vscode = acquireVsCodeApi();
          const editor = document.getElementById('editor');
          
          // 监听内容变化
          editor.addEventListener('input', () => {
            vscode.postMessage({
              type: 'update',
              content: editor.value
            });
          });
          
          function save() {
            vscode.postMessage({ type: 'save' });
          }
          
          function format() {
            try {
              const formatted = JSON.stringify(JSON.parse(editor.value), null, 2);
              editor.value = formatted;
              vscode.postMessage({
                type: 'update',
                content: formatted
              });
            } catch (error) {
              alert('格式化失败: ' + error.message);
            }
          }
          
          function validate() {
            try {
              JSON.parse(editor.value);
              alert('JSON 格式正确');
            } catch (error) {
              alert('JSON 格式错误: ' + error.message);
            }
          }
          
          // 监听来自扩展的消息
          window.addEventListener('message', event => {
            const message = event.data;
            switch (message.type) {
              case 'update':
                editor.value = message.content;
                break;
            }
          });
        </script>
      </body>
      </html>
    `;
  }
  
  private updateTextDocument(document: TraeAPI.TextDocument, content: string) {
    const edit = new TraeAPI.WorkspaceEdit();
    edit.replace(
      document.uri,
      new TraeAPI.Range(0, 0, document.lineCount, 0),
      content
    );
    TraeAPI.workspace.applyEdit(edit);
  }
  
  private updateWebview(panel: TraeAPI.WebviewPanel, document: TraeAPI.TextDocument) {
    panel.webview.postMessage({
      type: 'update',
      content: document.getText()
    });
  }
}

// 注册自定义编辑器
const customEditorProvider = CustomEditorProvider.register(context);
context.subscriptions.push(customEditorProvider);

语言服务器集成

typescript
// 语言客户端
import {
  LanguageClient,
  LanguageClientOptions,
  ServerOptions,
  TransportKind
} from 'vscode-languageclient/node';

class LanguageServerManager {
  private client: LanguageClient | undefined;
  
  async startLanguageServer(context: TraeAPI.ExtensionContext): Promise<void> {
    // 服务器选项
    const serverModule = context.asAbsolutePath(
      path.join('server', 'out', 'server.js')
    );
    
    const debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] };
    
    const serverOptions: ServerOptions = {
      run: { module: serverModule, transport: TransportKind.ipc },
      debug: {
        module: serverModule,
        transport: TransportKind.ipc,
        options: debugOptions
      }
    };
    
    // 客户端选项
    const clientOptions: LanguageClientOptions = {
      documentSelector: [{ scheme: 'file', language: 'mylanguage' }],
      synchronize: {
        fileEvents: TraeAPI.workspace.createFileSystemWatcher('**/.clientrc')
      }
    };
    
    // 创建语言客户端
    this.client = new LanguageClient(
      'myLanguageServer',
      'My Language Server',
      serverOptions,
      clientOptions
    );
    
    // 启动客户端
    await this.client.start();
    
    console.log('语言服务器已启动');
  }
  
  async stopLanguageServer(): Promise<void> {
    if (this.client) {
      await this.client.stop();
      this.client = undefined;
      console.log('语言服务器已停止');
    }
  }
  
  isRunning(): boolean {
    return this.client !== undefined;
  }
  
  async sendRequest<T>(method: string, params?: any): Promise<T> {
    if (!this.client) {
      throw new Error('语言服务器未运行');
    }
    
    return await this.client.sendRequest(method, params);
  }
  
  sendNotification(method: string, params?: any): void {
    if (this.client) {
      this.client.sendNotification(method, params);
    }
  }
}

// 使用示例
const languageServerManager = new LanguageServerManager();

// 启动语言服务器
await languageServerManager.startLanguageServer(context);

// 发送自定义请求
const result = await languageServerManager.sendRequest('custom/analyze', {
  uri: 'file:///path/to/file.mylang'
});

// 清理
context.subscriptions.push({
  dispose: () => languageServerManager.stopLanguageServer()
});

测试

单元测试

typescript
// test/extension.test.ts
import * as assert from 'assert';
import * as TraeAPI from 'trae';
import * as myExtension from '../src/extension';

suite('Extension Test Suite', () => {
  TraeAPI.window.showInformationMessage('开始运行测试!');
  
  test('扩展激活测试', async () => {
    // 模拟扩展上下文
    const context = {
      subscriptions: [],
      workspaceState: {
        get: () => undefined,
        update: () => Promise.resolve()
      },
      globalState: {
        get: () => undefined,
        update: () => Promise.resolve()
      }
    } as any;
    
    // 激活扩展
    const result = await myExtension.activate(context);
    
    // 验证结果
    assert.ok(result);
    assert.ok(context.subscriptions.length > 0);
  });
  
  test('命令注册测试', async () => {
    // 获取所有命令
    const commands = await TraeAPI.commands.getCommands();
    
    // 验证自定义命令是否注册
    assert.ok(commands.includes('myExtension.helloWorld'));
  });
  
  test('配置读取测试', () => {
    const config = TraeAPI.workspace.getConfiguration('myExtension');
    const enabled = config.get<boolean>('enabled');
    
    // 验证配置
    assert.strictEqual(typeof enabled, 'boolean');
  });
});

集成测试

typescript
// test/integration.test.ts
import * as assert from 'assert';
import * as TraeAPI from 'trae';
import * as path from 'path';

suite('Integration Test Suite', () => {
  test('文件操作集成测试', async () => {
    const workspaceFolder = TraeAPI.workspace.workspaceFolders?.[0];
    if (!workspaceFolder) {
      assert.fail('需要打开工作区');
    }
    
    const testFileUri = TraeAPI.Uri.joinPath(workspaceFolder.uri, 'test.txt');
    const testContent = 'Hello, World!';
    
    // 写入文件
    await TraeAPI.workspace.fs.writeFile(testFileUri, Buffer.from(testContent));
    
    // 读取文件
    const readContent = await TraeAPI.workspace.fs.readFile(testFileUri);
    const contentString = Buffer.from(readContent).toString();
    
    // 验证内容
    assert.strictEqual(contentString, testContent);
    
    // 清理
    await TraeAPI.workspace.fs.delete(testFileUri);
  });
  
  test('编辑器集成测试', async () => {
    // 创建新文档
    const document = await TraeAPI.workspace.openTextDocument({
      content: 'function test() {\n  console.log("test");\n}',
      language: 'javascript'
    });
    
    // 打开编辑器
    const editor = await TraeAPI.window.showTextDocument(document);
    
    // 验证编辑器
    assert.ok(editor);
    assert.strictEqual(editor.document.languageId, 'javascript');
    assert.ok(editor.document.getText().includes('function test'));
  });
});

发布

扩展打包

typescript
// 使用 vsce 打包扩展
// package.json 配置
{
  "name": "my-extension",
  "displayName": "My Extension",
  "description": "我的扩展描述",
  "version": "1.0.0",
  "publisher": "my-publisher",
  "engines": {
    "trae": "^1.0.0"
  },
  "categories": [
    "Other"
  ],
  "activationEvents": [
    "onCommand:myExtension.activate"
  ],
  "main": "./out/extension.js",
  "contributes": {
    "commands": [
      {
        "command": "myExtension.helloWorld",
        "title": "Hello World"
      }
    ]
  },
  "scripts": {
    "vscode:prepublish": "npm run compile",
    "compile": "tsc -p ./",
    "package": "vsce package",
    "publish": "vsce publish"
  },
  "devDependencies": {
    "@types/trae": "^1.0.0",
    "typescript": "^4.0.0",
    "vsce": "^2.0.0"
  }
}

发布流程

bash
# 安装 vsce
npm install -g vsce

# 登录发布者账户
vsce login <publisher-name>

# 打包扩展
vsce package

# 发布扩展
vsce publish

# 发布特定版本
vsce publish 1.0.1

# 发布预发布版本
vsce publish --pre-release

最佳实践

性能优化

typescript
// 延迟加载
class LazyFeatureManager {
  private features: Map<string, () => Promise<any>> = new Map();
  private loadedFeatures: Map<string, any> = new Map();
  
  registerFeature(name: string, loader: () => Promise<any>): void {
    this.features.set(name, loader);
  }
  
  async getFeature<T>(name: string): Promise<T> {
    // 检查是否已加载
    if (this.loadedFeatures.has(name)) {
      return this.loadedFeatures.get(name);
    }
    
    // 延迟加载
    const loader = this.features.get(name);
    if (!loader) {
      throw new Error(`功能 ${name} 未注册`);
    }
    
    const feature = await loader();
    this.loadedFeatures.set(name, feature);
    return feature;
  }
}

// 使用示例
const featureManager = new LazyFeatureManager();

// 注册功能
featureManager.registerFeature('heavyFeature', async () => {
  const { HeavyFeature } = await import('./heavy-feature');
  return new HeavyFeature();
});

// 按需加载
const heavyFeature = await featureManager.getFeature('heavyFeature');

错误处理

typescript
class ErrorHandler {
  private static instance: ErrorHandler;
  private errorCount: number = 0;
  private maxErrors: number = 10;
  
  static getInstance(): ErrorHandler {
    if (!ErrorHandler.instance) {
      ErrorHandler.instance = new ErrorHandler();
    }
    return ErrorHandler.instance;
  }
  
  handleError(error: Error, context?: string): void {
    this.errorCount++;
    
    console.error(`错误 [${context || 'Unknown'}]:`, error);
    
    // 记录错误
    this.logError(error, context);
    
    // 显示用户友好的错误消息
    this.showUserError(error, context);
    
    // 检查错误频率
    if (this.errorCount > this.maxErrors) {
      this.handleTooManyErrors();
    }
  }
  
  private logError(error: Error, context?: string): void {
    // 发送到日志服务
    const errorInfo = {
      message: error.message,
      stack: error.stack,
      context,
      timestamp: new Date().toISOString(),
      version: TraeAPI.extensions.getExtension('my-publisher.my-extension')?.packageJSON.version
    };
    
    // 这里可以发送到远程日志服务
    console.log('错误日志:', errorInfo);
  }
  
  private showUserError(error: Error, context?: string): void {
    let message = '操作失败';
    
    if (context) {
      message += `: ${context}`;
    }
    
    TraeAPI.window.showErrorMessage(message, '查看详情').then(selection => {
      if (selection === '查看详情') {
        TraeAPI.window.showErrorMessage(error.message);
      }
    });
  }
  
  private handleTooManyErrors(): void {
    TraeAPI.window.showWarningMessage(
      '扩展遇到多个错误,建议重启 IDE',
      '重启',
      '忽略'
    ).then(selection => {
      if (selection === '重启') {
        TraeAPI.commands.executeCommand('workbench.action.reloadWindow');
      }
    });
  }
  
  resetErrorCount(): void {
    this.errorCount = 0;
  }
}

// 全局错误处理装饰器
function handleErrors(target: any, propertyName: string, descriptor: PropertyDescriptor) {
  const method = descriptor.value;
  
  descriptor.value = async function (...args: any[]) {
    try {
      return await method.apply(this, args);
    } catch (error) {
      ErrorHandler.getInstance().handleError(error as Error, `${target.constructor.name}.${propertyName}`);
      throw error;
    }
  };
}

// 使用示例
class MyService {
  @handleErrors
  async processData(data: any): Promise<any> {
    // 可能抛出错误的代码
    if (!data) {
      throw new Error('数据不能为空');
    }
    
    return { processed: true, data };
  }
}

国际化

typescript
// package.json 中的国际化配置
{
  "contributes": {
    "languages": [
      {
        "id": "zh-cn",
        "aliases": ["Chinese (Simplified)", "中文(简体)"],
        "configuration": "./language-configuration.json"
      }
    ]
  }
}

// 国际化管理器
class I18nManager {
  private messages: Map<string, any> = new Map();
  private currentLocale: string = 'zh-CN';
  
  constructor(private context: TraeAPI.ExtensionContext) {
    this.loadMessages();
  }
  
  private async loadMessages(): Promise<void> {
    try {
      // 获取当前语言
      this.currentLocale = TraeAPI.env.language;
      
      // 加载对应的语言文件
      const messagesPath = path.join(
        this.context.extensionPath,
        'i18n',
        `${this.currentLocale}.json`
      );
      
      const messagesUri = TraeAPI.Uri.file(messagesPath);
      const messagesContent = await TraeAPI.workspace.fs.readFile(messagesUri);
      const messages = JSON.parse(Buffer.from(messagesContent).toString());
      
      this.messages.set(this.currentLocale, messages);
    } catch (error) {
      // 回退到默认语言
      console.warn('加载语言文件失败,使用默认语言:', error);
      this.loadDefaultMessages();
    }
  }
  
  private loadDefaultMessages(): void {
    const defaultMessages = {
      'hello': '你好',
      'goodbye': '再见',
      'error.fileNotFound': '文件未找到',
      'error.invalidInput': '输入无效',
      'success.saved': '保存成功',
      'confirm.delete': '确定要删除吗?'
    };
    
    this.messages.set('zh-CN', defaultMessages);
  }
  
  t(key: string, ...args: any[]): string {
    const messages = this.messages.get(this.currentLocale) || this.messages.get('zh-CN') || {};
    let message = messages[key] || key;
    
    // 替换占位符
    if (args.length > 0) {
      message = message.replace(/\{(\d+)\}/g, (match: string, index: string) => {
        const argIndex = parseInt(index, 10);
        return args[argIndex] !== undefined ? args[argIndex] : match;
      });
    }
    
    return message;
  }
  
  getCurrentLocale(): string {
    return this.currentLocale;
  }
  
  async changeLocale(locale: string): Promise<void> {
    this.currentLocale = locale;
    await this.loadMessages();
  }
}

// 使用示例
const i18n = new I18nManager(context);

// 获取翻译文本
const helloMessage = i18n.t('hello');
const errorMessage = i18n.t('error.fileNotFound');
const confirmMessage = i18n.t('confirm.delete');

// 带参数的翻译
const welcomeMessage = i18n.t('welcome.user', 'John'); // "欢迎,{0}!" -> "欢迎,John!"

// 在命令中使用
TraeAPI.commands.registerCommand('myExtension.showMessage', () => {
  TraeAPI.window.showInformationMessage(i18n.t('success.saved'));
});

完整扩展示例

typescript
// extension.ts - 完整的扩展示例
import * as TraeAPI from 'trae';
import * as path from 'path';

// 扩展主类
class MyExtension {
  private statusBar: TraeAPI.StatusBarItem;
  private outputChannel: TraeAPI.OutputChannel;
  private configManager: ConfigurationManager;
  private stateManager: StateManager;
  private disposables: TraeAPI.Disposable[] = [];
  
  constructor(private context: TraeAPI.ExtensionContext) {
    this.statusBar = TraeAPI.window.createStatusBarItem(TraeAPI.StatusBarAlignment.Right, 100);
    this.outputChannel = TraeAPI.window.createOutputChannel('My Extension');
    this.configManager = new ConfigurationManager();
    this.stateManager = new StateManager(context.globalState, context.workspaceState);
  }
  
  async activate(): Promise<void> {
    this.outputChannel.appendLine('扩展正在激活...');
    
    // 注册命令
    this.registerCommands();
    
    // 设置状态栏
    this.setupStatusBar();
    
    // 监听事件
    this.setupEventListeners();
    
    // 初始化功能
    await this.initializeFeatures();
    
    this.outputChannel.appendLine('扩展激活完成');
  }
  
  private registerCommands(): void {
    const commands = [
      TraeAPI.commands.registerCommand('myExtension.helloWorld', this.helloWorld.bind(this)),
      TraeAPI.commands.registerCommand('myExtension.showStatus', this.showStatus.bind(this)),
      TraeAPI.commands.registerCommand('myExtension.openSettings', this.openSettings.bind(this)),
      TraeAPI.commands.registerCommand('myExtension.processFile', this.processFile.bind(this))
    ];
    
    this.disposables.push(...commands);
  }
  
  private setupStatusBar(): void {
    this.statusBar.text = '$(heart) My Extension';
    this.statusBar.tooltip = '点击查看扩展状态';
    this.statusBar.command = 'myExtension.showStatus';
    this.statusBar.show();
    
    this.disposables.push(this.statusBar);
  }
  
  private setupEventListeners(): void {
    // 监听文档变化
    const docChangeListener = TraeAPI.workspace.onDidChangeTextDocument(e => {
      this.onDocumentChanged(e);
    });
    
    // 监听配置变化
    const configChangeListener = TraeAPI.workspace.onDidChangeConfiguration(e => {
      if (e.affectsConfiguration('myExtension')) {
        this.onConfigurationChanged();
      }
    });
    
    this.disposables.push(docChangeListener, configChangeListener);
  }
  
  private async initializeFeatures(): Promise<void> {
    // 加载用户偏好
    const preferences = this.stateManager.getUserPreferences();
    this.outputChannel.appendLine(`用户偏好: ${JSON.stringify(preferences)}`);
    
    // 检查配置
    const errors = this.configManager.validateConfiguration();
    if (errors.length > 0) {
      TraeAPI.window.showWarningMessage(`配置错误: ${errors.join(', ')}`);
    }
  }
  
  // 命令实现
  private async helloWorld(): Promise<void> {
    const message = 'Hello World from My Extension!';
    TraeAPI.window.showInformationMessage(message);
    this.outputChannel.appendLine(message);
    
    // 统计使用次数
    await this.stateManager.incrementUsageCount('helloWorld');
  }
  
  private async showStatus(): Promise<void> {
    const stats = this.stateManager.getAllUsageStats();
    const config = this.configManager.getAllSettings();
    
    const statusInfo = {
      version: this.context.extension.packageJSON.version,
      isActive: this.context.extension.isActive,
      usageStats: stats,
      configuration: config
    };
    
    this.outputChannel.appendLine('扩展状态:');
    this.outputChannel.appendLine(JSON.stringify(statusInfo, null, 2));
    this.outputChannel.show();
  }
  
  private async openSettings(): Promise<void> {
    await TraeAPI.commands.executeCommand('workbench.action.openSettings', 'myExtension');
  }
  
  private async processFile(uri?: TraeAPI.Uri): Promise<void> {
    const targetUri = uri || TraeAPI.window.activeTextEditor?.document.uri;
    
    if (!targetUri) {
      TraeAPI.window.showWarningMessage('请选择一个文件');
      return;
    }
    
    try {
      const content = await TraeAPI.workspace.fs.readFile(targetUri);
      const text = Buffer.from(content).toString();
      
      // 处理文件内容
      const processedText = text.toUpperCase();
      
      // 保存处理结果
      const outputUri = TraeAPI.Uri.file(targetUri.fsPath + '.processed');
      await TraeAPI.workspace.fs.writeFile(outputUri, Buffer.from(processedText));
      
      TraeAPI.window.showInformationMessage(`文件已处理: ${outputUri.fsPath}`);
    } catch (error) {
      TraeAPI.window.showErrorMessage(`处理文件失败: ${error}`);
    }
  }
  
  // 事件处理
  private onDocumentChanged(e: TraeAPI.TextDocumentChangeEvent): void {
    if (e.document.languageId === 'javascript' || e.document.languageId === 'typescript') {
      this.statusBar.text = '$(sync~spin) 分析中...';
      
      // 延迟分析
      setTimeout(() => {
        this.statusBar.text = '$(check) 分析完成';
      }, 1000);
    }
  }
  
  private onConfigurationChanged(): void {
    this.outputChannel.appendLine('配置已更改,重新初始化...');
    this.initializeFeatures();
  }
  
  // 清理资源
  dispose(): void {
    this.disposables.forEach(d => d.dispose());
    this.outputChannel.dispose();
  }
}

// 扩展激活函数
export async function activate(context: TraeAPI.ExtensionContext): Promise<void> {
  const extension = new MyExtension(context);
  await extension.activate();
  
  context.subscriptions.push(extension);
}

// 扩展停用函数
export function deactivate(): void {
  console.log('扩展已停用');
}

这个完整的扩展 API 参考涵盖了 Trae IDE 扩展开发的所有重要方面,包括基础概念、高级功能、最佳实践和完整示例。通过这些 API,您可以创建功能强大且用户友好的扩展。

您的终极 AI 驱动 IDE 学习指南