Skip to content

Add Kilo SDK-backed provider adapter#3882

Draft
Githubguy132010 wants to merge 3 commits into
pingdotgg:mainfrom
Githubguy132010:feat/kilo-provider-adapter
Draft

Add Kilo SDK-backed provider adapter#3882
Githubguy132010 wants to merge 3 commits into
pingdotgg:mainfrom
Githubguy132010:feat/kilo-provider-adapter

Conversation

@Githubguy132010

@Githubguy132010 Githubguy132010 commented Jul 11, 2026

Copy link
Copy Markdown

What Changed

  • Adds kilo as a first-party provider backed by @kilocode/sdk and a managed kilo serve process.
  • Discovers connected upstream models dynamically from /provider and stores selections as providerID/modelID while retaining one top-level Kilo provider.
  • Supports session creation, prompting, streamed assistant/reasoning output, interruption, permissions, questions, tool lifecycle events, todos/plan updates, best-effort rollback, and provider-backed text generation.
  • Adds the narrow Kilo settings surface requested in [Feature]: Add a Kilo SDK-backed provider adapter #1579: enabled state, binary path, and custom models.
  • Adds Kilo to provider settings/model selection with its brand icon.

Why

Closes #1579.

Kilo exposes typed server, session, provider, and event APIs through @kilocode/sdk. Using that integration surface avoids scraping CLI output and allows T3 Code to consume Kilo's live model inventory and structured session stream without exposing Kilo's internal upstream providers or agent modes as separate T3 concepts.

The initial adapter intentionally uses Kilo's built-in code agent by default, maps plan turns to plan, and treats recovery as best effort.

UI Changes

Kilo now appears in provider settings and the model picker. The UI reuses the existing generic provider settings and picker components; no new interaction surface or animation was added.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Verification

  • vp check
  • vp run typecheck
  • vp test run src/provider/kiloRuntime.test.ts src/provider/Layers/KiloProvider.test.ts src/provider/Layers/ProviderInstanceRegistryLive.test.ts (10 tests)
  • Live SDK smoke test against Kilo CLI 7.3.54: launched kilo serve and loaded /provider successfully.

Note

Add Kilo SDK-backed provider adapter with session lifecycle and text generation

  • Introduces a new kilo provider driver backed by the @kilocode/sdk package, including a full adapter (KiloAdapter.ts) and text generation implementation (KiloTextGeneration.ts).
  • The adapter manages session lifecycle, turn sending with text/file attachments, permission and question handling, event streaming, thread reading/rollback, and session interruption.
  • A KiloRuntime service wraps the Kilo binary and SDK: spawning a scoped server process, loading upstream provider inventory, and surfacing failures as structured KiloRuntimeError instances.
  • Adds KiloSettings to server config (enabled, binaryPath, customModels) and registers kilo in provider metadata, model defaults, display names, and the settings UI.
  • Risk: the Kilo server process is spawned as a detached child on non-Windows platforms; if process teardown fails, orphaned processes may remain.
📊 Macroscope summarized 0cd8252. 15 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 648e6d7d-33d7-45d2-b048-5c593501c920

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Jul 11, 2026
Comment thread apps/server/src/textGeneration/KiloTextGeneration.ts Outdated
Comment thread apps/server/src/textGeneration/KiloTextGeneration.ts Outdated
Comment thread apps/server/src/provider/kiloRuntime.ts Outdated
Comment thread apps/server/src/provider/Layers/KiloAdapter.ts
Comment thread apps/server/src/provider/Layers/KiloAdapter.ts
Comment thread apps/server/src/provider/kiloRuntime.ts

@macroscopeapp macroscopeapp Bot left a comment

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.

Effect service review: one convention issue found in the new Kilo text-generation service. See inline comment.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/textGeneration/KiloTextGeneration.ts Outdated
modelSelection: input.modelSelection,
prompt: `Return JSON with subject and body for this staged change.\nBranch: ${input.branch ?? "unknown"}\nSummary:\n${input.stagedSummary}\nPatch:\n${input.stagedPatch}`,
}).pipe(
Effect.flatMap((text) =>

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.

🟡 Medium textGeneration/KiloTextGeneration.ts:175

decodeCommitOutput and decodePrOutput are applied directly to the raw Kilo text, so when the model wraps its JSON in a Markdown code fence ( json ... ), Schema.fromJsonString rejects the string and both generateCommitMessage and generatePrContent fail. The other providers extract the JSON object before decoding, but this path does not. Strip Markdown fences or use the shared JSON extraction before decoding.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/textGeneration/KiloTextGeneration.ts around line 175:

`decodeCommitOutput` and `decodePrOutput` are applied directly to the raw Kilo text, so when the model wraps its JSON in a Markdown code fence ([code fence] [code fence]json ... [code fence] [code fence]), `Schema.fromJsonString` rejects the string and both `generateCommitMessage` and `generatePrContent` fail. The other providers extract the JSON object before decoding, but this path does not. Strip Markdown fences or use the shared JSON extraction before decoding.

Comment on lines +682 to +702
yield* runKiloSdk("session.promptAsync", () =>
context.client.session.promptAsync(
{
sessionID: context.kiloSessionId,
model,
agent: input.interactionMode === "plan" ? "plan" : FIXED_AGENT,
parts: [...(text ? [{ type: "text" as const, text }] : []), ...files],
},
{ throwOnError: true },
),
).pipe(
Effect.mapError(
(cause) =>
new ProviderAdapterRequestError({
provider: PROVIDER,
method: cause.operation,
detail: cause.detail,
cause,
}),
),
);

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.

🟠 High Layers/KiloAdapter.ts:682

When session.promptAsync rejects in sendTurn, the session stays permanently marked as running with the assigned activeTurnId instead of reverting to ready. A subsequent sendTurn sees context.activeTurnId still set, so freshTurn is false — it reuses the stale turn ID and suppresses the turn.started event. Consider resetting context.activeTurnId and updating the session status on the error path so the turn failure is fully rolled back.

      ).pipe(
+        Effect.catchAll((error) =>
+          Effect.gen(function* () {
+            if (freshTurn) {
+              context.activeTurnId = undefined;
+              yield* updateSession(context, { status: "ready" }, true);
+            }
+            return yield* Effect.fail(error);
+          }),
+        ),
        Effect.mapError(
          (cause) =>
            new ProviderAdapterRequestError({
              provider: PROVIDER,
              method: cause.operation,
              detail: cause.detail,
              cause,
            }),
        ),
      );
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/Layers/KiloAdapter.ts around lines 682-702:

When `session.promptAsync` rejects in `sendTurn`, the session stays permanently marked as `running` with the assigned `activeTurnId` instead of reverting to `ready`. A subsequent `sendTurn` sees `context.activeTurnId` still set, so `freshTurn` is `false` — it reuses the stale turn ID and suppresses the `turn.started` event. Consider resetting `context.activeTurnId` and updating the session status on the error path so the turn failure is fully rolled back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add a Kilo SDK-backed provider adapter

1 participant