Skip to content

Snayx/Aidy

Repository files navigation

Aidy

Aidy is an AI-powered desktop launcher and assistant built with Electron, React, and TypeScript. It provides quick access to AI capabilities through a Spotlight-like interface with an extensible plugin system.

Features

  • Global Hotkey Access: Summon Aidy from anywhere with Alt+Space (customizable)
  • LLM Integration: Powered by LM Studio for local AI inference
  • Plugin System: Extensible architecture for adding custom functionality
  • Tool Calling: LLM can invoke tools exposed by plugins
  • Clean UI: Modern React-based interface with search and results display
  • System Tray: Runs quietly in the background
  • Cross-Platform: Works on Windows, macOS, and Linux
  • Local Database: SQLite-based storage for settings and plugin state

Prerequisites

  • Node.js (v16 or higher)
  • npm (comes with Node.js)
  • LM Studio running at http://localhost:1234 - REQUIRED for all functionality
    • Download from lmstudio.ai
    • Load a model that supports tool calling (function calling)
    • Start the local server
    • Without LM Studio, Aidy cannot function

Installation

Development

  1. Clone the repository

    git clone <repository-url>
    cd Aidy
  2. Install dependencies

    npm install
  3. Start LM Studio

  4. Run in development mode

    npm run dev

Building for Production

Build for your current platform:

npm run dist

Platform-specific builds:

npm run dist:win      # Windows (portable)
npm run dist:mac      # macOS (dmg + zip)
npm run dist:linux    # Linux (AppImage + deb)

Built applications will be in the build-output/ directory.

Usage

Launching Aidy

  1. Global Hotkey: Press Alt+Space (default) from anywhere
  2. System Tray: Click the Aidy icon in your system tray
  3. Direct Launch: Open the application from your applications folder

Using the Interface

  1. Search/Ask: Type your query in the search bar
  2. LLM Processing: The LLM analyzes your query and decides which plugin tool to call
  3. Tool Execution: The appropriate plugin tool is invoked automatically
  4. View Results: Results are displayed with custom UI from the plugin
  5. Access Settings: Click the settings icon in the footer
  6. Manage Plugins: Click the grid icon to view/manage plugins
  7. Close: Press Esc or click the close button

How It Works: All user queries go through the LLM Chat plugin, which uses the LLM to determine the best tool to call based on plugin descriptions. The LLM makes tool calls like get_weather, search_notes, etc., and plugins respond through their tool providers.

Example Queries

  • "What is the capital of France?"
  • "How do I reverse a string in Python?"
  • "Explain quantum computing in simple terms"
  • Any general knowledge or coding question

Project Structure

Aidy/
├── src/
│   ├── main/              # Electron main process
│   │   ├── index.ts       # Application entry point
│   │   ├── window.ts      # Window management
│   │   ├── hotkey.ts      # Global hotkey handling
│   │   ├── tray.ts        # System tray integration
│   │   ├── splash.ts      # Splash screen
│   │   └── ipc-handlers.ts # IPC communication
│   │
│   ├── renderer/          # React renderer process
│   │   ├── App.tsx        # Main React component
│   │   ├── SearchBar.tsx  # Search input component
│   │   ├── Results.tsx    # Results display
│   │   ├── PluginManager.tsx # Plugin management UI
│   │   └── Settings.tsx   # Settings UI
│   │
│   ├── core/              # Core functionality
│   │   ├── database/      # SQLite database
│   │   ├── llm/           # LM Studio client
│   │   └── plugin-system/ # Plugin architecture
│   │       ├── BasePlugin.ts
│   │       ├── PluginInterface.ts
│   │       ├── PluginLoader.ts
│   │       ├── PluginRegistry.ts
│   │       ├── ToolRegistry.ts
│   │       └── LLMRouter.ts
│   │
│   └── plugins/           # Built-in plugins
│       └── llm-chat/      # LLM Chat plugin
│
├── assets/                # Application assets (icons, etc.)
├── dist/                  # Compiled output
├── build-output/          # Distribution packages
├── package.json           # Dependencies and scripts
├── electron-builder.json  # Build configuration
├── tsconfig.json          # TypeScript configuration
└── vite.config.ts         # Vite configuration

