*aibo-dev.txt*	Developer Documentation for Aibo

Author:  lambdalisue <lambdalisue@gmail.com>
License: MIT license

=============================================================================
CONTENTS					*aibo-dev-contents*

INTRODUCTION				|aibo-dev-introduction|
ARCHITECTURE				|aibo-dev-architecture|
  MODULE STRUCTURE			|aibo-dev-modules|
  DATA FLOW				|aibo-dev-dataflow|
  INTEGRATION POINTS			|aibo-dev-integration|
API REFERENCE				|aibo-dev-api|
  PUBLIC API				|aibo-dev-api-public|
  INTERNAL API				|aibo-dev-api-internal|
  COMMAND MODULE API			|aibo-dev-api-command|
  INTEGRATION MODULE API		|aibo-dev-api-integration|
TESTING					|aibo-dev-testing|
  TEST STRUCTURE			|aibo-dev-test-structure|
  WRITING TESTS				|aibo-dev-test-writing|
  RUNNING TESTS				|aibo-dev-test-running|
DEVELOPMENT				|aibo-dev-development|
  SETUP					|aibo-dev-setup|
  WORKFLOW				|aibo-dev-workflow|
  DEBUGGING				|aibo-dev-debugging|
CONTRIBUTING				|aibo-dev-contributing|
  CODE STYLE				|aibo-dev-style|
  COMMIT CONVENTIONS			|aibo-dev-commits|
  PULL REQUESTS				|aibo-dev-pr|
ADDING INTEGRATIONS			|aibo-dev-new-integration|
PLUGIN MAPPINGS				|aibo-dev-plug-mappings|

=============================================================================
INTRODUCTION					*aibo-dev-introduction*

This document provides comprehensive developer documentation for |Aibo|.
For user documentation, see |aibo.txt|.

This guide covers:
- Internal architecture and module organization
- API documentation for extending the plugin
- Testing framework and guidelines
- Development workflow and best practices
- How to add new AI tool integrations

=============================================================================
ARCHITECTURE					*aibo-dev-architecture*

The plugin follows a modular architecture with clear separation of concerns.

MODULE STRUCTURE				*aibo-dev-modules*

Directory layout:
>
	lua/aibo/
	├── command/                    # Command modules
	│   ├── aibo.lua               # Main Aibo command
	│   └── aibo_send.lua          # AiboSend command
	├── integration/               # AI tool integrations
	│   ├── claude.lua            # Claude integration
	│   ├── codex.lua             # Codex integration
	│   └── ollama.lua            # Ollama integration
	├── internal/                  # Internal utilities
	│   ├── argparse.lua          # Argument parsing
	│   ├── console_window.lua    # Console window management
	│   ├── integration.lua       # Integration module loader
	│   ├── prompt_window.lua     # Prompt window management
	│   ├── termcode.lua          # Terminal escape sequences
	│   └── timing.lua            # Debounce and throttle utilities
	├── health.lua                # Health check
	└── init.lua                  # Main entry point

	plugin/
	└── aibo.lua                  # Command registration

	ftplugin/
	├── aibo-prompt.lua           # Prompt filetype
	├── aibo-console.lua          # Console filetype
	└── aibo-tool-*.lua           # Tool-specific
<

Key principles:
- Command modules handle user-facing commands
- Integration modules own their <Plug> mappings
- Internal modules provide shared utilities
- Clear boundaries between components

DATA FLOW					*aibo-dev-dataflow*

User command flow:
>
	User Input → Command Module → Controller → Terminal Process
	                     ↓              ↓
	              Argument Parse    Buffer Setup
<

Message submission flow:
>
	Prompt Buffer → Send Module → Terminal → Console Buffer
	      ↓             ↓            ↓             ↓
	  User Input    Formatting    Process     Display
<

INTEGRATION POINTS				*aibo-dev-integration*

Extension points for new features:

1. Command hooks via `on_attach` callbacks
2. Tool-specific integrations in `integration/`
3. Custom <Plug> mappings in ftplugin files
4. Buffer-specific configuration

=============================================================================
API REFERENCE					*aibo-dev-api*

PUBLIC API					*aibo-dev-api-public*

Core module (`require("aibo")`):

`aibo.setup({opts})`				*aibo-dev-api-setup*
		Configure the plugin. Can be called multiple times.

		Parameters: ~
		  {opts}  (table) Configuration options
		    - submit_delay (number): Delay in ms (default: 100)
		    - submit_key (string): Key to send after submit (default: '<CR>')
		    - prompt_height (number): Prompt window height (default: 10)
		    - termcode_mode (string): Terminal escape sequence mode
		      'hybrid', 'xterm', or 'csi-n' (default: 'hybrid')
		    - prompt (table): Prompt buffer configuration
		    - console (table): Console buffer configuration
		    - tools (table): Tool-specific configuration

