mirror of
https://github.com/microsoft/vscode-extension-samples.git
synced 2026-04-27 16:55:44 +08:00
update
This commit is contained in:
104
chat-prompt-files-sample/src/chatResourceFileSystem.ts
Normal file
104
chat-prompt-files-sample/src/chatResourceFileSystem.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
/**
|
||||
* A virtual file system provider for serving dynamically generated chat resource content.
|
||||
* Resources are registered with a URI and content generator function, allowing
|
||||
* content to be generated on-demand when VS Code reads the file.
|
||||
*/
|
||||
export class ChatResourceFileSystemProvider implements vscode.FileSystemProvider {
|
||||
static readonly scheme = 'my-chat-resource';
|
||||
|
||||
private readonly _contentGenerators = new Map<string, () => string>();
|
||||
private readonly _onDidChangeFile = new vscode.EventEmitter<vscode.FileChangeEvent[]>();
|
||||
readonly onDidChangeFile = this._onDidChangeFile.event;
|
||||
|
||||
/**
|
||||
* Register a resource with a content generator function.
|
||||
* @param path The path portion of the URI (e.g., 'agents/workspace-helper.agent.md')
|
||||
* @param contentGenerator A function that generates the content on demand
|
||||
* @returns The full URI for the resource
|
||||
*/
|
||||
registerResource(path: string, contentGenerator: () => string): vscode.Uri {
|
||||
this._contentGenerators.set(path, contentGenerator);
|
||||
return vscode.Uri.parse(`${ChatResourceFileSystemProvider.scheme}:/${path}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify that a resource has changed, triggering VS Code to re-read the content.
|
||||
* @param path The path of the resource that changed
|
||||
*/
|
||||
notifyResourceChanged(path: string): void {
|
||||
const uri = vscode.Uri.parse(`${ChatResourceFileSystemProvider.scheme}:/${path}`);
|
||||
this._onDidChangeFile.fire([{ type: vscode.FileChangeType.Changed, uri }]);
|
||||
}
|
||||
|
||||
// FileSystemProvider implementation
|
||||
|
||||
watch(): vscode.Disposable {
|
||||
return new vscode.Disposable(() => { });
|
||||
}
|
||||
|
||||
stat(uri: vscode.Uri): vscode.FileStat {
|
||||
const path = uri.path.substring(1); // Remove leading /
|
||||
if (!this._contentGenerators.has(path)) {
|
||||
throw vscode.FileSystemError.FileNotFound(uri);
|
||||
}
|
||||
return {
|
||||
type: vscode.FileType.File,
|
||||
ctime: Date.now(),
|
||||
mtime: Date.now(),
|
||||
size: 0 // Size is not known until content is generated
|
||||
};
|
||||
}
|
||||
|
||||
readDirectory(): [string, vscode.FileType][] {
|
||||
return [];
|
||||
}
|
||||
|
||||
createDirectory(): void {
|
||||
throw vscode.FileSystemError.NoPermissions('Read-only file system');
|
||||
}
|
||||
|
||||
readFile(uri: vscode.Uri): Uint8Array {
|
||||
const path = uri.path.substring(1); // Remove leading /
|
||||
const generator = this._contentGenerators.get(path);
|
||||
if (!generator) {
|
||||
throw vscode.FileSystemError.FileNotFound(uri);
|
||||
}
|
||||
const content = generator();
|
||||
return new TextEncoder().encode(content);
|
||||
}
|
||||
|
||||
writeFile(): void {
|
||||
throw vscode.FileSystemError.NoPermissions('Read-only file system');
|
||||
}
|
||||
|
||||
delete(): void {
|
||||
throw vscode.FileSystemError.NoPermissions('Read-only file system');
|
||||
}
|
||||
|
||||
rename(): void {
|
||||
throw vscode.FileSystemError.NoPermissions('Read-only file system');
|
||||
}
|
||||
}
|
||||
|
||||
// Singleton instance
|
||||
let _instance: ChatResourceFileSystemProvider | undefined;
|
||||
|
||||
/**
|
||||
* Get the singleton ChatResourceFileSystemProvider instance.
|
||||
* Creates and registers it if it doesn't exist.
|
||||
*/
|
||||
export function getChatResourceFileSystem(context: vscode.ExtensionContext): ChatResourceFileSystemProvider {
|
||||
if (!_instance) {
|
||||
_instance = new ChatResourceFileSystemProvider();
|
||||
context.subscriptions.push(
|
||||
vscode.workspace.registerFileSystemProvider(
|
||||
ChatResourceFileSystemProvider.scheme,
|
||||
_instance,
|
||||
{ isReadonly: true }
|
||||
)
|
||||
);
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
@ -1,20 +1,15 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { getChatResourceFileSystem } from './chatResourceFileSystem';
|
||||
|
||||
const AGENT_PATH = 'agents/workspace-helper.agent.md';
|
||||
|
||||
export function createCustomAgentProvider(context: vscode.ExtensionContext): vscode.ChatCustomAgentProvider {
|
||||
const fs = getChatResourceFileSystem(context);
|
||||
const agentUri = fs.registerResource(AGENT_PATH, generateDynamicAgentContent);
|
||||
|
||||
export function createCustomAgentProvider(_context: vscode.ExtensionContext): vscode.CustomAgentProvider {
|
||||
return {
|
||||
label: 'Dynamic Workspace Agent Provider',
|
||||
async provideCustomAgents(_options, _token) {
|
||||
const agents: vscode.CustomAgentChatResource[] = [];
|
||||
|
||||
// Dynamic agent with generated content
|
||||
const dynamicContent = generateDynamicAgentContent();
|
||||
|
||||
agents.push(new vscode.CustomAgentChatResource({
|
||||
id: 'workspace-helper',
|
||||
content: dynamicContent
|
||||
}));
|
||||
|
||||
return agents;
|
||||
async provideCustomAgents(_context, _token): Promise<vscode.ChatResource[]> {
|
||||
return [{ uri: agentUri }];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,21 +1,15 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { getChatResourceFileSystem } from './chatResourceFileSystem';
|
||||
|
||||
const INSTRUCTIONS_PATH = 'instructions/workspace-context.instructions.md';
|
||||
|
||||
export function createInstructionsProvider(context: vscode.ExtensionContext): vscode.ChatInstructionsProvider {
|
||||
const fs = getChatResourceFileSystem(context);
|
||||
const instructionsUri = fs.registerResource(INSTRUCTIONS_PATH, generateDynamicInstructions);
|
||||
|
||||
export function createInstructionsProvider(_context: vscode.ExtensionContext): vscode.InstructionsProvider {
|
||||
return {
|
||||
label: 'Dynamic Workspace Instructions Provider',
|
||||
async provideInstructions(_options, _token) {
|
||||
const instructions: vscode.InstructionsChatResource[] = [];
|
||||
|
||||
// Dynamic instructions with current workspace info
|
||||
const dynamicContent = generateDynamicInstructions();
|
||||
|
||||
instructions.push(
|
||||
new vscode.InstructionsChatResource({
|
||||
id: 'workspace-context',
|
||||
content: dynamicContent
|
||||
}));
|
||||
|
||||
return instructions;
|
||||
async provideInstructions(_context, _token): Promise<vscode.ChatResource[]> {
|
||||
return [{ uri: instructionsUri }];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,22 +1,15 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { getChatResourceFileSystem } from './chatResourceFileSystem';
|
||||
|
||||
const PROMPT_PATH = 'prompts/time-aware.prompt.md';
|
||||
|
||||
export function createPromptFileProvider(context: vscode.ExtensionContext): vscode.ChatPromptFileProvider {
|
||||
const fs = getChatResourceFileSystem(context);
|
||||
const promptUri = fs.registerResource(PROMPT_PATH, generateDynamicPrompt);
|
||||
|
||||
export function createPromptFileProvider(_context: vscode.ExtensionContext): vscode.PromptFileProvider {
|
||||
return {
|
||||
label: 'Dynamic Time-Aware Prompt File Provider',
|
||||
async providePromptFiles(_options, _token) {
|
||||
const prompts: vscode.PromptFileChatResource[] = [];
|
||||
|
||||
// Dynamic prompt with time-based content
|
||||
const dynamicContent = generateDynamicPrompt();
|
||||
|
||||
prompts.push(
|
||||
new vscode.PromptFileChatResource({
|
||||
id: 'time-aware',
|
||||
content: dynamicContent
|
||||
})
|
||||
);
|
||||
|
||||
return prompts;
|
||||
async providePromptFiles(_context, _token): Promise<vscode.ChatResource[]> {
|
||||
return [{ uri: promptUri }];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,20 +1,15 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { getChatResourceFileSystem } from './chatResourceFileSystem';
|
||||
|
||||
const SKILL_PATH = 'skills/workspace-analysis/SKILL.md';
|
||||
|
||||
export function createSkillProvider(context: vscode.ExtensionContext): vscode.ChatSkillProvider {
|
||||
const fs = getChatResourceFileSystem(context);
|
||||
const skillUri = fs.registerResource(SKILL_PATH, generateDynamicSkillContent);
|
||||
|
||||
export function createSkillProvider(_context: vscode.ExtensionContext): vscode.SkillProvider {
|
||||
return {
|
||||
label: 'Dynamic Workspace Skills Provider',
|
||||
async provideSkills(_options, _token) {
|
||||
const skills: vscode.SkillChatResource[] = [];
|
||||
|
||||
// Dynamic skill with generated content
|
||||
const dynamicContent = generateDynamicSkillContent();
|
||||
|
||||
skills.push(new vscode.SkillChatResource({
|
||||
id: 'workspace-analysis',
|
||||
content: dynamicContent
|
||||
}));
|
||||
|
||||
return skills;
|
||||
async provideSkills(_context, _token): Promise<vscode.ChatResource[]> {
|
||||
return [{ uri: skillUri }];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user