import { join } from "node:path"; import type { RoleStep, WorkflowMessage } from "@uncaged/nerve-core"; type SolveIssueParse = { host: string; owner: string; repo: string; number: number; }; type SolveIssueRepo = { path: string; defaultBranch: string; packageManager: string; }; const HOME = process.env.HOME ?? "/home/azureuser"; function extractMarkedSection(text: string, marker: string): Record | null { const escaped = marker.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); const re = new RegExp(`---${escaped}---\\s*([\\s\\S]*?)(?:\\n---|$)`); const m = text.match(re); if (m === null) { return null; } const rec: Record = {}; for (const line of m[1].split("\n")) { const kv = line.match(/^([a-zA-Z]+):\s*(.+)$/); if (kv !== null) { rec[kv[1]] = kv[2].trim(); } } return Object.keys(rec).length > 0 ? rec : null; } function parseSolveIssueParse(text: string): SolveIssueParse | null { const rec = extractMarkedSection(text, "SOLVE_ISSUE_PARSE"); if (rec === null) { return null; } const host = rec.host ?? ""; const owner = rec.owner ?? ""; const repo = rec.repo ?? ""; const num = Number(rec.number ?? ""); if (host.length === 0 || owner.length === 0 || repo.length === 0 || !Number.isFinite(num) || num <= 0) { return null; } return { host, owner, repo, number: num }; } function parseSolveIssueRepo(text: string): SolveIssueRepo | null { const rec = extractMarkedSection(text, "SOLVE_ISSUE_REPO"); if (rec === null) { return null; } const path = rec.path ?? ""; if (path.length === 0) { return null; } return { path, defaultBranch: rec.defaultBranch ?? "main", packageManager: rec.packageManager ?? "pnpm", }; } /** Prefer explicit prepare marker; else ~/Code// from read-issue parse block. */ export function resolveRepoCwd(messages: WorkflowMessage[]): string | null { for (let i = messages.length - 1; i >= 0; i--) { if (messages[i].role === "prepare") { const repo = parseSolveIssueRepo(messages[i].content); if (repo !== null) { return repo.path; } } } for (let i = messages.length - 1; i >= 0; i--) { if (messages[i].role === "read-issue") { const parsed = parseSolveIssueParse(messages[i].content); if (parsed !== null) { return join(HOME, "Code", parsed.owner, parsed.repo); } } } return null; }