`aibo.send({data}, {bufnr})`			*aibo-dev-api-send*
		Send raw data to terminal.

		Parameters: ~
		  {data}   (string) Data to send
		  {bufnr}  (number) Buffer number

`aibo.submit({text}, {bufnr})`			*aibo-dev-api-submit*
		Submit text with automatic return key.

		Parameters: ~
		  {text}   (string) Text to submit
		  {bufnr}  (number) Buffer number

`aibo.get_config()`				*aibo-dev-api-get-config*
		Get current configuration.

		Returns: ~
		  (table) Current configuration

`aibo.get_buffer_config({type})`		*aibo-dev-api-get-buffer-config*
		Get buffer type configuration.

		Parameters: ~
		  {type}  (string) "prompt" or "console"

		Returns: ~
		  (table) Buffer configuration

`aibo.get_tool_config({tool})`		*aibo-dev-api-get-tool-config*
		Get tool-specific configuration.

		Parameters: ~
		  {tool}  (string) Tool name (e.g., "claude")

		Returns: ~
		  (table) Tool configuration

`aibo.resolve({input})`			*aibo-dev-api-resolve*
		Convert Vim key notation to terminal escape sequences
		using the configured termcode_mode.

		Parameters: ~
		  {input}  (string) Key notation like "<Up>", "<C-A>"

		Returns: ~
		  (string|nil) Terminal escape sequence

		Example: ~
>
		  aibo.resolve("<Up>")    -- Returns "\27[A"
		  aibo.resolve("<C-c>")   -- Returns "\3"
		  aibo.resolve("<S-Tab>") -- Returns "\27[Z" (hybrid)
		                          -- or "\27[9;2u" (csi-n)
<

INTERNAL API					*aibo-dev-api-internal*

Internal modules (not part of public API, may change):

`internal.console_window`			*aibo-dev-console-window*
		Console window and terminal management.

		Functions: ~
		  - open(): Open new console window
		  - get_info_by_bufnr(): Get console info by buffer
		  - get_info_by_winid(): Get console info by window
		  - find_info_in_tabpage(): Find console in current tab
		  - send(): Send data to terminal
		  - follow(): Move cursor to last line

`internal.argparse`				*aibo-dev-argparse*
		Command-line argument parsing.

		Functions: ~
		  - parse(): Parse command arguments
		  - get_option_completions(): Get completions
		  - parse_for_completion(): Parse for completion context

`internal.prompt_window`			*aibo-dev-prompt-window*
		Prompt window management.

		Functions: ~
		  - open(): Open prompt window for console
		  - get_info_by_bufnr(): Get prompt info by buffer
		  - get_info_by_winid(): Get prompt info by window
		  - find_info_in_tabpage(): Find prompt in current tab
		  - write(): Write content to prompt buffer
		  - submit(): Submit prompt content to console

`internal.timing`				*aibo-dev-timing*
		Utility functions for debouncing and throttling.

		Functions: ~
		  - debounce(): Create debounced function
		  - throttle(): Create throttled function

`internal.termcode`				*aibo-dev-termcode*
		Terminal escape sequence translation.

		Functions: ~
		  - resolve(input, opts): Convert Vim key notation to terminal
		    escape sequences. Options support mode: 'hybrid', 'xterm',
		    or 'csi-n'

		IMPORTANT: Use aibo.resolve() instead of accessing this ~
		module directly. This is an internal module that may change.

`internal.integration`			*aibo-dev-integration-module*
		Integration module management and loading.

		Functions: ~
		  - get_module(name): Load an integration module
		  - available_integrations(): List available integrations
		  - is_available(name): Check if integration exists
		  - check_health(name, report): Run health check
		  - get_command_completions(): Get tool completions

		This module manages loading of tool-specific integrations
		(claude, codex, ollama) from the integration/ directory.

COMMAND MODULE API				*aibo-dev-api-command*

Command modules export:

`setup()`					*aibo-dev-command-setup*
		Initialize command module and register commands.

`call({opts})`					*aibo-dev-command-call*
		Execute command with options.

		Parameters: ~
		  {opts}  (table) Command options

INTEGRATION MODULE API				*aibo-dev-api-integration*

Integration modules export:

`plug_mappings`					*aibo-dev-integration-mappings*
		Table of <Plug> mapping definitions.

		Structure: ~
>
		{
		  ["<Plug>(aibo-tool-action)"] = function(bufnr)
		    -- Implementation
		  end,
		}
<

