Skip to content

Conversation

@markijbema
Copy link
Contributor

Summary

This PR introduces a structural improvement to the FIM (Fill-In-the-Middle) support by replacing the boolean supportsFim() check with a more idiomatic fimSupport() method that returns a FimHandler interface.

Changes

New FimHandler Interface

interface FimHandler {
  streamFim(prefix: string, suffix: string, taskId?: string, onUsage?: (usage: CompletionUsage) => void): AsyncGenerator<string>
  getModel(): { id: string; info: ModelInfo; maxTokens?: number }
  getTotalCost(usage: CompletionUsage): number
}

New fimSupport() Method on ApiHandler

fimSupport?: () => FimHandler | undefined

This replaces the previous pattern of:

if (handler.supportsFim()) {
  for await (const chunk of handler.streamFim(prefix, suffix)) {
    // handle chunk
  }
}

With the cleaner:

const fimHandler = handler.fimSupport()
if (fimHandler) {
  for await (const chunk of fimHandler.streamFim(prefix, suffix)) {
    // handle chunk
  }
}

Files Changed

  • src/api/providers/kilocode/FimHandler.ts - New file defining the FimHandler interface
  • src/api/index.ts - Added fimSupport optional method to ApiHandler interface
  • src/api/providers/mistral.ts - Implemented fimSupport() pattern
  • src/api/providers/kilocode-openrouter.ts - Implemented fimSupport() pattern
  • src/services/ghost/GhostModel.ts - Updated to use getFimHandler() helper
  • src/api/providers/__tests__/mistral-fim.spec.ts - Updated tests
  • src/api/providers/__tests__/kilocode-openrouter.spec.ts - Updated tests

Backward Compatibility

The supportsFim() method is kept as deprecated for backward compatibility. It now simply returns this.fimSupport() !== undefined.

Related

This is a follow-up to #3856 which added FIM support for Mistral/Codestral models. This PR addresses the structural improvement suggested in the review comments.

- Add FimHandler interface with streamFim, getModel, and getTotalCost methods
- Add fimSupport() method to ApiHandler that returns FimHandler | undefined
- Refactor MistralHandler to implement fimSupport() pattern
- Refactor KilocodeOpenrouterHandler to implement fimSupport() pattern
- Update GhostModel to use getFimHandler() helper function
- Keep supportsFim() as deprecated for backward compatibility
- Update tests to use the new fimSupport() API

This structural improvement replaces the boolean supportsFim() check with
a more idiomatic pattern where fimSupport() returns the handler directly
if FIM is supported, or undefined if not.
@changeset-bot
Copy link

changeset-bot bot commented Jan 7, 2026

⚠️ No Changeset found

Latest commit: 75bdfd9

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

…ity code

- Remove supportsFim() method from MistralHandler and KilocodeOpenrouterHandler
- Remove backward compatibility fallback in GhostModel's getFimHandler()
- Remove tests for deprecated supportsFim() method
- Clean up comments that referenced the old pattern
@markijbema markijbema marked this pull request as ready for review January 7, 2026 15:11
@kiloconnect
Copy link
Contributor

kiloconnect bot commented Jan 7, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

This PR refactors the FIM (Fill-In-the-Middle) support from a duck-typing approach to a proper interface-based design. The changes are well-structured and follow good TypeScript practices.

Key Improvements

  • New FimHandler interface provides clean abstraction for FIM operations
  • ApiHandler interface extended with optional fimSupport() method
  • Duck-typing in GhostModel replaced with proper interface usage
  • streamFim methods appropriately made private in provider implementations
Files Reviewed (7 files)
  • src/api/index.ts - Added FimHandler type export and fimSupport to ApiHandler interface
  • src/api/providers/kilocode/FimHandler.ts - New interface definition
  • src/api/providers/kilocode-openrouter.ts - Refactored to use FimHandler pattern
  • src/api/providers/mistral.ts - Refactored to use FimHandler pattern
  • src/services/ghost/GhostModel.ts - Removed duck-typing, uses FimHandler interface
  • src/api/providers/__tests__/kilocode-openrouter.spec.ts - Tests updated for new API
  • src/api/providers/__tests__/mistral-fim.spec.ts - Tests updated for new API

Comment on lines +156 to +164
// Return a FimHandler implementation
return {
streamFim: this.streamFim.bind(this),
getModel: () => {
const { id, info, maxTokens } = this.getModel()
return { id, info, maxTokens }
},
getTotalCost: (usage: CompletionUsage) => this.getTotalCost(usage),
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Return a FimHandler implementation
return {
streamFim: this.streamFim.bind(this),
getModel: () => {
const { id, info, maxTokens } = this.getModel()
return { id, info, maxTokens }
},
getTotalCost: (usage: CompletionUsage) => this.getTotalCost(usage),
}
return this

isn't enough?

}

async *streamFim(
private async *streamFim(
Copy link
Contributor

Choose a reason for hiding this comment

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

well, without this change anyhow if you want to return this above

import { KilocodeOpenrouterHandler } from "./providers/kilocode-openrouter"
import { InceptionLabsHandler } from "./providers/inception"
import type { FimHandler } from "./providers/kilocode/FimHandler" // kilocode_change
export type { FimHandler } from "./providers/kilocode/FimHandler"
Copy link
Collaborator

Choose a reason for hiding this comment

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

any reason to export this here other than everyone/Opus does it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i assumed this to be best practice al this is the index file, and also has a barrel function. That's not the case?

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.

4 participants