Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/api/browser/mainThreadLanguageModelTools.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 { CancellationToken } from '../../../base/common/cancellation.js';
7
import { Disposable, DisposableMap } from '../../../base/common/lifecycle.js';
8
import { revive } from '../../../base/common/marshalling.js';
9
import { CountTokensCallback, ILanguageModelToolsService, IToolInvocation, IToolProgressStep, IToolResult, ToolProgress, toolResultHasBuffers } from '../../contrib/chat/common/languageModelToolsService.js';
10
import { IExtHostContext, extHostNamedCustomer } from '../../services/extensions/common/extHostCustomers.js';
11
import { Dto, SerializableObjectWithBuffers } from '../../services/extensions/common/proxyIdentifier.js';
12
import { ExtHostContext, ExtHostLanguageModelToolsShape, IToolDataDto, MainContext, MainThreadLanguageModelToolsShape } from '../common/extHost.protocol.js';
13
14
@extHostNamedCustomer(MainContext.MainThreadLanguageModelTools)
15
export class MainThreadLanguageModelTools extends Disposable implements MainThreadLanguageModelToolsShape {
16
17
private readonly _proxy: ExtHostLanguageModelToolsShape;
18
private readonly _tools = this._register(new DisposableMap<string>());
19
private readonly _runningToolCalls = new Map</* call ID */string, {
20
countTokens: CountTokensCallback;
21
progress: ToolProgress;
22
}>();
23
24
constructor(
25
extHostContext: IExtHostContext,
26
@ILanguageModelToolsService private readonly _languageModelToolsService: ILanguageModelToolsService,
27
) {
28
super();
29
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostLanguageModelTools);
30
31
this._register(this._languageModelToolsService.onDidChangeTools(e => this._proxy.$onDidChangeTools(this.getToolDtos())));
32
}
33
34
private getToolDtos(): IToolDataDto[] {
35
return Array.from(this._languageModelToolsService.getTools())
36
.map(tool => ({
37
id: tool.id,
38
displayName: tool.displayName,
39
toolReferenceName: tool.toolReferenceName,
40
tags: tool.tags,
41
userDescription: tool.userDescription,
42
modelDescription: tool.modelDescription,
43
inputSchema: tool.inputSchema,
44
source: tool.source,
45
} satisfies IToolDataDto));
46
}
47
48
async $getTools(): Promise<IToolDataDto[]> {
49
return this.getToolDtos();
50
}
51
52
async $invokeTool(dto: IToolInvocation, token?: CancellationToken): Promise<Dto<IToolResult> | SerializableObjectWithBuffers<Dto<IToolResult>>> {
53
const result = await this._languageModelToolsService.invokeTool(
54
dto,
55
(input, token) => this._proxy.$countTokensForInvocation(dto.callId, input, token),
56
token ?? CancellationToken.None,
57
);
58
59
// Don't return extra metadata to EH
60
const out: Dto<IToolResult> = { content: result.content };
61
return toolResultHasBuffers(result) ? new SerializableObjectWithBuffers(out) : out;
62
}
63
64
$acceptToolProgress(callId: string, progress: IToolProgressStep): void {
65
this._runningToolCalls.get(callId)?.progress.report(progress);
66
}
67
68
$countTokensForInvocation(callId: string, input: string, token: CancellationToken): Promise<number> {
69
const fn = this._runningToolCalls.get(callId);
70
if (!fn) {
71
throw new Error(`Tool invocation call ${callId} not found`);
72
}
73
74
return fn.countTokens(input, token);
75
}
76
77
$registerTool(id: string): void {
78
const disposable = this._languageModelToolsService.registerToolImplementation(
79
id,
80
{
81
invoke: async (dto, countTokens, progress, token) => {
82
try {
83
this._runningToolCalls.set(dto.callId, { countTokens, progress });
84
const resultSerialized = await this._proxy.$invokeTool(dto, token);
85
const resultDto: Dto<IToolResult> = resultSerialized instanceof SerializableObjectWithBuffers ? resultSerialized.value : resultSerialized;
86
return revive<IToolResult>(resultDto);
87
} finally {
88
this._runningToolCalls.delete(dto.callId);
89
}
90
},
91
prepareToolInvocation: (context, token) => this._proxy.$prepareToolInvocation(id, context, token),
92
});
93
this._tools.set(id, disposable);
94
}
95
96
$unregisterTool(name: string): void {
97
this._tools.deleteAndDispose(name);
98
}
99
}
100
101