Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .github/extensions/agentic-workflows-dashboard/dashboard-cli.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,18 @@ function spawnExecFile(file, args, options, callback) {

proc.stdout.on("data", chunk => {
stdoutLen += chunk.length;
if (stdoutLen > maxBuffer) { overflowed = true; return; }
if (stdoutLen > maxBuffer) {
overflowed = true;
return;
}
stdoutChunks.push(chunk);
});
proc.stderr.on("data", chunk => {
stderrLen += chunk.length;
if (stderrLen > maxBuffer) { overflowed = true; return; }
if (stderrLen > maxBuffer) {
overflowed = true;
return;
}
stderrChunks.push(chunk);
});

Expand Down
114 changes: 113 additions & 1 deletion .github/extensions/agentic-workflows-dashboard/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import type { CLIStatus, ExperimentInfo, PagedResult, UsageSummaryItem, Workflow
import { paginate } from "./pagination.js";

type FlashKind = "success" | "warn" | "error";
type DashboardTabId = "definitions" | "runs" | "details" | "usage" | "experiments" | "commands";
type DashboardTabId = "definitions" | "runs" | "details" | "usage" | "experiments" | "maintenance" | "commands";
type DashboardTab = { id: DashboardTabId; label: string; counter?: "definitions" | "runs" | "usage" | "experiments" };
type ReportWindow = { id: "3d" | "7d" | "1mo"; label: string; startDate: string };
type MaintenanceAction = "check-update" | "run-update" | "check-upgrade" | "run-upgrade";
type ReportMeta = {
window?: { id?: string; label?: string };
logsFetches?: number;
Expand All @@ -16,6 +17,8 @@ type ReportMeta = {
};
type RunsResponse = ReportMeta & { runs?: WorkflowRun[] };
type UsageResponse = ReportMeta & { items?: UsageSummaryItem[] };
type AuditFinding = { severity?: string };
type RunAudit = { key_findings?: AuditFinding[] };

interface DashboardState {
tabs: DashboardTab[];
Expand All @@ -34,6 +37,10 @@ interface DashboardState {
usagePaged: PagedResult<UsageSummaryItem>;
experimentsPaged: PagedResult<ExperimentInfo>;
selectedRun: WorkflowRun | null;
auditData: RunAudit | null;
includePreReleases: boolean;
maintenanceOutput: string;
maintenanceLastAction: string;
Comment on lines 39 to +43
commandInput: string;
commandOutput: string;
flashMessage: string;
Expand All @@ -43,11 +50,14 @@ interface DashboardState {
loadingRuns: boolean;
loadingUsage: boolean;
loadingExperiments: boolean;
loadingAudit: boolean;
loadingMaintenance: boolean;
errorCliStatus: string;
errorDefinitions: string;
errorRuns: string;
errorUsage: string;
errorExperiments: string;
errorAudit: string;
runsMeta: ReportMeta | null;
usageMeta: ReportMeta | null;
init(): Promise<void>;
Expand All @@ -69,7 +79,15 @@ interface DashboardState {
loadExperimentPage(page: number): void;
selectRun(runId: number): void;
viewRunDetails(runId: number): void;
loadAudit(): Promise<void>;
clearAudit(): void;
buildLogsCommand(count?: number): string;
buildMaintenanceCommand(action: MaintenanceAction): string;
maintenanceActionLabel(action: MaintenanceAction): string;
runMaintenanceAction(action: MaintenanceAction): Promise<void>;
auditHasFindings(): boolean;
auditSeverityClass(severity?: string): string;
auditPriorityClass(priority?: string): string;
buildReportSummaryMessage(meta: ReportMeta | null): string;
runCommand(): Promise<void>;
commandQuickFill(value: string): void;
Expand All @@ -91,6 +109,7 @@ const dashboardTabs: DashboardTab[] = [
{ id: "details", label: "Run details" },
{ id: "usage", label: "Usage", counter: "usage" },
{ id: "experiments", label: "Experiments", counter: "experiments" },
{ id: "maintenance", label: "Maintenance" },
{ id: "commands", label: "Commands" },
];

Expand Down Expand Up @@ -208,6 +227,10 @@ Alpine.data("dashboardApp", (): DashboardState => ({
usagePaged: paginate([], 1, 20),
experimentsPaged: paginate([], 1, 20),
selectedRun: null,
auditData: null,
includePreReleases: false,
maintenanceOutput: "Use this view to check dashboard maintenance commands before applying updates or upgrades.",
maintenanceLastAction: "",
commandInput: "",
commandOutput: "",
flashMessage: "",
Expand All @@ -217,11 +240,14 @@ Alpine.data("dashboardApp", (): DashboardState => ({
loadingRuns: false,
loadingUsage: false,
loadingExperiments: false,
loadingAudit: false,
loadingMaintenance: false,
errorCliStatus: "",
errorDefinitions: "",
errorRuns: "",
errorUsage: "",
errorExperiments: "",
errorAudit: "",
runsMeta: null,
usageMeta: null,

Expand Down Expand Up @@ -401,23 +427,109 @@ Alpine.data("dashboardApp", (): DashboardState => ({
},

selectRun(runId) {
const previousRunId = this.selectedRun?.run_id;
this.selectedRun = this.runs.find(run => run.run_id === runId) ?? null;
if (this.selectedRun?.run_id !== previousRunId) {
this.clearAudit();
}
},

viewRunDetails(runId) {
this.selectRun(runId);
this.setActiveTab("details");
},

async loadAudit() {
if (!this.selectedRun?.run_id) return;
this.loadingAudit = true;
this.errorAudit = "";
try {
const params = new URLSearchParams({ run_id: String(this.selectedRun.run_id) });
this.auditData = await fetchJson<RunAudit>(`/api/audit?${params.toString()}`);
} catch (error) {
this.auditData = null;
this.errorAudit = `Failed to load audit: ${error instanceof Error ? error.message : String(error)}`;
} finally {
this.loadingAudit = false;
}
},

clearAudit() {
this.auditData = null;
this.errorAudit = "";
this.loadingAudit = false;
},

buildLogsCommand(count = DEFAULT_LOGS_COMMAND_COUNT) {
const window = this.currentWindow();
return `gh aw logs --json -c ${count} --start-date ${window.startDate} --timeout ${this.logsTimeout}`;
},

buildMaintenanceCommand(action) {
if (action === "check-update") return "gh aw status --json";
if (action === "run-update") return "gh aw update";
if (action === "check-upgrade") return `gh aw upgrade --audit${this.includePreReleases ? " --pre-releases" : ""}`;
return `gh aw upgrade${this.includePreReleases ? " --pre-releases" : ""}`;
},

maintenanceActionLabel(action) {
if (action === "check-update") return "Check updates";
if (action === "run-update") return "Run update";
if (action === "check-upgrade") return "Check upgrades";
return "Run upgrade";
},

async runMaintenanceAction(action) {
const cmd = this.buildMaintenanceCommand(action);
this.loadingMaintenance = true;
this.maintenanceLastAction = this.maintenanceActionLabel(action);
this.maintenanceOutput = `$ ${cmd}\n(running…)`;
this.commandInput = cmd;
try {
const params = new URLSearchParams({
cmd,
window: this.selectedWindow,
timeout: String(this.logsTimeout),
});
const result = await fetchJson<{ command?: string; output?: string }>(`/api/run-command?${params.toString()}`);
this.maintenanceOutput = `$ ${result.command ?? cmd}\n${result.output ?? ""}`;
if (action === "run-update" || action === "run-upgrade") {
await fetch("/api/refresh");
await this.fetchCliStatus();
if (this.cliStatus?.available) {
await Promise.all([this.fetchDefinitions(), this.fetchRuns(), this.fetchUsage(), this.fetchExperiments()]);
}
}
Comment thread
Copilot marked this conversation as resolved.
} catch (error) {
this.maintenanceOutput = `$ ${cmd}\nError: ${error instanceof Error ? error.message : String(error)}`;
} finally {
this.loadingMaintenance = false;
}
},

cliUnavailableMessage() {
return (this.cliStatus?.message ?? this.errorCliStatus) || "gh aw is not installed.";
},

auditHasFindings() {
return (this.auditData?.key_findings ?? []).length > 0;
},

auditSeverityClass(severity) {
const normalized = (severity ?? "").toLowerCase();
if (normalized === "critical" || normalized === "high" || normalized === "error") return "Label Label--danger";
if (normalized === "medium" || normalized === "warning") return "Label Label--attention";
if (normalized === "low") return "Label Label--accent";
return "Label Label--secondary";
},

auditPriorityClass(priority) {
const normalized = (priority ?? "").toLowerCase();
if (normalized === "high" || normalized === "p0" || normalized === "p1") return "Label Label--danger";
if (normalized === "medium" || normalized === "p2") return "Label Label--attention";
return "Label Label--secondary";
},

buildReportSummaryMessage(meta) {
return buildReportMessage(meta, "No logs metadata available.");
},
Expand Down
106 changes: 103 additions & 3 deletions .github/extensions/agentic-workflows-dashboard/web/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const dashboardTabs = [
{ id: "details", label: "Run details" },
{ id: "usage", label: "Usage", counter: "usage" },
{ id: "experiments", label: "Experiments", counter: "experiments" },
{ id: "maintenance", label: "Maintenance" },
{ id: "commands", label: "Commands" },
];
const reportWindows = [
Expand Down Expand Up @@ -121,6 +122,10 @@ Alpine.data("dashboardApp", () => ({
usagePaged: paginate([], 1, 20),
experimentsPaged: paginate([], 1, 20),
selectedRun: null,
auditData: null,
includePreReleases: false,
maintenanceOutput: "Use this view to check dashboard maintenance commands before applying updates or upgrades.",
maintenanceLastAction: "",
commandInput: "",
Comment on lines 124 to 129
commandOutput: "",
flashMessage: "",
Expand All @@ -130,11 +135,14 @@ Alpine.data("dashboardApp", () => ({
loadingRuns: false,
loadingUsage: false,
loadingExperiments: false,
loadingAudit: false,
loadingMaintenance: false,
errorCliStatus: "",
errorDefinitions: "",
errorRuns: "",
errorUsage: "",
errorExperiments: "",
errorAudit: "",
runsMeta: null,
usageMeta: null,
async init() {
Expand All @@ -153,9 +161,7 @@ Alpine.data("dashboardApp", () => ({
return reportWindowById(this.selectedWindow);
},
reportWindowClass(windowId) {
return this.selectedWindow === windowId
? "BtnGroup-item btn btn-sm btn-primary"
: "BtnGroup-item btn btn-sm";
return this.selectedWindow === windowId ? "BtnGroup-item btn btn-sm btn-primary" : "BtnGroup-item btn btn-sm";
},
async selectReportWindow(windowId) {
if (this.selectedWindow === windowId)
Expand Down Expand Up @@ -315,19 +321,113 @@ Alpine.data("dashboardApp", () => ({
this.experimentsPaged = paginate(this.experiments, page, this.pageSize);
},
selectRun(runId) {
const previousRunId = this.selectedRun?.run_id;
this.selectedRun = this.runs.find(run => run.run_id === runId) ?? null;
if (this.selectedRun?.run_id !== previousRunId) {
this.clearAudit();
}
},
viewRunDetails(runId) {
this.selectRun(runId);
this.setActiveTab("details");
},
async loadAudit() {
if (!this.selectedRun?.run_id)
return;
this.loadingAudit = true;
this.errorAudit = "";
try {
const params = new URLSearchParams({ run_id: String(this.selectedRun.run_id) });
this.auditData = await fetchJson(`/api/audit?${params.toString()}`);
}
catch (error) {
this.auditData = null;
this.errorAudit = `Failed to load audit: ${error instanceof Error ? error.message : String(error)}`;
}
finally {
this.loadingAudit = false;
}
},
clearAudit() {
this.auditData = null;
this.errorAudit = "";
this.loadingAudit = false;
},
buildLogsCommand(count = DEFAULT_LOGS_COMMAND_COUNT) {
const window = this.currentWindow();
return `gh aw logs --json -c ${count} --start-date ${window.startDate} --timeout ${this.logsTimeout}`;
},
buildMaintenanceCommand(action) {
if (action === "check-update")
return "gh aw status --json";
if (action === "run-update")
return "gh aw update";
if (action === "check-upgrade")
return `gh aw upgrade --audit${this.includePreReleases ? " --pre-releases" : ""}`;
return `gh aw upgrade${this.includePreReleases ? " --pre-releases" : ""}`;
},
maintenanceActionLabel(action) {
if (action === "check-update")
return "Check updates";
if (action === "run-update")
return "Run update";
if (action === "check-upgrade")
return "Check upgrades";
return "Run upgrade";
},
async runMaintenanceAction(action) {
const cmd = this.buildMaintenanceCommand(action);
this.loadingMaintenance = true;
this.maintenanceLastAction = this.maintenanceActionLabel(action);
this.maintenanceOutput = `$ ${cmd}\n(running…)`;
this.commandInput = cmd;
try {
const params = new URLSearchParams({
cmd,
window: this.selectedWindow,
timeout: String(this.logsTimeout),
});
const result = await fetchJson(`/api/run-command?${params.toString()}`);
this.maintenanceOutput = `$ ${result.command ?? cmd}\n${result.output ?? ""}`;
if (action === "run-update" || action === "run-upgrade") {
await fetch("/api/refresh");
await this.fetchCliStatus();
if (this.cliStatus?.available) {
await Promise.all([this.fetchDefinitions(), this.fetchRuns(), this.fetchUsage(), this.fetchExperiments()]);
}
}
Comment thread
Copilot marked this conversation as resolved.
}
catch (error) {
this.maintenanceOutput = `$ ${cmd}\nError: ${error instanceof Error ? error.message : String(error)}`;
}
finally {
this.loadingMaintenance = false;
}
},
cliUnavailableMessage() {
return (this.cliStatus?.message ?? this.errorCliStatus) || "gh aw is not installed.";
},
auditHasFindings() {
return (this.auditData?.key_findings ?? []).length > 0;
},
auditSeverityClass(severity) {
const normalized = (severity ?? "").toLowerCase();
if (normalized === "critical" || normalized === "high" || normalized === "error")
return "Label Label--danger";
if (normalized === "medium" || normalized === "warning")
return "Label Label--attention";
if (normalized === "low")
return "Label Label--accent";
return "Label Label--secondary";
},
auditPriorityClass(priority) {
const normalized = (priority ?? "").toLowerCase();
if (normalized === "high" || normalized === "p0" || normalized === "p1")
return "Label Label--danger";
if (normalized === "medium" || normalized === "p2")
return "Label Label--attention";
return "Label Label--secondary";
},
buildReportSummaryMessage(meta) {
return buildReportMessage(meta, "No logs metadata available.");
},
Expand Down
Loading