refactor: resolve comments

This commit is contained in:
Catriel Müller
2026-05-18 11:45:36 -03:00
parent ad8d57707d
commit 2aa1b95074
24 changed files with 359 additions and 118 deletions
@@ -150,7 +150,9 @@ export async function handle(args: ArgumentsCamelCase) {
const structured = json || args.output === "md"
if (!args.quiet && !structured) {
UI.println(`${color(UI.Style.TEXT_INFO)}Starting roll call for models with prompt: "${args.prompt}"${color(UI.Style.TEXT_NORMAL)}`)
UI.println(
`${color(UI.Style.TEXT_INFO)}Starting roll call for models with prompt: "${args.prompt}"${color(UI.Style.TEXT_NORMAL)}`,
)
UI.println(
`${color(UI.Style.TEXT_INFO)}Timeout per model: ${args.timeout}ms, Parallel calls: ${args.parallel}${color(UI.Style.TEXT_NORMAL)}`,
)
@@ -178,7 +180,8 @@ export async function handle(args: ArgumentsCamelCase) {
)
if (models.length === 0) {
if (!args.quiet && !structured) UI.println(`${color(UI.Style.TEXT_WARNING)}No models to test after filtering.${color(UI.Style.TEXT_NORMAL)}`)
if (!args.quiet && !structured)
UI.println(`${color(UI.Style.TEXT_WARNING)}No models to test after filtering.${color(UI.Style.TEXT_NORMAL)}`)
if (json) console.log(JSON.stringify([], null, 2))
if (args.output === "md") console.log(formatMarkdown([]))
if (structured) return
@@ -262,7 +265,12 @@ export async function handle(args: ArgumentsCamelCase) {
})
}
async function call(model: Provider.Model, prompt: string, timeout: number, start: number): Promise<Omit<Result, "model">> {
async function call(
model: Provider.Model,
prompt: string,
timeout: number,
start: number,
): Promise<Omit<Result, "model">> {
try {
const language = await Provider.getLanguage(model)
const sessionID = randomUUID()
@@ -305,7 +313,10 @@ async function call(model: Provider.Model, prompt: string, timeout: number, star
}
function error(cause: unknown) {
if (cause instanceof Error && (cause.name === "AbortError" || cause.message.includes("abort") || cause.message.includes("timeout"))) {
if (
cause instanceof Error &&
(cause.name === "AbortError" || cause.message.includes("abort") || cause.message.includes("timeout"))
) {
return { type: "timeout", message: "The operation timed out." }
}
@@ -59,10 +59,7 @@ export function ModelInfoPanel(props: Props) {
gap={1}
flexShrink={0}
>
<scrollbox
maxHeight={maxHeight()}
paddingRight={1}
>
<scrollbox maxHeight={maxHeight()} paddingRight={1}>
<box>
<text fg={theme.text} attributes={TextAttributes.BOLD}>
{m().name ?? m().id ?? "Model"}
@@ -141,7 +138,7 @@ export function ModelInfoPanel(props: Props) {
</box>
</Show>
<Show when={desc()}>
<text fg={theme.textMuted}>{" "}</text>
<text fg={theme.textMuted}> </text>
<text fg={theme.textMuted} width={23}>
{desc()}
</text>
@@ -64,7 +64,10 @@ export namespace KiloCompactionChunks {
export function needed(input: { cfg: Config.Info; model: Provider.Model; tokens: number }) {
// Apply 1.3x multiplier to token estimate to compensate for Token.estimate
// under-counting actual provider tokenizer counts by ~15-30%.
return Math.ceil(input.tokens * 1.3) + model(input.model).limit.output > usable({ cfg: input.cfg, model: model(input.model) })
return (
Math.ceil(input.tokens * 1.3) + model(input.model).limit.output >
usable({ cfg: input.cfg, model: model(input.model) })
)
}
export function replay(input: Input & { replay: Replay }) {
@@ -161,10 +164,12 @@ export namespace KiloCompactionChunks {
function part(part: MessageV2.Part) {
if (part.type === "text") return clip({ text: part.text, chars: TRANSCRIPT_MAX_CHARS, label: "Text" })
if (part.type === "reasoning") return `[Reasoning]: ${clip({ text: part.text, chars: TRANSCRIPT_MAX_CHARS, label: "Reasoning" })}`
if (part.type === "reasoning")
return `[Reasoning]: ${clip({ text: part.text, chars: TRANSCRIPT_MAX_CHARS, label: "Reasoning" })}`
if (part.type === "file") return `[File attachment]: ${part.filename ?? part.url} (${part.mime})`
if (part.type === "agent") return `[Agent]: ${part.name}`
if (part.type === "subtask") return `[Subtask ${part.agent}]: ${part.description}\n${clip({ text: part.prompt, chars: TRANSCRIPT_MAX_CHARS, label: "Subtask prompt" })}`
if (part.type === "subtask")
return `[Subtask ${part.agent}]: ${part.description}\n${clip({ text: part.prompt, chars: TRANSCRIPT_MAX_CHARS, label: "Subtask prompt" })}`
if (part.type === "tool") {
const head = `[Tool ${part.tool} ${part.state.status}]`
if (part.state.status === "completed") {
@@ -174,7 +179,8 @@ export namespace KiloCompactionChunks {
`output: ${clip({ text: part.state.output, chars: TOOL_OUTPUT_MAX_CHARS, label: "Tool output" })}`,
].join("\n")
}
if (part.state.status === "error") return `${head}\n${clip({ text: part.state.error, chars: TOOL_OUTPUT_MAX_CHARS, label: "Tool error" })}`
if (part.state.status === "error")
return `${head}\n${clip({ text: part.state.error, chars: TOOL_OUTPUT_MAX_CHARS, label: "Tool error" })}`
return `${head}\ninput: ${clip({ text: JSON.stringify(part.state.input), chars: TOOL_OUTPUT_MAX_CHARS, label: "Tool input" })}`
}
if (part.type === "step-finish") return `[Step finished]: ${part.reason}`
@@ -185,11 +191,12 @@ export namespace KiloCompactionChunks {
function transcript(input: { messages: MessageV2.WithParts[] }) {
return input.messages
.map((msg, index) => {
const body = msg.parts
.map(part)
.filter(Boolean)
.join("\n\n")
return [`<message index=\"${index + 1}\" role=\"${msg.info.role}\">`, body || "[no content]", "</message>"].join("\n")
const body = msg.parts.map(part).filter(Boolean).join("\n\n")
return [
`<message index=\"${index + 1}\" role=\"${msg.info.role}\">`,
body || "[no content]",
"</message>",
].join("\n")
})
.join("\n\n")
}
@@ -239,10 +246,7 @@ export namespace KiloCompactionChunks {
...input.agent,
options: {
...opts,
maxOutputTokens: Math.min(
OUTPUT,
typeof opts?.maxOutputTokens === "number" ? opts.maxOutputTokens : OUTPUT,
),
maxOutputTokens: Math.min(OUTPUT, typeof opts?.maxOutputTokens === "number" ? opts.maxOutputTokens : OUTPUT),
},
}
const out = yield* Effect.gen(function* () {
@@ -325,16 +329,15 @@ export namespace KiloCompactionChunks {
const chunks = yield* split({ messages: input.messages, model: input.model, size })
log.info("fallback", { chunks: chunks.length, concurrency: CONCURRENCY })
const partial = yield* Effect.forEach(
chunks,
(chunk) => summarize({ ...input, chunk, total: chunks.length }),
{ concurrency: Math.min(CONCURRENCY, chunks.length) },
)
const partial = yield* Effect.forEach(chunks, (chunk) => summarize({ ...input, chunk, total: chunks.length }), {
concurrency: Math.min(CONCURRENCY, chunks.length),
})
if (partial.some((item) => item.result !== "continue" || !item.output)) return "compact" as const
const final = chunks.length === 1 && (yield* large({ messages: chunks[0].messages, model: input.model, size }))
? partial[0]
: yield* reduce({ ...input, summaries: partial.map((item) => item.output!), depth: 0 })
const final =
chunks.length === 1 && (yield* large({ messages: chunks[0].messages, model: input.model, size }))
? partial[0]
: yield* reduce({ ...input, summaries: partial.map((item) => item.output!), depth: 0 })
if (!final || final.result !== "continue" || !final.output) return "compact" as const
yield* input.updatePart({
+7 -1
View File
@@ -440,7 +440,13 @@ export async function CodexAuthPlugin(input: PluginInput): Promise<Hooks> {
if (!currentAuth.access || currentAuth.expires < Date.now()) {
log.info("refreshing codex access token")
// kilocode_change start
await refreshCodexAuth({ input, getAuth, auth: currentAuth, refresh: refreshAccessToken, account: extractAccountId })
await refreshCodexAuth({
input,
getAuth,
auth: currentAuth,
refresh: refreshAccessToken,
account: extractAccountId,
})
// kilocode_change end
}
+3 -10
View File
@@ -46,16 +46,9 @@ export const layer = Layer.effect(
yield* plugin.init()
yield* Effect.promise(() => KilocodeBootstrap.init()).pipe(Effect.forkDetach) // kilocode_change
// kilocode_change start - shareNext removed from list, handled by KilocodeBootstrap
yield* Effect.all(
[
lsp,
format,
file,
fileWatcher,
vcs,
snapshot,
].map((s) => Effect.forkDetach(s.init())),
).pipe(Effect.withSpan("InstanceBootstrap.init"))
yield* Effect.all([lsp, format, file, fileWatcher, vcs, snapshot].map((s) => Effect.forkDetach(s.init()))).pipe(
Effect.withSpan("InstanceBootstrap.init"),
)
// kilocode_change end
const projectID = ctx.project.id
+8 -2
View File
@@ -302,7 +302,10 @@ export const layer: Layer.Layer<
// goes backwards through parts until there are PRUNE_PROTECT tokens worth of tool
// calls, then erases output of older tool calls to free context space
// kilocode_change start - preserve normal opt-in pruning, but allow payload/compaction cleanup by default
const prune = Effect.fn("SessionCompaction.prune")(function* (input: { sessionID: SessionID; reason?: PruneReason }) {
const prune = Effect.fn("SessionCompaction.prune")(function* (input: {
sessionID: SessionID
reason?: PruneReason
}) {
const cfg = yield* config.get()
const reason = input.reason ?? "normal"
if (cfg.compaction?.prune === false) return
@@ -469,7 +472,10 @@ export const layer: Layer.Layer<
// kilocode_change end
// kilocode_change start - fallback to chunked compaction when the first summary overflows
const fallback = KiloCompactionChunks.eligible({ result, error: processor.message.error ?? processor.compactError?.() })
const fallback = KiloCompactionChunks.eligible({
result,
error: processor.message.error ?? processor.compactError?.(),
})
? yield* KiloCompactionChunks.process({
processors,
session,
-1
View File
@@ -239,7 +239,6 @@ function preview(text: string) {
return "...\n\n" + text.slice(-MAX_METADATA_LENGTH)
}
function tail(text: string, maxLines: number, maxBytes: number) {
const lines = text.split("\n")
if (lines.length <= maxLines && Buffer.byteLength(text, "utf-8") <= maxBytes) {
@@ -38,7 +38,8 @@ describe("Codex auth refresh", () => {
name: "ProviderAuthError",
data: {
providerID: "openai",
message: "Your ChatGPT sign-in expired or was revoked. Sign in with ChatGPT again to continue using Codex models.",
message:
"Your ChatGPT sign-in expired or was revoked. Sign in with ChatGPT again to continue using Codex models.",
},
})
})
@@ -342,25 +342,24 @@ describe("Encoding.read / Encoding.readSync / Encoding.write", () => {
})
})
describe("Encoding.write with existing parent directories", () => {
test("creates parent and writes file", async () => {
await tmp(async (dir) => {
const filepath = path.join(dir, "subdir", "test.txt");
await Encoding.write(filepath, "hello");
const text = await fs.readFile(filepath, "utf8");
expect(text).toBe("hello");
});
});
const filepath = path.join(dir, "subdir", "test.txt")
await Encoding.write(filepath, "hello")
const text = await fs.readFile(filepath, "utf8")
expect(text).toBe("hello")
})
})
test("writes into existing directory (Windows EEXIST resiliency)", async () => {
await tmp(async (dir) => {
const existing = path.join(dir, "exists");
await fs.mkdir(existing, { recursive: true });
const filepath = path.join(existing, "test.txt");
await Encoding.write(filepath, "hello");
const text = await fs.readFile(filepath, "utf8");
expect(text).toBe("hello");
});
});
});
const existing = path.join(dir, "exists")
await fs.mkdir(existing, { recursive: true })
const filepath = path.join(existing, "test.txt")
await Encoding.write(filepath, "hello")
const text = await fs.readFile(filepath, "utf8")
expect(text).toBe("hello")
})
})
})
@@ -45,7 +45,12 @@ test("failedProviders returns empty array when no fetch has occurred", () => {
test("getFailure returns undefined when fetch succeeds", async () => {
stubbedResult = {
models: {
"test/model": { id: "test/model", name: "Test", cost: { input: 1, output: 2 }, limit: { context: 128000, output: 4096 } },
"test/model": {
id: "test/model",
name: "Test",
cost: { input: 1, output: 2 },
limit: { context: 128000, output: 4096 },
},
},
}
ModelCache.clear("kilo")
@@ -81,7 +86,12 @@ test("failure state is cleared when subsequent fetch succeeds", async () => {
stubbedResult = {
models: {
"test/model": { id: "test/model", name: "Test", cost: { input: 1, output: 2 }, limit: { context: 128000, output: 4096 } },
"test/model": {
id: "test/model",
name: "Test",
cost: { input: 1, output: 2 },
limit: { context: 128000, output: 4096 },
},
},
}
ModelCache.clear("kilo")
@@ -209,7 +209,11 @@ function runtime(layer: Layer.Layer<LLM.Service>, context = 7_000) {
Layer.provide(Plugin.defaultLayer),
Layer.provide(status),
Layer.provide(bus),
Layer.provide(Layer.mock(Config.Service)({ get: () => Effect.succeed({ ...Config.Info.zod.parse({}), compaction: { reserved: 1_000 } }) })),
Layer.provide(
Layer.mock(Config.Service)({
get: () => Effect.succeed({ ...Config.Info.zod.parse({}), compaction: { reserved: 1_000 } }),
}),
),
),
)
}
@@ -234,7 +238,9 @@ function fakeRuntime() {
Effect.gen(function* () {
outputs.push(input.model.limit.output)
calls.push(JSON.stringify(stream.messages))
const text = stream.messages.some((msg) => JSON.stringify(msg).includes("Create a new anchored summary"))
const text = stream.messages.some((msg) =>
JSON.stringify(msg).includes("Create a new anchored summary"),
)
? "final summary"
: calls.length === 1
? "chunk one"
@@ -332,7 +338,9 @@ describe("KiloCompactionChunks", () => {
const chunks = await Effect.runPromise(KiloCompactionChunks.split({ messages, model, size: 2_000 }))
expect(chunks.length).toBeGreaterThan(1)
expect(chunks.flatMap((chunk) => chunk.messages.map((msg) => msg.info.id))).toEqual(messages.map((msg) => msg.info.id))
expect(chunks.flatMap((chunk) => chunk.messages.map((msg) => msg.info.id))).toEqual(
messages.map((msg) => msg.info.id),
)
})
test("falls back to chunk workers after the first compaction overflows", async () => {
@@ -365,7 +373,9 @@ describe("KiloCompactionChunks", () => {
const all = await svc.messages({ sessionID: session.id })
const summaries = all.filter((msg) => msg.info.role === "assistant" && msg.info.summary)
const parts = summaries.flatMap((msg) => msg.parts).filter((part): part is MessageV2.TextPart => part.type === "text")
const parts = summaries
.flatMap((msg) => msg.parts)
.filter((part): part is MessageV2.TextPart => part.type === "text")
expect(result).toBe("continue")
expect(calls.length).toBeGreaterThanOrEqual(1)
@@ -445,7 +455,9 @@ describe("KiloCompactionChunks", () => {
const all = await svc.messages({ sessionID: session.id })
const summaries = all.filter((msg) => msg.info.role === "assistant" && msg.info.summary)
const parts = summaries.flatMap((msg) => msg.parts).filter((part): part is MessageV2.TextPart => part.type === "text")
const parts = summaries
.flatMap((msg) => msg.parts)
.filter((part): part is MessageV2.TextPart => part.type === "text")
expect(result).toBe("continue")
expect(calls.length).toBeGreaterThan(0)
@@ -545,7 +557,13 @@ describe("KiloCompactionChunks", () => {
const old = await user(session.id, "old context")
await assistant(session.id, old.id, tmp.path, "old reply")
const large = await user(session.id, "large replay " + "x".repeat(40_000))
await SessionCompaction.create({ sessionID: session.id, agent: "build", model: ref, auto: true, overflow: true })
await SessionCompaction.create({
sessionID: session.id,
agent: "build",
model: ref,
auto: true,
overflow: true,
})
const rt = liveRuntime(stub.layer)
try {
@@ -58,11 +58,7 @@ describe("instruction markdown substitutions", () => {
yield* write(path.join(dir, "subdir", "nested", "file.ts"), "const value = 1")
const svc = yield* Instruction.Service
const results = yield* svc.resolve(
[],
path.join(dir, "subdir", "nested", "file.ts"),
MessageID.ascending(),
)
const results = yield* svc.resolve([], path.join(dir, "subdir", "nested", "file.ts"), MessageID.ascending())
expect(results).toHaveLength(1)
expect(results[0].content).toContain("file content")
@@ -68,9 +68,7 @@ describe("normalizeUrls", () => {
})
test("comma after URL in a list is not consumed", () => {
expect(normalizeUrls("check https://example.com, then continue")).toBe(
"check https://example.com, then continue",
)
expect(normalizeUrls("check https://example.com, then continue")).toBe("check https://example.com, then continue")
})
test("closing parenthesis after URL is not consumed", () => {