Debugger API 
Debugger APIは、Traeでアプリケーションのデバッグとデバッグセッションの管理機能を提供します。
概要 
Debugger APIでは以下のことができます:
- デバッグセッションの開始と停止
- ブレークポイントの設定と管理
- コード実行のステップ実行
- 変数とコールスタックの検査
- デバッグコンテキストでの式の評価
- デバッグイベントと通知の処理
- デバッグアダプターとプロトコルの設定
- デバッグコンソール出力の管理
基本的な使用方法 
デバッグセッションマネージャー 
typescript
import { TraeAPI } from '@trae/api';
// デバッグセッションマネージャー
class DebugSessionManager {
  private sessions: Map<string, TraeAPI.DebugSession> = new Map();
  private breakpoints: Map<string, TraeAPI.Breakpoint[]> = new Map();
  private eventEmitter = new TraeAPI.EventEmitter<DebugEvent>();
  private disposables: TraeAPI.Disposable[] = [];
  private debugAdapters: Map<string, DebugAdapterDescriptor> = new Map();
  private activeSession: TraeAPI.DebugSession | undefined;
  private debugConsole: DebugConsole;
  constructor() {
    this.debugConsole = new DebugConsole();
    this.setupBuiltinAdapters();
    this.setupEventHandlers();
  }
  // デバッグセッションの開始
  async startDebugging(
    folder: TraeAPI.WorkspaceFolder | undefined,
    nameOrConfiguration: string | TraeAPI.DebugConfiguration,
    parentSessionOrOptions?: TraeAPI.DebugSession | TraeAPI.DebugSessionOptions
  ): Promise<boolean> {
    try {
      let config: TraeAPI.DebugConfiguration;
      
      if (typeof nameOrConfiguration === 'string') {
        // 名前で設定を取得
        const configs = TraeAPI.workspace.getConfiguration('launch', folder?.uri);
        const launchConfig = configs.get('configurations', []);
        const foundConfig = launchConfig.find((c: any) => c.name === nameOrConfiguration);
        
        if (!foundConfig) {
          throw new Error(`デバッグ設定 '${nameOrConfiguration}' が見つかりません`);
        }
        
        config = foundConfig;
      } else {
        config = nameOrConfiguration;
      }
      // 設定の解決
      const resolvedConfig = await this.resolveDebugConfiguration(folder, config);
      if (!resolvedConfig) {
        throw new Error('デバッグ設定の解決に失敗しました');
      }
      // デバッグセッションの作成
      const sessionId = this.generateSessionId();
      const session = await this.createDebugSession(sessionId, resolvedConfig, folder);
      
      this.sessions.set(sessionId, session);
      this.activeSession = session;
      
      // セッションの開始
      await session.start();
      
      this.eventEmitter.fire({ type: 'sessionStarted', session });
      
      return true;
    } catch (error) {
      this.eventEmitter.fire({ type: 'sessionStartError', error });
      TraeAPI.window.showErrorMessage(`デバッグの開始に失敗しました: ${error}`);
      return false;
    }
  }
  // デバッグセッションの停止
  async stopDebugging(session?: TraeAPI.DebugSession): Promise<void> {
    const targetSession = session || this.activeSession;
    
    if (!targetSession) {
      return;
    }
    try {
      await targetSession.stop();
      
      this.sessions.delete(targetSession.id);
      
      if (this.activeSession === targetSession) {
        this.activeSession = undefined;
      }
      
      this.eventEmitter.fire({ type: 'sessionStopped', session: targetSession });
    } catch (error) {
      this.eventEmitter.fire({ type: 'sessionStopError', session: targetSession, error });
      throw error;
    }
  }
  // ブレークポイント管理
  async addBreakpoints(uri: TraeAPI.Uri, breakpoints: TraeAPI.SourceBreakpoint[]): Promise<TraeAPI.Breakpoint[]> {
    const uriString = uri.toString();
    const existingBreakpoints = this.breakpoints.get(uriString) || [];
    
    const newBreakpoints: TraeAPI.Breakpoint[] = [];
    
    for (const bp of breakpoints) {
      const breakpoint: TraeAPI.Breakpoint = {
        id: this.generateBreakpointId(),
        enabled: true,
        condition: bp.condition,
        hitCondition: bp.hitCondition,
        logMessage: bp.logMessage,
        location: new TraeAPI.Location(uri, new TraeAPI.Position(bp.line - 1, 0))
      };
      
      newBreakpoints.push(breakpoint);
    }
    
    const allBreakpoints = [...existingBreakpoints, ...newBreakpoints];
    this.breakpoints.set(uriString, allBreakpoints);
    
    // アクティブセッションのブレークポイントを更新
    if (this.activeSession) {
      await this.updateSessionBreakpoints(this.activeSession, uri, allBreakpoints);
    }
    
    this.eventEmitter.fire({ type: 'breakpointsAdded', uri, breakpoints: newBreakpoints });
    
    return newBreakpoints;
  }
  async removeBreakpoints(uri: TraeAPI.Uri, breakpoints: TraeAPI.Breakpoint[]): Promise<void> {
    const uriString = uri.toString();
    const existingBreakpoints = this.breakpoints.get(uriString) || [];
    
    const breakpointIds = new Set(breakpoints.map(bp => bp.id));
    const remainingBreakpoints = existingBreakpoints.filter(bp => !breakpointIds.has(bp.id));
    
    this.breakpoints.set(uriString, remainingBreakpoints);
    
    // アクティブセッションのブレークポイントを更新
    if (this.activeSession) {
      await this.updateSessionBreakpoints(this.activeSession, uri, remainingBreakpoints);
    }
    
    this.eventEmitter.fire({ type: 'breakpointsRemoved', uri, breakpoints });
  }
  async toggleBreakpoint(uri: TraeAPI.Uri, line: number): Promise<void> {
    const uriString = uri.toString();
    const breakpoints = this.breakpoints.get(uriString) || [];
    
    const existingIndex = breakpoints.findIndex(bp => 
      bp.location.range.start.line === line - 1
    );
    
    if (existingIndex >= 0) {
      // 既存のブレークポイントを削除
      const removed = breakpoints.splice(existingIndex, 1);
      await this.removeBreakpoints(uri, removed);
    } else {
      // 新しいブレークポイントを追加
      await this.addBreakpoints(uri, [{ line }]);
    }
  }
  getBreakpoints(uri?: TraeAPI.Uri): TraeAPI.Breakpoint[] {
    if (uri) {
      return this.breakpoints.get(uri.toString()) || [];
    }
    
    const allBreakpoints: TraeAPI.Breakpoint[] = [];
    for (const breakpoints of this.breakpoints.values()) {
      allBreakpoints.push(...breakpoints);
    }
    
    return allBreakpoints;
  }
  // デバッグ実行制御
  async continue(session?: TraeAPI.DebugSession): Promise<void> {
    const targetSession = session || this.activeSession;
    if (!targetSession) {
      throw new Error('アクティブなデバッグセッションがありません');
    }
    await targetSession.customRequest('continue', {
      threadId: targetSession.threadId
    });
    
    this.eventEmitter.fire({ type: 'continued', session: targetSession });
  }
  async stepOver(session?: TraeAPI.DebugSession): Promise<void> {
    const targetSession = session || this.activeSession;
    if (!targetSession) {
      throw new Error('アクティブなデバッグセッションがありません');
    }
    await targetSession.customRequest('next', {
      threadId: targetSession.threadId
    });
    
    this.eventEmitter.fire({ type: 'stepOver', session: targetSession });
  }
  async stepInto(session?: TraeAPI.DebugSession): Promise<void> {
    const targetSession = session || this.activeSession;
    if (!targetSession) {
      throw new Error('アクティブなデバッグセッションがありません');
    }
    await targetSession.customRequest('stepIn', {
      threadId: targetSession.threadId
    });
    
    this.eventEmitter.fire({ type: 'stepInto', session: targetSession });
  }
  async stepOut(session?: TraeAPI.DebugSession): Promise<void> {
    const targetSession = session || this.activeSession;
    if (!targetSession) {
      throw new Error('アクティブなデバッグセッションがありません');
    }
    await targetSession.customRequest('stepOut', {
      threadId: targetSession.threadId
    });
    
    this.eventEmitter.fire({ type: 'stepOut', session: targetSession });
  }
  async pause(session?: TraeAPI.DebugSession): Promise<void> {
    const targetSession = session || this.activeSession;
    if (!targetSession) {
      throw new Error('アクティブなデバッグセッションがありません');
    }
    await targetSession.customRequest('pause', {
      threadId: targetSession.threadId
    });
    
    this.eventEmitter.fire({ type: 'paused', session: targetSession });
  }
  // 変数の検査
  async getVariables(session?: TraeAPI.DebugSession): Promise<DebugVariable[]> {
    const targetSession = session || this.activeSession;
    if (!targetSession) {
      throw new Error('アクティブなデバッグセッションがありません');
    }
    try {
      const stackTrace = await targetSession.customRequest('stackTrace', {
        threadId: targetSession.threadId
      });
      
      if (!stackTrace.stackFrames || stackTrace.stackFrames.length === 0) {
        return [];
      }
      
      const topFrame = stackTrace.stackFrames[0];
      const scopes = await targetSession.customRequest('scopes', {
        frameId: topFrame.id
      });
      
      const variables: DebugVariable[] = [];
      
      for (const scope of scopes.scopes) {
        const scopeVariables = await targetSession.customRequest('variables', {
          variablesReference: scope.variablesReference
        });
        
        for (const variable of scopeVariables.variables) {
          variables.push({
            name: variable.name,
            value: variable.value,
            type: variable.type,
            scope: scope.name,
            variablesReference: variable.variablesReference
          });
        }
      }
      
      return variables;
    } catch (error) {
      this.eventEmitter.fire({ type: 'variableInspectionError', session: targetSession, error });
      throw error;
    }
  }
  async evaluateExpression(
    expression: string,
    context: 'watch' | 'repl' | 'hover' = 'repl',
    session?: TraeAPI.DebugSession
  ): Promise<DebugEvaluationResult> {
    const targetSession = session || this.activeSession;
    if (!targetSession) {
      throw new Error('アクティブなデバッグセッションがありません');
    }
    try {
      const result = await targetSession.customRequest('evaluate', {
        expression,
        context,
        frameId: targetSession.frameId
      });
      
      return {
        result: result.result,
        type: result.type,
        variablesReference: result.variablesReference,
        namedVariables: result.namedVariables,
        indexedVariables: result.indexedVariables
      };
    } catch (error) {
      this.eventEmitter.fire({ type: 'evaluationError', expression, error });
      throw error;
    }
  }
  // コールスタック
  async getCallStack(session?: TraeAPI.DebugSession): Promise<TraeAPI.StackFrame[]> {
    const targetSession = session || this.activeSession;
    if (!targetSession) {
      throw new Error('アクティブなデバッグセッションがありません');
    }
    try {
      const stackTrace = await targetSession.customRequest('stackTrace', {
        threadId: targetSession.threadId
      });
      
      return stackTrace.stackFrames || [];
    } catch (error) {
      this.eventEmitter.fire({ type: 'callStackError', session: targetSession, error });
      throw error;
    }
  }
  // デバッグアダプター管理
  registerDebugAdapterDescriptorFactory(
    debugType: string,
    factory: TraeAPI.DebugAdapterDescriptorFactory
  ): TraeAPI.Disposable {
    this.debugAdapters.set(debugType, { factory, type: debugType });
    
    this.eventEmitter.fire({ type: 'adapterRegistered', debugType });
    
    return {
      dispose: () => {
        this.debugAdapters.delete(debugType);
        this.eventEmitter.fire({ type: 'adapterUnregistered', debugType });
      }
    };
  }
  // デバッグ設定
  private async resolveDebugConfiguration(
    folder: TraeAPI.WorkspaceFolder | undefined,
    config: TraeAPI.DebugConfiguration
  ): Promise<TraeAPI.DebugConfiguration | undefined> {
    // 変数置換を適用
    const resolvedConfig = this.substituteVariables(config, folder);
    
    // 設定の検証
    if (!resolvedConfig.type) {
      throw new Error('デバッグ設定にはtypeを指定する必要があります');
    }
    
    if (!resolvedConfig.request) {
      throw new Error('デバッグ設定にはrequestタイプを指定する必要があります');
    }
    
    return resolvedConfig;
  }
  private substituteVariables(
    config: TraeAPI.DebugConfiguration,
    folder: TraeAPI.WorkspaceFolder | undefined
  ): TraeAPI.DebugConfiguration {
    const configString = JSON.stringify(config);
    const workspaceRoot = folder?.uri.fsPath || TraeAPI.workspace.workspaceFolders?.[0]?.uri.fsPath || '';
    
    const substituted = configString
      .replace(/\$\{workspaceFolder\}/g, workspaceRoot)
      .replace(/\$\{workspaceRoot\}/g, workspaceRoot)
      .replace(/\$\{file\}/g, TraeAPI.window.activeTextEditor?.document.uri.fsPath || '')
      .replace(/\$\{fileBasename\}/g, TraeAPI.window.activeTextEditor?.document.fileName || '')
      .replace(/\$\{fileDirname\}/g, TraeAPI.window.activeTextEditor?.document.uri.fsPath.split('/').slice(0, -1).join('/') || '');
    
    return JSON.parse(substituted);
  }
  private async createDebugSession(
    id: string,
    config: TraeAPI.DebugConfiguration,
    folder: TraeAPI.WorkspaceFolder | undefined
  ): Promise<TraeAPI.DebugSession> {
    const adapter = this.debugAdapters.get(config.type);
    if (!adapter) {
      throw new Error(`タイプ ${config.type} のデバッグアダプターが見つかりません`);
    }
    // デバッグセッションの作成
    const session = new DebugSessionImpl(id, config, folder, adapter);
    
    // セッションイベントハンドラーの設定
    session.onDidTerminate(() => {
      this.sessions.delete(id);
      if (this.activeSession === session) {
        this.activeSession = undefined;
      }
      this.eventEmitter.fire({ type: 'sessionTerminated', session });
    });
    
    return session;
  }
  private async updateSessionBreakpoints(
    session: TraeAPI.DebugSession,
    uri: TraeAPI.Uri,
    breakpoints: TraeAPI.Breakpoint[]
  ): Promise<void> {
    try {
      await session.customRequest('setBreakpoints', {
        source: { path: uri.fsPath },
        breakpoints: breakpoints.map(bp => ({
          line: bp.location.range.start.line + 1,
          condition: bp.condition,
          hitCondition: bp.hitCondition,
          logMessage: bp.logMessage
        }))
      });
    } catch (error) {
      console.warn('セッションブレークポイントの更新に失敗しました:', error);
    }
  }
  private setupBuiltinAdapters(): void {
    // 組み込みデバッグアダプターの登録
    this.registerDebugAdapterDescriptorFactory('node', {
      createDebugAdapterDescriptor: (session, executable) => {
        return new TraeAPI.DebugAdapterExecutable('node', [
          require.resolve('node-debug-adapter')
        ]);
      }
    });
  }
  private setupEventHandlers(): void {
    // デバッグイベントハンドラーの設定
  }
  private generateSessionId(): string {
    return `debug-session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  }
  private generateBreakpointId(): string {
    return `breakpoint-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  }
  // ゲッター
  get activeSessions(): TraeAPI.DebugSession[] {
    return Array.from(this.sessions.values());
  }
  get activeDebugSession(): TraeAPI.DebugSession | undefined {
    return this.activeSession;
  }
  // イベント処理
  onDidStartDebugSession(listener: (session: TraeAPI.DebugSession) => void): TraeAPI.Disposable {
    return this.eventEmitter.event(event => {
      if (event.type === 'sessionStarted') {
        listener(event.session!);
      }
    });
  }
  onDidTerminateDebugSession(listener: (session: TraeAPI.DebugSession) => void): TraeAPI.Disposable {
    return this.eventEmitter.event(event => {
      if (event.type === 'sessionTerminated') {
        listener(event.session!);
      }
    });
  }
  onDidChangeBreakpoints(listener: (event: BreakpointEvent) => void): TraeAPI.Disposable {
    return this.eventEmitter.event(event => {
      if (event.type === 'breakpointsAdded' || event.type === 'breakpointsRemoved') {
        listener(event as BreakpointEvent);
      }
    });
  }
  // リソースの解放
  dispose(): void {
    // すべてのセッションを停止
    for (const session of this.sessions.values()) {
      session.stop().catch(console.error);
    }
    this.sessions.clear();
    
    // ブレークポイントをクリア
    this.breakpoints.clear();
    
    // アダプターを解放
    this.debugAdapters.clear();
    
    // その他のリソースを解放
    this.disposables.forEach(d => d.dispose());
    this.disposables = [];
    
    this.eventEmitter.dispose();
    this.debugConsole.dispose();
  }
}
// デバッグコンソールの実装
class DebugConsole {
  private outputChannel: TraeAPI.OutputChannel;
  private history: string[] = [];
  private maxHistorySize = 1000;
  constructor() {
    this.outputChannel = TraeAPI.window.createOutputChannel('Debug Console');
  }
  append(text: string): void {
    this.outputChannel.append(text);
    this.addToHistory(text);
  }
  appendLine(text: string): void {
    this.outputChannel.appendLine(text);
    this.addToHistory(text + '\n');
  }
  clear(): void {
    this.outputChannel.clear();
    this.history = [];
  }
  show(): void {
    this.outputChannel.show();
  }
  private addToHistory(text: string): void {
    this.history.push(text);
    if (this.history.length > this.maxHistorySize) {
      this.history.shift();
    }
  }
  getHistory(): string[] {
    return [...this.history];
  }
  dispose(): void {
    this.outputChannel.dispose();
    this.history = [];
  }
}
// デバッグセッションの実装
class DebugSessionImpl implements TraeAPI.DebugSession {
  private _onDidTerminate = new TraeAPI.EventEmitter<void>();
  private _threadId = 1;
  private _frameId = 0;
  constructor(
    public readonly id: string,
    public readonly configuration: TraeAPI.DebugConfiguration,
    public readonly workspaceFolder: TraeAPI.WorkspaceFolder | undefined,
    private adapter: DebugAdapterDescriptor
  ) {}
  get type(): string {
    return this.configuration.type;
  }
  get name(): string {
    return this.configuration.name;
  }
  get threadId(): number {
    return this._threadId;
  }
  get frameId(): number {
    return this._frameId;
  }
  get onDidTerminate(): TraeAPI.Event<void> {
    return this._onDidTerminate.event;
  }
  async start(): Promise<void> {
    // デバッグアダプターを開始してセッションを初期化
    console.log(`デバッグセッションを開始: ${this.name}`);
  }
  async stop(): Promise<void> {
    // デバッグセッションを停止
    console.log(`デバッグセッションを停止: ${this.name}`);
    this._onDidTerminate.fire();
  }
  async customRequest(command: string, args?: any): Promise<any> {
    // デバッグアダプターにカスタムリクエストを送信
    console.log(`デバッグリクエスト: ${command}`, args);
    return {};
  }
}
// デバッグセッションマネージャーの初期化
const debugSessionManager = new DebugSessionManager();インターフェース定義 
typescript
// デバッグイベントタイプ
interface DebugEvent {
  type: 'sessionStarted' | 'sessionStopped' | 'sessionTerminated' | 'sessionStartError' | 'sessionStopError' |
        'breakpointsAdded' | 'breakpointsRemoved' | 'continued' | 'stepOver' | 'stepInto' | 'stepOut' | 'paused' |
        'variableInspectionError' | 'evaluationError' | 'callStackError' | 'adapterRegistered' | 'adapterUnregistered';
  session?: TraeAPI.DebugSession;
  uri?: TraeAPI.Uri;
  breakpoints?: TraeAPI.Breakpoint[];
  expression?: string;
  debugType?: string;
  error?: any;
}
// ブレークポイントイベント
interface BreakpointEvent {
  type: 'breakpointsAdded' | 'breakpointsRemoved';
  uri: TraeAPI.Uri;
  breakpoints: TraeAPI.Breakpoint[];
}
// デバッグ変数
interface DebugVariable {
  name: string;
  value: string;
  type?: string;
  scope: string;
  variablesReference: number;
}
// デバッグ評価結果
interface DebugEvaluationResult {
  result: string;
  type?: string;
  variablesReference: number;
  namedVariables?: number;
  indexedVariables?: number;
}
// デバッグアダプター記述子
interface DebugAdapterDescriptor {
  factory: TraeAPI.DebugAdapterDescriptorFactory;
  type: string;
}API リファレンス 
DebugSessionManager 
デバッグセッションの管理とブレークポイントの制御を行うメインクラスです。
メソッド 
- startDebugging(folder?, nameOrConfiguration, parentSessionOrOptions?)- デバッグセッションを開始
- stopDebugging(session?)- デバッグセッションを停止
- addBreakpoints(uri, breakpoints)- ブレークポイントを追加
- removeBreakpoints(uri, breakpoints)- ブレークポイントを削除
- toggleBreakpoint(uri, line)- ブレークポイントの切り替え
- getBreakpoints(uri?)- ブレークポイントの取得
- continue(session?)- 実行を継続
- stepOver(session?)- ステップオーバー
- stepInto(session?)- ステップイン
- stepOut(session?)- ステップアウト
- pause(session?)- 実行を一時停止
- getVariables(session?)- 変数の取得
- evaluateExpression(expression, context?, session?)- 式の評価
- getCallStack(session?)- コールスタックの取得
- registerDebugAdapterDescriptorFactory(debugType, factory)- デバッグアダプターファクトリーの登録
プロパティ 
- activeSessions- アクティブなセッションの配列
- activeDebugSession- 現在アクティブなデバッグセッション
イベント 
- onDidStartDebugSession(listener)- デバッグセッション開始イベント
- onDidTerminateDebugSession(listener)- デバッグセッション終了イベント
- onDidChangeBreakpoints(listener)- ブレークポイント変更イベント
DebugConsole 
デバッグコンソールの出力を管理するクラスです。
メソッド 
- append(text)- テキストを追加
- appendLine(text)- 行を追加
- clear()- コンソールをクリア
- show()- コンソールを表示
- getHistory()- 履歴を取得
最佳実践 
デバッグ設定の管理 
typescript
// launch.json設定の例
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Program",
      "program": "${workspaceFolder}/src/index.js",
      "args": ["--verbose"],
      "env": {
        "NODE_ENV": "development"
      },
      "console": "integratedTerminal",
      "sourceMaps": true,
      "outFiles": ["${workspaceFolder}/dist/**/*.js"]
    }
  ]
}エラー処理 
typescript
try {
  await debugSessionManager.startDebugging(workspaceFolder, 'Launch Program');
} catch (error) {
  TraeAPI.window.showErrorMessage(`デバッグの開始に失敗: ${error.message}`);
}リソース管理 
typescript
// 拡張機能の非アクティブ化時にリソースを適切に解放
export function deactivate() {
  debugSessionManager.dispose();
}関連API 
- Debugging API - 包括的なデバッグ機能
- Commands API - コマンドの登録と実行
- Editor API - エディターの制御
- Workspace API - ワークスペースの管理