fix: Regenerage sdk and port tests to new v1.4.4 style

This commit is contained in:
Johnny Amancio
2026-04-17 12:47:27 +02:00
parent 8bff3718aa
commit 3c7b0a7d3c
6 changed files with 91 additions and 60 deletions
@@ -1,7 +1,6 @@
import { Bus } from "../../bus"
import { BusEvent } from "../../bus/bus-event"
import { Identifier } from "../../id/id"
import { Instance } from "../../project/instance"
import { Log } from "../../util/log"
import z from "zod"
@@ -73,20 +72,16 @@ export namespace Suggestion {
),
}
const state = Instance.state(async () => {
const pending: Record<
string,
{
info: Request
resolve: (action: Action) => void
reject: (error: any) => void
}
> = {}
return {
pending,
// kilocode_change - Instance.state() removed in v1.4.4; use module-level state
// (request IDs are globally unique so instance scoping is not needed)
const pending: Record<
string,
{
info: Request
resolve: (action: Action) => void
reject: (error: any) => void
}
})
> = {}
export async function show(input: {
sessionID: string
@@ -95,7 +90,7 @@ export namespace Suggestion {
blocking?: boolean
tool?: { messageID: string; callID: string }
}): Promise<Action> {
const s = await state()
const s = { pending }
const id = Identifier.ascending("suggestion")
log.info("shown", { id, actions: input.actions.length })
@@ -119,7 +114,7 @@ export namespace Suggestion {
}
export async function accept(input: { requestID: string; index: number }): Promise<boolean> {
const s = await state()
const s = { pending }
const existing = s.pending[input.requestID]
if (!existing) {
log.warn("accept for unknown request", { requestID: input.requestID })
@@ -150,7 +145,7 @@ export namespace Suggestion {
}
export async function dismiss(requestID: string): Promise<boolean> {
const s = await state()
const s = { pending }
const existing = s.pending[requestID]
if (!existing) {
log.warn("dismiss for unknown request", { requestID })
@@ -176,7 +171,7 @@ export namespace Suggestion {
}
export async function dismissAll(sessionID: string): Promise<void> {
const s = await state()
const s = { pending }
for (const [id, entry] of Object.entries(s.pending)) {
if (entry.info.sessionID !== sessionID) continue
delete s.pending[id]
@@ -190,6 +185,6 @@ export namespace Suggestion {
}
export async function list() {
return state().then((state) => Object.values(state.pending).map((item) => item.info))
return Object.values(pending).map((item) => item.info)
}
}
+6
View File
@@ -23,6 +23,7 @@ import { ProviderID, type ModelID } from "../provider/schema"
import { WebSearchTool } from "./websearch"
import { CodeSearchTool } from "./codesearch"
import { KiloToolRegistry } from "../kilocode/tool/registry" // kilocode_change
import { makeRuntime } from "@/effect/run-service" // kilocode_change
import { Flag } from "@/flag/flag"
import { Log } from "@/util/log"
import { LspTool } from "./lsp"
@@ -334,4 +335,9 @@ export namespace ToolRegistry {
Layer.provide(Truncate.defaultLayer),
),
)
// kilocode_change start
const { runPromise } = makeRuntime(Service, defaultLayer)
export const ids = () => runPromise((svc) => svc.ids())
// kilocode_change end
}
@@ -8,6 +8,7 @@ import { AppFileSystem } from "../../src/filesystem"
import { FileTime } from "../../src/file/time"
import { LSP } from "../../src/lsp"
import { Instruction } from "../../src/session/instruction"
import { Truncate } from "../../src/tool/truncate"
import { MessageID, SessionID } from "../../src/session/schema"
import { ReadTool } from "../../src/tool/read"
import { Tool } from "../../src/tool/tool"
@@ -22,7 +23,7 @@ const baseCtx = {
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
ask: async () => {},
ask: () => Effect.void,
}
const expandCtx = { ...baseCtx, extra: { includeDirectoryFiles: true } }
@@ -35,12 +36,13 @@ const it = testEffect(
FileTime.defaultLayer,
Instruction.defaultLayer,
LSP.defaultLayer,
Truncate.defaultLayer,
),
)
const init = Effect.fn("ReadDirectoryTest.init")(function* () {
const info = yield* ReadTool
return yield* Effect.promise(() => info.init())
return yield* Tool.init(info)
})
const run = Effect.fn("ReadDirectoryTest.run")(function* (
@@ -48,7 +50,7 @@ const run = Effect.fn("ReadDirectoryTest.run")(function* (
ctx = expandCtx,
) {
const tool = yield* init()
return yield* Effect.promise(() => tool.execute(args, ctx))
return yield* tool.execute(args, ctx as any)
})
const exec = Effect.fn("ReadDirectoryTest.exec")(function* (
@@ -1,7 +1,22 @@
import { afterEach, beforeEach, describe, expect, test, spyOn } from "bun:test"
import { Effect, Layer, ManagedRuntime } from "effect"
import { Command } from "../../../src/command"
import { Suggestion } from "../../../src/kilocode/suggestion"
import { SuggestTool } from "../../../src/kilocode/suggestion/tool"
import { Tool } from "../../../src/tool/tool"
import { Truncate } from "../../../src/tool/truncate"
import { Agent } from "../../../src/agent/agent"
const toolRuntime = ManagedRuntime.make(Layer.mergeAll(Truncate.defaultLayer, Agent.defaultLayer))
async function initTool() {
return toolRuntime.runPromise(
Effect.gen(function* () {
const info = yield* SuggestTool
return yield* Tool.init(info)
}),
)
}
const ctx = {
sessionID: "ses_test",
@@ -23,7 +38,7 @@ const ctx = {
},
],
metadata: () => {},
ask: async () => {},
ask: () => Effect.void,
}
describe("tool.suggest", () => {
@@ -41,15 +56,17 @@ describe("tool.suggest", () => {
})
test("returns dismissal result when suggestion is dismissed", async () => {
const tool = await SuggestTool.init()
const tool = await initTool()
show.mockRejectedValueOnce(new Suggestion.DismissedError())
const result = await tool.execute(
{
suggest: "Run review?",
actions: [{ label: "Start", prompt: "/local-review-uncommitted" }],
},
ctx as any,
const result = await toolRuntime.runPromise(
tool.execute(
{
suggest: "Run review?",
actions: [{ label: "Start", prompt: "/local-review-uncommitted" }],
},
ctx as any,
),
)
expect(result.title).toBe("Suggestion dismissed")
@@ -58,7 +75,7 @@ describe("tool.suggest", () => {
})
test("resolves command template for slash-command action prompt", async () => {
const tool = await SuggestTool.init()
const tool = await initTool()
show.mockResolvedValueOnce({
label: "Start review",
description: "Run a local review now",
@@ -71,12 +88,14 @@ describe("tool.suggest", () => {
hints: [],
})
const result = await tool.execute(
{
suggest: "Run review?",
actions: [{ label: "Start review", prompt: "/local-review-uncommitted" }],
},
ctx as any,
const result = await toolRuntime.runPromise(
tool.execute(
{
suggest: "Run review?",
actions: [{ label: "Start review", prompt: "/local-review-uncommitted" }],
},
ctx as any,
),
)
expect(result.title).toBe("User accepted: Start review")
@@ -92,18 +111,20 @@ describe("tool.suggest", () => {
})
test("returns plain-text prompt directly for non-command actions", async () => {
const tool = await SuggestTool.init()
const tool = await initTool()
show.mockResolvedValueOnce({
label: "Run tests",
prompt: "Run the test suite and fix any failures",
})
const result = await tool.execute(
{
suggest: "Tests might need running",
actions: [{ label: "Run tests", prompt: "Run the test suite and fix any failures" }],
},
ctx as any,
const result = await toolRuntime.runPromise(
tool.execute(
{
suggest: "Tests might need running",
actions: [{ label: "Run tests", prompt: "Run the test suite and fix any failures" }],
},
ctx as any,
),
)
expect(result.title).toBe("User accepted: Run tests")
@@ -114,19 +135,21 @@ describe("tool.suggest", () => {
})
test("falls back to raw prompt when command is not found", async () => {
const tool = await SuggestTool.init()
const tool = await initTool()
show.mockResolvedValueOnce({
label: "Unknown cmd",
prompt: "/nonexistent-command",
})
cmdGet.mockResolvedValueOnce(undefined)
const result = await tool.execute(
{
suggest: "Try this?",
actions: [{ label: "Unknown cmd", prompt: "/nonexistent-command" }],
},
ctx as any,
const result = await toolRuntime.runPromise(
tool.execute(
{
suggest: "Try this?",
actions: [{ label: "Unknown cmd", prompt: "/nonexistent-command" }],
},
ctx as any,
),
)
expect(result.title).toBe("User accepted: Unknown cmd")
@@ -135,7 +158,7 @@ describe("tool.suggest", () => {
})
test("falls back to raw prompt when template resolution fails", async () => {
const tool = await SuggestTool.init()
const tool = await initTool()
show.mockResolvedValueOnce({
label: "Start review",
prompt: "/local-review-uncommitted",
@@ -147,12 +170,14 @@ describe("tool.suggest", () => {
hints: [],
})
const result = await tool.execute(
{
suggest: "Run review?",
actions: [{ label: "Start review", prompt: "/local-review-uncommitted" }],
},
ctx as any,
const result = await toolRuntime.runPromise(
tool.execute(
{
suggest: "Run review?",
actions: [{ label: "Start review", prompt: "/local-review-uncommitted" }],
},
ctx as any,
),
)
expect(result.title).toBe("User accepted: Start review")
+2 -2
View File
@@ -1,11 +1,11 @@
import { afterEach, describe, expect } from "bun:test"
import { afterEach, describe, expect, test } from "bun:test"
import path from "path"
import fs from "fs/promises"
import { Effect, Layer } from "effect"
import { Instance } from "../../src/project/instance"
import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner"
import { ToolRegistry } from "../../src/tool/registry"
import { provideTmpdirInstance } from "../fixture/fixture"
import { provideTmpdirInstance, tmpdir } from "../fixture/fixture"
import { testEffect } from "../lib/effect"
const node = CrossSpawnSpawner.defaultLayer
+3
View File
@@ -1286,6 +1286,9 @@ export type GlobalEvent = {
| EventTodoUpdated
| EventSessionStatus
| EventSessionIdle
| EventSuggestionShown
| EventSuggestionAccepted
| EventSuggestionDismissed
| EventSessionCompacted
| EventCommandExecuted
| EventVcsBranchUpdated