Architecture

Main Process (Electron)

The main process (src/main/) handles:

  • Application Lifecycle: Startup, shutdown, single instance lock
  • Window Management: Creating and controlling the UI window
  • Global Hotkeys: Registering system-wide keyboard shortcuts
  • System Tray: Background operation and tray menu
  • Plugin System: Loading, compiling, and managing plugins
  • Database: Persistent storage using SQLite
  • IPC Handlers: Communication bridge with renderer

Renderer Process (React)

The renderer process (src/renderer/) provides:

  • Search Interface: Input and query handling
  • Results Display: Dynamic rendering based on plugin output
  • Plugin Management: UI for enabling/disabling plugins
  • Settings Panel: Application and LLM configuration
  • Plugin UIs: Custom React components from plugins

Core Systems

Database (src/core/database/Database.ts)

  • SQLite database stored in user data directory
  • Tables for plugin state and app settings
  • Helper methods for plugin and settings management

LLM Client (src/core/llm/LMStudioClient.ts)

  • Communicates with LM Studio's OpenAI-compatible API
  • Supports chat completions and tool calling
  • Streaming responses for real-time output
  • Configurable temperature and token limits

Plugin System

  • PluginInterface: Defines plugin contract
  • BasePlugin: Abstract base class for plugin development
  • PluginLoader: Discovers and loads plugins from filesystem
  • PluginRegistry: Manages loaded plugins and their state
  • ToolRegistry: Manages LLM-callable tools from plugins
  • LLM Chat Plugin: Core plugin that routes all queries through LLM tool calling

Plugin Architecture

How Plugins Work: Aidy uses a centralized routing architecture with LLM tool calling:

  1. LLMRouter receives all user input and routes to the LLM Chat plugin
  2. LLM Chat plugin's execute() method is called with the user input
  3. Tool Discovery: Collects all tool definitions from enabled plugins via ToolRegistry
  4. LLM Tool Calling: Sends user query + tools to LLM, which decides which tool to call
  5. Tool Execution: The chosen plugin's executeTool() method runs
  6. Result Display: Tool returns data with optional _display metadata for UI

Example Flow:

User: "What's the weather in Paris?"
  → LLMRouter → llm-chat.execute()
  → LLM receives: query + [get_weather_forecast, search_clipboard, google_search, ...]
  → LLM decides: call get_weather_forecast with args {location: "Paris"}
  → Weather plugin's executeTool() runs
  → Returns weather data + display structure

Plugins provide:

  1. Tool Providers: Define tools the LLM can call via getToolDefinition() and executeTool()
  2. execute() Method: Required by interface, but only llm-chat's is actually called
  3. Custom UI: React components for displaying results (optional)
  4. Persist Settings: Store configuration in the database
  5. Settings UI: Custom settings interface (optional)

Important Notes:

  • Only the LLM Chat plugin's execute() method is invoked in normal operation
  • Other plugins respond via their toolProvider.executeTool() method
  • Tool names use snake_case (e.g., get_weather_forecast, search_clipboard_history)

Development

Scripts

npm run dev              # Start development mode
npm run build            # Build main, renderer, and plugins
npm run build:main       # Compile main process
npm run build:renderer   # Build renderer with Vite
npm run build:plugins    # Compile plugins
npm run dist             # Build and package app
npm start               # Run built application

Hot Reload

In development mode (npm run dev):

  • Renderer auto-reloads on changes (via Vite)
  • Plugin changes are detected and recompiled
  • Main process requires manual restart

Creating Plugins

Plugins are stored in the user data directory under plugin-build/plugins/ and compiled to plugins-compiled/plugins/.

Important: Plugins work through LLM tool calling. Your plugin must provide a toolProvider that defines a tool for the LLM to call.

Example plugin with tool provider:

import { BasePlugin } from '../../core/plugin-system/BasePlugin';
import { PluginContext, PluginResult } from '../../core/plugin-system/PluginInterface';
import { LLMToolDefinition } from '../../core/llm/LMStudioClient';

