mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-08-28 19:11:03 +08:00
fix(cli): ignore deleted cost sync
This commit is contained in:
committed by
Imanol Maiztegui
parent
af0227b1ab
commit
2a94a0cc11
@@ -19,6 +19,7 @@ import type { Provider } from "@/provider"
|
||||
import { Question } from "@/question"
|
||||
import { KiloSessionProcessor } from "@/kilocode/session/processor" // kilocode_change
|
||||
import { Suggestion } from "@/kilocode/suggestion" // kilocode_change
|
||||
import { NotFoundError } from "@/storage" // kilocode_change
|
||||
import { errorMessage } from "@/util/error"
|
||||
import { Log } from "@/util"
|
||||
import { isRecord } from "@/util/record"
|
||||
@@ -157,6 +158,22 @@ export const layer: Layer.Layer<
|
||||
return { call, part }
|
||||
})
|
||||
|
||||
// kilocode_change start - tolerate deleted sessions during subagent cost reconciliation (#6321)
|
||||
const reconcile = Effect.fn("SessionProcessor.reconcileCost")(function* () {
|
||||
const fresh = yield* Effect.sync(() => {
|
||||
try {
|
||||
return MessageV2.get({ sessionID: ctx.assistantMessage.sessionID, messageID: ctx.assistantMessage.id })
|
||||
} catch (err) {
|
||||
if (NotFoundError.isInstance(err)) return
|
||||
throw err
|
||||
}
|
||||
})
|
||||
if (fresh?.info.role !== "assistant") return
|
||||
if (fresh.info.cost <= ctx.assistantMessage.cost) return
|
||||
ctx.assistantMessage.cost = fresh.info.cost
|
||||
})
|
||||
// kilocode_change end
|
||||
|
||||
const updateToolCall = Effect.fn("SessionProcessor.updateToolCall")(function* (
|
||||
toolCallID: string,
|
||||
update: (part: MessageV2.ToolPart) => MessageV2.ToolPart,
|
||||
@@ -411,12 +428,7 @@ export const layer: Layer.Layer<
|
||||
// kilocode_change end
|
||||
ctx.assistantMessage.finish = value.finishReason
|
||||
// kilocode_change start - capture any subagent cost propagated by tool calls during this step (#6321)
|
||||
const fresh = yield* Effect.sync(() =>
|
||||
MessageV2.get({ sessionID: ctx.assistantMessage.sessionID, messageID: ctx.assistantMessage.id }),
|
||||
)
|
||||
if (fresh.info.role === "assistant" && fresh.info.cost > ctx.assistantMessage.cost) {
|
||||
ctx.assistantMessage.cost = fresh.info.cost
|
||||
}
|
||||
yield* reconcile()
|
||||
// kilocode_change end
|
||||
ctx.assistantMessage.cost += usage.cost
|
||||
ctx.assistantMessage.tokens = usage.tokens
|
||||
@@ -576,12 +588,7 @@ export const layer: Layer.Layer<
|
||||
KiloSessionProcessor.guardEmptyToolCalls(ctx.assistantMessage, MessageV2.parts(ctx.assistantMessage.id)) // kilocode_change
|
||||
ctx.assistantMessage.time.completed = Date.now()
|
||||
// kilocode_change start - reconcile cost with any subagent propagation written during tool calls (#6321)
|
||||
const fresh = yield* Effect.sync(() =>
|
||||
MessageV2.get({ sessionID: ctx.assistantMessage.sessionID, messageID: ctx.assistantMessage.id }),
|
||||
)
|
||||
if (fresh.info.role === "assistant" && fresh.info.cost > ctx.assistantMessage.cost) {
|
||||
ctx.assistantMessage.cost = fresh.info.cost
|
||||
}
|
||||
yield* reconcile()
|
||||
// kilocode_change end
|
||||
yield* session.updateMessage(ctx.assistantMessage)
|
||||
})
|
||||
|
||||
@@ -183,6 +183,77 @@ describe("session processor empty tool-calls", () => {
|
||||
),
|
||||
)
|
||||
|
||||
it.live("ignores deleted session during cost reconciliation", () =>
|
||||
provideTmpdirInstance(
|
||||
(dir) =>
|
||||
Effect.gen(function* () {
|
||||
const test = yield* TestLLM
|
||||
const processors = yield* SessionProcessor.Service
|
||||
const session = yield* Session.Service
|
||||
|
||||
yield* test.reply(
|
||||
{ type: "start" },
|
||||
{ type: "start-step" } as LLM.Event,
|
||||
{
|
||||
type: "finish-step",
|
||||
finishReason: "stop",
|
||||
usage: usage(),
|
||||
providerMetadata: undefined,
|
||||
} as LLM.Event,
|
||||
{ type: "finish" } as LLM.Event,
|
||||
)
|
||||
|
||||
const chat = yield* session.create({})
|
||||
const parent = yield* session.updateMessage({
|
||||
id: MessageID.ascending(),
|
||||
role: "user",
|
||||
sessionID: chat.id,
|
||||
agent: "code",
|
||||
model: ref,
|
||||
time: { created: Date.now() },
|
||||
})
|
||||
const msg: MessageV2.Assistant = {
|
||||
id: MessageID.ascending(),
|
||||
role: "assistant",
|
||||
sessionID: chat.id,
|
||||
parentID: parent.id,
|
||||
mode: "code",
|
||||
agent: "code",
|
||||
path: { cwd: path.resolve(dir), root: path.resolve(dir) },
|
||||
cost: 0,
|
||||
tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
|
||||
modelID: ref.modelID,
|
||||
providerID: ref.providerID,
|
||||
time: { created: Date.now() },
|
||||
}
|
||||
yield* session.updateMessage(msg)
|
||||
|
||||
const mdl = model()
|
||||
const handle = yield* processors.create({
|
||||
assistantMessage: msg,
|
||||
sessionID: chat.id,
|
||||
model: mdl,
|
||||
})
|
||||
yield* session.remove(chat.id)
|
||||
|
||||
const input: LLM.StreamInput = {
|
||||
user: parent as MessageV2.User,
|
||||
sessionID: chat.id,
|
||||
model: mdl,
|
||||
agent: { name: "code", mode: "primary", permission: [], options: {} } as any,
|
||||
system: [],
|
||||
messages: [],
|
||||
tools: {},
|
||||
}
|
||||
|
||||
const result = yield* handle.process(input)
|
||||
expect(result).toBe("continue")
|
||||
expect(handle.message.error).toBeUndefined()
|
||||
}),
|
||||
{ git: true },
|
||||
),
|
||||
)
|
||||
|
||||
it.live("preserves tool-calls finish when tool parts exist", () =>
|
||||
provideTmpdirInstance(
|
||||
(dir) =>
|
||||
|
||||
Reference in New Issue
Block a user