5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Serena 全体アーキテクチャ概要

5
Last updated at Posted at 2025-10-25

このドキュメントは、Serenaの全体アーキテクチャを包括的に解説します。システム設計、コンポーネント構成、データフロー、実装パターンなど、Serenaの技術的な側面を網羅的に説明します。

目次

  1. システム概要
  2. アーキテクチャ全体像
  3. レイヤー構造
  4. 主要コンポーネント詳細
  5. ツールシステム
  6. Language Server Protocol統合
  7. MCPサーバー統合
  8. データフローと実行フロー
  9. 設定システム
  10. メモリシステム
  11. パフォーマンス最適化
  12. 開発とカスタマイズ

システム概要

Serenaとは

Serenaは、LLM(大規模言語モデル)をコードベース上で直接動作する高機能エージェントに変換する、オープンソースのコーディングエージェントツールキットです。

コア価値提案:

従来のエージェント:
❌ ファイル全体を読み込む
❌ grepやテキスト置換で操作
❌ 大量のトークンを消費

Serena:
✅ シンボルレベルでピンポイント操作
✅ LSPによる意味解析
✅ トークン効率96%向上
✅ 20以上の言語に対応

主な特徴

  • 🚀 IDE相当の機能: IDEのようなセマンティックコード検索・編集機能を提供
  • 🔓 LLM・フレームワーク非依存: 特定のLLM、フレームワーク、インターフェースに依存しない
  • 🛠️ シンボルレベル操作: コードをシンボルレベルで抽出・編集し、関係構造を活用
  • 💰 無料・オープンソース: 完全に無料で利用可能
  • 🌐 MCP対応: Model Context Protocol (MCP) サーバーとして動作可能

対応プログラミング言語(20以上)

Python          TypeScript/JavaScript   PHP (Intelephense)
Go (gopls)      Rust (rust-analyzer)    C/C++ (clangd)
C#              Ruby (ruby-lsp)         Swift (sourcekit-lsp)
Kotlin          Java (eclipse.jdt.ls)   Clojure (clojure-lsp)
Dart            Bash                    Lua (lua-language-server)
Nix (nixd)      Elixir (NextLS)         Erlang (erlang_ls)
Zig (ZLS)       AL (Dynamics 365)       R (languageserver)

アーキテクチャ全体像

システム構成図

デュアルレイヤー設計


レイヤー構造

Layer 1: クライアントインターフェース層

責務: LLMクライアントとの通信

機能:
- MCP Protocol / OpenAPI による標準化された通信
- リクエスト/レスポンスのシリアライゼーション
- 認証・セッション管理

対応クライアント:

  • Claude Desktop, Claude Code
  • Codex, Gemini-CLI, Qwen3-Coder
  • VSCode, Cursor, Windsurf
  • Cline, Roo Code
  • OpenWebUI, Jan, Agno

Layer 2: Serena MCP Server層

責務: リクエストのルーティングとバリデーション

# src/serena/mcp_server.py
class SerenaMCPServer:
    """
    MCPリクエストを受け取り、SerenaAgentに委譲
    """
    - リクエストのルーティング
    - パラメータバリデーション
    - タイムアウト制御
    - ロギングとダッシュボード機能

通信プロトコル:

  1. stdio (標準入出力) - デフォルト
  2. Streamable HTTP - HTTPベースの双方向通信
  3. SSE - 非推奨

Layer 3: SerenaAgent - コアオーケストレーション層

責務: システム全体の中核となるオーケストレーター

# src/serena/agent.py
class SerenaAgent:
    """
    プロジェクト管理、ツール実行、状態管理を統括
    """
    - プロジェクトのアクティベーションと管理
    - ツールレジストリとディスパッチ
    - コンテキストモード管理
    - メモリ管理
    - 言語サーバーのライフサイクル管理

主要メソッド:

def activate_project(self, project_identifier) -> str
def execute_task(self, task_callable) -> T
def get_tool(self, tool_class) -> Tool
def switch_modes(self, mode_names) -> None
def get_available_tools(self) -> AvailableTools

Layer 4: Tool実行層

責務: 各種操作の実装

