Merge pull request #9844 from Kilo-Org/track-code-reviews

fix(cli): track local reviews
This commit is contained in:
Marian Alexandru Alecu
2026-05-05 16:38:43 +03:00
committed by GitHub
4 changed files with 51 additions and 1 deletions
+3
View File
@@ -154,6 +154,9 @@ export namespace Telemetry {
// LLM
export function trackLlmCompletion(properties: {
taskId?: string
mode?: "review"
feature?: "code_reviews"
command?: "local-review" | "local-review-uncommitted"
apiProvider: string
modelId: string
inputTokens?: number
@@ -8,12 +8,37 @@ import * as Log from "@opencode-ai/core/util/log"
import { Effect } from "effect"
import { Flag } from "@opencode-ai/core/flag/flag"
export type ReviewTelemetry = {
mode: "review"
feature: "code_reviews"
command: "local-review" | "local-review-uncommitted"
}
export namespace KiloSessionProcessor {
const log = Log.create({ service: "session.processor.kilo" })
export const OUTPUT_LENGTH_WARNING = "The model hit its output limit, so this response may be incomplete."
export const REASONING_LENGTH_WARNING =
"The model hit its output limit while reasoning and produced no actionable output. Try disabling reasoning or increasing the output limit."
export function reviewTelemetry(command: string): ReviewTelemetry | undefined {
if (command === "local-review" || command === "local-review-uncommitted") {
return { mode: "review", feature: "code_reviews", command }
}
}
export function extractReviewTelemetry(parts: MessageV2.Part[]): ReviewTelemetry | undefined {
for (const part of parts) {
if (part.type !== "text") continue
const meta: Record<string, unknown> | undefined = part.metadata
if (!meta) continue
if (meta.mode !== "review") continue
if (meta.feature !== "code_reviews") continue
const command = meta.command
if (command !== "local-review" && command !== "local-review-uncommitted") continue
return { mode: "review", feature: "code_reviews", command }
}
}
/**
* Track LLM completion telemetry for a finished step.
* Only fires if at least one token bucket is non-zero.
@@ -24,11 +49,13 @@ export namespace KiloSessionProcessor {
tokens: { input: number; output: number; cache: { read: number; write: number } }
cost: number
elapsed: number
telemetry?: ReviewTelemetry
}) {
const { tokens } = input
if (tokens.input > 0 || tokens.output > 0 || tokens.cache.write > 0 || tokens.cache.read > 0) {
Telemetry.trackLlmCompletion({
taskId: input.sessionID,
...(input.telemetry ?? {}),
apiProvider: input.model.providerID,
modelId: input.model.id,
inputTokens: tokens.input,
+4 -1
View File
@@ -17,7 +17,7 @@ import { SessionStatus } from "./status"
import { SessionSummary } from "./summary"
import type { Provider } from "@/provider/provider"
import { Question } from "@/question"
import { KiloSessionProcessor } from "@/kilocode/session/processor" // kilocode_change
import { KiloSessionProcessor, type ReviewTelemetry } from "@/kilocode/session/processor" // kilocode_change
import { Suggestion } from "@/kilocode/suggestion" // kilocode_change
import { NotFoundError } from "@/storage/storage" // kilocode_change
import { errorMessage } from "@/util/error"
@@ -53,6 +53,7 @@ type Input = {
assistantMessage: MessageV2.Assistant
sessionID: SessionID
model: Provider.Model
telemetry?: ReviewTelemetry // kilocode_change
}
export interface Interface {
@@ -131,6 +132,7 @@ export const layer: Layer.Layer<
needsCompaction: false,
currentText: undefined,
reasoningMap: {},
telemetry: input.telemetry, // kilocode_change
stepStart: 0, // kilocode_change
step: { reasoning: false, text: false, tool: false }, // kilocode_change
}
@@ -440,6 +442,7 @@ export const layer: Layer.Layer<
tokens: usage.tokens,
cost: usage.cost,
elapsed: Math.round(performance.now() - (ctx.stepStart || performance.now())),
telemetry: ctx.telemetry,
})
// kilocode_change end
ctx.assistantMessage.finish = value.finishReason
+17
View File
@@ -5,6 +5,7 @@ import { KiloSessionPrompt } from "@/kilocode/session/prompt" // kilocode_change
import { KiloSessionPromptQueue } from "@/kilocode/session/prompt-queue" // kilocode_change
import { KiloSession } from "@/kilocode/session" // kilocode_change
import { KiloCostPropagation } from "@/kilocode/session/cost-propagation" // kilocode_change
import { KiloSessionProcessor } from "@/kilocode/session/processor" // kilocode_change
import { Suggestion } from "@/kilocode/suggestion" // kilocode_change
import { Question } from "@/question" // kilocode_change
import z from "zod"
@@ -1374,6 +1375,12 @@ NOTE: At any point in time through this workflow you should feel free to ask the
if (!lastUser) throw new Error("No user message found in stream. This should never happen.")
// kilocode_change start - carry local review command marker into LLM telemetry
const telemetry = KiloSessionProcessor.extractReviewTelemetry(
msgs.findLast((m) => m.info.role === "user" && m.info.id === lastUser.id)?.parts ?? [],
)
// kilocode_change end
const lastAssistantMsg = msgs.findLast(
(msg) => msg.info.role === "assistant" && msg.info.id === lastAssistant?.id,
)
@@ -1512,6 +1519,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
assistantMessage: msg,
sessionID,
model,
telemetry, // kilocode_change
})
const outcome: "break" | "continue" = yield* Effect.gen(function* () {
@@ -1762,6 +1770,15 @@ NOTE: At any point in time through this workflow you should feel free to ask the
}
const templateParts = yield* resolvePromptParts(template)
// kilocode_change start - mark local review commands for completion telemetry
const telemetry = KiloSessionProcessor.reviewTelemetry(input.command)
if (telemetry) {
for (const part of templateParts) {
if (part.type !== "text") continue
part.metadata = { ...part.metadata, ...telemetry }
}
}
// kilocode_change end
const isSubtask = (agent.mode === "subagent" && cmd.subtask !== false) || cmd.subtask === true
const parts = isSubtask
? [