@javierkaiser/opencode-indexing 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +157 -2
- package/README.md +192 -21
- package/index.ts +133 -17
- package/install.mjs +229 -128
- package/install.ps1 +7 -1
- package/install.sh +1 -1
- package/package.json +6 -2
- package/src/config.ts +1 -1
- package/src/embedder.ts +339 -99
- package/src/import.ts +30 -9
- package/src/indexer.ts +23 -1
- package/src/registry.ts +105 -19
- package/src/rpc.ts +27 -3
- package/src/search.ts +41 -2
- package/src/settings-commands.ts +6 -4
- package/src/settings.ts +28 -13
- package/src/status.ts +52 -5
- package/src/tools.ts +65 -20
- package/src/types.ts +32 -0
- package/tui/settings-page-data.ts +31 -15
- package/tui/settings-page.tsx +7 -1
- package/tui/workspace-rpc.ts +98 -0
- package/tui.ts +112 -41
package/CHANGELOG.md
CHANGED
|
@@ -5,12 +5,166 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [0.2.1] - 2026-10-15
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`opencode plugin add @javierkaiser/opencode-indexing` is now the documented
|
|
13
|
+
install.** It was already possible — the package was published and exported
|
|
14
|
+
`./tui` — but the README told people to run `npm install` and edit
|
|
15
|
+
`opencode.json` by hand, which puts the package in whatever directory they were
|
|
16
|
+
standing in and never tells OpenCode about it. The CLI command installs into
|
|
17
|
+
OpenCode's own cache, records the entry, and brings the update and removal path
|
|
18
|
+
(`plugin check`, `plugin update`, `plugin remove`) with it.
|
|
19
|
+
- **The installer has a package mode**, and picks between the two from where it
|
|
20
|
+
runs: a checkout installs the working tree, an installed copy installs the
|
|
21
|
+
published package. `npx @javierkaiser/opencode-indexing` therefore does the
|
|
22
|
+
right thing with no flags, including the permission rules and the restart that
|
|
23
|
+
`plugin add` alone does not do.
|
|
24
|
+
- `bin` in `package.json`, so `npx` has something to run.
|
|
25
|
+
- The plugin options and `ignoreKiloConfig` are documented in the README. The
|
|
26
|
+
option existed in the code and had tests, but appeared in no documentation.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- **"No Kilo index found" for a workspace that has one.** The server plugin is
|
|
31
|
+
instantiated for the directory the service runs in, so every RPC that omitted a
|
|
32
|
+
`directory` described *that* project. `kilo.discover` took no directory at all,
|
|
33
|
+
which is why opening the palette in one project and importing reported nothing
|
|
34
|
+
while the footer, using the same client and passing the directory, looked
|
|
35
|
+
correct. `kilo.discover` and `settings.test` now accept a directory, and the
|
|
36
|
+
palette, the settings page and the index actions all send the caller's. The
|
|
37
|
+
directory is injected once by `bindWorkspace` rather than passed at each call
|
|
38
|
+
site, so a new workspace-scoped RPC is correct by default instead of correct by
|
|
39
|
+
remembering.
|
|
40
|
+
- **The tools read and indexed the service's directory.** All seven were pinned to
|
|
41
|
+
the plugin instance's root, so `indexing_search` in a session answered from
|
|
42
|
+
another codebase — results from the wrong project read as plausible — and
|
|
43
|
+
`indexing_import` refused an index that was sitting right there. They now use
|
|
44
|
+
`context.directory`, with the instance root as the fallback for hosts that do
|
|
45
|
+
not report one.
|
|
46
|
+
- **`@lancedb/lancedb` could never load, so no Kilo index was ever importable
|
|
47
|
+
from LanceDB.** `apache-arrow` is that package's *peerDependency*, and the
|
|
48
|
+
installer runs `npm install --omit=peer`, which drops peers from the tree: the
|
|
49
|
+
native binary loaded and then threw `Cannot find module 'apache-arrow'` on first
|
|
50
|
+
use. It is now declared explicitly. This also broke `vectorStore: lancedb`
|
|
51
|
+
outright.
|
|
52
|
+
- **An unreadable index was reported as a missing one.** Discovery swallowed
|
|
53
|
+
backend failures, so "Kilo is not running here" and "Kilo is not installed here"
|
|
54
|
+
both surfaced as *No Kilo index found*. It now names the path it found and the
|
|
55
|
+
reason it could not be read, in `indexing_status`, `indexing_build`,
|
|
56
|
+
`indexing_config`, `settings test kilo`, the import tool and the empty-state
|
|
57
|
+
toast. `indexing_build` is the one that matters most: with nothing reported, a
|
|
58
|
+
build in a workspace whose Kilo index could not be read re-embedded everything
|
|
59
|
+
without saying why.
|
|
60
|
+
- **`apache-arrow` is declared in `package.json`, not only in the installer.**
|
|
61
|
+
It is a *peer* of `@lancedb/lancedb`, and the two install paths disagreed about
|
|
62
|
+
peers: `install.mjs` runs `npm install --omit=peer`, which drops them, while
|
|
63
|
+
the npm-based install OpenCode performs keeps them. Declaring it makes the
|
|
64
|
+
dependency true for both instead of true for whichever path happened to be
|
|
65
|
+
tested.
|
|
66
|
+
- The installer no longer keeps its own copy of the dependency list; it derives
|
|
67
|
+
the installed `package.json` from the published one. That duplication is how
|
|
68
|
+
`apache-arrow` came to be declared for one install path and missing from the
|
|
69
|
+
other.
|
|
70
|
+
- `--package` deletes a previously copied plugin. Both sources define
|
|
71
|
+
`id: "opencode.indexing"` and the config directory is scanned automatically, so
|
|
72
|
+
leaving both would load the plugin twice.
|
|
73
|
+
|
|
74
|
+
## [0.2.0] - 2026-10-14
|
|
75
|
+
|
|
76
|
+
### Added
|
|
77
|
+
|
|
78
|
+
- **`gemini`, `voyage` and `openrouter` are implemented.** They were selectable in
|
|
79
|
+
the provider list, passed every validation gate, and then threw
|
|
80
|
+
`Unsupported embedder provider` once indexing had already started and been billed
|
|
81
|
+
for a probe. A test asserted that they were unimplemented, which pinned the gap in
|
|
82
|
+
place.
|
|
83
|
+
- **The model catalog is visible.** The TUI model field is now a chooser built from
|
|
84
|
+
the catalog, with a *Custom* entry for anything not listed and for providers with
|
|
85
|
+
no catalog at all. `indexing_config` lists every model with its dimension and
|
|
86
|
+
whether Kilo also knows it — which is the whole answer to whether a free import
|
|
87
|
+
will work.
|
|
88
|
+
- **Per-model input ceilings and per-provider batch limits.** The ceilings differ by
|
|
89
|
+
more than an order of magnitude (`mxbai-embed-large` takes 512 tokens,
|
|
90
|
+
`voyage-code-4` takes 32,000), and one global constant truncated every chunk past
|
|
91
|
+
the smallest model's limit. Batch limits are now per provider: OpenAI caps a
|
|
92
|
+
request at 300,000 tokens whatever the item count, Gemini accepts a fixed number of
|
|
93
|
+
items, Voyage has both.
|
|
94
|
+
- `voyage-code-4`, `voyage-4`, `voyage-4-large`, `voyage-4-lite`,
|
|
95
|
+
`gemini-embedding-2` and Ollama's `bge-m3` in the catalog, each marked as not
|
|
96
|
+
present in Kilo's registry so it is clear they cannot be imported.
|
|
97
|
+
- `indexing_status` warns before a model change re-embeds the workspace, with the
|
|
98
|
+
point count, rather than after the embeddings have been paid for.
|
|
99
|
+
|
|
100
|
+
### Changed
|
|
101
|
+
|
|
102
|
+
- **A search that cannot read part of the corpus now fails instead of shrinking.**
|
|
103
|
+
An embedding failure per profile was pushed onto a list rendered as "Warnings", and
|
|
104
|
+
the results that came back looked exactly like a complete set whose missing half
|
|
105
|
+
ranked lower. An index holding points whose profile cannot be embedded is now an
|
|
106
|
+
error naming the profile. An index with no points is not an error, so the common
|
|
107
|
+
case is unaffected.
|
|
108
|
+
- Changing provider clears the model, because model ids are namespaced per provider.
|
|
109
|
+
The previous code claimed to do this and did not, so switching to Voyage produced
|
|
110
|
+
`voyage` + `codestral-embed-2505`, which outranks the provider default.
|
|
111
|
+
- The stored dimension of a previous index is no longer inherited across a provider
|
|
112
|
+
change. A 1536-wide Mistral index made any new model look 1536-dimensional, and the
|
|
113
|
+
inherited number was then persisted as though it had been measured, making the
|
|
114
|
+
mismatch self-consistent and invisible on every later run.
|
|
115
|
+
- The `apiKeys` merge is derived from the incoming keys instead of a hand-written list
|
|
116
|
+
of provider names, which silently dropped any credential added to the shape but not
|
|
117
|
+
to the list.
|
|
118
|
+
- The settings page reports which providers have credentials instead of deriving it
|
|
119
|
+
from two booleans, which reported "none configured" for a Gemini, Voyage,
|
|
120
|
+
OpenRouter, Ollama or OpenAI-compatible setup.
|
|
121
|
+
- `indexing_config` and `settings test kilo` pass a target profile to the Kilo source
|
|
122
|
+
scan. Without it every source was reported as compatible, including ones that would
|
|
123
|
+
be refused a moment later.
|
|
124
|
+
- Ollama and Voyage are sent `truncate` / `truncation: false`, so an over-long chunk
|
|
125
|
+
fails instead of being silently shortened into a valid-looking wrong vector.
|
|
126
|
+
- Embedding results are placed by `data[].index` where the provider supplies it.
|
|
127
|
+
OpenAI documents the field rather than promising response order, and its own samples
|
|
128
|
+
fetch by it; a repeated or out-of-range index is now an error.
|
|
129
|
+
- The catalog's `openrouter` Gemini entry names `google/gemini-embedding-2-preview`,
|
|
130
|
+
which is what Kilo writes. It said `google/gemini-embedding-001`, and since the
|
|
131
|
+
profile comparison is exact string equality the drift was invisible and made every
|
|
132
|
+
such index un-importable.
|
|
133
|
+
|
|
134
|
+
### Fixed
|
|
135
|
+
|
|
136
|
+
- The model field is cleared on a provider change in the TUI as well as the chat
|
|
137
|
+
command; both paths had the same stale-model bug.
|
|
138
|
+
- `searchCode` and `getStatus` had no unit tests — only the e2e and cli scripts
|
|
139
|
+
exercised them, and those assert nothing. Both have tests now.
|
|
140
|
+
|
|
141
|
+
### Documentation
|
|
142
|
+
|
|
143
|
+
- The README states how far each provider has actually been tested. `mistral` has
|
|
144
|
+
touched its real API; `openrouter` reached the API and authenticated but was
|
|
145
|
+
refused by the key's own spend limit; `openai`, `gemini`, `voyage`,
|
|
146
|
+
`openai-compatible` and `ollama` have never contacted a real endpoint and are
|
|
147
|
+
covered only by fixtures written alongside their adapters. The same fact is
|
|
148
|
+
surfaced in the model chooser and in `indexing_config`, and a test pins the list so
|
|
149
|
+
the claim cannot quietly widen.
|
|
9
150
|
|
|
10
151
|
## [0.1.1] - 2026-10-14
|
|
11
152
|
|
|
153
|
+
### Added
|
|
154
|
+
|
|
155
|
+
- `src/lancedb-support.ts` reports up front that LanceDB ships one native binary per
|
|
156
|
+
platform and that there is no `lancedb-darwin-x64` build (there is no WASM
|
|
157
|
+
fallback), so the embedded store is unavailable on macOS on Intel — instead of
|
|
158
|
+
failing later with a module-not-found error.
|
|
159
|
+
|
|
12
160
|
### Changed
|
|
13
161
|
|
|
162
|
+
- **The own index now defaults to embedded LanceDB** instead of inheriting Kilo's
|
|
163
|
+
`vectorStore`. Kilo's setting is read as `kiloVectorStore`: it still decides where
|
|
164
|
+
an *import* reads from, and it is still reported, but it no longer decides where
|
|
165
|
+
the own index writes to. Dropping that inheritance is reported as a warning rather
|
|
166
|
+
than applied silently, so an existing Qdrant own index is not discovered to be
|
|
167
|
+
empty.
|
|
14
168
|
- npm releases are now automated: pushing a `v*` tag triggers a GitHub Actions
|
|
15
169
|
workflow that publishes through npm trusted publishing (OIDC), with no
|
|
16
170
|
long-lived token.
|
|
@@ -37,6 +191,7 @@ First public release.
|
|
|
37
191
|
- Cross-platform installer (`install.mjs`, plus `install.sh` / `install.ps1`
|
|
38
192
|
wrappers).
|
|
39
193
|
|
|
40
|
-
[Unreleased]: https://github.com/Javierkaiser/opencode-indexing/compare/v0.
|
|
194
|
+
[Unreleased]: https://github.com/Javierkaiser/opencode-indexing/compare/v0.2.0...HEAD
|
|
195
|
+
[0.2.0]: https://github.com/Javierkaiser/opencode-indexing/releases/tag/v0.2.0
|
|
41
196
|
[0.1.1]: https://github.com/Javierkaiser/opencode-indexing/releases/tag/v0.1.1
|
|
42
197
|
[0.1.0]: https://github.com/Javierkaiser/opencode-indexing/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -26,44 +26,83 @@ index is still installed.
|
|
|
26
26
|
|
|
27
27
|
## Install
|
|
28
28
|
|
|
29
|
-
###
|
|
29
|
+
### With the OpenCode CLI (recommended)
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
|
|
32
|
+
opencode plugin add @javierkaiser/opencode-indexing
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
That is the whole install. OpenCode downloads the package into its own cache and
|
|
36
|
+
records it in the global `plugins` array, and it loads both halves of the plugin:
|
|
37
|
+
the server side (`index.ts`, which registers the tools) and the terminal UI
|
|
38
|
+
(`tui.ts`, which adds the prompt-footer indicator and the `/indexing` page).
|
|
39
|
+
|
|
40
|
+
Update and remove it with the same command family:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
opencode plugin check # is there a newer version?
|
|
44
|
+
opencode plugin update # install it
|
|
45
|
+
opencode plugin remove @javierkaiser/opencode-indexing
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`plugin add` installs the plugin but knows nothing about its tools, so it does
|
|
49
|
+
not write permission rules. Add this one to `opencode.json` to keep the host
|
|
50
|
+
asking before the only tool that writes your settings file:
|
|
36
51
|
|
|
37
52
|
```jsonc
|
|
38
53
|
{
|
|
39
|
-
"
|
|
40
|
-
{ "
|
|
54
|
+
"permissions": [
|
|
55
|
+
{ "action": "indexing_config_set", "resource": "*", "effect": "ask" }
|
|
41
56
|
]
|
|
42
57
|
}
|
|
43
58
|
```
|
|
44
59
|
|
|
45
|
-
|
|
60
|
+
The other six tools only read. OpenCode's base policy already allows everything
|
|
61
|
+
(`{ "action": "*", "resource": "*", "effect": "allow" }`), so they need no rule;
|
|
62
|
+
write them out only if you want to tighten the set.
|
|
63
|
+
|
|
64
|
+
### One command, permissions included
|
|
46
65
|
|
|
47
|
-
|
|
66
|
+
To skip the manual rule:
|
|
48
67
|
|
|
49
68
|
```bash
|
|
50
|
-
|
|
51
|
-
|
|
69
|
+
npx @javierkaiser/opencode-indexing
|
|
70
|
+
```
|
|
52
71
|
|
|
53
|
-
|
|
54
|
-
|
|
72
|
+
The installer runs `opencode plugin add`, writes the permission rules, and
|
|
73
|
+
restarts the service. It picks its strategy from where it runs: from an installed
|
|
74
|
+
copy — an npx cache, an unpacked tarball — it installs the published package;
|
|
75
|
+
from a checkout it installs your working tree instead, so edits take effect on
|
|
76
|
+
restart with no publish in between. It prints which one it chose.
|
|
55
77
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
78
|
+
| Flag | Effect |
|
|
79
|
+
| --- | --- |
|
|
80
|
+
| `--package [spec]` | Install the published package (default spec `@latest`) |
|
|
81
|
+
| `--local` | Copy this directory into the config dir (development) |
|
|
82
|
+
| `--skip-deps` | `--local` only: copy the files, install no dependencies |
|
|
83
|
+
| `--no-restart` | Do not restart the service |
|
|
59
84
|
|
|
60
|
-
|
|
85
|
+
`install.sh` and `install.ps1` are thin wrappers over it; PowerShell also accepts
|
|
86
|
+
`-Local`, `-Package`, `-Spec`, `-SkipDeps` and `-NoRestart`.
|
|
61
87
|
|
|
62
|
-
|
|
88
|
+
`--package` deletes any copied plugin it finds: both sources define the same
|
|
89
|
+
plugin id and the config directory is scanned automatically, so leaving both
|
|
90
|
+
would load the plugin twice.
|
|
63
91
|
|
|
64
|
-
|
|
92
|
+
If no package manager is available, a `--local` install still copies the files
|
|
93
|
+
and the plugin runs with reduced features (line chunker instead of tree-sitter,
|
|
94
|
+
no LanceDB).
|
|
65
95
|
|
|
66
|
-
|
|
96
|
+
### Manual
|
|
97
|
+
|
|
98
|
+
To manage the directory yourself, point `opencode.json` at it. Relative paths
|
|
99
|
+
resolve from the config file containing the entry:
|
|
100
|
+
|
|
101
|
+
```jsonc
|
|
102
|
+
{
|
|
103
|
+
"plugins": ["./plugins/opencode-indexing"]
|
|
104
|
+
}
|
|
105
|
+
```
|
|
67
106
|
|
|
68
107
|
## How it works
|
|
69
108
|
|
|
@@ -176,11 +215,123 @@ Configurable from all three:
|
|
|
176
215
|
- **Vector store** for the own index: Qdrant or LanceDB.
|
|
177
216
|
- **Qdrant URL + API key** (local or remote) with connection test.
|
|
178
217
|
- **LanceDB directory** with availability test.
|
|
179
|
-
- **Embedding provider/model** (mistral, openai, ollama, openai-compatible, gemini, voyage, openrouter) and **API key**.
|
|
218
|
+
- **Embedding provider/model** (mistral, openai, ollama, openai-compatible, gemini, voyage, openrouter) and **API key**. The model is chosen from a catalog rather than typed blind. The model is chosen from a catalog rather than typed blind.
|
|
180
219
|
- **Import from Kilo** toggle with live source detection ("Qdrant ws-… (31,261 pts) · LanceDB …").
|
|
181
220
|
- **Auto-refresh on search** toggle.
|
|
182
221
|
- Build / refresh / import actions and a status summary.
|
|
183
222
|
|
|
223
|
+
### Embedding providers
|
|
224
|
+
|
|
225
|
+
All seven have an adapter. Every model below is in the catalog, which is what
|
|
226
|
+
supplies the dimension, the score threshold and the input ceiling; a model that
|
|
227
|
+
is not listed still works, and its dimension is probed from the provider on
|
|
228
|
+
first use. See the next section for how far each one has actually been tested.
|
|
229
|
+
|
|
230
|
+
| Provider | Default model | Also in the catalog | Input ceiling |
|
|
231
|
+
| --- | --- | --- | --- |
|
|
232
|
+
| `mistral` | `codestral-embed-2505` | `codestral-embed`, `mistral-embed` | 8,192 |
|
|
233
|
+
| `openai` | `text-embedding-3-small` | `text-embedding-3-large`, `text-embedding-ada-002` | 8,192 |
|
|
234
|
+
| `voyage` | `voyage-code-3` | **`voyage-code-4`**, `voyage-4`, `voyage-4-large`, `voyage-4-lite`, `voyage-3-lite` | **32,000** |
|
|
235
|
+
| `gemini` | `gemini-embedding-001` | **`gemini-embedding-2`**, `text-embedding-004`, `embedding-001` | 2,048 (001) / 8,192 (2) |
|
|
236
|
+
| `openrouter` | `openai/text-embedding-3-small` | `openai/text-embedding-3-large`, `google/gemini-embedding-2-preview` | 8,192 |
|
|
237
|
+
| `ollama` | `nomic-embed-text` | `mxbai-embed-large`, `all-minilm`, `bge-m3` | 512 – 8,192 |
|
|
238
|
+
| `openai-compatible` | none | whatever your endpoint serves | probed |
|
|
239
|
+
|
|
240
|
+
#### Getting an API key (Mistral)
|
|
241
|
+
|
|
242
|
+
Mistral is the default provider and the only one tested end to end here, so it is
|
|
243
|
+
the shortest path to a working index. API access is enabled by default on a free
|
|
244
|
+
account — **no credit card** — with a usage limit that is enough to index a
|
|
245
|
+
repository.
|
|
246
|
+
|
|
247
|
+
1. Create an account at <https://console.mistral.ai> if you do not have one.
|
|
248
|
+
2. Open the **Studio** console and click **API Keys** in the left sidebar.
|
|
249
|
+
3. Click **Create new key**: give it a name, set an expiration date, and choose the
|
|
250
|
+
connector access scope (*Shared connectors only* is enough for an API key).
|
|
251
|
+
4. Click **Create new key** and **copy the key right away** — it is shown once and
|
|
252
|
+
cannot be retrieved later.
|
|
253
|
+
|
|
254
|
+
Then hand it to the plugin. The simplest way keeps the key out of any file:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
export KILO_INDEX_MISTRAL_KEY=... # Linux / macOS
|
|
258
|
+
# PowerShell: $env:KILO_INDEX_MISTRAL_KEY = "..."
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Equivalently, set it from **`/indexing-config`** in any client or the `/indexing`
|
|
262
|
+
page in the terminal (the field is masked), or through the plugin's options in
|
|
263
|
+
`opencode.json` — see
|
|
264
|
+
[Configuration](#configuration-optional-opencodejson). Settings resolve in the
|
|
265
|
+
order *plugin options → `indexing.json` → environment → defaults*, so an
|
|
266
|
+
environment variable is overridden by anything set in the file or in the options.
|
|
267
|
+
|
|
268
|
+
To check the key before indexing:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
curl -s https://api.mistral.ai/v1/models \
|
|
272
|
+
-H "Authorization: Bearer $KILO_INDEX_MISTRAL_KEY" | head -c 200
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
A list of models means it works; a `401` means the key is wrong or the header is
|
|
276
|
+
missing.
|
|
277
|
+
|
|
278
|
+
#### How far each provider has actually been tested
|
|
279
|
+
|
|
280
|
+
Worth stating plainly, because "implemented" and "seen working" are not the
|
|
281
|
+
same claim and only one of them is safe to rely on.
|
|
282
|
+
|
|
283
|
+
| Provider | Against the real API | What that means |
|
|
284
|
+
| --- | --- | --- |
|
|
285
|
+
| `mistral` | **Yes** | Two inputs, 1536 dimensions, distinct vectors, ~680 ms |
|
|
286
|
+
| `openrouter` | **Partly** | The request reached the API and authenticated; it was refused by the key's own $0 spend limit, so the response parser is unverified |
|
|
287
|
+
| `ollama` | **No** | The local server was not running during the check |
|
|
288
|
+
| `openai`, `gemini`, `voyage`, `openai-compatible` | **No** | No credentials available; only mock-based tests |
|
|
289
|
+
|
|
290
|
+
The adapters for the last four were written from each provider's documentation
|
|
291
|
+
and tested against fixtures written alongside them, which means the tests encode
|
|
292
|
+
the same reading of the docs as the code. A wrong assumption about a field name
|
|
293
|
+
or a response shape would pass every test and fail on first use.
|
|
294
|
+
|
|
295
|
+
Three specific things this leaves open, in descending order of how quietly they
|
|
296
|
+
would fail:
|
|
297
|
+
|
|
298
|
+
- **Gemini's aggregation.** `gemini-embedding-2` returns a single aggregated
|
|
299
|
+
vector for a plain list of inputs, where `gemini-embedding-001` returns one per
|
|
300
|
+
input. The adapter wraps each input in its own `Content` to make both behave
|
|
301
|
+
the same way, and a test asserts the count — but the test is against a fixture,
|
|
302
|
+
not the model. If the wrapping is wrong, N inputs silently become one vector.
|
|
303
|
+
- **Voyage's response shape.** It is treated as OpenAI-shaped
|
|
304
|
+
(`data[].embedding` with an `index`). This matches its published API reference
|
|
305
|
+
and was not confirmed against the service.
|
|
306
|
+
- **Voyage and Ollama truncation.** Both are sent `truncation`/`truncate: false`
|
|
307
|
+
so that an over-long chunk fails instead of being silently shortened. If a
|
|
308
|
+
provider rejects that field rather than honouring it, indexing stops with an
|
|
309
|
+
error rather than degrading — which is the intended direction to fail, but it
|
|
310
|
+
is a guess about the field being accepted.
|
|
311
|
+
|
|
312
|
+
If you use one of these providers and it fails, the error message names the
|
|
313
|
+
provider and the endpoint; please report it, since this is the part of the
|
|
314
|
+
plugin most likely to be wrong.
|
|
315
|
+
|
|
316
|
+
Two things worth knowing before switching:
|
|
317
|
+
|
|
318
|
+
- **Model ids are namespaced per provider.** Changing provider clears the model
|
|
319
|
+
so the new provider's default applies. A leftover id like
|
|
320
|
+
`codestral-embed-2505` under `provider: "voyage"` would be sent to Voyage and
|
|
321
|
+
rejected.
|
|
322
|
+
- **Changing the model invalidates the own index.** A different model means a
|
|
323
|
+
different vector space, so the next build deletes the existing points and
|
|
324
|
+
re-embeds the whole workspace. `indexing_status` warns with the point count
|
|
325
|
+
*before* that happens. Re-embedding a repository is cheap — well under a
|
|
326
|
+
couple of dollars at any paid provider — but a large one takes a while.
|
|
327
|
+
|
|
328
|
+
**Which models can import from Kilo.** Kilo's registry is mirrored entry for
|
|
329
|
+
entry, because an import is accepted only when provider, model id and dimension
|
|
330
|
+
match exactly. Models marked *ours* in the table above are not in Kilo's
|
|
331
|
+
registry and can never be imported; `indexing_config` says which is which. If
|
|
332
|
+
your Kilo index uses a different model, set the same provider and model here and
|
|
333
|
+
the import costs nothing.
|
|
334
|
+
|
|
184
335
|
Settings are stored in `~/.config/opencode/indexing.json` (plugin options → `indexing.json` → environment → defaults). Plugin options in `opencode.json` still work and take precedence. API keys are never written to `indexing.json` in plain text; set them through the environment or plugin options.
|
|
185
336
|
|
|
186
337
|
`~/.config/kilo/kilo.jsonc` is still read, and still supplies the embedding provider, model, dimensions and API keys — and it still says where *Kilo* keeps its index. It no longer decides where this plugin's own index is written; that stopped being coupled so that the default could actually take effect for people running Kilo. See [Where each index lives](#where-each-index-lives).
|
|
@@ -190,16 +341,36 @@ Settings are stored in `~/.config/opencode/indexing.json` (plugin options → `i
|
|
|
190
341
|
```jsonc
|
|
191
342
|
{
|
|
192
343
|
"plugins": [
|
|
193
|
-
{ "package": "
|
|
344
|
+
{ "package": "@javierkaiser/opencode-indexing", "options": {
|
|
194
345
|
"vectorStore": "qdrant",
|
|
195
346
|
"qdrantUrl": "http://localhost:6333",
|
|
196
347
|
"importFromKilo": true,
|
|
197
|
-
"autoRefresh": false
|
|
348
|
+
"autoRefresh": false,
|
|
349
|
+
"ignoreKiloConfig": false
|
|
198
350
|
}}
|
|
199
351
|
]
|
|
200
352
|
}
|
|
201
353
|
```
|
|
202
354
|
|
|
355
|
+
| Option | Meaning |
|
|
356
|
+
| --- | --- |
|
|
357
|
+
| `vectorStore` | `qdrant` or `lancedb` for the **own** index. Does not affect where an import reads from. |
|
|
358
|
+
| `qdrantUrl` / `qdrantApiKey` | Qdrant connection |
|
|
359
|
+
| `provider` / `model` / `dimension` | Embedding profile, overriding the resolved one |
|
|
360
|
+
| `importFromKilo` | Import a compatible Kilo index on build instead of re-embedding |
|
|
361
|
+
| `autoRefresh` | Refresh inline on search when few files changed |
|
|
362
|
+
| `enabled` | Master switch: when false the own index is neither written nor refreshed |
|
|
363
|
+
| `ignoreKiloConfig` | Stop reading `~/.config/kilo/kilo.jsonc` entirely |
|
|
364
|
+
|
|
365
|
+
`~/.config/kilo/kilo.jsonc` is read as a fallback for the embedding provider,
|
|
366
|
+
model, dimensions **and API keys**, which is what makes a free import possible:
|
|
367
|
+
the same model has to be used to reuse Kilo's vectors. Set `ignoreKiloConfig` to
|
|
368
|
+
`true` to cut that off, or override any single value with the options above, an
|
|
369
|
+
environment variable, or `~/.config/opencode/indexing.json` — in that order of
|
|
370
|
+
precedence, with plugin options winning.
|
|
371
|
+
|
|
372
|
+
### Environment variables
|
|
373
|
+
|
|
203
374
|
| Variable | Meaning |
|
|
204
375
|
| --- | --- |
|
|
205
376
|
| `KILO_INDEX_VECTOR_STORE` | `lancedb` (default) or `qdrant` for the own index |
|