Implement enhanced CLI list command with detailed reason display and collection counts
Co-authored-by: AstroSteveo <34114851+AstroSteveo@users.noreply.github.com>
This commit is contained in:
parent
88e13bc74e
commit
25e6141857
@ -149,8 +149,16 @@ function handleListCommand(rawArgs) {
|
|||||||
const availableItems = getAllAvailableItems(section);
|
const availableItems = getAllAvailableItems(section);
|
||||||
|
|
||||||
// Count effectively enabled items
|
// Count effectively enabled items
|
||||||
const effectivelyEnabled = Object.values(effectiveStates[section] || {})
|
let effectivelyEnabled;
|
||||||
|
if (section === "collections") {
|
||||||
|
// For collections, count explicitly enabled ones
|
||||||
|
effectivelyEnabled = Object.values(sanitizedConfig[section] || {})
|
||||||
|
.filter(value => value === true).length;
|
||||||
|
} else {
|
||||||
|
// For other sections, count effectively enabled items
|
||||||
|
effectivelyEnabled = Object.values(effectiveStates[section] || {})
|
||||||
.filter(state => state.enabled).length;
|
.filter(state => state.enabled).length;
|
||||||
|
}
|
||||||
|
|
||||||
const { totalCharacters } = calculateSectionFootprint(section, sanitizedConfig[section]);
|
const { totalCharacters } = calculateSectionFootprint(section, sanitizedConfig[section]);
|
||||||
const headingParts = [
|
const headingParts = [
|
||||||
@ -170,20 +178,40 @@ function handleListCommand(rawArgs) {
|
|||||||
|
|
||||||
// Show items with effective state and reason
|
// Show items with effective state and reason
|
||||||
if (section === "collections") {
|
if (section === "collections") {
|
||||||
// Collections show simple enabled/disabled
|
// Collections show simple enabled/disabled with count of effectively enabled items
|
||||||
availableItems.forEach(itemName => {
|
availableItems.forEach(itemName => {
|
||||||
const isEnabled = Boolean(sanitizedConfig[section]?.[itemName]);
|
const isEnabled = Boolean(sanitizedConfig[section]?.[itemName]);
|
||||||
console.log(` [${isEnabled ? "✓" : " "}] ${itemName}`);
|
|
||||||
|
// Count how many items this collection would enable
|
||||||
|
let enabledCount = 0;
|
||||||
|
if (isEnabled) {
|
||||||
|
// Simulate what would happen if only this collection was enabled
|
||||||
|
const testConfig = { collections: { [itemName]: true } };
|
||||||
|
const testEffectiveStates = computeEffectiveItemStates(testConfig);
|
||||||
|
|
||||||
|
for (const sectionName of ["prompts", "instructions", "chatmodes"]) {
|
||||||
|
enabledCount += Object.values(testEffectiveStates[sectionName] || {})
|
||||||
|
.filter(state => state.enabled && state.reason === "collection").length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const countText = isEnabled ? ` (${enabledCount} items effectively enabled)` : "";
|
||||||
|
console.log(` [${isEnabled ? "✓" : " "}] ${itemName}${countText}`);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Other sections show effective state with reason
|
// Other sections show effective state with detailed reason
|
||||||
availableItems.forEach(itemName => {
|
availableItems.forEach(itemName => {
|
||||||
const effectiveState = effectiveStates[section]?.[itemName];
|
const effectiveState = effectiveStates[section]?.[itemName];
|
||||||
if (effectiveState) {
|
if (effectiveState) {
|
||||||
const symbol = effectiveState.enabled ? "✓" : " ";
|
const symbol = effectiveState.enabled ? "✓" : " ";
|
||||||
const reasonText = effectiveState.reason === "explicit"
|
let reasonText = "";
|
||||||
? ` (${effectiveState.reason})`
|
|
||||||
: effectiveState.enabled ? ` (${effectiveState.reason})` : "";
|
if (effectiveState.reason === "explicit") {
|
||||||
|
reasonText = ` (explicit:${effectiveState.enabled})`;
|
||||||
|
} else if (effectiveState.reason === "collection" && effectiveState.collections && effectiveState.collections.length > 0) {
|
||||||
|
reasonText = ` (via:[${effectiveState.collections.join(',')}])`;
|
||||||
|
}
|
||||||
|
|
||||||
console.log(` [${symbol}] ${itemName}${reasonText}`);
|
console.log(` [${symbol}] ${itemName}${reasonText}`);
|
||||||
} else {
|
} else {
|
||||||
console.log(` [ ] ${itemName}`);
|
console.log(` [ ] ${itemName}`);
|
||||||
|
|||||||
@ -203,14 +203,21 @@ function computeEffectiveItemStates(config) {
|
|||||||
chatmodes: {}
|
chatmodes: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build membership maps: Map<itemName, Set<collectionName>> per section for O(1) lookups
|
// Build detailed membership maps: Map<itemName, Set<collectionName>> per section
|
||||||
|
const collectionMemberships = {
|
||||||
|
prompts: new Map(),
|
||||||
|
instructions: new Map(),
|
||||||
|
chatmodes: new Map()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Build simple enabled sets for O(1) lookups
|
||||||
const collectionEnabledItems = {
|
const collectionEnabledItems = {
|
||||||
prompts: new Set(),
|
prompts: new Set(),
|
||||||
instructions: new Set(),
|
instructions: new Set(),
|
||||||
chatmodes: new Set()
|
chatmodes: new Set()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Identify enabled collections per section
|
// Identify enabled collections per section and track memberships
|
||||||
if (config.collections) {
|
if (config.collections) {
|
||||||
for (const [collectionName, enabled] of Object.entries(config.collections)) {
|
for (const [collectionName, enabled] of Object.entries(config.collections)) {
|
||||||
if (enabled === true) {
|
if (enabled === true) {
|
||||||
@ -222,12 +229,24 @@ function computeEffectiveItemStates(config) {
|
|||||||
// Extract item name from path - remove directory and all extensions
|
// Extract item name from path - remove directory and all extensions
|
||||||
const itemName = path.basename(item.path).replace(/\.(prompt|instructions|chatmode)\.md$/, '');
|
const itemName = path.basename(item.path).replace(/\.(prompt|instructions|chatmode)\.md$/, '');
|
||||||
|
|
||||||
|
let sectionName;
|
||||||
if (item.kind === "prompt") {
|
if (item.kind === "prompt") {
|
||||||
collectionEnabledItems.prompts.add(itemName);
|
sectionName = "prompts";
|
||||||
} else if (item.kind === "instruction") {
|
} else if (item.kind === "instruction") {
|
||||||
collectionEnabledItems.instructions.add(itemName);
|
sectionName = "instructions";
|
||||||
} else if (item.kind === "chat-mode") {
|
} else if (item.kind === "chat-mode") {
|
||||||
collectionEnabledItems.chatmodes.add(itemName);
|
sectionName = "chatmodes";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sectionName) {
|
||||||
|
// Track which collections enable this item
|
||||||
|
if (!collectionMemberships[sectionName].has(itemName)) {
|
||||||
|
collectionMemberships[sectionName].set(itemName, new Set());
|
||||||
|
}
|
||||||
|
collectionMemberships[sectionName].get(itemName).add(collectionName);
|
||||||
|
|
||||||
|
// Add to enabled set for O(1) lookups
|
||||||
|
collectionEnabledItems[sectionName].add(itemName);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -247,6 +266,7 @@ function computeEffectiveItemStates(config) {
|
|||||||
for (const itemName of availableItems) {
|
for (const itemName of availableItems) {
|
||||||
const explicitValue = sectionConfig[itemName];
|
const explicitValue = sectionConfig[itemName];
|
||||||
const isEnabledByCollection = collectionEnabled.has(itemName);
|
const isEnabledByCollection = collectionEnabled.has(itemName);
|
||||||
|
const enablingCollections = collectionMemberships[section].get(itemName) || new Set();
|
||||||
|
|
||||||
// Precedence rules:
|
// Precedence rules:
|
||||||
// 1. If explicitly set to true or false, use that value
|
// 1. If explicitly set to true or false, use that value
|
||||||
@ -255,6 +275,7 @@ function computeEffectiveItemStates(config) {
|
|||||||
|
|
||||||
let enabled = false;
|
let enabled = false;
|
||||||
let reason = "disabled";
|
let reason = "disabled";
|
||||||
|
let collections = [];
|
||||||
|
|
||||||
if (explicitValue === true) {
|
if (explicitValue === true) {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
@ -265,9 +286,10 @@ function computeEffectiveItemStates(config) {
|
|||||||
} else if (explicitValue === undefined && isEnabledByCollection) {
|
} else if (explicitValue === undefined && isEnabledByCollection) {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
reason = "collection";
|
reason = "collection";
|
||||||
|
collections = Array.from(enablingCollections).sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
effectiveStates[section][itemName] = { enabled, reason };
|
effectiveStates[section][itemName] = { enabled, reason, collections };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
36
final-test.yml
Normal file
36
final-test.yml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# Awesome Copilot Configuration File
|
||||||
|
# Generated on 2025-09-23T23:58:14.331Z
|
||||||
|
#
|
||||||
|
# This file uses effective state precedence:
|
||||||
|
# 1. Explicit item settings (true/false) override everything
|
||||||
|
# 2. Items not listed inherit from enabled collections
|
||||||
|
# 3. Otherwise items are disabled
|
||||||
|
#
|
||||||
|
# To use:
|
||||||
|
# - Enable collections for curated sets of related items
|
||||||
|
# - Explicitly set individual items to true/false to override collections
|
||||||
|
# - Items not mentioned will follow collection settings
|
||||||
|
#
|
||||||
|
# After configuring, run: awesome-copilot apply
|
||||||
|
#
|
||||||
|
|
||||||
|
version: "1.0"
|
||||||
|
project:
|
||||||
|
name: "My Project"
|
||||||
|
description: "A project using awesome-copilot customizations"
|
||||||
|
output_directory: ".github"
|
||||||
|
prompts:
|
||||||
|
create-readme: true
|
||||||
|
csharp-nunit: false
|
||||||
|
instructions:
|
||||||
|
chatmodes:
|
||||||
|
collections:
|
||||||
|
azure-cloud-development: false
|
||||||
|
csharp-dotnet-development: false
|
||||||
|
database-data-management: false
|
||||||
|
devops-oncall: false
|
||||||
|
frontend-web-dev: false
|
||||||
|
project-planning: false
|
||||||
|
security-best-practices: true
|
||||||
|
technical-spike: false
|
||||||
|
testing-automation: true
|
||||||
@ -92,7 +92,7 @@ async function runTests() {
|
|||||||
|
|
||||||
const result = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
const result = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||||
assert(result.success, 'List should succeed');
|
assert(result.success, 'List should succeed');
|
||||||
assert(result.stdout.includes('(collection)'), 'Should show collection reason');
|
assert(result.stdout.includes('(via:[testing-automation])'), 'Should show collection reason');
|
||||||
assert(result.stdout.includes('[✓]'), 'Should show enabled items');
|
assert(result.stdout.includes('[✓]'), 'Should show enabled items');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ async function runTests() {
|
|||||||
assert(result.success, 'Individual toggle should succeed');
|
assert(result.success, 'Individual toggle should succeed');
|
||||||
|
|
||||||
const listResult = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
const listResult = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||||
assert(listResult.stdout.includes('playwright-generate-test (explicit)'),
|
assert(listResult.stdout.includes('playwright-generate-test (explicit:false)'),
|
||||||
'Explicitly disabled item should show explicit reason');
|
'Explicitly disabled item should show explicit reason');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -119,14 +119,14 @@ async function runTests() {
|
|||||||
|
|
||||||
// Check it's explicitly disabled
|
// Check it's explicitly disabled
|
||||||
const listResult1 = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
const listResult1 = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||||
assert(listResult1.stdout.includes('create-readme (explicit)'), 'Should show explicit disabled');
|
assert(listResult1.stdout.includes('create-readme (explicit:false)'), 'Should show explicit disabled');
|
||||||
|
|
||||||
// Force enable all with --all flag
|
// Force enable all with --all flag
|
||||||
await runCommand(`node awesome-copilot.js toggle prompts all on --all --config ${TEST_CONFIG}`);
|
await runCommand(`node awesome-copilot.js toggle prompts all on --all --config ${TEST_CONFIG}`);
|
||||||
|
|
||||||
// Check it's now explicitly enabled
|
// Check it's now explicitly enabled
|
||||||
const listResult2 = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
const listResult2 = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||||
assert(listResult2.stdout.includes('create-readme (explicit)') && listResult2.stdout.includes('[✓]'), 'Should be explicitly enabled');
|
assert(listResult2.stdout.includes('create-readme (explicit:true)') && listResult2.stdout.includes('[✓]'), 'Should be explicitly enabled');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test 4: File cleanup on disable
|
// Test 4: File cleanup on disable
|
||||||
@ -180,7 +180,7 @@ async function runTests() {
|
|||||||
|
|
||||||
// Double-check with list command
|
// Double-check with list command
|
||||||
const listResult = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
const listResult = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||||
assert(listResult.stdout.includes('playwright-generate-test (explicit)'), "'playwright-generate-test (explicit)' should be present in the list output");
|
assert(listResult.stdout.includes('playwright-generate-test (explicit:false)'), "'playwright-generate-test (explicit:false)' should be present in the list output");
|
||||||
assert(!listResult.stdout.includes('[✓] playwright-generate-test'), "'[✓] playwright-generate-test' should NOT be present in the list output (should remain explicitly disabled)");
|
assert(!listResult.stdout.includes('[✓] playwright-generate-test'), "'[✓] playwright-generate-test' should NOT be present in the list output (should remain explicitly disabled)");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user