@indexnetwork/protocol 0.1.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 (365) hide show
  1. package/dist/agents/chat.agent.d.ts +218 -0
  2. package/dist/agents/chat.agent.d.ts.map +1 -0
  3. package/dist/agents/chat.agent.js +884 -0
  4. package/dist/agents/chat.agent.js.map +1 -0
  5. package/dist/agents/chat.prompt.d.ts +18 -0
  6. package/dist/agents/chat.prompt.d.ts.map +1 -0
  7. package/dist/agents/chat.prompt.js +372 -0
  8. package/dist/agents/chat.prompt.js.map +1 -0
  9. package/dist/agents/chat.prompt.modules.d.ts +61 -0
  10. package/dist/agents/chat.prompt.modules.d.ts.map +1 -0
  11. package/dist/agents/chat.prompt.modules.js +366 -0
  12. package/dist/agents/chat.prompt.modules.js.map +1 -0
  13. package/dist/agents/chat.title.generator.d.ts +20 -0
  14. package/dist/agents/chat.title.generator.d.ts.map +1 -0
  15. package/dist/agents/chat.title.generator.js +66 -0
  16. package/dist/agents/chat.title.generator.js.map +1 -0
  17. package/dist/agents/home.categorizer.d.ts +28 -0
  18. package/dist/agents/home.categorizer.d.ts.map +1 -0
  19. package/dist/agents/home.categorizer.js +170 -0
  20. package/dist/agents/home.categorizer.js.map +1 -0
  21. package/dist/agents/hyde.generator.d.ts +27 -0
  22. package/dist/agents/hyde.generator.d.ts.map +1 -0
  23. package/dist/agents/hyde.generator.js +75 -0
  24. package/dist/agents/hyde.generator.js.map +1 -0
  25. package/dist/agents/hyde.strategies.d.ts +17 -0
  26. package/dist/agents/hyde.strategies.d.ts.map +1 -0
  27. package/dist/agents/hyde.strategies.js +29 -0
  28. package/dist/agents/hyde.strategies.js.map +1 -0
  29. package/dist/agents/intent.clarifier.d.ts +29 -0
  30. package/dist/agents/intent.clarifier.d.ts.map +1 -0
  31. package/dist/agents/intent.clarifier.js +186 -0
  32. package/dist/agents/intent.clarifier.js.map +1 -0
  33. package/dist/agents/intent.indexer.d.ts +77 -0
  34. package/dist/agents/intent.indexer.d.ts.map +1 -0
  35. package/dist/agents/intent.indexer.js +164 -0
  36. package/dist/agents/intent.indexer.js.map +1 -0
  37. package/dist/agents/intent.inferrer.d.ts +95 -0
  38. package/dist/agents/intent.inferrer.d.ts.map +1 -0
  39. package/dist/agents/intent.inferrer.js +238 -0
  40. package/dist/agents/intent.inferrer.js.map +1 -0
  41. package/dist/agents/intent.reconciler.d.ts +106 -0
  42. package/dist/agents/intent.reconciler.d.ts.map +1 -0
  43. package/dist/agents/intent.reconciler.js +184 -0
  44. package/dist/agents/intent.reconciler.js.map +1 -0
  45. package/dist/agents/intent.verifier.d.ts +97 -0
  46. package/dist/agents/intent.verifier.d.ts.map +1 -0
  47. package/dist/agents/intent.verifier.js +234 -0
  48. package/dist/agents/intent.verifier.js.map +1 -0
  49. package/dist/agents/invite.generator.d.ts +47 -0
  50. package/dist/agents/invite.generator.d.ts.map +1 -0
  51. package/dist/agents/invite.generator.js +56 -0
  52. package/dist/agents/invite.generator.js.map +1 -0
  53. package/dist/agents/lens.inferrer.d.ts +37 -0
  54. package/dist/agents/lens.inferrer.d.ts.map +1 -0
  55. package/dist/agents/lens.inferrer.js +98 -0
  56. package/dist/agents/lens.inferrer.js.map +1 -0
  57. package/dist/agents/model.config.d.ts +120 -0
  58. package/dist/agents/model.config.d.ts.map +1 -0
  59. package/dist/agents/model.config.js +76 -0
  60. package/dist/agents/model.config.js.map +1 -0
  61. package/dist/agents/negotiation.insights.generator.d.ts +32 -0
  62. package/dist/agents/negotiation.insights.generator.d.ts.map +1 -0
  63. package/dist/agents/negotiation.insights.generator.js +105 -0
  64. package/dist/agents/negotiation.insights.generator.js.map +1 -0
  65. package/dist/agents/negotiation.proposer.d.ts +26 -0
  66. package/dist/agents/negotiation.proposer.d.ts.map +1 -0
  67. package/dist/agents/negotiation.proposer.js +67 -0
  68. package/dist/agents/negotiation.proposer.js.map +1 -0
  69. package/dist/agents/negotiation.responder.d.ts +26 -0
  70. package/dist/agents/negotiation.responder.d.ts.map +1 -0
  71. package/dist/agents/negotiation.responder.js +71 -0
  72. package/dist/agents/negotiation.responder.js.map +1 -0
  73. package/dist/agents/opportunity.evaluator.d.ts +253 -0
  74. package/dist/agents/opportunity.evaluator.d.ts.map +1 -0
  75. package/dist/agents/opportunity.evaluator.js +413 -0
  76. package/dist/agents/opportunity.evaluator.js.map +1 -0
  77. package/dist/agents/opportunity.presenter.d.ts +115 -0
  78. package/dist/agents/opportunity.presenter.d.ts.map +1 -0
  79. package/dist/agents/opportunity.presenter.js +524 -0
  80. package/dist/agents/opportunity.presenter.js.map +1 -0
  81. package/dist/agents/profile.generator.d.ts +67 -0
  82. package/dist/agents/profile.generator.d.ts.map +1 -0
  83. package/dist/agents/profile.generator.js +97 -0
  84. package/dist/agents/profile.generator.js.map +1 -0
  85. package/dist/agents/profile.hyde.generator.d.ts +43 -0
  86. package/dist/agents/profile.hyde.generator.d.ts.map +1 -0
  87. package/dist/agents/profile.hyde.generator.js +113 -0
  88. package/dist/agents/profile.hyde.generator.js.map +1 -0
  89. package/dist/agents/suggestion.generator.d.ts +24 -0
  90. package/dist/agents/suggestion.generator.d.ts.map +1 -0
  91. package/dist/agents/suggestion.generator.js +96 -0
  92. package/dist/agents/suggestion.generator.js.map +1 -0
  93. package/dist/graphs/chat.graph.d.ts +312 -0
  94. package/dist/graphs/chat.graph.d.ts.map +1 -0
  95. package/dist/graphs/chat.graph.js +267 -0
  96. package/dist/graphs/chat.graph.js.map +1 -0
  97. package/dist/graphs/home.graph.d.ts +180 -0
  98. package/dist/graphs/home.graph.d.ts.map +1 -0
  99. package/dist/graphs/home.graph.js +598 -0
  100. package/dist/graphs/home.graph.js.map +1 -0
  101. package/dist/graphs/hyde.graph.d.ts +110 -0
  102. package/dist/graphs/hyde.graph.d.ts.map +1 -0
  103. package/dist/graphs/hyde.graph.js +235 -0
  104. package/dist/graphs/hyde.graph.js.map +1 -0
  105. package/dist/graphs/index.graph.d.ts +620 -0
  106. package/dist/graphs/index.graph.d.ts.map +1 -0
  107. package/dist/graphs/index.graph.js +226 -0
  108. package/dist/graphs/index.graph.js.map +1 -0
  109. package/dist/graphs/index_membership.graph.d.ts +250 -0
  110. package/dist/graphs/index_membership.graph.d.ts.map +1 -0
  111. package/dist/graphs/index_membership.graph.js +204 -0
  112. package/dist/graphs/index_membership.graph.js.map +1 -0
  113. package/dist/graphs/intent.graph.d.ts +490 -0
  114. package/dist/graphs/intent.graph.d.ts.map +1 -0
  115. package/dist/graphs/intent.graph.js +787 -0
  116. package/dist/graphs/intent.graph.js.map +1 -0
  117. package/dist/graphs/intent_index.graph.d.ts +396 -0
  118. package/dist/graphs/intent_index.graph.d.ts.map +1 -0
  119. package/dist/graphs/intent_index.graph.js +331 -0
  120. package/dist/graphs/intent_index.graph.js.map +1 -0
  121. package/dist/graphs/maintenance.graph.d.ts +177 -0
  122. package/dist/graphs/maintenance.graph.d.ts.map +1 -0
  123. package/dist/graphs/maintenance.graph.js +173 -0
  124. package/dist/graphs/maintenance.graph.js.map +1 -0
  125. package/dist/graphs/negotiation.graph.d.ts +819 -0
  126. package/dist/graphs/negotiation.graph.d.ts.map +1 -0
  127. package/dist/graphs/negotiation.graph.js +255 -0
  128. package/dist/graphs/negotiation.graph.js.map +1 -0
  129. package/dist/graphs/opportunity.graph.d.ts +1082 -0
  130. package/dist/graphs/opportunity.graph.d.ts.map +1 -0
  131. package/dist/graphs/opportunity.graph.js +2534 -0
  132. package/dist/graphs/opportunity.graph.js.map +1 -0
  133. package/dist/graphs/profile.graph.d.ts +617 -0
  134. package/dist/graphs/profile.graph.d.ts.map +1 -0
  135. package/dist/graphs/profile.graph.js +839 -0
  136. package/dist/graphs/profile.graph.js.map +1 -0
  137. package/dist/graphs/tests/chat.graph.mocks.d.ts +104 -0
  138. package/dist/graphs/tests/chat.graph.mocks.d.ts.map +1 -0
  139. package/dist/graphs/tests/chat.graph.mocks.js +225 -0
  140. package/dist/graphs/tests/chat.graph.mocks.js.map +1 -0
  141. package/dist/index.d.ts +62 -0
  142. package/dist/index.d.ts.map +1 -0
  143. package/dist/index.js +44 -0
  144. package/dist/index.js.map +1 -0
  145. package/dist/interfaces/auth.interface.d.ts +15 -0
  146. package/dist/interfaces/auth.interface.d.ts.map +1 -0
  147. package/dist/interfaces/auth.interface.js +2 -0
  148. package/dist/interfaces/auth.interface.js.map +1 -0
  149. package/dist/interfaces/cache.interface.d.ts +43 -0
  150. package/dist/interfaces/cache.interface.d.ts.map +1 -0
  151. package/dist/interfaces/cache.interface.js +6 -0
  152. package/dist/interfaces/cache.interface.js.map +1 -0
  153. package/dist/interfaces/chat-session.interface.d.ts +11 -0
  154. package/dist/interfaces/chat-session.interface.d.ts.map +1 -0
  155. package/dist/interfaces/chat-session.interface.js +2 -0
  156. package/dist/interfaces/chat-session.interface.js.map +1 -0
  157. package/dist/interfaces/contact.interface.d.ts +48 -0
  158. package/dist/interfaces/contact.interface.d.ts.map +1 -0
  159. package/dist/interfaces/contact.interface.js +2 -0
  160. package/dist/interfaces/contact.interface.js.map +1 -0
  161. package/dist/interfaces/database.interface.d.ts +1495 -0
  162. package/dist/interfaces/database.interface.d.ts.map +1 -0
  163. package/dist/interfaces/database.interface.js +2 -0
  164. package/dist/interfaces/database.interface.js.map +1 -0
  165. package/dist/interfaces/embedder.interface.d.ts +85 -0
  166. package/dist/interfaces/embedder.interface.d.ts.map +1 -0
  167. package/dist/interfaces/embedder.interface.js +5 -0
  168. package/dist/interfaces/embedder.interface.js.map +1 -0
  169. package/dist/interfaces/enrichment.interface.d.ts +40 -0
  170. package/dist/interfaces/enrichment.interface.d.ts.map +1 -0
  171. package/dist/interfaces/enrichment.interface.js +2 -0
  172. package/dist/interfaces/enrichment.interface.js.map +1 -0
  173. package/dist/interfaces/integration.interface.d.ts +91 -0
  174. package/dist/interfaces/integration.interface.d.ts.map +1 -0
  175. package/dist/interfaces/integration.interface.js +2 -0
  176. package/dist/interfaces/integration.interface.js.map +1 -0
  177. package/dist/interfaces/queue.interface.d.ts +17 -0
  178. package/dist/interfaces/queue.interface.d.ts.map +1 -0
  179. package/dist/interfaces/queue.interface.js +5 -0
  180. package/dist/interfaces/queue.interface.js.map +1 -0
  181. package/dist/interfaces/scraper.interface.d.ts +31 -0
  182. package/dist/interfaces/scraper.interface.d.ts.map +1 -0
  183. package/dist/interfaces/scraper.interface.js +2 -0
  184. package/dist/interfaces/scraper.interface.js.map +1 -0
  185. package/dist/interfaces/storage.interface.d.ts +46 -0
  186. package/dist/interfaces/storage.interface.d.ts.map +1 -0
  187. package/dist/interfaces/storage.interface.js +6 -0
  188. package/dist/interfaces/storage.interface.js.map +1 -0
  189. package/dist/mcp/mcp.server.d.ts +29 -0
  190. package/dist/mcp/mcp.server.d.ts.map +1 -0
  191. package/dist/mcp/mcp.server.js +171 -0
  192. package/dist/mcp/mcp.server.js.map +1 -0
  193. package/dist/states/chat.state.d.ts +126 -0
  194. package/dist/states/chat.state.d.ts.map +1 -0
  195. package/dist/states/chat.state.js +112 -0
  196. package/dist/states/chat.state.js.map +1 -0
  197. package/dist/states/home.state.d.ts +100 -0
  198. package/dist/states/home.state.d.ts.map +1 -0
  199. package/dist/states/home.state.js +74 -0
  200. package/dist/states/home.state.js.map +1 -0
  201. package/dist/states/hyde.state.d.ts +54 -0
  202. package/dist/states/hyde.state.d.ts.map +1 -0
  203. package/dist/states/hyde.state.js +66 -0
  204. package/dist/states/hyde.state.js.map +1 -0
  205. package/dist/states/index.state.d.ts +179 -0
  206. package/dist/states/index.state.d.ts.map +1 -0
  207. package/dist/states/index.state.js +56 -0
  208. package/dist/states/index.state.js.map +1 -0
  209. package/dist/states/index_membership.state.d.ts +77 -0
  210. package/dist/states/index_membership.state.d.ts.map +1 -0
  211. package/dist/states/index_membership.state.js +43 -0
  212. package/dist/states/index_membership.state.js.map +1 -0
  213. package/dist/states/intent.state.d.ts +203 -0
  214. package/dist/states/intent.state.d.ts.map +1 -0
  215. package/dist/states/intent.state.js +153 -0
  216. package/dist/states/intent.state.js.map +1 -0
  217. package/dist/states/intent_index.state.d.ts +148 -0
  218. package/dist/states/intent_index.state.d.ts.map +1 -0
  219. package/dist/states/intent_index.state.js +100 -0
  220. package/dist/states/intent_index.state.js.map +1 -0
  221. package/dist/states/maintenance.state.d.ts +36 -0
  222. package/dist/states/maintenance.state.d.ts.map +1 -0
  223. package/dist/states/maintenance.state.js +56 -0
  224. package/dist/states/maintenance.state.js.map +1 -0
  225. package/dist/states/negotiation.state.d.ts +230 -0
  226. package/dist/states/negotiation.state.d.ts.map +1 -0
  227. package/dist/states/negotiation.state.js +82 -0
  228. package/dist/states/negotiation.state.js.map +1 -0
  229. package/dist/states/opportunity.state.d.ts +300 -0
  230. package/dist/states/opportunity.state.d.ts.map +1 -0
  231. package/dist/states/opportunity.state.js +207 -0
  232. package/dist/states/opportunity.state.js.map +1 -0
  233. package/dist/states/profile.state.d.ts +172 -0
  234. package/dist/states/profile.state.d.ts.map +1 -0
  235. package/dist/states/profile.state.js +133 -0
  236. package/dist/states/profile.state.js.map +1 -0
  237. package/dist/streamers/chat.streamer.d.ts +55 -0
  238. package/dist/streamers/chat.streamer.d.ts.map +1 -0
  239. package/dist/streamers/chat.streamer.js +186 -0
  240. package/dist/streamers/chat.streamer.js.map +1 -0
  241. package/dist/streamers/index.d.ts +3 -0
  242. package/dist/streamers/index.d.ts.map +1 -0
  243. package/dist/streamers/index.js +3 -0
  244. package/dist/streamers/index.js.map +1 -0
  245. package/dist/streamers/response.streamer.d.ts +36 -0
  246. package/dist/streamers/response.streamer.d.ts.map +1 -0
  247. package/dist/streamers/response.streamer.js +46 -0
  248. package/dist/streamers/response.streamer.js.map +1 -0
  249. package/dist/support/chat.utils.d.ts +42 -0
  250. package/dist/support/chat.utils.d.ts.map +1 -0
  251. package/dist/support/chat.utils.js +89 -0
  252. package/dist/support/chat.utils.js.map +1 -0
  253. package/dist/support/debug-meta.sanitizer.d.ts +18 -0
  254. package/dist/support/debug-meta.sanitizer.d.ts.map +1 -0
  255. package/dist/support/debug-meta.sanitizer.js +82 -0
  256. package/dist/support/debug-meta.sanitizer.js.map +1 -0
  257. package/dist/support/feed.health.d.ts +32 -0
  258. package/dist/support/feed.health.d.ts.map +1 -0
  259. package/dist/support/feed.health.js +76 -0
  260. package/dist/support/feed.health.js.map +1 -0
  261. package/dist/support/introducer.discovery.d.ts +78 -0
  262. package/dist/support/introducer.discovery.d.ts.map +1 -0
  263. package/dist/support/introducer.discovery.js +101 -0
  264. package/dist/support/introducer.discovery.js.map +1 -0
  265. package/dist/support/log.d.ts +65 -0
  266. package/dist/support/log.d.ts.map +1 -0
  267. package/dist/support/log.js +76 -0
  268. package/dist/support/log.js.map +1 -0
  269. package/dist/support/lucide.icon-catalog.d.ts +22 -0
  270. package/dist/support/lucide.icon-catalog.d.ts.map +1 -0
  271. package/dist/support/lucide.icon-catalog.js +101 -0
  272. package/dist/support/lucide.icon-catalog.js.map +1 -0
  273. package/dist/support/opportunity.card-text.d.ts +39 -0
  274. package/dist/support/opportunity.card-text.d.ts.map +1 -0
  275. package/dist/support/opportunity.card-text.js +333 -0
  276. package/dist/support/opportunity.card-text.js.map +1 -0
  277. package/dist/support/opportunity.constants.d.ts +9 -0
  278. package/dist/support/opportunity.constants.d.ts.map +1 -0
  279. package/dist/support/opportunity.constants.js +11 -0
  280. package/dist/support/opportunity.constants.js.map +1 -0
  281. package/dist/support/opportunity.discover.d.ts +144 -0
  282. package/dist/support/opportunity.discover.d.ts.map +1 -0
  283. package/dist/support/opportunity.discover.js +610 -0
  284. package/dist/support/opportunity.discover.js.map +1 -0
  285. package/dist/support/opportunity.enricher.d.ts +44 -0
  286. package/dist/support/opportunity.enricher.d.ts.map +1 -0
  287. package/dist/support/opportunity.enricher.js +245 -0
  288. package/dist/support/opportunity.enricher.js.map +1 -0
  289. package/dist/support/opportunity.persist.d.ts +39 -0
  290. package/dist/support/opportunity.persist.d.ts.map +1 -0
  291. package/dist/support/opportunity.persist.js +63 -0
  292. package/dist/support/opportunity.persist.js.map +1 -0
  293. package/dist/support/opportunity.presentation.d.ts +21 -0
  294. package/dist/support/opportunity.presentation.d.ts.map +1 -0
  295. package/dist/support/opportunity.presentation.js +75 -0
  296. package/dist/support/opportunity.presentation.js.map +1 -0
  297. package/dist/support/opportunity.sanitize.d.ts +18 -0
  298. package/dist/support/opportunity.sanitize.d.ts.map +1 -0
  299. package/dist/support/opportunity.sanitize.js +89 -0
  300. package/dist/support/opportunity.sanitize.js.map +1 -0
  301. package/dist/support/opportunity.utils.d.ts +99 -0
  302. package/dist/support/opportunity.utils.d.ts.map +1 -0
  303. package/dist/support/opportunity.utils.js +184 -0
  304. package/dist/support/opportunity.utils.js.map +1 -0
  305. package/dist/support/performance.d.ts +19 -0
  306. package/dist/support/performance.d.ts.map +1 -0
  307. package/dist/support/performance.js +43 -0
  308. package/dist/support/performance.js.map +1 -0
  309. package/dist/support/profile.enrichment-display-name.d.ts +16 -0
  310. package/dist/support/profile.enrichment-display-name.d.ts.map +1 -0
  311. package/dist/support/profile.enrichment-display-name.js +22 -0
  312. package/dist/support/profile.enrichment-display-name.js.map +1 -0
  313. package/dist/support/protocol.logger.d.ts +22 -0
  314. package/dist/support/protocol.logger.d.ts.map +1 -0
  315. package/dist/support/protocol.logger.js +44 -0
  316. package/dist/support/protocol.logger.js.map +1 -0
  317. package/dist/support/request-context.d.ts +19 -0
  318. package/dist/support/request-context.d.ts.map +1 -0
  319. package/dist/support/request-context.js +7 -0
  320. package/dist/support/request-context.js.map +1 -0
  321. package/dist/tools/contact.tools.d.ts +7 -0
  322. package/dist/tools/contact.tools.d.ts.map +1 -0
  323. package/dist/tools/contact.tools.js +115 -0
  324. package/dist/tools/contact.tools.js.map +1 -0
  325. package/dist/tools/index.d.ts +17 -0
  326. package/dist/tools/index.d.ts.map +1 -0
  327. package/dist/tools/index.js +140 -0
  328. package/dist/tools/index.js.map +1 -0
  329. package/dist/tools/index.tools.d.ts +3 -0
  330. package/dist/tools/index.tools.d.ts.map +1 -0
  331. package/dist/tools/index.tools.js +423 -0
  332. package/dist/tools/index.tools.js.map +1 -0
  333. package/dist/tools/integration.tools.d.ts +13 -0
  334. package/dist/tools/integration.tools.d.ts.map +1 -0
  335. package/dist/tools/integration.tools.js +77 -0
  336. package/dist/tools/integration.tools.js.map +1 -0
  337. package/dist/tools/intent.tools.d.ts +3 -0
  338. package/dist/tools/intent.tools.d.ts.map +1 -0
  339. package/dist/tools/intent.tools.js +458 -0
  340. package/dist/tools/intent.tools.js.map +1 -0
  341. package/dist/tools/opportunity.tools.d.ts +44 -0
  342. package/dist/tools/opportunity.tools.d.ts.map +1 -0
  343. package/dist/tools/opportunity.tools.js +814 -0
  344. package/dist/tools/opportunity.tools.js.map +1 -0
  345. package/dist/tools/profile.tools.d.ts +3 -0
  346. package/dist/tools/profile.tools.d.ts.map +1 -0
  347. package/dist/tools/profile.tools.js +513 -0
  348. package/dist/tools/profile.tools.js.map +1 -0
  349. package/dist/tools/tool.helpers.d.ts +225 -0
  350. package/dist/tools/tool.helpers.d.ts.map +1 -0
  351. package/dist/tools/tool.helpers.js +172 -0
  352. package/dist/tools/tool.helpers.js.map +1 -0
  353. package/dist/tools/tool.registry.d.ts +12 -0
  354. package/dist/tools/tool.registry.d.ts.map +1 -0
  355. package/dist/tools/tool.registry.js +62 -0
  356. package/dist/tools/tool.registry.js.map +1 -0
  357. package/dist/tools/utility.tools.d.ts +3 -0
  358. package/dist/tools/utility.tools.d.ts.map +1 -0
  359. package/dist/tools/utility.tools.js +107 -0
  360. package/dist/tools/utility.tools.js.map +1 -0
  361. package/dist/types/chat-streaming.types.d.ts +472 -0
  362. package/dist/types/chat-streaming.types.d.ts.map +1 -0
  363. package/dist/types/chat-streaming.types.js +260 -0
  364. package/dist/types/chat-streaming.types.js.map +1 -0
  365. package/package.json +32 -0
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Opportunity enricher: when creating an opportunity, find overlapping existing
3
+ * opportunities (by non-introducer actor userId), check semantic relatedness, and
4
+ * optionally merge into a single enriched opportunity and expire the old one(s).
5
+ */
6
+ import type { CreateOpportunityData, Opportunity, OpportunityStatus } from '../interfaces/database.interface.js';
7
+ import type { Embedder } from '../interfaces/embedder.interface.js';
8
+ import type { Id } from '../interfaces/database.interface.js';
9
+ export type EnricherDatabase = {
10
+ findOverlappingOpportunities(actorUserIds: Id<'users'>[], options?: {
11
+ excludeStatuses?: ('latent' | 'pending' | 'accepted' | 'rejected' | 'expired')[];
12
+ }): Promise<Opportunity[]>;
13
+ };
14
+ export type EnrichmentResult = {
15
+ enriched: false;
16
+ data: CreateOpportunityData;
17
+ } | {
18
+ enriched: true;
19
+ data: CreateOpportunityData;
20
+ expiredIds: string[];
21
+ resolvedStatus: OpportunityStatus;
22
+ };
23
+ export type EnrichOrCreateOptions = {
24
+ similarityThreshold?: number;
25
+ };
26
+ /**
27
+ * Enrich or create: find overlapping opportunities, filter by semantic relatedness
28
+ * using a two-phase approach, merge actors and interpretation into a single
29
+ * CreateOpportunityData, and return the data plus IDs to expire. If no related
30
+ * overlap, return original data unchanged.
31
+ *
32
+ * Phase 1 — Intent check (free, no API call):
33
+ * Shared intent IDs mean the same declared user goal drove both opportunities.
34
+ * This is rare because the IntentReconciler already deduplicates intents per-user
35
+ * upstream, but when it fires it is definitive.
36
+ *
37
+ * Phase 2 — Batched embedding similarity (one API call for all remaining):
38
+ * For opportunities without shared intents, embed all reasoning texts in a single
39
+ * batch call and compare cosine similarity. Cross-user intent comparison (e.g.
40
+ * Alice's "find ML co-founder" vs Bob's "join ML startup") is implicitly handled
41
+ * here since reasoning text synthesizes both users' intents.
42
+ */
43
+ export declare function enrichOrCreate(database: EnricherDatabase, embedder: Embedder, newData: CreateOpportunityData, options?: EnrichOrCreateOptions): Promise<EnrichmentResult>;
44
+ //# sourceMappingURL=opportunity.enricher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opportunity.enricher.d.ts","sourceRoot":"","sources":["../../src/support/opportunity.enricher.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,qBAAqB,EACrB,WAAW,EAIX,iBAAiB,EAClB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,qCAAqC,CAAC;AAQ9D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,4BAA4B,CAC1B,YAAY,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,EAC3B,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,CAAC,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC,EAAE,CAAA;KAAE,GAC7F,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,qBAAqB,CAAA;CAAE,GAChD;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,qBAAqB,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAE7G,MAAM,MAAM,qBAAqB,GAAG;IAClC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAgJF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,gBAAgB,EAC1B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,qBAAqB,EAC9B,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAqG3B"}
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Opportunity enricher: when creating an opportunity, find overlapping existing
3
+ * opportunities (by non-introducer actor userId), check semantic relatedness, and
4
+ * optionally merge into a single enriched opportunity and expire the old one(s).
5
+ */
6
+ import { protocolLogger } from './protocol.logger.js';
7
+ const logger = protocolLogger('OpportunityEnricher');
8
+ const DEFAULT_SIMILARITY_THRESHOLD = 0.7;
9
+ const MIN_REASONING_LENGTH_FOR_EMBEDDING = 10;
10
+ /**
11
+ * Cosine similarity between two vectors (0–1).
12
+ */
13
+ function cosineSimilarity(a, b) {
14
+ if (a.length !== b.length || a.length === 0)
15
+ return 0;
16
+ let dot = 0;
17
+ let normA = 0;
18
+ let normB = 0;
19
+ for (let i = 0; i < a.length; i++) {
20
+ dot += a[i] * b[i];
21
+ normA += a[i] * a[i];
22
+ normB += b[i] * b[i];
23
+ }
24
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
25
+ if (denom === 0)
26
+ return 0;
27
+ const sim = dot / denom;
28
+ return Math.max(0, Math.min(1, sim));
29
+ }
30
+ /**
31
+ * Resolve enriched opportunity status from related opportunities' statuses and the incoming status.
32
+ * Priority: accepted > pending > rejected > draft (only when incoming is draft) > latent.
33
+ * The incoming status is included so we do not wrongly downgrade when the new opportunity has a higher-priority status.
34
+ * When incoming is 'draft' (e.g. from in-chat discovery), we preserve draft so the opportunity stays chat-only and
35
+ * does not appear on the home view (home excludes draft).
36
+ * When incoming is NOT draft (e.g. 'latent' from the background broker), existing draft status does NOT contaminate
37
+ * the result — the broker-created opportunity retains its own status and can appear on the home view.
38
+ */
39
+ function resolveEnrichedStatus(relatedStatuses, incomingStatus) {
40
+ const statuses = incomingStatus ? [...relatedStatuses, incomingStatus] : relatedStatuses;
41
+ if (statuses.includes('accepted'))
42
+ return 'accepted';
43
+ if (statuses.includes('pending'))
44
+ return 'pending';
45
+ if (statuses.includes('rejected'))
46
+ return 'rejected';
47
+ if (incomingStatus === 'draft')
48
+ return 'draft';
49
+ return 'latent';
50
+ }
51
+ /**
52
+ * Extract non-introducer actor userIds from create data.
53
+ */
54
+ function getNonIntroducerUserIds(data) {
55
+ const ids = data.actors
56
+ .filter((a) => a.role !== 'introducer')
57
+ .map((a) => a.userId);
58
+ return [...new Set(ids)];
59
+ }
60
+ /**
61
+ * Extract intent IDs from actors.
62
+ */
63
+ function getIntentIdsFromActors(actors) {
64
+ const ids = new Set();
65
+ for (const a of actors) {
66
+ if (a.intent)
67
+ ids.add(a.intent);
68
+ }
69
+ return ids;
70
+ }
71
+ /**
72
+ * Check if two opportunities share at least one intent ID.
73
+ */
74
+ function shareIntentIds(newData, existing) {
75
+ const newIntents = getIntentIdsFromActors(newData.actors);
76
+ const existingIntents = getIntentIdsFromActors(existing.actors);
77
+ for (const id of newIntents) {
78
+ if (existingIntents.has(id))
79
+ return true;
80
+ }
81
+ return false;
82
+ }
83
+ /**
84
+ * Merge actors from new data and existing opportunities: union by (indexId, userId, intent),
85
+ * preserving all unique introducers and preferring newer role on conflict.
86
+ */
87
+ function mergeActors(newData, existingList) {
88
+ const key = (a) => `${a.indexId}:${a.userId}:${a.intent ?? ''}`;
89
+ const map = new Map();
90
+ // Add all from existing first (older)
91
+ for (const opp of existingList) {
92
+ for (const a of opp.actors) {
93
+ map.set(key(a), a);
94
+ }
95
+ }
96
+ // Add/overwrite with new (newer wins for same key, e.g. role)
97
+ for (const a of newData.actors) {
98
+ map.set(key(a), a);
99
+ }
100
+ return [...map.values()];
101
+ }
102
+ /**
103
+ * Merge interpretation: single reasoning (new data only), max confidence, merged signals.
104
+ * We use only the new opportunity's reasoning to avoid repetitive concatenation when
105
+ * multiple overlapping opportunities share the same or similar text (e.g. same pair
106
+ * across indexes), which previously produced long duplicated paragraphs in chat cards.
107
+ */
108
+ function mergeInterpretation(newData, existingList) {
109
+ const reasoning = newData.interpretation.reasoning;
110
+ let maxConf = typeof newData.interpretation.confidence === 'number'
111
+ ? newData.interpretation.confidence
112
+ : parseFloat(String(newData.interpretation.confidence ?? 0));
113
+ for (const o of existingList) {
114
+ const c = o.interpretation?.confidence;
115
+ const cNum = typeof c === 'number' ? c : parseFloat(String(c ?? 0));
116
+ if (cNum > maxConf)
117
+ maxConf = cNum;
118
+ }
119
+ const confidence = maxConf;
120
+ const signals = [
121
+ ...(newData.interpretation.signals ?? []),
122
+ ...existingList.flatMap((o) => o.interpretation?.signals ?? []),
123
+ ];
124
+ const seen = new Set();
125
+ const dedupedSignals = signals.filter((s) => {
126
+ const k = `${s.type}:${s.detail ?? ''}`;
127
+ if (seen.has(k))
128
+ return false;
129
+ seen.add(k);
130
+ return true;
131
+ });
132
+ return {
133
+ category: newData.interpretation.category,
134
+ reasoning,
135
+ confidence: typeof confidence === 'string' ? parseFloat(confidence) : confidence,
136
+ signals: dedupedSignals.length > 0 ? dedupedSignals : newData.interpretation.signals,
137
+ };
138
+ }
139
+ /**
140
+ * Enrich or create: find overlapping opportunities, filter by semantic relatedness
141
+ * using a two-phase approach, merge actors and interpretation into a single
142
+ * CreateOpportunityData, and return the data plus IDs to expire. If no related
143
+ * overlap, return original data unchanged.
144
+ *
145
+ * Phase 1 — Intent check (free, no API call):
146
+ * Shared intent IDs mean the same declared user goal drove both opportunities.
147
+ * This is rare because the IntentReconciler already deduplicates intents per-user
148
+ * upstream, but when it fires it is definitive.
149
+ *
150
+ * Phase 2 — Batched embedding similarity (one API call for all remaining):
151
+ * For opportunities without shared intents, embed all reasoning texts in a single
152
+ * batch call and compare cosine similarity. Cross-user intent comparison (e.g.
153
+ * Alice's "find ML co-founder" vs Bob's "join ML startup") is implicitly handled
154
+ * here since reasoning text synthesizes both users' intents.
155
+ */
156
+ export async function enrichOrCreate(database, embedder, newData, options) {
157
+ const actorUserIds = getNonIntroducerUserIds(newData);
158
+ if (actorUserIds.length === 0) {
159
+ return { enriched: false, data: newData };
160
+ }
161
+ const overlapping = await database.findOverlappingOpportunities(actorUserIds);
162
+ if (overlapping.length === 0) {
163
+ return { enriched: false, data: newData };
164
+ }
165
+ const threshold = options?.similarityThreshold ?? DEFAULT_SIMILARITY_THRESHOLD;
166
+ // Phase 1: Intent-based relatedness (free, strongest signal)
167
+ const related = [];
168
+ const remaining = [];
169
+ for (const opp of overlapping) {
170
+ if (shareIntentIds(newData, opp)) {
171
+ related.push(opp);
172
+ }
173
+ else {
174
+ remaining.push(opp);
175
+ }
176
+ }
177
+ // Phase 2: Batched embedding similarity (one API call for all remaining)
178
+ if (remaining.length > 0) {
179
+ const newReasoning = (newData.interpretation?.reasoning ?? '').trim();
180
+ // Only embed opps where both reasonings are long enough
181
+ const embeddable = [];
182
+ for (const opp of remaining) {
183
+ const existingReasoning = (opp.interpretation?.reasoning ?? '').trim();
184
+ if (newReasoning.length >= MIN_REASONING_LENGTH_FOR_EMBEDDING &&
185
+ existingReasoning.length >= MIN_REASONING_LENGTH_FOR_EMBEDDING) {
186
+ embeddable.push(opp);
187
+ }
188
+ // Short reasoning + no shared intents (Phase 1 missed) → not related
189
+ }
190
+ if (embeddable.length > 0) {
191
+ try {
192
+ const textsToEmbed = [
193
+ newReasoning,
194
+ ...embeddable.map((o) => (o.interpretation?.reasoning ?? '').trim()),
195
+ ];
196
+ const vectors = (await embedder.generate(textsToEmbed));
197
+ const newVec = vectors[0];
198
+ if (newVec?.length) {
199
+ for (let i = 0; i < embeddable.length; i++) {
200
+ const existingVec = vectors[i + 1];
201
+ if (existingVec?.length && cosineSimilarity(newVec, existingVec) >= threshold) {
202
+ related.push(embeddable[i]);
203
+ }
204
+ }
205
+ }
206
+ }
207
+ catch (e) {
208
+ logger.warn('[Enricher] Embedding check failed; intent-matched opportunities already captured', { error: e });
209
+ // Phase 1 matches are preserved; remaining opps without shared intents are not related
210
+ }
211
+ }
212
+ }
213
+ if (related.length === 0) {
214
+ return { enriched: false, data: newData };
215
+ }
216
+ const mergedActors = mergeActors(newData, related);
217
+ const mergedInterpretation = mergeInterpretation(newData, related);
218
+ const enrichedFrom = related.map((o) => o.id);
219
+ const mergedConfidence = typeof mergedInterpretation.confidence === 'number'
220
+ ? String(mergedInterpretation.confidence)
221
+ : mergedInterpretation.confidence;
222
+ const enrichedData = {
223
+ ...newData,
224
+ detection: {
225
+ ...newData.detection,
226
+ source: 'enrichment',
227
+ enrichedFrom,
228
+ },
229
+ actors: mergedActors,
230
+ interpretation: mergedInterpretation,
231
+ confidence: mergedConfidence,
232
+ };
233
+ const resolvedStatus = resolveEnrichedStatus(related.map((o) => o.status), newData.status);
234
+ logger.verbose('[Enricher] Enriched opportunity', {
235
+ enrichedFrom,
236
+ actorCount: mergedActors.length,
237
+ });
238
+ return {
239
+ enriched: true,
240
+ data: enrichedData,
241
+ expiredIds: enrichedFrom,
242
+ resolvedStatus,
243
+ };
244
+ }
245
+ //# sourceMappingURL=opportunity.enricher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opportunity.enricher.js","sourceRoot":"","sources":["../../src/support/opportunity.enricher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Shared persist phase for opportunity creation: enrichOrCreate → create (or create+expire) → optional chat injection.
3
+ * Used by the opportunity graph persist node and by the manual opportunity service for consistency.
4
+ */
5
+ import type { CreateOpportunityData, Opportunity, OpportunityStatus } from '../interfaces/database.interface.js';
6
+ import type { Embedder } from '../interfaces/embedder.interface.js';
7
+ import type { EnricherDatabase } from './opportunity.enricher.js';
8
+ export type PersistOpportunityDatabase = EnricherDatabase & {
9
+ createOpportunity(data: CreateOpportunityData): Promise<Opportunity>;
10
+ updateOpportunityStatus(id: string, status: OpportunityStatus): Promise<void | Opportunity | null>;
11
+ createOpportunityAndExpireIds?(data: CreateOpportunityData, expireIds: string[]): Promise<{
12
+ created: Opportunity;
13
+ expired: Opportunity[];
14
+ }>;
15
+ /** Optional: used to populate expired list in non-atomic path. */
16
+ getOpportunity?(id: string): Promise<Opportunity | null>;
17
+ };
18
+ export interface PersistOpportunitiesParams {
19
+ database: PersistOpportunityDatabase;
20
+ embedder: Embedder;
21
+ items: CreateOpportunityData[];
22
+ injectChat?: (opportunity: Opportunity) => Promise<unknown>;
23
+ }
24
+ export interface PersistOpportunitiesError {
25
+ itemIndex: number;
26
+ error: unknown;
27
+ }
28
+ export interface PersistOpportunitiesResult {
29
+ created: Opportunity[];
30
+ expired: Opportunity[];
31
+ errors?: PersistOpportunitiesError[];
32
+ }
33
+ /**
34
+ * Persist one or more opportunities: enrich (merge overlapping), create, expire replaced, optional chat injection.
35
+ * When the database has createOpportunityAndExpireIds and enrichment produced expireIds, uses it for atomic create+expire.
36
+ * Returns both created and expired so callers can emit events (e.g. manual service).
37
+ */
38
+ export declare function persistOpportunities(params: PersistOpportunitiesParams): Promise<PersistOpportunitiesResult>;
39
+ //# sourceMappingURL=opportunity.persist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opportunity.persist.d.ts","sourceRoot":"","sources":["../../src/support/opportunity.persist.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EAClB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAMlE,MAAM,MAAM,0BAA0B,GAAG,gBAAgB,GAAG;IAC1D,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACrE,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,GAAG,WAAW,GAAG,IAAI,CAAC,CAAC;IACnG,6BAA6B,CAAC,CAC5B,IAAI,EAAE,qBAAqB,EAC3B,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC;QAAE,OAAO,EAAE,WAAW,CAAC;QAAC,OAAO,EAAE,WAAW,EAAE,CAAA;KAAE,CAAC,CAAC;IAC7D,kEAAkE;IAClE,cAAc,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CAC1D,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,qBAAqB,EAAE,CAAC;IAC/B,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,yBAAyB,EAAE,CAAC;CACtC;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAoDlH"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Shared persist phase for opportunity creation: enrichOrCreate → create (or create+expire) → optional chat injection.
3
+ * Used by the opportunity graph persist node and by the manual opportunity service for consistency.
4
+ */
5
+ import { enrichOrCreate } from './opportunity.enricher.js';
6
+ import { protocolLogger } from './protocol.logger.js';
7
+ const logger = protocolLogger('OpportunityPersist');
8
+ /**
9
+ * Persist one or more opportunities: enrich (merge overlapping), create, expire replaced, optional chat injection.
10
+ * When the database has createOpportunityAndExpireIds and enrichment produced expireIds, uses it for atomic create+expire.
11
+ * Returns both created and expired so callers can emit events (e.g. manual service).
12
+ */
13
+ export async function persistOpportunities(params) {
14
+ const { database, embedder, items, injectChat } = params;
15
+ const created = [];
16
+ const expired = [];
17
+ const errors = [];
18
+ for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
19
+ const data = items[itemIndex];
20
+ try {
21
+ const enrichment = await enrichOrCreate(database, embedder, data);
22
+ const toCreate = enrichment.data;
23
+ if (enrichment.enriched) {
24
+ toCreate.status = enrichment.resolvedStatus;
25
+ }
26
+ if (database.createOpportunityAndExpireIds &&
27
+ enrichment.enriched &&
28
+ enrichment.expiredIds.length > 0) {
29
+ const result = await database.createOpportunityAndExpireIds(toCreate, enrichment.expiredIds);
30
+ created.push(result.created);
31
+ expired.push(...result.expired);
32
+ }
33
+ else {
34
+ const c = await database.createOpportunity(toCreate);
35
+ created.push(c);
36
+ if (enrichment.enriched && enrichment.expiredIds.length > 0) {
37
+ for (const id of enrichment.expiredIds) {
38
+ await database.updateOpportunityStatus(id, 'expired');
39
+ }
40
+ if (database.getOpportunity) {
41
+ for (const id of enrichment.expiredIds) {
42
+ const opp = await database.getOpportunity(id);
43
+ if (opp)
44
+ expired.push(opp);
45
+ }
46
+ }
47
+ }
48
+ }
49
+ const lastCreated = created[created.length - 1];
50
+ if (lastCreated?.status === 'pending' && injectChat) {
51
+ await injectChat(lastCreated).catch((err) => {
52
+ logger.warn('[PersistOpportunities] Chat injection failed', { opportunityId: lastCreated.id, error: err });
53
+ });
54
+ }
55
+ }
56
+ catch (err) {
57
+ errors.push({ itemIndex, error: err });
58
+ logger.warn('[PersistOpportunities] Item failed', { itemIndex, error: err });
59
+ }
60
+ }
61
+ return { created, expired, ...(errors.length > 0 ? { errors } : {}) };
62
+ }
63
+ //# sourceMappingURL=opportunity.persist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opportunity.persist.js","sourceRoot":"","sources":["../../src/support/opportunity.persist.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Pure presentation layer for opportunities.
3
+ * Generates title, description, and CTA based on viewer context — no DB access.
4
+ */
5
+ import type { Opportunity } from '../interfaces/database.interface.js';
6
+ export interface OpportunityPresentation {
7
+ title: string;
8
+ description: string;
9
+ callToAction: string;
10
+ }
11
+ export interface UserInfo {
12
+ id: string;
13
+ name: string;
14
+ avatar: string | null;
15
+ }
16
+ /**
17
+ * Generate presentation copy for an opportunity based on viewer context.
18
+ * Pure function — no side effects, no database access.
19
+ */
20
+ export declare function presentOpportunity(opp: Opportunity, viewerId: string, otherPartyInfo: UserInfo, introducerInfo: UserInfo | null, format: 'card' | 'email' | 'notification'): OpportunityPresentation;
21
+ //# sourceMappingURL=opportunity.presentation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opportunity.presentation.d.ts","sourceRoot":"","sources":["../../src/support/opportunity.presentation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAEvE,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,QAAQ,EACxB,cAAc,EAAE,QAAQ,GAAG,IAAI,EAC/B,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,cAAc,GACxC,uBAAuB,CAsEzB"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Pure presentation layer for opportunities.
3
+ * Generates title, description, and CTA based on viewer context — no DB access.
4
+ */
5
+ /**
6
+ * Generate presentation copy for an opportunity based on viewer context.
7
+ * Pure function — no side effects, no database access.
8
+ */
9
+ export function presentOpportunity(opp, viewerId, otherPartyInfo, introducerInfo, format) {
10
+ const myActor = opp.actors.find((a) => a.userId === viewerId);
11
+ const introducer = opp.actors.find((a) => a.role === 'introducer');
12
+ if (!myActor) {
13
+ throw new Error('Viewer is not an actor in this opportunity');
14
+ }
15
+ const otherName = otherPartyInfo.name;
16
+ let title;
17
+ let description;
18
+ let descriptionIsReasoning = false;
19
+ switch (myActor.role) {
20
+ case 'agent':
21
+ title = `You can help ${otherName}`;
22
+ description = `Based on your expertise, ${otherName} might benefit from connecting with you.`;
23
+ break;
24
+ case 'patient':
25
+ title = `${otherName} might be able to help you`;
26
+ description = `${otherName} has skills that align with what you're looking for.`;
27
+ break;
28
+ case 'peer':
29
+ title = `Potential collaboration with ${otherName}`;
30
+ description = `You and ${otherName} have complementary interests.`;
31
+ break;
32
+ case 'mentee':
33
+ title = `${otherName} could mentor you`;
34
+ description = `${otherName} has experience that could help guide your journey.`;
35
+ break;
36
+ case 'mentor':
37
+ title = `${otherName} is looking for guidance`;
38
+ description = `Your expertise could help ${otherName} on their path.`;
39
+ break;
40
+ case 'founder':
41
+ title = `${otherName} might be interested in your venture`;
42
+ description = `${otherName}'s investment focus aligns with what you're building.`;
43
+ break;
44
+ case 'investor':
45
+ title = `${otherName} is building something interesting`;
46
+ description = `${otherName}'s venture might fit your investment thesis.`;
47
+ break;
48
+ case 'party':
49
+ default:
50
+ if (introducer && introducerInfo) {
51
+ title = `${introducerInfo.name} thinks you should meet ${otherName}`;
52
+ description = opp.interpretation.reasoning;
53
+ descriptionIsReasoning = true;
54
+ }
55
+ else {
56
+ title = `Opportunity with ${otherName}`;
57
+ description = opp.interpretation.reasoning;
58
+ descriptionIsReasoning = true;
59
+ }
60
+ break;
61
+ }
62
+ if (!descriptionIsReasoning) {
63
+ description += `\n\n${opp.interpretation.reasoning}`;
64
+ }
65
+ if (format === 'notification') {
66
+ description =
67
+ description.length > 100 ? description.slice(0, 97) + '...' : description;
68
+ }
69
+ return {
70
+ title,
71
+ description,
72
+ callToAction: 'View Opportunity',
73
+ };
74
+ }
75
+ //# sourceMappingURL=opportunity.presentation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opportunity.presentation.js","sourceRoot":"","sources":["../../src/support/opportunity.presentation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,GAAgB,EAChB,QAAgB,EAChB,cAAwB,EACxB,cAA+B,EAC/B,MAAyC;IAEzC,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;IAEnE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC;IACtC,IAAI,KAAa,CAAC;IAClB,IAAI,WAAmB,CAAC;IACxB,IAAI,sBAAsB,GAAG,KAAK,CAAC;IAEnC,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,OAAO;YACV,KAAK,GAAG,gBAAgB,SAAS,EAAE,CAAC;YACpC,WAAW,GAAG,4BAA4B,SAAS,0CAA0C,CAAC;YAC9F,MAAM;QACR,KAAK,SAAS;YACZ,KAAK,GAAG,GAAG,SAAS,4BAA4B,CAAC;YACjD,WAAW,GAAG,GAAG,SAAS,sDAAsD,CAAC;YACjF,MAAM;QACR,KAAK,MAAM;YACT,KAAK,GAAG,gCAAgC,SAAS,EAAE,CAAC;YACpD,WAAW,GAAG,WAAW,SAAS,gCAAgC,CAAC;YACnE,MAAM;QACR,KAAK,QAAQ;YACX,KAAK,GAAG,GAAG,SAAS,mBAAmB,CAAC;YACxC,WAAW,GAAG,GAAG,SAAS,qDAAqD,CAAC;YAChF,MAAM;QACR,KAAK,QAAQ;YACX,KAAK,GAAG,GAAG,SAAS,0BAA0B,CAAC;YAC/C,WAAW,GAAG,6BAA6B,SAAS,iBAAiB,CAAC;YACtE,MAAM;QACR,KAAK,SAAS;YACZ,KAAK,GAAG,GAAG,SAAS,sCAAsC,CAAC;YAC3D,WAAW,GAAG,GAAG,SAAS,uDAAuD,CAAC;YAClF,MAAM;QACR,KAAK,UAAU;YACb,KAAK,GAAG,GAAG,SAAS,oCAAoC,CAAC;YACzD,WAAW,GAAG,GAAG,SAAS,8CAA8C,CAAC;YACzE,MAAM;QACR,KAAK,OAAO,CAAC;QACb;YACE,IAAI,UAAU,IAAI,cAAc,EAAE,CAAC;gBACjC,KAAK,GAAG,GAAG,cAAc,CAAC,IAAI,2BAA2B,SAAS,EAAE,CAAC;gBACrE,WAAW,GAAG,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC;gBAC3C,sBAAsB,GAAG,IAAI,CAAC;YAChC,CAAC;iBAAM,CAAC;gBACN,KAAK,GAAG,oBAAoB,SAAS,EAAE,CAAC;gBACxC,WAAW,GAAG,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC;gBAC3C,sBAAsB,GAAG,IAAI,CAAC;YAChC,CAAC;YACD,MAAM;IACV,CAAC;IAED,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAC5B,WAAW,IAAI,OAAO,GAAG,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;IACvD,CAAC;IAED,IAAI,MAAM,KAAK,cAAc,EAAE,CAAC;QAC9B,WAAW;YACT,WAAW,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC;IAC9E,CAAC;IAED,OAAO;QACL,KAAK;QACL,WAAW;QACX,YAAY,EAAE,kBAAkB;KACjC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Strips UUID patterns from user-facing text to prevent internal ID leaks.
3
+ */
4
+ export declare function stripUuids(text: string): string;
5
+ /**
6
+ * Strips introducer mentions from opportunity summary text.
7
+ * Removes patterns like:
8
+ * - "[Introducer] introduced you to [Counterpart]"
9
+ * - "[Introducer] thinks you should meet [Counterpart]"
10
+ * - "[Introducer] connected you to [Counterpart]"
11
+ * - "[Introducer] suggested you meet [Counterpart]"
12
+ *
13
+ * @param text - The text to clean (personalizedSummary)
14
+ * @param introducerName - Full name of the introducer to strip
15
+ * @returns Text with introducer mentions removed, counterpart preserved
16
+ */
17
+ export declare function stripIntroducerMentions(text: string, introducerName: string | undefined): string;
18
+ //# sourceMappingURL=opportunity.sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opportunity.sanitize.d.ts","sourceRoot":"","sources":["../../src/support/opportunity.sanitize.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkB/C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,MAAM,CAqFR"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Strips UUID patterns from user-facing text to prevent internal ID leaks.
3
+ */
4
+ const UUID_PATTERN = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi;
5
+ export function stripUuids(text) {
6
+ return text
7
+ .replace(/\(([^)]*)\)/g, (_match, inner) => {
8
+ if (!UUID_PATTERN.test(inner)) {
9
+ UUID_PATTERN.lastIndex = 0;
10
+ return _match;
11
+ }
12
+ UUID_PATTERN.lastIndex = 0;
13
+ const cleaned = inner
14
+ .replace(UUID_PATTERN, '')
15
+ .replace(/,\s*,/g, ',')
16
+ .replace(/\b(?:from|and)\b/gi, '')
17
+ .replace(/^[\s,]+|[\s,]+$/g, '');
18
+ return cleaned ? `(${cleaned})` : '';
19
+ })
20
+ .replace(UUID_PATTERN, '')
21
+ .replace(/\s{2,}/g, ' ')
22
+ .trim();
23
+ }
24
+ /**
25
+ * Strips introducer mentions from opportunity summary text.
26
+ * Removes patterns like:
27
+ * - "[Introducer] introduced you to [Counterpart]"
28
+ * - "[Introducer] thinks you should meet [Counterpart]"
29
+ * - "[Introducer] connected you to [Counterpart]"
30
+ * - "[Introducer] suggested you meet [Counterpart]"
31
+ *
32
+ * @param text - The text to clean (personalizedSummary)
33
+ * @param introducerName - Full name of the introducer to strip
34
+ * @returns Text with introducer mentions removed, counterpart preserved
35
+ */
36
+ export function stripIntroducerMentions(text, introducerName) {
37
+ if (!introducerName?.trim())
38
+ return text;
39
+ const fullName = introducerName.trim();
40
+ const firstName = fullName.split(/\s+/)[0];
41
+ const namesToCheck = [fullName];
42
+ if (firstName && firstName.length > 1) {
43
+ namesToCheck.push(firstName);
44
+ }
45
+ let result = text;
46
+ for (const [idx, name] of namesToCheck.entries()) {
47
+ const escapedName = escapeRegex(name);
48
+ // Pattern: "Name introduced you to " (with or without comma, optionally with "directly")
49
+ result = result.replace(new RegExp(`\\b${escapedName}\\s+introduced\\s+you\\s+(?:directly\\s+)?to\\s*`, "gi"), "");
50
+ // Pattern: "Name thinks you should meet "
51
+ result = result.replace(new RegExp(`\\b${escapedName}\\s+thinks\\s+you\\s+should\\s+meet\\s*`, "gi"), "");
52
+ // Pattern: "Name connected you to "
53
+ result = result.replace(new RegExp(`\\b${escapedName}\\s+connected\\s+you\\s+(?:to|with)\\s*`, "gi"), "");
54
+ // Pattern: "Name suggested you meet "
55
+ result = result.replace(new RegExp(`\\b${escapedName}\\s+suggested\\s+you\\s+(?:meet|connect\\s+(?:to|with))\\s*`, "gi"), "");
56
+ // Pattern: "Name recommended you meet "
57
+ result = result.replace(new RegExp(`\\b${escapedName}\\s+recommended\\s+you\\s+(?:meet|connect)\\s*`, "gi"), "");
58
+ // Pattern: "Name thinks you and Counterpart should meet" -> remove entire phrase up to Counterpart
59
+ result = result.replace(new RegExp(`\\b${escapedName}\\s+thinks\\s+you\\s+and\\s+`, "gi"), "");
60
+ // Pattern: "Name also thought..." - remove sentences starting with Name + also/also thought
61
+ result = result.replace(new RegExp(`\\b${escapedName}\\s+(?:also\\s+)?(?:thought|thinks?|believes?|felt)\\s*`, "gi"), "");
62
+ // General: Remove any remaining standalone mention of the introducer name at sentence start.
63
+ // Only apply for fullName (idx === 0) to avoid stripping valid counterpart first names
64
+ // (e.g. "David Smith" intro to "David Johnson" → we strip "David Smith" but not "David" in "David Johnson").
65
+ if (idx === 0) {
66
+ result = result.replace(new RegExp(`(?:^|\\.\\s*)\\b${escapedName}\\s+`, "gi"), (match, offset) => {
67
+ if (offset === 0 || match.startsWith(".")) {
68
+ return match.startsWith(".") ? ". " : "";
69
+ }
70
+ return match;
71
+ });
72
+ }
73
+ }
74
+ // Clean up: remove leading/trailing whitespace and common punctuation artifacts
75
+ result = result
76
+ .replace(/^[\,\s]+/, "") // Remove leading commas/spaces
77
+ .replace(/\s{2,}/g, " ") // Normalize multiple spaces
78
+ .trim();
79
+ // Capitalize first letter if we removed from start
80
+ if (result.length > 0) {
81
+ result = result.charAt(0).toUpperCase() + result.slice(1);
82
+ }
83
+ return result;
84
+ }
85
+ // Helper function
86
+ function escapeRegex(s) {
87
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
88
+ }
89
+ //# sourceMappingURL=opportunity.sanitize.js.map