Skip to content

Latest commit

 

History

History
250 lines (140 loc) · 13 KB

File metadata and controls

250 lines (140 loc) · 13 KB

Diffusion.nvim Code Flow Guide

This document provides an interactive guide to the codebase of diffusion.nvim. It outlines the typical code flows of the application, with links to the relevant files and lines of code.

1. Initialization and Configuration

The plugin is initialized when Neovim starts. The entry point is plugin/diffusion.lua.

1.1. Plugin Entry Point

This file is the main entry point for the plugin. It sets up the user commands and keymaps.

  • setup_commands(): This function creates all the user-facing commands like :Diffusion, :CC, :OC, etc.
  • setup_keymaps(): This function sets up the default keymaps, such as <leader>ds for sending the current selection.

1.2. Core Initialization

The diffusion.lua script calls require('diffusion'), which loads lua/diffusion/init.lua.

This file is the core of the plugin. It initializes all the main components.

  • Diffusion:setup(user_config): This is the main setup function. It gets called when the user runs the :Diffusion command for the first time or if auto_start is enabled in the config.
    • It initializes the configuration by calling require('diffusion.config'):setup(user_config).
    • It sets up the event system using require('diffusion.utils.events'):new().
    • It initializes the logger with require('diffusion.utils.logger'):setup(self._config.logging).
    • It creates the protocol layer with require('diffusion.protocol'):new(self._config, self._events).
    • It initializes the diff system with require('diffusion.diff'):init(self._config.diff, self._events).
    • It sets up the UI with require('diffusion.ui'):init(self._events, self._config.ui).

1.3. Configuration Loading

The configuration is managed by lua/diffusion/config.lua.

This file handles the layered configuration of the plugin. It merges default settings with user-defined configurations.

  • Config:setup(user_config): This function is called from the main init.lua. It loads the configuration from multiple sources:
    1. Defaults: The default configuration is defined at the top of the file.
    2. Environment Variables: It applies settings from environment variables like DIFFUSION_DEFAULT_SERVICE.
    3. Project Config: It looks for a .diffusion.lua or .diffusion.json file in the current working directory.
    4. User Config: It applies the user's configuration passed from their Neovim config.
  • Config:_validate_config(config): After loading, the configuration is validated to ensure all settings are correct.

2. Protocol Layer

The protocol layer is responsible for communicating with the different AI services. It's managed by lua/diffusion/protocol/init.lua.

2.1. Protocol Manager

This file acts as a router for the different protocol handlers (Claude, OpenCode, Codex).

  • Protocol:new(config, events): The constructor initializes the protocol manager and loads the available protocol handlers based on the user's configuration.
  • Protocol:setup(): This function sets up the protocol layer, initializes the handlers, and detects the initial service to use.
  • Protocol:switch_service(service): This function allows switching between the available AI services.
  • Protocol:send_selection(selection_data): This function sends the current selection to the active service handler.

2.2. Claude Protocol Handler

This handler implements the Model Context Protocol (MCP) for communicating with Claude.

  • ClaudeHandler:start(): This function starts the Claude handler. It creates a WebSocket server that the Claude CLI can connect to.
  • ClaudeHandler:_setup_discovery(): It sets up the necessary environment variables (CLAUDE_CODE_SSE_PORT, ENABLE_IDE_INTEGRATION) and creates a lock file in ~/.claude/ide for the Claude CLI to discover the server.
  • ClaudeHandler:_handle_websocket_message(client_id, message): This function processes incoming messages from the Claude CLI. It handles tool calls like openFile, openDiff, etc.

2.3. OpenCode Protocol Handler

This handler communicates with the OpenCode service via HTTP and WebSockets.

  • OpenCodeHandler:start(): This function starts the OpenCode handler. It also sets up a WebSocket server for real-time communication.
  • OpenCodeHandler:send_selection(selection_data): It sends the selection to the OpenCode service via an HTTP POST request.

2.4. Codex Protocol Handler

This handler communicates with the Codex service. It uses a WebSocket bridge.

  • CodexHandler:start(): This function starts the Codex handler and its WebSocket server.
  • CodexHandler:_setup_discovery(port): It creates a lock file in ~/.codex/ide for the bridge to discover the server.

2.5. WebSocket Server

