diff --git a/packages/opencode/src/kilocode/plan-followup.ts b/packages/opencode/src/kilocode/plan-followup.ts index e8a7bd5c94e..b851bf3cc1a 100644 --- a/packages/opencode/src/kilocode/plan-followup.ts +++ b/packages/opencode/src/kilocode/plan-followup.ts @@ -19,39 +19,40 @@ import { Todo } from "@/session/todo" import { makeRuntime } from "@/effect/run-service" import * as Log from "@opencode-ai/core/util/log" import { KiloSessionPromptQueue } from "@/kilocode/session/prompt-queue" +import { lazy } from "@/util/lazy" import path from "path" import z from "zod" -const agents = makeRuntime(Agent.Service, Agent.defaultLayer) -const providers = makeRuntime(Provider.Service, Provider.defaultLayer) -const questions = makeRuntime(Question.Service, Question.defaultLayer) -const todo = makeRuntime(Todo.Service, Todo.defaultLayer) +const agents = lazy(() => makeRuntime(Agent.Service, Agent.defaultLayer)) +const providers = lazy(() => makeRuntime(Provider.Service, Provider.defaultLayer)) +const questions = lazy(() => makeRuntime(Question.Service, Question.defaultLayer)) +const todo = lazy(() => makeRuntime(Todo.Service, Todo.defaultLayer)) const pending = new Map() export const PlanFollowupRuntime = { agent(name: string): Promise { - return agents.runPromise((svc) => svc.get(name)) + return agents().runPromise((svc) => svc.get(name)) }, model(providerID: ProviderID, modelID: ModelID): Promise { - return providers.runPromise((svc) => svc.getModel(providerID, modelID)) + return providers().runPromise((svc) => svc.getModel(providerID, modelID)) }, question: { ask(input: Parameters[0]) { - return questions.runPromise((svc) => svc.ask(input)) + return questions().runPromise((svc) => svc.ask(input)) }, list() { - return questions.runPromise((svc) => svc.list()) + return questions().runPromise((svc) => svc.list()) }, reject(requestID: Parameters[0]) { - return questions.runPromise((svc) => svc.reject(requestID)) + return questions().runPromise((svc) => svc.reject(requestID)) }, }, todo: { get(sessionID: SessionID) { - return todo.runPromise((svc) => svc.get(sessionID)) + return todo().runPromise((svc) => svc.get(sessionID)) }, update(input: Parameters[0]) { - return todo.runPromise((svc) => svc.update(input)) + return todo().runPromise((svc) => svc.update(input)) }, }, async loop(sessionID: SessionID) { diff --git a/packages/opencode/src/kilocode/server/httpapi/handlers/commit-message.ts b/packages/opencode/src/kilocode/server/httpapi/handlers/commit-message.ts index 51c90ee5c20..d1c4366a0e2 100644 --- a/packages/opencode/src/kilocode/server/httpapi/handlers/commit-message.ts +++ b/packages/opencode/src/kilocode/server/httpapi/handlers/commit-message.ts @@ -1,5 +1,6 @@ import { Effect } from "effect" import { HttpApiBuilder } from "effect/unstable/httpapi" +import { EffectBridge } from "@/effect/bridge" import { InstanceHttpApi } from "@/server/routes/instance/httpapi/api" import { Config } from "@/config/config" import { generateCommitMessage } from "@/kilocode/commit-message" @@ -14,7 +15,7 @@ export const commitMessageHandlers = HttpApiBuilder.group(InstanceHttpApi, "comm }) { const cfg = yield* config.get() const prompt = cfg.commit_message?.prompt || undefined - const result = yield* Effect.promise(() => + const result = yield* EffectBridge.fromPromise(() => generateCommitMessage({ path: ctx.payload.path, selectedFiles: ctx.payload.selectedFiles ? [...ctx.payload.selectedFiles] : undefined, diff --git a/packages/opencode/src/kilocode/server/httpapi/handlers/enhance-prompt.ts b/packages/opencode/src/kilocode/server/httpapi/handlers/enhance-prompt.ts index 4abdd24a316..38e70536685 100644 --- a/packages/opencode/src/kilocode/server/httpapi/handlers/enhance-prompt.ts +++ b/packages/opencode/src/kilocode/server/httpapi/handlers/enhance-prompt.ts @@ -1,5 +1,6 @@ import { Effect } from "effect" import { HttpApiBuilder } from "effect/unstable/httpapi" +import { EffectBridge } from "@/effect/bridge" import { InstanceHttpApi } from "@/server/routes/instance/httpapi/api" import { enhancePrompt } from "@/kilocode/enhance-prompt" import { EnhancePromptPayload } from "../groups/enhance-prompt" @@ -9,7 +10,7 @@ export const enhancePromptHandlers = HttpApiBuilder.group(InstanceHttpApi, "enha const enhance = Effect.fn("EnhancePromptHttpApi.enhance")(function* (ctx: { payload: typeof EnhancePromptPayload.Type }) { - const text = yield* Effect.promise(() => enhancePrompt(ctx.payload.text)) + const text = yield* EffectBridge.fromPromise(() => enhancePrompt(ctx.payload.text)) return { text } }) diff --git a/packages/opencode/src/kilocode/server/httpapi/handlers/indexing.ts b/packages/opencode/src/kilocode/server/httpapi/handlers/indexing.ts index abf46c01979..54d9a59d1f3 100644 --- a/packages/opencode/src/kilocode/server/httpapi/handlers/indexing.ts +++ b/packages/opencode/src/kilocode/server/httpapi/handlers/indexing.ts @@ -1,12 +1,13 @@ import { Effect } from "effect" import { HttpApiBuilder } from "effect/unstable/httpapi" +import { EffectBridge } from "@/effect/bridge" import { InstanceHttpApi } from "@/server/routes/instance/httpapi/api" export const indexingHandlers = HttpApiBuilder.group(InstanceHttpApi, "indexing", (handlers) => Effect.gen(function* () { const status = Effect.fn("IndexingHttpApi.status")(function* () { const mod = yield* Effect.promise(() => import("@/kilocode/indexing")) - const current = yield* Effect.promise(() => mod.KiloIndexing.current()) + const current = yield* EffectBridge.fromPromise(() => mod.KiloIndexing.current()) return current }) diff --git a/packages/opencode/src/kilocode/server/httpapi/handlers/kilo-gateway.ts b/packages/opencode/src/kilocode/server/httpapi/handlers/kilo-gateway.ts index 388cb0b340e..5c979617e1e 100644 --- a/packages/opencode/src/kilocode/server/httpapi/handlers/kilo-gateway.ts +++ b/packages/opencode/src/kilocode/server/httpapi/handlers/kilo-gateway.ts @@ -25,6 +25,7 @@ import * as Stream from "effect/Stream" import { HttpServerRequest, HttpServerResponse } from "effect/unstable/http" import { HttpApiBuilder, HttpApiError } from "effect/unstable/httpapi" import { Auth } from "@/auth" +import { EffectBridge } from "@/effect/bridge" import { Bus } from "@/bus" import { Identifier } from "@/id/id" import { Instance } from "@/project/instance" @@ -279,19 +280,24 @@ export const kiloGatewayHandlers = HttpApiBuilder.group(InstanceHttpApi, "kilo", if (!fetched.ok) return yield* Effect.fail(new HttpApiError.BadRequest({})) if (!fetched.data?.info?.id) return yield* Effect.fail(new HttpApiError.BadRequest({})) - return yield* Effect.try({ + const bridge = yield* EffectBridge.make() + return yield* Effect.tryPromise({ try: () => - importSessionToDb(fetched.data, { - Database, - Instance, - SessionTable, - MessageTable, - PartTable, - SessionToRow: Session.toRow, - Bus, - SessionCreatedEvent: Session.Event.Created, - Identifier, - }), + bridge.promise( + Effect.sync(() => + importSessionToDb(fetched.data, { + Database, + Instance, + SessionTable, + MessageTable, + PartTable, + SessionToRow: Session.toRow, + Bus, + SessionCreatedEvent: Session.Event.Created, + Identifier, + }), + ), + ), catch: () => new HttpApiError.BadRequest({}), }) }) diff --git a/packages/opencode/src/kilocode/server/httpapi/handlers/kilocode.ts b/packages/opencode/src/kilocode/server/httpapi/handlers/kilocode.ts index da4e628152e..c8811b6576e 100644 --- a/packages/opencode/src/kilocode/server/httpapi/handlers/kilocode.ts +++ b/packages/opencode/src/kilocode/server/httpapi/handlers/kilocode.ts @@ -1,6 +1,7 @@ import { Effect } from "effect" import { HttpApiBuilder } from "effect/unstable/httpapi" import { Agent } from "@/agent/agent" +import { EffectBridge } from "@/effect/bridge" import { HeapSnapshot } from "@/kilocode/cli/heap-snapshot" import { InstanceHttpApi } from "@/server/routes/instance/httpapi/api" import { Skill } from "@/skill" @@ -22,7 +23,7 @@ export const kilocodeHandlers = HttpApiBuilder.group(InstanceHttpApi, "kilocode" const removeAgent = Effect.fn("KilocodeHttpApi.removeAgent")(function* (ctx: { payload: typeof RemoveAgentPayload.Type }) { - yield* Effect.promise(() => Agent.remove(ctx.payload.name)) + yield* EffectBridge.fromPromise(() => Agent.remove(ctx.payload.name)) return true }) diff --git a/packages/opencode/src/kilocode/server/httpapi/handlers/network.ts b/packages/opencode/src/kilocode/server/httpapi/handlers/network.ts index 738f610afba..cfcc4af88aa 100644 --- a/packages/opencode/src/kilocode/server/httpapi/handlers/network.ts +++ b/packages/opencode/src/kilocode/server/httpapi/handlers/network.ts @@ -1,5 +1,6 @@ import { Effect } from "effect" import { HttpApiBuilder } from "effect/unstable/httpapi" +import { EffectBridge } from "@/effect/bridge" import { QuestionID } from "@/question/schema" import { SessionNetwork } from "@/session/network" import { InstanceHttpApi } from "@/server/routes/instance/httpapi/api" @@ -7,16 +8,16 @@ import { InstanceHttpApi } from "@/server/routes/instance/httpapi/api" export const networkHandlers = HttpApiBuilder.group(InstanceHttpApi, "network", (handlers) => Effect.gen(function* () { const list = Effect.fn("NetworkHttpApi.list")(function* () { - return yield* Effect.promise(() => SessionNetwork.list()) + return yield* EffectBridge.fromPromise(() => SessionNetwork.list()) }) const reply = Effect.fn("NetworkHttpApi.reply")(function* (ctx: { params: { requestID: QuestionID } }) { - yield* Effect.promise(() => SessionNetwork.reply({ requestID: ctx.params.requestID })) + yield* EffectBridge.fromPromise(() => SessionNetwork.reply({ requestID: ctx.params.requestID })) return true }) const reject = Effect.fn("NetworkHttpApi.reject")(function* (ctx: { params: { requestID: QuestionID } }) { - yield* Effect.promise(() => SessionNetwork.reject({ requestID: ctx.params.requestID })) + yield* EffectBridge.fromPromise(() => SessionNetwork.reject({ requestID: ctx.params.requestID })) return true }) diff --git a/packages/opencode/src/kilocode/server/httpapi/handlers/remote.ts b/packages/opencode/src/kilocode/server/httpapi/handlers/remote.ts index 100026e6f18..6d5765879b2 100644 --- a/packages/opencode/src/kilocode/server/httpapi/handlers/remote.ts +++ b/packages/opencode/src/kilocode/server/httpapi/handlers/remote.ts @@ -1,13 +1,15 @@ import { Effect } from "effect" import { HttpApiBuilder, HttpApiError } from "effect/unstable/httpapi" +import { EffectBridge } from "@/effect/bridge" import { KiloSessions } from "@/kilo-sessions/kilo-sessions" import { InstanceHttpApi } from "@/server/routes/instance/httpapi/api" export const remoteHandlers = HttpApiBuilder.group(InstanceHttpApi, "remote", (handlers) => Effect.gen(function* () { const enable = Effect.fn("RemoteHttpApi.enable")(function* () { + const bridge = yield* EffectBridge.make() yield* Effect.tryPromise({ - try: () => KiloSessions.enableRemote(), + try: () => bridge.promise(Effect.promise(() => KiloSessions.enableRemote())), catch: () => new HttpApiError.Unauthorized(), }) return KiloSessions.remoteStatus() diff --git a/packages/opencode/src/server/routes/instance/httpapi/handlers/experimental.ts b/packages/opencode/src/server/routes/instance/httpapi/handlers/experimental.ts index 419aa7b1687..af18474bc48 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/handlers/experimental.ts +++ b/packages/opencode/src/server/routes/instance/httpapi/handlers/experimental.ts @@ -1,6 +1,7 @@ import { Account } from "@/account/account" import { Agent } from "@/agent/agent" import { Config } from "@/config/config" +import { EffectBridge } from "@/effect/bridge" // kilocode_change import { InstanceState } from "@/effect/instance-state" import { MCP } from "@/mcp" import { Project } from "@/project/project" @@ -128,7 +129,7 @@ export const experimentalHandlers = HttpApiBuilder.group(InstanceHttpApi, "exper // kilocode_change start - worktree diff endpoints for agent manager const base = Effect.fn("ExperimentalHttpApi.worktreeDiffBase")(function* (input: { base?: string }) { if (input.base) return input.base - return yield* Effect.promise(() => Review.getBaseBranch()) + return yield* EffectBridge.fromPromise(() => Review.getBaseBranch()) }) const worktreeDiff = Effect.fn("ExperimentalHttpApi.worktreeDiff")(function* (ctx: { @@ -178,7 +179,7 @@ export const experimentalHandlers = HttpApiBuilder.group(InstanceHttpApi, "exper // kilocode_change start const state = yield* InstanceState.context const projectID = ctx.query.worktrees && !ctx.query.projectID ? state.project.id : ctx.query.projectID - const directories = ctx.query.worktrees ? yield* Effect.promise(() => WorktreeFamily.list()) : undefined + const directories = ctx.query.worktrees ? yield* EffectBridge.fromPromise(() => WorktreeFamily.list()) : undefined const sorted = directories ? [...directories].sort((a, b) => b.length - a.length) : undefined // kilocode_change end const sessions = Array.from( diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index e19074e6d17..1b4b7ea7d25 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -35,8 +35,6 @@ export type Event = | EventInstallationUpdateAvailable | EventFileEdited | EventFileWatcherUpdated - | EventCommandExecuted - | EventProjectUpdated | EventTodoUpdated | EventSessionStatus | EventSessionIdle @@ -44,6 +42,8 @@ export type Event = | EventSuggestionAccepted | EventSuggestionDismissed | EventSessionCompacted + | EventCommandExecuted + | EventProjectUpdated | EventKilocodeAgentManagerStart | EventVcsBranchUpdated | EventWorkspaceReady @@ -328,30 +328,6 @@ export type ApiError = { } } -export type Project = { - id: string - worktree: string - vcs?: "git" - name?: string - icon?: { - url?: string - override?: string - color?: string - } - commands?: { - /** - * Startup script to run when creating a new workspace (worktree) - */ - start?: string - } - time: { - created: number - updated: number - initialized?: number - } - sandboxes: Array -} - export type Todo = { /** * Brief description of the task @@ -408,6 +384,30 @@ export type SuggestionRequest = { } } +export type Project = { + id: string + worktree: string + vcs?: "git" + name?: string + icon?: { + url?: string + override?: string + color?: string + } + commands?: { + /** + * Startup script to run when creating a new workspace (worktree) + */ + start?: string + } + time: { + created: number + updated: number + initialized?: number + } + sandboxes: Array +} + export type Pty = { id: string title: string @@ -880,8 +880,6 @@ export type GlobalEvent = { | EventInstallationUpdateAvailable | EventFileEdited | EventFileWatcherUpdated - | EventCommandExecuted - | EventProjectUpdated | EventTodoUpdated | EventSessionStatus | EventSessionIdle @@ -889,6 +887,8 @@ export type GlobalEvent = { | EventSuggestionAccepted | EventSuggestionDismissed | EventSessionCompacted + | EventCommandExecuted + | EventProjectUpdated | EventKilocodeAgentManagerStart | EventVcsBranchUpdated | EventWorkspaceReady @@ -2687,23 +2687,6 @@ export type EventFileWatcherUpdated = { } } -export type EventCommandExecuted = { - id: string - type: "command.executed" - properties: { - name: string - sessionID: string - arguments: string - messageID: string - } -} - -export type EventProjectUpdated = { - id: string - type: "project.updated" - properties: Project -} - export type EventTodoUpdated = { id: string type: "todo.updated" @@ -2774,6 +2757,23 @@ export type EventSessionCompacted = { } } +export type EventCommandExecuted = { + id: string + type: "command.executed" + properties: { + name: string + sessionID: string + arguments: string + messageID: string + } +} + +export type EventProjectUpdated = { + id: string + type: "project.updated" + properties: Project +} + export type EventKilocodeAgentManagerStart = { id: string type: "kilocode.agent_manager.start"