ツールカテゴリ:
├── シンボルツール (symbol_tools.py)
│   - find_symbol, find_referencing_symbols
│   - get_symbols_overview
│   - replace_symbol_body
│
├── ファイルツール (file_tools.py)
│   - read_file, write_file
│   - search_for_pattern, replace_regex
│
├── コマンドツール (cmd_tools.py)
│   - execute_shell_command
│
├── メモリツール (memory_tools.py)
│   - write_memory, read_memory, list_memories
│
├── 設定ツール (config_tools.py)
│   - activate_project, switch_modes
│
└── ワークフローツール (workflow_tools.py)
    - onboarding, prepare_for_new_conversation

Layer 5: SolidLSP層(言語サーバー抽象化)

責備: 言語サーバーとの通信とキャッシング

# src/solidlsp/ls.py
class SolidLanguageServer(ABC):
    """
    複数言語サーバーの統一インターフェース
    """
    - 言語サーバーとの通信
    - シンボル情報のキャッシング
    - ドキュメント同期管理
    - エラーハンドリングと自動リトライ

主要メソッド:

def request_document_symbols(self, relative_path, include_body) -> tuple
def request_definition(self, relative_path, line, character) -> list
def request_references(self, relative_path, line, character) -> list
def start_server(self) -> ContextManager
def save_cache(self) -> None

Layer 6: 言語サーバープロセス層

責務: 各言語専用の言語サーバー実行

言語サーバー階層:
SolidLanguageServer (Abstract Base)
├── PythonLanguageServer (Pyright)
├── TypeScriptLanguageServer (typescript-language-server)
├── RustLanguageServer (rust-analyzer)
├── GoLanguageServer (gopls)
├── JavaLanguageServer (eclipse.jdt.ls)
├── PHPLanguageServer (Intelephense)
└── ... (他16言語)

主要コンポーネント詳細

1. SerenaAgent (src/serena/agent.py)

役割: システム全体の中核となるオーケストレーター

ライフサイクル:

状態管理:

class SerenaAgent:
    _active_project: Project | None
    _active_project_lock: threading.Lock
    _active_ls: SolidLanguageServer | None
    _memories_manager: MemoriesManager | None
    _tool_registry: dict[str, Tool]
    _context: Context
    _modes: list[Mode]

2. SolidLanguageServer (src/solidlsp/ls.py)

役割: 言語サーバープロトコル(LSP)の統一インターフェース

キャッシング戦略:

self._document_symbols_cache: dict[
    str,  # ファイルパス
    tuple[
        str,  # ファイルハッシュ (MD5)
        tuple[
            list[UnifiedSymbolInformation],  # シンボル情報
            list[UnifiedSymbolInformation]   # ボディ含むシンボル情報
        ]
    ]
]

キャッシュフロー:

キャッシュの無効化条件:

  • ファイル内容変更時(ハッシュ変更)
  • 明示的なキャッシュクリア
  • 言語サーバーバージョン変更時

3. Project Management (src/serena/project.py)

役割: プロジェクト固有の設定と操作の管理

プロジェクト構成:

project_root/
├── .serena/
│   ├── project.yml          # プロジェクト設定
│   ├── cache/               # 言語サーバーキャッシュ
│   │   └── PythonLanguageServer.pkl
│   ├── memories/            # メモリファイル(Markdown)
│   │   ├── architecture.md
│   │   ├── how_to_test.md
│   │   └── how_to_build.md
│   └── logs/                # ログファイル
├── src/                     # ソースコード
└── ...

主要機能:

class Project:
    def gather_source_files(self) -> list[str]
        """gitignoreを尊重してソースファイルを収集"""

    def is_ignored_path(self, path) -> bool
        """パスが無視対象かどうか判定"""

    def create_language_server(self) -> SolidLanguageServer
        """プロジェクトの言語に応じたLSを作成"""

    def search_text_in_project(self, pattern, ...) -> dict
        """正規表現でプロジェクト全体を検索"""

4. Memory System (agent.py: MemoriesManager)

役割: プロジェクト知識の永続化と取得

メモリの種類:

.serena/memories/
├── project_structure.md      # プロジェクト構造
├── how_to_test.md            # テスト実行方法
├── how_to_build.md           # ビルド手順
├── architecture.md           # アーキテクチャ概要
├── key_symbols.md            # 重要なシンボル
├── coding_conventions.md     # コーディング規約
└── task_progress.md          # タスク進捗(継続作業用)

メモリライフサイクル:

1. オンボーディング時に自動作成
   └─ プロジェクト構造、テスト方法等を分析

2. 作業中に手動/自動で追加
   └─ 設計決定、規約、進捗状況等

3. 新セッション開始時に読み込み
   └─ list_memories → read_memory

4. 必要に応じて更新・削除
   └─ 情報が古くなった場合

5. Tool System (src/serena/tools/)

ツールベースクラス階層:

Tool (Component)
├─ ToolMarkerSymbolicRead      # シンボル読み取り系
├─ ToolMarkerCanEdit           # 編集系
├─ ToolMarkerOptional          # オプショナル(デフォルト無効)
└─ ToolMarkerDoesNotRequireActiveProject  # プロジェクト不要

ツール実装パターン:

class MyTool(Tool, ToolMarkerCanEdit):
    """
    ツールの説明。LLMが読む。
    """

    def apply(
        self,
        param1: str,
        param2: int = 10,
        max_answer_chars: int = -1
    ) -> str:
        """
        詳細な説明。

        :param param1: パラメータ1
        :param param2: パラメータ2
        :param max_answer_chars: 出力文字数制限
        :return: 実行結果
        """
        # 1. パラメータ検証
        # 2. プロジェクトルート取得
        project_root = self.get_project_root()

        # 3. 実際の処理
        result = perform_operation(param1, param2)

        # 4. 文字数制限適用
        return self._limit_length(result, max_answer_chars)

ツール実行フロー:


ツールシステム

デフォルト有効ツール(27個)

シンボルツール

# find_symbol: グローバル/ローカルシンボル検索
find_symbol(
    name_path="/MyClass/myMethod",  # シンボルパス
    depth=1,                         # 子要素の深さ
    include_body=True,               # ボディを含む
    include_kinds=[5, 6]             # クラス、メソッドのみ
)

# find_referencing_symbols: シンボル参照検索
find_referencing_symbols(
    name_path="/authenticate",
    relative_path="src/auth.py"
)

# get_symbols_overview: ファイル内シンボル一覧
get_symbols_overview(relative_path="src/main.py")

# replace_symbol_body: シンボル定義の置換
replace_symbol_body(
    name_path="/MyClass/foo",
    relative_path="src/main.py",
    new_body="def foo(self):\n    pass"
)

# insert_after_symbol: シンボル後に挿入
insert_after_symbol(
    name_path="/MyClass",
    relative_path="src/main.py",
    content="    def new_method(self):\n        pass"
)

# insert_before_symbol: シンボル前に挿入
insert_before_symbol(
    name_path="/MyClass",
    relative_path="src/main.py",
    content="# Important class\n"
)

シンボルカインド(LSP標準):

1=file, 2=module, 3=namespace, 4=package, 5=class, 6=method,
7=property, 8=field, 9=constructor, 10=enum, 11=interface,
12=function, 13=variable, 14=constant, 15=string, 16=number,
17=boolean, 18=array, 19=object, 20=key, 21=null,
22=enum member, 23=struct, 24=event, 25=operator, 26=type parameter

名前パスマッチング:

"method"           → method, class/method, class/nested/method
"class/method"     → class/method, nested/class/method (但しmethodは単独NG)
"/class/method"    → class/method のみ(絶対パス)

ファイルツール

# read_file: ファイル読み取り
read_file(relative_path="src/main.py", max_lines=100)

# create_text_file: ファイル作成・上書き
create_text_file(
    relative_path="src/new.py",
    content="def hello():\n    print('Hello')"
)

# search_for_pattern: 正規表現パターン検索
search_for_pattern(
    pattern=r"def\s+\w+",
    include_glob="**/*.py",
    context_lines=2
)

# replace_regex: 正規表現置換
replace_regex(
    relative_path="src/main.py",
    pattern=r"old_name",
    replacement="new_name"
)

# list_dir: ディレクトリ一覧
list_dir(relative_path="src/", recursive=True)

# find_file: ファイル検索
find_file(
    pattern="**/test_*.py",
    relative_path="tests/"
)

メモリツール

# write_memory: メモリ保存
write_memory(
    memory_name="api_conventions.md",
    content="# API設計原則\n..."
)

# read_memory: メモリ読み取り
read_memory(memory_file_name="api_conventions.md")

