Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/chat/common/chatResponseResourceFileSystemProvider.ts
3296 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 { decodeBase64, VSBuffer } from '../../../../base/common/buffer.js';
7
import { Event } from '../../../../base/common/event.js';
8
import { Disposable, IDisposable } from '../../../../base/common/lifecycle.js';
9
import { newWriteableStream, ReadableStreamEvents } from '../../../../base/common/stream.js';
10
import { URI } from '../../../../base/common/uri.js';
11
import { createFileSystemProviderError, FileSystemProviderCapabilities, FileSystemProviderErrorCode, FileType, IFileService, IFileSystemProviderWithFileAtomicReadCapability, IFileSystemProviderWithFileReadStreamCapability, IFileSystemProviderWithFileReadWriteCapability, IStat } from '../../../../platform/files/common/files.js';
12
import { IWorkbenchContribution } from '../../../common/contributions.js';
13
import { ChatResponseResource } from './chatModel.js';
14
import { IChatService, IChatToolInvocation, IChatToolInvocationSerialized } from './chatService.js';
15
import { isToolResultInputOutputDetails } from './languageModelToolsService.js';
16
17
export class ChatResponseResourceFileSystemProvider extends Disposable implements
18
IWorkbenchContribution,
19
IFileSystemProviderWithFileReadWriteCapability,
20
IFileSystemProviderWithFileAtomicReadCapability,
21
IFileSystemProviderWithFileReadStreamCapability {
22
23
public static readonly ID = 'workbench.contrib.chatResponseResourceFileSystemProvider';
24
25
public readonly onDidChangeCapabilities = Event.None;
26
public readonly onDidChangeFile = Event.None;
27
28
public readonly capabilities: FileSystemProviderCapabilities = FileSystemProviderCapabilities.None
29
| FileSystemProviderCapabilities.Readonly
30
| FileSystemProviderCapabilities.PathCaseSensitive
31
| FileSystemProviderCapabilities.FileReadStream
32
| FileSystemProviderCapabilities.FileAtomicRead
33
| FileSystemProviderCapabilities.FileReadWrite;
34
35
constructor(
36
@IChatService private readonly chatService: IChatService,
37
@IFileService private readonly _fileService: IFileService
38
) {
39
super();
40
this._register(this._fileService.registerProvider(ChatResponseResource.scheme, this));
41
}
42
43
readFile(resource: URI): Promise<Uint8Array> {
44
return Promise.resolve(this.lookupURI(resource));
45
}
46
47
readFileStream(resource: URI): ReadableStreamEvents<Uint8Array> {
48
const stream = newWriteableStream<Uint8Array>(data => VSBuffer.concat(data.map(data => VSBuffer.wrap(data))).buffer);
49
Promise.resolve(this.lookupURI(resource)).then(v => stream.end(v));
50
return stream;
51
}
52
53
async stat(resource: URI): Promise<IStat> {
54
const r = await this.lookupURI(resource);
55
return {
56
type: FileType.File,
57
ctime: 0,
58
mtime: 0,
59
size: r.length,
60
};
61
}
62
63
delete(): Promise<void> {
64
throw createFileSystemProviderError('fs is readonly', FileSystemProviderErrorCode.NoPermissions);
65
}
66
67
watch(): IDisposable {
68
return Disposable.None;
69
}
70
71
mkdir(): Promise<void> {
72
throw createFileSystemProviderError('fs is readonly', FileSystemProviderErrorCode.NoPermissions);
73
}
74
75
readdir(): Promise<[string, FileType][]> {
76
return Promise.resolve([]);
77
}
78
79
rename(): Promise<void> {
80
throw createFileSystemProviderError('fs is readonly', FileSystemProviderErrorCode.NoPermissions);
81
}
82
83
writeFile(): Promise<void> {
84
throw createFileSystemProviderError('fs is readonly', FileSystemProviderErrorCode.NoPermissions);
85
}
86
87
private lookupURI(uri: URI): Uint8Array | Promise<Uint8Array> {
88
const parsed = ChatResponseResource.parseUri(uri);
89
if (!parsed) {
90
throw createFileSystemProviderError(`File not found`, FileSystemProviderErrorCode.FileNotFound);
91
}
92
const { sessionId, requestId, toolCallId } = parsed;
93
const result = this.chatService.getSession(sessionId)
94
?.getRequests()
95
.find(r => r.id === requestId)
96
?.response?.entireResponse.value
97
.find((r): r is IChatToolInvocation | IChatToolInvocationSerialized => (r.kind === 'toolInvocation' || r.kind === 'toolInvocationSerialized') && r.toolCallId === toolCallId);
98
99
if (!result) {
100
throw createFileSystemProviderError(`File not found`, FileSystemProviderErrorCode.FileNotFound);
101
}
102
103
if (!isToolResultInputOutputDetails(result.resultDetails)) {
104
throw createFileSystemProviderError(`Tool does not have I/O`, FileSystemProviderErrorCode.FileNotFound);
105
}
106
107
const part = result.resultDetails.output.at(parsed.index);
108
if (!part) {
109
throw createFileSystemProviderError(`Tool does not have part`, FileSystemProviderErrorCode.FileNotFound);
110
}
111
112
if (part.type === 'ref') {
113
return this._fileService.readFile(part.uri).then(r => r.value.buffer);
114
}
115
116
return part.isText ? new TextEncoder().encode(part.value) : decodeBase64(part.value).buffer;
117
}
118
}
119
120