The plugin includes its own WebSocket server to communicate with the AI services.

This file is the main entry point for the WebSocket server.

This file contains the implementation of the WebSocket server.

  • WebSocketServer:_handle_new_connection(): This function is called when a new client connects. It handles the WebSocket handshake.
  • WebSocketServer:_handle_handshake(client): This function processes the WebSocket handshake request from the client.
  • WebSocketServer:_handle_websocket_frames(client): This function parses incoming WebSocket frames and processes them.

3. Diff System

The diff system is a core component of diffusion.nvim. It's responsible for displaying diffs, handling user interactions, and applying changes.

3.1. Diff Manager

This is the central coordinator for the diff system.

  • DiffManager:show_diff(params): This is the main entry point for showing a diff. It validates the parameters, checks concurrent diff limits, and then delegates to the appropriate handler (blocking or event-based).
  • DiffManager:wait_for_response(diff_id, timeout_ms): In blocking mode, this function waits for the user to accept or reject the diff.
  • DiffManager:accept_diff(diff_id): This function is called when the user accepts a diff. It applies the changes to the file.
  • DiffManager:dismiss_diff(diff_id): This function is called to close and clean up a diff view.

3.2. Diff Handlers

Depending on the protocol and configuration, the diff manager uses one of the following handlers:

This handler is used for protocols that require a blocking response, like Claude. It creates the diff view and then blocks until the user responds.

This handler is used for event-based protocols like OpenCode. It creates the diff view and returns immediately, without blocking.

3.3. Diff Display

The diffs can be displayed in two modes: split view or unified view.

This module handles the side-by-side split view. It creates two buffers, one for the original content and one for the proposed changes, and then displays them in a vertical split.

This module handles the unified diff view. It creates a single buffer with a unified diff, using virtual text to show deletions and highlighting for additions.

3.4. Diff Components

This module manages the creation and cleanup of the buffers used in the diff views.

This module sets up the keymaps for the diff buffers, allowing the user to accept, reject, and navigate the diff.

This module handles real-time updates to the diff content, which is used by protocols that support streaming, like OpenCode.

This module is responsible for cleaning up the resources used by a diff view after it's been closed.

This module handles the "follow file changes" feature. After a diff is accepted, it can automatically navigate to the changed file and highlight the modified lines.

4. UI System

The UI system handles user interactions, such as getting the current selection and displaying notifications.

4.1. UI Manager

This is the main UI manager.

  • UI:get_current_selection(): This function gets the current text selection from the editor. It can handle visual mode selections, previous selections, and fallbacks to the current word or line.
  • UI:setup_selection_tracking(enabled): This function sets up autocommands to track the user's selection in real-time.
  • UI:show_notification(message, level, opts): This function displays a notification to the user.

4.2. Immersive Mode Overlay

This module implements the overlay panel for the immersive mode.

  • Overlay:show(): This function creates and displays the overlay, which consists of a chat window and an input prompt.
  • Overlay:append_output(prefix, text): This function appends text to the chat window.
  • Overlay:submit_input(): This function is called when the user presses Enter in the input prompt. It sends the message to the active AI service.

5. Tools and Utilities

This section covers the tool system and the various utility modules used throughout the plugin.

5.1. Tool System

The tool system allows the AI services to execute actions in the editor, such as opening files or showing diffs.

This is the main entry point for the tool system.

  • ToolSystem:register(tool_name, tool_config): This function registers a new tool with a schema and a handler function.

  • ToolSystem:execute(tool_name, args, context, callback): This function executes a registered tool with the given arguments and context.

  • File: lua/diffusion/tools/registry.lua

This module manages the registration of all available tools.

This module handles the execution of the tools, including timeouts and error handling.

This module validates the arguments passed to a tool against its schema.

5.2. Utility Modules

This file contains a collection of general-purpose utility functions, such as deep_merge, find_available_port, debounce, etc.

This module provides cryptographic functions, such as generating UUIDs and secure tokens, and calculating SHA-1 hashes for the WebSocket handshake.

This module handles the discovery of the AI services by creating and managing lock files.

This module implements a simple pub/sub event system that allows the different components of the plugin to communicate with each other.

This module provides a set of functions for safe and secure file operations.

This module manages information about running instances of the plugin.

This module provides a structured logging system with different log levels and file output.