export class MyPlugin extends BasePlugin {
  constructor() {
    super({
      id: 'my-plugin',
      name: 'My Plugin',
      description: 'Performs a specific task when requested',
      version: '1.0.0',
      enabled: true
    });

    // Define tool provider for LLM
    this.toolProvider = {
      getToolDefinition: () => ({
        type: 'function',
        function: {
          name: 'do_my_task',
          description: 'Performs my specific task',
          parameters: {
            type: 'object',
            properties: {
              input: { type: 'string', description: 'Task input' }
            },
            required: ['input']
          }
        }
      }),
      executeTool: async (args, context) => {
        // This runs when LLM calls the tool
        return {
          result: 'Task completed',
          _display: {
            pluginId: this.id,
            data: { result: 'Task completed' },
            display: {
              type: 'text',
              title: 'My Plugin',
              content: `Task completed with input: ${args.input}`
            },
            actions: []
          }
        };
      }
    };
  }

  async execute(input: string, context: PluginContext): Promise<PluginResult> {
    // Not used when called as tool
    return this.helpers.textResult('Use via LLM tool calling', 'My Plugin');
  }
}

See PLUGIN_DEVELOPMENT.md for comprehensive documentation.

Configuration

Settings Location

Settings are stored in:

  • Windows: %APPDATA%/Aidy/
  • macOS: ~/Library/Application Support/Aidy/
  • Linux: ~/.config/Aidy/

Database

  • aidy.db - SQLite database with settings and plugin state
  • aidy.log - Application logs

Configurable Settings

Via the Settings UI:

  • LM Studio URL: Default http://localhost:1234/v1
  • Global Hotkey: Default Alt+Space
  • Temperature: LLM sampling temperature
  • Max Tokens: Maximum response length
  • Base Prompt: System prompt for the LLM

Built-in Plugin

LLM Chat

  • ID: llm-chat
  • Purpose: Core routing plugin that handles ALL user queries
  • How It Works:
    1. Receives user input
    2. Collects tool definitions from all enabled plugins
    3. Sends query + tools to LLM
    4. LLM decides which tool to call (e.g., get_weather_forecast)
    5. Routes tool call to appropriate plugin's executeTool() method
    6. Returns result to user
  • Features:
    • LLM-based tool routing
    • Direct LLM responses (when no tool is called)
    • Tool calling orchestration
    • Thinking/reasoning display
    • Markdown rendering
  • Note: This plugin cannot be disabled as it is required for the application to function

Troubleshooting

LLM Not Responding

  1. Ensure LM Studio is running at http://localhost:1234
  2. Check that a model is loaded in LM Studio
  3. Verify the local server is started
  4. Check logs in the user data directory

Model Requirements

CRITICAL: Your LLM model MUST support tool calling (function calling). Recommended models:

  • Models with "tool" or "function" in their name
  • Models specifically fine-tuned for function calling
  • Check the model card to verify tool calling support

Without tool calling support, plugins will not work correctly and Aidy's core functionality will be limited.

Plugins Not Loading

  1. Check aidy.log in the user data directory
  2. Verify plugin compilation succeeded
  3. Ensure TypeScript has no errors
  4. Check plugin is enabled in Plugin Manager

Hotkey Not Working

  1. Check another app isn't using the same hotkey
  2. Try changing the hotkey in Settings
  3. On Linux, ensure you have proper permissions

Build Issues

  1. Clear build artifacts: rm -rf dist build-output
  2. Reinstall dependencies: rm -rf node_modules && npm install
  3. Check Node.js version is 16+

Technologies

  • Electron: Desktop application framework
  • React: UI library
  • TypeScript: Type-safe JavaScript
  • Vite: Frontend build tool
  • better-sqlite3: SQLite database
  • LM Studio: Local LLM inference
  • react-markdown: Markdown rendering
  • react-icons: Icon library

License

ISC

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Test thoroughly
  5. Submit a pull request

Support

For issues, questions, or feature requests, please use the GitHub issue tracker.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors