Merge branch 'tyriar/291275' into copilot/fix-github-actions-workflow-again

This commit is contained in:
Daniel Imms authored and GitHub committed 2026-02-11 13:54:22 -08:00
commit 73c3b1444f
6 files changed
+75 -3

No files matched your search

+1
View File
@@ -94,6 +94,7 @@
"**/*.snap": true,
},
// --- TypeScript ---
"typescript.experimental.useTsgo": true,
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.preferences.importModuleSpecifier": "relative",
"typescript.preferences.quoteStyle": "single",
Binary file not shown.
@@ -105,6 +105,11 @@ export interface ITipDefinition {
* The tip won't be shown if the tool it describes has already been used.
*/
readonly excludeWhenToolsInvoked?: string[];
/**
* Tool set reference names where at least one must be registered for the tip to be eligible.
* If none of the listed tool sets are registered, the tip is not shown.
*/
readonly requiresAnyToolSetRegistered?: string[];
/**
* If set, exclude this tip when prompt files of the specified type exist in the workspace.
*/
@@ -205,6 +210,7 @@ const TIP_CATALOG: ITipDefinition[] = [
ContextKeyExpr.notEquals('gitOpenRepositoryCount', '0'),
),
excludeWhenToolsInvoked: ['github-pull-request_doSearch', 'github-pull-request_issue_fetch', 'github-pull-request_formSearchQuery'],
requiresAnyToolSetRegistered: ['github', 'github-pull-request'],
},
{
id: 'tip.subagents',
@@ -271,7 +277,7 @@ export class TipEligibilityTracker extends Disposable {
@ICommandService commandService: ICommandService,
@IStorageService private readonly _storageService: IStorageService,
@IPromptsService private readonly _promptsService: IPromptsService,
@ILanguageModelToolsService languageModelToolsService: ILanguageModelToolsService,
@ILanguageModelToolsService private readonly _languageModelToolsService: ILanguageModelToolsService,
@ILogService private readonly _logService: ILogService,
) {
super();
@@ -335,7 +341,7 @@ export class TipEligibilityTracker extends Disposable {
// --- Set up tool listener (auto-disposes when all seen) -----------------
if (this._pendingTools.size > 0) {
this._toolListener.value = languageModelToolsService.onDidInvokeTool(e => {
this._toolListener.value = this._languageModelToolsService.onDidInvokeTool(e => {
if (this._pendingTools.has(e.toolId)) {
this._invokedTools.add(e.toolId);
this._persistSet(TipEligibilityTracker._TOOLS_STORAGE_KEY, this._invokedTools);
@@ -428,6 +434,13 @@ export class TipEligibilityTracker extends Disposable {
this._logService.debug('#ChatTips: tip excluded because prompt files exist', tip.id);
return true;
}
if (tip.requiresAnyToolSetRegistered) {
const hasAny = tip.requiresAnyToolSetRegistered.some(name => this._languageModelToolsService.getToolSetByName(name));
if (!hasAny) {
this._logService.debug('#ChatTips: tip excluded because no required tool sets are registered', tip.id);
return true;
}
}
return false;
}
@@ -613,6 +613,47 @@ suite('ChatTipService', () => {
assert.strictEqual(tracker.isExcluded(tip), false, 'Should not be excluded when no skill files exist');
});
test('excludes tip when requiresAnyToolSetRegistered tool sets are not registered', () => {
const tip: ITipDefinition = {
id: 'tip.githubRepo',
message: 'test',
requiresAnyToolSetRegistered: ['github', 'github-pull-request'],
};
const tracker = testDisposables.add(new TipEligibilityTracker(
[tip],
{ onDidExecuteCommand: Event.None, onWillExecuteCommand: Event.None } as Partial<ICommandService> as ICommandService,
storageService,
createMockPromptsService() as IPromptsService,
createMockToolsService(),
new NullLogService(),
));
assert.strictEqual(tracker.isExcluded(tip), true, 'Should be excluded when no required tool sets are registered');
});
test('does not exclude tip when at least one requiresAnyToolSetRegistered tool set is registered', () => {
const mockToolsService = createMockToolsService();
mockToolsService.addRegisteredToolSetName('github');
const tip: ITipDefinition = {
id: 'tip.githubRepo',
message: 'test',
requiresAnyToolSetRegistered: ['github', 'github-pull-request'],
};
const tracker = testDisposables.add(new TipEligibilityTracker(
[tip],
{ onDidExecuteCommand: Event.None, onWillExecuteCommand: Event.None } as Partial<ICommandService> as ICommandService,
storageService,
createMockPromptsService() as IPromptsService,
mockToolsService,
new NullLogService(),
));
assert.strictEqual(tracker.isExcluded(tip), false, 'Should not be excluded when at least one required tool set is registered');
});
test('re-checks agent file exclusion when onDidChangeCustomAgents fires', async () => {
const agentChangeEmitter = testDisposables.add(new Emitter<void>());
let agentFiles: IPromptPath[] = [];
@@ -27,6 +27,9 @@ export class MockLanguageModelToolsService extends Disposable implements ILangua
private readonly _onDidInvokeTool = this._register(new Emitter<IToolInvokedEvent>());
private readonly _registeredToolIds = new Set<string>();
private readonly _registeredToolSetNames = new Set<string>();
constructor() {
super();
}
@@ -88,7 +91,14 @@ export class MockLanguageModelToolsService extends Disposable implements ILangua
return [];
}
addRegisteredToolId(id: string): void {
this._registeredToolIds.add(id);
}
getTool(id: string): IToolData | undefined {
if (this._registeredToolIds.has(id)) {
return { id, source: ToolDataSource.Internal, displayName: id, modelDescription: id };
}
return undefined;
}
@@ -125,7 +135,14 @@ export class MockLanguageModelToolsService extends Disposable implements ILangua
return [];
}
addRegisteredToolSetName(name: string): void {
this._registeredToolSetNames.add(name);
}
getToolSetByName(name: string): IToolSet | undefined {
if (this._registeredToolSetNames.has(name)) {
return { id: name, referenceName: name, icon: ThemeIcon.fromId(Codicon.tools.id), source: ToolDataSource.Internal, getTools: () => [] };
}
return undefined;
}
@@ -342,7 +342,7 @@ const terminalConfiguration: IStringDictionary<IConfigurationPropertySchema> = {
},
[TerminalSettingId.TerminalTitle]: {
'type': 'string',
'default': '${process}',
'default': '${sequence}',
'markdownDescription': terminalTitle
},
[TerminalSettingId.TerminalDescription]: {