mirror of
https://github.com/github/awesome-copilot.git
synced 2026-09-17 04:11:16 +00:00
chore: publish from main
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
import { basename } from "node:path";
|
||||
import { CanvasError, createCanvas, joinSession } from "@github/copilot-sdk/extension";
|
||||
import { createInstanceServer, pushState } from "./lib/server.mjs";
|
||||
import {
|
||||
configureWorkflow,
|
||||
getWorkflowState,
|
||||
refreshWorkflow,
|
||||
resolveWorkspace,
|
||||
setStepStatus,
|
||||
} from "./lib/state.mjs";
|
||||
|
||||
const instances = new Map();
|
||||
let sessionRef;
|
||||
let workingDirectory = process.cwd();
|
||||
|
||||
function instance(ctx) {
|
||||
const value = instances.get(ctx.instanceId);
|
||||
if (!value) throw new CanvasError("not_open", "Open the Modernization Workflow canvas first.");
|
||||
return value;
|
||||
}
|
||||
|
||||
async function updateInstance(rec, operation) {
|
||||
const state = await operation(rec.workspace, rec.stateId);
|
||||
await pushState(rec, state);
|
||||
return state;
|
||||
}
|
||||
|
||||
const session = await joinSession({
|
||||
canvases: [
|
||||
createCanvas({
|
||||
id: "modernization-workflow",
|
||||
displayName: "Modernization Workflow",
|
||||
description: "Track and guide a Modernize CLI Assess, Plan, and Execute workflow from real repository artifacts.",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
workspace: { type: "string", description: "Absolute local application repository path." },
|
||||
stateId: {
|
||||
type: "string",
|
||||
pattern: "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$",
|
||||
description: "Stable workflow identifier used for persisted state.",
|
||||
},
|
||||
language: { type: "string", enum: ["auto", "dotnet", "java", "cpp"] },
|
||||
source: { type: "string" },
|
||||
goal: { type: "string" },
|
||||
upgradeTarget: { type: "string" },
|
||||
planName: { type: "string", pattern: "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$" },
|
||||
},
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
name: "get_workflow_state",
|
||||
description: "Return the current workflow configuration, generated commands, artifacts, and step progress.",
|
||||
handler: async (ctx) => {
|
||||
const rec = instance(ctx);
|
||||
return getWorkflowState(rec.workspace, rec.stateId);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "configure_workflow",
|
||||
description: "Configure the source, language, modernization goal, and plan name.",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
language: { type: "string", enum: ["auto", "dotnet", "java", "cpp"] },
|
||||
source: { type: "string", minLength: 1 },
|
||||
goal: { type: "string", minLength: 1 },
|
||||
upgradeTarget: { type: "string" },
|
||||
planName: { type: "string", pattern: "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$" },
|
||||
delegate: { type: "string", enum: ["local", "cloud"] },
|
||||
},
|
||||
},
|
||||
handler: async (ctx) => {
|
||||
const rec = instance(ctx);
|
||||
return updateInstance(rec, (workspace, stateId) =>
|
||||
configureWorkflow(workspace, stateId, ctx.input ?? {}));
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "set_step_status",
|
||||
description: "Set an Assess, Plan, or Execute step to pending, active, complete, or blocked.",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
required: ["step", "status"],
|
||||
properties: {
|
||||
step: { type: "string", enum: ["assess", "plan", "execute"] },
|
||||
status: { type: "string", enum: ["pending", "active", "complete", "blocked"] },
|
||||
},
|
||||
},
|
||||
handler: async (ctx) => {
|
||||
const rec = instance(ctx);
|
||||
return updateInstance(rec, (workspace, stateId) =>
|
||||
setStepStatus(workspace, stateId, ctx.input.step, ctx.input.status));
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "refresh_from_artifacts",
|
||||
description: "Re-scan the repository and update progress from Modernize CLI output artifacts.",
|
||||
handler: async (ctx) => {
|
||||
const rec = instance(ctx);
|
||||
return updateInstance(rec, refreshWorkflow);
|
||||
},
|
||||
},
|
||||
],
|
||||
open: async (ctx) => {
|
||||
const workspace = resolveWorkspace(ctx.input?.workspace, workingDirectory);
|
||||
const stateId = ctx.input?.stateId ?? "default";
|
||||
let rec = instances.get(ctx.instanceId);
|
||||
|
||||
if (rec && (rec.workspace !== workspace || rec.stateId !== stateId)) {
|
||||
for (const client of rec.clients) client.end();
|
||||
await new Promise((resolve) => rec.server.close(resolve));
|
||||
instances.delete(ctx.instanceId);
|
||||
rec = null;
|
||||
}
|
||||
|
||||
if (!rec) {
|
||||
rec = await createInstanceServer({
|
||||
workspace,
|
||||
stateId,
|
||||
initialConfig: ctx.input ?? {},
|
||||
onConfigure: (input) => configureWorkflow(workspace, stateId, input),
|
||||
onSetStep: (step, status) => setStepStatus(workspace, stateId, step, status),
|
||||
onRefresh: () => refreshWorkflow(workspace, stateId),
|
||||
});
|
||||
instances.set(ctx.instanceId, rec);
|
||||
}
|
||||
|
||||
return {
|
||||
title: "Modernization Workflow",
|
||||
status: basename(workspace),
|
||||
url: rec.url,
|
||||
};
|
||||
},
|
||||
onClose: async (ctx) => {
|
||||
const rec = instances.get(ctx.instanceId);
|
||||
if (!rec) return;
|
||||
instances.delete(ctx.instanceId);
|
||||
for (const client of rec.clients) client.end();
|
||||
await new Promise((resolve) => rec.server.close(resolve));
|
||||
},
|
||||
}),
|
||||
],
|
||||
hooks: {
|
||||
onSessionStart: async (input) => {
|
||||
if (input.workingDirectory) workingDirectory = input.workingDirectory;
|
||||
return {
|
||||
additionalContext:
|
||||
"When a user is modernizing an application, use the Modernization Workflow canvas to make Assess, Plan, and Execute progress visible. Refresh it after Modernize CLI commands change repository artifacts.",
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
sessionRef = session;
|
||||
|
||||
session.on("session.idle", async () => {
|
||||
for (const rec of instances.values()) {
|
||||
const state = await refreshWorkflow(rec.workspace, rec.stateId);
|
||||
await pushState(rec, state);
|
||||
}
|
||||
});
|
||||
|
||||
await session.log("Modernization Workflow canvas ready", { ephemeral: true });
|
||||
Reference in New Issue
Block a user