mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-24 16:02:55 +08:00
refactor: move dynamic editor context from system prompt to user message
Split editor context into static and dynamic parts: - Static (system prompt, cached): date, timezone, shell These rarely change and benefit from prompt caching. - Dynamic (user message, per-turn): active file, visible files, open tabs These change frequently as the user switches files/tabs. Injected as a synthetic <environment_details> block on each user message so the model always has fresh context. This matches the pattern used by the VS Code extension, where getEnvironmentDetails() is called before every agent turn.
This commit is contained in:
@@ -6,36 +6,50 @@ export interface EditorContext {
|
||||
timezone?: string
|
||||
}
|
||||
|
||||
function formatDate(timezone?: string): string[] {
|
||||
/**
|
||||
* Build static <env> lines from editor context.
|
||||
* These rarely change during a session and belong in the system prompt
|
||||
* so they benefit from prompt caching.
|
||||
*/
|
||||
export function staticEnvLines(ctx?: EditorContext): string[] {
|
||||
const now = new Date()
|
||||
const lines = [` Today's date: ${now.toDateString()}`]
|
||||
if (timezone) {
|
||||
if (ctx?.timezone) {
|
||||
const offset = -now.getTimezoneOffset()
|
||||
const sign = offset >= 0 ? "+" : "-"
|
||||
const hours = Math.floor(Math.abs(offset) / 60)
|
||||
const mins = Math.abs(offset) % 60
|
||||
lines.push(` User timezone: ${timezone}, UTC${sign}${hours}:${mins.toString().padStart(2, "0")}`)
|
||||
lines.push(` User timezone: ${ctx.timezone}, UTC${sign}${hours}:${mins.toString().padStart(2, "0")}`)
|
||||
}
|
||||
if (ctx?.shell) {
|
||||
lines.push(` Default shell: ${ctx.shell}`)
|
||||
}
|
||||
return lines
|
||||
}
|
||||
|
||||
/**
|
||||
* Build additional <env> lines from VS Code editor context.
|
||||
* Returns an array of pre-formatted ` key: value` strings.
|
||||
* Build a per-message <environment_details> block from editor context.
|
||||
* These change frequently (user switches files/tabs) and belong in the
|
||||
* user message so the model always has fresh context.
|
||||
* Returns undefined when there is nothing dynamic to report.
|
||||
*/
|
||||
export function editorContextEnvLines(ctx?: EditorContext): string[] {
|
||||
const lines = formatDate(ctx?.timezone)
|
||||
if (ctx?.shell) {
|
||||
lines.push(` Default shell: ${ctx.shell}`)
|
||||
}
|
||||
export function environmentDetails(ctx?: EditorContext): string | undefined {
|
||||
const lines: string[] = []
|
||||
if (ctx?.activeFile) {
|
||||
lines.push(` Active file: ${ctx.activeFile}`)
|
||||
lines.push(`Active file: ${ctx.activeFile}`)
|
||||
}
|
||||
if (ctx?.visibleFiles?.length) {
|
||||
lines.push(` Visible files: ${ctx.visibleFiles.join(", ")}`)
|
||||
lines.push(`Visible files:`)
|
||||
for (const f of ctx.visibleFiles) {
|
||||
lines.push(` ${f}`)
|
||||
}
|
||||
}
|
||||
if (ctx?.openTabs?.length) {
|
||||
lines.push(` Open tabs: ${ctx.openTabs.join(", ")}`)
|
||||
lines.push(`Open tabs:`)
|
||||
for (const f of ctx.openTabs) {
|
||||
lines.push(` ${f}`)
|
||||
}
|
||||
}
|
||||
return lines
|
||||
if (lines.length === 0) return undefined
|
||||
return ["<environment_details>", ...lines, "</environment_details>"].join("\n")
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import { iife } from "@/util/iife"
|
||||
import { Shell } from "@/shell/shell"
|
||||
import { Truncate } from "@/tool/truncation"
|
||||
import { PlanFollowup } from "@/kilocode/plan-followup" // kilocode_change
|
||||
import { environmentDetails } from "@/kilocode/editor-context" // kilocode_change
|
||||
|
||||
// @ts-ignore
|
||||
globalThis.AI_SDK_LOG_WARNINGS = false
|
||||
@@ -1355,6 +1356,20 @@ export namespace SessionPrompt {
|
||||
}),
|
||||
).then((x) => x.flat().map(assign))
|
||||
|
||||
// kilocode_change start — inject dynamic editor context into user message
|
||||
const envBlock = environmentDetails(input.editorContext)
|
||||
if (envBlock) {
|
||||
parts.push({
|
||||
id: Identifier.ascending("part"),
|
||||
messageID: info.id,
|
||||
sessionID: input.sessionID,
|
||||
type: "text",
|
||||
text: envBlock,
|
||||
synthetic: true,
|
||||
})
|
||||
}
|
||||
// kilocode_change end
|
||||
|
||||
await Plugin.trigger(
|
||||
"chat.message",
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ import type { Provider } from "@/provider/provider"
|
||||
|
||||
// kilocode_change start
|
||||
import SOUL from "../kilocode/soul.txt"
|
||||
import { editorContextEnvLines, type EditorContext } from "../kilocode/editor-context"
|
||||
import { staticEnvLines, type EditorContext } from "../kilocode/editor-context"
|
||||
// kilocode_change end
|
||||
|
||||
export namespace SystemPrompt {
|
||||
@@ -67,7 +67,7 @@ export namespace SystemPrompt {
|
||||
` Working directory: ${Instance.directory}`,
|
||||
` Is directory a git repo: ${project.vcs === "git" ? "yes" : "no"}`,
|
||||
` Platform: ${process.platform}`,
|
||||
...editorContextEnvLines(editorContext), // kilocode_change
|
||||
...staticEnvLines(editorContext), // kilocode_change
|
||||
`</env>`,
|
||||
`<directories>`,
|
||||
` ${
|
||||
|
||||
Reference in New Issue
Block a user