Skip to content

Add Mercury Next Edit (NES) as an opt-in autocomplete mode - #10536

Merged
3 commits merged into
Kilo-Org:mainfrom
tfiras:mercury-next-edit-integration
May 27, 2026
Merged

Add Mercury Next Edit (NES) as an opt-in autocomplete mode#10536
3 commits merged into
Kilo-Org:mainfrom
tfiras:mercury-next-edit-integration

Conversation

@tfiras

@tfiras tfiras commented May 22, 2026

Copy link
Copy Markdown

Summary

Adds Inception Labs' Mercury Edit 2 as a Next Edit Suggestion provider alongside the existing Codestral FIM and gateway-routed Mercury Edit 2 (FIM) options. Selecting Mercury Next Edit (Inception) from the autocomplete model dropdown routes through a new pipeline; every other choice continues through the classic FIM provider unchanged.

This PR was prepared by Inception Labs as part of our integration partnership with Kilo Code.

How to test

A self-contained HTML walk-through with 20 test scenarios is included at:

packages/kilo-vscode/docs/mercury-next-edit-testing.html

Open that file in any browser and work through the cases — it covers Python, TypeScript, Go, Rust, JavaScript, SQL, and a Markdown negative case. The same-line ghost-text path and the off-cursor decoration / jump-to-edit path are both exercised.

Quick enable

  1. Settings → search kilo-code.new.autocomplete
  2. Set model to Mercury Next Edit (Inception) (not Mercury Edit 2, which keeps its original FIM-via-gateway behaviour)
  3. Set nextEdit.apiKey to your Inception API key (or export INCEPTION_API_KEY)
  4. View → Output → choose "Kilo Code · Next Edit" to watch the pipeline

What's new

New module at packages/kilo-vscode/src/services/autocomplete/next-edit/:

File Role
MercuryEditProvider.ts HTTP client for POST /v1/edit/completions (single user message, max_tokens: 512)
mercuryPromptTemplate.ts Sentinel-tagged prompt builder + trailing <|!@#IS_NEXT_EDIT!@#|> token
editCompletionParser.ts Extracts the fenced replacement from Mercury's reply
editableRegion.ts [cursor − 5, cursor + 10] window, capped at 25 lines
EditHistoryTracker.ts Per-file debounced unidiff buffer (last 5 diffs, blank-line separated)
recentSnippetsAdapter.ts Maps the existing RecentlyVisitedRangesService output into Mercury's snippet shape (3–5 snippets × 20 lines)
NextEditInlineCompletionProvider.ts Same-line ghost-text path via vscode.InlineCompletionItem
NextEditSuggestionManager.ts Decoration-based jump-to-next-edit UX for off-cursor predictions (Tab/Esc keybindings gated on a context key)
log.ts Dedicated Kilo Code · Next Edit OutputChannel with an opt-in console mirror

Behavioural additions:

  • Same-line predictions render as inline ghost text — Tab accepts (just like FIM).
  • Off-cursor predictions render as a decoration (red strikethrough + green ghost annotation) at the predicted location. First Tab teleports the cursor; second Tab applies.
  • Chained Tab-Tab-Tab: after any accept, the integration immediately re-triggers Mercury so the user can walk a refactor with repeated Tab presses.
  • Telemetry: NES events ride on the existing AUTOCOMPLETE_LLM_* event names with mode: \"next-edit\" — no schema change.

Backwards compatibility

  • The classic FIM path is untouched: same provider, same gateway routing, same model ids.
  • inception/mercury-edit-2 keeps its original FIM-via-gateway behaviour. The new NES path is opt-in via a separate model id (inception/mercury-next-edit).
  • The only cross-cutting change is making recentlyVisitedRangesService on AutocompleteInlineCompletionProvider public readonly so the new NES provider can read from the same LRU instead of double-tracking.

Settings added

Setting Default Purpose
kilo-code.new.autocomplete.nextEdit.apiKey empty Inception API key (falls back to INCEPTION_API_KEY env var)
kilo-code.new.autocomplete.nextEdit.baseUrl empty Override the API base (defaults to https://api.inceptionlabs.ai/v1); useful for self-hosted gateways
kilo-code.new.autocomplete.nextEdit.debug false Mirror diagnostic logs to DevTools console in addition to the output channel

Plus a new entry in the existing kilo-code.new.autocomplete.model enum: inception/mercury-next-edit → label "Mercury Next Edit (Inception)".

Two new keybindings, both gated on kilo-code.nextEdit.hasPendingSuggestion:

  • Tabkilo-code.next-edit.acceptOrJump
  • Escapekilo-code.next-edit.dismiss

Test plan

  • bun run check-types:extension clean
  • bun run lint src clean
  • bun test src/services/autocomplete/next-edit/__tests__/ — 23/23 pass (prompt template, response parser, region selector, snippets adapter)
  • Walk through docs/mercury-next-edit-testing.html in the Extension Development Host with a real Inception API key
  • Verify the classic FIM path still works when model = inception/mercury-edit-2 or mistralai/codestral-2508
  • Try the jump-then-apply UX on a real refactor (the test playground exercises it; a real-world refactor is the true ground truth)

Notes for reviewers

  • No system prompt is sent on the /v1/edit/completions endpoint — Mercury bakes its system prompt server-side and the endpoint actively rejects requests with a role: \"system\" message (returns HTTP 400). The constants file documents this so it doesn't get re-introduced.
  • The integration calls api.inceptionlabs.ai directly (not via the Kilo gateway) when in NES mode. If you'd prefer to route through the gateway, the nextEdit.baseUrl setting and MercuryEditProvider.options.model already make that swappable.
  • Console logging defaults to the dedicated Kilo Code · Next Edit output channel; nothing goes to DevTools console unless nextEdit.debug = true.

Feedback we're hoping for

  1. Cases where the prediction is wrong but the UX is right (helps us tune the model)
  2. Cases where the UX is in the way (Tab semantics, decoration appearance, chained-prediction timing)
  3. Any regression in the classic FIM autocomplete — this PR should be invisible there
  4. Things you tried that aren't in the test playground

Reach out: firas@inceptionlabs.ai

🤖 Generated with Claude Code

if (debugEnabled()) console.warn(`[NES] ${message}`)
}

export function disposeLog(): void {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: disposeLog() is exported but never called anywhere in the codebase. The OutputChannel created by getChannel() will never be disposed when the extension deactivates, leaking a VS Code UI resource.

The dispose() method on AutocompleteServiceManager and NextEditSuggestionManager both clean up their own resources, but nothing calls disposeLog(). Either:

  • Call disposeLog() from AutocompleteServiceManager.dispose(), or
  • Make the channel instance-owned (pass it in or create it inside the manager) rather than module-level so it naturally participates in the disposal chain.

import type { NextEditSuggestionManager } from "./NextEditSuggestionManager"
import type { MercuryEditRequestContext, MercuryRecentSnippet } from "./types"

const INLINE_COMPLETION_ACCEPTED_COMMAND = "kilocode.autocomplete.next-edit.accepted"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Command ID naming inconsistency — "kilocode.autocomplete.next-edit.accepted" uses kilocode (no dash) while every other command in this extension uses the kilo-code.* prefix (e.g. kilo-code.next-edit.acceptOrJump, kilo-code.next-edit.dismiss).

This means the accepted-command fires under a different namespace than the jump/dismiss commands, breaking the naming convention established in AGENTS.md (All VSCode commands must use kilo-code.new. prefix). Since this command is attached to InlineCompletionItem and not user-facing, it won't break UX, but it will cause confusion and inconsistency in telemetry/logs.

Suggestion: rename to "kilo-code.new.autocomplete.next-edit.accepted" (or at minimum "kilo-code.next-edit.accepted") and update the NEXT_EDIT_ACCEPTED_COMMAND constant + package.json command declaration.

if (document.uri.scheme !== "file") return undefined
const apiKey = this.deps.getApiKey()
if (!apiKey) {
nesLog("skip — no API key resolved")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: nesLog("skip — no API key resolved") fires on every keystroke when mercury-next-edit is selected but no API key is configured, eagerly creating the OutputChannel and flooding it with messages.

Consider a silent early return here, or at minimum rate-limiting/de-duplicating this log message. A single warning on first skip (e.g. via a hasWarnedNoKey flag) would be less noisy for users who haven't finished configuring the integration.

@kilo-code-bot

kilo-code-bot Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 3
SUGGESTION 0
Issue Details (click to expand)

WARNING

| File | Line | Issue |
|---|---|
|---|
| packages/kilo-gateway/src/server/edit.ts | 35 | console.info fires unconditionally on every NES edit request — logs provider, model, URL, and prompt char count on every keystroke trigger |
| packages/opencode/src/kilocode/server/httpapi/handlers/kilo-gateway.ts | 190 | Same console.info on every NES request in the Effect handler path — both Hono and Effect handlers log unconditionally |
| packages/kilo-vscode/src/services/autocomplete/next-edit/NextEditInlineCompletionProvider.ts | 72 | nesLog("skip — file is gitignore/kilocodeignore-excluded") fires on every keystroke in an ignored file, flooding the OutputChannel |

Resolved Issues (from previous reviews)

| File | Issue | Status |
|---|---|
|---|
| packages/kilo-vscode/src/services/autocomplete/next-edit/log.ts | disposeLog() never called — OutputChannel leaked on deactivation | ✅ Fixed |
| packages/kilo-vscode/src/services/autocomplete/next-edit/NextEditInlineCompletionProvider.ts | Command ID kilocode.autocomplete.next-edit.accepted used wrong prefix | ✅ Fixed |
| packages/kilo-vscode/src/services/autocomplete/next-edit/NextEditInlineCompletionProvider.ts | Per-keystroke nesLog("skip — no API key resolved") flooded output channel | ✅ Fixed: API key path removed entirely |
| packages/kilo-vscode/package.json | kilo-code.next-edit.acceptOrJump and .dismiss missing from contributes.commands | ✅ Fixed |
| packages/kilo-gateway/src/server/edit.ts | extractFencedBody returns raw message when no fence found | ✅ Fixed |

Files Reviewed (incremental — commit 7437f77)

Changed files in this commit reviewed:

  • packages/kilo-gateway/src/edit-prompt.ts — 0 issues (prompt templating correctly moved to gateway; well-tested)
  • packages/kilo-gateway/src/server/edit.ts — 1 issue (carried forward: console.info per-request)
  • packages/kilo-gateway/src/server/routes.ts — 0 issues (schema updated to match structured context)
  • packages/kilo-gateway/test/edit-prompt.test.ts — 0 issues (good coverage of all builders)
  • packages/kilo-vscode/src/services/autocomplete/AutocompleteServiceManager.ts — 0 issues (FileIgnoreController correctly wired for both sync and async paths)
  • packages/kilo-vscode/src/services/autocomplete/classic-auto-complete/AutocompleteInlineCompletionProvider.ts — 0 issues (ignoreController visibility change to public readonly)
  • packages/kilo-vscode/src/services/autocomplete/next-edit/MercuryEditProvider.ts — 0 issues (prompt building removed, structured context sent)
  • packages/kilo-vscode/src/services/autocomplete/next-edit/NextEditInlineCompletionProvider.ts — 1 issue (new nesLog per-keystroke for ignored files)
  • packages/kilo-vscode/src/services/autocomplete/next-edit/__tests__/mercuryPromptTemplate.spec.ts — deleted (tests moved to gateway)
  • packages/kilo-vscode/src/services/autocomplete/next-edit/constants.ts — 0 issues (sentinel tokens removed, comment updated)
  • packages/kilo-vscode/src/services/autocomplete/next-edit/log.ts — 0 issues (debug setting removed, env-only toggle)
  • packages/kilo-vscode/src/services/autocomplete/next-edit/mercuryPromptTemplate.ts — deleted (moved to gateway)
  • packages/opencode/src/kilocode/server/httpapi/groups/kilo-gateway.ts — 0 issues (schema updated)
  • packages/opencode/src/kilocode/server/httpapi/handlers/kilo-gateway.ts — 1 issue (carried forward: console.info per-request)
  • packages/sdk/js/src/v2/gen/sdk.gen.ts — 0 issues (auto-generated, reflects schema change)
  • packages/sdk/js/src/v2/gen/types.gen.ts — 0 issues (auto-generated, reflects schema change)

Fix these issues in Kilo Cloud


Reviewed by claude-4.6-sonnet-20260217 · 656,260 tokens

Review guidance: REVIEW.md from base branch main

@markijbema

Copy link
Copy Markdown
Contributor

Since this is a big change, I think it's best to first give a high over review, with the main points where this PR differs from where we want to take our autocomplete implementation. I understand this isnt all clear from existing code so I'll try to sketch some context

where code should live

Ideally most of the code lives in the sdk/backend, not the vscode extension. Since autocomplete inherently needs to use the editor we can't move all the code to the backend, of course, but if possible it should go there. Main reason is that we want to share this code between the VS Code extension, the Jetbrains extension (and possibly the TUI, for chat autocomplete)

This means that at least the request handling should move to the backend.

how providers are chosen

In the old extension we did this all through magic and fallbacks, and we got our users very confused, so I think it's important the user makes the explicit choice of what model and what provider to use. Therefore I don't think we should change behaviour based on discovery of env vars. However, there was no design yet for other providers than kilo gateway, so I added that here:

#10559

configuration

Configuration should be stored as much as possible via the backend, and not in vscode. autocomplete is a bad example here as we store a lot of config still in vscode, but we want to move that, we should not add new config however, and specifically not an api key.

Ignoring files

We use the FileIgnoreController to make sure the autocomplete functionality does not send .env files etc to a server, the NES should use this as well

Other

I've had some agent sessions review this PR, and they had some other comments, but I think the comments above are more broad, and it would be good to do a more detailed review after adressing those

Addresses @markijbema's architectural feedback on Kilo-Org#10536: moves the HTTP
edit-completion call to the gateway, removes the standalone API-key
setting, and aligns with the provider/model selection design introduced
in Kilo-Org#10559.

Wire-level changes
------------------
* New `/kilo/edit` endpoint added to the opencode HttpApi contract
  (`packages/opencode/src/kilocode/server/httpapi/groups/kilo-gateway.ts`)
  and mirrored into `packages/kilo-gateway/src/server/routes.ts` for the
  hono surface. SDK regenerated; `client.kilo.edit({ content, provider,
  model, maxTokens })` is now available.
* `packages/kilo-gateway/src/edit.ts` — `EditTarget` resolver mirroring
  the FIM pattern. Only the Inception provider is wired today (Mistral
  doesn't expose a comparable surface); Kilo Gateway has a placeholder
  branch that returns 400 until a server-side proxy exists.
* `packages/kilo-gateway/src/server/edit.ts` — `createEditHandler` reads
  the Inception BYOK key from `Auth.get("inception")` and falls back to
  `INCEPTION_API_KEY` from env, exactly like the FIM handler.
* The gateway unwraps Mercury's triple-backtick fence (and any
  `<|code_to_edit|>` sentinels) server-side so the VSCode response is
  just the rewritten code.
* `AutocompleteModelDef` gains an optional `kind: "fim" | "edit"`
  discriminator; new entry `inception/mercury-next-edit` (label "Mercury
  Next Edit") sets `kind: "edit"` and shares the wire model
  `mercury-edit-2`.

VSCode-side
-----------
* `MercuryEditProvider` no longer does its own HTTP — it's now a thin
  wrapper around `client.kilo.edit(...)` via `KiloConnectionService`.
* Dropped `kilo-code.new.autocomplete.nextEdit.apiKey` and
  `.nextEdit.baseUrl` settings. Auth and routing live in the gateway.
* The `AutocompleteServiceManager` dispatch now switches on the model's
  `kind` field (set by `getAutocompleteModel(provider, model)`) instead
  of string-comparing a model id, matching Mark's provider+model split.
* The `NextEditInlineCompletionProvider`,
  `NextEditSuggestionManager`, prompt template, parser, editable-region
  selector, edit-history tracker, recently-viewed-snippets adapter, and
  decoration-based jump-to-edit UX remain in the VSCode extension since
  they need editor-specific APIs (`InlineCompletionItem`,
  `TextEditorDecorationType`, keybinding context keys).

Bot review nits resolved
------------------------
* `INLINE_COMPLETION_ACCEPTED_COMMAND` renamed `kilocode.*` →
  `kilo-code.*` to match the project convention.
* `kilo-code.next-edit.acceptOrJump` and `.dismiss` now declared in
  `contributes.commands` so VS Code can resolve them in the palette.
* `disposeLog()` wired into `AutocompleteServiceManager.dispose()` so
  the dedicated "Kilo Code · Next Edit" OutputChannel doesn't leak.
* Per-keystroke "skip — no API key resolved" log removed (the entire
  API-key code path is gone).

Tests
-----
* `bun run check-types:extension` clean
* `bun run lint src` clean
* `bun test src/services/autocomplete/next-edit/__tests__/` — 23/23
  pass

Docs
----
* The partner walkthrough at
  `packages/kilo-vscode/docs/mercury-next-edit-testing.html` and the
  20-test playground under
  `packages/kilo-vscode/docs/nes-examples/` survive from the prior
  iteration. The walkthrough's "Install the PR locally" section still
  applies (the model dropdown choice is now "Mercury Next Edit
  (Inception)" — the API-key step is gone since BYOK is plumbed through
  the gateway's Auth store).

Known follow-ups (not in this commit)
-------------------------------------
* `FileIgnoreController` plumbing through the NES context builder so
  `.env`-style files don't get sent. Hook point identified in
  `NextEditInlineCompletionProvider.buildRequestContext`.
* Settings UI changes in the webview to expose Mercury Next Edit as a
  selectable provider/model pair alongside the FIM entries.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tfiras
tfiras force-pushed the mercury-next-edit-integration branch from 47c952c to fe60a46 Compare May 26, 2026 22:52
function extractFencedBody(message: string): string {
if (!message) return ""
const fenceOpen = message.indexOf("```")
if (fenceOpen === -1) return message

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: extractFencedBody returns the raw message when no code fence is found, but the old parseMercuryEditReply (still present in editCompletionParser.ts) returned null for the same case.

If Mercury responds without a triple-backtick fence — e.g. a rate-limit prose message, a refusal, or an unexpected format — the full response text will propagate to parseSuccess as replacement, pass the replacement.length === 0 guard, and be inserted directly into the user's document as code.

Consider returning "" instead so the gateway's response schema sends content: "", which parseSuccess already treats as a no-op (replacement.length === 0 → return null):

Suggested change
if (fenceOpen === -1) return message
if (fenceOpen === -1) return ""

Two-agent review pass on the gateway-routed NES change. Fixes:

Correctness (🔴)
- MercuryEditProvider read the HTTP status off the parsed error body
  (`error.status`, always undefined), so 401/402 never reached
  onFatalError and NES had no credit-exhausted/auth backoff. Now reads
  `response.status` from the SDK result.
- NextEditSuggestionManager applied "insert" suggestions without the
  apply-time drift re-validation the "replace" path already had — edits
  between the anchor and insertion point could land the insert in the
  wrong place. Now re-checks the anchor line before inserting.
- The opencode Effect edit handler collapsed every upstream failure to
  HTTP 400; now passes the real status through (mirrors the FIM handler)
  so 401/402/429/5xx are distinguishable under the experimental backend.

Conciseness / DRY (🔴)
- Deleted dead module editCompletionParser.ts (+ spec): the gateway
  unwraps the fence server-side now, so the VSCode-side parser was unused.
- Hoisted the triplicated extractFencedBody into a single exported
  function in kilo-gateway/src/edit.ts; both the hono and Effect handlers
  import it. Added a shared EditUpstreamResponse type to replace three
  inline copies.

Robustness (🟡)
- extractFencedBody now keeps the body when the closing fence is missing
  (truncated/max_tokens output) instead of dropping the suggestion.
- EditHistoryTracker seeds snapshots on document open so the first edit
  in a freshly-opened file is captured (was previously dropped).
- Single-line inserts that span non-blank lines below the cursor (a
  multi-line→single-line collapse) now route to the decoration path
  instead of emitting a ghost item VSCode can't render.

Cleanup (🟡)
- Removed unused constants (MERCURY_EDIT_MODEL_ID, INCEPTION_API_BASE_URL,
  INCEPTION_EDIT_PATH).
- getProviderKey typed to DirectAutocompleteProviderID (matches FIM).
- resolveEditTarget keys on kind==="edit" defensively, so a future
  FIM-only Inception model can't resolve to the edit endpoint.
- AutocompleteModelDef doc comments made endpoint-neutral (not "FIM").
- Declared the internal accept command in contributes.commands.

Tests
- New packages/kilo-gateway/test/edit.test.ts: resolveEditTarget routing
  (incl. the mercury-edit-2 FIM model must NOT reach the edit endpoint)
  and extractFencedBody variants (lang tag, sentinels, truncation, blank
  lines, no-fence).
- typecheck clean across kilo-gateway, opencode, kilo-vscode; lint clean;
  all unit tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
}

const signal = AbortSignal.any([c.req.raw.signal, AbortSignal.timeout(EDIT_TIMEOUT_MS)])
console.info(`[EDIT] request provider=${target.provider} model=${target.model} url=${target.url} chars=${content.length}`)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: console.info fires on every NES edit request via the gateway server's stdout. This is the same class of issue previously noted for fim.ts. Gateway logs should use a structured logger or be gated on a debug flag — unconditional console.info will appear in server logs on every keystroke trigger. Consider removing or replacing with the nesLog/debug-gated pattern used on the VSCode side.

: AbortSignal.timeout(FIM_TIMEOUT_MS)

const response = yield* Effect.promise(async () => {
console.info(`[EDIT] request provider=${target.provider} model=${target.model} chars=${ctx.payload.content.length}`)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Same console.info on every NES edit request in the Effect handler path. Both the Hono (packages/kilo-gateway/src/server/edit.ts:31) and this Effect handler log unconditionally. If either fires in production, every NES trigger produces a server-side log line. Consider removing or moving behind a debug flag.

Addresses the two remaining points from @markijbema's review.

Prompt templating now lives in the gateway
-------------------------------------------
The Mercury sentinel-prompt assembly moved out of the VSCode extension
into packages/kilo-gateway/src/edit-prompt.ts. Clients now send
structured editor context (currentFileContent, cursor position,
editable region, recently-viewed snippets, edit-diff history) and the
gateway builds the sentinel-tagged prompt. This keeps the entire
Mercury contract — endpoint, auth, prompt format, response parsing — in
one place that VS Code, JetBrains, and the TUI can all share, instead
of each editor re-implementing the templating.

- New EditBody is the structured context (was: a pre-built `content`
  string). Updated the opencode HttpApi schema, the hono zod validator,
  both handlers, and regenerated the SDK.
- Deleted the VSCode-side mercuryPromptTemplate.ts (+ spec); the tests
  moved to packages/kilo-gateway/test/edit-prompt.test.ts.
- VSCode constants.ts now holds only the editable-region sizing; the
  sentinel tokens live in the gateway.

FileIgnoreController
--------------------
NES must not send ignored files (.env, secrets, anything matched by
.gitignore/.kilocodeignore) to the server. The NES provider now:
- skips the request entirely if the active document fails
  ignoreController.validateAccess(), and
- filters recently-viewed snippets through the same controller before
  they go into the prompt.
It reuses the classic provider's FileIgnoreController instance (now
public) rather than building a second one.

Also: dropped the implicit nextEdit.debug config read in log.ts (debug
is env-only via KILO_NES_DEBUG) so no VSCode autocomplete config is
added — per the "config should move to the backend" guidance.

Validation: typecheck clean across kilo-gateway, opencode, kilo-vscode;
lint clean; gateway 46 tests, vscode next-edit 10 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

// Never send an ignored file (.env, secrets, etc.) to the model.
if (this.deps.isFileAllowed && !(await this.deps.isFileAllowed(document.uri.fsPath))) {
nesLog("skip — file is gitignore/kilocodeignore-excluded")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: nesLog(...) fires unconditionally on every keystroke in an ignored file

For any file matching .gitignore or .kilocodeignore (e.g. .env), every single keystroke triggers provideInlineCompletionItems, the isFileAllowed check returns false, and this nesLog call appends a timestamped line to the VS Code OutputChannel. Over a few minutes of editing a .env file the channel will accumulate thousands of entries.

The previous nesLog("skip — no API key resolved") was removed for exactly this reason. The same fix applies here: guard behind debugEnabled() or remove the log entirely (the early return undefined is sufficient; the skip is observable by the absence of suggestions).

@LigiaZ

LigiaZ commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

@tfiras could you please link your GitHub account to the Kilo account? This way, we can grant you credits for the merged PRs.
Once you have done that, please message hi@kilocode.ai

t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
Addresses @markijbema's architectural feedback on Kilo-Org#10536: moves the HTTP
edit-completion call to the gateway, removes the standalone API-key
setting, and aligns with the provider/model selection design introduced
in Kilo-Org#10559.

Wire-level changes
------------------
* New `/kilo/edit` endpoint added to the opencode HttpApi contract
  (`packages/opencode/src/kilocode/server/httpapi/groups/kilo-gateway.ts`)
  and mirrored into `packages/kilo-gateway/src/server/routes.ts` for the
  hono surface. SDK regenerated; `client.kilo.edit({ content, provider,
  model, maxTokens })` is now available.
* `packages/kilo-gateway/src/edit.ts` — `EditTarget` resolver mirroring
  the FIM pattern. Only the Inception provider is wired today (Mistral
  doesn't expose a comparable surface); Kilo Gateway has a placeholder
  branch that returns 400 until a server-side proxy exists.
* `packages/kilo-gateway/src/server/edit.ts` — `createEditHandler` reads
  the Inception BYOK key from `Auth.get("inception")` and falls back to
  `INCEPTION_API_KEY` from env, exactly like the FIM handler.
* The gateway unwraps Mercury's triple-backtick fence (and any
  `<|code_to_edit|>` sentinels) server-side so the VSCode response is
  just the rewritten code.
* `AutocompleteModelDef` gains an optional `kind: "fim" | "edit"`
  discriminator; new entry `inception/mercury-next-edit` (label "Mercury
  Next Edit") sets `kind: "edit"` and shares the wire model
  `mercury-edit-2`.

VSCode-side
-----------
* `MercuryEditProvider` no longer does its own HTTP — it's now a thin
  wrapper around `client.kilo.edit(...)` via `KiloConnectionService`.
* Dropped `kilo-code.new.autocomplete.nextEdit.apiKey` and
  `.nextEdit.baseUrl` settings. Auth and routing live in the gateway.
* The `AutocompleteServiceManager` dispatch now switches on the model's
  `kind` field (set by `getAutocompleteModel(provider, model)`) instead
  of string-comparing a model id, matching Mark's provider+model split.
* The `NextEditInlineCompletionProvider`,
  `NextEditSuggestionManager`, prompt template, parser, editable-region
  selector, edit-history tracker, recently-viewed-snippets adapter, and
  decoration-based jump-to-edit UX remain in the VSCode extension since
  they need editor-specific APIs (`InlineCompletionItem`,
  `TextEditorDecorationType`, keybinding context keys).

Bot review nits resolved
------------------------
* `INLINE_COMPLETION_ACCEPTED_COMMAND` renamed `kilocode.*` →
  `kilo-code.*` to match the project convention.
* `kilo-code.next-edit.acceptOrJump` and `.dismiss` now declared in
  `contributes.commands` so VS Code can resolve them in the palette.
* `disposeLog()` wired into `AutocompleteServiceManager.dispose()` so
  the dedicated "Kilo Code · Next Edit" OutputChannel doesn't leak.
* Per-keystroke "skip — no API key resolved" log removed (the entire
  API-key code path is gone).

Tests
-----
* `bun run check-types:extension` clean
* `bun run lint src` clean
* `bun test src/services/autocomplete/next-edit/__tests__/` — 23/23
  pass

Docs
----
* The partner walkthrough at
  `packages/kilo-vscode/docs/mercury-next-edit-testing.html` and the
  20-test playground under
  `packages/kilo-vscode/docs/nes-examples/` survive from the prior
  iteration. The walkthrough's "Install the PR locally" section still
  applies (the model dropdown choice is now "Mercury Next Edit
  (Inception)" — the API-key step is gone since BYOK is plumbed through
  the gateway's Auth store).

Known follow-ups (not in this commit)
-------------------------------------
* `FileIgnoreController` plumbing through the NES context builder so
  `.env`-style files don't get sent. Hook point identified in
  `NextEditInlineCompletionProvider.buildRequestContext`.
* Settings UI changes in the webview to expose Mercury Next Edit as a
  selectable provider/model pair alongside the FIM entries.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants