darkfire514 commited on
Commit
1c9799a
·
verified ·
1 Parent(s): 4481af3

Update openspace/skill_engine/store.py

Browse files
Files changed (1) hide show
  1. openspace/skill_engine/store.py +114 -6
openspace/skill_engine/store.py CHANGED
@@ -795,10 +795,8 @@ class SkillStore:
795
  ).fetchall()
796
  else:
797
  rows = conn.execute("SELECT * FROM skill_records").fetchall()
798
- result: Dict[str, SkillRecord] = {}
799
- for row in rows:
800
- rec = self._to_record(conn, row)
801
- result[rec.skill_id] = rec
802
  logger.info(f"Loaded {len(result)} skill records (active_only={active_only})")
803
  return result
804
 
@@ -841,7 +839,7 @@ class SkillStore:
841
  "ORDER BY lineage_generation ASC",
842
  (name,),
843
  ).fetchall()
844
- return [self._to_record(conn, r) for r in rows]
845
 
846
  @_db_retry()
847
  def load_by_category(
@@ -864,7 +862,7 @@ class SkillStore:
864
  "SELECT * FROM skill_records WHERE category=?",
865
  (category.value,),
866
  ).fetchall()
867
- return [self._to_record(conn, r) for r in rows]
868
 
869
  @_db_retry()
870
  def load_analyses(
@@ -1437,6 +1435,116 @@ class SkillStore:
1437
  return analysis_id
1438
 
1439
  # Deserialization
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1440
  def _to_record(
1441
  self, conn: sqlite3.Connection, row: sqlite3.Row
1442
  ) -> SkillRecord:
 
795
  ).fetchall()
796
  else:
797
  rows = conn.execute("SELECT * FROM skill_records").fetchall()
798
+ records = self._to_records_bulk(conn, rows)
799
+ result: Dict[str, SkillRecord] = {rec.skill_id: rec for rec in records}
 
 
800
  logger.info(f"Loaded {len(result)} skill records (active_only={active_only})")
801
  return result
802
 
 
839
  "ORDER BY lineage_generation ASC",
840
  (name,),
841
  ).fetchall()
842
+ return self._to_records_bulk(conn, rows)
843
 
844
  @_db_retry()
845
  def load_by_category(
 
862
  "SELECT * FROM skill_records WHERE category=?",
863
  (category.value,),
864
  ).fetchall()
865
+ return self._to_records_bulk(conn, rows)
866
 
867
  @_db_retry()
