diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index 37acb1e9..b77c5725 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -13,7 +13,7 @@ "name": "accessibility-kanban", "source": "extensions/accessibility-kanban", "description": "Kanban board to manage accessibility issues, allow you to plan, track, and complete remediation work.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "acreadiness-cockpit", @@ -85,13 +85,13 @@ "name": "apng-studio", "source": "extensions/apng-studio", "description": "Interactive GitHub Copilot app canvas extension for building Animated PNG (APNG) files from frames. Draw or upload frames, tune per-frame timing and compositing, preview live, send the result to your phone by QR, and export an animated .png.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "arcade-canvas", "source": "extensions/arcade-canvas", "description": "Play five retro Phaser mini-games in a Copilot canvas while agents work.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "arch", @@ -158,7 +158,7 @@ "name": "backlog-swipe-triage", "source": "extensions/backlog-swipe-triage", "description": "Quickly swipe through backlog issues to triage decisions like assign, needs-info, defer, close, or ignore.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "cast-imaging", @@ -195,7 +195,7 @@ "name": "chromium-control-canvas", "source": "extensions/chromium-control-canvas", "description": "Opens a real Chromium window you can navigate and interact with from a Copilot canvas control panel and agent actions.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "clojure-interactive-programming", @@ -239,13 +239,13 @@ "name": "color-orb", "source": "extensions/color-orb", "description": "A visual orb that users can ask the agent to recolor while showing a live activity log in the canvas.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "connector-namespaces", "source": "extensions/connector-namespaces", "description": "Browse, connect, and open MCP connectors from an Azure Connector Namespace.", - "version": "1.1.1" + "version": "1.1.2" }, { "name": "context-engineering", @@ -373,7 +373,7 @@ "name": "diagram-viewer", "source": "extensions/diagram-viewer", "description": "Render diagrams, click nodes to drill down, and view agent-generated explanations directly in the canvas.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "dotnet", @@ -520,7 +520,7 @@ "name": "feedback-themes", "source": "extensions/feedback-themes", "description": "Explore grouped customer feedback signals by impact and drill into a theme to guide product next steps.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "figma", @@ -593,7 +593,7 @@ "name": "gesture-review", "source": "extensions/gesture-review", "description": "Review pull requests with a live camera feed and approve or reject using thumbs-up/thumbs-down gestures.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "gh-skills-builder", @@ -701,7 +701,7 @@ "name": "java-modernization-studio", "source": "extensions/java-modernization-studio", "description": "Drive the GitHub Copilot App Modernization for Java workflow from an interactive canvas: environment readiness, repo assessment, prioritized plan and progress, validation gates, and one-click predefined-task runs grounded in the repo's real artifacts.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "kotlin-mcp-development", @@ -980,13 +980,13 @@ "name": "release-notes-showcase", "source": "extensions/release-notes-showcase", "description": "Compose and refine launch-ready release notes with contributor callouts and export-friendly output.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "repo-actions-hub", "source": "extensions/repo-actions-hub", "description": "Browse repository GitHub Actions workflows, inspect recent runs, and trigger manual workflow_dispatch runs from a Copilot canvas.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "roundup", @@ -1028,7 +1028,7 @@ "name": "site-studio", "source": "extensions/site-studio", "description": "Plan, draft, and track a personal website section by section — a shared canvas where you and your agent author content, watch progress, and review every change.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "skill-image-gen", @@ -1118,13 +1118,13 @@ "name": "tiny-tool-town-submitter", "source": "extensions/tiny-tool-town-submitter", "description": "Inspect a repository, improve Tiny Tool Town readiness, submit its listing issue, and launch remediation work.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "token-pacman", "source": "extensions/token-pacman", "description": "Visualizes live session AI-credit usage as a Pac-Man board with pellets, ghosts, fruit milestones, and game-over limits.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "typescript-mcp-development", @@ -1335,7 +1335,7 @@ "name": "where-was-i", "source": "extensions/where-was-i", "description": "Reconstruct your dev context (branch, commits, uncommitted work, PR clues) and trigger a resume prompt to continue quickly.", - "version": "1.0.1" + "version": "1.0.2" }, { "name": "winappcli", @@ -1399,7 +1399,7 @@ "name": "work-hub", "source": "extensions/work-hub", "description": "Generic cross-repo command center canvas for GitHub Copilot with onboarding, focus planning, repo health, work signals, and session cleanup.", - "version": "1.0.1" + "version": "1.0.2" } ] } diff --git a/eng/clean-materialized-plugins.mjs b/eng/clean-materialized-plugins.mjs index 2fcbacc2..6b034276 100644 --- a/eng/clean-materialized-plugins.mjs +++ b/eng/clean-materialized-plugins.mjs @@ -28,6 +28,41 @@ const MATERIALIZED_SPECS = { }, }; +function copyDirRecursive(src, dest) { + fs.mkdirSync(dest, { recursive: true }); + for (const entry of fs.readdirSync(src, { withFileTypes: true })) { + const srcPath = path.join(src, entry.name); + const destPath = path.join(dest, entry.name); + if (entry.isDirectory()) { + copyDirRecursive(srcPath, destPath); + } else { + fs.copyFileSync(srcPath, destPath); + } + } +} + +function moveEntry(srcPath, destPath) { + fs.mkdirSync(path.dirname(destPath), { recursive: true }); + try { + fs.renameSync(srcPath, destPath); + return; + } catch (error) { + if (!["EXDEV", "EEXIST", "ENOTEMPTY", "EPERM"].includes(error?.code)) { + throw error; + } + } + + const stats = fs.statSync(srcPath); + if (stats.isDirectory()) { + copyDirRecursive(srcPath, destPath); + fs.rmSync(srcPath, { recursive: true, force: true }); + return; + } + + fs.copyFileSync(srcPath, destPath); + fs.rmSync(srcPath, { force: true }); +} + export function restoreManifestFromMaterializedFiles(pluginPath) { const pluginJsonPath = path.join(pluginPath, ".github/plugin", "plugin.json"); if (!fs.existsSync(pluginJsonPath)) { @@ -90,15 +125,22 @@ function cleanPlugin(pluginPath) { return { removed, manifestUpdated }; } -function cleanMaterializedExtensionPlugin(extensionPath) { +export function cleanMaterializedExtensionPlugin(extensionPath) { const pluginJsonPath = path.join(extensionPath, ".github", "plugin", "plugin.json"); let manifestUpdated = false; if (fs.existsSync(pluginJsonPath)) { const plugin = JSON.parse(fs.readFileSync(pluginJsonPath, "utf8")); + const extensionBundlePrefix = `extensions/${path.basename(extensionPath)}/`; if (plugin.extensions === "extensions") { plugin.extensions = "."; - fs.writeFileSync(pluginJsonPath, JSON.stringify(plugin, null, 2) + "\n", "utf8"); manifestUpdated = true; + } + if (typeof plugin.logo === "string" && plugin.logo.startsWith(extensionBundlePrefix)) { + plugin.logo = plugin.logo.slice(extensionBundlePrefix.length); + manifestUpdated = true; + } + if (manifestUpdated) { + fs.writeFileSync(pluginJsonPath, JSON.stringify(plugin, null, 2) + "\n", "utf8"); console.log(` Updated ${path.basename(extensionPath)}/.github/plugin/plugin.json`); } } @@ -108,12 +150,43 @@ function cleanMaterializedExtensionPlugin(extensionPath) { return { removed: 0, manifestUpdated }; } + const bundleRoot = path.join(target, path.basename(extensionPath)); const count = countFiles(target); + if (fs.existsSync(bundleRoot) && fs.statSync(bundleRoot).isDirectory()) { + for (const entry of fs.readdirSync(bundleRoot, { withFileTypes: true })) { + moveEntry(path.join(bundleRoot, entry.name), path.join(extensionPath, entry.name)); + } + console.log(` Restored ${path.basename(extensionPath)}/ from materialized extensions bundle`); + } + fs.rmSync(target, { recursive: true, force: true }); console.log(` Removed ${path.basename(extensionPath)}/extensions/ (${count} files)`); return { removed: count, manifestUpdated }; } +function isExtensionPluginDirectory(extensionPath) { + if (fs.existsSync(path.join(extensionPath, "extension.mjs"))) { + return true; + } + + const bundleEntry = path.join(extensionPath, "extensions", path.basename(extensionPath), "extension.mjs"); + if (fs.existsSync(bundleEntry)) { + return true; + } + + const pluginJsonPath = path.join(extensionPath, ".github", "plugin", "plugin.json"); + if (!fs.existsSync(pluginJsonPath)) { + return false; + } + + try { + const plugin = JSON.parse(fs.readFileSync(pluginJsonPath, "utf8")); + return plugin.extensions === "extensions"; + } catch { + return false; + } +} + function countFiles(dir) { let count = 0; for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { @@ -204,7 +277,7 @@ function main() { for (const dirName of extensionDirs) { const extensionPath = path.join(EXTENSIONS_DIR, dirName); - if (!fs.existsSync(path.join(extensionPath, "extension.mjs"))) { + if (!isExtensionPluginDirectory(extensionPath)) { continue; } const { removed, manifestUpdated } = cleanMaterializedExtensionPlugin(extensionPath); diff --git a/eng/generate-marketplace.mjs b/eng/generate-marketplace.mjs index 45a54b21..6c40c463 100755 --- a/eng/generate-marketplace.mjs +++ b/eng/generate-marketplace.mjs @@ -62,6 +62,16 @@ function collectLocalPluginsFromRoot(rootDir, sourcePrefix, includeEntry = () => return plugins; } +function hasExtensionEntryPoint(extensionDir, extensionName) { + const candidateEntryPoints = [ + path.join(extensionDir, "extension.mjs"), + path.join(extensionDir, "extensions", "extension.mjs"), + path.join(extensionDir, "extensions", extensionName, "extension.mjs"), + ]; + + return candidateEntryPoints.some((entryPointPath) => fs.existsSync(entryPointPath)); +} + /** * Generate marketplace.json from plugin directories */ @@ -78,7 +88,7 @@ function generateMarketplace() { ...collectLocalPluginsFromRoot( EXTENSIONS_DIR, "extensions", - (entryName) => fs.existsSync(path.join(EXTENSIONS_DIR, entryName, "extension.mjs")) + (entryName) => hasExtensionEntryPoint(path.join(EXTENSIONS_DIR, entryName), entryName) ) ]; diff --git a/eng/generate-website-data.mjs b/eng/generate-website-data.mjs index ef052693..f6fc2082 100755 --- a/eng/generate-website-data.mjs +++ b/eng/generate-website-data.mjs @@ -35,6 +35,16 @@ const WEBSITE_SOURCE_DATA_DIR = path.join(WEBSITE_DIR, "data"); const EXTERNAL_CANVAS_KEYWORD = "canvas"; const EXTERNAL_CANVAS_PREVIEW_PATH = "assets/preview.png"; +function hasExtensionEntryPoint(extensionDir, extensionName) { + const candidateEntryPoints = [ + path.join(extensionDir, "extension.mjs"), + path.join(extensionDir, "extensions", "extension.mjs"), + path.join(extensionDir, "extensions", extensionName, "extension.mjs"), + ]; + + return candidateEntryPoints.some((entryPointPath) => fs.existsSync(entryPointPath)); +} + /** * Ensure the output directory exists */ @@ -544,7 +554,7 @@ function generatePluginsData(gitDates, resourceIndex = {}) { const extensionDirs = fs.readdirSync(EXTENSIONS_DIR, { withFileTypes: true }) .filter((entry) => { if (!entry.isDirectory()) return false; - return fs.existsSync(path.join(EXTENSIONS_DIR, entry.name, "extension.mjs")); + return hasExtensionEntryPoint(path.join(EXTENSIONS_DIR, entry.name), entry.name); }) .map((entry) => entry.name) .sort((a, b) => a.localeCompare(b)); @@ -1235,12 +1245,7 @@ function generateCanvasManifest(gitDates, commitSha) { .readdirSync(EXTENSIONS_DIR, { withFileTypes: true }) .filter((entry) => { if (!entry.isDirectory()) return false; - const extensionEntryPoint = path.join( - EXTENSIONS_DIR, - entry.name, - "extension.mjs" - ); - return fs.existsSync(extensionEntryPoint); + return hasExtensionEntryPoint(path.join(EXTENSIONS_DIR, entry.name), entry.name); }) .sort((a, b) => a.name.localeCompare(b.name)); diff --git a/eng/materialize-plugins.mjs b/eng/materialize-plugins.mjs index 2d91cb61..905b2faf 100644 --- a/eng/materialize-plugins.mjs +++ b/eng/materialize-plugins.mjs @@ -24,15 +24,34 @@ function copyDirRecursive(src, dest) { } } -function copyEntryRecursive(srcPath, destPath) { +function moveEntry(srcPath, destPath) { + fs.mkdirSync(path.dirname(destPath), { recursive: true }); + try { + fs.renameSync(srcPath, destPath); + return; + } catch (error) { + if (error?.code !== "EXDEV") { + throw error; + } + } + const stats = fs.statSync(srcPath); if (stats.isDirectory()) { copyDirRecursive(srcPath, destPath); + fs.rmSync(srcPath, { recursive: true, force: true }); return; } - fs.mkdirSync(path.dirname(destPath), { recursive: true }); fs.copyFileSync(srcPath, destPath); + fs.rmSync(srcPath, { force: true }); +} + +function isRelativeAssetPath(assetPath) { + return typeof assetPath === "string" && + assetPath.length > 0 && + !/^(?:[a-z][a-z0-9+.-]*:)?\/\//i.test(assetPath) && + !assetPath.startsWith("data:") && + !path.isAbsolute(assetPath); } /** @@ -61,7 +80,7 @@ function resolveSource(relPath) { export function materializeExtensionPlugin(extensionPath) { const pluginJsonPath = path.join(extensionPath, ".github", "plugin", "plugin.json"); if (!fs.existsSync(pluginJsonPath)) { - return { copiedEntries: 0, manifestUpdated: false, skipped: true }; + return { movedEntries: 0, manifestUpdated: false, skipped: true }; } let metadata; @@ -72,20 +91,31 @@ export function materializeExtensionPlugin(extensionPath) { } const extensionContainerPath = path.join(extensionPath, "extensions"); + const extensionBundlePath = path.join(extensionContainerPath, path.basename(extensionPath)); fs.rmSync(extensionContainerPath, { recursive: true, force: true }); - fs.mkdirSync(extensionContainerPath, { recursive: true }); + fs.mkdirSync(extensionBundlePath, { recursive: true }); - let copiedEntries = 0; + let movedEntries = 0; for (const entry of fs.readdirSync(extensionPath, { withFileTypes: true })) { if (entry.name === ".github" || entry.name === "extensions") { continue; } - copyEntryRecursive( + moveEntry( path.join(extensionPath, entry.name), - path.join(extensionContainerPath, entry.name) + path.join(extensionBundlePath, entry.name) ); - copiedEntries++; + movedEntries++; + } + + if (isRelativeAssetPath(metadata.logo)) { + const normalizedLogoPath = metadata.logo.replace(/\\/g, "/").replace(/^\.\//, ""); + const bundledLogoPath = path.join(extensionBundlePath, normalizedLogoPath); + if (fs.existsSync(bundledLogoPath)) { + const rootLogoPath = path.join(extensionPath, normalizedLogoPath); + fs.mkdirSync(path.dirname(rootLogoPath), { recursive: true }); + fs.copyFileSync(bundledLogoPath, rootLogoPath); + } } let manifestUpdated = false; @@ -97,7 +127,7 @@ export function materializeExtensionPlugin(extensionPath) { fs.writeFileSync(pluginJsonPath, JSON.stringify(metadata, null, 2) + "\n", "utf8"); } - return { copiedEntries, manifestUpdated, skipped: false }; + return { movedEntries, manifestUpdated, skipped: false }; } function materializePlugins() { @@ -261,8 +291,8 @@ function materializePlugins() { } totalExtensionPlugins++; - totalExtensionPluginEntries += result.copiedEntries; - console.log(`✓ ${dirName}: materialized extension bundle into ./extensions (${result.copiedEntries} entries)`); + totalExtensionPluginEntries += result.movedEntries; + console.log(`✓ ${dirName}: materialized extension bundle into ./extensions (${result.movedEntries} entries)`); } catch (err) { console.error(`Error: Failed to materialize extension plugin ${dirName}: ${err.message}`); errors++; diff --git a/eng/materialize-plugins.test.mjs b/eng/materialize-plugins.test.mjs index 7f42981c..d0bce457 100644 --- a/eng/materialize-plugins.test.mjs +++ b/eng/materialize-plugins.test.mjs @@ -4,6 +4,7 @@ import os from "os"; import path from "path"; import { after, test } from "node:test"; import { materializeExtensionPlugin } from "./materialize-plugins.mjs"; +import { cleanMaterializedExtensionPlugin } from "./clean-materialized-plugins.mjs"; const tempDirs = []; @@ -13,7 +14,7 @@ after(() => { } }); -test("materializeExtensionPlugin writes extension bundles to ./extensions and rewrites manifest", () => { +test("materializeExtensionPlugin writes extension bundles to ./extensions and preserves root logo assets", () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "materialize-extension-plugin-")); tempDirs.push(tempDir); @@ -32,17 +33,57 @@ test("materializeExtensionPlugin writes extension bundles to ./extensions and re fs.writeFileSync(path.join(pluginDir, "assets", "preview.png"), "fake-image-bytes"); const result = materializeExtensionPlugin(pluginDir); + const bundleRoot = path.join(pluginDir, "extensions", "extension-plugin"); assert.equal(result.skipped, false); assert.equal(result.manifestUpdated, true); - assert.equal(result.copiedEntries, 3); - assert.equal(fs.existsSync(path.join(pluginDir, "extensions", "extension.mjs")), true); - assert.equal(fs.existsSync(path.join(pluginDir, "extensions", "assets", "preview.png")), true); - assert.equal(fs.existsSync(path.join(pluginDir, "extensions", "README.md")), true); + assert.equal(result.movedEntries, 3); + assert.equal(fs.existsSync(path.join(bundleRoot, "extension.mjs")), true); + assert.equal(fs.existsSync(path.join(bundleRoot, "assets", "preview.png")), true); + assert.equal(fs.existsSync(path.join(bundleRoot, "README.md")), true); assert.equal(fs.existsSync(path.join(pluginDir, "extensions", ".github")), false); + assert.equal(fs.existsSync(path.join(pluginDir, "extension.mjs")), false); + assert.equal(fs.existsSync(path.join(pluginDir, "README.md")), false); + assert.equal(fs.existsSync(path.join(pluginDir, "assets", "preview.png")), true); const pluginManifest = JSON.parse( fs.readFileSync(path.join(pluginDir, ".github", "plugin", "plugin.json"), "utf8") ); assert.equal(pluginManifest.extensions, "extensions"); + assert.equal(pluginManifest.logo, "assets/preview.png"); +}); + +test("cleanMaterializedExtensionPlugin restores moved extension files to root", () => { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "clean-materialized-extension-plugin-")); + tempDirs.push(tempDir); + + const pluginDir = path.join(tempDir, "extension-plugin"); + fs.mkdirSync(path.join(pluginDir, ".github", "plugin"), { recursive: true }); + fs.mkdirSync(path.join(pluginDir, "assets"), { recursive: true }); + fs.writeFileSync(path.join(pluginDir, ".github", "plugin", "plugin.json"), JSON.stringify({ + name: "test-extension-plugin", + description: "test plugin", + version: "1.0.0", + logo: "assets/preview.png", + extensions: ".", + }, null, 2)); + fs.writeFileSync(path.join(pluginDir, "extension.mjs"), "export default {};\n"); + fs.writeFileSync(path.join(pluginDir, "README.md"), "# test\n"); + fs.writeFileSync(path.join(pluginDir, "assets", "preview.png"), "fake-image-bytes"); + + materializeExtensionPlugin(pluginDir); + const result = cleanMaterializedExtensionPlugin(pluginDir); + + assert.equal(result.removed, 3); + assert.equal(result.manifestUpdated, true); + assert.equal(fs.existsSync(path.join(pluginDir, "extension.mjs")), true); + assert.equal(fs.existsSync(path.join(pluginDir, "README.md")), true); + assert.equal(fs.existsSync(path.join(pluginDir, "assets", "preview.png")), true); + assert.equal(fs.existsSync(path.join(pluginDir, "extensions")), false); + + const pluginManifest = JSON.parse( + fs.readFileSync(path.join(pluginDir, ".github", "plugin", "plugin.json"), "utf8") + ); + assert.equal(pluginManifest.extensions, "."); + assert.equal(pluginManifest.logo, "assets/preview.png"); }); diff --git a/extensions/accessibility-kanban/.github/plugin/plugin.json b/extensions/accessibility-kanban/.github/plugin/plugin.json index 03903a27..25bfbc1a 100644 --- a/extensions/accessibility-kanban/.github/plugin/plugin.json +++ b/extensions/accessibility-kanban/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "accessibility-kanban", "description": "Kanban board to manage accessibility issues, allow you to plan, track, and complete remediation work.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "Aaron Powell", "url": "https://github.com/aaronpowell" diff --git a/extensions/apng-studio/.github/plugin/plugin.json b/extensions/apng-studio/.github/plugin/plugin.json index fcd5bfc8..9522900b 100644 --- a/extensions/apng-studio/.github/plugin/plugin.json +++ b/extensions/apng-studio/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "apng-studio", "description": "Interactive GitHub Copilot app canvas extension for building Animated PNG (APNG) files from frames. Draw or upload frames, tune per-frame timing and compositing, preview live, send the result to your phone by QR, and export an animated .png.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "Andrea Griffiths", "url": "https://github.com/AndreaGriffiths11" diff --git a/extensions/arcade-canvas/.github/plugin/plugin.json b/extensions/arcade-canvas/.github/plugin/plugin.json index 975971d8..9c45471e 100644 --- a/extensions/arcade-canvas/.github/plugin/plugin.json +++ b/extensions/arcade-canvas/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "arcade-canvas", "description": "Play five retro Phaser mini-games in a Copilot canvas while agents work.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "Dan Wahlin", "url": "https://github.com/DanWahlin" diff --git a/extensions/backlog-swipe-triage/.github/plugin/plugin.json b/extensions/backlog-swipe-triage/.github/plugin/plugin.json index 6dda88bd..aa7f7c16 100644 --- a/extensions/backlog-swipe-triage/.github/plugin/plugin.json +++ b/extensions/backlog-swipe-triage/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "backlog-swipe-triage", "description": "Quickly swipe through backlog issues to triage decisions like assign, needs-info, defer, close, or ignore.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "James Montemagno", "url": "https://github.com/jamesmontemagno" diff --git a/extensions/chromium-control-canvas/.github/plugin/plugin.json b/extensions/chromium-control-canvas/.github/plugin/plugin.json index 8c4d631d..301485a6 100644 --- a/extensions/chromium-control-canvas/.github/plugin/plugin.json +++ b/extensions/chromium-control-canvas/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "chromium-control-canvas", "description": "Opens a real Chromium window you can navigate and interact with from a Copilot canvas control panel and agent actions.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "Andrea Griffiths", "url": "https://github.com/AndreaGriffiths11" diff --git a/extensions/color-orb/.github/plugin/plugin.json b/extensions/color-orb/.github/plugin/plugin.json index 3b564245..e5e31f0b 100644 --- a/extensions/color-orb/.github/plugin/plugin.json +++ b/extensions/color-orb/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "color-orb", "description": "A visual orb that users can ask the agent to recolor while showing a live activity log in the canvas.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "Aaron Powell", "url": "https://github.com/aaronpowell" diff --git a/extensions/connector-namespaces/.github/plugin/plugin.json b/extensions/connector-namespaces/.github/plugin/plugin.json index 397859c5..a75cb84c 100644 --- a/extensions/connector-namespaces/.github/plugin/plugin.json +++ b/extensions/connector-namespaces/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "connector-namespaces", "description": "Browse, connect, and open MCP connectors from an Azure Connector Namespace.", - "version": "1.1.1", + "version": "1.1.2", "author": { "name": "Alex Yang", "url": "https://github.com/alexyaang" diff --git a/extensions/diagram-viewer/.github/plugin/plugin.json b/extensions/diagram-viewer/.github/plugin/plugin.json index 9e2b6ef2..5e9b0975 100644 --- a/extensions/diagram-viewer/.github/plugin/plugin.json +++ b/extensions/diagram-viewer/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "diagram-viewer", "description": "Render diagrams, click nodes to drill down, and view agent-generated explanations directly in the canvas.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "Aaron Powell", "url": "https://github.com/aaronpowell" diff --git a/extensions/feedback-themes/.github/plugin/plugin.json b/extensions/feedback-themes/.github/plugin/plugin.json index 09435104..7a93483d 100644 --- a/extensions/feedback-themes/.github/plugin/plugin.json +++ b/extensions/feedback-themes/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "feedback-themes", "description": "Explore grouped customer feedback signals by impact and drill into a theme to guide product next steps.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "Aaron Powell", "url": "https://github.com/aaronpowell" diff --git a/extensions/gesture-review/.github/plugin/plugin.json b/extensions/gesture-review/.github/plugin/plugin.json index 1ba5cf3b..db776361 100644 --- a/extensions/gesture-review/.github/plugin/plugin.json +++ b/extensions/gesture-review/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "gesture-review", "description": "Review pull requests with a live camera feed and approve or reject using thumbs-up/thumbs-down gestures.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "Aaron Powell", "url": "https://github.com/aaronpowell" diff --git a/extensions/java-modernization-studio/.github/plugin/plugin.json b/extensions/java-modernization-studio/.github/plugin/plugin.json index c3f22658..4eba3dd3 100644 --- a/extensions/java-modernization-studio/.github/plugin/plugin.json +++ b/extensions/java-modernization-studio/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "java-modernization-studio", "description": "Drive the GitHub Copilot App Modernization for Java workflow from an interactive canvas: environment readiness, repo assessment, prioritized plan and progress, validation gates, and one-click predefined-task runs grounded in the repo's real artifacts.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "Ayan Gupta", "url": "https://github.com/ayangupt" diff --git a/extensions/release-notes-showcase/.github/plugin/plugin.json b/extensions/release-notes-showcase/.github/plugin/plugin.json index dcc4ba18..aa8a7462 100644 --- a/extensions/release-notes-showcase/.github/plugin/plugin.json +++ b/extensions/release-notes-showcase/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "release-notes-showcase", "description": "Compose and refine launch-ready release notes with contributor callouts and export-friendly output.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "Kayla Cinnamon", "url": "https://github.com/cinnamon-msft" diff --git a/extensions/repo-actions-hub/.github/plugin/plugin.json b/extensions/repo-actions-hub/.github/plugin/plugin.json index bd317192..f43e4af1 100644 --- a/extensions/repo-actions-hub/.github/plugin/plugin.json +++ b/extensions/repo-actions-hub/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "repo-actions-hub", "description": "Browse repository GitHub Actions workflows, inspect recent runs, and trigger manual workflow_dispatch runs from a Copilot canvas.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "James Montemagno", "url": "https://github.com/jamesmontemagno" diff --git a/extensions/site-studio/.github/plugin/plugin.json b/extensions/site-studio/.github/plugin/plugin.json index 2c1605b6..2cc5f51d 100644 --- a/extensions/site-studio/.github/plugin/plugin.json +++ b/extensions/site-studio/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "site-studio", "description": "Plan, draft, and track a personal website section by section — a shared canvas where you and your agent author content, watch progress, and review every change.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "Ayan Gupta", "url": "https://github.com/ayangupt" diff --git a/extensions/tiny-tool-town-submitter/.github/plugin/plugin.json b/extensions/tiny-tool-town-submitter/.github/plugin/plugin.json index 70b8c98a..53edf975 100644 --- a/extensions/tiny-tool-town-submitter/.github/plugin/plugin.json +++ b/extensions/tiny-tool-town-submitter/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "tiny-tool-town-submitter", "description": "Inspect a repository, improve Tiny Tool Town readiness, submit its listing issue, and launch remediation work.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "James Montemagno", "url": "https://github.com/jamesmontemagno" diff --git a/extensions/token-pacman/.github/plugin/plugin.json b/extensions/token-pacman/.github/plugin/plugin.json index b7868bb1..b63359a8 100644 --- a/extensions/token-pacman/.github/plugin/plugin.json +++ b/extensions/token-pacman/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "token-pacman", "description": "Visualizes live session AI-credit usage as a Pac-Man board with pellets, ghosts, fruit milestones, and game-over limits.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "James Montemagno", "url": "https://github.com/jamesmontemagno" diff --git a/extensions/where-was-i/.github/plugin/plugin.json b/extensions/where-was-i/.github/plugin/plugin.json index e43c6f26..7ef8a679 100644 --- a/extensions/where-was-i/.github/plugin/plugin.json +++ b/extensions/where-was-i/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "where-was-i", "description": "Reconstruct your dev context (branch, commits, uncommitted work, PR clues) and trigger a resume prompt to continue quickly.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "Aaron Powell", "url": "https://github.com/aaronpowell" diff --git a/extensions/work-hub/.github/plugin/plugin.json b/extensions/work-hub/.github/plugin/plugin.json index c3999519..8f88dd01 100644 --- a/extensions/work-hub/.github/plugin/plugin.json +++ b/extensions/work-hub/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "work-hub", "description": "Generic cross-repo command center canvas for GitHub Copilot with onboarding, focus planning, repo health, work signals, and session cleanup.", - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "James Montemagno", "url": "https://github.com/jamesmontemagno"