Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 49 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,65 @@
# Model-cmp.nvim

AI autocomplete plugin for neovim
AI autocomplete plugin.

support me!!! it is difficult to develop open source while searching for jobs. scan and support
![IMG-20250829-WA0012](https://github.com/user-attachments/assets/e86526b6-6819-4ae5-a3b7-6698af3f03ee)
Official first Release date: 9 Sep 2025
## Installation

Before installing the plugin, please make sure you have following pre-requisities:
- llama.cpp or gemini api key
- system specs for local llm inferencing [Checkout Here for system requriements]()

### Lazy.nvim

```lua
{
"PyDevC/model-cmp.nvim",
config = function()
require("model_cmp").setup()
end
}
```

## How to launch the server
### Setup Gemini API key

There are two ways to setup gemini api keys:
1. Environment variable
2. Inside config

- Environment variable:
```bash
llama-server --no-mmap -hf bartowski/Llama-3.2-3B-Instruct-GGUF:Q8_0
export GEMINI_API_KEY="<your-key>"
```

## Installation
or

### Lazy.nvim
you can setup api key in your ~/.bashrc or ~/.zshrc which I highly don't recommend

- Inside Config:

```lua
{
api = {
apikeys = {
GEMINI_API_KEY = "<your-key>"
}
}
}
```

## Config

```lua
return {
"PyDevC/model-cmp.nvim",
config = function()
require("model_cmp").setup({
delay = 1,
delay = 1000, -- 1 sec delay

api = {
apikeys = {
GEMINI_API_KEY = "<your-key>"
}
custom_url = {
url = "http://127.0.0.1",
port = "8080"
Expand All @@ -45,3 +81,8 @@ return {
end,
}
```

## Support

support me!!! it is difficult to develop open source while searching for jobs. scan and support
![IMG-20250829-WA0012](https://github.com/user-attachments/assets/e86526b6-6819-4ae5-a3b7-6698af3f03ee)
18 changes: 9 additions & 9 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# TODO

- Load multiple lines of vitualtext even if not enough space.
- improve modelapi
- remove all the extmarks even.
- Capture single line virtual text
- Capture All line capture
- Treat the suggestions as a buffer and move through it for custom suggestions pickup
- manage response gracefully
- improve context engine
- improve modelapi
- setup openai and claude services
- Different prompt style
- Conversational few-shot prompt
- improve commands for different scenarios
- Language supported Prompts
- Lsp support
- nvim-cmp support
- Chat options
- more AI models

## Comming Soon (Before Todo list)

- Support for gemini requests
- better managment of api keys, via config or environment variable
- Commands for starting services
- Fully functional model-services
66 changes: 66 additions & 0 deletions docs/model_cmp.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
model_cmp.txt
model-cmp model_cmp model-cmp.nvim
--------------------------------------------------------------------------------
CONTENTS *model-cmp-contents*

1. Config |model-cmp-config|
2. UserCommands |mode-cmp-commands|
3. API |model-cmp-api|


--------------------------------------------------------------------------------
CONFIG model-cmp-config

```lua
return {
"PyDevC/model-cmp.nvim",
config = function()
require("model_cmp").setup({
delay = 1000, -- 1 sec

api = {
apikeys = {
GEMINI_API_KEY = "<your-key>"
}
custom_url = {
url = "http://127.0.0.1",
port = "8080"
}
},

virtualtext = {
enable = false,
type = "inline",

style = { -- This is just a highlight group
fg = "#b53a3a",
italic = false,
bold = false
}

},
})
end,
}
```

--------------------------------------------------------------------------------
USERCOMMANDS model-cmp-commands

ModelCmp
ModelCmp is main command for all actions

virtualtext {enable, disable, toggle}
enables or disables virtualtext suggestions on screen

capture {all, first}
capture virtualtext lines

ModelCmpStart
Start server reading

ModelCmpStop
Stop server reading

ModelCmpLogs
Look up current session Logs
82 changes: 81 additions & 1 deletion lua/model_cmp/commands.lua
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
local api = require("model_cmp.modelapi.common")
local common = require("model_cmp.modelapi.common")
local gemini = require("model_cmp.modelapi.gemini")
local llama = require("model_cmp.modelapi.llama")
local logger = require("model_cmp.logger")
local virtualtext = require("model_cmp.virtualtext")

local uv = vim.uv

local M = {}

function M.setup(config)
M.delay = config.delay
end

function M.create_autocmds(group)
M.timer = uv.new_timer()
vim.api.nvim_create_autocmd({ 'TextChanged', 'TextChangedI', 'TextChangedP' },
{
group = group,
callback = function(event)
local file = event["file"]
-- also Check for buffer editing in oil.nvim
if file == "" or file:find 'oil:///' then
if file == "" or file:find 'oil:///' or M.timer:is_active() then
return
end
M.timer:start(M.delay, 0, function() end)
api.send_request()
end
})
Expand All @@ -29,8 +41,72 @@ function M.create_autocmds(group)
virtualtext.action.clear_preview()
end
})