# list_memories: メモリ一覧
list_memories()  # → ["architecture.md", "how_to_test.md", ...]

# delete_memory: メモリ削除
delete_memory(memory_file_name="outdated_info.md")

ワークフローツール

# onboarding: プロジェクトオンボーディング
onboarding()  # 自動でプロジェクトを分析してメモリ作成

# check_onboarding_performed: オンボーディング状態確認
check_onboarding_performed()

# prepare_for_new_conversation: 新規会話準備
prepare_for_new_conversation()  # 進捗サマリーを生成

# 思考ツール(LLMの自己反省用)
think_about_task_adherence()
think_about_collected_information()
think_about_whether_you_are_done()

設定ツール

# activate_project: プロジェクトアクティベーション
activate_project(project_identifier="/path/to/project")

# switch_modes: モード切り替え
switch_modes(mode_names=["planning", "one-shot"])

コマンドツール

# execute_shell_command: シェルコマンド実行
execute_shell_command(
    command="pytest tests/",
    working_dir=".",
    timeout=60
)

オプションツール(9個)

デフォルトでは無効、明示的に有効化が必要:

# delete_lines: 行削除
# insert_at_line: 行位置に挿入
# replace_lines: 行範囲置換
# get_current_config: 現在の設定表示
# initial_instructions: 初期指示取得
# remove_project: プロジェクト削除
# restart_language_server: 言語サーバー再起動
# jet_brains_find_symbol: JetBrainsシンボル検索
# jet_brains_find_referencing_symbols: JetBrains参照検索
# jet_brains_get_symbols_overview: JetBrainsシンボル一覧

ツールの有効化/無効化制御

# context.yml または mode.yml
included_optional_tools:
  - delete_lines
  - insert_at_line

excluded_tools:
  - execute_shell_command

優先順位:


Language Server Protocol統合

LSPの活用

Language Server Protocol (LSP) は、IDE機能を言語非依存で提供する標準プロトコルです。Serenaは、LSPを通じてセマンティックなコード理解を実現します。

主要なLSP機能:

textDocument/documentSymbol    - ファイル内のシンボル一覧取得
textDocument/definition        - シンボル定義へのジャンプ
textDocument/references        - シンボル参照検索
textDocument/hover             - シンボル情報表示
textDocument/didOpen           - ドキュメントを開く通知
textDocument/didChange         - ドキュメント変更通知
textDocument/didClose          - ドキュメントを閉じる通知

SolidLSPレイヤーの設計目標

✅ 非同期LSP通信を同期APIでラップ
✅ 複数言語サーバーの統一インターフェース
✅ 高速化のための積極的なキャッシング
✅ エラーハンドリングと自動リトライ
✅ 言語サーバーのライフサイクル管理

言語サーバーのライフサイクル

エラーハンドリング

一般的なエラーと対処:

# 1. 言語サーバークラッシュ
try:
    result = ls.request_document_symbols(path)
except LSPError:
    # 自動再起動
    # キャッシュからのフォールバック

# 2. タイムアウト
try:
    result = ls.request_references(path, pos, timeout=30)
except TimeoutError:
    # 部分的な結果の返却

# 3. シンボル見つからず
result = ls.find_symbol(name)
if not result:
    # 空のリスト返却
    # ログに記録

# 4. ファイルエンコーディングエラー
try:
    content = read_file(path, encoding='utf-8')
except UnicodeDecodeError:
    # 他のエンコーディングで試行
    content = read_file(path, encoding='latin-1')

言語サーバー抽象化

# src/solidlsp/language_servers/
class PythonLanguageServer(SolidLanguageServer):
    """Pyright言語サーバーのラッパー"""

    @staticmethod
    def get_launch_info(repository_root_path, settings):
        return ProcessLaunchInfo(
            command="pyright-langserver",
            args=["--stdio"],
            env={}
        )

    def is_ignored_dirname(self, dirname: str) -> bool:
        return dirname in [
            "__pycache__", ".pytest_cache",
            "venv", ".venv", "env"
        ]

class TypeScriptLanguageServer(SolidLanguageServer):
    """TypeScript言語サーバーのラッパー"""

    @staticmethod
    def get_launch_info(repository_root_path, settings):
        return ProcessLaunchInfo(
            command="typescript-language-server",
            args=["--stdio"],
            env={}
        )

    def is_ignored_dirname(self, dirname: str) -> bool:
        return dirname in ["node_modules", "dist", "build"]

