Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/platform/log/common/messageStringify.ts
13401 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Raw } from '@vscode/prompt-tsx';
7
import { mapFindFirst } from '../../../util/vs/base/common/arraysFind';
8
import { roleToString } from '../../chat/common/globalStringUtils';
9
import { rawPartAsStatefulMarker } from '../../endpoint/common/statefulMarkerContainer';
10
import { rawPartAsThinkingData } from '../../endpoint/common/thinkingDataContainer';
11
12
export function messageToMarkdown(message: Raw.ChatMessage, ignoreStatefulMarker?: boolean, skipFencing?: boolean): string {
13
const role = roleToString(message.role);
14
const capitalizedRole = role.charAt(0).toUpperCase() + role.slice(1);
15
let str = skipFencing ? `### ${capitalizedRole}\n` : `### ${capitalizedRole}\n~~~md\n`;
16
if (message.role === Raw.ChatRole.Tool) {
17
str += `🛠️ ${message.toolCallId}`;
18
if (message.content) {
19
str += '\n';
20
}
21
}
22
23
if (Array.isArray(message.content)) {
24
str += message.content.map(item => {
25
if (item.type === Raw.ChatCompletionContentPartKind.Text) {
26
return item.text;
27
} else if (item.type === Raw.ChatCompletionContentPartKind.Image) {
28
return JSON.stringify(item);
29
} else if (item.type === Raw.ChatCompletionContentPartKind.Opaque) {
30
const asThinking = rawPartAsThinkingData(item);
31
if (asThinking) {
32
const parts: string[] = [];
33
if (asThinking.text) {
34
const thinkingText = Array.isArray(asThinking.text) ? asThinking.text.join('\n') : asThinking.text;
35
parts.push(`reasoning: ${thinkingText}`);
36
}
37
if (asThinking.encrypted?.length) {
38
parts.push(`encrypted_content=${asThinking.encrypted.length} chars`);
39
}
40
41
if (parts.length) {
42
return parts.join('\n');
43
}
44
}
45
}
46
}).join('\n');
47
} else {
48
str += message.content;
49
}
50
51
if (message.role === Raw.ChatRole.Assistant && message.toolCalls?.length) {
52
if (message.content) {
53
str += '\n';
54
}
55
str += message.toolCalls.map(c => {
56
let argsStr = c.function.arguments;
57
try {
58
const parsedArgs = JSON.parse(c.function.arguments);
59
argsStr = JSON.stringify(parsedArgs, undefined, 2)
60
.replace(/(?<!\\)\\n/g, '\n')
61
.replace(/(?<!\\)\\t/g, '\t');
62
} catch (e) { }
63
return `🛠️ ${c.function.name} (${c.id}) ${argsStr}`;
64
}).join('\n');
65
}
66
67
if (message.content.some(part => part.type === Raw.ChatCompletionContentPartKind.CacheBreakpoint)) {
68
str += `\n[copilot_cache_control: { type: 'ephemeral' }]`;
69
}
70
71
const statefulMarker = mapFindFirst(message.content, c => c.type === Raw.ChatCompletionContentPartKind.Opaque ? rawPartAsStatefulMarker(c) : undefined);
72
if (statefulMarker && !ignoreStatefulMarker) {
73
str += `\n[response_id: ${statefulMarker.marker} with ${statefulMarker.modelId}]`;
74
}
75
76
if (!skipFencing) {
77
str += '\n~~~\n';
78
} else {
79
str += '\n';
80
}
81
82
return str;
83
}
84
85