six-degrees 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 (609) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +4 -0
  3. package/.next/standalone/.next/build-manifest.json +3 -3
  4. package/.next/standalone/.next/prerender-manifest.json +42 -14
  5. package/.next/standalone/.next/routes-manifest.json +24 -0
  6. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  7. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_not-found/page.js +1 -1
  12. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  15. package/.next/standalone/.next/server/app/_not-found.rsc +26 -18
  16. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +26 -18
  17. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +25 -16
  18. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  19. package/.next/standalone/.next/server/app/api/admin-delete/route.js +2 -2
  20. package/.next/standalone/.next/server/app/api/admin-delete/route.js.nft.json +1 -1
  21. package/.next/standalone/.next/server/app/api/admin-update/route.js +2 -2
  22. package/.next/standalone/.next/server/app/api/admin-update/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/bridges/route.js +2 -2
  24. package/.next/standalone/.next/server/app/api/bridges/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/bulk-import/route.js +2 -2
  26. package/.next/standalone/.next/server/app/api/bulk-import/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js +3 -3
  28. package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/company-scores/route.js +3 -3
  30. package/.next/standalone/.next/server/app/api/company-scores/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/connections/route.js +2 -2
  32. package/.next/standalone/.next/server/app/api/connections/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/data/backup/route/app-paths-manifest.json +3 -0
  34. package/.next/standalone/.next/server/app/api/data/backup/route/build-manifest.json +12 -0
  35. package/.next/standalone/.next/server/app/api/data/backup/route/server-reference-manifest.json +4 -0
  36. package/.next/standalone/.next/server/app/api/data/backup/route.js +7 -0
  37. package/.next/standalone/.next/server/app/api/data/backup/route.js.map +5 -0
  38. package/.next/standalone/.next/server/app/api/data/backup/route.js.nft.json +1 -0
  39. package/.next/standalone/.next/server/app/api/data/backup/route_client-reference-manifest.js +3 -0
  40. package/.next/standalone/.next/server/app/api/data/csv/route/app-paths-manifest.json +3 -0
  41. package/.next/standalone/.next/server/app/api/data/csv/route/build-manifest.json +12 -0
  42. package/.next/standalone/.next/server/app/api/data/csv/route/server-reference-manifest.json +4 -0
  43. package/.next/standalone/.next/server/app/api/data/csv/route.js +8 -0
  44. package/.next/standalone/.next/server/app/api/data/csv/route.js.map +5 -0
  45. package/.next/standalone/.next/server/app/api/data/csv/route.js.nft.json +1 -0
  46. package/.next/standalone/.next/server/app/api/data/csv/route_client-reference-manifest.js +3 -0
  47. package/.next/standalone/.next/server/app/api/data/export/route.js +1 -1
  48. package/.next/standalone/.next/server/app/api/data/export/route.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/api/data/import/route.js +1 -1
  50. package/.next/standalone/.next/server/app/api/data/import/route.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/api/data/restart/route.js +1 -1
  52. package/.next/standalone/.next/server/app/api/data/restart/route.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/api/data/restore/route/app-paths-manifest.json +3 -0
  54. package/.next/standalone/.next/server/app/api/data/restore/route/build-manifest.json +12 -0
  55. package/.next/standalone/.next/server/app/api/data/restore/route/server-reference-manifest.json +4 -0
  56. package/.next/standalone/.next/server/app/api/data/restore/route.js +7 -0
  57. package/.next/standalone/.next/server/app/api/data/restore/route.js.map +5 -0
  58. package/.next/standalone/.next/server/app/api/data/restore/route.js.nft.json +1 -0
  59. package/.next/standalone/.next/server/app/api/data/restore/route_client-reference-manifest.js +3 -0
  60. package/.next/standalone/.next/server/app/api/data/reveal/route.js +1 -1
  61. package/.next/standalone/.next/server/app/api/data/reveal/route.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/api/data/route.js +1 -1
  63. package/.next/standalone/.next/server/app/api/data/route.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/api/delete-cluster/route.js +2 -2
  65. package/.next/standalone/.next/server/app/api/delete-cluster/route.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/api/ingest/route.js +2 -2
  67. package/.next/standalone/.next/server/app/api/ingest/route.js.nft.json +1 -1
  68. package/.next/standalone/.next/server/app/api/network/route.js +2 -2
  69. package/.next/standalone/.next/server/app/api/network/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/notifications/route.js +2 -2
  71. package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/api/outreach/route.js +3 -3
  73. package/.next/standalone/.next/server/app/api/outreach/route.js.nft.json +1 -1
  74. package/.next/standalone/.next/server/app/api/queue/route.js +2 -2
  75. package/.next/standalone/.next/server/app/api/queue/route.js.nft.json +1 -1
  76. package/.next/standalone/.next/server/app/api/scraper/route.js +5 -3
  77. package/.next/standalone/.next/server/app/api/scraper/route.js.nft.json +1 -1
  78. package/.next/standalone/.next/server/app/api/settings/route.js +3 -3
  79. package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
  80. package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js +3 -3
  81. package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.nft.json +1 -1
  82. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js +3 -3
  83. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.nft.json +1 -1
  84. package/.next/standalone/.next/server/app/api/setup-profile/route.js +2 -2
  85. package/.next/standalone/.next/server/app/api/setup-profile/route.js.nft.json +1 -1
  86. package/.next/standalone/.next/server/app/api/social/crm/route.js +1 -1
  87. package/.next/standalone/.next/server/app/api/social/crm/route.js.nft.json +1 -1
  88. package/.next/standalone/.next/server/app/api/social/messages/route.js +1 -1
  89. package/.next/standalone/.next/server/app/api/social/messages/route.js.nft.json +1 -1
  90. package/.next/standalone/.next/server/app/api/social/route.js +2 -2
  91. package/.next/standalone/.next/server/app/api/social/route.js.nft.json +1 -1
  92. package/.next/standalone/.next/server/app/api/unlock/route.js +2 -2
  93. package/.next/standalone/.next/server/app/api/unlock/route.js.nft.json +1 -1
  94. package/.next/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/update-images/route.js +2 -2
  96. package/.next/standalone/.next/server/app/api/update-images/route.js.nft.json +1 -1
  97. package/.next/standalone/.next/server/app/api/users/route.js +2 -2
  98. package/.next/standalone/.next/server/app/api/users/route.js.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/avatars/[file]/route.js +1 -1
  100. package/.next/standalone/.next/server/app/avatars/[file]/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/import/page.js +1 -1
  102. package/.next/standalone/.next/server/app/import/page.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/import/page_client-reference-manifest.js +1 -1
  104. package/.next/standalone/.next/server/app/import.html +1 -1
  105. package/.next/standalone/.next/server/app/import.rsc +32 -24
  106. package/.next/standalone/.next/server/app/import.segments/_full.segment.rsc +32 -24
  107. package/.next/standalone/.next/server/app/import.segments/_tree.segment.rsc +2 -2
  108. package/.next/standalone/.next/server/app/import.segments/import/__PAGE__.segment.rsc +23 -18
  109. package/.next/standalone/.next/server/app/index.html +1 -1
  110. package/.next/standalone/.next/server/app/index.rsc +29 -22
  111. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +20 -15
  112. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +29 -22
  113. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  114. package/.next/standalone/.next/server/app/insights/page/app-paths-manifest.json +3 -0
  115. package/.next/standalone/.next/server/app/insights/page/build-manifest.json +20 -0
  116. package/.next/standalone/.next/server/app/insights/page/next-font-manifest.json +11 -0
  117. package/.next/standalone/.next/server/app/insights/page/react-loadable-manifest.json +1 -0
  118. package/.next/standalone/.next/server/app/insights/page/server-reference-manifest.json +4 -0
  119. package/.next/standalone/.next/server/app/insights/page.js +13 -0
  120. package/.next/standalone/.next/server/app/insights/page.js.map +5 -0
  121. package/.next/standalone/.next/server/app/insights/page.js.nft.json +1 -0
  122. package/.next/standalone/.next/server/app/insights/page_client-reference-manifest.js +3 -0
  123. package/.next/standalone/.next/server/app/insights.html +1 -0
  124. package/.next/standalone/.next/server/app/insights.meta +26 -0
  125. package/.next/standalone/.next/server/app/insights.rsc +35 -0
  126. package/.next/standalone/.next/server/app/insights.segments/_full.segment.rsc +35 -0
  127. package/.next/standalone/.next/server/app/insights.segments/_tree.segment.rsc +4 -0
  128. package/.next/standalone/.next/server/app/insights.segments/insights/__PAGE__.segment.rsc +33 -0
  129. package/.next/standalone/.next/server/app/launch/page.js +1 -1
  130. package/.next/standalone/.next/server/app/launch/page.js.nft.json +1 -1
  131. package/.next/standalone/.next/server/app/launch/page_client-reference-manifest.js +1 -1
  132. package/.next/standalone/.next/server/app/launch.html +2 -2
  133. package/.next/standalone/.next/server/app/launch.rsc +32 -24
  134. package/.next/standalone/.next/server/app/launch.segments/_full.segment.rsc +32 -24
  135. package/.next/standalone/.next/server/app/launch.segments/_tree.segment.rsc +2 -2
  136. package/.next/standalone/.next/server/app/launch.segments/launch/__PAGE__.segment.rsc +23 -18
  137. package/.next/standalone/.next/server/app/page.js +1 -1
  138. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  139. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  140. package/.next/standalone/.next/server/app/paths/page.js +1 -1
  141. package/.next/standalone/.next/server/app/paths/page.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/paths/page_client-reference-manifest.js +1 -1
  143. package/.next/standalone/.next/server/app/paths.html +1 -1
  144. package/.next/standalone/.next/server/app/paths.rsc +32 -24
  145. package/.next/standalone/.next/server/app/paths.segments/_full.segment.rsc +32 -24
  146. package/.next/standalone/.next/server/app/paths.segments/_tree.segment.rsc +2 -2
  147. package/.next/standalone/.next/server/app/paths.segments/paths/__PAGE__.segment.rsc +21 -18
  148. package/.next/standalone/.next/server/app/profile/page.js +1 -1
  149. package/.next/standalone/.next/server/app/profile/page.js.nft.json +1 -1
  150. package/.next/standalone/.next/server/app/profile/page_client-reference-manifest.js +1 -1
  151. package/.next/standalone/.next/server/app/profile.html +1 -1
  152. package/.next/standalone/.next/server/app/profile.rsc +32 -24
  153. package/.next/standalone/.next/server/app/profile.segments/_full.segment.rsc +32 -24
  154. package/.next/standalone/.next/server/app/profile.segments/_tree.segment.rsc +2 -2
  155. package/.next/standalone/.next/server/app/profile.segments/profile/__PAGE__.segment.rsc +23 -18
  156. package/.next/standalone/.next/server/app/queue/page.js +1 -1
  157. package/.next/standalone/.next/server/app/queue/page.js.nft.json +1 -1
  158. package/.next/standalone/.next/server/app/queue/page_client-reference-manifest.js +1 -1
  159. package/.next/standalone/.next/server/app/queue.html +1 -1
  160. package/.next/standalone/.next/server/app/queue.rsc +32 -24
  161. package/.next/standalone/.next/server/app/queue.segments/_full.segment.rsc +32 -24
  162. package/.next/standalone/.next/server/app/queue.segments/_tree.segment.rsc +2 -2
  163. package/.next/standalone/.next/server/app/queue.segments/queue/__PAGE__.segment.rsc +21 -18
  164. package/.next/standalone/.next/server/app/scores/page.js +1 -1
  165. package/.next/standalone/.next/server/app/scores/page.js.nft.json +1 -1
  166. package/.next/standalone/.next/server/app/scores/page_client-reference-manifest.js +1 -1
  167. package/.next/standalone/.next/server/app/scores.html +1 -1
  168. package/.next/standalone/.next/server/app/scores.rsc +32 -24
  169. package/.next/standalone/.next/server/app/scores.segments/_full.segment.rsc +32 -24
  170. package/.next/standalone/.next/server/app/scores.segments/_tree.segment.rsc +2 -2
  171. package/.next/standalone/.next/server/app/scores.segments/scores/__PAGE__.segment.rsc +23 -18
  172. package/.next/standalone/.next/server/app/settings/page.js +1 -1
  173. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  174. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  175. package/.next/standalone/.next/server/app/settings.html +1 -1
  176. package/.next/standalone/.next/server/app/settings.rsc +32 -24
  177. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +32 -24
  178. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  179. package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +20 -18
  180. package/.next/standalone/.next/server/app/setup/page.js +1 -1
  181. package/.next/standalone/.next/server/app/setup/page.js.nft.json +1 -1
  182. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  183. package/.next/standalone/.next/server/app/setup.html +1 -1
  184. package/.next/standalone/.next/server/app/setup.rsc +32 -24
  185. package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +32 -24
  186. package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +2 -2
  187. package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +21 -18
  188. package/.next/standalone/.next/server/app/social/page.js +1 -1
  189. package/.next/standalone/.next/server/app/social/page.js.nft.json +1 -1
  190. package/.next/standalone/.next/server/app/social/page_client-reference-manifest.js +1 -1
  191. package/.next/standalone/.next/server/app/social.html +1 -1
  192. package/.next/standalone/.next/server/app/social.rsc +32 -24
  193. package/.next/standalone/.next/server/app/social.segments/_full.segment.rsc +32 -24
  194. package/.next/standalone/.next/server/app/social.segments/_tree.segment.rsc +2 -2
  195. package/.next/standalone/.next/server/app/social.segments/social/__PAGE__.segment.rsc +23 -18
  196. package/.next/standalone/.next/server/app-paths-manifest.json +4 -0
  197. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00la_y0._.js +1 -1
  198. package/.next/standalone/.next/server/chunks/[root-of-the-server]__05_3-22._.js +1 -1
  199. package/.next/standalone/.next/server/chunks/[root-of-the-server]__066rab1._.js +7 -0
  200. package/.next/standalone/.next/server/chunks/[root-of-the-server]__07t47cm._.js +1 -1
  201. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cj5jqc._.js +1 -1
  202. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e0fei3._.js +1 -1
  203. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fooke1._.js +7 -0
  204. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljnyho._.js +1 -1
  205. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o5-tcg._.js +1 -1
  206. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qrnous._.js +1 -1
  207. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__15wc9e-._.js → [root-of-the-server]__0r-0t-9._.js} +2 -2
  208. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ra6xyg._.js +15 -0
  209. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__20rwfdw._.js → [root-of-the-server]__0rcpjad._.js} +6 -3
  210. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t3v1a1._.js +1 -1
  211. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t6y79e._.js +7 -0
  212. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wmexuc._.js +1 -1
  213. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0x29muh._.js +7 -0
  214. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xu34sz._.js +1 -1
  215. package/.next/standalone/.next/server/chunks/[root-of-the-server]__133knx1._.js +1 -1
  216. package/.next/standalone/.next/server/chunks/[root-of-the-server]__15-17hl._.js +1 -1
  217. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19b7mig._.js +1 -1
  218. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a_6x37._.js +8 -0
  219. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1an_8pa._.js +7 -0
  220. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1bbcwub._.js +1 -1
  221. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ducpz2._.js +3 -0
  222. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1eris29._.js +1 -1
  223. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1gjo_cq._.js +1 -1
  224. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qcm08_._.js +1 -1
  225. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tir0vc._.js +1 -1
  226. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1w25q0m._.js +1 -1
  227. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xhyinn._.js +3 -0
  228. package/.next/standalone/.next/server/chunks/_072jl0y._.js +1 -1
  229. package/.next/standalone/.next/server/chunks/_0lw8_i0._.js +1 -1
  230. package/.next/standalone/.next/server/chunks/_0sqqpzb._.js +3 -0
  231. package/.next/standalone/.next/server/chunks/_1_fynia._.js +7 -7
  232. package/.next/standalone/.next/server/chunks/_1fn30_l._.js +1 -1
  233. package/.next/standalone/.next/server/chunks/_1itd1o_._.js +1 -1
  234. package/.next/standalone/.next/server/chunks/_1iwkh8t._.js +1 -1
  235. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_backup_route_actions_0zoj04p.js +3 -0
  236. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_csv_route_actions_0l6m7lg.js +3 -0
  237. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_restore_route_actions_0-b05bv.js +3 -0
  238. package/.next/standalone/.next/server/chunks/lib_02iz_9q._.js +4 -0
  239. package/.next/standalone/.next/server/chunks/lib_05agvk3._.js +4 -0
  240. package/.next/standalone/.next/server/chunks/lib_0v84u66._.js +4 -0
  241. package/.next/standalone/.next/server/chunks/lib_db-client_0_dch35.js +174 -0
  242. package/.next/standalone/.next/server/chunks/lib_linkedin-export_12imqxg.js +1 -1
  243. package/.next/standalone/.next/server/chunks/lib_rpc_00nndai.js +3 -0
  244. package/.next/standalone/.next/server/chunks/lib_rpc_03ibb-x.js +3 -0
  245. package/.next/standalone/.next/server/chunks/lib_rpc_03ri3ji.js +3 -0
  246. package/.next/standalone/.next/server/chunks/lib_rpc_078ce48.js +3 -0
  247. package/.next/standalone/.next/server/chunks/lib_rpc_0a69mgr.js +3 -0
  248. package/.next/standalone/.next/server/chunks/lib_rpc_0c9d9ti.js +7 -0
  249. package/.next/standalone/.next/server/chunks/lib_rpc_0cej3t8.js +3 -0
  250. package/.next/standalone/.next/server/chunks/lib_rpc_0cmh4g6.js +3 -0
  251. package/.next/standalone/.next/server/chunks/lib_rpc_0nx2_pc.js +3 -0
  252. package/.next/standalone/.next/server/chunks/lib_rpc_0r79-w1.js +3 -0
  253. package/.next/standalone/.next/server/chunks/lib_rpc_0t552z6.js +3 -0
  254. package/.next/standalone/.next/server/chunks/lib_rpc_0yx8ynd.js +3 -0
  255. package/.next/standalone/.next/server/chunks/lib_rpc_12p-o9-.js +3 -0
  256. package/.next/standalone/.next/server/chunks/lib_rpc_1466dnb.js +3 -0
  257. package/.next/standalone/.next/server/chunks/lib_rpc_1sryxv6.js +3 -0
  258. package/.next/standalone/.next/server/chunks/lib_rpc_1trn-x5.js +3 -0
  259. package/.next/standalone/.next/server/chunks/lib_rpc_1ygu_mv.js +3 -0
  260. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0egamyq._.js +3 -0
  261. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qd8pzm._.js +3 -0
  262. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0qdeuyo._.js → [root-of-the-server]__1-012q1._.js} +2 -2
  263. package/.next/standalone/.next/server/chunks/ssr/_04am_h8._.js +3 -0
  264. package/.next/standalone/.next/server/chunks/ssr/_06rgzfh._.js +3 -0
  265. package/.next/standalone/.next/server/chunks/ssr/_07zb7lu._.js +3 -0
  266. package/.next/standalone/.next/server/chunks/ssr/_0_79idq._.js +3 -0
  267. package/.next/standalone/.next/server/chunks/ssr/_0gds903._.js +3 -0
  268. package/.next/standalone/.next/server/chunks/ssr/_0hb-dhy._.js +3 -0
  269. package/.next/standalone/.next/server/chunks/ssr/_0klqt9z._.js +3 -0
  270. package/.next/standalone/.next/server/chunks/ssr/_14jak5s._.js +7 -0
  271. package/.next/standalone/.next/server/chunks/ssr/_14nxd3q._.js +3 -0
  272. package/.next/standalone/.next/server/chunks/ssr/_1cj2yog._.js +3 -0
  273. package/.next/standalone/.next/server/chunks/ssr/_1fm1ih_._.js +2 -2
  274. package/.next/standalone/.next/server/chunks/ssr/_1hdqw0-._.js +7 -0
  275. package/.next/standalone/.next/server/chunks/ssr/_1k2nmbw._.js +2 -2
  276. package/.next/standalone/.next/server/chunks/ssr/_1r62six._.js +7 -0
  277. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_insights_page_actions_0-0tf75.js +3 -0
  278. package/.next/standalone/.next/server/chunks/ssr/app_141w189._.js +1 -1
  279. package/.next/standalone/.next/server/chunks/ssr/app_components_0uuff77._.js +25 -2
  280. package/.next/standalone/.next/server/chunks/ssr/app_components_1j3q-h5._.js +25 -2
  281. package/.next/standalone/.next/server/chunks/ssr/app_components_CompanyScores_1g0mytz.js +1 -1
  282. package/.next/standalone/.next/server/chunks/ssr/app_components_settings_SectorPicker_1c-29qw.js +1 -1
  283. package/.next/standalone/.next/server/chunks/ssr/app_components_ui_0pdmz2z.js +3 -0
  284. package/.next/standalone/.next/server/chunks/ssr/app_import_page_1fmu6_l.js +1 -1
  285. package/.next/standalone/.next/server/chunks/ssr/app_insights_page_1d_chja.js +3 -0
  286. package/.next/standalone/.next/server/chunks/ssr/app_launch_page_19t0dyd.js +1 -1
  287. package/.next/standalone/.next/server/chunks/ssr/app_page_1fazqbf.js +26 -14
  288. package/.next/standalone/.next/server/chunks/ssr/app_paths_page_1ol90m7.js +2 -2
  289. package/.next/standalone/.next/server/chunks/ssr/app_profile_page_0u3-l5y.js +1 -1
  290. package/.next/standalone/.next/server/chunks/ssr/app_queue_page_0c6znd6.js +11 -11
  291. package/.next/standalone/.next/server/chunks/ssr/app_settings_page_1f8mjj_.js +1 -1
  292. package/.next/standalone/.next/server/chunks/ssr/app_setup_page_1-282zx.js +12 -13
  293. package/.next/standalone/.next/server/chunks/ssr/app_social_page_0h7zxda.js +1 -1
  294. package/.next/standalone/.next/server/chunks/ssr/{lib_1c4ieuw._.js → lib_csv_1ttiu_h.js} +2 -2
  295. package/.next/standalone/.next/server/chunks/ssr/lib_galaxy-lab_108_lu-.js +1 -1
  296. package/.next/standalone/.next/server/chunks/ssr/lib_separation_1305zsx.js +3 -0
  297. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0pco7a6._.js +1 -1
  298. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  299. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  300. package/.next/standalone/.next/server/next-font-manifest.js +1 -1
  301. package/.next/standalone/.next/server/next-font-manifest.json +4 -0
  302. package/.next/standalone/.next/server/pages/404.html +1 -1
  303. package/.next/standalone/.next/server/pages/500.html +1 -1
  304. package/.next/standalone/.next/server/prefetch-hints.json +14 -0
  305. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  306. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  307. package/.next/standalone/.next/static/chunks/02wnf8dkxegxg.js +34 -0
  308. package/.next/standalone/.next/static/chunks/03-_esd2x_yk6.js +1 -0
  309. package/.next/standalone/.next/static/chunks/03-demj2iy-0p.js +44 -0
  310. package/.next/standalone/.next/static/chunks/0838_s6w-i_ik.js +1 -0
  311. package/.next/standalone/.next/static/chunks/0_1r-3csplxnj.js +1 -0
  312. package/.next/standalone/.next/static/chunks/0ka4prpk3w9wn.js +34 -0
  313. package/.next/standalone/.next/static/chunks/0kscsqnvfq3-r.js +1 -0
  314. package/.next/standalone/.next/static/chunks/0s_xxwp7z88vv.js +1 -0
  315. package/.next/standalone/.next/static/chunks/1-nnl8amfm4yh.js +57 -0
  316. package/.next/standalone/.next/static/chunks/112mv-com-mqa.js +21 -0
  317. package/.next/standalone/.next/static/chunks/1bkt_hhjzvbh8.js +1 -0
  318. package/.next/standalone/.next/static/chunks/1cmphb3kh2ers.css +3 -0
  319. package/.next/standalone/.next/static/chunks/1d8yv3k_atka7.js +1 -0
  320. package/.next/standalone/.next/static/chunks/{0ws7zy0w57ufi.js → 1eyajb9ntzlrl.js} +1 -1
  321. package/.next/standalone/.next/static/chunks/1z9lb-dbcg4aa.js +1 -0
  322. package/.next/standalone/.next/static/chunks/23hc51oa4vkhc.js +5 -0
  323. package/.next/standalone/.next/static/chunks/27n8k9wxlz5-7.js +1 -0
  324. package/.next/standalone/.next/static/chunks/2q9i7pcxcnph1.js +7 -0
  325. package/.next/standalone/.next/static/chunks/2w-y83mjlpnse.js +1 -0
  326. package/.next/standalone/.next/static/chunks/2ws1xf293j-tm.js +5 -0
  327. package/.next/standalone/.next/static/chunks/2z1-q0_vunbql.js +2 -0
  328. package/.next/standalone/.next/static/chunks/34g73qhayuevu.js +1 -0
  329. package/.next/standalone/.next/static/chunks/3cqn-r-y5rrw1.js +5 -0
  330. package/.next/standalone/.next/static/chunks/3opgg1efrx8q6.js +1 -0
  331. package/.next/standalone/.next/static/chunks/3p51fpxxi4d5y.js +34 -0
  332. package/.next/standalone/.next/static/chunks/3y40z6of3r9py.js +1 -0
  333. package/.next/standalone/.next/static/chunks/403dpflln8ah5.js +1 -0
  334. package/.next/standalone/.next/static/chunks/43pg2sursiypz.js +1 -0
  335. package/.next/standalone/CHANGELOG.md +203 -0
  336. package/.next/standalone/README.md +96 -50
  337. package/.next/standalone/SECURITY.md +25 -11
  338. package/.next/standalone/app/api/data/backup/route.js +25 -0
  339. package/.next/standalone/app/api/data/csv/route.js +74 -0
  340. package/.next/standalone/app/api/data/export/route.js +1 -1
  341. package/.next/standalone/app/api/data/restore/route.js +48 -0
  342. package/.next/standalone/app/api/data/reveal/route.js +19 -6
  343. package/.next/standalone/app/api/data/route.js +15 -4
  344. package/.next/standalone/app/api/ingest/route.js +1 -1
  345. package/.next/standalone/app/api/outreach/route.js +13 -73
  346. package/.next/standalone/app/api/queue/route.js +1 -1
  347. package/.next/standalone/app/api/scraper/route.js +217 -36
  348. package/.next/standalone/app/api/social/crm/route.js +2 -1
  349. package/.next/standalone/app/components/AppHeader.js +41 -21
  350. package/.next/standalone/app/components/AppTabs.js +12 -8
  351. package/.next/standalone/app/components/AutoConnect.js +286 -0
  352. package/.next/standalone/app/components/AutoScanButton.js +2 -2
  353. package/.next/standalone/app/components/Avatar.js +1 -1
  354. package/.next/standalone/app/components/ChainView.js +258 -113
  355. package/.next/standalone/app/components/CirclePanel.js +16 -16
  356. package/.next/standalone/app/components/ClusterSpinner.js +64 -0
  357. package/.next/standalone/app/components/CompanyScores.js +20 -20
  358. package/.next/standalone/app/components/EmptyState.js +39 -18
  359. package/.next/standalone/app/components/FieldStep.js +15 -13
  360. package/.next/standalone/app/components/FilterPanel.js +25 -18
  361. package/.next/standalone/app/components/ForceGraph.js +49 -14
  362. package/.next/standalone/app/components/GalaxyLab.js +33 -33
  363. package/.next/standalone/app/components/GridView.js +18 -18
  364. package/.next/standalone/app/components/LegacyScoresCard.js +10 -11
  365. package/.next/standalone/app/components/LinkedInLimits.js +57 -27
  366. package/.next/standalone/app/components/LiquidGlass.js +99 -0
  367. package/.next/standalone/app/components/ListView.js +20 -20
  368. package/.next/standalone/app/components/MapControls.js +5 -5
  369. package/.next/standalone/app/components/MappingProgress.js +16 -16
  370. package/.next/standalone/app/components/NoteDetail.js +13 -13
  371. package/.next/standalone/app/components/OnboardingGate.js +4 -4
  372. package/.next/standalone/app/components/OutlinkQuest.js +56 -35
  373. package/.next/standalone/app/components/PathsAnalyzer.js +37 -36
  374. package/.next/standalone/app/components/PeopleMap.js +21 -21
  375. package/.next/standalone/app/components/RingsView.js +11 -11
  376. package/.next/standalone/app/components/ScanRadar.js +84 -39
  377. package/.next/standalone/app/components/ScanStatusBar.js +40 -21
  378. package/.next/standalone/app/components/ScanTrail.js +21 -8
  379. package/.next/standalone/app/components/SeparationView.js +172 -124
  380. package/.next/standalone/app/components/Sidebar.js +308 -199
  381. package/.next/standalone/app/components/StaleServerBanner.js +4 -4
  382. package/.next/standalone/app/components/TheirCircle.js +26 -26
  383. package/.next/standalone/app/components/ThemeDefs.js +42 -0
  384. package/.next/standalone/app/components/ThemeLoader.js +20 -1
  385. package/.next/standalone/app/components/UpdatePanel.js +22 -22
  386. package/.next/standalone/app/components/UserProvider.js +22 -15
  387. package/.next/standalone/app/components/insights/Boards.js +275 -0
  388. package/.next/standalone/app/components/insights/PeopleView.js +266 -0
  389. package/.next/standalone/app/components/insights/Rail.js +156 -0
  390. package/.next/standalone/app/components/insights/Report.js +382 -0
  391. package/.next/standalone/app/components/insights/parts.js +239 -0
  392. package/.next/standalone/app/components/settings/AppearanceSection.js +47 -24
  393. package/.next/standalone/app/components/settings/DataSection.js +276 -109
  394. package/.next/standalone/app/components/settings/NetworkHealthSection.js +13 -13
  395. package/.next/standalone/app/components/settings/SectorPicker.js +12 -12
  396. package/.next/standalone/app/components/settings/SectorSection.js +13 -14
  397. package/.next/standalone/app/components/settings/TierSection.js +9 -9
  398. package/.next/standalone/app/components/settings/TitleSection.js +11 -11
  399. package/.next/standalone/app/components/settings/UsageSection.js +360 -0
  400. package/.next/standalone/app/components/ui.js +8 -8
  401. package/.next/standalone/app/globals.css +161 -5
  402. package/.next/standalone/app/import/page.js +94 -38
  403. package/.next/standalone/app/insights/page.js +220 -0
  404. package/.next/standalone/app/launch/page.js +5 -5
  405. package/.next/standalone/app/layout.js +6 -2
  406. package/.next/standalone/app/page.js +53 -53
  407. package/.next/standalone/app/paths/page.js +63 -63
  408. package/.next/standalone/app/profile/page.js +58 -58
  409. package/.next/standalone/app/queue/page.js +84 -72
  410. package/.next/standalone/app/scores/page.js +2 -2
  411. package/.next/standalone/app/settings/page.js +16 -13
  412. package/.next/standalone/app/setup/page.js +236 -133
  413. package/.next/standalone/app/social/Crm.js +63 -62
  414. package/.next/standalone/app/social/SocialHub.js +22 -22
  415. package/.next/standalone/app/social/Thread.js +7 -7
  416. package/.next/standalone/app/social/page.js +2 -2
  417. package/.next/standalone/lib/auto-connect.js +145 -0
  418. package/.next/standalone/lib/backups.js +458 -0
  419. package/.next/standalone/lib/chain-layout.js +32 -0
  420. package/.next/standalone/lib/companies.js +1 -1
  421. package/.next/standalone/lib/csv-store.js +131 -0
  422. package/.next/standalone/lib/csv.js +137 -39
  423. package/.next/standalone/lib/data-folder.js +19 -3
  424. package/.next/standalone/lib/data-import.js +5 -2
  425. package/.next/standalone/lib/db-client.js +78 -20
  426. package/.next/standalone/lib/demo.js +5 -4
  427. package/.next/standalone/lib/galaxy-export.js +9 -2
  428. package/.next/standalone/lib/galaxy-lab.js +19 -5
  429. package/.next/standalone/lib/galaxy-layouts.js +43 -0
  430. package/.next/standalone/lib/gate.js +10 -4
  431. package/.next/standalone/lib/in-progress.js +46 -0
  432. package/.next/standalone/lib/ingest.js +1 -1
  433. package/.next/standalone/lib/insights-board.js +613 -0
  434. package/.next/standalone/lib/linkedin-limits.js +240 -14
  435. package/.next/standalone/lib/liquid-glass.js +59 -0
  436. package/.next/standalone/lib/notifications.js +13 -0
  437. package/.next/standalone/lib/requests-client.js +10 -0
  438. package/.next/standalone/lib/requests.js +124 -0
  439. package/.next/standalone/lib/scan-pace.js +11 -0
  440. package/.next/standalone/lib/scan-progress.js +20 -0
  441. package/.next/standalone/lib/scan-risk.js +44 -0
  442. package/.next/standalone/lib/scan-state.js +1 -0
  443. package/.next/standalone/lib/scanner-setup.js +97 -15
  444. package/.next/standalone/lib/scraper-client.js +35 -8
  445. package/.next/standalone/lib/search-risk.js +7 -3
  446. package/.next/standalone/lib/settings-client.js +5 -3
  447. package/.next/standalone/lib/settings.js +13 -0
  448. package/.next/standalone/lib/social-store.js +3 -2
  449. package/.next/standalone/lib/synced-setting.js +46 -0
  450. package/.next/standalone/lib/theme-store.js +42 -10
  451. package/.next/standalone/lib/themes.js +111 -21
  452. package/.next/standalone/lib/usage.js +200 -0
  453. package/.next/standalone/package-lock.json +2 -2
  454. package/.next/standalone/package.json +1 -1
  455. package/.next/standalone/scripts/scrape.py +595 -11
  456. package/.next/static/chunks/02wnf8dkxegxg.js +34 -0
  457. package/.next/static/chunks/03-_esd2x_yk6.js +1 -0
  458. package/.next/static/chunks/03-demj2iy-0p.js +44 -0
  459. package/.next/static/chunks/0838_s6w-i_ik.js +1 -0
  460. package/.next/static/chunks/0_1r-3csplxnj.js +1 -0
  461. package/.next/static/chunks/0ka4prpk3w9wn.js +34 -0
  462. package/.next/static/chunks/0kscsqnvfq3-r.js +1 -0
  463. package/.next/static/chunks/0s_xxwp7z88vv.js +1 -0
  464. package/.next/static/chunks/1-nnl8amfm4yh.js +57 -0
  465. package/.next/static/chunks/112mv-com-mqa.js +21 -0
  466. package/.next/static/chunks/1bkt_hhjzvbh8.js +1 -0
  467. package/.next/static/chunks/1cmphb3kh2ers.css +3 -0
  468. package/.next/static/chunks/1d8yv3k_atka7.js +1 -0
  469. package/.next/static/chunks/{0ws7zy0w57ufi.js → 1eyajb9ntzlrl.js} +1 -1
  470. package/.next/static/chunks/1z9lb-dbcg4aa.js +1 -0
  471. package/.next/static/chunks/23hc51oa4vkhc.js +5 -0
  472. package/.next/static/chunks/27n8k9wxlz5-7.js +1 -0
  473. package/.next/static/chunks/2q9i7pcxcnph1.js +7 -0
  474. package/.next/static/chunks/2w-y83mjlpnse.js +1 -0
  475. package/.next/static/chunks/2ws1xf293j-tm.js +5 -0
  476. package/.next/static/chunks/2z1-q0_vunbql.js +2 -0
  477. package/.next/static/chunks/34g73qhayuevu.js +1 -0
  478. package/.next/static/chunks/3cqn-r-y5rrw1.js +5 -0
  479. package/.next/static/chunks/3opgg1efrx8q6.js +1 -0
  480. package/.next/static/chunks/3p51fpxxi4d5y.js +34 -0
  481. package/.next/static/chunks/3y40z6of3r9py.js +1 -0
  482. package/.next/static/chunks/403dpflln8ah5.js +1 -0
  483. package/.next/static/chunks/43pg2sursiypz.js +1 -0
  484. package/CHANGELOG.md +203 -0
  485. package/README.md +96 -50
  486. package/SECURITY.md +25 -11
  487. package/lib/auto-connect.js +145 -0
  488. package/lib/backups.js +458 -0
  489. package/lib/chain-layout.js +32 -0
  490. package/lib/companies.js +1 -1
  491. package/lib/csv-store.js +131 -0
  492. package/lib/csv.js +137 -39
  493. package/lib/data-folder.js +19 -3
  494. package/lib/data-import.js +5 -2
  495. package/lib/db-client.js +78 -20
  496. package/lib/demo.js +5 -4
  497. package/lib/galaxy-export.js +9 -2
  498. package/lib/galaxy-lab.js +19 -5
  499. package/lib/galaxy-layouts.js +43 -0
  500. package/lib/gate.js +10 -4
  501. package/lib/in-progress.js +46 -0
  502. package/lib/ingest.js +1 -1
  503. package/lib/insights-board.js +613 -0
  504. package/lib/linkedin-limits.js +240 -14
  505. package/lib/liquid-glass.js +59 -0
  506. package/lib/notifications.js +13 -0
  507. package/lib/requests-client.js +10 -0
  508. package/lib/requests.js +124 -0
  509. package/lib/scan-pace.js +11 -0
  510. package/lib/scan-progress.js +20 -0
  511. package/lib/scan-risk.js +44 -0
  512. package/lib/scan-state.js +1 -0
  513. package/lib/scanner-setup.js +97 -15
  514. package/lib/scraper-client.js +35 -8
  515. package/lib/search-risk.js +7 -3
  516. package/lib/settings-client.js +5 -3
  517. package/lib/settings.js +13 -0
  518. package/lib/social-store.js +3 -2
  519. package/lib/synced-setting.js +46 -0
  520. package/lib/theme-store.js +42 -10
  521. package/lib/themes.js +111 -21
  522. package/lib/usage.js +200 -0
  523. package/package.json +1 -1
  524. package/scripts/scrape.py +595 -11
  525. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-rnla2._.js +0 -3
  526. package/.next/standalone/.next/server/chunks/[root-of-the-server]__13dx4sd._.js +0 -8
  527. package/.next/standalone/.next/server/chunks/[root-of-the-server]__14ou7j5._.js +0 -3
  528. package/.next/standalone/.next/server/chunks/[root-of-the-server]__16iu0hv._.js +0 -3
  529. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1kbl21f._.js +0 -3
  530. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rphsdk._.js +0 -3
  531. package/.next/standalone/.next/server/chunks/_02twlca._.js +0 -10
  532. package/.next/standalone/.next/server/chunks/lib_0851sk0._.js +0 -8
  533. package/.next/standalone/.next/server/chunks/lib_1q7p2ro._.js +0 -8
  534. package/.next/standalone/.next/server/chunks/lib_1r6l86l._.js +0 -8
  535. package/.next/standalone/.next/server/chunks/lib_db-client_15le7cw.js +0 -174
  536. package/.next/standalone/.next/server/chunks/lib_rpc_04s8mzr.js +0 -3
  537. package/.next/standalone/.next/server/chunks/lib_rpc_053z7as.js +0 -3
  538. package/.next/standalone/.next/server/chunks/lib_rpc_0b_-2te.js +0 -3
  539. package/.next/standalone/.next/server/chunks/lib_rpc_0dhbxdm.js +0 -3
  540. package/.next/standalone/.next/server/chunks/lib_rpc_0dxlk31.js +0 -3
  541. package/.next/standalone/.next/server/chunks/lib_rpc_0f8b-qc.js +0 -3
  542. package/.next/standalone/.next/server/chunks/lib_rpc_0pzie7_.js +0 -3
  543. package/.next/standalone/.next/server/chunks/lib_rpc_0r76fq_.js +0 -3
  544. package/.next/standalone/.next/server/chunks/lib_rpc_0ut7pjp.js +0 -3
  545. package/.next/standalone/.next/server/chunks/lib_rpc_15zyqaz.js +0 -3
  546. package/.next/standalone/.next/server/chunks/lib_rpc_18zpjtq.js +0 -3
  547. package/.next/standalone/.next/server/chunks/lib_rpc_1a8xkiz.js +0 -3
  548. package/.next/standalone/.next/server/chunks/lib_rpc_1e_55xo.js +0 -3
  549. package/.next/standalone/.next/server/chunks/lib_rpc_1oxfd1_.js +0 -3
  550. package/.next/standalone/.next/server/chunks/lib_rpc_1s0lod0.js +0 -3
  551. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08oxiqh._.js +0 -3
  552. package/.next/standalone/.next/server/chunks/ssr/_03l7vge._.js +0 -3
  553. package/.next/standalone/.next/server/chunks/ssr/_08g31gm._.js +0 -3
  554. package/.next/standalone/.next/server/chunks/ssr/_0gk_ofx._.js +0 -3
  555. package/.next/standalone/.next/server/chunks/ssr/_0nwsf93._.js +0 -3
  556. package/.next/standalone/.next/server/chunks/ssr/_0vho1lb._.js +0 -3
  557. package/.next/standalone/.next/server/chunks/ssr/_1-658fq._.js +0 -3
  558. package/.next/standalone/.next/server/chunks/ssr/_1bc46kz._.js +0 -3
  559. package/.next/standalone/.next/server/chunks/ssr/_1f_n00p._.js +0 -3
  560. package/.next/standalone/.next/server/chunks/ssr/_2105jz8._.js +0 -3
  561. package/.next/standalone/.next/server/chunks/ssr/app_components_0t908t-._.js +0 -3
  562. package/.next/standalone/.next/static/chunks/02pq76u7y4v9-.js +0 -22
  563. package/.next/standalone/.next/static/chunks/0cmq0exd4d0h9.js +0 -1
  564. package/.next/standalone/.next/static/chunks/0i02yxppzds1o.js +0 -1
  565. package/.next/standalone/.next/static/chunks/0m_p4k-q2qh--.js +0 -1
  566. package/.next/standalone/.next/static/chunks/0oyslj62jkubd.js +0 -1
  567. package/.next/standalone/.next/static/chunks/0vo-l8hxneba6.css +0 -3
  568. package/.next/standalone/.next/static/chunks/0yh8z2tbrc5i_.js +0 -1
  569. package/.next/standalone/.next/static/chunks/17-rhp8sg4m1b.js +0 -44
  570. package/.next/standalone/.next/static/chunks/172e10mi-tpo_.js +0 -34
  571. package/.next/standalone/.next/static/chunks/1ei5vbe2uw6fl.js +0 -1
  572. package/.next/standalone/.next/static/chunks/1f7_pl_wq7lh3.js +0 -11
  573. package/.next/standalone/.next/static/chunks/1jzbe7zdx9vbj.js +0 -2
  574. package/.next/standalone/.next/static/chunks/1m3017gp790pw.js +0 -45
  575. package/.next/standalone/.next/static/chunks/1t20e8u0st7ep.js +0 -1
  576. package/.next/standalone/.next/static/chunks/2-ch9rm27eril.js +0 -11
  577. package/.next/standalone/.next/static/chunks/2ldv-v3s9yaif.js +0 -1
  578. package/.next/standalone/.next/static/chunks/3bp284gjf7dyq.js +0 -1
  579. package/.next/standalone/.next/static/chunks/3k1f6clbn3gj3.js +0 -7
  580. package/.next/standalone/.next/static/chunks/3l4t8je6iguzc.js +0 -1
  581. package/.next/standalone/.next/static/chunks/3tplzuc9jk-tl.js +0 -1
  582. package/.next/standalone/.next/static/chunks/42m0bqr8pbovz.js +0 -11
  583. package/.next/static/chunks/02pq76u7y4v9-.js +0 -22
  584. package/.next/static/chunks/0cmq0exd4d0h9.js +0 -1
  585. package/.next/static/chunks/0i02yxppzds1o.js +0 -1
  586. package/.next/static/chunks/0m_p4k-q2qh--.js +0 -1
  587. package/.next/static/chunks/0oyslj62jkubd.js +0 -1
  588. package/.next/static/chunks/0vo-l8hxneba6.css +0 -3
  589. package/.next/static/chunks/0yh8z2tbrc5i_.js +0 -1
  590. package/.next/static/chunks/17-rhp8sg4m1b.js +0 -44
  591. package/.next/static/chunks/172e10mi-tpo_.js +0 -34
  592. package/.next/static/chunks/1ei5vbe2uw6fl.js +0 -1
  593. package/.next/static/chunks/1f7_pl_wq7lh3.js +0 -11
  594. package/.next/static/chunks/1jzbe7zdx9vbj.js +0 -2
  595. package/.next/static/chunks/1m3017gp790pw.js +0 -45
  596. package/.next/static/chunks/1t20e8u0st7ep.js +0 -1
  597. package/.next/static/chunks/2-ch9rm27eril.js +0 -11
  598. package/.next/static/chunks/2ldv-v3s9yaif.js +0 -1
  599. package/.next/static/chunks/3bp284gjf7dyq.js +0 -1
  600. package/.next/static/chunks/3k1f6clbn3gj3.js +0 -7
  601. package/.next/static/chunks/3l4t8je6iguzc.js +0 -1
  602. package/.next/static/chunks/3tplzuc9jk-tl.js +0 -1
  603. package/.next/static/chunks/42m0bqr8pbovz.js +0 -11
  604. /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_buildManifest.js +0 -0
  605. /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_clientMiddlewareManifest.js +0 -0
  606. /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_ssgManifest.js +0 -0
  607. /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_buildManifest.js +0 -0
  608. /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_clientMiddlewareManifest.js +0 -0
  609. /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_ssgManifest.js +0 -0
@@ -4,23 +4,35 @@
4
4
  // reads them with the same rules, and writes only the two things a person
5
5
  // changes here — the budget, and lifting a cooldown.
6
6
  //
7
+ // Settings → LinkedIn usage reads the same record more closely (linkedinUsage):
8
+ // the last hour and the last 7 days, when the next search frees up, and the
9
+ // last time LinkedIn pushed back. lib/usage.js says what the numbers mean.
10
+ //
7
11
  // The budget is searches (a day and a month) and profile views (a day). Profile
8
12
  // views got an account restricted (TRAPS §16), so their cap has no "no limit",
9
13
  // and the scanner also keeps any two a minute apart. Searches did too, at 373 in
10
14
  // 24 hours: the page asks before a risky search budget (lib/search-risk.js).
11
15
  //
16
+ // Auto's connection requests (lib/auto-connect.js) are a third list in the same
17
+ // record, "invites", with caps of their own: 15 in any 24 hours, 80 in any 7 days.
18
+ //
12
19
  // They belong to the LinkedIn account, not to a profile in the app. TRAPS §35.
13
20
 
14
- import { readFileSync, writeFileSync, renameSync, unlinkSync, existsSync, lstatSync } from 'node:fs';
21
+ import {
22
+ readFileSync, writeFileSync, renameSync, unlinkSync, existsSync, lstatSync, readdirSync, openSync, readSync, closeSync,
23
+ } from 'node:fs';
15
24
  import path from 'node:path';