`setup({bufnr}, {info})`			*aibo-dev-integration-setup*
		Set up integration for buffer.

		Parameters: ~
		  {bufnr}  (number) Buffer number
		  {info}   (table) Context information

=============================================================================
TESTING						*aibo-dev-testing*

The project uses mini.test for testing.

TEST STRUCTURE					*aibo-dev-test-structure*

Test organization:
>
	tests/
	├── internal/             # Internal module tests
	│   ├── test_init.lua
	│   ├── test_argparse.lua
	│   ├── test_console_window.lua
	│   ├── test_prompt_window.lua
	│   ├── test_timing.lua
	│   └── test_termcode.lua
	├── integrations/         # Integration tests
	│   ├── test_claude.lua
	│   ├── test_codex.lua
	│   └── test_ollama.lua
	├── commands/             # Command tests
	│   ├── test_aibo_command.lua
	│   └── test_aibo_send_command.lua
	├── plugin/               # Plugin tests
	│   └── test_plugin_setup.lua
	├── mock.lua             # Test mocking utilities
	└── runner.lua           # Test runner
<

WRITING TESTS					*aibo-dev-test-writing*

Test structure:
>
	local mock = require("tests.mock")
	local T = require("mini.test")

	local test_set = T.new_set()

	-- Setup/teardown
	test_set.hooks.pre_case = function()
	  -- Setup clean environment
	end

	test_set.hooks.post_case = function()
	  -- Cleanup resources
	end

	-- Test cases
	test_set["function works correctly"] = function()
	  -- Arrange
	  local input = "test"

	  -- Act
	  local result = module.function(input)

	  -- Assert
	  T.expect.equality(result, "expected")
	end

	return test_set
<

Test guidelines:
- One test file per module
- Test public API thoroughly
- Include edge cases
- Keep tests independent
- Use descriptive names

RUNNING TESTS					*aibo-dev-test-running*

Using just:
>
	just test           # Run all tests
	just test-file aibo # Run specific file
	just test-watch     # Watch mode
<

Direct execution:
>
	nvim --headless -c "luafile tests/runner.lua" -c "qa!"
<

=============================================================================
DEVELOPMENT					*aibo-dev-development*

SETUP						*aibo-dev-setup*

Prerequisites:
- Neovim 0.10.0+
- Lua 5.1 or LuaJIT
- Git
- just (optional)

Initial setup:
>
	# Fork and clone
	git clone https://github.com/your-username/nvim-aibo.git
	cd nvim-aibo

	# Install mini.test
	git clone https://github.com/echasnovski/mini.nvim.git /tmp/mini
	mkdir -p ~/.local/share/nvim/site/pack/vendor/start/mini.nvim/lua/mini
	cp /tmp/mini/lua/mini/test.lua \
	   ~/.local/share/nvim/site/pack/vendor/start/mini.nvim/lua/mini/

	# Verify setup
	nvim -c "checkhealth aibo"
<

WORKFLOW					*aibo-dev-workflow*

Development workflow:

1. Create feature branch:
>
	git checkout -b feature/your-feature
<

2. Make changes following code style

3. Run tests:
>
	just test
<

4. Lint code:
>
	just lint
<

5. Commit with conventional commits:
>
	git commit -m "feat(module): add new feature"
<

DEBUGGING					*aibo-dev-debugging*

Debugging tips:

Enable debug logging:
>
	vim.g.aibo_debug = true
<

Inspect data:
>
	vim.notify(vim.inspect(data), vim.log.levels.DEBUG)
<

Check terminal output:
>
	:terminal
	:messages
<

Process inspection:
>
	:!ps aux | grep <process>
<

=============================================================================
CONTRIBUTING					*aibo-dev-contributing*

CODE STYLE					*aibo-dev-style*

Lua style guide:

1. Naming conventions:
   - snake_case for variables/functions
   - PascalCase for modules
   - Prefix private with underscore

2. Documentation:
   - Use LuaLS annotations
   - Document complex logic
   - Keep comments concise

Example:
>
	local M = {}

	--- Public function description
	---@param param string Parameter description
	---@return string result Description
	function M.public_function(param)
	  -- Implementation
	end

	-- Private helper
	local function _private_helper()
	  -- Implementation
	end

	return M
<

COMMIT CONVENTIONS				*aibo-dev-commits*

Use conventional commits:

- feat: New features
- fix: Bug fixes
- docs: Documentation
- style: Code style
- refactor: Refactoring
- test: Testing
- chore: Maintenance

Examples:
>
	feat(integration): add support for new AI tool
	fix(console): resolve buffer cleanup issue
	docs: update API documentation
	refactor(core): improve module structure
<

PULL REQUESTS					*aibo-dev-pr*

