@bbearai/core 0.8.0 → 0.8.1

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.
package/dist/index.d.mts CHANGED
@@ -377,6 +377,8 @@ interface TestAssignment {
377
377
  startedAt?: string;
378
378
  /** Duration in seconds (calculated when completed) */
379
379
  durationSeconds?: number;
380
+ /** Active time in seconds, computed from presence heartbeats */
381
+ activeSeconds?: number;
380
382
  /** Whether this is a verification assignment for a fixed bug */
381
383
  isVerification?: boolean;
382
384
  /** Original report ID if this is a verification assignment */
@@ -789,6 +791,14 @@ interface TesterIssue {
789
791
  originalBugId?: string;
790
792
  /** Original bug title (for reopened/test_fail issues) */
791
793
  originalBugTitle?: string;
794
+ /** Resolution notes from the developer (for ready_to_test issues) */
795
+ resolutionNotes?: string;
796
+ /** Fix commit SHA (for ready_to_test issues) */
797
+ fixCommitSha?: string;
798
+ /** Fix commit message */
799
+ fixCommitMessage?: string;
800
+ /** Files changed in the fix */
801
+ fixFilesChanged?: string[];
792
802
  }
793
803
  /** Delivery status for captured emails */
794
804
  type EmailDeliveryStatus = 'pending' | 'sent' | 'delivered' | 'bounced' | 'dropped' | 'deferred';
package/dist/index.d.ts CHANGED
@@ -377,6 +377,8 @@ interface TestAssignment {
377
377
  startedAt?: string;
378
378
  /** Duration in seconds (calculated when completed) */
379
379
  durationSeconds?: number;
380
+ /** Active time in seconds, computed from presence heartbeats */
381
+ activeSeconds?: number;
380
382
  /** Whether this is a verification assignment for a fixed bug */
381
383
  isVerification?: boolean;
382
384
  /** Original report ID if this is a verification assignment */
@@ -789,6 +791,14 @@ interface TesterIssue {
789
791
  originalBugId?: string;
790
792
  /** Original bug title (for reopened/test_fail issues) */
791
793
  originalBugTitle?: string;
794
+ /** Resolution notes from the developer (for ready_to_test issues) */
795
+ resolutionNotes?: string;
796
+ /** Fix commit SHA (for ready_to_test issues) */
797
+ fixCommitSha?: string;
798
+ /** Fix commit message */
799
+ fixCommitMessage?: string;
800
+ /** Files changed in the fix */
801
+ fixFilesChanged?: string[];
792
802
  }
793
803
  /** Delivery status for captured emails */
794
804
  type EmailDeliveryStatus = 'pending' | 'sent' | 'delivered' | 'bounced' | 'dropped' | 'deferred';
package/dist/index.js CHANGED
@@ -1475,55 +1475,66 @@ var BugBearClient = class {
1475
1475
  ...pendingResult.data || [],
1476
1476
  ...completedResult.data || []
1477
1477
  ];
1478
- const mapItem = (item) => ({
1479
- id: item.id,
1480
- status: item.status,
1481
- startedAt: item.started_at,
1482
- skipReason: item.skip_reason,
1483
- isVerification: item.is_verification || false,
1484
- originalReportId: item.original_report_id,
1485
- testCase: {
1486
- id: item.test_case.id,
1487
- title: item.test_case.title,
1488
- testKey: item.test_case.test_key,
1489
- description: item.test_case.description,
1490
- steps: item.test_case.steps,
1491
- expectedResult: item.test_case.expected_result,
1492
- priority: item.test_case.priority,
1493
- targetRoute: item.test_case.target_route,
1494
- track: item.test_case.track ? {
1495
- id: item.test_case.track.id,
1496
- name: item.test_case.track.name,
1497
- icon: item.test_case.track.icon,
1498
- color: item.test_case.track.color,
1499
- testTemplate: item.test_case.track.test_template,
1500
- rubricMode: item.test_case.track.rubric_mode || "pass_fail",
1501
- description: item.test_case.track.description
1502
- } : void 0,
1503
- group: item.test_case.group ? {
1504
- id: item.test_case.group.id,
1505
- name: item.test_case.group.name,
1506
- description: item.test_case.group.description,
1507
- sortOrder: item.test_case.group.sort_order
1508
- } : void 0,
1509
- role: item.test_case.role ? {
1510
- id: item.test_case.role.id,
1511
- name: item.test_case.role.name,
1512
- slug: item.test_case.role.slug,
1513
- color: item.test_case.role.color,
1514
- description: item.test_case.role.description,
1515
- loginHint: item.test_case.role.login_hint
1516
- } : void 0,
1517
- platforms: item.test_case.platforms || void 0
1518
- }
1519
- });
1520
- const mapped = allData.filter((item) => {
1521
- if (!item.test_case) {
1522
- console.warn("BugBear: Assignment returned without test_case", { id: item.id });
1523
- return false;
1524
- }
1525
- return true;
1526
- }).map(mapItem);
1478
+ const mapItem = (item) => {
1479
+ const tc = item.test_case;
1480
+ return {
1481
+ id: item.id,
1482
+ status: item.status,
1483
+ startedAt: item.started_at,
1484
+ skipReason: item.skip_reason,
1485
+ isVerification: item.is_verification || false,
1486
+ originalReportId: item.original_report_id,
1487
+ testCase: tc ? {
1488
+ id: tc.id,
1489
+ title: tc.title,
1490
+ testKey: tc.test_key,
1491
+ description: tc.description,
1492
+ steps: tc.steps,
1493
+ expectedResult: tc.expected_result,
1494
+ priority: tc.priority,
1495
+ targetRoute: tc.target_route,
1496
+ track: tc.track ? {
1497
+ id: tc.track.id,
1498
+ name: tc.track.name,
1499
+ icon: tc.track.icon,
1500
+ color: tc.track.color,
1501
+ testTemplate: tc.track.test_template,
1502
+ rubricMode: tc.track.rubric_mode || "pass_fail",
1503
+ description: tc.track.description
1504
+ } : void 0,
1505
+ group: tc.group ? {
1506
+ id: tc.group.id,
1507
+ name: tc.group.name,
1508
+ description: tc.group.description,
1509
+ sortOrder: tc.group.sort_order
1510
+ } : void 0,
1511
+ role: tc.role ? {
1512
+ id: tc.role.id,
1513
+ name: tc.role.name,
1514
+ slug: tc.role.slug,
1515
+ color: tc.role.color,
1516
+ description: tc.role.description,
1517
+ loginHint: tc.role.login_hint
1518
+ } : void 0,
1519
+ platforms: tc.platforms || void 0
1520
+ } : {
1521
+ // Standalone verification assignment (bug reported without a test case)
1522
+ id: item.original_report_id || item.id,
1523
+ title: item.notes || "Bug Verification",
1524
+ testKey: "VERIFY",
1525
+ description: "Verify that the reported bug has been fixed",
1526
+ steps: [],
1527
+ expectedResult: "The bug should no longer be reproducible",
1528
+ priority: "P1",
1529
+ targetRoute: void 0,
1530
+ track: void 0,
1531
+ group: void 0,
1532
+ role: void 0,
1533
+ platforms: void 0
1534
+ }
1535
+ };
1536
+ };
1537
+ const mapped = allData.map(mapItem);
1527
1538
  mapped.sort((a, b) => {
1528
1539
  if (a.isVerification && !b.isVerification) return -1;
1529
1540
  if (!a.isVerification && b.isVerification) return 1;
@@ -1617,7 +1628,7 @@ var BugBearClient = class {
1617
1628
  async updateAssignmentStatus(assignmentId, status, options) {
1618
1629
  try {
1619
1630
  await this.ensureReady();
1620
- const { data: currentAssignment, error: fetchError } = await this.supabase.from("test_assignments").select("status, started_at").eq("id", assignmentId).single();
1631
+ const { data: currentAssignment, error: fetchError } = await this.supabase.from("test_assignments").select("status, started_at, tester_id, project_id").eq("id", assignmentId).single();
1621
1632
  if (fetchError || !currentAssignment) {
1622
1633
  console.error("BugBear: Assignment not found", {
1623
1634
  message: fetchError?.message,
@@ -1638,6 +1649,19 @@ var BugBearClient = class {
1638
1649
  const completedAt = /* @__PURE__ */ new Date();
1639
1650
  durationSeconds = Math.round((completedAt.getTime() - startedAt.getTime()) / 1e3);
1640
1651
  updateData.duration_seconds = durationSeconds;
1652
+ if (currentAssignment.tester_id && currentAssignment.project_id) {
1653
+ try {
1654
+ const { data: activeTime } = await this.supabase.rpc("compute_assignment_active_time", {
1655
+ p_tester_id: currentAssignment.tester_id,
1656
+ p_project_id: currentAssignment.project_id,
1657
+ p_started_at: currentAssignment.started_at,
1658
+ p_completed_at: updateData.completed_at
1659
+ });
1660
+ updateData.active_seconds = typeof activeTime === "number" ? activeTime : Math.min(durationSeconds, 1800);
1661
+ } catch {
1662
+ updateData.active_seconds = Math.min(durationSeconds, 1800);
1663
+ }
1664
+ }
1641
1665
  }
1642
1666
  }
1643
1667
  if (options?.notes) {
@@ -1716,6 +1740,7 @@ var BugBearClient = class {
1716
1740
  started_at: (/* @__PURE__ */ new Date()).toISOString(),
1717
1741
  completed_at: null,
1718
1742
  duration_seconds: null,
1743
+ active_seconds: null,
1719
1744
  skip_reason: null
1720
1745
  }).eq("id", assignmentId).eq("status", current.status);
1721
1746
  if (error) {
@@ -2023,7 +2048,11 @@ var BugBearClient = class {
2023
2048
  verifiedByName: row.verified_by_name || void 0,
2024
2049
  verifiedAt: row.verified_at || void 0,
2025
2050
  originalBugId: row.original_bug_id || void 0,
2026
- originalBugTitle: row.original_bug_title || void 0
2051
+ originalBugTitle: row.original_bug_title || void 0,
2052
+ resolutionNotes: row.resolution_notes || void 0,
2053
+ fixCommitSha: row.code_context?.fix?.commit_sha || void 0,
2054
+ fixCommitMessage: row.code_context?.fix?.commit_message || void 0,
2055
+ fixFilesChanged: row.code_context?.fix?.files_changed || void 0
2027
2056
  }));
2028
2057
  } catch (err) {
2029
2058
  console.error("BugBear: Error fetching issues", err);
package/dist/index.mjs CHANGED
@@ -1429,55 +1429,66 @@ var BugBearClient = class {
1429
1429
  ...pendingResult.data || [],
1430
1430
  ...completedResult.data || []
1431
1431
  ];
1432
- const mapItem = (item) => ({
1433
- id: item.id,
1434
- status: item.status,
1435
- startedAt: item.started_at,
1436
- skipReason: item.skip_reason,
1437
- isVerification: item.is_verification || false,
1438
- originalReportId: item.original_report_id,
1439
- testCase: {
1440
- id: item.test_case.id,
1441
- title: item.test_case.title,
1442
- testKey: item.test_case.test_key,
1443
- description: item.test_case.description,
1444
- steps: item.test_case.steps,
1445
- expectedResult: item.test_case.expected_result,
1446
- priority: item.test_case.priority,
1447
- targetRoute: item.test_case.target_route,
1448
- track: item.test_case.track ? {
1449
- id: item.test_case.track.id,
1450
- name: item.test_case.track.name,
1451
- icon: item.test_case.track.icon,
1452
- color: item.test_case.track.color,
1453
- testTemplate: item.test_case.track.test_template,
1454
- rubricMode: item.test_case.track.rubric_mode || "pass_fail",
1455
- description: item.test_case.track.description
1456
- } : void 0,
1457
- group: item.test_case.group ? {
1458
- id: item.test_case.group.id,
1459
- name: item.test_case.group.name,
1460
- description: item.test_case.group.description,
1461
- sortOrder: item.test_case.group.sort_order
1462
- } : void 0,
1463
- role: item.test_case.role ? {
1464
- id: item.test_case.role.id,
1465
- name: item.test_case.role.name,
1466
- slug: item.test_case.role.slug,
1467
- color: item.test_case.role.color,
1468
- description: item.test_case.role.description,
1469
- loginHint: item.test_case.role.login_hint
1470
- } : void 0,
1471
- platforms: item.test_case.platforms || void 0
1472
- }
1473
- });
1474
- const mapped = allData.filter((item) => {
1475
- if (!item.test_case) {
1476
- console.warn("BugBear: Assignment returned without test_case", { id: item.id });
1477
- return false;
1478
- }
1479
- return true;
1480
- }).map(mapItem);
1432
+ const mapItem = (item) => {
1433
+ const tc = item.test_case;
1434
+ return {
1435
+ id: item.id,
1436
+ status: item.status,
1437
+ startedAt: item.started_at,
1438
+ skipReason: item.skip_reason,
1439
+ isVerification: item.is_verification || false,
1440
+ originalReportId: item.original_report_id,
1441
+ testCase: tc ? {
1442
+ id: tc.id,
1443
+ title: tc.title,
1444
+ testKey: tc.test_key,
1445
+ description: tc.description,
1446
+ steps: tc.steps,
1447
+ expectedResult: tc.expected_result,
1448
+ priority: tc.priority,
1449
+ targetRoute: tc.target_route,
1450
+ track: tc.track ? {
1451
+ id: tc.track.id,
1452
+ name: tc.track.name,
1453
+ icon: tc.track.icon,
1454
+ color: tc.track.color,
1455
+ testTemplate: tc.track.test_template,
1456
+ rubricMode: tc.track.rubric_mode || "pass_fail",
1457
+ description: tc.track.description
1458
+ } : void 0,
1459
+ group: tc.group ? {
1460
+ id: tc.group.id,
1461
+ name: tc.group.name,
1462
+ description: tc.group.description,
1463
+ sortOrder: tc.group.sort_order
1464
+ } : void 0,
1465
+ role: tc.role ? {
1466
+ id: tc.role.id,
1467
+ name: tc.role.name,
1468
+ slug: tc.role.slug,
1469
+ color: tc.role.color,
1470
+ description: tc.role.description,
1471
+ loginHint: tc.role.login_hint
1472
+ } : void 0,
1473
+ platforms: tc.platforms || void 0
1474
+ } : {
1475
+ // Standalone verification assignment (bug reported without a test case)
1476
+ id: item.original_report_id || item.id,
1477
+ title: item.notes || "Bug Verification",
1478
+ testKey: "VERIFY",
1479
+ description: "Verify that the reported bug has been fixed",
1480
+ steps: [],
1481
+ expectedResult: "The bug should no longer be reproducible",
1482
+ priority: "P1",
1483
+ targetRoute: void 0,
1484
+ track: void 0,
1485
+ group: void 0,
1486
+ role: void 0,
1487
+ platforms: void 0
1488
+ }
1489
+ };
1490
+ };
1491
+ const mapped = allData.map(mapItem);
1481
1492
  mapped.sort((a, b) => {
1482
1493
  if (a.isVerification && !b.isVerification) return -1;
1483
1494
  if (!a.isVerification && b.isVerification) return 1;
@@ -1571,7 +1582,7 @@ var BugBearClient = class {
1571
1582
  async updateAssignmentStatus(assignmentId, status, options) {
1572
1583
  try {
1573
1584
  await this.ensureReady();
1574
- const { data: currentAssignment, error: fetchError } = await this.supabase.from("test_assignments").select("status, started_at").eq("id", assignmentId).single();
1585
+ const { data: currentAssignment, error: fetchError } = await this.supabase.from("test_assignments").select("status, started_at, tester_id, project_id").eq("id", assignmentId).single();
1575
1586
  if (fetchError || !currentAssignment) {
1576
1587
  console.error("BugBear: Assignment not found", {
1577
1588
  message: fetchError?.message,
@@ -1592,6 +1603,19 @@ var BugBearClient = class {
1592
1603
  const completedAt = /* @__PURE__ */ new Date();
1593
1604
  durationSeconds = Math.round((completedAt.getTime() - startedAt.getTime()) / 1e3);
1594
1605
  updateData.duration_seconds = durationSeconds;
1606
+ if (currentAssignment.tester_id && currentAssignment.project_id) {
1607
+ try {
1608
+ const { data: activeTime } = await this.supabase.rpc("compute_assignment_active_time", {
1609
+ p_tester_id: currentAssignment.tester_id,
1610
+ p_project_id: currentAssignment.project_id,
1611
+ p_started_at: currentAssignment.started_at,
1612
+ p_completed_at: updateData.completed_at
1613
+ });
1614
+ updateData.active_seconds = typeof activeTime === "number" ? activeTime : Math.min(durationSeconds, 1800);
1615
+ } catch {
1616
+ updateData.active_seconds = Math.min(durationSeconds, 1800);
1617
+ }
1618
+ }
1595
1619
  }
1596
1620
  }
1597
1621
  if (options?.notes) {
@@ -1670,6 +1694,7 @@ var BugBearClient = class {
1670
1694
  started_at: (/* @__PURE__ */ new Date()).toISOString(),
1671
1695
  completed_at: null,
1672
1696
  duration_seconds: null,
1697
+ active_seconds: null,
1673
1698
  skip_reason: null
1674
1699
  }).eq("id", assignmentId).eq("status", current.status);
1675
1700
  if (error) {
@@ -1977,7 +2002,11 @@ var BugBearClient = class {
1977
2002
  verifiedByName: row.verified_by_name || void 0,
1978
2003
  verifiedAt: row.verified_at || void 0,
1979
2004
  originalBugId: row.original_bug_id || void 0,
1980
- originalBugTitle: row.original_bug_title || void 0
2005
+ originalBugTitle: row.original_bug_title || void 0,
2006
+ resolutionNotes: row.resolution_notes || void 0,
2007
+ fixCommitSha: row.code_context?.fix?.commit_sha || void 0,
2008
+ fixCommitMessage: row.code_context?.fix?.commit_message || void 0,
2009
+ fixFilesChanged: row.code_context?.fix?.files_changed || void 0
1981
2010
  }));
1982
2011
  } catch (err) {
1983
2012
  console.error("BugBear: Error fetching issues", err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbearai/core",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "Core utilities and types for BugBear QA platform",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",