16
25
  import { durable } from './durable.js';
17
26
  import { PACES, DEFAULT_PACE } from './scan-pace.js';
27
+ import { countAfter } from './usage.js';
28
+ import { INVITE_CAPS } from './auto-connect.js';
18
29
 
19
30
  export const DEFAULT_LIMITS = { daily: 50, monthly: 250, profiles: 50, pace: DEFAULT_PACE };
20
31
  export const DAILY_CHOICES = [25, 50, 100, 200, 500];
21
32
  export const MONTHLY_CHOICES = [100, 250, 500, 1000, 0]; // 0 = no monthly cap (Premium)
22
33
  export const PROFILE_CHOICES = [10, 25, 50, 100]; // profile views a day; never unlimited
23
34
  const DAY = 24 * 3600;
35
+ const WEEK = 7 * DAY;
24
36
  const PACIFIC = 'America/Los_Angeles';
25
37
 
26
38
  function readJson(file) {
@@ -94,6 +106,19 @@ export function writeLimits(dir, { daily, monthly, profiles, pace } = {}) {
94
106
  return next;
95
107
  }
96
108
 
109
+ /**
110
+ * The scanner's record as three lists of times (epoch seconds): searches,
111
+ * profile views and Auto's connection requests. null when it can't be read. No
112
+ * record at all is nothing done yet.
113
+ */
114
+ function readActivity(dir) {
115
+ const file = path.join(dir, 'linkedin-activity.json');
116
+ const data = existsSync(file) ? readJson(file) : { searches: [], profiles: [] };
117
+ if (!data || typeof data !== 'object') return null;
118
+ const times = (v) => (Array.isArray(v) ? v : []).map(Number);
119
+ return { searches: times(data.searches), profiles: times(data.profiles), invites: times(data.invites) };
120
+ }
121
+
97
122
  /**
98
123
  * Searches in the last 24 hours and since LinkedIn's month began, and profile
99
124
  * views in the last 24 hours. An unreadable record reads as the day used up,
@@ -101,31 +126,59 @@ export function writeLimits(dir, { daily, monthly, profiles, pace } = {}) {
101
126
  * would say nothing had been searched.
102
127
  */
103
128
  export function usage(dir, now = Date.now()) {
104
- const file = path.join(dir, 'linkedin-activity.json');
105
- const data = existsSync(file) ? readJson(file) : { searches: [], profiles: [] };
106
- if (!data || typeof data !== 'object') return { searchesToday: Infinity, searchesMonth: 0, profilesToday: Infinity, unreadable: true };
107
- const s = (Array.isArray(data.searches) ? data.searches : []).map(Number);
108
- const p = (Array.isArray(data.profiles) ? data.profiles : []).map(Number);
129
+ const rec = readActivity(dir);
130
+ if (!rec) {
131
+ return { searchesToday: Infinity, searchesMonth: 0, profilesToday: Infinity, invitesToday: Infinity, invitesWeek: Infinity, unreadable: true };
132
+ }
133
+ const { searches: s, profiles: p, invites: i } = rec;
109
134
  const dayAgo = now / 1000 - DAY;
110
135
  const month0 = monthStartPacific(now) / 1000;
111
136
  return {
112
137
  searchesToday: s.filter((t) => t > dayAgo).length,
113
138
  searchesMonth: s.filter((t) => t >= month0).length,
114
139
  profilesToday: p.filter((t) => t > dayAgo).length,
140
+ // Auto's connection requests (lib/auto-connect.js), against their own caps.
141
+ invitesToday: i.filter((t) => t > dayAgo).length,
142
+ invitesWeek: i.filter((t) => t > now / 1000 - WEEK).length,
115
143
  };
116
144
  }
117
145
 
118
- /** The active cooldown { until (ms), reason, setAt }, or null. */
146
+ /** The active cooldown { until (ms), reason, setAt }, or null. A lifted one (liftCooldown) is none. */
119
147
  export function readCooldown(dir, now = Date.now()) {
120
148
  const raw = readJson(path.join(dir, 'linkedin-cooldown.json'));
121
149
  const until = Number(raw?.until) * 1000;
122
- if (!raw || !Number.isFinite(until) || until <= now) return null;
150
+ if (!raw || raw.lifted_at !== undefined || !Number.isFinite(until) || until <= now) return null;
123
151
  return { until, reason: String(raw.reason || 'LinkedIn pushed back'), setAt: Number(raw.set_at) * 1000 || null };
124
152
  }
125
153
 
126
- /** Lift it: the person says LinkedIn works for them again. */
127
- export function liftCooldown(dir) {
128
- try { unlinkSync(path.join(dir, 'linkedin-cooldown.json')); } catch { /* none to lift */ }
154
+ /**
155
+ * Lift it: the person says LinkedIn works for them again. The record is kept,
156
+ * marked lifted, so Settings → LinkedIn usage can still say when LinkedIn last
157
+ * pushed back; deleting it forgot that. Its `until` becomes the moment it was
158
+ * lifted and the old end moves to `was_until`, so everything that reads the
159
+ * file sees a pause that has simply ended, with no change of its own: here
160
+ * (readCooldown, the import's merge) and in the scanner (read_cooldown and
161
+ * set_cooldown in scripts/scrape.py ask only whether `until` is still ahead),
162
+ * so the scanner's pacing is exactly what it was. A pause already over is
163
+ * left alone; a record that can't be read is removed, as before.
164
+ */
165
+ export function liftCooldown(dir, now = Date.now()) {
166
+ const file = path.join(dir, COOLDOWN);
167
+ const raw = readJson(file);
168
+ const until = Number(raw?.until);
169
+ if (!isObject(raw) || !Number.isFinite(until)) {
170
+ try { unlinkSync(file); } catch { /* none to lift */ }
171
+ return;
172
+ }
173
+ const at = now / 1000;
174
+ if (until <= at) return;
175
+ writeJsonAtomic(file, {
176
+ until: at,
177
+ reason: typeof raw.reason === 'string' ? raw.reason : 'LinkedIn pushed back',
178
+ set_at: isTime(raw.set_at) ? raw.set_at : null,
179
+ lifted_at: at,
180
+ was_until: until,
181
+ });
129
182
  }
130
183
 
131
184
  /** Everything the Scan page shows, in one object. */
@@ -133,17 +186,175 @@ export function linkedinState(dir, now = Date.now()) {
133
186
  const limits = readLimits(dir);
134
187
  const use = usage(dir, now);
135
188
  const left = (limit, used) => (limit ? Math.max(0, limit - used) : null);
189
+ // When Auto may send again once a cap is reached: the request that stops
190
+ // counting soonest frees the next (freesAt below).
191
+ const invites = use.unreadable ? null : readActivity(dir)?.invites || [];
136
192
  return {
137
193
  ...use,
138
194
  limits,
139
195
  leftToday: left(limits.daily, use.searchesToday),
140
196
  leftMonth: left(limits.monthly, use.searchesMonth),
141
197
  profilesLeftToday: left(limits.profiles, use.profilesToday),
198
+ inviteCaps: INVITE_CAPS,
199
+ invitesFreeAt: invites ? freesAt(invites, now, INVITE_CAPS.day) : null,
200
+ invitesWeekFreeAt: invites ? freesAt(invites, now, INVITE_CAPS.week, WEEK) : null,
142
201
  monthResets: nextMonthStartPacific(now),
143
202
  cooldown: readCooldown(dir, now),
144
203
  };
145
204
  }
146
205
 
206
+ // ── Settings → LinkedIn usage ────────────────────────────────────────────────
207
+ // The same record, read more closely. Windows count a time strictly inside
208
+ // them (t > now - window), as usage() and the scanner's linkedin_usage do, so a
209
+ // search exactly 24 hours old has stopped counting.
210
+
211
+ /** How many of `times` (epoch s) fall in the last `seconds` before `now` (ms). */
212
+ export function countWithin(times, now, seconds) {
213
+ const from = now / 1000 - seconds;
214
+ return times.filter((t) => t > from).length;
215
+ }
216
+
217
+ /**
218
+ * When the count in the window next drops under `cap`, in ms: the moment a
219
+ * search (or profile view) is free again. null when one is free now, or with
220
+ * no cap. The scanner says the same for profile views (scrape.py
221
+ * budget_message: the one that stops counting soonest frees the next).
222
+ */
223
+ export function freesAt(times, now, cap, seconds = DAY) {
224
+ if (!cap) return null;
225
+ const live = times.filter((t) => t > now / 1000 - seconds).sort((a, b) => a - b);
226
+ if (live.length < cap) return null;
227
+ return (live[live.length - cap] + seconds) * 1000;
228
+ }
229
+
230
+ /** When the window holds nothing at all again (the newest time turns `seconds` old), in ms; null if it's empty. */
231
+ export function clearAt(times, now, seconds = DAY) {
232
+ const live = times.filter((t) => t > now / 1000 - seconds);
233
+ return live.length ? (Math.max(...live) + seconds) * 1000 : null;
234
+ }
235
+
236
+ // The scanner keeps what the page showed when LinkedIn pushed back as
237
+ // pushback/<local date>_<time>.txt: "reason: …", then "url: …", then the page's
238
+ // text (scrape.py _keep_pushback_evidence). Only the name's time and the first
239
+ // line are read here: the page's address and its text are LinkedIn's page about
240
+ // this account and stay in the file.
241
+ const PUSHBACK_FILE = /^(\d{4})-(\d{2})-(\d{2})_(\d{2})(\d{2})(\d{2})\.txt$/;
242
+ const FIRST_LINE_BYTES = 256;
243
+
244
+ /** The reason on a pushback file's first line, or null. Never more of the file. */
245
+ function pushbackReason(file) {
246
+ let fd;
247
+ try {
248
+ fd = openSync(file, 'r');
249
+ const buf = Buffer.alloc(FIRST_LINE_BYTES);
250
+ const n = readSync(fd, buf, 0, FIRST_LINE_BYTES, 0);
251
+ const line = buf.subarray(0, n).toString('utf8').split(/\r?\n/)[0];
252
+ const m = line.match(/^reason: (.+)$/);
253
+ const reason = m && m[1].replace(/[\u0000-\u001f\u007f]/g, '').trim().slice(0, 120);
254
+ // The scanner's reasons are its own short phrases; anything shaped like an address isn't one.
255
+ return reason && !/:\/\/|www\.|linkedin\.com|\/in\//i.test(reason) ? reason : null;
256
+ } catch {
257
+ return null;
258
+ } finally {
259
+ if (fd !== undefined) closeSync(fd);
260
+ }
261
+ }
262
+
263
+ /** The newest pushback file: { at (ms, from its name), reason }, or null. */
264
+ export function newestPushback(dir) {
265
+ let names;
266
+ try {
267
+ // Plain files only: a link or a folder by that name is not the scanner's.
268
+ names = readdirSync(path.join(dir, 'pushback'), { withFileTypes: true })
269
+ .filter((e) => e.isFile() && PUSHBACK_FILE.test(e.name)).map((e) => e.name);
270
+ } catch {
271
+ return null;
272
+ }
273
+ // Newest first by name, which is by time; a name that isn't a real time is passed over.
274
+ for (const name of names.sort().reverse()) {
275
+ const [, y, mo, d, h, mi, s] = name.match(PUSHBACK_FILE).map(Number);
276
+ // The scanner names it by this computer's clock (datetime.now()), as this reads it.
277
+ const when = new Date(y, mo - 1, d, h, mi, s);
278
+ if (when.getMonth() !== mo - 1 || when.getDate() !== d || h > 23 || mi > 59 || s > 59) continue;
279
+ return { at: when.getTime(), reason: pushbackReason(path.join(dir, 'pushback', name)) };
280
+ }
281
+ return null;
282
+ }
283
+
284
+ // One pushback usually leaves both: the page kept, then the pause set, moments
285
+ // (at most the rest of that person's read) apart.
286
+ const SAME_EVENT_MS = 10 * 60 * 1000;
287
+
288
+ /**
289
+ * The last time LinkedIn pushed back, from the cooldown file (active, ended or
290
+ * lifted) and the newest pushback file: { at (ms or null), reason, pausedUntil,
291
+ * liftedAt, active }, or null when there's no sign of one. Times and the
292
+ * reason only.
293
+ */
294
+ export function lastPushback(dir, now = Date.now()) {
295
+ const file = newestPushback(dir);
296
+ const raw = readJson(path.join(dir, COOLDOWN));
297
+ const until = Number(raw?.until);
298
+ const pause = isObject(raw) && Number.isFinite(until) ? {
299
+ at: isTime(raw.set_at) ? raw.set_at * 1000 : null,
300
+ reason: typeof raw.reason === 'string' && raw.reason.trim() ? raw.reason.trim().slice(0, 160) : 'LinkedIn pushed back',
301
+ pausedUntil: (isTime(raw.was_until) ? raw.was_until : until) * 1000,
302
+ liftedAt: isTime(raw.lifted_at) ? raw.lifted_at * 1000 : null,
303
+ } : null;
304
+ const fromFile = file && {
305
+ at: file.at,
306
+ reason: file.reason ? `LinkedIn pushed back: ${file.reason}` : 'LinkedIn pushed back',
307
+ pausedUntil: null,
308
+ liftedAt: null,
309
+ };
310
+ let last;
311
+ if (pause && fromFile && pause.at != null && Math.abs(pause.at - fromFile.at) <= SAME_EVENT_MS) {
312
+ last = { ...pause, at: Math.min(pause.at, fromFile.at) };
313
+ } else if (pause && fromFile) {
314
+ last = (pause.at ?? -Infinity) >= fromFile.at ? pause : fromFile;
315
+ } else {
316
+ last = pause || fromFile;
317
+ }
318
+ if (!last) return null;
319
+ return { ...last, active: !last.liftedAt && last.pausedUntil != null && last.pausedUntil > now };
320
+ }
321
+
322
+ /**
323
+ * Everything Settings → LinkedIn usage shows (GET /api/scraper?usage): the
324
+ * Scan page's state, plus
325
+ * searchesLastHour, searchesWeek counted like searchesToday
326
+ * dayFreesAt when the daily budget has a search free again (null: one is free now)
327
+ * dayClearAt when the last 24 hours hold no searches at all
328
+ * profilesFreeAt when a profile view is free again
329
+ * lastPushback lastPushback() above
330
+ * searchesSincePushback searches made after it (lib/usage.js countAfter)
331
+ * An unreadable record gives nulls, never zeros: it isn't "nothing searched".
332
+ */
333
+ export function linkedinUsage(dir, now = Date.now()) {
334
+ const state = linkedinState(dir, now);
335
+ const rec = readActivity(dir);
336
+ const pushback = lastPushback(dir, now);
337
+ const known = (fn) => (rec ? fn(rec) : null);
338
+ return {
339
+ ...state,
340
+ now,
341
+ searchesToday: rec ? state.searchesToday : null,
342
+ profilesToday: rec ? state.profilesToday : null,
343
+ // Auto's connection requests: the last 24 hours and the last 7 days, against INVITE_CAPS.
344
+ invitesToday: rec ? state.invitesToday : null,
345
+ invitesWeek: rec ? state.invitesWeek : null,
346
+ searchesMonth: rec ? state.searchesMonth : null,
347
+ leftMonth: rec ? state.leftMonth : null,
348
+ searchesLastHour: known((r) => countWithin(r.searches, now, 3600)),
349
+ searchesWeek: known((r) => countWithin(r.searches, now, 7 * DAY)),
350
+ dayFreesAt: known((r) => freesAt(r.searches, now, state.limits.daily)),
351
+ dayClearAt: known((r) => clearAt(r.searches, now)),
352
+ profilesFreeAt: known((r) => freesAt(r.profiles, now, state.limits.profiles)),
353
+ lastPushback: pushback,
354
+ searchesSincePushback: known((r) => countAfter(r.searches, pushback?.at)),
355
+ };
356
+ }
357
+
147
358
  // ── another computer's budget (Settings → Your data → Import) ───────────────
148
359
  // An import carries these three files from the other computer. They describe
149
360
  // the same LinkedIn account, so they are merged with the ones here, never put
@@ -170,11 +381,15 @@ const isTime = (v) => typeof v === 'number' && Number.isFinite(v) && v >= 0;
170
381
  export function budgetFileProblem(name, data) {
171
382
  if (!isObject(data)) return 'it is not a JSON object';
172
383
  if (name === ACTIVITY) {
173
- if (!isTimeList(data.searches) || !isTimeList(data.profiles)) return 'its record of searches is not a list of times';
384
+ if (!isTimeList(data.searches) || !isTimeList(data.profiles) || !isTimeList(data.invites)) return 'its record of searches is not a list of times';
174
385
  } else if (name === COOLDOWN) {
175
386
  if (!isTime(data.until)) return 'its pause has no end time';
176
387
  if (data.reason !== undefined && typeof data.reason !== 'string') return 'its pause has a reason that is not text';
177
388
  if (data.set_at !== undefined && !isTime(data.set_at)) return 'its pause has a start time that is not a time';
389
+ // A pause lifted by hand (liftCooldown) says when, and when it would have ended.
390
+ for (const key of ['lifted_at', 'was_until']) {
391
+ if (data[key] !== undefined && !isTime(data[key])) return 'its lifted pause has a time that is not a time';
392
+ }
178
393
  } else if (name === LIMITS) {
179
394
  if (data.daily !== undefined && !DAILY_CHOICES.includes(data.daily)) {
180
395
  return `its daily limit (${String(data.daily).slice(0, 20)}) is not one Six Degrees offers`;
@@ -218,7 +433,8 @@ const hasFile = (p) => {
218
433
  /**
219
434
  * Merge the budget files in `from` (an import's, already checked with
220
435
  * budgetFileProblem) into the data folder `dir`:
221
- * linkedin-activity.json both computers' searches and profile views (mergeTimes)
436
+ * linkedin-activity.json both computers' searches, profile views and Auto's
437
+ * connection requests (mergeTimes)
222
438
  * linkedin-cooldown.json whichever pause ends later
223
439
  * scan-limits.json this computer's, if it has one; the copy's otherwise.
224
440
  * The limits are a choice someone made here, and an
@@ -240,10 +456,16 @@ export function mergeBudgetFiles({ dir, from }) {
240
456
  const mine = hasFile(here(ACTIVITY)) ? readJson(here(ACTIVITY)) : {};
241
457
  const searches = isObject(mine) ? readableTimes(mine.searches) : null;
242
458
  const profiles = isObject(mine) ? readableTimes(mine.profiles) : null;
243
- if (searches && profiles) {
459
+ const invites = isObject(mine) ? readableTimes(mine.invites) : null;
460
+ if (searches && profiles && invites) {
461
+ // Auto's requests too, or a copy brought in would forget the ones sent here
462
+ // (and Auto's caps would start again from nothing). Written only when
463
+ // either side has any, so a record from before Auto keeps its old layout.
464
+ const sent = mergeTimes(invites, activity.invites);
244
465
  durable.writeJsonDurably(here(ACTIVITY), {
245
466
  searches: mergeTimes(searches, activity.searches),
246
467
  profiles: mergeTimes(profiles, activity.profiles),
468
+ ...(sent.length ? { invites: sent } : {}),
247
469
  });
248
470
  }
249
471
  }
@@ -252,11 +474,15 @@ export function mergeBudgetFiles({ dir, from }) {
252
474
  if (cooldown) {
253
475
  const mine = readJson(here(COOLDOWN));
254
476
  const mineEnds = Number.isFinite(Number(mine?.until)) ? Number(mine.until) : -Infinity;
477
+ // A pause lifted here ends when it was lifted (liftCooldown), so one still
478
+ // on in the copy comes back, as it did when lifting deleted the file.
255
479
  if (cooldown.until > mineEnds) {
256
480
  durable.writeJsonDurably(here(COOLDOWN), {
257
481
  until: cooldown.until,
258
482
  reason: cooldown.reason ?? 'LinkedIn pushed back',
259
483
  set_at: cooldown.set_at ?? null,
484
+ // Lifted in the copy: still lifted here, and still the last pushback on record.
485
+ ...(cooldown.lifted_at !== undefined && { lifted_at: cooldown.lifted_at, was_until: cooldown.was_until ?? cooldown.until }),
260
486
  });
261
487
  }
262
488
  }
@@ -0,0 +1,59 @@
1
+ // Liquid Glass's lensing (Apple, WWDC25 "Meet Liquid Glass"; HIG → Materials):
2
+ // the edge of a pane of glass bends what's behind it, where frosted glass only
3
+ // blurs it. Done the way the good web versions do it in Chromium: a
4
+ // displacement map, drawn here for a panel's exact size, used by an SVG
5
+ // feDisplacementMap that the panel's backdrop-filter runs
6
+ // (app/components/LiquidGlass.js).
7
+ //
8
+ // The map's red channel shifts a pixel across, green up and down; 128 is no
9
+ // shift. Only a band along the edge (the bezel) moves, and it always pulls
10
+ // inward, since a backdrop is clipped to the panel and anything pulled from
11
+ // outside it would come back empty.
12
+
13
+ /**
14
+ * How far, and which way, each pixel of a rounded rectangle w×h (corner r)
15
+ * bends: [dx, dy] in -1…1 for (x, y), strongest at the edge and fading to
16
+ * nothing `bezel` pixels in.
17
+ */
18
+ export function lensAt(x, y, w, h, r, bezel) {
19
+ const px = x + 0.5 - w / 2;
20
+ const py = y + 0.5 - h / 2;
21
+ const qx = Math.abs(px) - (w / 2 - r);
22
+ const qy = Math.abs(py) - (h / 2 - r);
23
+ const ox = Math.max(qx, 0);
24
+ const oy = Math.max(qy, 0);
25
+ const o = Math.hypot(ox, oy);
26
+ const dist = r - (o + Math.min(Math.max(qx, qy), 0)); // pixels in from the edge
27
+ let nx = 0;
28
+ let ny = 0;
29
+ if (o > 0) { nx = ox / o; ny = oy / o; } else if (qx > qy) nx = 1; else ny = 1;
30
+ nx *= -Math.sign(px) || 0;
31
+ ny *= -Math.sign(py) || 0;
32
+ const t = Math.max(0, 1 - dist / bezel);
33
+ const m = t * t;
34
+ return [nx * m, ny * m];
35
+ }
36
+
37
+ /** The displacement map for a w×h panel, as a PNG data URL (needs a canvas: the browser only). */
38
+ export function lensMap(w, h, r, bezel) {
39
+ const c = document.createElement('canvas');
40
+ c.width = w;
41
+ c.height = h;
42
+ const ctx = c.getContext('2d');
43
+ const img = ctx.createImageData(w, h);
44
+ const d = img.data;
45
+ for (let y = 0; y < h; y++) {
46
+ for (let x = 0; x < w; x++) {
47
+ const i = (y * w + x) * 4;
48
+ // Most of a big panel is its middle, which never moves.
49
+ const nearEdge = x < bezel + r || y < bezel + r || x >= w - bezel - r || y >= h - bezel - r;
50
+ const [dx, dy] = nearEdge ? lensAt(x, y, w, h, r, bezel) : [0, 0];
51
+ d[i] = 128 + 127 * dx;
52
+ d[i + 1] = 128 + 127 * dy;
53
+ d[i + 2] = 128;
54
+ d[i + 3] = 255;
55
+ }
56
+ }
57
+ ctx.putImageData(img, 0, 0);
58
+ return c.toDataURL();
59
+ }
@@ -94,6 +94,19 @@ const NAME_IN_TITLE = [
94
94
  * `via` is who you met them through: the notification's own, else the person's
95
95
  * recorded introducer. `people` are everyone it names (a top-company list).
96
96
  */
97
+ /**
98
+ * Which circle a notification is about, as a connection's id (a string), or
99
+ * null: whoever someone came through for "added you back" and "top companies",
100
+ * and whose circle it was for "Scan done". Read from what the note saved, so it
101
+ * needs nothing loaded.
102
+ */
103
+ export function noteCircle(note) {
104
+ const data = typeof note?.data === 'string' ? safeJson(note.data) : note?.data || {};
105
+ if (data.viaId != null) return String(data.viaId);
106
+ if (data.action && data.personId != null) return String(data.personId);
107
+ return null;
108
+ }
109
+
97
110
  export function noteSubject(note, connections = [], degree2 = []) {
98
111
  const all = [...(connections || []), ...(degree2 || [])];
99
112
  const byId = new Map(all.map((r) => [r.id, r]));
@@ -96,6 +96,16 @@ export async function markRequested(row, { bridgeId } = {}) {
96
96
  }
97
97
  }
98
98
 
99
+ /**
100
+ * A request the app has already saved, shown everywhere at once with nothing
101
+ * posted: Auto's, which the server marks itself once LinkedIn shows it pending
102
+ * (app/api/scraper/route.js, lib/requests.js).
103
+ */
104
+ export function sawRequested(row) {
105
+ mine.set(keyFor(row), true);
106
+ publish();
107
+ }
108
+
99
109
  /** Take a request back, everywhere. */
100
110
  export async function undoRequest(row) {
101
111
  const key = keyFor(row);
@@ -0,0 +1,124 @@
1
+ // Requests you've sent, kept per PERSON: the server side of
2
+ // lib/requests-client.js.
3
+ //
4
+ // A person has one row per bridge whose circle holds them (the table's key is
5
+ // profile + bridge + user), and a request used to mark only the copy that was
6
+ // clicked. The other copies still offered "Add", the Pending count counted
7
+ // copies, and every click awarded XP again. Now a request marks every copy of
8
+ // the person, in both columns, the bridge you asked through is kept (so once
9
+ // they accept, their card and circle say who introduced you: lib/promote.js
10
+ // keeps it), XP comes once per person, and Undo takes back all of it.
11
+ //
12
+ // Two callers: POST /api/outreach (a Connect pressed on a page), and the
13
+ // scanner's route once Auto has sent a request and LinkedIn showed it pending
14
+ // (app/api/scraper/route.js; Blake, 2026-10-03). Both go through markSent here,
15
+ // so a request sent by Auto is the same request everywhere as one sent by hand.
16
+
17
+ import { db as supabase } from './db.js';
18
+ import { resolveProfile } from './profile.js';
19
+
20
+ // XP rewards by tier
21
+ export const XP_SEND = { S: 25, A: 15, B: 10, C: 5, D: 2 };
22
+ export const XP_ACCEPT = { S: 100, A: 60, B: 35, C: 15, D: 5 };
23
+ const TIER_ORDER = ['S', 'A', 'B', 'C', 'D'];
24
+
25
+ export async function awardXP(userId, amount) {
26
+ if (!userId || !amount) return;
27
+ // Upsert: create if not exists, change if exists. Never below zero: an Undo
28
+ // takes back what a send gave, including sends from before sends gave any.
29
+ const { data: existing } = await supabase.from('user_stats').select('xp').eq('id', userId).single();
30
+ if (existing) {
31
+ await supabase.from('user_stats').update({ xp: Math.max(0, (existing.xp || 0) + amount) }).eq('id', userId);
32
+ } else if (amount > 0) {
33
+ await supabase.from('user_stats').insert([{ id: userId, xp: amount, level: 1 }]).catch(() => {});
34
+ }
35
+ }
36
+
37
+ /** The profile a request belongs to: the one sent, else this machine's. */
38
+ export function whose(userId) {
39
+ if (userId) return String(userId);
40
+ try { return resolveProfile({ create: false })?.id || null; } catch { return null; }
41
+ }
42
+
43
+ /** Every copy of one person: by the clicked row's profile URL, or the URL given. */
44
+ export function copiesOf(db, { connectionId, profileUrl, userId }) {
45
+ let url = profileUrl ? String(profileUrl) : null;
46
+ let user = userId ? String(userId) : null;
47
+ let clicked = null;
48
+ if (connectionId != null) {
49
+ clicked = db.prepare('SELECT id, profile_url, user_id FROM linkedin_connections WHERE id = ?').get(String(connectionId)) || null;
50
+ if (clicked) {
51
+ url = clicked.profile_url || url;
52
+ user = user || clicked.user_id || null;
53
+ }
54
+ }
55
+ const cols = 'id, degree, tier, outreach_status, unlock_status, unlocked_from_bridge_id';
56
+ let rows = [];
57
+ if (url) {
58
+ rows = user
59
+ ? db.prepare(`SELECT ${cols} FROM linkedin_connections WHERE profile_url = ? AND user_id = ?`).all(url, user)
60
+ : db.prepare(`SELECT ${cols} FROM linkedin_connections WHERE profile_url = ?`).all(url);
61
+ } else if (clicked) {
62
+ rows = db.prepare(`SELECT ${cols} FROM linkedin_connections WHERE id = ?`).all(clicked.id);
63
+ }
64
+ return { url, user, rows };
65
+ }
66
+
67
+ export const inList = (ids) => ids.map(() => '?').join(', ');
68
+ export const bestTier = (rows) => TIER_ORDER.find((t) => rows.some((r) => r.tier === t)) || 'D';
69
+
70
+ /**
71
+ * Mark a request to this person as sent, on every copy of them, through
72
+ * `bridgeId` (one of your own connections) when given: the rows only, at once.
73
+ * Returns { saved, xp, already, user }: `saved` is how many rows (0 when nobody
74
+ * is on file, as for the sample network, which lives in the browser), `xp` what
75
+ * the send is worth (once per person), for markSent or the caller to award.
76
+ */
77
+ export function markSentRows(db, { connectionId, profileUrl, userId, bridgeId } = {}) {
78
+ const { user, rows } = copiesOf(db, { connectionId, profileUrl, userId });
79
+ if (!rows.length) return { saved: 0, xp: 0, already: false, user };
80
+ const ids = rows.map((r) => r.id);
81
+ const now = new Date().toISOString();
82
+ const already = rows.some((r) => r.outreach_status === 'sent' || r.outreach_status === 'accepted');
83
+ db.prepare(`UPDATE linkedin_connections SET outreach_status = 'sent', updated_at = ?
84
+ WHERE id IN (${inList(ids)}) AND (outreach_status IS NULL OR outreach_status NOT IN ('sent', 'accepted'))`).run(now, ...ids);
85
+ db.prepare(`UPDATE linkedin_connections SET unlock_status = 'pending', updated_at = ?
86
+ WHERE id IN (${inList(ids)}) AND (unlock_status IS NULL OR unlock_status = 'locked')`).run(now, ...ids);
87
+ // Who you asked through: one of your own connections, or nothing.
88
+ if (bridgeId != null) {
89
+ const bridge = db.prepare(
90
+ `SELECT id, name FROM linkedin_connections WHERE id = ? AND degree = 1${user ? ' AND user_id = ?' : ''}`,
91
+ ).get(...[String(bridgeId), ...(user ? [user] : [])]);
92
+ if (bridge) {
93
+ db.prepare(`UPDATE linkedin_connections SET unlocked_from_bridge_id = ?, unlocked_from_name = ?, updated_at = ?
94
+ WHERE id IN (${inList(ids)}) AND degree = 2 AND unlocked_from_bridge_id IS NULL`).run(bridge.id, bridge.name, now, ...ids);
95
+ }
96
+ }
97
+ const xp = already ? 0 : XP_SEND[bestTier(rows)] || 2;
98
+ return { saved: ids.length, xp, already, user };
99
+ }
100
+
101
+ /** markSentRows, and its XP awarded: { saved, xp, already }. */
102
+ export async function markSent(db, request = {}) {
103
+ const { saved, xp, already, user } = markSentRows(db, request);
104
+ if (saved) await awardXP(whose(user), xp);
105
+ return { saved, xp, already };
106
+ }
107
+
108
+ /**
109
+ * Where this person stands for a new request, over every copy of them:
110
+ * { connected, requested, accepted }. `connected`: a copy of them is one of
111
+ * your own connections; `requested`: a request is out (sent or pending);
112
+ * `accepted`: one was accepted (or their path is unlocked).
113
+ */
114
+ export function requestStanding(db, { profileUrl, userId }) {
115
+ if (!profileUrl) return { connected: false, requested: false, accepted: false };
116
+ const rows = userId
117
+ ? db.prepare('SELECT degree, outreach_status, unlock_status FROM linkedin_connections WHERE profile_url = ? AND user_id = ?').all(String(profileUrl), String(userId))
118
+ : db.prepare('SELECT degree, outreach_status, unlock_status FROM linkedin_connections WHERE profile_url = ?').all(String(profileUrl));
119
+ return {
120
+ connected: rows.some((r) => r.degree === 1),
121
+ requested: rows.some((r) => r.outreach_status === 'sent' || r.unlock_status === 'pending'),
122
+ accepted: rows.some((r) => r.outreach_status === 'accepted' || r.unlock_status === 'unlocked'),
123
+ };
124
+ }
@@ -29,6 +29,17 @@ export function paceSeconds(name, searches) {
29
29
  return n * (WORK_SECONDS + p.pagePause) + Math.floor(n / EVERY) * p.chunkCooldown;
30
30
  }
31
31
 
32
+ /**
33
+ * About how long a circle scan takes to show its first people on the map. The
34
+ * scanner saves after its first ten pages (scrape.py SAVE_EVERY_PAGES), so it's
35
+ * those ten at this speed; the longer rest counted after them stands in for
36
+ * opening Chrome and the person's profile first. About 5 minutes at Fast: the
37
+ * Scan page's honest "first circle" (the rest of a network takes days).
38
+ */
39
+ export function firstCircleSeconds(name) {
40
+ return paceSeconds(name, EVERY);
41
+ }
42
+
32
43
  /** About how many searches an hour a speed makes. */
33
44
  export function searchesPerHour(name) {
34
45
  const p = paceOf(name);
@@ -70,6 +70,26 @@ export function scanProgress(log, action) {
70
70
  return null;
71
71
  }
72
72
 
73
+ // "[3/10] Ada Park (A-tier, score 6.2)", with ", carrying on from page 11"
74
+ // after it when a read goes on: the name is everything before the last
75
+ // "(…-tier, score …)".
76
+ const BRIDGE_PERSON = /^\[\d+\/\d+\] (.+) \([^()]*-tier, score [^()]*\)/;
77
+
78
+ /**
79
+ * Whose circle a batch (Map 2nd degree, every paused list) is reading now,
80
+ * by name, from the line it printed as that person started; null for any
81
+ * other job, or before the first. The Scan page's "Watch it fill in" link
82
+ * (app/api/scraper/route.js turns the name into one of your connections).
83
+ */
84
+ export function mappingNow(log, action) {
85
+ if (!Array.isArray(log) || !action || !(action.startsWith('auto-bridge') || action === 'resume-all')) return null;
86
+ for (let i = log.length - 1; i >= 0; i--) {
87
+ const m = String(log[i]).match(BRIDGE_PERSON);
88
+ if (m) return m[1];
89
+ }
90
+ return null;
91
+ }
92
+
73
93
  function walk(done, total) {
74
94
  if (!total) return null;
75
95
  return { done: Math.min(done, total), total, kind: 'walk' };