Skip to content

Commit b28f1e9

Browse files
committed
use global storage
1 parent d5599f9 commit b28f1e9

File tree

4 files changed

+61
-28
lines changed

4 files changed

+61
-28
lines changed

vscode/src/createProject.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export async function initProjectCreator(context: vscode.ExtensionContext) {
6565
}
6666

6767
// Call updateCopilotInstructions to update the Copilot instructions file
68-
await updateCopilotInstructions("Project", context.extensionUri);
68+
await updateCopilotInstructions("Project", context);
6969
},
7070
),
7171
);

vscode/src/extension.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ export async function activate(
8888
await initProjectCreator(context);
8989
registerCopilotPanel(context);
9090
registerLanguageModelTools(context);
91+
// fire-and-forget
9192
registerGhCopilotInstructionsCommand(context);
9293

9394
log.info("Q# extension activated.");

vscode/src/gh-copilot/instructions.ts

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ import { EventType, sendTelemetryEvent, UserFlowStatus } from "../telemetry";
1111
*/
1212
export async function updateCopilotInstructions(
1313
trigger: "Command" | "Project" | "Activation" | "ChatToolCall",
14-
extensionUri: vscode.Uri,
14+
context: vscode.ExtensionContext,
1515
): Promise<string | undefined> {
16+
const globalStateUri = context.globalStorageUri;
1617
const userInvoked = trigger === "Command";
1718

18-
if (isExtensionInstructionsConfigured(extensionUri)) {
19+
if (isExtensionInstructionsConfigured(globalStateUri)) {
1920
if (userInvoked) {
2021
// fire-and-forget
2122
showInfoMessage("Copilot instructions for Q# are already configured.", {
@@ -53,7 +54,7 @@ export async function updateCopilotInstructions(
5354
}
5455

5556
try {
56-
await addExtensionInstructionsToUserConfig(extensionUri);
57+
await addExtensionInstructionsToUserConfig(globalStateUri);
5758
const removedOldInstructions = await removeOldQSharpCopilotInstructions();
5859

5960
// fire-and-forget
@@ -93,8 +94,10 @@ export async function updateCopilotInstructions(
9394
* Checks the user's instructionsFilesLocations setting to see if
9495
* our extension's instructions directory is already included.
9596
*/
96-
function isExtensionInstructionsConfigured(extensionUri: vscode.Uri): boolean {
97-
const extensionInstructionsDir = getExtensionInstructionsDir(extensionUri);
97+
function isExtensionInstructionsConfigured(
98+
globalStateUri: vscode.Uri,
99+
): boolean {
100+
const extensionInstructionsDir = getExtensionInstructionsDir(globalStateUri);
98101
const instructionsLocations = getConfiguredInstructionsFilesLocations();
99102

100103
// Check if our directory is in the map as a key and it's enabled (true)
@@ -109,10 +112,10 @@ function isExtensionInstructionsConfigured(extensionUri: vscode.Uri): boolean {
109112
* our extension's instructions directory.
110113
*/
111114
async function addExtensionInstructionsToUserConfig(
112-
extensionUri: vscode.Uri,
115+
globalStateUri: vscode.Uri,
113116
): Promise<void> {
114117
const instructionsLocations = getConfiguredInstructionsFilesLocations();
115-
const extensionInstructionsDir = getExtensionInstructionsDir(extensionUri);
118+
const extensionInstructionsDir = getExtensionInstructionsDir(globalStateUri);
116119

117120
// Only add the extension's chat-instructions directory
118121
// if it's not already configured or if it's disabled
@@ -149,9 +152,9 @@ function getConfiguredInstructionsFilesLocations(): Record<string, boolean> {
149152
*
150153
* TODO: create GitHub issue to track how we handle this in the browser.
151154
*/
152-
function getExtensionInstructionsDir(extensionUri: vscode.Uri): string {
155+
function getExtensionInstructionsDir(globalStateUri: vscode.Uri): string {
153156
const instructionsUri = vscode.Uri.joinPath(
154-
extensionUri,
157+
globalStateUri,
155158
"chat-instructions",
156159
);
157160

@@ -298,37 +301,66 @@ function getOldInstructionsFileLocation(
298301
);
299302
}
300303

304+
async function copyInstructionsFileToGlobalStorage(
305+
context: vscode.ExtensionContext,
306+
) {
307+
const source = vscode.Uri.joinPath(
308+
context.extensionUri,
309+
"chat-instructions",
310+
"qsharp.instructions.md",
311+
);
312+
313+
const target = vscode.Uri.joinPath(
314+
context.globalStorageUri,
315+
"chat-instructions",
316+
"qsharp.instructions.md",
317+
);
318+
319+
try {
320+
await vscode.workspace.fs.copy(source, target, { overwrite: true });
321+
return true;
322+
} catch {
323+
log.warn(
324+
`Error copying Q# instructions file from ${source.toString()} to ${target.toString()}`,
325+
);
326+
return false;
327+
}
328+
}
329+
301330
/**
302331
* Registers the command to configure GitHub Copilot to use Q# coding instructions.
303332
* This updates the chat.instructionsFilesLocations setting to include the extension's
304333
* chat-instructions directory, rather than creating a file in the user's workspace.
305334
*/
306-
export function registerGhCopilotInstructionsCommand(
335+
export async function registerGhCopilotInstructionsCommand(
307336
context: vscode.ExtensionContext,
308337
) {
309338
context.subscriptions.push(
310339
vscode.commands.registerCommand(
311340
"qsharp-vscode.updateCopilotInstructions",
312-
() => updateCopilotInstructions("Command", context.extensionUri),
341+
() => updateCopilotInstructions("Command", context),
313342
),
314343
);
315344

345+
// Copy the instructions file to the global storage location
346+
// The global storage location is stable across versions,
347+
// but our instructions content may change from version to version.
348+
await copyInstructionsFileToGlobalStorage(context);
349+
316350
// Also do a one-time prompt at activation time
317351
if (
318352
context.globalState.get<boolean>(
319-
"showUpdateCopilotInstructionsPromptAtStartup1",
353+
"showUpdateCopilotInstructionsPromptAtStartup2", // TODO
320354
true,
321355
)
322356
) {
323-
updateCopilotInstructions("Activation", context.extensionUri).then(
324-
(response) => {
325-
if (response === "Don't show again") {
326-
context.globalState.update(
327-
"showUpdateCopilotInstructionsPromptAtStartup1",
328-
false,
329-
);
330-
}
331-
},
332-
);
357+
updateCopilotInstructions("Activation", context).then((response) => {
358+
if (response === "Don't show again") {
359+
context.globalState.update(
360+
"showUpdateCopilotInstructionsPromptAtStartup2", // TODO
361+
false,
362+
);
363+
}
364+
});
333365
}
334366
}

vscode/src/gh-copilot/tools.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,19 @@ export function registerLanguageModelTools(context: vscode.ExtensionContext) {
9696
qsharpTools = new QSharpTools(context.extensionUri);
9797
for (const { name, tool: fn, confirm: confirmFn } of toolDefinitions) {
9898
context.subscriptions.push(
99-
vscode.lm.registerTool(name, tool(context.extensionUri, fn, confirmFn)),
99+
vscode.lm.registerTool(name, tool(context, fn, confirmFn)),
100100
);
101101
}
102102
}
103103

104104
function tool(
105-
extensionUri: vscode.Uri,
105+
context: vscode.ExtensionContext,
106106
toolFn: (input: any) => Promise<any>,
107107
confirmFn?: (input: any) => vscode.PreparedToolInvocation,
108108
): vscode.LanguageModelTool<any> {
109109
return {
110110
invoke: (options: vscode.LanguageModelToolInvocationOptions<any>) =>
111-
invokeTool(extensionUri, options.input, toolFn),
111+
invokeTool(context, options.input, toolFn),
112112
prepareInvocation:
113113
confirmFn &&
114114
((options: vscode.LanguageModelToolInvocationPrepareOptions<any>) =>
@@ -117,11 +117,11 @@ function tool(
117117
}
118118

119119
async function invokeTool(
120-
extensionUri: vscode.Uri,
120+
context: vscode.ExtensionContext,
121121
input: any,
122122
toolFn: (input: any) => Promise<any>,
123123
): Promise<vscode.LanguageModelToolResult> {
124-
updateCopilotInstructions("ChatToolCall", extensionUri);
124+
updateCopilotInstructions("ChatToolCall", context);
125125

126126
const result = await toolFn(input);
127127

0 commit comments

Comments
 (0)