feat: remove assistantMessageParser experiment flag and enable for all users (#7300)

- Remove assistantMessageParser from experiment definitions in packages/types
- Remove ASSISTANT_MESSAGE_PARSER from shared experiments configuration
- Update Task.ts to always initialize and use AssistantMessageParser
- Remove conditional logic that checked for experiment flag
- Remove unused parseAssistantMessage import
- Update test files to remove assistantMessageParser references
- All tests passing successfully

Co-authored-by: Roo Code <roomote@roocode.com>
This commit is contained in:
roomote[bot] 2025-08-21 15:30:42 -07:00 • committed by GitHub
parent 9fe06db921
commit 4222036c58
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 11 additions and 34 deletions

View file

@ -6,12 +6,7 @@ import type { Keys, Equals, AssertEqual } from "./type-fu.js"
* ExperimentId
*/
export const experimentIds = [
"powerSteering",
"multiFileApplyDiff",
"preventFocusDisruption",
"assistantMessageParser",
] as const
export const experimentIds = ["powerSteering", "multiFileApplyDiff", "preventFocusDisruption"] as const
export const experimentIdsSchema = z.enum(experimentIds)
@ -25,7 +20,6 @@ export const experimentsSchema = z.object({
powerSteering: z.boolean().optional(),
multiFileApplyDiff: z.boolean().optional(),
preventFocusDisruption: z.boolean().optional(),
assistantMessageParser: z.boolean().optional(),
})
export type Experiments = z.infer<typeof experimentsSchema>

View file

@ -80,7 +80,7 @@ import { ToolRepetitionDetector } from "../tools/ToolRepetitionDetector"
import { FileContextTracker } from "../context-tracking/FileContextTracker"
import { RooIgnoreController } from "../ignore/RooIgnoreController"
import { RooProtectedController } from "../protect/RooProtectedController"
import { type AssistantMessageContent, presentAssistantMessage, parseAssistantMessage } from "../assistant-message"
import { type AssistantMessageContent, presentAssistantMessage } from "../assistant-message"
import { AssistantMessageParser } from "../assistant-message/AssistantMessageParser"
import { truncateConversationIfNeeded } from "../sliding-window"
import { ClineProvider } from "../webview/ClineProvider"
@ -270,8 +270,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
didRejectTool = false
didAlreadyUseTool = false
didCompleteReadingStream = false
assistantMessageParser?: AssistantMessageParser
isAssistantMessageParserEnabled = false
assistantMessageParser: AssistantMessageParser
private lastUsedInstructions?: string
private skipPrevResponseIdOnce: boolean = false
@ -355,6 +354,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
TelemetryService.instance.captureTaskCreated(this.taskId)
}
// Initialize the assistant message parser
this.assistantMessageParser = new AssistantMessageParser()
// Only set up diff strategy if diff is enabled.
if (this.diffEnabled) {
// Default to old strategy, will be updated if experiment is enabled.
@ -1751,9 +1753,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
this.didAlreadyUseTool = false
this.presentAssistantMessageLocked = false
this.presentAssistantMessageHasPendingUpdates = false
if (this.assistantMessageParser) {
this.assistantMessageParser.reset()
}
this.assistantMessageParser.reset()
await this.diffViewProvider.reset()
@ -1794,12 +1794,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
// Parse raw assistant message chunk into content blocks.
const prevLength = this.assistantMessageContent.length
if (this.isAssistantMessageParserEnabled && this.assistantMessageParser) {
this.assistantMessageContent = this.assistantMessageParser.processChunk(chunk.text)
} else {
// Use the old parsing method when experiment is disabled
this.assistantMessageContent = parseAssistantMessage(assistantMessage)
}
this.assistantMessageContent = this.assistantMessageParser.processChunk(chunk.text)
if (this.assistantMessageContent.length > prevLength) {
// New content we need to present, reset to
@ -2058,11 +2053,8 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
// this.assistantMessageContent.forEach((e) => (e.partial = false))
// Now that the stream is complete, finalize any remaining partial content blocks
if (this.isAssistantMessageParserEnabled && this.assistantMessageParser) {
this.assistantMessageParser.finalizeContentBlocks()
this.assistantMessageContent = this.assistantMessageParser.getContentBlocks()
}
// When using old parser, no finalization needed - parsing already happened during streaming
this.assistantMessageParser.finalizeContentBlocks()
this.assistantMessageContent = this.assistantMessageParser.getContentBlocks()
if (partialBlocks.length > 0) {
// If there is content to update then it will complete and
@ -2081,9 +2073,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
await this.providerRef.deref()?.postStateToWebview()
// Reset parser after each complete conversation round
if (this.assistantMessageParser) {
this.assistantMessageParser.reset()
}
this.assistantMessageParser.reset()
// Now add to apiConversationHistory.
// Need to save assistant responses to file before proceeding to

View file

@ -29,7 +29,6 @@ describe("experiments", () => {
powerSteering: false,
multiFileApplyDiff: false,
preventFocusDisruption: false,
assistantMessageParser: false,
}
expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.POWER_STEERING)).toBe(false)
})
@ -39,7 +38,6 @@ describe("experiments", () => {
powerSteering: true,
multiFileApplyDiff: false,
preventFocusDisruption: false,
assistantMessageParser: false,
}
expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.POWER_STEERING)).toBe(true)
})
@ -49,7 +47,6 @@ describe("experiments", () => {
powerSteering: false,
multiFileApplyDiff: false,
preventFocusDisruption: false,
assistantMessageParser: false,
}
expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.POWER_STEERING)).toBe(false)
})

View file

@ -4,7 +4,6 @@ export const EXPERIMENT_IDS = {
MULTI_FILE_APPLY_DIFF: "multiFileApplyDiff",
POWER_STEERING: "powerSteering",
PREVENT_FOCUS_DISRUPTION: "preventFocusDisruption",
ASSISTANT_MESSAGE_PARSER: "assistantMessageParser",
} as const satisfies Record<string, ExperimentId>
type _AssertExperimentIds = AssertEqual<Equals<ExperimentId, Values<typeof EXPERIMENT_IDS>>>
@ -19,7 +18,6 @@ export const experimentConfigsMap: Record<ExperimentKey, ExperimentConfig> = {
MULTI_FILE_APPLY_DIFF: { enabled: false },
POWER_STEERING: { enabled: false },
PREVENT_FOCUS_DISRUPTION: { enabled: false },
ASSISTANT_MESSAGE_PARSER: { enabled: false },
}
export const experimentDefault = Object.fromEntries(

View file

@ -229,7 +229,6 @@ describe("mergeExtensionState", () => {
concurrentFileReads: true,
multiFileApplyDiff: true,
preventFocusDisruption: false,
assistantMessageParser: false,
newTaskRequireTodos: false,
} as Record<ExperimentId, boolean>,
}
@ -248,7 +247,6 @@ describe("mergeExtensionState", () => {
concurrentFileReads: true,
multiFileApplyDiff: true,
preventFocusDisruption: false,
assistantMessageParser: false,
newTaskRequireTodos: false,
})
})