MCPサーバー統合

Model Context Protocol (MCP) とは

MCPは、LLMクライアントが外部ツールやデータソースと対話するための標準プロトコルです。Anthropic社が策定し、Claude Desktop等で採用されています。

MCPの主要概念:

Server   - ツールやリソースを提供するサービス
Client   - ツールを呼び出すLLMアプリケーション
Tool     - 実行可能な関数
Resource - 読み取り可能なデータ
Prompt   - 事前定義されたプロンプトテンプレート

Serena MCP Serverアーキテクチャ

MCPツール変換

SerenaのToolからMCPツールへの変換:

def make_mcp_tool(serena_tool: Tool) -> MCPTool:
    """
    1. apply()メソッドのシグネチャを抽出
    2. 型アノテーションをJSON Schemaに変換
    3. docstringをツール説明に変換
    4. Pydanticモデルを生成してバリデーション設定
    """

変換例:

# Serena Tool
class FindSymbolTool(Tool):
    def apply(
        self,
        name_path: str,
        depth: int = 0,
        include_body: bool = False
    ) -> str:
        """
        シンボルを検索します。
        :param name_path: 検索するシンボル名
        :param depth: 取得する階層の深さ
        :param include_body: ボディを含むか
        :return: JSON形式の検索結果
        """

# 変換後のMCP Tool
{
  "name": "find_symbol",
  "description": "シンボルを検索します。",
  "inputSchema": {
    "type": "object",
    "properties": {
      "name_path": {
        "type": "string",
        "description": "検索するシンボル名"
      },
      "depth": {
        "type": "integer",
        "default": 0,
        "description": "取得する階層の深さ"
      },
      "include_body": {
        "type": "boolean",
        "default": false,
        "description": "ボディを含むか"
      }
    },
    "required": ["name_path"]
  }
}

通信プロトコル

Serenaがサポートする3つのトランスポート:

1. stdio (標準入出力)

// Claude Desktop設定例
{
  "mcpServers": {
    "serena": {
      "command": "uvx",
      "args": [
        "--from", "git+https://github.com/oraios/serena",
        "serena", "start-mcp-server"
      ]
    }
  }
}
  • デフォルト
  • クライアントがサーバーをサブプロセスとして起動
  • Claude Desktop、Claude Code等で使用

2. Streamable HTTP

# サーバー起動
serena start-mcp-server --transport streamable-http --port 9121

# クライアント接続先
http://localhost:9121/mcp
  • HTTPベースの双方向通信
  • サーバーを独立して起動
  • 複数クライアントから接続可能

3. SSE (Server-Sent Events)

# 非推奨(Streamable HTTPを推奨)
serena start-mcp-server --transport sse --port 9122

データフローと実行フロー

典型的な実行フロー: "クラスFooのメソッドbarを見つけて編集"

プロジェクトアクティベーションフロー

オンボーディングフロー


設定システム

設定ファイルの階層と優先順位

serena_config.yml

場所: ~/.serena/serena_config.yml

# ログ設定
log_level: INFO  # DEBUG, INFO, WARNING, ERROR, CRITICAL

# ダッシュボード設定
web_dashboard: true
web_dashboard_open_on_launch: true
gui_log_window_enabled: false

# ツール実行設定
tool_timeout: 300.0  # 秒
max_answer_chars: 30000

# 言語サーバー設定
trace_lsp_communication: false
ls_specific_settings:
  python:
    pyrightconfig:
      analysis:
        typeCheckingMode: "basic"
  typescript:
    preferences:
      includeInlayParameterNameHints: "all"

# 統計記録
record_tool_usage_stats: true
token_count_estimator: cl100k_base  # tiktoken encoding

# 登録済みプロジェクト
projects:
  - name: my_project
    path: /absolute/path/to/project
    language: python

project.yml

場所: <project_root>/.serena/project.yml

# プロジェクト識別
project_name: my_awesome_project

# 言語設定
language: python  # または auto

# エンコーディング
encoding: utf-8

# 読み取り専用モード
read_only: false

# 無視パス
ignored_paths:
  - "**/__pycache__/**"
  - "**/node_modules/**"
  - "**/.git/**"

