Skip to content

Commit 115efcc

Browse files
committed
sythesize
1 parent c15680c commit 115efcc

File tree

14 files changed

+136
-128
lines changed

14 files changed

+136
-128
lines changed

src/core/Cline.ts

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ import { truncateConversationIfNeeded, estimateTokenCount } from "./sliding-wind
9090
import { ClineProvider } from "./webview/ClineProvider"
9191
import { validateToolUse } from "./mode-validator"
9292
import { MultiSearchReplaceDiffStrategy } from "./diff/strategies/multi-search-replace"
93-
import { ContextSummarizer } from "../services/summarization/ContextSummarizer" // Added ContextSummarizer
93+
import { ContextSynthesizer } from "../services/synthesization/ContextSynthesizer" // Updated to ContextSynthesizer
9494
import { readApiMessages, saveApiMessages, readTaskMessages, saveTaskMessages, taskMetadata } from "./task-persistence"
9595

9696
type UserContent = Array<Anthropic.Messages.ContentBlockParam>
@@ -1056,16 +1056,16 @@ export class Cline extends EventEmitter<ClineEvents> {
10561056
let historyModifiedBySummarization = false // Flag to track if summarization updated history
10571057

10581058
if (this.enableContextSummarization) {
1059-
// --- Summarization Logic ---
1059+
// --- Synthesizing Logic ---
10601060
const currentTokens = await this._estimateTotalTokenCount(this.apiConversationHistory)
10611061
const triggerTokenCount = contextWindow * (this.contextSummarizationTriggerThreshold / 100)
10621062

10631063
this.providerRef
10641064
.deref()
1065-
?.log(`[Summarization] Current tokens: ${currentTokens}, Trigger: ${triggerTokenCount}`)
1065+
?.log(`[Synthesizing] Current tokens: ${currentTokens}, Trigger: ${triggerTokenCount}`)
10661066

10671067
if (currentTokens >= triggerTokenCount) {
1068-
this.providerRef.deref()?.log(`[Summarization] Threshold met. Attempting summarization.`)
1068+
this.providerRef.deref()?.log(`[Synthesizing] Threshold met. Attempting synthesizing.`)
10691069
const initialMessagesToKeep = this.contextSummarizationInitialStaticTurns
10701070
const recentMessagesToKeep = this.contextSummarizationRecentTurns
10711071

@@ -1089,43 +1089,43 @@ export class Cline extends EventEmitter<ClineEvents> {
10891089
this.providerRef
10901090
.deref()
10911091
?.log(
1092-
`[Summarization] Slicing: Keep Initial ${initialMessages.length}, Summarize ${messagesToSummarize.length}, Keep Recent ${recentMessages.length}`,
1092+
`[Synthesizing] Slicing: Keep Initial ${initialMessages.length}, Synthesize ${messagesToSummarize.length}, Keep Recent ${recentMessages.length}`,
10931093
)
10941094

1095-
// Instantiate the summarizer (consider using a dedicated API handler/model later)
1096-
const summarizer = new ContextSummarizer(this.api)
1097-
const summaryMessage = await summarizer.summarize(messagesToSummarize)
1095+
// Instantiate the synthesizer (consider using a dedicated API handler/model later)
1096+
const synthesizer = new ContextSynthesizer(this.api)
1097+
const summaryMessage = await synthesizer.synthesize(messagesToSummarize)
10981098

10991099
if (summaryMessage) {
11001100
const newHistory = [...initialMessages, summaryMessage, ...recentMessages]
11011101
this.providerRef
11021102
.deref()
11031103
?.log(
1104-
`[Summarization] Summarization successful. New history length: ${newHistory.length}`,
1104+
`[Synthesizing] Synthesizing successful. New history length: ${newHistory.length}`,
11051105
)
11061106
// Add a system message to notify the user in the UI
1107-
await this.say("text", "[Older conversation turns summarized to preserve context]")
1107+
await this.say("text", "[Older conversation turns synthesized to preserve context]")
11081108
await this.overwriteApiConversationHistory(newHistory)
11091109
historyModifiedBySummarization = true // Mark history as modified
11101110
} else {
11111111
this.providerRef
11121112
.deref()
1113-
?.log(`[Summarization] Summarization failed. Falling back to truncation.`)
1113+
?.log(`[Synthesizing] Synthesizing failed. Falling back to truncation.`)
11141114
// Fall through to truncation if summarization fails
11151115
}
11161116
} else {
11171117
this.providerRef
11181118
.deref()
11191119
?.log(
1120-
`[Summarization] Skipping: initialSliceEnd (${initialSliceEnd}) >= recentSliceStart (${recentSliceStart}). Not enough messages between initial/recent turns.`,
1120+
`[Synthesizing] Skipping: initialSliceEnd (${initialSliceEnd}) >= recentSliceStart (${recentSliceStart}). Not enough messages between initial/recent turns.`,
11211121
)
11221122
// Fall through to truncation if slicing is not possible
11231123
}
11241124
} else {
11251125
this.providerRef
11261126
.deref()
11271127
?.log(
1128-
`[Summarization] Skipping: Not enough messages (${this.apiConversationHistory.length}) to satisfy keep counts (${initialMessagesToKeep} + ${recentMessagesToKeep}).`,
1128+
`[Synthesizing] Skipping: Not enough messages (${this.apiConversationHistory.length}) to satisfy keep counts (${initialMessagesToKeep} + ${recentMessagesToKeep}).`,
11291129
)
11301130
// Fall through to truncation if history is too short
11311131
}
@@ -1146,7 +1146,7 @@ export class Cline extends EventEmitter<ClineEvents> {
11461146
})
11471147

11481148
if (trimmedMessages !== this.apiConversationHistory) {
1149-
this.providerRef.deref()?.log(`[Truncation] Truncation applied.`)
1149+
this.providerRef.deref()?.log(`[Synthesizing] Truncation applied as fallback.`)
11501150
await this.overwriteApiConversationHistory(trimmedMessages)
11511151
}
11521152
}
@@ -2682,22 +2682,22 @@ export class Cline extends EventEmitter<ClineEvents> {
26822682
* @param isManualTrigger Whether this summarization was manually triggered by the user.
26832683
* @returns A promise that resolves when summarization is complete.
26842684
*/
2685-
public async summarizeConversationContext(_isManualTrigger: boolean = false): Promise<void> {
2686-
// Skip if summarization is disabled
2685+
public async synthesizeConversationContext(_isManualTrigger: boolean = false): Promise<void> {
2686+
// Skip if synthesizing is disabled
26872687
if (!this.enableContextSummarization) {
2688-
this.providerRef.deref()?.log("[Summarization] Context summarization is disabled.")
2688+
this.providerRef.deref()?.log("[Synthesizing] Context synthesizing is disabled.")
26892689
return
26902690
}
26912691

26922692
const initialMessagesToKeep = this.contextSummarizationInitialStaticTurns
26932693
const recentMessagesToKeep = this.contextSummarizationRecentTurns
26942694

2695-
// Ensure we have enough messages to summarize
2695+
// Ensure we have enough messages to synthesize
26962696
if (this.apiConversationHistory.length <= initialMessagesToKeep + recentMessagesToKeep) {
26972697
this.providerRef
26982698
.deref()
26992699
?.log(
2700-
`[Summarization] Not enough messages to summarize. Need more than ${initialMessagesToKeep + recentMessagesToKeep} messages.`,
2700+
`[Synthesizing] Not enough messages to synthesize. Need more than ${initialMessagesToKeep + recentMessagesToKeep} messages.`,
27012701
)
27022702
return
27032703
}
@@ -2711,7 +2711,7 @@ export class Cline extends EventEmitter<ClineEvents> {
27112711
this.providerRef
27122712
.deref()
27132713
?.log(
2714-
`[Summarization] Skipping: initialSliceEnd (${initialSliceEnd}) >= recentSliceStart (${recentSliceStart}). Not enough messages between initial/recent turns.`,
2714+
`[Synthesizing] Skipping: initialSliceEnd (${initialSliceEnd}) >= recentSliceStart (${recentSliceStart}). Not enough messages between initial/recent turns.`,
27152715
)
27162716
return
27172717
}
@@ -2724,15 +2724,15 @@ export class Cline extends EventEmitter<ClineEvents> {
27242724
this.providerRef
27252725
.deref()
27262726
?.log(
2727-
`[Summarization] Slicing: Keep Initial ${initialMessages.length}, Summarize ${messagesToSummarize.length}, Keep Recent ${recentMessages.length}`,
2727+
`[Synthesizing] Slicing: Keep Initial ${initialMessages.length}, Synthesize ${messagesToSummarize.length}, Keep Recent ${recentMessages.length}`,
27282728
)
27292729

2730-
// Create summarizer and generate summary
2731-
const summarizer = new ContextSummarizer(this.api)
2732-
const summaryMessage = await summarizer.summarize(messagesToSummarize)
2730+
// Create synthesizer and generate synthesis
2731+
const synthesizer = new ContextSynthesizer(this.api)
2732+
const summaryMessage = await synthesizer.synthesize(messagesToSummarize)
27332733

27342734
if (!summaryMessage) {
2735-
this.providerRef.deref()?.log(`[Summarization] Failed to generate summary.`)
2735+
this.providerRef.deref()?.log(`[Synthesizing] Failed to generate synthesis.`)
27362736
return
27372737
}
27382738

@@ -2745,7 +2745,7 @@ export class Cline extends EventEmitter<ClineEvents> {
27452745
this.providerRef
27462746
.deref()
27472747
?.log(
2748-
`[Summarization] Successfully summarized ${messagesToSummarize.length} messages. New history length: ${newHistory.length}`,
2748+
`[Synthesizing] Successfully synthesized ${messagesToSummarize.length} messages. New history length: ${newHistory.length}`,
27492749
)
27502750
}
27512751
}

src/core/webview/webviewMessageHandler.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,7 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
860860
await updateGlobalState("historyPreviewCollapsed", message.bool ?? false)
861861
// No need to call postStateToWebview here as the UI already updated optimistically
862862
break
863-
// Context Summarization Settings (Added)
863+
// Context Synthesization Settings
864864
case "enableContextSummarization":
865865
await updateGlobalState("enableContextSummarization", message.bool ?? false)
866866
await provider.postStateToWebview()
@@ -877,43 +877,43 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
877877
await updateGlobalState("contextSummarizationRecentTurns", message.value ?? 10)
878878
await provider.postStateToWebview()
879879
break
880-
case "manualSummarize":
881-
// Trigger manual summarization of the conversation context
880+
case "manualSynthesize":
881+
// Trigger manual synthesizing of the conversation context
882882
const currentCline = provider.getCurrentCline()
883883
if (currentCline) {
884884
// First send a message to the webview to show a progress indicator
885885
void provider.postMessageToWebview({
886-
type: "summarizationStatus",
886+
type: "synthesizationStatus",
887887
status: "started",
888-
text: t("common:info.summarizing_context"),
888+
text: t("common:info.synthesizing_context"),
889889
})
890890

891891
// Use a non-blocking approach with proper error handling
892892
try {
893-
// Trigger the summarization process directly without adding system messages
894-
await currentCline.summarizeConversationContext(true) // true indicates manual trigger
893+
// Trigger the synthesizing process directly without adding system messages
894+
await currentCline.synthesizeConversationContext(true) // true indicates manual trigger
895895

896896
// Send a message to the webview to hide the progress indicator
897897
void provider.postMessageToWebview({
898-
type: "summarizationStatus",
898+
type: "synthesizationStatus",
899899
status: "completed",
900-
text: t("common:info.summarization_complete"),
900+
text: t("common:info.synthesization_complete"),
901901
})
902902
} catch (error) {
903903
provider.log(
904-
`Error during manual summarization: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
904+
`Error during manual synthesizing: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
905905
)
906906

907907
// Update the UI to show the error
908908
void provider.postMessageToWebview({
909-
type: "summarizationStatus",
909+
type: "synthesizationStatus",
910910
status: "failed",
911-
text: t("common:errors.summarization_failed"),
911+
text: t("common:errors.synthesization_failed"),
912912
})
913913
}
914914
}
915915
break
916-
// --- End Context Summarization ---
916+
// --- End Context Synthesization ---
917917
case "toggleApiConfigPin":
918918
if (message.text) {
919919
const currentPinned = getGlobalState("pinnedApiConfigs") ?? {}

src/i18n/locales/en/common.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"create_mcp_json": "Failed to create or open .roo/mcp.json: {{error}}",
4848
"hmr_not_running": "Local development server is not running, HMR will not work. Please run 'npm run dev' before launching the extension to enable HMR.",
4949
"retrieve_current_mode": "Error: failed to retrieve current mode from state.",
50-
"summarization_failed": "Failed to summarize conversation context.",
50+
"synthesization_failed": "Failed to synthesize conversation context.",
5151
"failed_delete_repo": "Failed to delete associated shadow repository or branch: {{error}}",
5252
"failed_remove_directory": "Failed to remove task directory: {{error}}",
5353
"custom_storage_path_unusable": "Custom storage path \"{{path}}\" is unusable, will use default path",
@@ -69,8 +69,8 @@
6969
"custom_storage_path_set": "Custom storage path set: {{path}}",
7070
"default_storage_path": "Reverted to using default storage path",
7171
"settings_imported": "Settings imported successfully.",
72-
"summarizing_context": "Summarizing conversation context...",
73-
"summarization_complete": "Conversation context summarization complete."
72+
"synthesizing_context": "Synthesizing conversation context...",
73+
"synthesization_complete": "Conversation context synthesization complete."
7474
},
7575
"answers": {
7676
"yes": "Yes",

src/services/summarization/ContextSummarizer.ts renamed to src/services/synthesization/ContextSynthesizer.ts

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,36 @@ import { Anthropic } from "@anthropic-ai/sdk"
33
import { ApiHandler } from "../../api"
44

55
/**
6-
* Service responsible for summarizing conversation history segments.
6+
* Service responsible for synthesizing conversation history segments.
77
*/
8-
export class ContextSummarizer {
8+
export class ContextSynthesizer {
99
private apiHandler: ApiHandler
1010

1111
constructor(apiHandler: ApiHandler) {
1212
this.apiHandler = apiHandler
13-
// TODO: Consider if a specific, potentially faster/cheaper model should be configured for summarization,
13+
// TODO: Consider if a specific, potentially faster/cheaper model should be configured for synthesizing,
1414
// possibly by accepting a separate ApiConfiguration or model ID in the constructor.
1515
}
1616

1717
/**
18-
* Summarizes a given array of conversation messages using an LLM.
19-
* @param messagesToSummarize The array of messages to be summarized.
20-
* @returns A promise that resolves to a new message object containing the summary,
21-
* or null if summarization fails or is not possible.
18+
* Synthesizes a given array of conversation messages using an LLM.
19+
* @param messagesToSynthesize The array of messages to be synthesized.
20+
* @returns A promise that resolves to a new message object containing the synthesis,
21+
* or null if synthesizing fails or is not possible.
2222
*/
23-
async summarize(messagesToSummarize: Anthropic.MessageParam[]): Promise<Anthropic.MessageParam | null> {
24-
if (messagesToSummarize.length === 0) {
25-
return null // Nothing to summarize
23+
async synthesize(messagesToSynthesize: Anthropic.MessageParam[]): Promise<Anthropic.MessageParam | null> {
24+
if (messagesToSynthesize.length === 0) {
25+
return null // Nothing to synthesize
2626
}
2727

28-
// Construct the prompt for the summarization model (User Final Refinement)
28+
// Construct the prompt for the synthesizing model (User Final Refinement)
2929
const systemPrompt = `You are a specialized context compression system for Roo-Code, a VS Code extension that enables AI coding agents. Your sole purpose is to condense conversation history while preserving maximum technical context with minimum tokens.
3030
3131
**Context Schema:**
32-
- You are summarizing the MIDDLE portion of a conversation
33-
- The original system prompt and initial interactions remain intact before your summary
34-
- Recent conversation turns remain intact after your summary
35-
- Your summary will be the critical bridge connecting these preserved segments
32+
- You are synthesizing the MIDDLE portion of a conversation
33+
- The original system prompt and initial interactions remain intact before your synthesis
34+
- Recent conversation turns remain intact after your synthesis
35+
- Your synthesis will be the critical bridge connecting these preserved segments
3636
3737
**Content Priorities (Highest to Lowest):**
3838
1. **Code Context:**
@@ -64,19 +64,19 @@ export class ContextSummarizer {
6464
- Testing approaches
6565
6666
**Output Requirements:**
67-
- Produce ONLY the summary text with no meta-commentary
67+
- Produce ONLY the synthesis text with no meta-commentary
6868
- Use precise, technical language optimized for information density
6969
- Structure with minimal formatting (use ## for major sections if necessary)
7070
- Omit pleasantries, acknowledgments, and conversational elements
7171
- Format sequences of related facts as compact, semicolon-separated phrases
7272
- Use minimal tokens while maximizing preserved information
7373
- Prioritize factual over instructional content
7474
75-
This summary must enable seamless conversation continuity with no perceived context loss between the earlier and later preserved segments.`
75+
This synthesis must enable seamless conversation continuity with no perceived context loss between the earlier and later preserved segments.`
7676

7777
// Format the messages for the prompt. Simple stringification might be too verbose or lose structure.
7878
// Let's try a more readable format.
79-
const formattedMessages = messagesToSummarize
79+
const formattedMessages = messagesToSynthesize
8080
.map((msg) => {
8181
let contentText = ""
8282
if (Array.isArray(msg.content)) {
@@ -95,52 +95,52 @@ This summary must enable seamless conversation continuity with no perceived cont
9595
})
9696
.join("\n\n---\n\n")
9797

98-
const userPrompt = `Please summarize the following conversation turns:\n\n${formattedMessages}`
98+
const userPrompt = `Please synthesize the following conversation turns:\n\n${formattedMessages}`
9999

100100
try {
101-
// Use the configured API handler to make the summarization call
102-
// Note: This uses the main configured model. Consider allowing a specific summarization model.
103-
// Disable prompt caching for summarization calls? - Currently not directly supported per-call.
101+
// Use the configured API handler to make the synthesizing call
102+
// Note: This uses the main configured model. Consider allowing a specific synthesizing model.
103+
// Disable prompt caching for synthesizing calls? - Currently not directly supported per-call.
104104
// It will use the handler's configured caching setting.
105105
const stream = this.apiHandler.createMessage(
106106
systemPrompt,
107107
[{ role: "user", content: userPrompt }],
108-
undefined, // No specific cache key for summarization
108+
undefined, // No specific cache key for synthesizing
109109
// { promptCachingEnabled: false } // Removed incorrect 4th argument
110110
)
111111

112-
let summaryText = ""
112+
let synthesisText = ""
113113
let finalUsage = null
114114

115115
// Consume the stream to get the full response
116116
for await (const chunk of stream) {
117117
if (chunk.type === "text") {
118-
summaryText += chunk.text
118+
synthesisText += chunk.text
119119
} else if (chunk.type === "usage") {
120120
// Capture usage details if needed for cost tracking/logging
121121
finalUsage = chunk
122122
}
123123
}
124124

125125
if (finalUsage) {
126-
// Optional: Log summarization cost/tokens
126+
// Optional: Log synthesizing cost/tokens
127127
console.log(
128-
`[Summarization] Usage: In=${finalUsage.inputTokens}, Out=${finalUsage.outputTokens}, Cost=${finalUsage.totalCost?.toFixed(6) ?? "N/A"}`,
128+
`[Synthesizing] Usage: In=${finalUsage.inputTokens}, Out=${finalUsage.outputTokens}, Cost=${finalUsage.totalCost?.toFixed(6) ?? "N/A"}`,
129129
)
130130
}
131131

132-
if (!summaryText || summaryText.trim() === "") {
133-
console.warn("Context summarization resulted in an empty summary.")
132+
if (!synthesisText || synthesisText.trim() === "") {
133+
console.warn("Context synthesizing resulted in an empty synthesis.")
134134
return null
135135
}
136136

137-
// Return the summary as a user message, representing the summarized history.
137+
// Return the synthesis as a user message, representing the synthesized history.
138138
return {
139-
role: "user", // Represents the summarized user/assistant interaction leading up to the current point.
140-
content: `[Summarized Conversation History]\n${summaryText.trim()}`,
139+
role: "user", // Represents the synthesized user/assistant interaction leading up to the current point.
140+
content: `[Synthesized Conversation History]\n${synthesisText.trim()}`,
141141
}
142142
} catch (error) {
143-
console.error("Context summarization API call failed:", error)
143+
console.error("Context synthesizing API call failed:", error)
144144
// TODO: Add more robust error handling/logging (e.g., telemetry)
145145
return null // Indicate failure
146146
}

src/shared/ExtensionMessage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export interface ExtensionMessage {
6767
| "toggleApiConfigPin"
6868
| "acceptInput"
6969
| "setHistoryPreviewCollapsed"
70-
| "summarizationStatus"
70+
| "synthesizationStatus"
7171
text?: string
7272
action?:
7373
| "chatButtonClicked"

0 commit comments

Comments
 (0)