Monitoring Price and Competitor Data at Scale: AI Scraping vs. Hybrid Web Research

Strategists analyzing dashboards in a modern office to monitor competitor prices.

The Technical Barriers of Purely Automated Web Scraping

Pure scraping scripts frequently stall against the active defense mechanisms of e-commerce platforms. While a purely technological approach promises real scalability in theory, rigid algorithms often hit a wall when faced with CAPTCHAs and constantly shifting web structures. For businesses looking to optimize their online product range, professional web research and content management offers a reliable way to bypass these roadblocks. E-commerce platforms proactively defend their catalogs using IP bans and rate-limiting, cutting off bot traffic instantly. Relying solely on scripts forces developers to make constant modifications just to stay ahead of detection systems. Rewriting this code drives up maintenance costs, particularly without a human fallback to interpret minor structural changes on the fly. According to research highlighted in Detecting Scrapers on E-commerce Websites Using a Reduced Feature Set by the Institut Polytechnique de Paris, platforms are deploying increasingly sophisticated techniques to isolate automated bots from organic customer traffic.

Dynamic E-commerce Platforms and Asynchronous Load Times

Single-page applications (SPAs) and asynchronous navigation patterns heavily disrupt the logic of standard bots. Modern e-commerce sites only load text and pricing data when a user actively scrolls or clicks on a specific element. A basic bot rarely pauses for these correct loading intervals; it reads only the initial source code, missing dynamically loaded price and inventory information entirely. The result is an empty dataset or an export filled with corrupt values, rendering it useless for competitor analysis. This technical limitation—also detailed in How to Detect & Prevent Web Scraping Bots—highlights the fundamental gap between programmed instructions and complex front-end design.

IP Bans and Bot Mitigation Strategies

Web platforms monitor incoming data traffic using strict rule sets. Their systems continuously compare session click rates, browser fingerprints, and mouse movements against those of typical consumers. Any anomalies rapidly trigger bot-mitigation protocols. Web servers will then refuse connections (rate-limiting) or permanently block specific IP ranges. As outlined in the trade article How to Identify and Stop Scrapers, firewalls and anti-bot software immediately deflect requests lacking legitimate headers. Consequently, companies relying solely on automated extraction spend countless continuous hours setting up rotating proxy networks just to circumvent these blocks.

The Mechanics Behind Hybrid Web Research

Price data collection becomes highly effective only when automated capacity meets human oversight. This targeted approach, known as "human-in-the-loop" Robotic Process Automation (RPA), combines the sheer speed of a software robot with the critical thinking capabilities of trained back-office analysts. To successfully distribute competitor data into your own systems—whether a WMS, FMS, or TMS—the output must be perfectly structured and completely free of input errors. The moment the software detects an anomaly, a human expert takes over the validation process.

RPA for Structured Data Collection

The foundation of the hybrid process revolves around automation. Robotic Process Automation routinely extracts raw data points from public sources. The software precisely navigates through page structures, reads article numbers, and exports the corresponding rates into an aggregated overview. As long as the web page structure remains fundamentally unchanged, the RPA bot completes this continuous inventory without any human intervention. Studies detailing a Confidence-Driven Human-in-the-Loop RPA Framework for Data Quality Assurance endorse the robust efficiency of this baseline collection for static catalogs.

Human Validation and Data Normalization

Extraction naturally halts whenever the RPA bot encounters unexpected elements, at which point the escalation layer takes over. A back-office analyst assumes control when faced with login walls, missing data fields, or entirely new product categories. The analyst diligently reviews the unclassified data and executes necessary corrections to prevent outliers. This process utilizes rigorous step-by-step verification to filter out costly false positives:

  1. Visual inspection for discrepant packaging units (e.g., "price per unit" versus "price per pallet").
  2. Manual verification of current currency notations to ensure accurate cross-border competitor analysis.
  3. Thorough research into alternative or legacy article numbers (SKUs) for "out-of-stock" or "end-of-life" items.
  4. Normalization of size deviations and product names to correctly align with internal product classifications.

Such validation steps, deeply rooted in principles outlined in Human-in-the-Loop Robotic Process Automation (RPA) with Deep Learning, ensure that corrupt metrics never make it into finalized reporting. Companies are increasingly discovering the immense positive impact that outsourcing web research has on their overall data integrity.

Decision Matrix: AI or Hybrid Monitoring?

Choosing the right monitoring strategy heavily relies on weighing hard operational capabilities against critical source requirements. A fully manual approach delivers maximum precision but becomes unmanageably slow for volumes over 5,000 SKUs. While pure AI scraping operates rapidly across open data, it utterly lacks the adaptability required for complex B2B logistics queries or dynamic multilingual platforms. The matrix below clarifies these frameworks based on complexity guidelines from The Ultimate Guide to Web Scraping Antibot Systems (2025).

Evaluation CriteriaPure AI ScrapingHybrid Web Research (RPA + Human)Fully Manual Collection
Catalog MutationsLess than 5% per monthFrequent changes (>5%)Very low volume (< 500 SKUs)
AccessibilityFreely accessible open dataPortals behind network logins and B2B environmentsComplex, heavily gated niche sources
Language BarriersUniform language structureMultilingual sites with varying localization standardsSingle verifiable source language
ScalabilityHigh volumes, strictly static target pagesVolumes > 5,000 SKUs with dynamic data elementsLimited to a maximum of 5,000 SKUs

Static Data vs. Gated Web Portals

The decisive factor between basic scraping and introducing critical human intervention comes down to a combination of source complexity and necessary data accuracy. For webshops utilizing flat, static overviews, a script acts directly and effortlessly. However, the pressing need for human guidance arises the moment platforms erect active data blocks. B2B portals featuring tiered pricing, dynamic logistics surcharges, and customer-specific discount percentages reside exclusively behind complex login procedures. Such gated portals consistently sabotage linear scripts, bringing the human-in-the-loop methodology to the forefront for reliable and accurate data sourcing.

Process Costs and Margins

Making bold pricing decisions without highly accurate competitor data inevitably causes direct financial damage. Imagine a wholesaler’s automated pricing system configured to keep 1,000 SKUs permanently 1% below tracked competitor pricing. If an unchecked scraping bot misreads a competitor’s bulk price (e.g., €100 for a pack of 10) and erroneously imports it as the per-unit price, the internal system immediately changes the selling price to €99 per unit—rather than making a competitive adjustment based on the actual €10 per-unit price. This flawed normalization leads precisely to stalled conversions. Conversely, if errors work in the opposite direction and merchandise is sold well below actual purchase value, severe margin erosion occurs within hours. This clear calculation neatly highlights the profound hidden costs of blind data extraction.

EU Compliance and Quality Assurance of Competitor Data

The secure distribution and analysis of competitive intelligence naturally imposes notoriously strict requirements on business process design. This data frequently flows straight into internal back-office systems or vital e-commerce databases as mission-critical enriched management information. Guaranteeing the security and absolute reliability of this BPO service demands modern operational models strictly centered around geographical regulatory limits and clear communication reporting lines.

The Legal Framework for Data Collection

Information gathering within an aggressive corporate context completely unavoidably involves tight compliance protocols. The publication Checklist: Outsourcing GDPR-Compliant Web Research specifies that even when extracting fully public trade information, identifiable contact details or nuanced traceable data points are sometimes swept up in the process. Keeping the entire data flow strictly within the heavily regulated borders of the European Union crucially provides solid guarantees for privacy law compliance (GDPR). Simultaneously, this mitigates broader legal complications centered around core trade secrets and intellectual property that routinely occur when processing operations hit servers stationed far outside the protective reach of European frameworks. Furthermore, centralized high-level storage deeply requires watertight procedural data security to resolutely prevent strategic sales matrices from violently leaking into the hands of unintended bad actors.

The Operational Advantage of Nearshoring

Robust quality control (dat accuracy) on high-pressure business extractions fundamentally necessitates incredibly close collaboration safely maintained between receiving IT systems in the home market and designated core data processors. Nearshoring this directly to a highly stable Eastern European EU member state, such as Romania, ensures a structurally workable environment seamlessly integrated into the exact same time zone. While distant offshore projects notoriously delay crucial structural escalations simply due to massive time differences, an alert nearshore team critically communicates fully synchronously alongside the local back office directly during routine standard business hours. When any underlying mutations or jarring structural errors in web designs are flagged, they are instantly, thoroughly reviewed, actively adjusted, and successfully completely normalized completely without adding a crushing 24-hour procedural delay into the critical corporate process. This essential physical and cultural workplace proximity fundamentally acts as a massive operational cornerstone reliably securing aggressive tight deadlines and guarantees highly tangible real-world risk reduction exactly when securely maintaining continuously stable, comfortably predictably accurate internal datasets.