# .gitignoreを尊重するか
ignore_all_files_in_gitignore: true

# ツール除外
excluded_tools:
  - execute_shell_command

# ツール包含(オプションツール)
included_optional_tools:
  - delete_lines

Context & Mode システム

コンテキスト (Context)

定義: Serenaが動作する環境の定義

組み込みコンテキスト:

# 1. desktop-app (デフォルト)
name: desktop-app
description: Claude Desktop等のデスクトップアプリ用
included_optional_tools:
  - execute_shell_command
excluded_tools: []

# 2. agent
name: agent
description: 自律エージェント用(Agno等)
# フル機能セット

# 3. ide-assistant
name: ide-assistant
description: IDE統合用(Cursor、Cline等)
excluded_tools:
  - execute_shell_command  # IDE既存機能との重複を避ける

# 4. codex
name: codex
description: OpenAI Codex CLI用
# MCP仕様の非互換性を吸収

# 5. oaicompat-agent
name: oaicompat-agent
description: OpenAI互換ローカルサーバー用
openai_tool_compatible: true

モード (Mode)

定義: 特定のタスクタイプや対話スタイルへの最適化

組み込みモード:

# 1. planning: 計画・分析重視
name: planning
description: 実装前の設計フェーズ
excluded_tools:
  - replace_symbol_body
  - create_text_file

# 2. editing: コード編集重視
name: editing
description: 実装フェーズ
# 編集ツール優先

# 3. interactive: 対話型
name: interactive
description: ユーザーとの頻繁なやり取り

# 4. one-shot: 一発完了型
name: one-shot
description: 一度の応答で完了

# 5. no-onboarding: オンボーディングスキップ
name: no-onboarding
description: 既知プロジェクト用

# 6. onboarding: オンボーディング専用
name: onboarding
description: 自動トリガー

モード切り替え:

# 実行時に動的に切り替え可能
switch_modes(mode_names=["planning", "one-shot"])

カスタムコンテキスト・モードの作成

# コンテキスト作成
serena context create --name my_context
serena context edit my_context

# モード作成
serena mode create --name my_mode
serena mode edit my_mode

# 使用
serena start-mcp-server \
  --context my_context \
  --mode my_mode

カスタム設定例:

# ~/.serena/contexts/my_context.yml
name: my_custom_context
description: 私のカスタムコンテキスト

prompt: |
  You are Serena, an AI coding assistant.
  {{project_specific_instructions}}

  Available tools: {{tool_names}}

included_optional_tools:
  - initial_instructions

excluded_tools:
  - execute_shell_command

openai_tool_compatible: false

メモリシステム

メモリの仕組み

保存場所: <project_root>/.serena/memories/

形式: Markdown(人間にも読みやすい)

特徴:

  • プロジェクト固有の知識を永続化
  • セッションをまたいで利用可能
  • 手動編集が可能
  • LLMが自動的に読み書き

メモリの種類

.serena/memories/
├── project_structure.md      # プロジェクト構造
│   - ディレクトリ構成
│   - 主要ファイルの説明
│   - モジュール間の関係
│
├── how_to_test.md            # テスト実行方法
│   - テストフレームワーク
│   - テストコマンド
│   - CI/CD設定
│
├── how_to_build.md           # ビルド手順
│   - ビルドツール
│   - ビルドコマンド
│   - 環境設定
│
├── architecture.md           # アーキテクチャ概要
│   - システム設計
│   - デザインパターン
│   - データフロー
│
├── key_symbols.md            # 重要なシンボル
│   - 主要クラス・関数
│   - エントリーポイント
│   - ユーティリティ
│
├── coding_conventions.md     # コーディング規約
│   - 命名規則
│   - ディレクトリ構造規約
│   - コメント規約
│
└── task_progress.md          # タスク進捗(継続作業用)
    - 現在の状態
    - 完了した作業
    - 次にやるべきこと

メモリの活用例

# .serena/memories/api_conventions.md

## API設計原則

このプロジェクトでは以下の原則に従ってAPIを設計:

1. RESTful な URL 構造
2. すべてのエンドポイントは `/api/v1/` プレフィックス
3. 認証は JWT トークンを使用
4. エラーレスポンスは RFC 7807 形式

