Skip to content

Commit

Permalink
add markdownBeforeBlock to code block (#230050)
Browse files Browse the repository at this point in the history
  • Loading branch information
aeschli committed Sep 29, 2024
1 parent 6ffa99f commit b116d4a
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 46 deletions.
21 changes: 18 additions & 3 deletions src/vs/workbench/api/common/extHostCodeMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { CancellationToken } from '../../../base/common/cancellation.js';
import { IExtensionDescription } from '../../../platform/extensions/common/extensions.js';
import { ICodeMapperResult } from '../../contrib/chat/common/chatCodeMapperService.js';
import * as extHostProtocol from './extHost.protocol.js';
import { TextEdit } from './extHostTypeConverters.js';
import { ChatAgentResult, DocumentContextItem, TextEdit } from './extHostTypeConverters.js';
import { URI } from '../../../base/common/uri.js';

export class ExtHostCodeMapper implements extHostProtocol.ExtHostCodeMapperShape {
Expand Down Expand Up @@ -45,10 +45,25 @@ export class ExtHostCodeMapper implements extHostProtocol.ExtHostCodeMapperShape
codeBlocks: internalRequest.codeBlocks.map(block => {
return {
code: block.code,
resource: URI.revive(block.resource)
resource: URI.revive(block.resource),
markdownBeforeBlock: block.markdownBeforeBlock
};
}),
conversation: internalRequest.conversation
conversation: internalRequest.conversation.map(item => {
if (item.type === 'request') {
return {
type: 'request',
message: item.message
} satisfies vscode.ConversationRequest;
} else {
return {
type: 'response',
message: item.message,
result: item.result ? ChatAgentResult.to(item.result) : undefined,
references: item.references?.map(DocumentContextItem.to)
} satisfies vscode.ConversationResponse;
}
})
};

const result = await provider.provideMappedEdits(request, stream, token);
Expand Down
22 changes: 19 additions & 3 deletions src/vs/workbench/api/common/extHostTypeConverters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1629,7 +1629,7 @@ export namespace MappedEditsContext {
);
}