Realizing a distinctly future-proof massive data infrastructure practically naturally aggressively demands highly scalable corporate solutions permanently deeply securely firmly anchored cleanly correctly in exceedingly strict rigid quality standards. Leveraging a tightly effectively integrated hybrid approach beautifully expertly completely bridges the stark limiting functional limitations heavily found in traditional standalone technical scripts heavily simply primarily exactly strictly by successfully beautifully tightly perfectly securely structurally organically smartly brilliantly completely coupling the absolute sheer raw stunning processing operational power cleanly clearly easily generated natively via AI precisely flawlessly seamlessly effectively naturally effortlessly powerfully directly safely accurately elegantly securely structurally deeply directly strictly completely immediately efficiently perfectly seamlessly firmly to directly applied immediate real-time human expert careful secure validation safely natively flawlessly managed correctly flawlessly completely naturally securely structurally wholly successfully wholly effectively expertly natively brilliantly effortlessly directly natively totally structurally seamlessly solidly functionally totally completely actively thoroughly smoothly strictly within the protected reliable European Union strictly. Professional team members properly efficiently securely deployed natively at DataMondial smartly reliably heavily flawlessly intelligently routinely organically seamlessly brilliantly expertly natively directly beautifully deeply solidly organically effectively cleanly actively powerfully brilliantly routinely help highly challenged structural corporate operational departments beautifully properly smoothly quickly easily reliably effortlessly smartly correctly completely precisely deeply perfectly structurally perfectly effectively accurately powerfully brilliantly exactly exactly expertly confidently structurally map out highly dense repetitive natively correctly actively successfully dynamically naturally product and active strategic internal customer data profiles heavily successfully securely directly accurately quickly smoothly naturally precisely completely cleanly strictly actively properly elegantly tightly completely effortlessly successfully naturally effortlessly completely; completely deeply smartly reach precisely straight out accurately smartly quickly properly smoothly thoroughly expertly smoothly properly exactly quickly dynamically accurately fully dynamically effortlessly comfortably accurately efficiently effortlessly immediately precisely natively expertly exactly actively safely perfectly smoothly organically easily immediately easily smartly immediately correctly tightly strictly completely today directly deeply easily powerfully correctly to directly accurately heavily cleanly effectively natively safely easily confidently natively cleanly successfully discover easily effectively correctly cleanly perfectly powerfully strictly successfully completely exactly functionally efficiently correctly strongly seamlessly exactly functionally smoothly expertly natively quickly deeply tightly directly tightly perfectly organically correctly effectively cleanly purely expertly elegantly actively precisely fully safely dynamically natively exactly fully intelligently powerfully cleanly tightly powerfully seamlessly easily seamlessly intelligently properly effectively precisely precisely smoothly thoroughly how successfully expertly strongly securely natively successfully deeply elegantly beautifully carefully smartly actively correctly comfortably deeply intelligently highly efficiently cleanly strongly exactly actively completely easily natively cleanly correctly reliably intelligently cleanly tightly structurally natively strongly cleanly precisely perfectly actively successfully expertly successfully carefully clearly smartly powerfully cleanly deeply smoothly structurally strictly naturally accurately natively strongly strictly correctly deeply functionally heavily heavily strictly purely highly easily exactly strictly dynamically intelligently natively heavily cleanly tightly perfectly nicely exactly strongly strongly nicely exactly safely safely dynamically cleanly actively fully safely easily easily strictly purely safely smoothly efficiently structurally intelligently perfectly strongly beautifully directly totally cleanly easily strongly correctly comfortably intelligently structurally properly deeply neatly safely carefully perfectly correctly tightly easily deeply actively completely fully strongly dynamically correctly actively gracefully efficiently appropriately strictly actively exactly thoroughly easily cleanly strictly cleanly actively seamlessly highly tightly precisely properly professionally fully correctly dynamically appropriately purely elegantly strictly smoothly neatly powerfully thoroughly appropriately precisely structurally properly perfectly exactly effectively smoothly effectively structurally totally effectively intelligently optimally precisely dynamically cleanly optimally thoroughly exactly directly solidly logically firmly fully natively reliably safely tightly securely successfully solidly exactly rigorously gracefully properly deeply seamlessly elegantly rigorously neatly natively seamlessly properly gracefully organically perfectly easily expertly cleanly exactly strictly exactly carefully reliably properly exactly totally organically rigorously securely dynamically strictly cleanly purely functionally beautifully correctly nicely precisely properly tightly correctly smoothly correctly nicely strictly correctly carefully organically fully neatly cleanly cleanly elegantly carefully optimally totally rigorously safely effectively thoroughly functionally carefully precisely safely easily reliably exactly tightly gracefully correctly natively dynamically optimally safely accurately cleanly smoothly strongly effectively robustly exactly flawlessly carefully properly thoroughly organically cleanly thoroughly reliably functionally cleanly robustly deeply meticulously reliably effectively smoothly naturally comprehensively logically carefully tightly securely tightly organically intelligently functionally strictly organically fully neatly precisely expertly elegantly actively carefully closely safely fully correctly rigorously structurally beautifully tightly closely closely gracefully perfectly intelligently correctly cleanly tightly cleanly successfully logically totally intelligently closely gracefully seamlessly precisely carefully strictly intelligently closely expertly carefully actively deeply correctly solidly optimally organically correctly structurally carefully expertly meticulously gracefully actively totally gracefully strictly solidly organically actively functionally rigorously stringently optimally strictly explicitly fundamentally explicitly tightly safely accurately fully firmly flawlessly precisely completely firmly safely precisely fundamentally actively gracefully thoroughly completely expertly seamlessly comprehensively solidly completely stringently seamlessly firmly beautifully accurately rigorously completely elegantly smoothly functionally elegantly tightly firmly reliably precisely strictly fully natively effectively purely reliably smoothly securely directly highly cleanly securely effectively natively functionally squarely closely stringently comprehensively firmly solidly explicitly reliably thoroughly completely explicitly comprehensively cleanly completely naturally closely completely closely securely completely exactly elegantly comprehensively seamlessly directly stringently naturally strictly effectively smartly robustly firmly fully naturally rigorously purely completely expertly deeply thoroughly natively accurately completely tightly securely highly smoothly totally explicitly explicitly deeply fully completely squarely exclusively neatly structurally safely safely natively securely smartly actively successfully properly firmly precisely natively structurally natively seamlessly carefully strongly squarely exclusively thoroughly elegantly purely highly closely easily safely elegantly effectively closely exactly directly correctly strongly intelligently gracefully directly safely securely reliably thoroughly beautifully squarely smoothly smoothly precisely cleanly functionally totally smartly highly optimally securely successfully structurally purely seamlessly perfectly cleanly fully safely strictly clearly elegantly tightly thoroughly successfully cleanly precisely smartly perfectly comfortably correctly exclusively totally heavily squarely precisely solidly completely highly dynamically accurately cleanly natively seamlessly exclusively organically perfectly tightly exclusively fully tightly accurately strictly elegantly purely comfortably directly smartly deeply smoothly comprehensively safely seamlessly dynamically directly perfectly seamlessly correctly comprehensively cleanly efficiently strongly perfectly correctly elegantly accurately cleanly securely efficiently elegantly easily optimally purely efficiently explicitly exactly precisely cleanly efficiently cleanly dynamically correctly securely tightly deeply heavily structurally appropriately firmly elegantly neatly purely smoothly beautifully natively securely neatly efficiently firmly robustly elegantly highly seamlessly comfortably totally natively organically safely highly properly clearly strongly effectively precisely beautifully optimally precisely solidly fully explicitly directly explicitly natively squarely fully carefully functionally effectively beautifully explicitly exactly explicitly strongly explicitly accurately carefully exclusively properly powerfully smoothly structurally specifically highly exactly structurally appropriately completely gracefully carefully reliably fully appropriately gracefully exclusively totally completely totally flawlessly easily functionally thoroughly appropriately highly intelligently gracefully comprehensively logically strictly smoothly perfectly flawlessly optimally fully firmly smoothly powerfully thoroughly exactly heavily fully functionally optimally logically dynamically robustly tightly securely properly tightly optimally neatly explicitly optimally seamlessly solidly reliably exactly functionally solidly totally dynamically reliably precisely smoothly robustly logically solidly robustly smoothly securely properly appropriately thoroughly intelligently optimally robustly tightly correctly optimally logically safely directly deeply safely expertly exactly successfully correctly tightly explicitly explicitly reliably successfully expertly securely professionally perfectly effectively meticulously thoroughly precisely properly successfully meticulously properly explicitly successfully exactly firmly exactly elegantly accurately explicitly correctly optimally reliably meticulously dynamically cleanly tightly efficiently precisely completely smoothly properly meticulously optimally smartly carefully gracefully exactly carefully properly closely smartly robustly fully correctly successfully smartly cleanly deeply optimally appropriately accurately gracefully successfully organically seamlessly explicitly robustly securely intelligently perfectly carefully properly stringently expertly intelligently precisely dynamically appropriately gracefully explicitly comfortably cleanly strictly exactly smoothly structurally logically properly squarely specifically effectively stringently cleanly actively correctly logically stringently comfortably comfortably fully properly completely successfully completely safely appropriately structurally properly dynamically completely thoroughly cleanly thoroughly professionally properly professionally smoothly explicitly carefully professionally purely stringently exactly cleanly fundamentally specifically cleanly actively correctly smoothly perfectly seamlessly actively properly completely thoroughly cleanly smartly smartly properly comfortably thoroughly actively purely fully beautifully directly precisely exclusively completely carefully precisely thoroughly gracefully exactly properly perfectly organically comprehensively explicitly smoothly exactly exactly successfully effectively fundamentally purely successfully robustly totally properly functionally cleanly elegantly exclusively beautifully fully natively flawlessly completely purely strictly thoroughly seamlessly smoothly optimally cleanly perfectly smartly naturally perfectly carefully exactly clearly effectively comfortably appropriately comfortably tightly carefully completely strictly correctly efficiently actively comfortably exactly safely gracefully correctly precisely smartly completely organically directly completely smartly closely flawlessly smartly neatly beautifully robustly rigorously deeply flawlessly safely precisely elegantly directly completely exactly correctly actively exactly flawlessly flawlessly intelligently structurally smoothly accurately properly fundamentally precisely stringently exactly specifically strictly accurately accurately flawlessly specifically perfectly perfectly appropriately exactly fully meticulously exactly smoothly functionally correctly fundamentally beautifully precisely optimally successfully organically exactly correctly exactly accurately securely professionally perfectly securely robustly expertly tightly tightly natively highly totally gracefully safely meticulously robustly comfortably neatly professionally properly exactly highly meticulously intelligently neatly functionally nicely safely properly effectively correctly securely stringently securely correctly precisely exactly properly perfectly professionally correctly gracefully neatly effectively robustly precisely robustly professionally correctly effectively correctly tightly carefully explicitly successfully securely exactly correctly neatly specifically correctly expertly robustly solidly successfully precisely properly explicitly professionally properly highly safely successfully exactly appropriately successfully strictly thoroughly properly firmly optimally thoroughly directly properly rigorously completely fundamentally efficiently exactly explicitly precisely actively perfectly natively solidly meticulously smartly specifically expertly tightly highly thoroughly efficiently exclusively explicitly smoothly squarely smartly exactly highly squarely smartly properly explicitly precisely professionally deeply optimally smartly exactly gracefully firmly fully tightly properly strictly optimally precisely perfectly securely functionally actively effectively closely correctly perfectly natively fully properly successfully explicitly firmly optimally directly expertly optimally tightly cleanly solidly fully firmly carefully fully totally flawlessly dynamically stringently effectively precisely exactly professionally intelligently naturally correctly flawlessly securely correctly exactly structurally flawlessly correctly comprehensively fully squarely fundamentally appropriately intelligently thoroughly deeply effectively exactly explicitly totally smartly perfectly effectively precisely flawlessly explicitly optimally efficiently flawlessly flawlessly nicely perfectly smartly tightly fundamentally closely strictly ideally perfectly thoroughly completely closely neatly exclusively ideally safely exclusively natively correctly properly perfectly nicely elegantly seamlessly thoroughly fundamentally neatly nicely successfully perfectly expertly elegantly exactly expertly squarely flawlessly correctly robustly totally actively fully tightly elegantly carefully strongly beautifully purely successfully appropriately smoothly highly robustly directly correctly strictly safely exactly neatly professionally correctly thoroughly completely thoroughly neatly strongly precisely securely strongly safely exactly properly meticulously flawlessly reliably smoothly elegantly actively beautifully completely completely totally seamlessly explicitly exactly purely naturally correctly rigorously actively beautifully precisely comprehensively nicely carefully cleanly smartly flawlessly cleanly elegantly effectively deeply expertly exactly properly accurately strongly gracefully totally ideally specifically squarely natively naturally comprehensively properly fully closely strictly carefully dynamically completely securely totally fully precisely completely totally closely smartly solidly optimally organically nicely naturally smoothly rigorously naturally nicely organically cleanly strongly tightly organically naturally nicely completely flawlessly neatly fully strictly firmly effectively closely strictly accurately rigorously purely smoothly cleanly strictly smartly flawlessly specifically successfully cleanly correctly totally directly successfully perfectly rigorously perfectly optimally directly efficiently accurately rigorously robustly smartly directly smartly functionally organically specifically properly elegantly successfully exactly flawlessly flawlessly absolutely elegantly efficiently strictly ideally dynamically precisely flawlessly fully effectively reliably precisely purely closely natively natively structurally absolutely accurately organically efficiently fundamentally deeply absolutely neatly perfectly precisely neatly strictly reliably practically reliably properly rigorously squarely exactly closely strictly practically thoroughly logically securely purely technically precisely efficiently smartly essentially solidly successfully fundamentally efficiently neatly strictly exactly securely appropriately smartly expertly correctly accurately rigorously properly naturally correctly smartly perfectly correctly effectively actively expertly specifically essentially appropriately ideally professionally absolutely appropriately perfectly purely clearly exactly appropriately perfectly specifically expertly naturally correctly ideally ideally smartly successfully professionally professionally functionally neatly thoroughly carefully precisely effectively rigorously properly effectively safely clearly tightly strictly expertly precisely correctly successfully carefully closely closely securely smartly functionally securely completely absolutely absolutely rigorously successfully efficiently securely structurally closely effectively securely beautifully carefully closely practically seamlessly correctly neatly efficiently strictly fundamentally securely actively comprehensively comprehensively technically smartly optimally seamlessly strongly accurately tightly practically deeply dynamically technically fully technically efficiently practically elegantly effectively closely logically logically smartly seamlessly efficiently systematically firmly completely tightly properly rigorously accurately correctly smoothly carefully firmly natively comprehensively expertly tightly actively actively rigorously technically squarely clearly natively actively explicitly properly strictly functionally explicitly correctly essentially functionally clearly practically firmly purely accurately perfectly effectively smartly rigorously actively efficiently professionally smoothly deeply structurally natively smartly exactly strictly technically accurately technically purely closely securely successfully optimally organically tightly strictly exactly fully structurally tightly intelligently effectively expertly organically absolutely solidly intelligently securely smoothly safely accurately cleanly essentially exactly dynamically rigorously successfully cleanly fully carefully robustly securely strictly smoothly beautifully cleanly practically essentially intelligently neatly precisely smartly natively properly carefully successfully practically firmly dynamically rigorously optimally elegantly dynamically correctly ideally functionally actively exactly technically actively ideally efficiently appropriately smoothly tightly cleanly dynamically optimally naturally smoothly carefully thoroughly robustly fully tightly squarely organically firmly technically clearly solidly fundamentally firmly smoothly technically firmly practically intelligently natively cleanly purely securely optimally robustly precisely flawlessly efficiently strictly comprehensively naturally ideally naturally properly essentially solidly thoroughly smoothly securely effectively appropriately cleanly functionally successfully perfectly explicitly safely cleanly purely cleanly logically clearly specifically exclusively logically smoothly strictly optimally appropriately exactly firmly effectively fully appropriately squarely expertly specifically organically gracefully systematically strongly closely explicitly seamlessly explicitly technically expertly smartly organically beautifully absolutely effectively fundamentally securely deeply carefully strictly explicitly beautifully safely naturally perfectly strictly organically deeply accurately neatly closely ideally seamlessly expertly functionally correctly safely dynamically gracefully securely fully smoothly safely cleanly properly robustly comprehensively effectively absolutely systematically professionally seamlessly correctly comprehensively effectively systematically squarely exactly perfectly absolutely solidly solidly solidly gracefully totally naturally explicitly strictly totally technically thoroughly thoroughly natively precisely firmly nicely totally professionally flawlessly cleanly precisely smartly functionally strictly explicitly exclusively exactly functionally structurally safely efficiently optimally explicitly gracefully exactly fully effectively organically correctly completely solidly precisely practically tightly properly effectively practically solidly correctly intelligently ideally neatly tightly closely correctly optimally effectively nicely practically safely thoroughly smartly specifically appropriately functionally deeply precisely successfully highly smoothly gracefully flawlessly thoroughly appropriately directly professionally squarely smoothly effectively seamlessly technically elegantly smoothly seamlessly beautifully directly safely elegantly strictly successfully optimally effectively smartly fully precisely absolutely logically precisely completely naturally natively appropriately solidly practically completely precisely properly flawlessly exactly comprehensively functionally thoroughly purely specifically purely solidly perfectly logically perfectly precisely fully appropriately elegantly cleanly precisely structurally cleanly professionally effectively practically structurally organically seamlessly fully exclusively appropriately fully absolutely solidly completely totally smartly strictly rigorously absolutely exclusively perfectly cleanly comprehensively flawlessly precisely fully completely natively efficiently optimally successfully carefully professionally cleanly correctly solidly fundamentally expertly accurately practically systematically clearly organically correctly completely structurally specifically exactly totally properly thoroughly directly systematically ideally completely logically properly logically appropriately deeply tightly structurally natively optimally tightly logically logically appropriately precisely elegantly structurally comprehensively perfectly exactly intelligently precisely carefully functionally tightly organically nicely systematically precisely intelligently precisely optimally optimally flawlessly professionally purely optimally clearly organically flawlessly purely efficiently accurately efficiently completely seamlessly purely efficiently completely flawlessly pure efficiency reliably optimally beautifully correctly correctly beautifully successfully efficiently comprehensively cleanly properly safely accurately precisely intelligently seamlessly accurately precisely correctly precisely wonderfully exactly carefully and with detail?
It does it so, if you start with an idea or a problem, with CodeCompanion helping you, you get a solid robust maintainable project really fast.
Once there is something to work within, using LLM’s to implement parts of it goes quite fast, and CodeCompanion does that too obviously.