vim.api.nvim_create_autocmd({ 'VimLeave' },
{
group = group,
callback = function()
logger.save_logs()
end
})
end

local function modelcmp_start()
vim.api.nvim_create_user_command('ModelCmpStart', function(args)
local fargs = args.fargs
if fargs[2] == nil then
fargs[2] = "default"
end
local servers = {
local_llama = function(server_name) llama.start(server_name) end,
gemini = function(server_name) gemini.start(server_name) end
}

servers[fargs[1]](fargs[2])
end, {
nargs = '+',
complete = function(_, cmdline, _)
cmdline = cmdline or ''

if cmdline:find 'local_llama' then
return {}
end

if cmdline:find 'gemini' then
return {
"gemini-1.5-flash",
"gemini-2.0-flash",
"gemini-2.5-pro",
}
end

return { 'local_llama', 'gemini' }
end,
})
end

local function modelcmp_stop()
vim.api.nvim_create_user_command('ModelCmpStop', function()
common.stop()
logger.debugging("Stopped api")
end, {})
end

local function modelcmp_logs()
vim.api.nvim_create_user_command('ModelCmpLogs', function()
vim.cmd('tabnew')
local newbuf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_name(newbuf, "Model Cmp logs")
vim.api.nvim_set_current_buf(newbuf)
vim.api.nvim_buf_set_option(newbuf, 'bufhidden', 'wipe') -- Close buffer when window is closed
vim.api.nvim_buf_set_option(newbuf, 'buftype', 'nofile') -- Not a file buffer
vim.api.nvim_buf_set_option(newbuf, 'swapfile', false) -- No swap file
vim.api.nvim_buf_set_lines(newbuf, 0, -1, false, logger.Logs)
vim.api.nvim_buf_set_option(newbuf, 'modifiable', false) -- Make it read-only
end, {})
end

-- This is our main command
function M.create_usercmds()
vim.api.nvim_create_user_command('ModelCmp', function(args)
local fargs = args.fargs
Expand Down Expand Up @@ -67,6 +143,10 @@ function M.create_usercmds()
return { 'virtualtext', 'capture' }
end,
})

modelcmp_start()
modelcmp_stop()
modelcmp_logs()
end

return M
1 change: 1 addition & 0 deletions lua/model_cmp/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ local M = {}
---@return ModelCmp.Config
function M.default()
return {
delay = 1000,
api = apiconfig.default(),

virtualtext = {
Expand Down
11 changes: 5 additions & 6 deletions lua/model_cmp/context.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
local string = string
local M = {}

local function get_cursor()

return vim.api.nvim_win_get_cursor(0)
end

Expand All @@ -19,20 +19,20 @@ end

---@class ModelCmp.ContextEngine
---@field bufnr integer -- current buffer number
---@field id integer -- context id
---@field cursor integer[] -- current cursor pos
---@field ctx table<string, string[]> -- context
---@field currlang string -- current language eg: python, c, cpp, markdown
---@field id integer -- context id
---@field ctx table<string, string[]> -- context
M.ContextEngine = {
bufnr = vim.api.nvim_get_current_buf(),
id = 0, -- Need to think how to manipulate this this is imp to put the right virtual text for right context
cursor = { 0, 0 },
currlang = "text", -- default if none is set or found
id = 0, -- Need to think how to manipulate this this is imp to put the right virtual text for right context
ctx = {
before = {},
current = {},
after = {}
},
currlang = "text" -- default if none is set or found
}

function M.ContextEngine:get_ctx()
Expand Down Expand Up @@ -69,7 +69,6 @@ function M.generate_context_text()
end

-- current

local line = M.ContextEngine.ctx.current[1]
local col = M.ContextEngine.cursor[2]
if line == nil then
Expand Down
5 changes: 4 additions & 1 deletion lua/model_cmp/init.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
local api = require("model_cmp.modelapi.common")
local commands = require("model_cmp.commands")
local logger = require("model_cmp.logger")
local mainconfig = require("model_cmp.config")
local virtualtext = require("model_cmp.virtualtext")
local api = require("model_cmp.modelapi.common")

local M = {}

Expand All @@ -12,11 +13,13 @@ function M.setup(config)
local default_config = mainconfig.default()
config = vim.tbl_deep_extend('force', default_config, config)

commands.setup(config)
commands.create_autocmds(model_cmp_grp)
commands.create_usercmds()

virtualtext.setup(config)
api.setup(config)
logger.trace("Setup Completed for model-cmp.nvim")
end

return M
Loading