export function from(extContext: vscode.MappedEditsContext): languages.MappedEditsContext {
export function from(extContext: vscode.MappedEditsContext): Dto<languages.MappedEditsContext> {
return {
documents: extContext.documents.map((subArray) =>
subArray.map(DocumentContextItem.from)
Expand All @@ -1643,6 +1643,7 @@ export namespace MappedEditsContext {
{
type: 'response',
message: item.message,
result: item.result ? ChatAgentResult.from(item.result) : undefined,
references: item.references?.map(DocumentContextItem.from)
}
))
Expand All @@ -1663,13 +1664,21 @@ export namespace DocumentContextItem {
);
}

export function from(item: vscode.DocumentContextItem): languages.DocumentContextItem {
export function from(item: vscode.DocumentContextItem): Dto<languages.DocumentContextItem> {
return {
uri: URI.from(item.uri),
uri: item.uri,
version: item.version,
ranges: item.ranges.map(r => Range.from(r)),
};
}

export function to(item: Dto<languages.DocumentContextItem>): vscode.DocumentContextItem {
return {
uri: URI.revive(item.uri),
version: item.version,
ranges: item.ranges.map(r => Range.to(r)),
};
}
}

export namespace NotebookRange {
Expand Down Expand Up @@ -2831,6 +2840,13 @@ export namespace ChatAgentResult {
nextQuestion: result.nextQuestion,
};
}
export function from(result: vscode.ChatResult): Dto<IChatAgentResult> {
return {
errorDetails: result.errorDetails,
metadata: result.metadata,
nextQuestion: result.nextQuestion,
};
}
}

export namespace ChatAgentUserActionEvent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ import { VSBuffer } from '../../../../../base/common/buffer.js';
import { CancellationTokenSource } from '../../../../../base/common/cancellation.js';
import { CharCode } from '../../../../../base/common/charCode.js';
import { isCancellationError } from '../../../../../base/common/errors.js';
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 { 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';
import { Range } from '../../../../../editor/common/core/range.js';
import { ConversationRequest, ConversationResponse, DocumentContextItem, isLocation, IWorkspaceFileEdit, IWorkspaceTextEdit } from '../../../../../editor/common/languages.js';
import { ConversationRequest, ConversationResponse, DocumentContextItem, IWorkspaceFileEdit, IWorkspaceTextEdit } from '../../../../../editor/common/languages.js';
import { ILanguageService } from '../../../../../editor/common/languages/language.js';
import { ITextModel } from '../../../../../editor/common/model.js';
import { ILanguageFeaturesService } from '../../../../../editor/common/services/languageFeatures.js';
Expand All @@ -31,7 +29,8 @@ import { InlineChatController } from '../../../inlineChat/browser/inlineChatCont
import { insertCell } from '../../../notebook/browser/controller/cellOperations.js';
import { IActiveNotebookEditor, INotebookEditor } from '../../../notebook/browser/notebookBrowser.js';
import { CellKind, NOTEBOOK_EDITOR_ID } from '../../../notebook/common/notebookCommon.js';
import { ChatUserAction, IChatContentReference, IChatService } from '../../common/chatService.js';
import { getReferencesAsDocumentContext } from '../../common/chatCodeMapperService.js';
import { ChatUserAction, IChatService } from '../../common/chatService.js';
import { isRequestVM, isResponseVM } from '../../common/chatViewModel.js';
import { ICodeBlockActionContext } from '../codeBlockPart.js';

Expand Down Expand Up @@ -404,32 +403,6 @@ function getChatConversation(context: ICodeBlockActionContext): (ConversationReq
}
}

function getReferencesAsDocumentContext(res: readonly IChatContentReference[]): DocumentContextItem[] {
const map = new ResourceMap<DocumentContextItem>();
for (const r of res) {
let uri;
let range;
if (URI.isUri(r.reference)) {
uri = r.reference;
} else if (isLocation(r.reference)) {
uri = r.reference.uri;
range = r.reference.range;
}
if (uri) {
const item = map.get(uri);
if (item) {
if (range) {
item.ranges.push(range);
}
} else {
map.set(uri, { uri, version: -1, ranges: range ? [range] : [] });
}
}
}
return [...map.values()];
}


function reindent(codeBlockContent: string, model: ITextModel, seletionStartLine: number): string {
const newContent = strings.splitLines(codeBlockContent);
if (newContent.length === 0) {
Expand Down
66 changes: 57 additions & 9 deletions src/vs/workbench/contrib/chat/common/chatCodeMapperService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,25 @@
import { CancellationToken } from '../../../../base/common/cancellation.js';
import { CharCode } from '../../../../base/common/charCode.js';
import { IDisposable } from '../../../../base/common/lifecycle.js';
import { ResourceMap } from '../../../../base/common/map.js';
import { splitLinesIncludeSeparators } from '../../../../base/common/strings.js';
import { isString } from '../../../../base/common/types.js';
import { URI } from '../../../../base/common/uri.js';
import { TextEdit } from '../../../../editor/common/languages.js';
import { DocumentContextItem, isLocation, TextEdit } from '../../../../editor/common/languages.js';
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
import { IChatAgentResult } from './chatAgents.js';
import { IChatResponseModel } from './chatModel.js';
import { IChatContentReference } from './chatService.js';


export interface ICodeMapperResponse {
textEdit: (resource: URI, textEdit: TextEdit[]) => void;
}

export interface ICodeMapperCodeBlock {
code: string;
resource: URI;
readonly code: string;
readonly resource: URI;
readonly markdownBeforeBlock?: string;
}

export interface ConversationRequest {
Expand All @@ -31,16 +35,17 @@ export interface ConversationRequest {
export interface ConversationResponse {
readonly type: 'response';
readonly message: string;
// readonly references?: DocumentContextItem[];
readonly result?: IChatAgentResult;
readonly references?: DocumentContextItem[];
}

export interface ICodeMapperRequest {
codeBlocks: ICodeMapperCodeBlock[];
conversation: (ConversationRequest | ConversationResponse)[];
readonly codeBlocks: ICodeMapperCodeBlock[];
readonly conversation: (ConversationResponse | ConversationRequest)[];
}

export interface ICodeMapperResult {
errorMessage?: string;
readonly errorMessage?: string;
}

export interface ICodeMapperProvider {
Expand Down Expand Up @@ -103,7 +108,7 @@ export class CodeMapperService implements ICodeMapperService {
fence = undefined;
if (currentBlockUri) {
// report the code block if we have a URI
codeBlocks.push({ code: currentBlock.join(''), resource: currentBlockUri });
codeBlocks.push({ code: currentBlock.join(''), resource: currentBlockUri, markdownBeforeBlock: markdownBeforeBlock.join('') });
currentBlock.length = 0;
markdownBeforeBlock.length = 0;
currentBlockUri = undefined;
Expand All @@ -123,7 +128,24 @@ export class CodeMapperService implements ICodeMapperService {
currentBlockUri = lineOrUri;
}
}
return this.mapCode({ codeBlocks, conversation: [] }, response, token);
const conversation: (ConversationRequest | ConversationResponse)[] = [];
for (const request of responseModel.session.getRequests()) {
const response = request.response;
if (!response || response === responseModel) {
break;
}
conversation.push({
type: 'request',
message: request.message.text
});
conversation.push({
type: 'response',
message: response.response.toMarkdown(),
result: response.result,
references: getReferencesAsDocumentContext(response.contentReferences)
});
}
return this.mapCode({ codeBlocks, conversation }, response, token);
}
}

Expand Down Expand Up @@ -155,3 +177,29 @@ function isLineIncomplete(line: string) {
const lastChar = line.charCodeAt(line.length - 1);
return lastChar !== CharCode.LineFeed && lastChar !== CharCode.CarriageReturn;
}


export function getReferencesAsDocumentContext(res: readonly IChatContentReference[]): DocumentContextItem[] {
const map = new ResourceMap<DocumentContextItem>();
for (const r of res) {
let uri;
let range;
if (URI.isUri(r.reference)) {
uri = r.reference;
} else if (isLocation(r.reference)) {
uri = r.reference.uri;
range = r.reference.range;
}
if (uri) {
const item = map.get(uri);
if (item) {
if (range) {
item.ranges.push(range);
}
} else {
map.set(uri, { uri, version: -1, ranges: range ? [range] : [] });
}
}
}
return [...map.values()];
}
3 changes: 2 additions & 1 deletion src/vscode-dts/vscode.proposed.mappedEditsProvider.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ declare module 'vscode' {
export interface ConversationResponse {
readonly type: 'response';
readonly message: string;
readonly result?: ChatResult;
readonly references?: DocumentContextItem[];
}

Expand Down Expand Up @@ -53,7 +54,7 @@ declare module 'vscode' {
}

export interface MappedEditsRequest {
readonly codeBlocks: { code: string; resource: Uri }[];
readonly codeBlocks: { code: string; resource: Uri; markdownBeforeBlock?: string }[];
readonly conversation: (ConversationRequest | ConversationResponse)[]; // for every prior response that contains codeblocks, make sure we pass the code as well as the resources based on the reported codemapper URIs
}

Expand Down

0 comments on commit b116d4a

Please sign in to comment.