## 新規エンドポイント追加手順

1. `src/api/routes/` に新しいルートファイルを作成
2. `src/api/__init__.py` にルートを登録
3. `test/api/` にテストを追加
4. ドキュメントを `docs/api/` に追加

## 既存のエンドポイント

- `/api/v1/users` - ユーザー管理
  - GET /users - ユーザー一覧
  - POST /users - ユーザー作成
  - GET /users/{id} - ユーザー詳細

- `/api/v1/auth` - 認証・認可
  - POST /auth/login - ログイン
  - POST /auth/refresh - トークン更新

- `/api/v1/products` - 商品管理
  - GET /products - 商品一覧
  - POST /products - 商品作成

## エラーハンドリング

すべてのエンドポイントは以下の形式でエラーを返す:

```json
{
  "type": "https://example.com/errors/not-found",
  "title": "Resource Not Found",
  "status": 404,
  "detail": "The requested user was not found",
  "instance": "/api/v1/users/123"
}

### メモリライフサイクル

```mermaid
graph TD
    A[メモリライフサイクル]

    A --> B[1.オンボーディング時]
    B --> C[onboarding ツール実行]
    C --> D[自動でメモリ作成<br/>project_structure.md<br/>how_to_test.md等]

    A --> E[2.作業中]
    E --> F[write_memory で手動作成<br/>設計決定、規約、メモ等]
    E --> G[prepare_for_new_conversation<br/>で進捗保存<br/>task_progress.md]

    A --> H[3.新セッション開始時]
    H --> I[list_memories で一覧取得]
    I --> J[read_memory で読み込み]

    A --> K[4.更新・削除]
    K --> L[write_memory で上書き<br/>更新]
    K --> M[delete_memory で削除]

    style B fill:#e1f5ff
    style E fill:#fff4e1
    style H fill:#e1ffe1
    style K fill:#ffe1f5

コンテキスト枯渇時の継続性

長いタスクでコンテキストが一杯になった場合:

1. prepare_for_new_conversation ツールを実行
   → 現在の進捗状況をサマリ化

2. write_memory で "task_progress.md" に保存
   内容:
   - 完了した作業
   - 現在の状態
   - 次にやるべきこと
   - 重要な決定事項

3. 新しいセッションを開始

4. read_memory("task_progress.md") で前回の状態を復元

5. 作業を継続

パフォーマンス最適化

キャッシング戦略

シンボル情報のキャッシュ

# src/solidlsp/ls.py
self._document_symbols_cache: dict[
    str,  # ファイルパス
    tuple[
        str,  # ファイルハッシュ (MD5)
        tuple[...]  # シンボル情報
    ]
]

キャッシュの動作:

キャッシュファイル:

<project_root>/.serena/cache/
├── PythonLanguageServer.pkl
├── TypeScriptLanguageServer.pkl
└── ...

パフォーマンス指標

典型的な実行時間 (中規模Pythonプロジェクト、10,000行):

操作 初回(キャッシュなし) 2回目以降(キャッシュあり)
プロジェクトアクティベーション 5-10秒 1-2秒
シンボル検索(単一ファイル) 500ms-1秒 50-100ms
シンボル検索(プロジェクト全体) 3-5秒 200-500ms
参照検索 1-3秒 500ms-1秒
ファイル読み取り 10-50ms 10-50ms
シンボル編集 100-300ms 100-300ms

メモリ使用量:

Serena本体: 50-100MB
言語サーバー: 100-500MB(言語による)
キャッシュ: 1-50MB(プロジェクトサイズによる)

プロジェクトインデックス

# 事前にシンボル情報をキャッシュ
serena project index /path/to/project

# 特定ファイルだけインデックス
serena project index-file src/main.py /path/to/project

# 詳細表示
serena project index-file src/main.py --verbose

設定での最適化

# serena_config.yml

# タイムアウト調整
tool_timeout: 600.0  # 大規模プロジェクト用

# 言語サーバー固有設定
ls_specific_settings:
  python:
    analysis:
      useLibraryCodeForTypes: false  # 高速化
      diagnosticMode: "openFilesOnly"

  typescript:
    preferences:
      disableSuggestions: true  # 不要な機能を無効化

開発とカスタマイズ

開発環境のセットアップ

