agent-orchestrator/packages/web/src/lib/format.ts

59 lines
2.0 KiB
TypeScript

/**
* Pure formatting utilities safe for both server and client components.
* No side effects, no external dependencies.
*/
import type { DashboardSession } from "./types.js";
/**
* Humanize a git branch name into a readable title.
* e.g., "feat/infer-project-id" → "Infer Project ID"
* "fix/broken-auth-flow" → "Broken Auth Flow"
* "session/ao-52" → "ao-52"
*/
export function humanizeBranch(branch: string): string {
// Remove common prefixes
const withoutPrefix = branch.replace(
/^(?:feat|fix|chore|refactor|docs|test|ci|session|release|hotfix|feature|bugfix|build|wip|improvement)\//,
"",
);
// Replace hyphens and underscores with spaces, then title-case each word
return withoutPrefix
.replace(/[-_]/g, " ")
.replace(/\b\w/g, (c) => c.toUpperCase())
.trim();
}
/**
* Compute the best display title for a session card.
*
* Fallback chain (ordered by signal quality):
* 1. PR title — human-visible deliverable name
* 2. Quality summary — real agent-generated summary (not a fallback)
* 3. Issue title — human-written task description
* 4. Any summary — even a fallback excerpt is better than nothing
* 5. Humanized branch — last resort with semantic content
* 6. Status text — absolute fallback
*/
export function getSessionTitle(session: DashboardSession): string {
// 1. PR title — always best
if (session.pr?.title) return session.pr.title;
// 2. Quality summary — skip fallback summaries (truncated spawn prompts)
if (session.summary && !session.summaryIsFallback) {
return session.summary;
}
// 3. Issue title — human-written task description
if (session.issueTitle) return session.issueTitle;
// 4. Any summary — even fallback excerpts beat branch names
if (session.summary) return session.summary;
// 5. Humanized branch
if (session.branch) return humanizeBranch(session.branch);
// 6. Status
return session.status;
}