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
@@ -19,6 +19,7 @@ Usage:
19
19
  python3 scripts/scrape.py --auto-bridge --tiers=S,A --max-bridges=10
20
20
  python3 scripts/scrape.py --rescrape "Name" # Delete + re-scrape a bridge
21
21
  python3 scripts/scrape.py --auto-bridge --deeper # ...and finish lists read only partly
22
+ python3 scripts/scrape.py --connect URL # Auto: one connection request, no note
22
23
 
23
24
  IMPORTANT: Only scrape ONE bridge at a time. Do NOT batch multiple bridges
24
25
  in one session — LinkedIn detects automation and flags your account.
@@ -227,6 +228,19 @@ MAX_SCROLL_ROUNDS = 400 # ~10 people load per round
227
228
  SCROLL_PAUSE_SECONDS = 0.9
228
229
  SCROLL_STALL_LIMIT = 10 # rounds with no new names before stopping
229
230
  LOGIN_POLL_SECONDS = 2
231
+ # The Scan page's "Signed in" (lib/scanner-setup.js SIGNED_IN_FILE, which a
232
+ # test keeps the same): true once the session is confirmed below, false while
233
+ # a sign-in is awaited. It went by Chrome's cookie file, which exists as soon
234
+ # as this window first opens, so closing it without signing in ticked the step.
235
+ SIGNED_IN_FILE = "signed-in.json"
236
+
237
+
238
+ def _note_signed_in(ok):
239
+ """Write down for the Scan page whether LinkedIn's session is confirmed. Only a note: never stops a run."""
240
+ try:
241
+ _write_json_atomic(_home() / SIGNED_IN_FILE, {"signedIn": bool(ok), "at": time.time()})
242
+ except Exception as exc:
243
+ print(f" (could not note the sign-in for the Scan page: {exc})")
230
244
 
231
245
 
232
246
  def _has_session_cookie(target):
