Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/agents/vscode-node/githubOrgInstructionsProvider.ts
13399 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 vscode from 'vscode';
7
import { INSTRUCTION_FILE_EXTENSION, PromptsType } from '../../../platform/customInstructions/common/promptTypes';
8
import { IOctoKitService } from '../../../platform/github/common/githubService';
9
import { ILogService } from '../../../platform/log/common/logService';
10
import { Disposable } from '../../../util/vs/base/common/lifecycle';
11
import { IGitHubOrgChatResourcesService } from './githubOrgChatResourcesService';
12
13
const INSTRUCTIONS_BASE_FILE_NAME = 'default';
14
const REFRESH_INTERVAL_MS = 2 * 60 * 1000;
15
16
export class GitHubOrgInstructionsProvider extends Disposable implements vscode.ChatInstructionsProvider {
17
18
private readonly _onDidChangeInstructions = this._register(new vscode.EventEmitter<void>());
19
readonly onDidChangeInstructions = this._onDidChangeInstructions.event;
20
21
constructor(
22
@ILogService private readonly logService: ILogService,
23
@IOctoKitService private readonly octoKitService: IOctoKitService,
24
@IGitHubOrgChatResourcesService private readonly githubOrgChatResourcesService: IGitHubOrgChatResourcesService,
25
) {
26
super();
27
28
// Set up polling with provider-specific interval
29
this._register(this.githubOrgChatResourcesService.startPolling(REFRESH_INTERVAL_MS, this.pollInstructions.bind(this)));
30
}
31
32
async provideInstructions(
33
_options: unknown,
34
token: vscode.CancellationToken
35
): Promise<vscode.ChatResource[]> {
36
try {
37
const orgId = await this.githubOrgChatResourcesService.getPreferredOrganizationName();
38
if (!orgId) {
39
this.logService.trace('[GitHubOrgInstructionsProvider] No organization available for providing agents');
40
return [];
41
}
42
43
if (token.isCancellationRequested) {
44
this.logService.trace('[GitHubOrgInstructionsProvider] provideCustomAgents was cancelled');
45
return [];
46
}
47
48
return await this.githubOrgChatResourcesService.listCachedFiles(PromptsType.instructions, orgId);
49
} catch (error) {
50
this.logService.error(`[GitHubOrgInstructionsProvider] Error reading from cache: ${error}`);
51
return [];
52
}
53
}
54
55
private async pollInstructions(orgId: string): Promise<void> {
56
try {
57
const instructions = await this.octoKitService.getOrgCustomInstructions(orgId, {});
58
if (!instructions) {
59
await this.githubOrgChatResourcesService.clearCache(PromptsType.instructions, orgId);
60
this.logService.trace(`[GitHubOrgInstructionsProvider] No custom instructions found for org ${orgId}`);
61
return;
62
}
63
64
// Write the instructions to cache
65
const fileName = `${INSTRUCTIONS_BASE_FILE_NAME}${INSTRUCTION_FILE_EXTENSION}`;
66
const content = `---
67
applyTo: '**'
68
---
69
${instructions}`;
70
const contentChanged = await this.githubOrgChatResourcesService.writeCacheFile(PromptsType.instructions, orgId, fileName, content, { checkForChanges: true });
71
72
// If no changes, we can return
73
if (!contentChanged) {
74
this.logService.trace(`[GitHubOrgInstructionsProvider] No changes detected in cache for org ${orgId}`);
75
return;
76
}
77
78
// Otherwise, fire event to notify consumers that instructions have changed
79
this._onDidChangeInstructions.fire();
80
} catch (error) {
81
this.logService.error(`[GitHubOrgInstructionsProvider] Error polling for instructions: ${error}`);
82
}
83
}
84
}
85
86