PR checklist:

- [ ] Tests pass
- [ ] Linting passes
- [ ] Documentation updated
- [ ] Conventional commits used
- [ ] Clear PR description

=============================================================================
ADDING INTEGRATIONS				*aibo-dev-new-integration*

To add support for a new AI tool:

1. Create integration module (optional):
>
	-- lua/aibo/integration/myai.lua
	local M = {}

	-- Optional: Argument completion
	function M.get_command_completions(arglead, cmdline, cursorpos)
	  -- Return completion candidates
	  return {}
	end

	-- Optional: Health check
	function M.check_health(report)
	  report.start("MyAI Integration")
	  -- Health check logic
	end

	return M
<

2. Create ftplugin file:
>
	-- ftplugin/aibo-tool-myai.lua
	if vim.b.loaded_aibo_tool_myai_ftplugin then
	  return
	end
	vim.b.loaded_aibo_tool_myai_ftplugin = true

	local bufnr = vim.api.nvim_get_current_buf()
	local aibo = require("aibo")

	-- Default key mappings (unless disabled in config)
	local cfg = aibo.get_tool_config("myai")
	if not (cfg and cfg.no_default_mappings) then
	  local opts = { buffer = bufnr, nowait = true, silent = true }
	  -- Use <Plug>(aibo-send)<Key> pattern to send keys to terminal
	  vim.keymap.set({ "n", "i" }, "<C-g>", "<Plug>(aibo-send)<C-g>", opts)
	  vim.keymap.set({ "n", "i" }, "<F6>", "<Plug>(aibo-send)<F6>", opts)
	end
<

3. Update command completion:
>
	-- In lua/aibo/command/aibo.lua
	local known_tools = { "claude", "codex", "ollama", "myai" }
<

4. Add tests:
>
	-- tests/integrations/test_myai.lua
	local test_set = T.new_set()
	-- Test implementation
	return test_set
<

5. Update documentation in README and help files

=============================================================================
PLUGIN MAPPINGS					*aibo-dev-plug-mappings*

The <Plug>(aibo-send) pattern~

The recommended approach for tool-specific mappings is to use the
`<Plug>(aibo-send)<Key>` pattern. This automatically converts Vim key
notation to terminal escape sequences:
>
	-- In ftplugin/aibo-tool-*.lua
	local opts = { buffer = bufnr, nowait = true, silent = true }
	vim.keymap.set({ "n", "i" }, "<C-g>", "<Plug>(aibo-send)<C-g>", opts)
<

This pattern:
- Automatically handles key conversion using aibo.resolve()
- Works in both normal and insert mode
- Sends keys directly to the terminal process
- Simplifies tool integration

For custom logic~

If you need custom behavior beyond sending keys:
>
	vim.keymap.set("n", "<C-x>", "<Plug>(aibo-tool-action)",
	  { buffer = bufnr })
<

SENDING KEYS TO TERMINAL			*aibo-dev-terminal-keys*

When creating mappings that send keys to the terminal, use
`aibo.resolve()` instead of `nvim_replace_termcodes()`:

CORRECT example:
>
	local aibo = require("aibo")

	vim.keymap.set("n", "<Leader>au", function()
	  -- Send Up arrow to terminal
	  aibo.send(aibo.resolve("<Up>"), bufnr)
	end, { buffer = bufnr, desc = "Send Up arrow" })

	vim.keymap.set("n", "<Leader>ac", function()
	  -- Send Ctrl-C to interrupt
	  aibo.send(aibo.resolve("<C-c>"), bufnr)
	end, { buffer = bufnr, desc = "Interrupt process" })
<

INCORRECT (will not work):
>
	-- This sends Neovim's internal codes, not terminal sequences!
	vim.keymap.set("n", "<Leader>au", function()
	  local up = vim.api.nvim_replace_termcodes("<Up>", true, false, true)
	  aibo.send(up, bufnr)  -- Sends "\x80\x6B\x75" instead of "\27[A"
	end, { buffer = bufnr })
<

Supported key formats:
- Navigation: <Up>, <Down>, <Left>, <Right>, <Home>, <End>
- Function keys: <F1> through <F12>
- Control combinations: <C-a>, <C-c>, <C-l>, etc.
- Modified keys: <S-Tab>, <C-Left>, <A-Up>, etc.
- Special keys: <CR>, <Tab>, <Esc>, <Space>, <BS>

Naming convention:
- Format: <Plug>(aibo-{context}-{action})
- Examples:
  - <Plug>(aibo-prompt-submit)
  - <Plug>(aibo-claude-mode)
  - <Plug>(aibo-console-clear)

vim:tw=78:ts=8:ft=help:norl:
