Files
stack/extensions/goal/lib/display.ts
T

45 lines
2.2 KiB
TypeScript

import type { GoalState } from "./state.ts";
export type GoalDisplay = {
label: "Active" | "Waiting" | "Paused" | "Blocked" | "Complete" | "None";
color: "accent" | "warning" | "error" | "success" | "muted";
};
export function goalDisplay(state: GoalState): GoalDisplay {
if (state.status === "none") return state.lastOutcome
? { label: "Complete", color: "success" }
: { label: "None", color: "muted" };
if (state.status === "blocked" ||
(state.status === "paused" && state.pausedReason?.startsWith("blocked:"))) {
return { label: "Blocked", color: "error" };
}
if (state.status === "paused") return { label: "Paused", color: "warning" };
if (state.activeWait && !state.activeWait.wakeSent) return { label: "Waiting", color: "warning" };
return { label: "Active", color: "accent" };
}
/** Full recall is deliberately separate from short transient notifications. */
export function goalDetails(state: GoalState): string {
const display = goalDisplay(state);
if (display.label === "None") return "Goal: None\nUse /goal <text> to set a goal.";
const completed = state.status === "none" ? state.lastOutcome : undefined;
const lines = [`Goal: ${display.label}`, "", completed?.text ?? state.text, ""];
if (completed) {
lines.push(`Completed: ${completed.at}`, `Evidence: ${completed.evidence}`);
} else {
if (state.pausedReason) lines.push(`Reason: ${state.pausedReason}`);
if (state.status === "active" && state.activeWait) {
lines.push(`Wait owner: ${state.activeWait.owner}`);
if (state.activeWait.nextCheck) lines.push(`Next check: ${state.activeWait.nextCheck}`);
if (state.activeWait.watchId) lines.push(`Watch: ${state.activeWait.watchId}`);
if (state.activeWait.deadlineAt !== undefined) {
const deadline = new Date(state.activeWait.deadlineAt);
lines.push(`Deadline: ${Number.isFinite(deadline.getTime()) ? deadline.toISOString() : "invalid"}`);
}
}
lines.push(`Checks: ${state.checks}/${state.maxChecks}`, `No-progress reports: ${state.noProgressReports}/${state.maxNoProgressReports}`);
}
lines.push("", "/goal stop | /goal resume | /goal clear");
return lines.join("\n");
}