# リポジトリクローン
git clone https://github.com/oraios/serena
cd serena

# 依存関係インストール(開発用)
uv sync --all-extras

# 設定ファイル生成
uv run serena config edit

# テスト実行
uv run poe test

# コードフォーマット
uv run poe format

# 型チェック
uv run poe type-check

# リント
uv run poe lint

新しいツールの追加

ステップ:

# 1. ツールクラス作成 (src/serena/tools/my_tools.py)
from serena.tools import Tool, ToolMarkerOptional

class MyCustomTool(Tool, ToolMarkerOptional):
    """
    カスタムツールの説明。
    """

    def apply(self, param1: str, param2: int = 10) -> str:
        """
        詳細な説明。

        :param param1: パラメータ1
        :param param2: パラメータ2
        :return: 実行結果
        """
        # 実装
        result = f"Processed {param1} with {param2}"
        return result

# 2. ツールを__init__.pyに追加
# src/serena/tools/__init__.py
from .my_tools import *

# 3. テスト作成 (test/serena/test_my_tools.py)
def test_my_custom_tool(serena_agent):
    tool = serena_agent.get_tool(MyCustomTool)
    result = tool.apply("test", 20)
    assert "test" in result
    assert "20" in result

# 4. ツールを有効化(オプションツールの場合)
# context.yml or mode.yml
included_optional_tools:
  - my_custom_tool

新しい言語サーバーの追加

# 1. 言語サーバークラス作成
# src/solidlsp/language_servers/my_language_server.py
from solidlsp.ls import SolidLanguageServer
from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo

class MyLanguageServer(SolidLanguageServer):
    @staticmethod
    def get_launch_info(
        repository_root_path: str,
        solidlsp_settings
    ) -> ProcessLaunchInfo:
        """言語サーバーの起動情報を返す"""
        return ProcessLaunchInfo(
            command="my-language-server",
            args=["--stdio"],
            env={}
        )

    def is_ignored_dirname(self, dirname: str) -> bool:
        """無視すべきディレクトリ"""
        if super().is_ignored_dirname(dirname):
            return True
        return dirname in ["build", "dist"]

# 2. 言語列挙に追加 (src/solidlsp/ls_config.py)
class Language(Enum):
    MY_LANGUAGE = "my_language"

# 3. ファクトリメソッドに追加 (src/solidlsp/ls.py)
def create(...):
    elif language == Language.MY_LANGUAGE:
        from solidlsp.language_servers.my_language_server import MyLanguageServer
        ls = MyLanguageServer(...)

# 4. テストリポジトリ作成
# test/resources/repos/mylang/

# 5. テスト作成
# test/solidlsp/mylang/

# 6. pytest マーカー追加 (pyproject.toml)
[tool.pytest.ini_options]
markers = [
    "mylang: language server running for MyLang",
]

まとめ

アーキテクチャの利点

✅ 階層化された設計
   └─ 各レイヤーが明確な責任を持つ

✅ キャッシング戦略
   └─ 高速な応答時間(50-100ms)

✅ エラーハンドリング
   └─ 堅牢な実行環境

✅ 拡張性
   └─ 新しいツール・言語の追加が容易

✅ LLM・フレームワーク非依存
   └─ どんな環境でも利用可能

✅ オープンソース
   └─ 完全無料、カスタマイズ自由

主要な強み

1. セマンティックコード理解
   └─ シンボルレベルでのコード操作

2. トークン効率
   └─ 必要な部分だけを読み取り、コスト削減

3. 20+言語対応
   └─ 幅広いプロジェクトで使用可能

4. 柔軟な統合
   └─ MCP、OpenAPI、ライブラリとして利用可能

5. メモリシステム
   └─ プロジェクト知識の永続化

6. Context & Mode
   └─ 用途に応じた最適な動作

推奨ユースケース

✅ 大規模コードベースの探索
   └─ シンボルベース検索で効率的

✅ 精密なコード編集
   └─ インデント保持、シンボル単位の操作

✅ プロジェクトオンボーディング
   └─ 自動的な理解とドキュメント化

✅ コスト削減
   └─ トークン効率の向上により API コスト削減

✅ 長期的なプロジェクト作業
   └─ メモリシステムで文脈を保持

参考資料

公式ドキュメント

ソースコード

関連プロジェクト

5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?