Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/prompts/node/panel/binaryFileHexdump.tsx
13405 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 { BasePromptElementProps, PromptElement, PromptReference } from '@vscode/prompt-tsx';
7
import { IFileSystemService } from '../../../../platform/filesystem/common/fileSystemService';
8
import { formatHexdump, isBinaryContent } from '../../../../util/common/hexdump';
9
import { Schemas } from '../../../../util/vs/base/common/network';
10
import { Uri } from '../../../../vscodeTypes';
11
import { Tag } from '../base/tag';
12
import { CodeBlock } from './safeElements';
13
14
export interface BinaryFileData {
15
readonly data: Uint8Array;
16
}
17
18
export interface HexdumpIfBinaryOptions {
19
/** If provided, files already open as text documents are assumed to be text and skipped. */
20
readonly openTextDocuments?: readonly { readonly uri: Uri }[];
21
}
22
23
// Known binary extensions that don't trip the usual nul-byte detection
24
const knownBinaryFileExtensions = new Set([
25
'.pdf',
26
]);
27
28
/**
29
* Reads a file and returns its raw bytes if the content is binary.
30
* Returns `undefined` for text files, notebook cell URIs, or files already open
31
* as text documents, so callers can fall through to normal text handling.
32
*/
33
export async function hexdumpIfBinary(fileService: IFileSystemService, uri: Uri, options?: HexdumpIfBinaryOptions): Promise<BinaryFileData | undefined> {
34
if (uri.scheme === Schemas.vscodeNotebookCell || uri.scheme === Schemas.vscodeNotebookCellOutput) {
35
return undefined;
36
}
37
38
if (options?.openTextDocuments?.some(doc => doc.uri.toString() === uri.toString())) {
39
return undefined;
40
}
41
42
try {
43
const buffer = await fileService.readFile(uri);
44
const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
45
const extDot = uri.path.lastIndexOf('.');
46
const ext = extDot >= 0 ? uri.path.substring(extDot).toLowerCase() : '';
47
if (isBinaryContent(data) || knownBinaryFileExtensions.has(ext)) {
48
return { data };
49
}
50
} catch {
51
// fall through
52
}
53
return undefined;
54
}
55
56
export interface BinaryFileHexdumpProps extends BasePromptElementProps {
57
uri: Uri;
58
data: Uint8Array;
59
startByte?: number;
60
endByte?: number;
61
variableName?: string;
62
description?: string;
63
omitReferences?: boolean;
64
}
65
66
const MAX_HEXDUMP_BYTES = 512;
67
68
export class BinaryFileHexdump extends PromptElement<BinaryFileHexdumpProps> {
69
override async render() {
70
const { uri, data, startByte = 0, endByte = startByte + 128 } = this.props;
71
let start = startByte ?? 0;
72
let end = endByte ?? data.length;
73
if (start > end) {
74
[end, start] = [start, end];
75
}
76
start = Math.max(0, start);
77
end = Math.min(end, data.length, start + MAX_HEXDUMP_BYTES);
78
79
const truncated = start !== (startByte ?? 0) || end !== (endByte ?? data.length);
80
const hexdump = formatHexdump(data, start, end - start);
81
const references = this.props.omitReferences ? undefined : [new PromptReference(this.props.variableName ? { variableName: this.props.variableName, value: uri } : uri)];
82
83
return (
84
<Tag name='attachment' attrs={{ id: this.props.variableName, startByte: start, endByte: end, totalSize: data.length, truncated, description: this.props.description }}>
85
<CodeBlock uri={uri} references={references} code={hexdump} languageId='' fence='' />
86
</Tag>
87
);
88
}
89
}
90
91