868
  def load_analyses(
 
1435
  return analysis_id
1436
 
1437
  # Deserialization
1438
+ def _to_records_bulk(
1439
+ self, conn: sqlite3.Connection, rows: List[sqlite3.Row]
1440
+ ) -> List[SkillRecord]:
1441
+ """Bulk deserialize skill_records rows → List[SkillRecord]."""
1442
+ if not rows:
1443
+ return []
1444
+
1445
+ sids = [r["skill_id"] for r in rows]
1446
+ parents_map = {sid: [] for sid in sids}
1447
+ deps_map = {sid: [] for sid in sids}
1448
+ tags_map = {sid: [] for sid in sids}
1449
+ analyses_map = {sid: [] for sid in sids}
1450
+
1451
+ def chunks(lst, n):
1452
+ for i in range(0, len(lst), n):
1453
+ yield lst[i:i + n]
1454
+
1455
+ for chunk in chunks(sids, 900):
1456
+ placeholders = ",".join(["?"] * len(chunk))
1457
+
1458
+ # Parents
1459
+ p_rows = conn.execute(
1460
+ f"SELECT skill_id, parent_skill_id FROM skill_lineage_parents WHERE skill_id IN ({placeholders})",
1461
+ chunk,
1462
+ ).fetchall()
1463
+ for pr in p_rows:
1464
+ parents_map[pr["skill_id"]].append(pr["parent_skill_id"])
1465
+
1466
+ # Tool deps
1467
+ d_rows = conn.execute(
1468
+ f"SELECT skill_id, tool_key, critical FROM skill_tool_deps WHERE skill_id IN ({placeholders})",
1469
+ chunk,
1470
+ ).fetchall()
1471
+ for dr in d_rows:
1472
+ deps_map[dr["skill_id"]].append(dr)
1473
+
1474
+ # Tags
1475
+ t_rows = conn.execute(
1476
+ f"SELECT skill_id, tag FROM skill_tags WHERE skill_id IN ({placeholders})",
1477
+ chunk,
1478
+ ).fetchall()
1479
+ for tr in t_rows:
1480
+ tags_map[tr["skill_id"]].append(tr["tag"])
1481
+
1482
+ # Analyses
1483
+ a_rows = conn.execute(
1484
+ f"""
1485
+ SELECT ea.*, sj.skill_id as sj_skill_id
1486
+ FROM execution_analyses ea
1487
+ JOIN skill_judgments sj ON ea.id = sj.analysis_id
1488
+ WHERE sj.skill_id IN ({placeholders})
1489
+ ORDER BY ea.timestamp DESC
1490
+ """,
1491
+ chunk,
1492
+ ).fetchall()
1493
+ for ar in a_rows:
1494
+ sid = ar["sj_skill_id"]
1495
+ if len(analyses_map[sid]) < SkillRecord.MAX_RECENT:
1496
+ analyses_map[sid].append(self._to_analysis(conn, ar))
1497
+
1498
+ result = []
1499
+ for row in rows:
1500
+ sid = row["skill_id"]
1501
+
1502
+ raw_snapshot = row["lineage_content_snapshot"] or "{}"
1503
+ snapshot: Dict[str, str] = json.loads(raw_snapshot)
1504
+
1505
+ lineage = SkillLineage(
1506
+ origin=SkillOrigin(row["lineage_origin"]),
1507
+ generation=row["lineage_generation"],
1508
+ parent_skill_ids=parents_map[sid],
1509
+ source_task_id=row["lineage_source_task_id"],
1510
+ change_summary=row["lineage_change_summary"],
1511
+ content_diff=row["lineage_content_diff"],
1512
+ content_snapshot=snapshot,
1513
+ created_at=datetime.fromisoformat(row["lineage_created_at"]),
1514
+ created_by=row["lineage_created_by"],
1515
+ )
1516
+
1517
+ deps = deps_map[sid]
1518
+ record = SkillRecord(
1519
+ skill_id=sid,
1520
+ name=row["name"],
1521
+ description=row["description"],
1522
+ path=row["path"],
1523
+ is_active=bool(row["is_active"]),
1524
+ category=SkillCategory(row["category"]),
1525
+ tags=tags_map[sid],
1526
+ visibility=(
1527
+ SkillVisibility(row["visibility"])
1528
+ if row["visibility"] else SkillVisibility.PRIVATE
1529
+ ),
1530
+ creator_id=row["creator_id"] or "",
1531
+ lineage=lineage,
1532
+ tool_dependencies=[r["tool_key"] for r in deps],
1533
+ critical_tools=[
1534
+ r["tool_key"] for r in deps if r["critical"]
1535
+ ],
1536
+ total_selections=row["total_selections"],
1537
+ total_applied=row["total_applied"],
1538
+ total_completions=row["total_completions"],
1539
+ total_fallbacks=row["total_fallbacks"],
1540
+ recent_analyses=analyses_map[sid],
1541
+ first_seen=datetime.fromisoformat(row["first_seen"]),
1542
+ last_updated=datetime.fromisoformat(row["last_updated"]),
1543
+ )
1544
+ result.append(record)
1545
+
1546
+ return result
1547
+
1548
  def _to_record(
1549
  self, conn: sqlite3.Connection, row: sqlite3.Row
1550
  ) -> SkillRecord: