()
| 180 | } |
| 181 | |
| 182 | async function runIssueFlow(): Promise<number> { |
| 183 | intro("Magic Context Issue Report"); |
| 184 | |
| 185 | const title = await text("Issue title", { |
| 186 | placeholder: "Short summary of the problem", |
| 187 | validate: (value) => (value.trim() ? undefined : "Title is required"), |
| 188 | }); |
| 189 | const description = await text("Issue description", { |
| 190 | placeholder: "Describe what happened, what you expected, and repro steps", |
| 191 | validate: (value) => (value.trim() ? undefined : "Description is required"), |
| 192 | }); |
| 193 | |
| 194 | const s = spinner(); |
| 195 | s.start("Collecting diagnostics"); |
| 196 | |
| 197 | try { |
| 198 | const report = await collectDiagnostics(); |
| 199 | s.stop("Diagnostics collected"); |
| 200 | |
| 201 | // Ask the user which session this issue relates to. Only show the |
| 202 | // picker when there's more than one recent session — otherwise the |
| 203 | // single-session case is unambiguous, and the no-session case |
| 204 | // (Node-only run without bun:sqlite) skips filtering entirely. |
| 205 | let sessionFilter: string | null = null; |
| 206 | if (report.recentSessions.length > 1) { |
| 207 | const choice = await selectOne( |
| 208 | "Which session is this issue about? (filters log lines from other sessions)", |
| 209 | [ |
| 210 | ...report.recentSessions.map((session, index) => { |
| 211 | const displayTitle = session.title.trim() || "(no title)"; |
| 212 | const truncatedTitle = |
| 213 | displayTitle.length > 50 |
| 214 | ? `${displayTitle.slice(0, 47)}...` |
| 215 | : displayTitle; |
| 216 | return { |
| 217 | label: `${truncatedTitle} — ${session.sessionId}${index === 0 ? " (most recent)" : ""}`, |
| 218 | value: session.sessionId, |
| 219 | }; |
| 220 | }), |
| 221 | { |
| 222 | label: "All sessions (no filtering)", |
| 223 | value: "__all__", |
| 224 | }, |
| 225 | ], |
| 226 | ); |
| 227 | sessionFilter = choice === "__all__" ? null : choice; |
| 228 | } |
| 229 | |
| 230 | s.start("Bundling issue report"); |
| 231 | const bundled = await bundleIssueReport(report, description, title, sessionFilter); |
| 232 | s.stop(`Report written to ${bundled.path}`); |
| 233 | |
| 234 | const shouldSubmit = await confirm("Submit this issue on GitHub now?", true); |
| 235 | if (shouldSubmit && isGhInstalled()) { |
| 236 | const result = spawnSync( |
| 237 | "gh", |
| 238 | [ |
| 239 | "issue", |
no test coverage detected