birdclaw 0.6.0 → 0.8.0

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +32 -2
  3. package/package.json +29 -30
  4. package/scripts/build-docs-site.mjs +39 -12
  5. package/src/cli.ts +457 -26
  6. package/src/components/AppNav.tsx +10 -0
  7. package/src/components/MarkdownViewer.tsx +438 -72
  8. package/src/components/ProfileAnalysisStream.tsx +428 -0
  9. package/src/components/ProfilePreview.tsx +120 -9
  10. package/src/components/SavedTimelineView.tsx +30 -8
  11. package/src/components/SyncNowButton.tsx +5 -2
  12. package/src/components/TimelineCard.tsx +20 -4
  13. package/src/components/TimelineRouteFrame.tsx +16 -0
  14. package/src/components/TweetRichText.tsx +36 -12
  15. package/src/components/useTimelineRouteData.ts +74 -6
  16. package/src/lib/account-sync-job.ts +15 -3
  17. package/src/lib/archive-finder.ts +1 -1
  18. package/src/lib/archive-import.ts +245 -7
  19. package/src/lib/authored-live.ts +1 -0
  20. package/src/lib/avatar-cache.ts +50 -0
  21. package/src/lib/backup.ts +4 -3
  22. package/src/lib/bird.ts +33 -0
  23. package/src/lib/config.ts +35 -2
  24. package/src/lib/data-sources.ts +219 -0
  25. package/src/lib/db.ts +62 -1
  26. package/src/lib/geocoding.ts +296 -0
  27. package/src/lib/link-insights.ts +2 -0
  28. package/src/lib/location.ts +137 -0
  29. package/src/lib/mention-threads-live.ts +94 -1
  30. package/src/lib/mentions-live.ts +187 -40
  31. package/src/lib/network-map.ts +382 -0
  32. package/src/lib/period-digest.ts +468 -29
  33. package/src/lib/profile-analysis.ts +1272 -0
  34. package/src/lib/profile-bio-entities.ts +1 -1
  35. package/src/lib/queries.ts +14 -4
  36. package/src/lib/search-discussion.ts +1016 -0
  37. package/src/lib/timeline-live.ts +272 -19
  38. package/src/lib/tweet-account-edges.ts +2 -0
  39. package/src/lib/tweet-render.ts +141 -1
  40. package/src/lib/tweet-search-live.ts +565 -0
  41. package/src/lib/types.ts +37 -2
  42. package/src/lib/ui.ts +1 -1
  43. package/src/lib/web-sync.ts +7 -2
  44. package/src/lib/xurl-rate-limits.ts +267 -0
  45. package/src/lib/xurl.ts +551 -41
  46. package/src/routeTree.gen.ts +231 -0
  47. package/src/routes/__root.tsx +5 -6
  48. package/src/routes/api/data-sources.tsx +24 -0
  49. package/src/routes/api/network-map.tsx +55 -0
  50. package/src/routes/api/period-digest.tsx +29 -3
  51. package/src/routes/api/profile-analysis.tsx +152 -0
  52. package/src/routes/api/query.tsx +1 -0
  53. package/src/routes/api/search-discussion.tsx +169 -0
  54. package/src/routes/api/xurl-rate-limits.tsx +24 -0
  55. package/src/routes/data-sources.tsx +257 -0
  56. package/src/routes/discuss.tsx +419 -0
  57. package/src/routes/network-map.tsx +1035 -0
  58. package/src/routes/profile-analyze.tsx +112 -0
  59. package/src/routes/profiles.$handle.tsx +228 -0
  60. package/src/routes/rate-limits.tsx +309 -0
  61. package/src/routes/today.tsx +22 -8
  62. package/src/styles.css +22 -0
@@ -9,7 +9,7 @@ interface ExtractedBioEntity {
9
9
  raw: Record<string, unknown>;
10
10
  }
11
11
 
12
- const HANDLE_RE = /(^|[^\w])@([A-Za-z0-9_]{1,15})\b/g;
12
+ const HANDLE_RE = /(^|[^\w@./])@([A-Za-z0-9_]{1,15})\b/g;
13
13
  const DOMAIN_RE =
14
14
  /\b(?:https?:\/\/)?(?:www\.)?([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+)\b/gi;
15
15
  const COMPANY_RE =
@@ -786,6 +786,7 @@ export function listTimelineItems({
786
786
  replyFilter = "all",
787
787
  since,
788
788
  until,
789
+ untilId,
789
790
  includeReplies = true,
790
791
  qualityFilter = "all",
791
792
  lowQualityThreshold,
@@ -969,8 +970,17 @@ export function listTimelineItems({
969
970
  }
970
971
 
971
972
  if (until?.trim()) {
972
- where += " and t.created_at < ?";
973
- params.push(until.trim());
973
+ // Deterministic keyset cursor: page on (created_at, id) so rows that share
974
+ // the boundary timestamp are not skipped. Uses the same text comparison as
975
+ // the `order by t.created_at desc, t.id desc` below, which is a total order
976
+ // because t.id is unique.
977
+ if (untilId?.trim()) {
978
+ where += " and (t.created_at < ? or (t.created_at = ? and t.id < ?))";
979
+ params.push(until.trim(), until.trim(), untilId.trim());
980
+ } else {
981
+ where += " and t.created_at < ?";
982
+ params.push(until.trim());
983
+ }
974
984
  }
975
985
 
976
986
  const ftsSearch = search?.trim() ? toFtsSearchQuery(search) : "";
@@ -1075,7 +1085,7 @@ export function listTimelineItems({
1075
1085
  left join profiles qp on qp.id = qt.author_profile_id
1076
1086
  ${join}
1077
1087
  ${where}
1078
- order by t.created_at desc
1088
+ order by t.created_at desc, t.id desc
1079
1089
  limit ?
1080
1090
  `;
1081
1091
 
@@ -1955,7 +1965,7 @@ function getDmSearchMatches({
1955
1965
  }
1956
1966
 
1957
1967
  export function queryResource(
1958
- resource: "home" | "mentions" | "authored" | "dms",
1968
+ resource: "home" | "mentions" | "authored" | "search" | "dms",
1959
1969
  filters: (TimelineQuery | DmQuery) & { conversationId?: string },
1960
1970
  ): QueryResponse {
1961
1971
  if (resource === "dms") {