Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
814d9eb
feat: add Kilo SDK-backed provider adapter
Githubguy132010 Jul 17, 2026
525cd9c
fix(kilo): address review findings for server lifecycle and turns
Githubguy132010 Jul 17, 2026
a6e5be0
fix(kilo): only delete session map entry for stopped context
Githubguy132010 Jul 17, 2026
48282b3
fix(kilo): handle clean SSE close and bound server log capture
Githubguy132010 Jul 17, 2026
c290766
test(kilo): keep mock SSE stream open after seeded events
Githubguy132010 Jul 17, 2026
0d088c4
test(kilo): honor abort signal in mock SSE keep-alive
Githubguy132010 Jul 17, 2026
3bd9c7f
fix(kilo): bound post-ready log capture; keep OpenCode SSE end semantics
Githubguy132010 Jul 17, 2026
235b778
fix(kilo): clear log capture only after ready settles
Githubguy132010 Jul 17, 2026
2eb40af
fix(kilo): atomically claim activeTurnId for concurrent sendTurn
Githubguy132010 Jul 17, 2026
61df41a
fix(kilo): only clear activeTurnId on failure if claim still owned
Githubguy132010 Jul 17, 2026
168b687
fix(kilo): harden interrupt claim clear and startup race
Githubguy132010 Jul 17, 2026
4dd769b
Merge branch 'main' into feat/kilo-provider-adapter
Githubguy132010 Jul 19, 2026
3fbe10c
fix(kilo): guard turn ownership across idle, interrupt, and error paths
Githubguy132010 Jul 19, 2026
50a201d
Merge branch 'main' into feat/kilo-provider-adapter
Githubguy132010 Jul 20, 2026
195fda0
fix(kilo-adapter): harden concurrency in session lifecycle and interrupt
Githubguy132010 Jul 20, 2026
8ebf766
Merge branch 'main' into feat/kilo-provider-adapter
Githubguy132010 Jul 20, 2026
5797ecf
fix(kilo-adapter): keep activeTurnId claim during in-flight session.a…
Githubguy132010 Jul 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@effect/platform-node-shared": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@ff-labs/fff-node": "0.9.4",
"@kilocode/sdk": "^7.4.11",
"@opencode-ai/sdk": "^1.3.15",
"@pierre/diffs": "catalog:",
"effect": "catalog:",
Expand Down
172 changes: 172 additions & 0 deletions apps/server/src/provider/Drivers/KiloDriver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/**
* KiloDriver — `ProviderDriver` for the Kilo runtime.
*
* Mirrors OpenCode: a plain value whose `create()` bundles
* `snapshot` / `adapter` / `textGeneration` closures over the
* per-instance `KiloSettings`.
*
* @module provider/Drivers/KiloDriver
*/
import { KiloSettings, ProviderDriverKind, type ServerProvider } from "@t3tools/contracts";
import * as Duration from "effect/Duration";
import * as Crypto from "effect/Crypto";
import * as Effect from "effect/Effect";
import * as FileSystem from "effect/FileSystem";
import * as Path from "effect/Path";
import * as Schema from "effect/Schema";
import { HttpClient } from "effect/unstable/http";
import { ChildProcessSpawner } from "effect/unstable/process";

import { makeKiloTextGeneration } from "../../textGeneration/KiloTextGeneration.ts";
import { ServerConfig } from "../../config.ts";
import { ServerSettingsService } from "../../serverSettings.ts";
import { ProviderDriverError } from "../Errors.ts";
import { makeKiloAdapter } from "../Layers/KiloAdapter.ts";
import { checkKiloProviderStatus, makePendingKiloProvider } from "../Layers/KiloProvider.ts";
import { ProviderEventLoggers } from "../Layers/ProviderEventLoggers.ts";
import { makeManagedServerProvider } from "../makeManagedServerProvider.ts";
import { KiloRuntime } from "../kiloRuntime.ts";
import {
defaultProviderContinuationIdentity,
type ProviderDriver,
type ProviderInstance,
} from "../ProviderDriver.ts";
import type { ServerProviderDraft } from "../providerSnapshot.ts";
import { mergeProviderInstanceEnvironment } from "../ProviderInstanceEnvironment.ts";
import {
enrichProviderSnapshotWithVersionAdvisory,
makeManualOnlyProviderMaintenanceCapabilities,
makeStaticProviderMaintenanceResolver,
resolveProviderMaintenanceCapabilitiesEffect,
} from "../providerMaintenance.ts";
import {
haveProviderSnapshotSettingsChanged,
makeProviderSnapshotSettingsSource,
type ProviderSnapshotSettings,
} from "../providerUpdateSettings.ts";

const decodeKiloSettings = Schema.decodeSync(KiloSettings);

const DRIVER_KIND = ProviderDriverKind.make("kilo");
const SNAPSHOT_REFRESH_INTERVAL = Duration.minutes(5);
const UPDATE = makeStaticProviderMaintenanceResolver(
makeManualOnlyProviderMaintenanceCapabilities({
provider: DRIVER_KIND,
packageName: null,
}),
);

export type KiloDriverEnv =
| ChildProcessSpawner.ChildProcessSpawner
| Crypto.Crypto
| FileSystem.FileSystem
| HttpClient.HttpClient
| KiloRuntime
| Path.Path
| ProviderEventLoggers
| ServerConfig
| ServerSettingsService;

const withInstanceIdentity =
(input: {
readonly instanceId: ProviderInstance["instanceId"];
readonly displayName: string | undefined;
readonly accentColor: string | undefined;
readonly continuationGroupKey: string;
}) =>
(snapshot: ServerProviderDraft): ServerProvider => ({
...snapshot,
instanceId: input.instanceId,
driver: DRIVER_KIND,
...(input.displayName ? { displayName: input.displayName } : {}),
...(input.accentColor ? { accentColor: input.accentColor } : {}),
continuation: { groupKey: input.continuationGroupKey },
});

export const KiloDriver: ProviderDriver<KiloSettings, KiloDriverEnv> = {
driverKind: DRIVER_KIND,
metadata: {
displayName: "Kilo",
supportsMultipleInstances: true,
},
configSchema: KiloSettings,
defaultConfig: (): KiloSettings => decodeKiloSettings({}),
create: ({ instanceId, displayName, accentColor, environment, enabled, config }) =>
Effect.gen(function* () {
const kiloRuntime = yield* KiloRuntime;
const serverConfig = yield* ServerConfig;
const httpClient = yield* HttpClient.HttpClient;
const serverSettings = yield* ServerSettingsService;
const eventLoggers = yield* ProviderEventLoggers;
const processEnv = mergeProviderInstanceEnvironment(environment);
const continuationIdentity = defaultProviderContinuationIdentity({
driverKind: DRIVER_KIND,
instanceId,
});
const stampIdentity = withInstanceIdentity({
instanceId,
displayName,
accentColor,
continuationGroupKey: continuationIdentity.continuationKey,
});
const effectiveConfig = { ...config, enabled } satisfies KiloSettings;
const maintenanceCapabilities = yield* resolveProviderMaintenanceCapabilitiesEffect(UPDATE, {
binaryPath: effectiveConfig.binaryPath,
env: processEnv,
});

const adapter = yield* makeKiloAdapter(effectiveConfig, {
instanceId,
environment: processEnv,
...(eventLoggers.native ? { nativeEventLogger: eventLoggers.native } : {}),
});
const textGeneration = yield* makeKiloTextGeneration(effectiveConfig, processEnv);

const checkProvider = checkKiloProviderStatus(
effectiveConfig,
serverConfig.cwd,
processEnv,
).pipe(Effect.map(stampIdentity), Effect.provideService(KiloRuntime, kiloRuntime));

const snapshotSettings = makeProviderSnapshotSettingsSource(effectiveConfig, serverSettings);
const snapshot = yield* makeManagedServerProvider<ProviderSnapshotSettings<KiloSettings>>({
maintenanceCapabilities,
getSettings: snapshotSettings.getSettings,
streamSettings: snapshotSettings.streamSettings,
haveSettingsChanged: haveProviderSnapshotSettingsChanged,
initialSnapshot: (settings) =>
makePendingKiloProvider(settings.provider).pipe(Effect.map(stampIdentity)),
checkProvider,
enrichSnapshot: ({ settings, snapshot, publishSnapshot }) =>
enrichProviderSnapshotWithVersionAdvisory(snapshot, maintenanceCapabilities, {
enableProviderUpdateChecks: settings.enableProviderUpdateChecks,
}).pipe(
Effect.provideService(HttpClient.HttpClient, httpClient),
Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)),
),
refreshInterval: SNAPSHOT_REFRESH_INTERVAL,
}).pipe(
Effect.mapError(
(cause) =>
new ProviderDriverError({
driver: DRIVER_KIND,
instanceId,
detail: `Failed to build Kilo snapshot: ${cause.message ?? String(cause)}`,
cause,
}),
),
);

return {
instanceId,
driverKind: DRIVER_KIND,
continuationIdentity,
displayName,
accentColor,
enabled,
snapshot,
adapter,
textGeneration,
} satisfies ProviderInstance;
}),
};
Loading
Loading