Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/chat/browser/chatDebug/chatDebugHookContentRenderer.ts
13406 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 * as DOM from '../../../../../base/browser/dom.js';
7
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
8
import { localize } from '../../../../../nls.js';
9
import { IClipboardService } from '../../../../../platform/clipboard/common/clipboardService.js';
10
import { ILanguageService } from '../../../../../editor/common/languages/language.js';
11
import { ChatDebugHookResult, IChatDebugEventHookContent } from '../../common/chatDebugService.js';
12
import { renderSection, tokenizeContent } from './chatDebugToolCallContentRenderer.js';
13
14
const $ = DOM.$;
15
16
/**
17
* Render a resolved hook execution content with structured sections for
18
* hook type, command, result, duration, input, and output.
19
* When JSON is detected in input/output, renders it with syntax highlighting.
20
*/
21
export async function renderHookContent(content: IChatDebugEventHookContent, languageService: ILanguageService, clipboardService?: IClipboardService, scrollable?: { scanDomNode(): void }): Promise<{ element: HTMLElement; disposables: DisposableStore }> {
22
const disposables = new DisposableStore();
23
const container = $('div.chat-debug-message-content');
24
container.tabIndex = 0;
25
26
// Header: hook type
27
DOM.append(container, $('div.chat-debug-message-content-title', undefined, content.hookType));
28
29
// Status summary line
30
const statusParts: string[] = [];
31
if (content.result !== undefined) {
32
statusParts.push(formatHookResult(content.result));
33
}
34
if (content.exitCode !== undefined) {
35
statusParts.push(localize('chatDebug.hook.exitCode', "Exit Code: {0}", content.exitCode));
36
}
37
if (content.durationInMillis !== undefined) {
38
statusParts.push(localize('chatDebug.hook.duration', "{0}ms", content.durationInMillis));
39
}
40
if (statusParts.length > 0) {
41
DOM.append(container, $('div.chat-debug-message-content-summary', undefined, statusParts.join(' \u00b7 ')));
42
}
43
44
// Build collapsible sections for command, input, output, and error
45
const sectionsContainer = DOM.append(container, $('div.chat-debug-message-sections'));
46
47
if (content.command) {
48
const { plainText, tokenizedHtml } = await tokenizeContent(content.command, languageService);
49
renderSection(sectionsContainer, localize('chatDebug.hook.command', "Command"), plainText, tokenizedHtml, disposables, false, clipboardService, scrollable);
50
}
51
52
if (content.input) {
53
const { plainText, tokenizedHtml } = await tokenizeContent(content.input, languageService);
54
renderSection(sectionsContainer, localize('chatDebug.hook.input', "Input"), plainText, tokenizedHtml, disposables, false, clipboardService, scrollable);
55
}
56
57
if (content.output) {
58
const { plainText, tokenizedHtml } = await tokenizeContent(content.output, languageService);
59
renderSection(sectionsContainer, localize('chatDebug.hook.output', "Output"), plainText, tokenizedHtml, disposables, false, clipboardService, scrollable);
60
}
61
62
if (content.errorMessage) {
63
const { plainText, tokenizedHtml } = await tokenizeContent(content.errorMessage, languageService);
64
renderSection(sectionsContainer, localize('chatDebug.hook.error', "Error"), plainText, tokenizedHtml, disposables, false, clipboardService, scrollable);
65
}
66
67
return { element: container, disposables };
68
}
69
70
function formatHookResult(result: ChatDebugHookResult): string {
71
switch (result) {
72
case ChatDebugHookResult.Success:
73
return localize('chatDebug.hook.result.success', "Success");
74
case ChatDebugHookResult.Error:
75
return localize('chatDebug.hook.result.error', "Error");
76
case ChatDebugHookResult.NonBlockingError:
77
return localize('chatDebug.hook.result.nonBlockingError', "Non-blocking Error");
78
default:
79
return String(result);
80
}
81
}
82
83
/**
84
* Convert a resolved hook content to plain text for clipboard / editor output.
85
*/
86
export function hookContentToPlainText(content: IChatDebugEventHookContent): string {
87
const lines: string[] = [];
88
lines.push(localize('chatDebug.hook.typeLabel', "Hook Type: {0}", content.hookType));
89
90
if (content.result !== undefined) {
91
lines.push(localize('chatDebug.hook.resultLabel', "Result: {0}", formatHookResult(content.result)));
92
}
93
if (content.exitCode !== undefined) {
94
lines.push(localize('chatDebug.hook.exitCodeLabel', "Exit Code: {0}", content.exitCode));
95
}
96
if (content.durationInMillis !== undefined) {
97
lines.push(localize('chatDebug.hook.durationLabel', "Duration: {0}ms", content.durationInMillis));
98
}
99
100
if (content.command) {
101
lines.push('');
102
lines.push(`[${localize('chatDebug.hook.command', "Command")}]`);
103
lines.push(content.command);
104
}
105
106
if (content.input) {
107
lines.push('');
108
lines.push(`[${localize('chatDebug.hook.input', "Input")}]`);
109
try {
110
const parsed = JSON.parse(content.input);
111
lines.push(JSON.stringify(parsed, null, 2));
112
} catch {
113
lines.push(content.input);
114
}
115
}
116
117
if (content.output) {
118
lines.push('');
119
lines.push(`[${localize('chatDebug.hook.output', "Output")}]`);
120
try {
121
const parsed = JSON.parse(content.output);
122
lines.push(JSON.stringify(parsed, null, 2));
123
} catch {
124
lines.push(content.output);
125
}
126
}
127
128
if (content.errorMessage) {
129
lines.push('');
130
lines.push(`[${localize('chatDebug.hook.error', "Error")}]`);
131
lines.push(content.errorMessage);
132
}
133
134
return lines.join('\n');
135
}
136
137