@bragduck/cli 2.2.0 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1166,11 +1166,19 @@ var init_api_service = __esm({
1166
1166
  * Refine brags using AI
1167
1167
  */
1168
1168
  async refineBrags(request) {
1169
- logger.debug(`Refining ${request.brags.length} brags`);
1169
+ const MAX_TEXT_LENGTH = 1e4;
1170
+ const trimmedRequest = {
1171
+ ...request,
1172
+ brags: request.brags.map((brag) => ({
1173
+ ...brag,
1174
+ text: brag.text && brag.text.length > MAX_TEXT_LENGTH ? brag.text.substring(0, MAX_TEXT_LENGTH) : brag.text
1175
+ }))
1176
+ };
1177
+ logger.debug(`Refining ${trimmedRequest.brags.length} brags`);
1170
1178
  try {
1171
1179
  const response = await this.makeRequest(API_ENDPOINTS.BRAGS.REFINE, {
1172
1180
  method: "POST",
1173
- body: request
1181
+ body: trimmedRequest
1174
1182
  });
1175
1183
  logger.debug(`Successfully refined ${response.refined_brags.length} brags`);
1176
1184
  return response;
@@ -2161,12 +2169,12 @@ function formatRefinedCommitsTable(brags, selectedCommits) {
2161
2169
  });
2162
2170
  brags.forEach((brag, index) => {
2163
2171
  const isNewBragType = !("sha" in brag);
2164
- let displaySha;
2172
+ let displaySha = `#${index + 1}`;
2165
2173
  if (isNewBragType && selectedCommits) {
2166
2174
  const commit = selectedCommits[index];
2167
- if (commit.sha.startsWith("pr-")) {
2175
+ if (commit && commit.sha.startsWith("pr-")) {
2168
2176
  displaySha = commit.sha.replace("pr-", "#");
2169
- } else {
2177
+ } else if (commit) {
2170
2178
  displaySha = commit.sha.substring(0, 7);
2171
2179
  }
2172
2180
  } else if (!isNewBragType) {
@@ -2312,12 +2320,14 @@ async function promptReviewBrags(refinedBrags, selectedCommits) {
2312
2320
  let reviewingBrag = true;
2313
2321
  while (reviewingBrag) {
2314
2322
  const isNewBragType = !("sha" in currentBrag);
2315
- let displaySha;
2323
+ let displaySha = `#${i + 1}`;
2316
2324
  let prUrl;
2317
2325
  if (isNewBragType && selectedCommits) {
2318
2326
  const commit = selectedCommits[i];
2319
- displaySha = commit.sha.startsWith("pr-") ? commit.sha.replace("pr-", "#") : commit.sha.substring(0, 7);
2320
- prUrl = commit.url;
2327
+ if (commit) {
2328
+ displaySha = commit.sha.startsWith("pr-") ? commit.sha.replace("pr-", "#") : commit.sha.substring(0, 7);
2329
+ prUrl = commit.url;
2330
+ }
2321
2331
  } else if (!isNewBragType) {
2322
2332
  const commit = currentBrag;
2323
2333
  displaySha = commit.sha.startsWith("pr-") ? commit.sha.replace("pr-", "#") : commit.sha.substring(0, 7);
@@ -2579,23 +2589,25 @@ async function scanCommand(options = {}) {
2579
2589
  logger.log("");
2580
2590
  logger.log(formatCommitStats(commits));
2581
2591
  logger.log("");
2582
- const sortOption = await promptSortOption();
2583
- logger.log("");
2584
2592
  let sortedCommits = [...commits];
2585
- if (sortOption === "date") {
2586
- sortedCommits.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
2587
- } else if (sortOption === "size") {
2588
- sortedCommits.sort((a, b) => {
2589
- const sizeA = (a.diffStats?.insertions || 0) + (a.diffStats?.deletions || 0);
2590
- const sizeB = (b.diffStats?.insertions || 0) + (b.diffStats?.deletions || 0);
2591
- return sizeB - sizeA;
2592
- });
2593
- } else if (sortOption === "files") {
2594
- sortedCommits.sort((a, b) => {
2595
- const filesA = a.diffStats?.filesChanged || 0;
2596
- const filesB = b.diffStats?.filesChanged || 0;
2597
- return filesB - filesA;
2598
- });
2593
+ if (commits.length > 1) {
2594
+ const sortOption = await promptSortOption();
2595
+ logger.log("");
2596
+ if (sortOption === "date") {
2597
+ sortedCommits.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
2598
+ } else if (sortOption === "size") {
2599
+ sortedCommits.sort((a, b) => {
2600
+ const sizeA = (a.diffStats?.insertions || 0) + (a.diffStats?.deletions || 0);
2601
+ const sizeB = (b.diffStats?.insertions || 0) + (b.diffStats?.deletions || 0);
2602
+ return sizeB - sizeA;
2603
+ });
2604
+ } else if (sortOption === "files") {
2605
+ sortedCommits.sort((a, b) => {
2606
+ const filesA = a.diffStats?.filesChanged || 0;
2607
+ const filesB = b.diffStats?.filesChanged || 0;
2608
+ return filesB - filesA;
2609
+ });
2610
+ }
2599
2611
  }
2600
2612
  const selectedShas = await promptSelectCommits(sortedCommits);
2601
2613
  if (selectedShas.length === 0) {
@@ -2607,14 +2619,38 @@ async function scanCommand(options = {}) {
2607
2619
  const selectedCommits = sortedCommits.filter((c) => selectedShas.includes(c.sha));
2608
2620
  logger.log(formatSelectionSummary(selectedCommits.length, selectedCommits));
2609
2621
  logger.log("");
2622
+ const existingBrags = await apiService.listBrags({ limit: 100 });
2623
+ logger.debug(`Fetched ${existingBrags.brags.length} existing brags`);
2624
+ const existingUrls = new Set(existingBrags.brags.flatMap((b) => b.attachments || []));
2625
+ logger.debug(`Existing PR URLs in attachments: ${existingUrls.size}`);
2626
+ const duplicates = selectedCommits.filter((c) => c.url && existingUrls.has(c.url));
2627
+ const newCommits = selectedCommits.filter((c) => !c.url || !existingUrls.has(c.url));
2628
+ logger.debug(`Duplicates: ${duplicates.length}, New: ${newCommits.length}`);
2629
+ if (duplicates.length > 0) {
2630
+ logger.log("");
2631
+ logger.info(
2632
+ colors.warning(
2633
+ `${duplicates.length} PR${duplicates.length > 1 ? "s" : ""} already added to Bragduck - skipping`
2634
+ )
2635
+ );
2636
+ logger.log("");
2637
+ }
2638
+ if (newCommits.length === 0) {
2639
+ logger.log("");
2640
+ logger.info(
2641
+ theme.secondary("All selected PRs already exist in Bragduck. Nothing to refine.")
2642
+ );
2643
+ logger.log("");
2644
+ return;
2645
+ }
2610
2646
  const refineSpinner = createStepSpinner(
2611
2647
  3,
2612
2648
  TOTAL_STEPS,
2613
- `Refining ${theme.count(selectedCommits.length)} PR${selectedCommits.length > 1 ? "s" : ""} with AI`
2649
+ `Refining ${theme.count(newCommits.length)} PR${newCommits.length > 1 ? "s" : ""} with AI`
2614
2650
  );
2615
2651
  refineSpinner.start();
2616
2652
  const refineRequest = {
2617
- brags: selectedCommits.map((c) => ({
2653
+ brags: newCommits.map((c) => ({
2618
2654
  text: c.message,
2619
2655
  date: c.date,
2620
2656
  title: c.message.split("\n")[0]
@@ -2627,9 +2663,9 @@ async function scanCommand(options = {}) {
2627
2663
  logger.log("");
2628
2664
  logger.info("Preview of refined brags:");
2629
2665
  logger.log("");
2630
- logger.log(formatRefinedCommitsTable(refinedBrags, selectedCommits));
2666
+ logger.log(formatRefinedCommitsTable(refinedBrags, newCommits));
2631
2667
  logger.log("");
2632
- const acceptedBrags = await promptReviewBrags(refinedBrags, selectedCommits);
2668
+ const acceptedBrags = await promptReviewBrags(refinedBrags, newCommits);
2633
2669
  if (acceptedBrags.length === 0) {
2634
2670
  logger.log("");
2635
2671
  logger.info(theme.secondary("No brags selected for creation. Scan cancelled."));
@@ -2645,7 +2681,7 @@ async function scanCommand(options = {}) {
2645
2681
  createSpinner2.start();
2646
2682
  const createRequest = {
2647
2683
  brags: acceptedBrags.map((refined, index) => {
2648
- const originalCommit = selectedCommits[index];
2684
+ const originalCommit = newCommits[index];
2649
2685
  return {
2650
2686
  commit_sha: originalCommit?.sha || `brag-${index}`,
2651
2687
  title: refined.refined_title,
@@ -2655,7 +2691,8 @@ async function scanCommand(options = {}) {
2655
2691
  date: refined.date,
2656
2692
  commit_url: originalCommit?.url || "",
2657
2693
  impact_score: refined.suggested_impactLevel,
2658
- impact_description: refined.impact_description
2694
+ impact_description: refined.impact_description,
2695
+ attachments: originalCommit?.url ? [originalCommit.url] : []
2659
2696
  };
2660
2697
  })
2661
2698
  };