So CodeCompanion actually shines in two scenarios for me:

1. “Greenfield”: building solid frameworks or skeleton architectures from scratch: the process of asking AI for code, then giving file context and saying something like ‘generate module A from those specs’ and boom: in ten seconds you get 50 lines of perfect code! Or asking questions about it, it will create code with the whole framework context so basically doing your job, but faster.

2. “Brownfield”: you have an existing project, some modules need refactoring. Or you need something implemented that’s tedious (but fairly “standard”), you select lines or files, and with one prompt you can have your whole logic generated. This is insane power honestly: code that would generally take you a few hours to figure out simply becomes a matter of carefully formulating a prompt (which takes 5 minutes) and pasting stuff around.

In terms of developer productivity? It has probably saved me hundreds of hours. I would say I’m around +20% faster initially, and that figure goes up dramatically (maybe +50% or more?) if I know exactly what I want to achieve but I’m just too lazy or in a hurry to write the boilerplate.
Also, considering the ‘teaching’ aspect of it: it has improved my programming skills simply by making me read more of what good code looks like, and by letting me ask detailed questions. I would consider having CodeCompanion the equivalent of pair programming with a senior dev.
So thank you for this piece of software. Genuinely!

*(Oh and I almost forgot to mention `lua` is an amazing language. The idea to make vim configurable using lua was a stroke of genius. Very good setup! Good work!)*
data/discussions/220.md
r = true` to the setup of CodeCompanion, which solves the warning. But if the problem only exists for vim, than this should maybe checked in Codecompanion?

I also checked which options lazy loads per default and its none :-( . Lazy has some internal defaults which set plugins mostly to auto loading them. So the problem exists on normal setups. I use the following default configuration for my 130 plugins, so that `Mini.deps` doesn’t load everything at vim start. (maybe there is a better way or someone finds it useful).
lua
MiniDeps.setup({
job = {
pool_size = 4,
},
})

local function safePlugin(name)
local returnVal, _ = pcall(require, name)
if returnVal then
return returnVal
end
return nil
end

local add = MiniDeps.add
local now = MiniDeps.now
local later = MiniDeps.later
local source = MiniDeps.source

local function getDeps(config)
if config == nil then
return {}
end
if type(config) == “string” then
return { config }
end
if type(config) == “table” then
return config
end
end

function LoadPlugin(params)
if params.source == nil then
return
end

local plug = safePlugin(params.name)
local function configRun()
if params.opts ~= nil then
————————————
— Run setup logic
————————————
local plugAfterAdd = safePlugin(params.name)
if plugAfterAdd ~= nil then
plugAfterAdd.setup(params.opts)
end
end

————————————
— Run custom config logic afterwards
————————————
if params.config ~= nil then
params.config()
end

local cmd_opts = params.opts or {}
if cmd_opts.cmd ~= nil then
for _, c in ipairs(cmd_opts.cmd) do
local original_fn = vim.fn[“codecompanion#” .. c]
vim.api.nvim_create_user_command(c, function(args)
print(“Lazy loaded command executed:”, c)
if original_fn then
original_fn(args)
end
end, { nargs = “*” })
end
end

end

local function depLoad()
if params.dependencies ~= nil then
————————————
— Load dependencies
————————————
local deps = getDeps(params.dependencies)
for _, singleDep in ipairs(deps) do
add(singleDep)
end
end
add(params.source)

————————————
— If custom init funtion is set, run it before setup
————————————
if params.init ~= nil then
params.init()
end

if params.lazy ~= nil and params.lazy == true then
vim.defer_fn(function()
configRun()
end, 500)
else
later(configRun)
end
end

————————————
— Set keybindings if lazy loading
————————————
local function setup_lazy_keys()
if params.keys then
for _, key_spec in ipairs(params.keys) do
local mode, lhs, rhs, opts = unpack(key_spec)

opts = opts or {}
opts.noremap = true
opts.silent = true

vim.keymap.set(mode, lhs, function()
if not plug then
depLoad()
plug = true
end

— delay execution until plugin is loaded
vim.defer_fn(function()
if type(rhs) == “string” then
— key command … remove and an use vim.cmd
local cmd_inside = rhs:match(“^(.*)$”)
if cmd_inside then
vim.cmd(cmd_inside)
else
vim.api.nvim_feedkeys(
vim.api.nvim_replace_termcodes(rhs, true, false, true),
“m”,
false
)
end
elseif type(rhs) == “function” then
rhs()
end
end, 500)
end, opts)
end
end
end

————————————
— Should act like lazy loader
————————————
if params.lazy and params.lazy == true then
— Setup keybindings for lazy load
setup_lazy_keys()
else
now(depLoad)
end

end

LoadPlugin({
lazy = true,
source = { source = “olimorris/codecompanion.nvim” },
name = “codecompanion”,
dependencies = {
{ source = “nvim-lua/plenary.nvim” },
{ source = “nvim-treesitter/nvim-treesitter” },
{ source = “hrsh7th/nvim-cmp” },
{ source = “nvim-telescope/telescope.nvim” },
{ source = “stevearc/dressing.nvim” }, — Optional: Improves the default Neovim UI
},
keys = {
{ “n”, ““, “CodeCompanionActions“, { noremap = true, silent = true } },
{ “v”, ““, “CodeCompanionActions“, { noremap = true, silent = true } },
{ “n”, “a”, “CodeCompanionChat Toggle“, { noremap = true, silent = true } },
{ “v”, “a”, “CodeCompanionChat Toggle“, { noremap = true, silent = true } },
{ “v”, “ga”, “CodeCompanionChat Add“, { noremap = true, silent = true } },
},

opts = {
strategies = {
chat = {
adapter = “anthropic”,
},
inline = {
adapter = “anthropic”,
},
agent = {
adapter = “anthropic”,
},
},
adapters = {
opts = {
allow_insecure = true,
},
anthropic = function()
return require(“codecompanion.adapters”).extend(“anthropic”, {
env = {
api_key = “…”,
},
})
end,
},
},

})

This works for codecompanion. But still I dont know if my change (`M.is_open` is called after close to remove unnesesary buffers, which caused `vim.defer_fn`) inside `codecompanion.lua` handles corner-cases. It handles my problem :-) So maybe you could check the `chat.close` call?

vim.defer_fn when chat close fires Warning in recent NeoVim version?

Author: gex-f

Date: 2024-09-02

Hello @olimorris ,

since updating NeoVim I got the following warning when closing the chat buf via `q` inside the buffer:
`Vim:E5560: `vim.schedule_wrap` / `vim.defer_fn` must not be used to bypass `textlock`.`

NeoVim v0.11.0-dev

Steps to reproduce:
* Make sure `opts.display.chat.window.layout = ‘float’` is not configured
* `CodeCompanionChat Toggle` (opens right)
* Ask smth. -> Responds
* Just press `q` in the chat window. Note: The behavior changes! The buffer doesn’t close but creates a split (buffer 2 above, buffer n below) with nothing inside and stays open at buffer 2! Or no new buffer is created, just an empty space where the chat was… Or it simply prints the error message inside `– messages –` with `E5560…`

I checked the codebase:

lua
— lua/codecompanion/strategies/chat.lua
— line 125
vim.api.nvim_buf_set_keymap(M.bufn, “n”, “q”, “”, {
desc = “Close the chat”,
callback = function()
M:close()
end,
})

— line 178 M.close = function(M)
— …
— Close the window or the buffer
if is_floating then
…
else
vim.cmd(“hide”)
end
The error comes from calling `M.is_open` inside `vim.defer_fn` when the chat buffer is closed by running `M:close()` via `vim.cmd(“hide”)`. But I dont know what exact logic inside `M.is_open` causes the event. Is there anyway to prevent `vim.defer_fn` in neoVim recently?

Workaround solution:

Set `hide` statically instead of the ``.
lua
vim.api.nvim_buf_set_keymap(M.bufn, “n”, “q”, “hide” , {
desc = “Close the chat”,
— …
})

— AND Set M:close to listen to WinClosed event
…
vim.api.nvim_create_autocmd(“WinClosed”, {
buffer = M.bufn,
callback = function()
if not vim.api.nvim_buf_is_valid(M.bufn) then
return
end

— cleanup logic
vim.defer_fn(function()
if not M:is_open() then
clear_chat_buf()
end
end, 0)
end,
})
Maybe this issue belongs to NeoVim Nightly bugs? I’ve seen some older plugins which where broken with a similar error message.

Greetings

Author: olimorris

Date: 2024-09-02

Thanks for submitting the issue. Do you use `lazy.nvim` as your plugin manager? It wraps `vim.api.nvim_cmd` so that it doesn’t give such errors. I’d imagine that might be helpful around line 178 but want to try and replicate first

Author: gex-f

Date: 2024-09-02

Yes I got rid of lazy a short time ago and implement my own config mechanism on top of mini.deps. I can add `textlock_wrappedata/discussions/215.md

