Fix Apply failure with <think> tags (#283)

- Add utility to strip <think> tags from responses
- Strip tags before computing diffs in Apply operation
- Handle nested tags properly
- Keep original response intact for UI display

Fixes #283

Co-Authored-By: Jack Hacksman <slack@hannis.io>
This commit is contained in:
Devin AI 2025-02-15 13:35:58 +00:00
parent 7fbe8d905f
commit 7849b0a107
2 changed files with 33 additions and 4 deletions

View file

@ -11,6 +11,7 @@ import { ResourceMap } from '../../../../../base/common/map.js';
import { isEqual } from '../../../../../base/common/resources.js';
import * as strings from '../../../../../base/common/strings.js';
import { URI } from '../../../../../base/common/uri.js';
import { stripThinkTags } from '../../common/chatModel.js';
import { IActiveCodeEditor, isCodeEditor, isDiffEditor } from '../../../../../editor/browser/editorBrowser.js';
import { IBulkEditService, ResourceTextEdit } from '../../../../../editor/browser/services/bulkEditService.js';
import { ICodeEditorService } from '../../../../../editor/browser/services/codeEditorService.js';
@ -382,13 +383,11 @@ function collectDocumentContextFromContext(context: ICodeBlockActionContext, res
}
function getChatConversation(context: ICodeBlockActionContext): (ConversationRequest | ConversationResponse)[] {
// TODO@aeschli for now create a conversation with just the current element
// this will be expanded in the future to include the request and any other responses
if (isResponseVM(context.element)) {
return [{
type: 'response',
message: context.element.response.toMarkdown(),
// Strip think tags before computing diffs
message: stripThinkTags(context.element.response.toMarkdown()),
references: getReferencesAsDocumentContext(context.element.contentReferences)
}];
} else if (isRequestVM(context.element)) {

View file

@ -354,6 +354,36 @@ export class Response extends Disposable implements IResponse {
}
}
/**
* Strips <think> tags and their content from a text string.
* Handles nested tags using a stack-based approach.
* @param text The text to strip tags from
* @returns The text with all <think> tags and their content removed
*/
export function stripThinkTags(text: string): string {
// Handle nested tags with a stack-based approach
let result = '';
let depth = 0;
let i = 0;
while (i < text.length) {
if (text.startsWith('<think>', i)) {
depth++;
i += 7; // length of '<think>'
} else if (text.startsWith('</think>', i)) {
depth--;
i += 8; // length of '</think>'
} else if (depth === 0) {
result += text[i];
i++;
} else {
i++;
}
}
return result;
}
export class ChatResponseModel extends Disposable implements IChatResponseModel {
private readonly _onDidChange = this._register(new Emitter<void>());
readonly onDidChange = this._onDidChange.event;