-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathresolveMemoryFileUriTool.tsx
More file actions
74 lines (63 loc) · 3.09 KB
/
resolveMemoryFileUriTool.tsx
File metadata and controls
74 lines (63 loc) · 3.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import type * as vscode from 'vscode';
import { IVSCodeExtensionContext } from '../../../platform/extContext/common/extensionContext';
import { URI } from '../../../util/vs/base/common/uri';
import { LanguageModelTextPart, LanguageModelToolResult } from '../../../vscodeTypes';
import { ToolName } from '../common/toolNames';
import { ICopilotTool, ToolRegistry } from '../common/toolsRegistry';
import { extractSessionId } from './memoryTool';
const MEMORY_BASE_DIR = 'memory-tool/memories';
interface IResolveMemoryFileUriParams {
readonly path: string;
}
export class ResolveMemoryFileUriTool implements ICopilotTool<IResolveMemoryFileUriParams> {
public static toolName = ToolName.ResolveMemoryFileUri;
constructor(
@IVSCodeExtensionContext private readonly _extensionContext: vscode.ExtensionContext,
) { }
async invoke(options: vscode.LanguageModelToolInvocationOptions<IResolveMemoryFileUriParams>, _token: vscode.CancellationToken): Promise<vscode.LanguageModelToolResult> {
const memoryPath = options.input.path;
if (!memoryPath || !memoryPath.startsWith('/memories/')) {
throw new Error('Path must start with /memories/');
}
if (memoryPath.includes('..')) {
throw new Error('Path traversal is not allowed');
}
const segments = memoryPath.split('/').filter(s => s.length > 0);
const sessionResource = options.chatSessionResource?.toString();
let resolved: URI;
if (memoryPath.startsWith('/memories/session/') || memoryPath === '/memories/session') {
const storageUri = this._extensionContext.storageUri;
if (!storageUri) {
throw new Error('No workspace storage available');
}
const relativeSegments = segments.slice(2);
const baseUri = URI.from(storageUri);
if (sessionResource) {
const sessionId = extractSessionId(sessionResource);
resolved = URI.joinPath(baseUri, MEMORY_BASE_DIR, sessionId, ...relativeSegments);
} else {
resolved = URI.joinPath(baseUri, MEMORY_BASE_DIR, ...relativeSegments);
}
} else if (memoryPath.startsWith('/memories/repo/') || memoryPath === '/memories/repo') {
const storageUri = this._extensionContext.storageUri;
if (!storageUri) {
throw new Error('No workspace storage available');
}
const relativeSegments = segments.slice(2);
resolved = URI.joinPath(URI.from(storageUri), MEMORY_BASE_DIR, 'repo', ...relativeSegments);
} else {
const globalStorageUri = this._extensionContext.globalStorageUri;
if (!globalStorageUri) {
throw new Error('No global storage available');
}
const relativeSegments = segments.slice(1);
resolved = URI.joinPath(globalStorageUri, MEMORY_BASE_DIR, ...relativeSegments);
}
return new LanguageModelToolResult([new LanguageModelTextPart(resolved.toString())]);
}
}
ToolRegistry.registerTool(ResolveMemoryFileUriTool);