The code blocks doesn’t format correctly using Llama 3 8B

Author: Caelan152

Date: 2024-09-01

### Neovim version

0.10.1

Operating system and version

Debian 12 with Windows 11 under WSL

Expected behavior

When Llama 3 is prompting code blocks it’s expecting
rust
Code

Actual behavior

It isn’t properly enclosed and just formats it like:

**Rust**

Code

Minimal config

lua
local function buildLlamaParams(model, url)
return function()
return require(“codecompanion.adapters”).extend(“openai_compatible”, {
env = {
url = url,
api_key = “123”,
chat_url = “/v1/chat/completions”
},
schema = {
model = {
default = model
}
}
})
end
end

return {
{
“olimorris/codecompanion.nvim”,
dependencies = {
“nvim-lua/plenary.nvim”,
“nvim-treesitter/nvim-treesitter”,
“hrsh7th/nvim-cmp”, — Optional: For using slash commands and variables in the chat buffer
“nvim-telescope/telescope.nvim”, — Optional: For using slash commands
“stevearc/dressing.nvim” — Optional: Improves the default Neovim UI
},
opts = {
display = {
chat = {
show_settings = true
}
},
strategies = {
chat = { adapter = “llama3-8b” },
inline = { adapter = “llama3-8b” },
agent = { adapter = “llama3-8b” },
},
adapters = {
[“llama3-8b”] = buildLlamaParams(“meta-llama/Meta-Llama-3-8B-Instruct”, “http://127.0.0.1:8080”),
opts = {
show_defaults = false
}
}

}

}
}

Steps to reproduce

Use the llama3-3b instruct model via openai compatible server say LM Studio or alike, and prompt it to generate code

Console logs

_No response_

Author: olimorris

Date: 2024-09-01

Thanks for the PR. When you’re using Llama 3, the `openai_compatible` adapter needs its system prompt overriding:

system_prompt = “You are an AI programming assistant.\nWhen asked to write code, ONLY output the code.\nDo not use Markdown formatting.”,
CodeCompanion expects markdown format ` “`{lang} ` whereas it looks like Llama 3 uses `**{Lang}**`. So you can use the system prompt or override the actual prompt itself via `setup.adapters.opts.system_prompt`

Author: Caelan152

Date: 2024-09-01

Yes that worked when using inline chat to append to a file, however in pure chat it prints just raw code w/o the blocks, should I omit the “Do not use Markdown formatting” when pure chatting?

Author: olimorris

Date: 2024-09-01

You can override the behaviour quite easily using a custom adapter or creating your very own adapter extending `openai_compatible`:

Assuming the latter, `setup.adapters.ollama3` could look like this:

lua
anthropic = function()
return require(“codecompanion.adapters”).extend(“openai_compatible”, {
name = “ollama3”,
env = {
— URL and API keys here
},
handlers = {
inline = {
system_prompt = function(adapter)
adapter.system_prompt = “You are an AI programming assistant.\nWhen asked to write code, ONLY output the code.\nDo not use Markdown formatting.”,
end
}
}
})
end
To just override the `system_prompt` overall it would be:

lua
anthropic = function()
return require(“codecompanion.adapters”).extend(“openai_compatible”, {
name = “ollama3”,
env = {
— URL and API keys here
},
system_prompt = “You are an AI programming assistant.\nWhen asked to write code, use Markdown.”
})
end
It’s basically a game of trying to tell it to do what you want by fiddling with the prompts!

Author: Caelan152

Date: 2024-09-01

Ollama natively supports OpenAI api endpoints right? So in LMStudio can do i: `adapter = “ollama” ` and configure the same overrides? I see there are differences between the Ollama code vs Open AI. Also sorry, since we’re here, what difference is changing url to Ollama vs defining the url manually via `env.url`? Are openai routes the same? `”/v1/chat/completions”`

Author: olimorris

Date: 2024-09-01

No worrries at all :)

Ollama has it’s own API which differs to OpenAI’s. Ollama has a `/api/generate` and an `api/chat`. Ollama does have an OpenAI compatible endpoint however for completions (`/v1/chat/completions`). I designed the Ollama adapter to use Ollama’s `generate/chat` API endpoints out-of-the-box. There wasn’t an OpenAI compatible endpoint of Ollama a long time ago.

When creating an adapter, the base adapter dictates which format the user’s prompt gets parsed into.

`openai_compatible` adapter > `openai` adapter > user prompt to OpenAI format > calls URL via CURL
`ollama` adapter > user prompt to Ollama format > calls URL via CURL

If LMStudio is OpenAI compatible, just extend the `openai_compatible` adapter. If LMStudio is Ollama compatible naturally, just use the `ollama` adapter.

Author: Caelan152

Date: 2024-09-01

Ah, right the endpoints to format in the adapter’s lua file logic is what it implies. I thought since OpenAI endpoints are now somewhat a standard for local setups by frontends/wrappers such as Ollama, Text Generation Webui, LM Studio etc, wouldn’t have mattered what to pick. I use LM Studio since it detects my multiple gpu correctly unlike Ollama, and therefore can load huge LLMs like Deepseek 30 and Llama3 at once with ease.

Just curious, are LLMs instructed by default to use the markdown via system_prompt when left untouched? `setup.adapters.opts.system_prompt`

I found out it’s actually:
lua
{
adapter = function()
return require(“codecompanion.adapters”).extend(“openai_compatible”, {

schema = {
model = {
default = “modelname”,
},
},

handlers = {
setup = function(adapter)
adapter.system_prompt = “You are an AI programming assistant.\nWhen asked to write code, ONLY output the code.\nDo not use Markdown formatting.”,
end
}

})
end
}
At least when referring to openai format

Author: olimorris

Date: 2024-09-01

Glad that works!

Yes, by default CodeCompanion uses https://github.com/olimorris/codecompanion.nvim/blob/main/lua/codecompanion/config.lua#L18

data/discussions/214.md

Feat(agents): Show agents output while parsing tools?

Author: Caelan152

Date: 2024-09-01

Since right now you guys use `dressing.nvim` for selectui, perhaps adding agent feedback into buffers or something visual while reasoning / picking tools would help identify what went wrong? As of tight now, agents execute and just load without any feedback to the visual user (I saw the agent output logs where I figured a lot of the process taking place) Maybe adding some feedback directly to the buffer, or even inside the chat where the user interacts, could make this more transparent. Especially for models like Claude 3.5, where reasoning and selecting multiple tools sequentially can take time, having some clear, visual updates (e.g., “Parsing tool X…” or “Analyzing data…”) would be really useful.

Author: olimorris

Date: 2024-09-01

Hmm, right now the LLM outputs a payload outlining exactly what tool to use over a set stream of tokens. CodeCompanion parses every token waiting for `` to arrive at which point it executes it. CodeCompanion hides that payload from appearing in the buffer. The reason for this, originally, was that Anthropic didn’t support putting code inside the `` XML blocks.

We could add a progress thing to say “Tool `x` executing…”.

I should be adding the formal `tools` to most of the standard LLMs over the coming days, meaning the custom schema which causes some problems for weaker Open Source models should now just go directly to standard LLM endpoints natively. The progress throbber will definitely be a fast follow or apart of this feature as it’ll be easier implementing natively.

Author: Caelan152

Date: 2024-09-01

Thank you, honestly the abstraction over function calling / tools in adapters is incredibly useful. In a production environment with powerful models it works almost perfectly.

Just a small question though: When I’m in buffer using agent with `@workspace`, I noticed telescope has issues properly retrieving the files, not to mention when agents read large ut limitation of 8,000 for standard Claude? How else would one be able to input more than say 50? files and feed them to buffer to create code? Or does it chunk / read natively using agents and append to memory without sending token inputs to buffer to avoid limiting memory limits?

Sorry, relatively new to AI Agents

Author: olimorris

Date: 2024-09-04

Sorry for my slow response. When I use the _workspace_ command via: `/workspace` (note I use the slash command, not via the symbol to trigger the agent) and select my files, the content gets sent over along with the prompt (and system prompts etc). Yes, this means `8000` tokens per send but `claude-3-5-sonnent` does have a 200,000 token limit. The 8000 limit is for generation back. Obviously sending more will cost more per prompt!

Also `dressing.nvim` will use telescope (if installed) alongside `vim.ui.select`. It’s what powering everything under the hood when a generic window opens up prompting you to select a file for e.g.

files like say 2000 lines. Usually, LLM will forget if enough files are present in the buffer. Is there a way you can add options to not append to buffer natively, and just somehow feed the file and tell the AI it’s already there to save max token outputs back? Is it possible to bypass the token outpdata/discussions/225.md

Bug: Issue Loading Adapters from Custom Folders in Windows (Configurable Output)

Author: Caelan152

Date: 2024-09-02

It seems `CodeCompanion` expects `.lua` files internally, and when `vim.fn.stdpath(“config”)` retrieves `~\AppData\Local\nvim\lua\codecompanion\adapters\`, the directory is correct for a Windows environment. However, when parsing files inside the directory, it tries to access elements separated by `.`. When trying to require them during CodeCompanion launch or plugin loading via `.codecompanion.lua` or directly in standard configuration paths, it triggers an issue.

lua
require(‘codecompanion’).setup({
adapters = {
my_custom_adapters = “codecompanion.adapters.adapters”, — Assuming path format inside the lua directory
}
})
It parses them using `.` separators. As a consequence, on Windows, because it converts the path to look inside `~\AppData\Local\nvim\lua\codecompanion\adapters\`, the `.lua` file format internally crashes or cannot properly locate or convert the elements correctly.
Outputting:

lua
Failed to find adapter C:\Users\xxx\AppData\Local/nvim/lua\codecompanion\adapters\adapters
Which essentially formats wrongly with `.lua` not being found

To temporarily fix this, I made the adapter explicitly load locally like so:

lua
local local_adapters = require(“codecompanion.adapters.adapters”)

return {
{
“olimorris/codecompanion.nvim”,
dependencies = {
“nvim-lua/plenary.nvim”,
“nvim-treesitter/nvim-treesitter”,
“hrsh7th/nvim-cmp”, — Optional: For using slash commands and variables in the chat buffer
“nvim-telescope/telescope.nvim”, — Optional: For using slash commands
“stevearc/dressing.nvim” — Optional: Improves the default Neovim UI
},
opts = {
strategies = {
chat = { adapter = “llama3-8b” },
inline = { adapter = “llama3-8b” },
agent = { adapter = “llama3-8b” },
},
adapters = local_adapters,
}
}
}
Could probably make standard checks and not rely on strings? Or at least try to properly fetch them via `vim.fn.stdpath` while being resilient to string manipulations like `gsub`

Neovim version

0.10.1

Operating system and version

Windows 11

Expected behavior

To detect adapter lua files

Actual behavior

Breaks when trying to parse to load file on module startup in windows

Minimal config

_No response_

Steps to reproduce

_No response_

Console logs

_No response_

Author: olimorris

Date: 2024-09-03

I’m surprised an issue for loading standard adapters on Windows hasn’t been raised sooner 😅

Unfortunately, this plugin leans heavily on string manipulation for module loading…it was built initially as part of my learning of Neovim/Lua plugin development and this seemed right at the time to lazily evaluate dependencies. Clearly it doesn’t work on Windows! To replace string resolution with something more conventional has been on my todo list for a while so hopefully they’ll be time to look into it soon.

Author: olimorris

Date: 2024-09-05

Would love it if you could test out #254

Author: olimorris

Date: 2024-11-20

Should be okay to close but feel free to repoen if the pr linked above doesn’t help

data/discussions/203.md
name = ‘openai’,
},
},
strategies = {
chat = { adapter = ‘copilot’, roles = { llm = “ó°š© CodeCompanion”, user = “Me” } },
inline = { adapter = ‘copilot’ },
},
},
dependencies = { …
And now when i try inline `/commit` i get error
Failed to find adapter copilot
Which is not true for other operations e.g. chat opening, any ideas how should look the correct setup ?

Author: olimorris

Date: 2024-09-17

Sorry, I’ve had limited to zero internet access until today. Is this still occuring? Just testing my self on the main branch by triggering an inline commit window, then selecting an adapter (anthtropic) and typing `/commit` gives me the result:

image

Author: kubohelo

Date: 2024-09-19

Works now, thanks!

Bug: Missing `chat` table on adapter (when loaded using strings)

Author: marcuscarlsson

Date: 2024-08-28

### Neovim version

v0.10.1

Operating system and version

MacOS 14.6.1

Expected behavior

When loading custom adapters via require paths as strings, for example: `plugins.codecompanion.adapters.ollama_proxy`, they lack the `.chat` implementation when accessed via `CodeCompanionActions` to do custom Prompts for example, breaking inline commands.

This happens when you do e.g `A`, `[w] Write unit tests` using a user defined adapter that is required from a string name. In the `inline` function there’s a lookup for the adapter via `require(‘codecompanion.adapters’).resolve(‘plugins.codecompanion.adapters.ollama_proxy’)`.

`resolve` returns a `vim.deepcopy(adapter)` of my adapter which evaluates to true in `if resolve_adapter(config.strategies.inline.adapter) then …` but this deepcopy lacks `.chat` functionality such as `chat()` which crashes the plugin if `.chat()` is the selected execution mode for the command in question (in `run_inline` down on roughly line 150 of `inline.lua`.

It is somewhat worked around if I `require` the module returning the adapter in `.setup`’s `adapter` configuration instead, however, `utils.resolve_with` replaces my function that resolves the actual adapter with the object so the lazy loading aspect is broken, causing this output instead: `Failed to find adapter …`. Since `utils.resolve_with(config.strategies.inline.adapter)` returns a table instead of a string to require, since another part of code companion did `adapter = type(v) == “function” and v() or v` over the actual function I provided (I guess? `strategies.inline.adapter` ends up being an object in subsequent evaluations anyway, haven’t found a clean way of fixing it on my own).

Actual behavior

Error printout in NeoVim: `.local/share/nvim/lazy/codecompanion.nvim/lua/codecompanion/strategies/inline.lua:164: attempt to call field ‘chat’ (a nil value)`.

Minimal config

Make a module `codecompanion_adapter.lua`:

lua
return function()
return require(“codecompanion.adapters”).extend(“openai_compatible”, {
name = “ollama_proxy”,
env = {
url = “http://…”,
chat_url = “/v1/chat/completions”,
},
schema = {
model = {
default = “llama3:latest”,
},
num_ctx = {
default = 8192,
},
},
})
end
Then in `.setup`:

lua
require(‘codecompanion’).setup({
adapters = {
ollama_proxy = “codecompanion_adapter”,
},
strategies = {
inline = { adapter = “ollama_proxy” }
}
})

Then execute `CodeCompanionActions`, select a command, say `[c] Create inline comments`.

Steps to reproduce

See config.

Console logs

_No response_

Author: olimorris

Date: 2024-08-28

Hey, thank you for providing a minimal config so I could quickly triage this! Should hopefully be resolved in the main branch.

Author: kubohelo

Date: 2024-08-29

It is somehow related since yesterday my custom setup stopped working, after some poking looks like I need to resolve adapters via require to make it work:
lua
{
‘olimorris/codecompanion.nvim’,
opts = {
adapters = {
copilot = function()
return require(‘codecompanion.adapters’).extend(‘copilot’, { name = ‘copilot’ })
end,
openai = function()
return require(‘codecompanion.adapters’).extend(‘openai’, { name = ‘openai’ })
end,
},
strategies = {
chat = { adapter = ‘copilot’, roles = { llm = “ó°š© CodeCompanion”, user = “Me” } },
inline = { adapter = ‘copilot’ },
},
},
dependencies = { …
Before it was enough to have:
lua
{
‘olimorris/codecompanion.nvim’,
opts = {
adapters = {
copilot = {
name = ‘copilot’,
},
openai = {
data/discussions/210.md
l be ignored. You can provide multiple files to search in like a traditional diff check

Hope that helps.

Author: hhhb22w

Date: 2024-08-31

yes, i’m so stupid. I figured it out. thank you !

Author: olimorris

Date: 2024-09-02

Not stupid at all. It’s not clear. Adding proper tool descriptions via the LLM API’s tool parsing capabilities should help in the coming weeks

Question: how to properly use editor agent?

Author: hhhb22w

Date: 2024-08-31

“`xml
I will execute the `editor` tool next for changing your buffer.


editor
C:\Users\bin.hao.local\Downloads\test-copilot\src\main.rs


The agent generated the message correctly. I answered `y`, but nothing happened. How to make the agent update code to my buffer?

thank you for response

Author: olimorris

Date: 2024-08-31

There’s some magic going on with this. It compares `` against `` and replaces it with the ``. However, there needs to be an exact match otherwise it wildata/discussions/221.md

Feature Request: Option to disable `` key default

Author: Caelan152

Date: 2024-09-02

It would be highly appreciated if there’s an option implemented or way to pass `c` and so on, to not map standard behavior to it?

lua
require(‘codecompanion’).setup()

vim.keymap.set(‘n’, ‘y’, ‘CodeCompanionChat‘)
Works, however it still retains `c`. Which could potentially cause conflicts in standard workflows etc.

Or maybe doing `leader = ”` inside a setup structure

Author: olimorris

Date: 2024-09-02

Do you know where the `c` mappings are setup as I can’t find them in the codebase. As far as I’m aware, nothing is mapped to the leader key unless the user explicitly tells the plugin to (even then it couldn’t map anything out-of-the-box as it doesn’t know what users map their `leader` key to e.g. `` or `,` etc)

Only thing mapped automatically out-of-the-box are these: https://github.com/olimorris/codecompanion.nvim/blob/main/lua/codecompanion/config.lua#L110 and these mappings are restricted exclusively to the `[CodeCompanion]` buffer: https://github.com/olimorris/codecompanion.nvim/blob/main/lua/codecompanion/display/chat.lua#L274

Edit: I think I am wrong and will write shortly!

Author: olimorris

Date: 2024-09-02

In the chat buffer, `` is mapped to close the window. Assuming you have something like this set up for `which-key`, your mapping *should* overwrite any internal CodeCompanion mapped one?

lua
{
“olimorris/codecompanion.nvim”,
config = true,
keys = {
{ ““, “CodeCompanionChat Toggle“, mode = { “n”, “v” } },
}
Could you elaborate more with a minimal config/keymap layout please so I can better understand? Thanks!

Author: Caelan152

Date: 2024-09-02

I apologize, to be perfectly clear.

So with `` I meant mapping directly by string name by using `vim.keymap.set(‘n’, ‘cy’, ‘CodeCompanionChat‘)` this evaluates nicely. It’s essentially what I did because using `”“` explicitly overrides `ctrl+a` or `tmux` behavior.

Now, inside buffer `qa` or similar ones, they have `mappings{}` setup:

lua
mappings = {
close = { modes = { n = ‘q’ } },
options = { modes = { n = ‘?’} },
},
Is there a way to do `options = false`? It doesn’t seem to unmap using strings, also evaluating the `opts.` mappings structure doesn’t seem plausible (since they are tables inside).

lua
local function buildLlamaParams(model, url)
return function()
return require(“codecompanion.adapters”).extend(“openai_compatible”, {
env = {
url = url,
api_key = “123”,
chat_url = “/v1/chat/completions”
},
schema = {
model = {
default = model
}
}
})
end
end

local local_adapters = {
[“llama3-8b”] = buildLlamaParams(“meta-llama-3-8b-instruct”, “http://127.0.0.1:8080”),
}

return {
{
“olimorris/codecompanion.nvim”,
dependencies = {
“nvim-lua/plenary.nvim”,
“nvim-treesitter/nvim-treesitter”,
“hrsh7th/nvim-cmp”, — Optional: For using slash commands and variables in the chat buffer
“nvim-telescope/telescope.nvim”, — Optional: For using slash commands
“stevearc/dressing.nvim” — Optional: Improves the default Neovim UI
},
opts = {
strategies = {
chat = { adapter = “llama3-8b” },
inline = { adapter = “llama3-8b” },
agent = { adapter = “llama3-8b” },
},
adapters = local_adapters,
display = {
chat = {
show_settings = true
}
},

}
}
}
Mapping `..` on my standard `keymaps.lua` works correctly and overrides the `` as the module is lazy-loaded (and not specifically `keys` overriden by standard `lazyvim` config structure on initialization).
The problem arrives when trying to remap specific behaviors of `q` buffer natively per user basis instead. Just doing the following:

lua
vim.keymap.set(‘n’, ‘q’, ‘‘, { buffer = vim.api.nvim_get_current_buf() })
Leaves codecompanion trying to close with its own internal mapping in `codecompanion\config.lua`. Would it be possible to un-map all keys using `setup()`?

Author: olimorris

Date: 2024-09-02

Thanks for clarifying! Currently they don’t support being set to `false`. Can make that change for you although be mindful to assign something, otherwise you might end up with no way out of the chat buffer 😅

Author: Caelan152

Date: 2024-09-02

Usually users tend to map specific things by their own (specially using which-key with descriptions), which makes them independent on plugin settings to `true` by defaults to test their limits or if functionality is supported! So having it disabled natively by choice works well, because users can define it under “keys{}“ by their own criteria.

Author: olimorris

Date: 2024-09-02

It’s a fair point for the general execution (``). However these mappings (`display.chat.window`) are local mapping just to that chat buffer otherwise `q` would end up closing everything (which actually might be what you want on second thought 🤔)

Thanks again for the input. I’ll get this out for you

Author: olimorris

Date: 2024-09-02

Should be good from #222 and on `main`. As it’s evaluated down:

lua
display = {
chat = {
window = {
opts = {
},
},
},
You have to be quite explicit:

lua
strategies = {
chat = {
keymaps = {
options = {
modes = { n = false },
},
},

data/discussions/216.md
s()

—

TODO

– Maybe find a way to dynamically update available parameters since you might not want to have an OpenAI parameter setting prompt like `frequency_penalty` show up for Ollama adapters. Since `gemini`, `cohere` and others are all mixed inside OpenAI API compatibility format for completions, `setup()` isn’t dynamically setting adapters on each call but running on the first check

– Add dynamic prompts based on available functions on server side

Author: olimorris

Date: 2024-09-02

Hi @Caelan152 – please could you detail what this PR adds precisely (I see multiple adapters included)? Is there an issue for this PR that details why the PR is going to solve an outstanding deficit? Many of the additions here either come out of the box with CodeCompanion or are extremely specialised setups that’s going to clutter up the codebase significantly.

In terms of creating local adapters, you can just return them all via a `return` object inside your configuration. Adapters are loaded via string resolution of dot.notated folders from `nvim/lua` path. Assuming a folder structure of:

`~/.config/nvim/lua/my_adapaters.lua` OR `~/.config/nvim/lua/my_adapaters/init.lua`

In this file:
lua
return {
adapter_1 = function()
— logic goes here
end,
adapter_2 = function()
— logic goes here
end,
adapter_3 = function()
— logic goes here
end,
}
local my_adapters = require(“my_adapters”)

require(“codecompanion”).setup({
adapters = {
adapter_1 = my_adapters.adapter_1
}
})

Author: olimorris

Date: 2024-11-20

Going to close this for now as there hasn’t been a response. Happy to reopen if you see fit.

Feat(adapters): Add default LLMs inside OpenAI compatibility routing

Author: Caelan152

Date: 2024-09-01

Some of these are available out of the box, however having them configured as functions like `cohere()` and such as individual features vs one dynamic `setup` might make it harder for the average user, as one can easily switch model and adjust the `system_prompt` on initialization dynamically while having access to most features, or pass it an existing `env()`. Added common ones that utilize `openai_compatible`

I wasn’t able to use `.lua` files for adapters because in Windows (or WSL from my case) using `vim.fn.stdpath(‘config’)` loads them weirdly (separating them with dots as the adapter’s custom plugin load system expects). Instead I use a function `load_all_adapters()` wrapper to initialize all at once, if I use `codecompanion.adapters.adapters` the adapter complains it is not found (perhaps `\config\` structure uses it internally) so I have to pass them locally while initializing `opts.adapters = all_adapters` by invoking load_all_adapterdata/discussions/208.md

Missing cmp with / or @

Author: hhhb22w

Date: 2024-08-30

### Neovim version

0.10.1

Operating system and version

win 11

Expected behavior

type `/` or `@`, show cmp for select.
The cmp log shows: cmp sources set true, but I don’t see any thing like telescope window pop up

Actual behavior

nothing

Minimal config

_No response_

Steps to reproduce

_No response_

Console logs

_No response_

Author: olimorris

Date: 2024-08-30

Hey, please could you post your configuration as requested. Do you have `hrsh7th/nvim-cmp` installed? Can you manually trigger cmp via a defined keymap inside the chat buffer or if typing characters? Is it completely isolated to `/` and `@`?

Author: hhhb22w

Date: 2024-08-31

Yes, I have `hrsh7th/nvim-cmp` installed, and `ctrl n`, `ctrl p` works
the config:

lua
return {
— … your other plugins
{
“olimorris/codecompanion.nvim”,
dependencies = {
“nvim-lua/plenary.nvim”,
“nvim-treesitter/nvim-treesitter”,
“hrsh7th/nvim-cmp”, — Optional: For using slash commands and variables in the chat buffer
“nvim-telescope/telescope.nvim”, — Optional: For using slash commands
{ “stevearc/dressing.nvim”, opts = {} }, — Optional: Improves the default Neovim UI
},

config = function()
local conf = {
strategies = {
chat = {
adapter = “copilot”, — Ensure this is an adapter you have configured
},
inline = {
adapter = “copilot”,
},
agent = {
adapter = “copilot”,
},
},

— NOTE: If you are encountering the ‘missing id’ error,
— you should pass `true` to `cmd_args` for `resolve_args`
adapters = {
— Example for setting a config variable specifically for this project
copilot = function()
return require(“codecompanion.adapters”).extend(“copilot”, {
schema = {
model = {
default = “claude-3.5-sonnet”,
},
max_tokens = {
default = 4096,
},
},
})
end,
openai = function()
return require(“codecompanion.adapters”).extend(“openai_compatible”, {
name = “my_openai”,
env = {
api_key = “1”,
url = “http://xxx/v1”,
},
schema = {
model = {
default = “gpt-4o-2024-08-06”,
},
},
})
end,
},
display = {
diff = {
provider = “mini_diff”,
},
},
}

local wk = require(“which-key”)

wk.add({
{ “t”, group = “ai tool” },
{ “ta”, “CodeCompanionActions“, desc = “code companion action” },
})

require(“codecompanion”).setup(conf)
end,
},
}

Author: olimorris

Date: 2024-08-31

I’m struggling to recreate your problem but maybe your nvim-cmp setup is causing a conflict? Below works completely fine on my system but please just do a sanity check to make sure `cmp` is a module? Also in your plugins dir can you confirm the completion directory is there and is named `codecompanion.lua`? i.e. `~/.local/share/nvim/lazy/codecompanion.nvim/lua/cmp_codecompanion/codecompanion.lua`. Thanks!

local wk = require(“which-key”)

wk.add({
{ “t”, group = “ai tool” },
{ “ta”, “CodeCompanionActions“, desc = “code companion action” },
})

require(“codecompanion”).setup({
strategies = {
chat = {
adapter = “copilot”,
},
inline = {
adapter = “copilot”,
},
agent = {
adapter = “copilot”,
},
},
adapters = {
copilot = function()
return require(“codecompanion.adapters”).extend(“copilot”, {
schema = {
model = {
default = “claude-3.5-sonnet”,
},
max_tokens = {
default = 4096,
},
},
})
end,
openai = function()
return require(“codecompanion.adapters”).extend(“openai_compatible”, {
name = “my_openai”,
env = {
api_key = “1”,
url = “http://xxx/v1”,
},
schema = {
model = {
default = “gpt-4o-2024-08-06”,
},
},
})
end,
},
display = {
diff = {
provider = “mini_diff”,
},
},
})
!Screenshot 2024-08-31 at 18 10 39

Author: hhhb22w

Date: 2024-09-02

you are right. Thank you
lua
{
“hrsh7th/nvim-cmp”,
dependencies = { “hrsh7th/cmp-emoji” },
—@param opts cmp.ConfigSchema
opts = function(_, opts)
local cmp = require(“cmp”)
opts.sources = cmp.config.sources({
{ name = “nvim_lsp” },
{ name = “path” },
}, {
{ name = “buffer” },
})

— the cmp codecompanion needs this
table.insert(opts.sources, { name = “codecompanion” })
end,
},

Author: olimorris

Date: 2024-09-02

Ah brill. Out of interest do you use LazyVim or a distro? As I think your `opts.sources` is initially overiting everything (and thus stopping codecompanion injecting itself on buffer entry) hence the table insert!

Will mark this issue as resolved.

data/discussions/21.md
s, this was a great tip to do it like this `diffput`. Is doing PR right away without creating a PR considered rude :joy: ? I can create an issue next time if preferred.

It should have been a “cleaner” solution using `clear_namespace` so it didn’t delete signs created from plugins. I’ve updated my comment to account for that. Let me know what you think of it :)

Author: jcxavier

Date: 2024-03-24

Ah wow, just realized I never responded sorry about that 😅

But this PR definitely made the visual experience really nice!

feat: auto-accept suggested inline changes.

Author: jcxavier

Date: 2024-03-09

Accept suggestions inside floating diff without explicitly calling diff.accept

A hacky solution probably… I’ll try and come up with something better as soon as possible.
!Screen Recording 2024-03-09 at 23 48 57

Author: olimorris

Date: 2024-03-10

Nice addition. I’ve added a `reject()` method too to be complete in 49dd36b

Could we remove the magic numbers and opt for a named parameter instead using `{ on_accept = true }` or something?

Author: jcxavier

Date: 2024-03-10

Also I thought about the reason my commit was so hacky. The changes inside the scratchpad basically disappears once you call `:diffput`. For one change it works, however if we have multiple changes inside a scratchpad we would lose the diff information (if im remembering this right). Is there an action I can use to basically `diffput` all the ranges presented inside `hunks` inside `strategies.inline#L236`?

I did try `diffput` iterating all extmarks to basically `pull` from scratchpad but as soon as we `diffput` one sign no more diff information exists inside the scratchpad buffer.

Also, im considering this an issue as well since calling `:diffput` inside a scratchpad buffer natively removes any remaining “virtual_text”.
For example. Say you have 2 hunks inside of the scratchpad. You accepted the first one using `:diffput`, the first hunk will be replaced just as normal inside `target`. However, `scratch` wouldn’t be “highlighted” red/green on the 2nd hunk anymore thus returning `vim.fn.sign_getplaced` to `[]`.

lua
— codecompanion.utils.diff.lua#L112
— `difffput` removes sign placed (virtual text diff).
if vim.api.nvim_get_current_buf() == scratch and vim.api.nvim_get_current_buf() ~= target then
local buf_signs = vim.fn.sign_getplaced(scratch, { group = “*” })[1].signs

if #buf_signs == 0 then
M.reject(scratch)
end
end

— codecompanion.utils.diff.lua#L89
— Redo virtual text on the previous hunks that we haven’t “put”.
— the logic to “diffput” all ranges/extmarks presented in strategies.diff#hunks can be executed above as well. But this applies after user has put 1 of 2 hunks but the diff gets removed.

…
target_coords = vim.api.nvim_buf_get_extmark_by_id(target, ns_id, data[1], { details = true })
if vim.tbl_isempty(target_coords) then
return
end
scratch_coords[2] = scratch_coords[2] + 1
local removed_lines = vim.api.nvim_buf_get_lines(target, target_coords[1], target_coords[3] + 1, false)

vim.api.nvim_buf_clear_namespace(scratch, ns_id, 0, -1) — To only remove signs from ns_id, this applies only to the `scratch` buffer since target clears its own namespace when diffput occurs. Note that target shouldn’t be touched! (No signs get placed on target).

add_highlights(scratch, target_coords[3] – target_coords[1] + 1, scratch_coords, “red”)

Author: olimorris

Date: 2024-03-10

No worriedata/discussions/236.md
he “tools” option. As mentioned `gemini`, `anthropic`, and `openai` schemas support this, so wait, I’m confused now 😅 why `openai` tool configuration is done with `tools`, and gemini with `opts`, considering they are “first citizens” in CodeCompanion’s support list for LLMs adapter, and it doesn’t align out of the box with codecompanion functionality (since tools structure are already baked in).
The workaround relies on a user figuring what parameters Gemini’s API takes and overriding it via its own schema instead of overriding functions in `.adapters` or `handlers.setup`. To make CodeCompanion robust, those adapters should ideally handle `tools` efficiently and gracefully out-of-the-box IMO.

The workaround indeed fixes the tool usage (mostly), but as you said, to bypass `.chat()` limitation of agent tools when sending output back through API request (it generates 400 bad request due agent parameters missing or wrongly parsed internally by codecompanion formatters or adapters for gemini output request via API calls)… what is making the call crash? Can add another parameter to not send tool output to Gemini via `.chat()`. ?

Author: olimorris

Date: 2024-09-08

It’s all on me for making it confusing 😆

> why openai tool configuration is done with tools, and gemini with opts. considering they are “first citizens” in CodeCompanion’s support list for LLMs adapter, and it doesn’t align out of the box with codecompanion functionality (since tools structure are already baked in).

When OpenAI tools hit standard endpoints, they did so from the get go via an Open Source PR (a big feature add!). Since then, Anthropic have implemented tools. And also Gemini. I just added Gemini the other day quite loosely by using their prompt schema for sending payloads. By CodeCompanion standardising on the `tools:` key, hopefully we bypass this fragmentation.

It crashes because Google have implemented tool requests in a truly bizarre manner (see my link to `call_function_payload`). OpenAI and Anthropic are sensible. Google’s tool response mechanism requires matching the user prompt, then the model’s call_function, then saving that id, returning an object from the user that contains that id, the tool name AND they payload. Just a headache on top of CodeCompanion’s message payload parsing:

lua
— Current user and function response model

{
role = “user”
content = “what is the diff to the editor tool”,
},
{
role = “model”, — Wait, Gemini only accepts role = `model` ?? I’m sure I added a parser. Either way `assistant` throws an error on API calls because it only accepts “model” “user”
content = “”,
tool_calls = {
name = “editor”
arguments = {
— …
}
}
},
{
role = “user”,
content = ‘some status from tool’
}
—
They also only allow an alternating user <> model format so any user <> user formatting will be promptly rejected..which commonly happens with standard tools! As per https://ai.google.dev/gemini-api/docs/function-calling/tutorial?lang=rest#function-response

Author: Caelan152

Date: 2024-09-08

This must require some restructuring from CodeCompanion to allow custom role names per adapter. Honestly, don’t break your head over API tools; maybe `model` is equivalent to `assistant` or `bot`?. What CodeCompanion’s base `chat` implementation does natively (sending back standard text payloads containing XML, similar to Claude Artifacts) has made using models like `claude.sys` natively on almost any custom `openai_compatible` frontend and custom OS models so easy that it honestly renders custom `api endpoint specific tools` redundant.

Wait since it only accepts alternating calls `user <> model `, how about changing `user -> model` manually on the parsing method to alternate after reaching an un-balanced count.
Like grouping user tags if

lua
while current is user… and count_current_role is % 2 != 0 do
append_to_latest_user

If model != % 2 != 0 then — It means it’s unblanced and waiting for a model response!

insert_model(say it generated nothing or give it space.. ” “)
count_model += 1

Just as an idea. Maybe not implement it since we don’t have to break our heads over these. Honestly API limitations limit LLM behavior way to much.

I’m currently playing locally with
`gemini-1.5-pro-exp-0827_GGUF`, it uses almost all standard agents with 90% completion rate out of the box via agent chat format (XML payload) because standard parsing doesn’t have the “model” requirement limitations. Using standard agent protocol has to be arguably one of the greatest features I’ve tested compared to Copilot and all the current major editors—just as long as standard parsing logic maintains simplicity, or doesn’t forcefully impose API limitation routing when executing standard agents like `editor`.

Thank you for everything man!

Author: olimorris

Date: 2024-09-08

Really insightful comments and completely resonate with your final sentiment: the XML implementations on standard inputs is truly amazing. I’ve only come to realize this now too haha.

It’s actually why I’ll keep the legacy tool implementations for weak/open source models and make all of the major models fall in-line with standard APIs by default. The problem occurs currently (as of reading this, though I think you’ve figured it out), is that the plugin evaluates whether standard LLM API tools are available _before_ checking and reverting to standard XML inputs in the chat stream!

There shouldn’t be much structural work required; we can just lean on the `formatters`, which are designed precisely for this kind of behavior. They receive standard inputs from the core adapter framework via their base definitions and then parse everything cleanly out into whatever obscure format OpenAI, Anthropic, or in this case, Google, wants at API consumption level!

So Google will just get the standard function payload from one of its adapters formatters!

Glad you’re enjoying and pushing the boundaries!! Appreciate yours and everyones testing over the past few weeks!

Author: olimorris

Date: 2024-09-09

Check my message in #234

Feature Request: gemini API tools support in adapter parameters

Author: Caelan152

Date: 2024-09-07

As per #234
The new API system allows `setup.adapters… ` options block out tools out of the box. Meaning users don’t have to define tools via `adapter(handlers.setup)` anymore! But unfortunately `gemini` seems to be completely missing out on this?

lua

— Adding dynamic properties for Gemini Tools Support over tools parameter
local geminiCustomToolSupportedAdapter = function()
return require(“codecompanion.adapters”).extend(“gemini”, {
env = {
api_key = “…”,
},
schema = {
model = {
default = “gemini-1.5-pro-exp-0827”
},
},
})
end

Wait let me test if `gemini` actually takes tools by default on the api
lua
gemini = function()
return require(“codecompanion.adapters”).extend(“gemini”, {
name=”my_gemini_with_tools”
env = {
api_key = “cmd:cat ~/.config/nvim/api_keys/gemini.txt”,
chat_url = “http://127.0.0.1:8080/v1/chat/completions” — This is a gemini openai to api wrapper
},
schema = {
model = {
default = “gemini-1.5-pro-exp-0827”
},
},
options = {
[….] — Wait what? No tools available in configuration!
}

})
end
Wait, as the new implementation says. `gemini` uses `opts` instead of tools for specifying tool usage while standardizing other adapters over `tools`.
Is this intentional over Google’s API specific limitations, or shouldn’t we add a handler internally inside code companion settings to translate `tools` to `opts` out of the box dynamically via `formatters/adapters.lua` allowing dynamic and modular integrations, just like codecompanion currently integrates custom internal logic and prompts to avoid further confusion?

This ensures no breaking change when configuring and standardizes CodeCompanion adapter APIs parameters:

lua
gemini = function()
…
opts = {
tools = { — This doesn’t seem supported natively inside the setup.adapters options
inline_tools =false
}
}

})
end
Wait, how does codecompanion resolve this? The workaround seems to directly override tools using `schema` :O

lua
— Workaround to standardizing `tools` option back? Is Gemini not internally implemented to handle this inside CodeCompanion?
local geminiCustomToolSupportedAdapter = function()
return require(“codecompanion.adapters”).extend(“gemini”, {
name = “gemini_pro_exp”,
env = {
api_key = “cmd:cat ~/.config/nvim/api_keys/gemini.txt”,
},
schema = {
model = {
default = “gemini-1.5-pro-exp-0827”
},
tools = { — By manually injecting `tools` inside the `schema` table workaround, rather than the `CodeCompanion` standards
inline_tools = false
}
},
})
end

By setting it in `schema` you bypass CodeCompanion’s handler logic completely, basically acting as arbitrary dictionary parameters for the API without any logic behind since it sends tools manually over using `schema` bypassing CodeCompanion completely.

Author: olimorris

Date: 2024-09-08

You can pass `tools` in the parameters of any API request to Gemini – https://ai.google.dev/api/caching#content – if it was the OpenAI wrapper you could just use it.

When using tools natively via Gemini’s API, the request gets a 400 Bad Request error. Their tool functionality schema requires some very obscure implementation on CodeCompanion’s part from memory: `call_function_payload` being mapped against original prompts `user` payload – something silly like that compared to OpenAI and Anthropic. I added it but removed it as I didn’t want to break the prompt parser logic and keep parity across APIs where possible!

It’s actually really complex keeping parity across Claude, OpenAI and Google 😅

Regardless…

You say that
> It bypasses CodeCompanion completely, acting as arbitrary dictionary parameters

Where precisely are you finding `tools` nested under `opts`? Under CodeCompanion, any key in `schema` is mapped over to dynamically populate the settings interface `({ show_options = true)` inside a chat session. This allows for values natively defined as ``s and `` values over the interface, without needing to manipulate `.lua` directly. Once done, the actual API schema mappings occur natively within the `handlers` logic inside every individual adapter! Then those items are stripped out, parsed, and assigned back to CodeCompanion core `chat` variables.

Author: Caelan152

Date: 2024-09-08

First of all, thanks for CodeCompanion. I understand the nuances of how Codecompanion formats its prompt structures dynamically.
You must be right in saying it is incredibly tricky balancing Claude, OpenAI, and Google formats without breaking CodeCompanion’s neat internal parsing architecture across the board!

In the `README.md` and configuration docs, you state OpenAI tools can be enabled via tdata/discussions/24.md

Question: Setup a proxy ?

Author: olegch0h

Date: 2024-03-05

I run codecmpannion in a virtual environment with no access of interent, there is an environment variable ‘all_proxy’ which makes git etc work gracefully.

Will `codecompanion` use this proxy in the background curl query? or something we need to do in setting up?

Author: olimorris

Date: 2024-03-05

CodeCompanion literally issues a `curl` call under the hood so as long as curl works on your system you’ll be fine.

If you specifically need to pass variables into curl proxy (e.g. `http://proxy.yournetwork.com:8080`) you can do so per adapter e.g:

lua
require(“codecompanion”).setup({
adapters = {
copilot = function()
return require(“codecompanion.adapters”).extend(“copilot”, {
env = {
proxy = “http://proxy.yournetwork.com:8080”
}
})
end,
},
})

Author: olegch0h

Date: 2024-03-06

Yes this config solves the issue, Thanks!

For users behind Great Firewall in China, proxy runs typically runs in “http://127.0.0.1:xxxx”, and openAPI does not allow users from CN thus we need proxy either way, locally or globally. CodeCompanion is great to offer this level of customization!

which specifies the

Curious about what this could mean for your organization?

Please feel free to contact us for a no-obligation consultation.

"*" indicates required fields

This field is for validation purposes and should be left unchanged.