Created
May 1, 2026 14:37
-
-
Save muhfaris/cb9529b7bece2ebda6a2f879f0a3adfd to your computer and use it in GitHub Desktop.
Custom Adapter CodeCompanion NVIM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| ### Ringkasan Masalah | |
| Adapter custom `sumopod_buddy` yang extend dari OpenAI adapter gagal berkomunikasi dengan backend LiteLLM karena **3 bug berbeda** yang ditemukan secara bertahap. | |
| --- | |
| ### Bug #1 — `model=None` (Error 400) | |
| **Error:** | |
| ``` | |
| Invalid model name passed in model=None | |
| ``` | |
| **Penyebab:** | |
| Config mendefinisikan `model` di **dua tempat sekaligus** yang saling konflik: | |
| ```lua | |
| -- KONFLIK: model di-set di parameters... | |
| parameters = { | |
| model = "gpt-4o-mini", -- <-- ini | |
| }, | |
| -- ...dan juga di schema dengan mapping ke parameters | |
| schema = { | |
| model = { | |
| mapping = "parameters", -- <-- ini juga inject ke parameters | |
| default = "gpt-4o-mini", | |
| }, | |
| }, | |
| ``` | |
| OpenAI adapter punya logic di `setup` handler yang me-resolve model dari `schema.model.default` dan meng-inject-nya ke parameters. Ketika `model` sudah ada di `parameters` secara hardcode, terjadi konflik dan hasilnya `None`. | |
| **Fix:** Hapus `model` dari `parameters` table. Biarkan schema yang handle injection-nya. | |
| --- | |
| ### Bug #2 — `before_request` handler tidak ada (Silent Fail) | |
| **Error:** Tidak ada error eksplisit — handler diabaikan sepenuhnya. | |
| **Penyebab:** | |
| Kode awal menggunakan lifecycle hook `before_request` yang **tidak exist** di CodeCompanion: | |
| ```lua | |
| handlers = { | |
| lifecycle = { | |
| before_request = function(self, request) -- <-- tidak ada di docs | |
| -- patch tool schema | |
| end, | |
| }, | |
| }, | |
| ``` | |
| Lifecycle handlers yang valid hanya: `setup`, `on_exit`, `teardown`. | |
| **Fix:** Pindah logic patch ke `request.build_tools` yang memang tempat yang tepat untuk mutate tool schema sebelum dikirim. | |
| --- | |
| ### Bug #3 — Tool Schema Invalid untuk Strict Mode (Error 400) | |
| **Error:** | |
| ``` | |
| Invalid schema for function 'sequential-thinking_sequentialthinking': | |
| - 'required' is required to be supplied and to be an array including every key in properties. Missing 'isRevision' | |
| - 'additionalProperties' is required to be supplied and to be false | |
| ``` | |
| **Penyebab:** | |
| Tool `sequential-thinking` dari MCP server menggunakan `strict: true`. OpenAI strict mode mengharuskan: | |
| 1. `additionalProperties` harus `false` | |
| 2. **Semua** keys di `properties` harus ada di array `required` | |
| Tool schema yang dikirim hanya punya sebagian keys di `required`: | |
| ```lua | |
| required = { "thought", "nextThoughtNeeded", "thoughtNumber", "totalThoughts" } | |
| -- Missing: isRevision, revisesThought, branchFromThought, branchId, needsMoreThoughts | |
| ``` | |
| **Sub-bug saat patching:** Kondisi pengecekan `strict` salah level: | |
| ```lua | |
| -- SALAH: strict dicek di schema level | |
| if fn and schema.strict == true then | |
| -- BENAR: strict ada di fn level | |
| local is_strict = schema.strict == true or (fn and fn.strict == true) | |
| ``` | |
| Struktur aktual payload: | |
| ```lua | |
| { | |
| ["function"] = { | |
| strict = true, -- <-- strict ada di sini | |
| name = "...", | |
| parameters = { ... } | |
| }, | |
| type = "function" | |
| } | |
| ``` | |
| **Fix final di `build_tools`:** | |
| ```lua | |
| build_tools = function(self, tools) | |
| if not self.opts.tools or not tools or vim.tbl_count(tools) == 0 then | |
| return nil | |
| end | |
| local transformed = {} | |
| for _, tool in pairs(tools) do | |
| for _, schema in pairs(tool) do | |
| local fn = schema["function"] | |
| local is_strict = schema.strict == true or (fn and fn.strict == true) | |
| if fn and is_strict then | |
| local params = fn.parameters | |
| if params and params.type == "object" and params.properties then | |
| params.additionalProperties = false | |
| local all_keys = {} | |
| for k, _ in pairs(params.properties) do | |
| table.insert(all_keys, k) | |
| end | |
| params.required = all_keys | |
| end | |
| end | |
| table.insert(transformed, schema) | |
| end | |
| end | |
| return { tools = transformed } | |
| end, | |
| ``` | |
| --- | |
| ### Timeline Error | |
| | # | Error | Root Cause | | |
| |---|-------|-----------| | |
| | 1 | `model=None` | `model` didefinisikan dobel di `parameters` dan `schema` | | |
| | 2 | `Internal Server Error 500` | Tool schema invalid karena `before_request` tidak exist, patch tidak jalan | | |
| | 3 | `missing 'isRevision'` | Strict mode butuh semua properties di `required` | | |
| | 4 | `additionalProperties` required | Patch tidak kepanggil karena cek `schema.strict` salah level | | |
| | ✅ | Berhasil | Semua fix diterapkan | | |
| --- | |
| ### Pelajaran | |
| 1. **Selalu cek docs** untuk lifecycle hooks yang tersedia — jangan assume ada `before_request` | |
| 2. **Jangan definisikan `model` di dua tempat** — pilih schema atau parameters, bukan keduanya | |
| 3. **OpenAI strict mode** butuh schema yang benar-benar ketat: semua properties wajib di `required` + `additionalProperties: false` | |
| 4. **Debug dengan `vim.notify(vim.inspect(...))`** adalah cara paling efektif untuk lihat payload aktual yang dikirim |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment