mirror of
https://github.com/github/awesome-copilot.git
synced 2026-08-26 10:45:03 +00:00
ca87445cb2
* Add Git Worktree Explorer canvas Add an interactive repository, worktree, branch, and commit graph with GitHub PR enrichment, safe inspection actions, and shared lane visualization. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 69dd5824-7094-4b82-8cfa-83c2fbe53307 * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Address review feedback for Git Worktree Explorer Security - Quote copied shell commands (git -C / git log) with shell-safe single quoting and --end-of-options via new public/shell-quote.mjs - Move repository path into the untrusted data block of the commit Ask Copilot prompt Performance - Compute branch divergence with a single `git for-each-ref %(ahead-behind:...)` query (Git 2.41+), falling back to rev-list with bounded concurrency (8) instead of one process per branch - Drop the unused `git show --stat` summary from commit details Correctness - Only attach same-repository pull requests to local branches (filter isCrossRepository / headRepositoryOwner) - Resolve the default branch by full name or upstream instead of a suffix match (server + client) - Preserve already-loaded commit pages when a load-more request fails; only reset requests show the error state - Size the lane graph from the widest row (lanes + branch badges + text) and collapse >3 branch tips into a "+N more" badge Accessibility / UX - Add aria-pressed to view toggles and graph nodes; replace the unimplemented ARIA tree with group/button semantics - preventDefault on Space/Enter for branch badges so keyboard activation does not scroll - Use a lane palette that meets 3:1 contrast in both light and dark themes (tested) - Mobile inspector no longer auto-opens on snapshot load and gains a close button Tests: 19 -> 29 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 18350039-5e2b-40f0-b537-bc22cabcbb1b * Migrate git-worktree-explorer to plugins/ manifest layout Move the manifest from extensions/git-worktree-explorer/.github/plugin/plugin.json to plugins/git-worktree-explorer/plugin.json with README and copilot-extension.json, matching the extensions-container migration (#2334). Regenerated marketplace.json and docs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 18350039-5e2b-40f0-b537-bc22cabcbb1b * Address follow-up review: shell-specific quoting and sibling row controls - quoteShellArg/formatShellCommand take a target shell; PowerShell doubles apostrophes while POSIX uses '\\''. app.js detects the platform and reports which syntax was copied. - Commit rows no longer nest branch badge buttons inside the row button; the row button and badges are sibling controls. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 18350039-5e2b-40f0-b537-bc22cabcbb1b * Make the closed mobile inspector inert and restore focus to the graph When the inspector overlay is dismissed on narrow viewports it is now marked inert/aria-hidden so its controls leave the tab order and accessibility tree, focus returns to the selected graph control, Escape closes it, and viewport changes re-sync the state. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 18350039-5e2b-40f0-b537-bc22cabcbb1b --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Aaron Powell <me@aaron-powell.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Copilot-Session: 69dd5824-7094-4b82-8cfa-83c2fbe53307 Copilot-Session: 18350039-5e2b-40f0-b537-bc22cabcbb1b
95 lines
4.3 KiB
JavaScript
95 lines
4.3 KiB
JavaScript
import { CanvasError, createCanvas, joinSession } from "@github/copilot-sdk/extension";
|
|
import { getServerEntry, refreshServer, startServer, stopServer } from "./server.mjs";
|
|
|
|
const session = await joinSession({
|
|
canvases: [
|
|
createCanvas({
|
|
id: "git-worktree-explorer",
|
|
displayName: "Git Worktree Explorer",
|
|
description: "Explore the active Git repository through worktrees, branches, commits, and related GitHub pull requests.",
|
|
inputSchema: {
|
|
type: "object",
|
|
additionalProperties: false,
|
|
properties: {
|
|
startAt: {
|
|
type: "string",
|
|
enum: ["repository"],
|
|
description: "Initial topology level.",
|
|
},
|
|
},
|
|
},
|
|
actions: [
|
|
{
|
|
name: "refresh",
|
|
description: "Refresh Git and GitHub information shown by an open explorer.",
|
|
inputSchema: {
|
|
type: "object",
|
|
additionalProperties: false,
|
|
properties: {},
|
|
},
|
|
handler: async (ctx) => {
|
|
try {
|
|
const snapshot = await refreshServer(ctx.instanceId);
|
|
return {
|
|
gatheredAt: snapshot.gatheredAt,
|
|
worktrees: snapshot.worktrees.length,
|
|
branches: snapshot.branches.length,
|
|
};
|
|
} catch (error) {
|
|
throw new CanvasError("git_refresh_failed", error.message);
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "focus_node",
|
|
description: "Ask an open explorer to focus a repository, worktree, or branch node by its canvas node ID.",
|
|
inputSchema: {
|
|
type: "object",
|
|
additionalProperties: false,
|
|
properties: {
|
|
nodeId: { type: "string", minLength: 1 },
|
|
},
|
|
required: ["nodeId"],
|
|
},
|
|
handler: async (ctx) => {
|
|
const entry = getServerEntry(ctx.instanceId);
|
|
if (!entry) throw new CanvasError("canvas_not_open", "Canvas instance is not open.");
|
|
const nodeId = ctx.input?.nodeId;
|
|
const snapshot = entry.snapshot;
|
|
const exists = nodeId === "repository"
|
|
|| snapshot.worktrees.some((item) => item.id === nodeId)
|
|
|| snapshot.branches.some((item) => item.id === nodeId);
|
|
if (!exists) throw new CanvasError("git_node_not_found", `Git node not found: ${nodeId}`);
|
|
for (const client of entry.clients) {
|
|
client.write(`event: focus\ndata: ${JSON.stringify({ nodeId })}\n\n`);
|
|
}
|
|
return { nodeId };
|
|
},
|
|
},
|
|
],
|
|
open: async (ctx) => {
|
|
const cwd = ctx.session?.workingDirectory;
|
|
if (!cwd) {
|
|
throw new CanvasError("workspace_unavailable", "The active session working directory is unavailable.");
|
|
}
|
|
try {
|
|
const entry = await startServer(ctx.instanceId, {
|
|
cwd,
|
|
sendPrompt: async (prompt) => session.send({ prompt }),
|
|
});
|
|
return {
|
|
title: "Git Worktree Explorer",
|
|
status: `${entry.snapshot.worktrees.length} worktrees · ${entry.snapshot.branches.length} branches`,
|
|
url: entry.url,
|
|
};
|
|
} catch (error) {
|
|
throw new CanvasError("git_repository_unavailable", error.message);
|
|
}
|
|
},
|
|
onClose: async (ctx) => {
|
|
await stopServer(ctx.instanceId);
|
|
},
|
|
}),
|
|
],
|
|
});
|