@@ -345,8 +359,10 @@ def ensure_logged_in(page, timeout_s=LOGIN_WAIT_SECONDS, log_fn=None, stop_on_ch
345
359
  raise LinkedInPushedBack(0, reason)
346
360
 
347
361
  if _has_session_cookie(context) and not _looks_logged_out(page) and not wall:
362
+ _note_signed_in(True)
348
363
  return True
349
364
 
365
+ _note_signed_in(False)
350
366
  say = log_fn or (lambda m: None)
351
367
  if had_session and wall == "checkpoint":
352
368
  print()
@@ -356,7 +372,10 @@ def ensure_logged_in(page, timeout_s=LOGIN_WAIT_SECONDS, log_fn=None, stop_on_ch
356
372
  say("Waiting for you to finish LinkedIn's security check...")
357
373
  else:
358
374
  _print_sign_in_banner(say)
359
- return _wait_for_sign_in(page, context, timeout_s, say)
375
+ ok = _wait_for_sign_in(page, context, timeout_s, say)
376
+ if ok:
377
+ _note_signed_in(True)
378
+ return ok
360
379
 
361
380
 
362
381
  def _print_sign_in_banner(say):
@@ -1407,16 +1426,26 @@ def note_unclear(profile_url, clear=False):
1407
1426
  # profile in the app: three app profiles must not triple the budget. The app's
1408
1427
  # Scan page reads and edits the same files (lib/linkedin-limits.js).
1409
1428
  #
1410
- # linkedin-activity.json {"searches": [epoch s, ...], "profiles": [...]}
1429
+ # linkedin-activity.json {"searches": [epoch s, ...], "profiles": [...],
1430
+ # "invites": [...]} Auto's connection requests (--connect)
1411
1431
  # scan-limits.json {"daily": 50, "monthly": 250, "profiles": 50}
1412
1432
  # 0 = no cap on searches; profile views always have one
1413
1433
  # linkedin-cooldown.json {"until": epoch s, "reason": "...", "set_at": ...}
1434
+ # lifted on the Scan page: "until" is when, plus
1435
+ # "lifted_at" and "was_until"; read here as ended
1414
1436
  # ---------------------------------------------------------------------------
1415
1437
  DEFAULT_DAILY_SEARCHES = 50
1416
1438
  DEFAULT_MONTHLY_SEARCHES = 250
1417
1439
  DEFAULT_DAILY_PROFILES = 50
1418
1440
  PROFILE_GAP = 60 # seconds between any two profile opens, whatever opened them
1419
1441
  DAY_SECONDS = 24 * 3600
1442
+ WEEK_SECONDS = 7 * DAY_SECONDS
1443
+ # Auto's connection requests (--connect), in any 24 hours and any 7 days. The
1444
+ # app shows and enforces the same two (lib/auto-connect.js INVITE_CAPS; a test
1445
+ # checks they match). LinkedIn doesn't publish its invitation limit; people
1446
+ # commonly report about 100 a week, so the week stays well under it.
1447
+ INVITE_DAY_CAP = 15
1448
+ INVITE_WEEK_CAP = 80
1420
1449
  PACIFIC = "America/Los_Angeles"
1421
1450
 
1422
1451
 
@@ -1497,9 +1526,10 @@ def _read_activity():
1497
1526
  if not isinstance(data, dict):
1498
1527
  raise ValueError("not an object")
1499
1528
  return {"searches": [float(x) for x in data.get("searches", [])],
1500
- "profiles": [float(x) for x in data.get("profiles", [])]}
1529
+ "profiles": [float(x) for x in data.get("profiles", [])],
1530
+ "invites": [float(x) for x in data.get("invites", [])]}
1501
1531
  except FileNotFoundError:
1502
- return {"searches": [], "profiles": []}
1532
+ return {"searches": [], "profiles": [], "invites": []}
1503
1533
  except Exception:
1504
1534
  # Kept aside, and replaced by a record that says today's budget is used —
1505
1535
  # written, so it holds for the whole day rather than one check. (Failing
@@ -1511,7 +1541,8 @@ def _read_activity():
1511
1541
  pass
1512
1542
  print(" (the record of LinkedIn searches couldn't be read; counting today as used)")
1513
1543
  lim = search_limits()
1514
- fresh = {"searches": [now] * max(1, lim["daily"] or 1), "profiles": [now] * lim["profiles"]}
1544
+ fresh = {"searches": [now] * max(1, lim["daily"] or 1), "profiles": [now] * lim["profiles"],
1545
+ "invites": [now] * INVITE_DAY_CAP}
1515
1546
  try:
1516
1547
  _write_json_atomic(path, fresh)
1517
1548
  except Exception:
@@ -1520,7 +1551,7 @@ def _read_activity():
1520
1551
 
1521
1552
 
1522
1553
  def charge_linkedin(kind="searches", n=1):
1523
- """Write down n searches (or profile views) made just now."""
1554
+ """Write down n searches (or profile views, or connection requests) made just now."""
1524
1555
  with _Locked("linkedin-activity"):
1525
1556
  _charge(_read_activity(), kind, n, time.time())
1526
1557
 
@@ -1528,9 +1559,9 @@ def charge_linkedin(kind="searches", n=1):
1528
1559
  def _charge(data, kind, n, now):
1529
1560
  """Add n of `kind` at `now` to the record and write it. The caller holds the lock."""
1530
1561
  keep_from = month_start_pacific(now) - 32 * DAY_SECONDS
1531
- data[kind] = [t for t in data.get(kind, []) if t >= keep_from] + [now] * n
1532
- other = "profiles" if kind == "searches" else "searches"
1533
- data[other] = [t for t in data.get(other, []) if t >= keep_from]
1562
+ for each in ("searches", "profiles", "invites"):
1563
+ data[each] = [t for t in data.get(each, []) if t >= keep_from]
1564
+ data[kind] = data.get(kind, []) + [now] * n
1534
1565
  try:
1535
1566
  _write_json_atomic(_home() / "linkedin-activity.json", data)
1536
1567
  except Exception as exc:
@@ -3376,7 +3407,11 @@ def scrape_bridge(bridge_name, headless=False, max_pages=LINKEDIN_MAX_PAGES, dee
3376
3407
  raise SearchLimitReached(len(read))
3377
3408
  if reach.get("pushed_back"):
3378
3409
  why = reach.get("pushback_reason") or "a page that would not open"
3379
- set_cooldown(seconds=DAY_SECONDS, reason=f"LinkedIn pushed back: {why}")
3410
+ # Auto scan rests two days after any check from LinkedIn, as the Scan
3411
+ # page promises and AUTO_PUSHBACK_REST says; a pushback partway through
3412
+ # a list used to rest it one day, like a scan you start yourself.
3413
+ set_cooldown(seconds=AUTO_PUSHBACK_REST if EXPERIMENT["on"] else DAY_SECONDS,
3414
+ reason=f"LinkedIn pushed back: {why}")
3380
3415
  raise LinkedInPushedBack(len(read), why)
3381
3416
  if reach.get("budget"):
3382
3417
  raise BudgetReached(len(read), reach["budget"])
@@ -4109,6 +4144,529 @@ def rescrape_bridge(bridge_name, headless=False, max_pages=LINKEDIN_MAX_PAGES):
4109
4144
  scrape_bridge(bridge_name, headless=headless, max_pages=max_pages, fresh=True)
4110
4145
 
4111
4146
 
4147
+ # ---------------------------------------------------------------------------
4148
+ # Auto: one connection request, for the person whose Auto was pressed (--connect)
4149
+ # ---------------------------------------------------------------------------
4150
+ # Blake, 2026-10-03: "auto add and basically adds the person for them in the
4151
+ # card or wherever its available ... sometimes when adding it'll prompt the user
4152
+ # to have a email from their work or to send a personal note if they have
4153
+ # premium so if thats the case then have it close out of that in the scanner
4154
+ # for adding but it should be seamless."
4155
+ #
4156
+ # This is the one thing the scanner ever does on LinkedIn besides reading, and
4157
+ # only because a person pressed Auto on one card: one person per run, never a
4158
+ # batch, never on a timer. It is openly slow like everything else here: fixed
4159
+ # waits, a profile view taken like any other (cap and gap), no "human" timing
4160
+ # and no mouse movement made up to look like someone (Blake's standing scanner
4161
+ # boundary). The app looks the person up by id and refuses first (cooldown,
4162
+ # caps, already connected or requested; app/api/scraper/route.js); this checks
4163
+ # the cooldown and the caps again before anything opens.
4164
+ #
4165
+ # How it finds things, without a CSS class (TRAPS §5): by role and accessible
4166
+ # name, the way a screen reader would. Their Connect is a button (or link, or
4167
+ # menu item) labelled "Invite <their name> to connect"; the name must be theirs,
4168
+ # word for word, because the same page lists other people with Connect buttons
4169
+ # of their own ("People also viewed"). When it isn't on the front of their
4170
+ # profile, it is under "More". A bare "Connect" with no name is only taken from
4171
+ # that menu, and only when the menu is what brought it on screen: on the page
4172
+ # itself, a nameless Connect could be anyone's.
4173
+ #
4174
+ # What LinkedIn asks next is answered like this:
4175
+ # a note? "Send without a note", or the only Send there is
4176
+ # a personal note (Premium) the same: never a note, never Premium
4177
+ # their email address closed, nothing sent ("email-needed")
4178
+ # its invitation limit closed, nothing sent ("linkedin-limit")
4179
+ # anything else closed, nothing sent ("not-sent")
4180
+ # It is "sent" only when their profile then shows it Pending (or LinkedIn says
4181
+ # the invitation to them was sent). Anything else after pressing Send is
4182
+ # "unclear", and the app doesn't mark it as sent: never a confident wrong answer
4183
+ # (TRAPS §7). A security check or a sign-in wall is LinkedIn pushing back, as in
4184
+ # every other run: the page is kept, everything pauses for a day, and it stops.
4185
+ #
4186
+ # None of this has been run against LinkedIn's real page: the labels above are
4187
+ # what LinkedIn is known to use, and tests/auto-connect.test.mjs runs it against
4188
+ # a stand-in page. Watch the first real one.
4189
+
4190
+ CONNECT_LOAD_ATTEMPTS = 6 # looks for their profile to render, CONNECT_LOAD_STEP apart
4191
+ CONNECT_LOAD_STEP = 5 # seconds
4192
+ CONNECT_STEP = 1 # seconds between looks for LinkedIn's answer
4193
+ DIALOG_WAIT = 10 # seconds to wait for the invitation window after Connect
4194
+ CONFIRM_WAIT = 12 # seconds to wait for Pending after Send
4195
+
4196
+ # Every result a run can end with, printed as "Connect result: <name>" for the
4197
+ # app (lib/auto-connect.js OUTCOMES has the same names and their words; a test
4198
+ # checks the two lists match).
4199
+ CONNECT_RESULTS = (
4200
+ "sent", "already-pending", "email-needed", "no-connect", "not-sent", "unclear", "not-loaded",
4201
+ "unavailable", "linkedin-limit", "pushback", "stopped", "not-signed-in", "cooldown",
4202
+ "invites-day", "invites-week", "profiles", "not-found",
4203
+ )
4204
+
4205
+ ACTION_ROLES = ("button", "link", "menuitem")
4206
+ INVITE_LABEL = re.compile(r"^\s*Invite\s+(.+?)\s+to\s+connect\s*$", re.I)
4207
+ PENDING_LABEL = re.compile(r"^\s*Pending\b", re.I)
4208
+ BARE_CONNECT = re.compile(r"^\s*Connect\s*$", re.I)
4209
+ BARE_PENDING = re.compile(r"^\s*Pending\s*$", re.I)
4210
+ MORE_LABEL = re.compile(r"^\s*More( actions)?\s*$", re.I)
4211
+ SEND_PLAIN = re.compile(r"^\s*Send without a note\s*$", re.I)
4212
+ SEND_ANY = re.compile(r"^\s*Send( now| invitation)?\s*$", re.I)
4213
+ CLOSE_LABEL = re.compile(r"^\s*(Dismiss|Close|Cancel|Got it|Not now)\s*$", re.I)
4214
+ EMAIL_BOX = re.compile(r"e-?mail", re.I)
4215
+ EMAIL_ASK = re.compile(r"enter (their|his|her|the member.?s) e-?mail|e-?mail( address)? to connect|knows you.{0,60}e-?mail", re.I)
4216
+ INVITE_LIMIT = re.compile(r"invitation limit|reached the (weekly )?limit|too many (pending )?invitations", re.I)
4217
+ PREMIUM_NOTE = re.compile(r"premium|personali[sz]ed (invitation|note)", re.I)
4218
+ SENT_NOTICE = re.compile(r"invitation to (.+?) (?:was|has been) sent", re.I)
4219
+
4220
+
4221
+ def invites_left(now=None):
4222
+ """(how many more requests Auto may send, "day" | "week": whichever runs out first)."""
4223
+ now = now if now is not None else time.time()
4224
+ invites = _read_activity()["invites"]
4225
+ day = INVITE_DAY_CAP - sum(1 for t in invites if t > now - DAY_SECONDS)
4226
+ week = INVITE_WEEK_CAP - sum(1 for t in invites if t > now - WEEK_SECONDS)
4227
+ return (max(0, day), "day") if day <= week else (max(0, week), "week")
4228
+
4229
+
4230
+ def take_invite(now=None):
4231
+ """Write down one connection request about to be sent, if the caps allow one.
4232
+
4233
+ None once it is written down; "day" or "week" when that cap is reached and
4234
+ nothing was written. The check and the write are one step under the lock.
4235
+ """
4236
+ with _Locked("linkedin-activity"):
4237
+ now = now if now is not None else time.time()
4238
+ data = _read_activity()
4239
+ invites = data["invites"]
4240
+ if sum(1 for t in invites if t > now - DAY_SECONDS) >= INVITE_DAY_CAP:
4241
+ return "day"
4242
+ if sum(1 for t in invites if t > now - WEEK_SECONDS) >= INVITE_WEEK_CAP:
4243
+ return "week"
4244
+ _charge(data, "invites", 1, now)
4245
+ return None
4246
+
4247
+
4248
+ def invite_message(kind):
4249
+ """Why Auto sent nothing: a cap on its requests is reached, and when one frees up."""
4250
+ now = time.time()
4251
+ window = WEEK_SECONDS if kind == "week" else DAY_SECONDS
4252
+ cap = INVITE_WEEK_CAP if kind == "week" else INVITE_DAY_CAP
4253
+ sent = sorted(t for t in _read_activity()["invites"] if t > now - window)
4254
+ extra = len(sent) - cap
4255
+ free = f" The next one frees up at {_when(sent[extra] + window)}." if extra >= 0 else ""
4256
+ span = "7 days" if kind == "week" else "24 hours"
4257
+ return f"Auto has sent {cap} connection requests in the last {span}, its limit.{free} Nothing was opened or sent."
4258
+
4259
+
4260
+ def _names_words(text):
4261
+ """The words of a name, lower case, letters only (any alphabet)."""
4262
+ return re.findall(r"[^\W\d_]+", str(text or "").lower())
4263
+
4264
+
4265
+ def _same_person(shown, name):
4266
+ """Does what LinkedIn shows (a label, a heading) name this person: their first and last name, as whole words?"""
4267
+ want = _names_words(str(name or "").split(",")[0])
4268
+ have = set(_names_words(shown))
4269
+ return bool(want) and want[0] in have and want[-1] in have
4270
+
4271
+
4272
+ def _shown(loc, limit=40):
4273
+ """The items of a locator that are on screen."""
4274
+ out = []
4275
+ try:
4276
+ n = loc.count()
4277
+ except Exception:
4278
+ return out
4279
+ for i in range(min(n, limit)):
4280
+ item = loc.nth(i)
4281
+ try:
4282
+ if item.is_visible():
4283
+ out.append(item)
4284
+ except Exception:
4285
+ pass
4286
+ return out
4287
+
4288
+
4289
+ def _label(item):
4290
+ """An element's accessible name as LinkedIn wrote it: its aria-label, else its text."""
4291
+ try:
4292
+ label = item.get_attribute("aria-label")
4293
+ if label:
4294
+ return label
4295
+ except Exception:
4296
+ pass
4297
+ try:
4298
+ return item.inner_text() or ""
4299
+ except Exception:
4300
+ return ""
4301
+
4302
+
4303
+ def _enabled(item):
4304
+ try:
4305
+ return item.is_enabled()
4306
+ except Exception:
4307
+ return False
4308
+
4309
+
4310
+ def _in_main(page):
4311
+ """The profile's <main>, where its own buttons are, or the page if there is none."""
4312
+ try:
4313
+ main = page.locator("main")
4314
+ if main.count() > 0:
4315
+ return main.first
4316
+ except Exception:
4317
+ pass
4318
+ return page
4319
+
4320
+
4321
+ def _actions(scope, name_pattern):
4322
+ """Every button, link or menu item on screen whose accessible name matches."""
4323
+ found = []
4324
+ for role in ACTION_ROLES:
4325
+ try:
4326
+ found.extend(_shown(scope.get_by_role(role, name=name_pattern)))
4327
+ except Exception:
4328
+ pass
4329
+ return found
4330
+
4331
+
4332
+ def _invite_for(page, name):
4333
+ """Their own Connect: "Invite <their name> to connect", never someone else's."""
4334
+ for item in _actions(page, INVITE_LABEL):
4335
+ m = INVITE_LABEL.match(_label(item))
4336
+ if m and _same_person(m.group(1), name):
4337
+ return item
4338
+ return None
4339
+
4340
+
4341
+ def _pending_for(page, name):
4342
+ """Their profile says a request to them is pending, naming them."""
4343
+ return any(_same_person(_label(item), name) for item in _actions(page, PENDING_LABEL))
4344
+
4345
+
4346
+ def _bare_pending(page):
4347
+ """How many nameless "Pending" buttons their profile shows."""
4348
+ return len(_actions(_in_main(page), BARE_PENDING))
4349
+
4350
+
4351
+ def _sent_shown(page, name, bare_before):
4352
+ """LinkedIn shows the request to them as sent: Pending naming them, a new
4353
+ "Pending" on their profile, or its notice that the invitation to them was sent."""
4354
+ if _pending_for(page, name):
4355
+ return True
4356
+ if _bare_pending(page) > bare_before:
4357
+ return True
4358
+ try:
4359
+ for item in _shown(page.get_by_text(SENT_NOTICE)):
4360
+ m = SENT_NOTICE.search(_label(item))
4361
+ if m and _same_person(m.group(1), name):
4362
+ return True
4363
+ except Exception:
4364
+ pass
4365
+ return False
4366
+
4367
+
4368
+ def _press_escape(page):
4369
+ try:
4370
+ page.keyboard.press("Escape")
4371
+ except Exception:
4372
+ pass
4373
+
4374
+
4375
+ def _connect_under_more(page, name):
4376
+ """Connect from their profile's More menu, or None (the menu is closed again)."""
4377
+ more = _actions(_in_main(page), MORE_LABEL)
4378
+ if not more:
4379
+ return None
4380
+ bare_before = len(_actions(page, BARE_CONNECT))
4381
+ print(" Connect isn't on the front of their profile; looking under More...")
4382
+ try:
4383
+ more[0].click(timeout=10000)
4384
+ except Exception:
4385
+ return None
4386
+ time.sleep(CONNECT_STEP)
4387
+ found = _invite_for(page, name)
4388
+ if found:
4389
+ return found
4390
+ # A nameless "Connect" only when opening the menu is what brought it on screen.
4391
+ bare = _actions(page, BARE_CONNECT)
4392
+ if bare_before == 0 and len(bare) == 1:
4393
+ return bare[0]
4394
+ _press_escape(page)
4395
+ return None
4396
+
4397
+
4398
+ def _dialog(page):
4399
+ """LinkedIn's window on top of the page (the newest), or None."""
4400
+ shown = []
4401
+ for role in ("dialog", "alertdialog"):
4402
+ try:
4403
+ shown.extend(_shown(page.get_by_role(role)))
4404
+ except Exception:
4405
+ pass
4406
+ return shown[-1] if shown else None
4407
+
4408
+
4409
+ def _close_dialog(page, dialog):
4410
+ """Close LinkedIn's window without answering it: its Dismiss (or Close, Cancel), else Escape."""
4411
+ try:
4412
+ close = _shown(dialog.get_by_role("button", name=CLOSE_LABEL))
4413
+ if close:
4414
+ close[0].click(timeout=5000)
4415
+ else:
4416
+ _press_escape(page)
4417
+ except Exception:
4418
+ _press_escape(page)
4419
+ time.sleep(CONNECT_STEP)
4420
+
4421
+
4422
+ def _asks_for_email(dialog, text):
4423
+ """The invitation window wants their email address before it sends."""
4424
+ for loc in (lambda: dialog.get_by_role("textbox", name=EMAIL_BOX), lambda: dialog.locator("input[type=email]")):
4425
+ try:
4426
+ if _shown(loc()):
4427
+ return True
4428
+ except Exception:
4429
+ pass
4430
+ return bool(EMAIL_ASK.search(text or ""))
4431
+
4432
+
4433
+ def _send_button(dialog):
4434
+ """"Send without a note", or the one Send there is. Never "Add a note", never Premium."""
4435
+ plain = [b for b in _shown(dialog.get_by_role("button", name=SEND_PLAIN)) if _enabled(b)]
4436
+ if plain:
4437
+ return plain[0]
4438
+ sends = [b for b in _shown(dialog.get_by_role("button", name=SEND_ANY)) if _enabled(b)]
4439
+ return sends[0] if len(sends) == 1 else None
4440
+
4441
+
4442
+ def _dialog_text(dialog):
4443
+ try:
4444
+ return dialog.inner_text() or ""
4445
+ except Exception:
4446
+ return ""
4447
+
4448
+
4449
+ def _connect_pushback(page, why):
4450
+ """LinkedIn pushed back while Auto was on their profile: keep the page, pause for a day."""
4451
+ print(f" LinkedIn is pushing back ({why}). Stopping here.")
4452
+ _keep_pushback_evidence(page, why)
4453
+ set_cooldown(seconds=DAY_SECONDS, reason=f"LinkedIn pushed back: {why}")
4454
+
4455
+
4456
+ def _confirm_sent(page, name, bare_before):
4457
+ """After Send: "sent" once their profile shows it, else "unclear" (or "pushback", "linkedin-limit")."""
4458
+ waited = 0
4459
+ while waited < CONFIRM_WAIT:
4460
+ time.sleep(CONNECT_STEP)
4461
+ waited += CONNECT_STEP
4462
+ why = _pushback(page)
4463
+ if why:
4464
+ _connect_pushback(page, why)
4465
+ return "pushback"
4466
+ dialog = _dialog(page)
4467
+ if dialog is not None and INVITE_LIMIT.search(_dialog_text(dialog)):
4468
+ _close_dialog(page, dialog)
4469
+ print(" LinkedIn says this account has reached its invitation limit.")
4470
+ return "linkedin-limit"
4471
+ if _sent_shown(page, name, bare_before):
4472
+ return "sent"
4473
+ leftover = _dialog(page)
4474
+ if leftover is not None:
4475
+ _close_dialog(page, leftover)
4476
+ return "unclear"
4477
+
4478
+
4479
+ def _answer_invitation(page, name, bare_before):
4480
+ """What LinkedIn asks once Connect is pressed, answered without a note."""
4481
+ dialog = None
4482
+ waited = 0
4483
+ while waited < DIALOG_WAIT:
4484
+ time.sleep(CONNECT_STEP)
4485
+ waited += CONNECT_STEP
4486
+ dialog = _dialog(page)
4487
+ if dialog is not None:
4488
+ break
4489
+ if _sent_shown(page, name, bare_before):
4490
+ # Some accounts send straight from Connect, with nothing to answer.
4491
+ charge_linkedin("invites")
4492
+ print(" LinkedIn sent it straight from Connect; their profile shows it pending.")
4493
+ return "sent"
4494
+ if dialog is None:
4495
+ # Nothing came up and nothing shows it pending. It may have gone, so it
4496
+ # counts toward Auto's caps; it isn't called sent.
4497
+ charge_linkedin("invites")
4498
+ print(" Nothing came up after Connect, and their profile doesn't show it pending.")
4499
+ return "unclear"
4500
+
4501
+ text = _dialog_text(dialog)
4502
+ if _asks_for_email(dialog, text):
4503
+ _close_dialog(page, dialog)
4504
+ print(" LinkedIn wants their email address before it sends this one. Closed that; nothing was sent.")
4505
+ return "email-needed"
4506
+ if INVITE_LIMIT.search(text):
4507
+ _close_dialog(page, dialog)
4508
+ print(" LinkedIn says this account has reached its invitation limit. Closed that; nothing was sent.")
4509
+ return "linkedin-limit"
4510
+ send = _send_button(dialog)
4511
+ if send is None:
4512
+ _close_dialog(page, dialog)
4513
+ print(" LinkedIn's invitation window had no way to send without a note. Closed it; nothing was sent.")
4514
+ return "not-sent"
4515
+ if PREMIUM_NOTE.search(text):
4516
+ print(" LinkedIn offered a personal note (Premium). Sending without one.")
4517
+ if stop_requested() or _window_closed(page):
4518
+ _close_dialog(page, dialog)
4519
+ return "stopped"
4520
+ taken = take_invite()
4521
+ if taken:
4522
+ _close_dialog(page, dialog)
4523
+ print(" " + invite_message(taken))
4524
+ return f"invites-{taken}"
4525
+ print(" Sending without a note...")
4526
+ try:
4527
+ send.click(timeout=10000)
4528
+ except Exception as exc:
4529
+ print(f" Send couldn't be pressed ({str(exc)[:60]}).")
4530
+ _close_dialog(page, dialog)
4531
+ return "unclear"
4532
+ result = _confirm_sent(page, name, bare_before)
4533
+ if result == "sent":
4534
+ print(f" Sent. {name}'s profile shows the request pending.")
4535
+ elif result == "unclear":
4536
+ print(" Send was pressed, but their profile doesn't show the request pending. Not calling it sent.")
4537
+ return result
4538
+
4539
+
4540
+ def _connect_on_page(page, profile_url, name):
4541
+ """Open their profile (one profile view) and send the request. Returns a CONNECT_RESULTS name."""
4542
+ why = _wait_for_profile_view(page)
4543
+ if why == "budget":
4544
+ print(budget_message("profiles"))
4545
+ return "profiles"
4546
+ if why:
4547
+ return "stopped"
4548
+
4549
+ print(f" Opening {name}'s profile...")
4550
+ try:
4551
+ page.goto(profile_url, wait_until="commit")
4552
+ except Exception as exc:
4553
+ print(f" Navigation slow: {str(exc)[:50]}... carrying on")
4554
+
4555
+ shown = False
4556
+ for _ in range(CONNECT_LOAD_ATTEMPTS):
4557
+ time.sleep(CONNECT_LOAD_STEP)
4558
+ if stop_requested() or _window_closed(page):
4559
+ return "stopped"
4560
+ why = _pushback(page)
4561
+ if why:
4562
+ _connect_pushback(page, why)
4563
+ return "pushback"
4564
+ if _profile_unavailable(page):
4565
+ print(" LinkedIn says their profile isn't available. Nothing was sent.")
4566
+ return "unavailable"
4567
+ try:
4568
+ shown = bool(page.evaluate(PROFILE_SHOWN_JS, name))
4569
+ except Exception:
4570
+ shown = False
4571
+ if shown:
4572
+ break
4573
+ if not shown:
4574
+ print(" Their profile didn't load properly, so nothing was pressed.")
4575
+ return "not-loaded"
4576
+
4577
+ if _pending_for(page, name):
4578
+ print(f" A request to {name} is already pending on LinkedIn. Nothing new was sent.")
4579
+ return "already-pending"
4580
+ bare_before = _bare_pending(page)
4581
+ target = _invite_for(page, name) or _connect_under_more(page, name)
4582
+ if target is None:
4583
+ print(" LinkedIn shows no Connect for them here (only Follow or Message, say). Nothing was sent.")
4584
+ return "no-connect"
4585
+ if stop_requested() or _window_closed(page):
4586
+ return "stopped"
4587
+ left, kind = invites_left()
4588
+ if left <= 0:
4589
+ print(" " + invite_message(kind))
4590
+ return f"invites-{kind}"
4591
+ print(f" Pressing Connect for {name}...")
4592
+ try:
4593
+ target.click(timeout=10000)
4594
+ except Exception as exc:
4595
+ print(f" Connect couldn't be pressed ({str(exc)[:60]}). Nothing was sent.")
4596
+ return "not-sent"
4597
+ return _answer_invitation(page, name, bare_before)
4598
+
4599
+
4600
+ def connect_person(profile_url, name=None, headless=False):
4601
+ """Send one connection request, without a note, to the person at profile_url.
4602
+
4603
+ Returns one of CONNECT_RESULTS; main() prints it as "Connect result: ...".
4604
+ Nothing opens during a cooldown, with Auto's caps reached, or with no
4605
+ profile view left: each is checked before a browser starts.
4606
+ """
4607
+ from playwright.sync_api import sync_playwright
4608
+
4609
+ cd = read_cooldown()
4610
+ if cd:
4611
+ print(cooldown_message(cd))
4612
+ return "cooldown"
4613
+ left, kind = invites_left()
4614
+ if left <= 0:
4615
+ print(invite_message(kind))
4616
+ return f"invites-{kind}"
4617
+ if profiles_left() <= 0:
4618
+ print(budget_message("profiles"))
4619
+ return "profiles"
4620
+ if not name:
4621
+ params = {"profile_url": f"eq.{profile_url}", "limit": "1"}
4622
+ if _active_user_id:
4623
+ params["user_id"] = f"eq.{_active_user_id}"
4624
+ rows = read_connections(params=params)
4625
+ if not rows:
4626
+ print(f" {profile_url} isn't in your network on this computer. Nothing was sent.")
4627
+ return "not-found"
4628
+ name = rows[0].get("name") or ""
4629
+
4630
+ print(f"\n=== Sending {name} a connection request, without a note ===\n")
4631
+ result = None
4632
+ try:
4633
+ with sync_playwright() as p:
4634
+ browser = p.chromium.launch_persistent_context(
4635
+ user_data_dir=get_scraper_profile_path(),
4636
+ headless=headless,
4637
+ channel="chrome",
4638
+ args=["--disable-blink-features=AutomationControlled"],
4639
+ timeout=120000,
4640
+ )
4641
+ try:
4642
+ page = browser.pages[0] if browser.pages else browser.new_page()
4643
+ page.set_default_timeout(120000)
4644
+ page.set_default_navigation_timeout(120000)
4645
+ # A security check or a sign-out here is LinkedIn pushing back,
4646
+ # as for a circle scan: it raises, after pausing everything.
4647
+ if not ensure_logged_in(page, stop_on_checkpoint=True):
4648
+ result = "stopped" if stop_requested() else "not-signed-in"
4649
+ else:
4650
+ result = _connect_on_page(page, profile_url, name)
4651
+ finally:
4652
+ try:
4653
+ browser.close()
4654
+ except Exception:
4655
+ pass
4656
+ except LinkedInPushedBack as exc:
4657
+ print(f" LinkedIn pushed back ({exc.reason}). Nothing was sent.")
4658
+ result = "pushback"
4659
+ except Exception:
4660
+ # A stop takes the browser down with it. Anything else is a failure
4661
+ # with its reason, never a result that could read as sent.
4662
+ if result is None:
4663
+ if stop_requested():
4664
+ result = "stopped"
4665
+ else:
4666
+ raise
4667
+ return result
4668
+
4669
+
4112
4670
  def run_server(port=5555):
4113
4671
  """
4114
4672
  Run a local HTTP server that the website's Setup page can talk to.
@@ -4373,6 +4931,12 @@ Examples:
4373
4931
  "The app's Scan buttons use it, since two connections can share a name")
4374
4932
  parser.add_argument("--only-unfinished", action="store_true",
4375
4933
  help="With --auto-bridge: only people whose read was cut short (Resume all)")
4934
+ parser.add_argument("--connect", type=str,
4935
+ help="Auto: send one connection request, without a note, to the person at this LinkedIn "
4936
+ f"profile URL. Never with a note; at most {INVITE_DAY_CAP} in any 24 hours and "
4937
+ f"{INVITE_WEEK_CAP} in any 7 days")
4938
+ parser.add_argument("--connect-name", type=str, default="",
4939
+ help="With --connect: their name as the app has it (else it is looked up in the app)")
4376
4940
  parser.add_argument("--save-photos", action="store_true",
4377
4941
  help="Save the profile photos still kept as links to LinkedIn, then exit "
4378
4942
  "(every scan also does this at its end)")
@@ -4384,7 +4948,10 @@ Examples:
4384
4948
  args.max_pages = max(1, min(LINKEDIN_MAX_PAGES, args.max_pages))
4385
4949
  # The Scan page's speed. Signing in searches nothing, so it isn't said there.
4386
4950
  _pace = apply_pace()
4387
- if not args.login:
4951
+ if args.connect:
4952
+ # Auto reads no pages: only the gap before opening their profile applies.
4953
+ print(f"Speed: {_pace.capitalize()}. Profiles at least {PROFILE_GAP}s apart.")
4954
+ elif not args.login:
4388
4955
  print(f"Speed: {_pace.capitalize()}. {PAGE_PAUSE}s before each page of results, {CHUNK_COOLDOWN}s more after "
4389
4956
  f"every {SAVE_EVERY_PAGES}, and profiles at least {PROFILE_GAP}s apart.")
4390
4957
 
@@ -4430,6 +4997,23 @@ Examples:
4430
4997
  # A budget or a cooldown ending a run is the design working, not a failure:
4431
4998
  # say why and exit 0, so the Scan page doesn't show it as a red error.
4432
4999
  try:
5000
+ if args.connect:
5001
+ # Auto (lib/auto-connect.js): one request, then out. Its last line is
5002
+ # the result the app reads; no photos are saved after it, since it
5003
+ # read no one. A pushback or no sign-in ends it as a failure, with why.
5004
+ if not re.match(r"^https?://([a-z]{2,3}\.|www\.)?linkedin\.com/in/[^/?#\s]+/?$", args.connect, re.I):
5005
+ print(" --connect takes a LinkedIn profile URL (https://www.linkedin.com/in/...).", file=sys.stderr)
5006
+ raise SystemExit(2)
5007
+ result = connect_person(args.connect, name=args.connect_name.strip() or None, headless=args.headless)
5008
+ print(f"Connect result: {result}", flush=True)
5009
+ if result == "pushback":
5010
+ print(f"\n LinkedIn pushed back, so nothing more is sent. {_pushback_advice('')}\n", file=sys.stderr)
5011
+ raise SystemExit(1)
5012
+ if result == "not-signed-in":
5013
+ print("\n LinkedIn isn't signed in, so nothing was sent. Sign in with --login (or the Scan page), "
5014
+ "then try again.\n", file=sys.stderr)
5015
+ raise SystemExit(1)
5016
+ raise SystemExit(0)
4433
5017
  if args.company:
4434
5018
  # The server mode scraped and pushed as one step; the CLI has to do the
4435
5019
  # same or the scan appears to work and saves nothing.