deepline 0.3.463 → 0.3.465

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 (158) hide show
  1. package/dist/bundling-sources/sdk/src/play.ts +3 -0
  2. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  3. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +130 -55
  4. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +16 -2
  5. package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +98 -0
  6. package/dist/bundling-sources/shared_libs/plays/field-catalog.ts +353 -52
  7. package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +63 -3
  8. package/dist/cli/auth-W62UTNJZ.js +41 -0
  9. package/dist/cli/{auth-LZLBR4C3.mjs → auth-WZCX4MTH.mjs} +5 -5
  10. package/dist/cli/{billing-OTOP5RE4.mjs → billing-ATR3CLIW.mjs} +6 -6
  11. package/dist/cli/{billing-6TJPNJQD.js → billing-DQUD3DBY.js} +77 -77
  12. package/dist/cli/{chunk-IKWRUNAP.mjs → chunk-3K3EHT6E.mjs} +1 -1
  13. package/dist/cli/{chunk-ALZBANZI.js → chunk-3XFNF6RR.js} +8 -8
  14. package/dist/cli/{chunk-3BOIOCNX.js → chunk-4URRABMM.js} +1 -1
  15. package/dist/cli/{chunk-BGNWI3KH.js → chunk-5VGMRONE.js} +3 -3
  16. package/dist/cli/{chunk-5LEAXRHV.js → chunk-6P4OYABU.js} +54 -226
  17. package/dist/cli/{chunk-UROQDCVW.js → chunk-6WKYRHGT.js} +3 -3
  18. package/dist/cli/{chunk-VDGTTH7K.mjs → chunk-6Y34LU6P.mjs} +2 -2
  19. package/dist/cli/{chunk-5DRNNC72.js → chunk-7R76B3WE.js} +5 -5
  20. package/dist/cli/{chunk-C25QE4CH.mjs → chunk-7Y2MLWTM.mjs} +1 -1
  21. package/dist/cli/chunk-7YDN6AEK.mjs +649 -0
  22. package/dist/cli/{chunk-VY2GBNTX.js → chunk-A3GML7WW.js} +9 -9
  23. package/dist/cli/{chunk-UIURR26V.mjs → chunk-B6GAIXVD.mjs} +4 -4
  24. package/dist/cli/{chunk-7XYDDCQ2.js → chunk-BQNUJK53.js} +26 -26
  25. package/dist/cli/{chunk-FK2HNDCN.js → chunk-DDF74332.js} +2 -2
  26. package/dist/cli/{chunk-JVDKZJUH.js → chunk-DJD4KLIX.js} +258 -258
  27. package/dist/cli/{chunk-7D6X7IXW.mjs → chunk-E3EYQ2FQ.mjs} +4 -4
  28. package/dist/cli/{chunk-WUZS2HK6.js → chunk-E3PLLFE2.js} +53 -53
  29. package/dist/cli/{chunk-BAPTQDLF.mjs → chunk-EA2F4YVX.mjs} +2 -2
  30. package/dist/cli/{chunk-XDWS2JJT.mjs → chunk-EISIAWBD.mjs} +1 -1
  31. package/dist/cli/{chunk-GUT7CLOL.mjs → chunk-EVQBOVOJ.mjs} +3 -3
  32. package/dist/cli/{chunk-S4XQCFES.mjs → chunk-FFTLJGZQ.mjs} +5 -5
  33. package/dist/cli/{chunk-5LHXOIPT.js → chunk-GBQSEOXE.js} +7 -7
  34. package/dist/cli/{chunk-NTLI6P6Y.mjs → chunk-GNLCGR7R.mjs} +2 -2
  35. package/dist/cli/{chunk-RD6IQ2JY.mjs → chunk-GW7RUNLW.mjs} +1 -1
  36. package/dist/cli/{chunk-6PMCRYDA.js → chunk-HIMV32ZX.js} +6 -4
  37. package/dist/cli/{chunk-CVQ7N5CV.mjs → chunk-HS6CM7TF.mjs} +11 -11
  38. package/dist/cli/{chunk-DHXCBITQ.mjs → chunk-HXWZ52CW.mjs} +3 -3
  39. package/dist/cli/{chunk-MSY22NQW.mjs → chunk-I2TCWIW2.mjs} +44 -216
  40. package/dist/cli/chunk-JLZKF7EY.js +649 -0
  41. package/dist/cli/{chunk-TIRBDQ3W.js → chunk-JN7AOVD4.js} +16 -16
  42. package/dist/cli/{chunk-4YZKBBLZ.mjs → chunk-JQSPKPHT.mjs} +5 -5
  43. package/dist/cli/{chunk-XQCTG5OO.js → chunk-L3U44YVO.js} +5 -5
  44. package/dist/cli/{chunk-7FCYPAPP.js → chunk-LFTLH5BK.js} +2 -2
  45. package/dist/cli/{chunk-TKAQR3IB.mjs → chunk-MUQAKLBP.mjs} +1 -1
  46. package/dist/cli/{chunk-3U5EAP6E.mjs → chunk-N27BUJU3.mjs} +5 -5
  47. package/dist/cli/{chunk-NDHJR2WZ.js → chunk-N57JYG7J.js} +36 -36
  48. package/dist/cli/{chunk-O3BJYD6D.mjs → chunk-NIJYJI67.mjs} +2 -2
  49. package/dist/cli/{chunk-CTQ56DXP.mjs → chunk-OEU3ZNBZ.mjs} +1 -1
  50. package/dist/cli/{chunk-VPHN2HAL.mjs → chunk-OGCAGZXO.mjs} +6 -4
  51. package/dist/cli/{chunk-NAPTMYTY.js → chunk-OKI3HWFF.js} +8 -8
  52. package/dist/cli/{chunk-PVY4DPPF.js → chunk-OQDN6JK6.js} +13 -13
  53. package/dist/cli/{chunk-CBZP6J3V.js → chunk-PIGMBDBZ.js} +21 -21
  54. package/dist/cli/{chunk-SKU6ECIY.js → chunk-QPJ2BDFD.js} +5 -5
  55. package/dist/cli/{chunk-UC4SFYNU.js → chunk-RREWUPC3.js} +6 -6
  56. package/dist/cli/{chunk-LYFKBLJI.mjs → chunk-SBM5JVTK.mjs} +1 -1
  57. package/dist/cli/{chunk-2NISBXMN.js → chunk-SOIXDMZK.js} +51 -51
  58. package/dist/cli/{chunk-WUMIYOXQ.mjs → chunk-SSQXSMAT.mjs} +2 -2
  59. package/dist/cli/{chunk-2ZIRCBYG.js → chunk-TJXGEK7P.js} +6 -6
  60. package/dist/cli/{chunk-XW2JIYG7.mjs → chunk-UMQT7QMB.mjs} +2 -2
  61. package/dist/cli/{chunk-RGOUCIIZ.js → chunk-W4J2EK5K.js} +3 -3
  62. package/dist/cli/{chunk-3BVLLJ3H.mjs → chunk-X6BQ4JAD.mjs} +2 -2
  63. package/dist/cli/{chunk-F2RHUPVH.mjs → chunk-XFAO5A5R.mjs} +1 -1
  64. package/dist/cli/{chunk-YGGIZ3VT.js → chunk-XJ5W64AC.js} +4 -4
  65. package/dist/cli/{chunk-I624J4H5.mjs → chunk-YZZGFUQ4.mjs} +1 -1
  66. package/dist/cli/command-docs.js +2 -2
  67. package/dist/cli/command-docs.mjs +1 -1
  68. package/dist/cli/{csv-OK45Z5XQ.mjs → csv-AE7OLXCV.mjs} +4 -4
  69. package/dist/cli/{csv-EH5QWR4O.js → csv-ZVFGYRB7.js} +13 -13
  70. package/dist/cli/{db-3ESJKETS.js → db-JOD2MQ2T.js} +27 -27
  71. package/dist/cli/{db-6Z5E4HKN.mjs → db-KTXMCLB5.mjs} +6 -6
  72. package/dist/cli/describe-2IKB4KIX.js +48 -0
  73. package/dist/cli/{describe-PNDQB7YS.mjs → describe-FENTKQFK.mjs} +20 -20
  74. package/dist/cli/describe-core.d.mts +3 -3
  75. package/dist/cli/describe-core.d.ts +3 -3
  76. package/dist/cli/describe-core.js +4 -4
  77. package/dist/cli/describe-core.mjs +3 -3
  78. package/dist/cli/{executions-2NTWQFEG.mjs → executions-FJCV5L37.mjs} +6 -6
  79. package/dist/cli/{executions-KUOBRX5V.js → executions-IT6TQ65Q.js} +8 -8
  80. package/dist/cli/{feedback-7RPRMSGY.mjs → feedback-LTTO73YD.mjs} +4 -4
  81. package/dist/cli/{feedback-UPHAZJ4C.js → feedback-WGURC3BG.js} +8 -8
  82. package/dist/cli/git-UOIC2DJL.js +25 -0
  83. package/dist/cli/{git-SCYP6WSZ.mjs → git-ZYEDB2UG.mjs} +5 -5
  84. package/dist/cli/index.js +139 -139
  85. package/dist/cli/index.mjs +41 -41
  86. package/dist/cli/{legacy-noops-A4KYAGI6.mjs → legacy-noops-EGQ4G4BT.mjs} +5 -5
  87. package/dist/cli/{legacy-noops-7XMFCVRG.js → legacy-noops-JFXWEOZF.js} +8 -8
  88. package/dist/cli/{monitors-FLC5J7RI.mjs → monitors-IK6GWLCA.mjs} +7 -7
  89. package/dist/cli/{monitors-NZV6IX5H.js → monitors-WKN2K6ZH.js} +91 -91
  90. package/dist/cli/{org-IZ7UP3XF.js → org-FE5VMAKF.js} +68 -68
  91. package/dist/cli/{org-LUETJ7Z5.mjs → org-PD5YBUHR.mjs} +6 -6
  92. package/dist/cli/{pages-22ML3O7O.js → pages-H3DKEVVI.js} +17 -17
  93. package/dist/cli/{pages-EUX5EAGF.mjs → pages-ZVKSOSZJ.mjs} +6 -6
  94. package/dist/cli/{play-USJBQADG.js → play-2UL5OPGH.js} +305 -305
  95. package/dist/cli/{play-CDHPAKKM.mjs → play-RLIQY22H.mjs} +18 -18
  96. package/dist/cli/{providers-WFEUNPGC.js → providers-2IMHQDBC.js} +9 -9
  97. package/dist/cli/{providers-CCXZ3SQF.mjs → providers-M4AFFJF2.mjs} +6 -6
  98. package/dist/cli/{quickstart-O4JSUORZ.js → quickstart-OE64DBKK.js} +6 -6
  99. package/dist/cli/{quickstart-ZUULI635.mjs → quickstart-PS4QKNG2.mjs} +4 -4
  100. package/dist/cli/{run-QJ4NX5F5.mjs → run-3TKR5CZU.mjs} +25 -25
  101. package/dist/cli/{run-ISDJYJMU.js → run-SWLGV2VS.js} +40 -40
  102. package/dist/cli/{search-IX3XKZJ3.mjs → search-AMZ67RKO.mjs} +7 -7
  103. package/dist/cli/search-LXG7T6YZ.js +32 -0
  104. package/dist/cli/{secrets-7VUDXTUZ.mjs → secrets-INBXKNFM.mjs} +6 -6
  105. package/dist/cli/{secrets-ELQSNCTR.js → secrets-ZTLJY7L2.js} +15 -15
  106. package/dist/cli/{sessions-A3FG3AZX.js → sessions-3GKS45NP.js} +6 -6
  107. package/dist/cli/{sessions-VOIQ62GB.mjs → sessions-ZVBTKQ7J.mjs} +5 -5
  108. package/dist/cli/{settings-ZTXQEMZI.js → settings-7YG3UWJH.js} +78 -78
  109. package/dist/cli/{settings-S6N6EFBG.mjs → settings-AUPDZZ2U.mjs} +11 -11
  110. package/dist/cli/{setup-AYPIK4JE.mjs → setup-44QB72NU.mjs} +9 -9
  111. package/dist/cli/{setup-Y3WOIFLS.js → setup-YGESCFTH.js} +44 -44
  112. package/dist/cli/{skills-5SF5QWNI.mjs → skills-N3AWWCWO.mjs} +7 -7
  113. package/dist/cli/skills-QALGBUFY.js +31 -0
  114. package/dist/cli/{tools-3XNZ4J64.mjs → tools-3SHNTJPU.mjs} +18 -18
  115. package/dist/cli/tools-PUQ3JBZ7.js +55 -0
  116. package/dist/cli/{update-3U4OVX5R.mjs → update-3TWB5EEV.mjs} +9 -9
  117. package/dist/cli/update-O7XSJMLX.js +33 -0
  118. package/dist/cli/{workflow-2M5JP7SA.mjs → workflow-SYP62XNN.mjs} +7 -7
  119. package/dist/cli/{workflow-RM7H7555.js → workflow-ULIZU7KI.js} +17 -17
  120. package/dist/{client-DTwnz_AW.d.mts → client-ADFHNtFM.d.mts} +1 -1
  121. package/dist/{client-DS2IWYZF.d.ts → client-BClp2yrq.d.ts} +1 -1
  122. package/dist/{client-core-B_6HAIBy.d.ts → client-core-BFU73Ttw.d.ts} +1 -1
  123. package/dist/{client-core-DzBSlY1U.d.mts → client-core-DWLmmJWo.d.mts} +1 -1
  124. package/dist/{compiler-manifest-Dcyd3-Zd.d.ts → compiler-manifest-Cs17yO-H.d.mts} +321 -3
  125. package/dist/{compiler-manifest-Dcyd3-Zd.d.mts → compiler-manifest-Cs17yO-H.d.ts} +321 -3
  126. package/dist/{errors-yQwfgrcX.d.ts → errors-Dee-QpVS.d.ts} +1 -1
  127. package/dist/{errors-d-sTrZhe.d.mts → errors-qNfvQuRB.d.mts} +1 -1
  128. package/dist/{index-C6oXchjN.d.mts → index-BTqNNXmC.d.mts} +1 -1
  129. package/dist/{index-P56zy_z5.d.ts → index-DXTh1Lxe.d.ts} +1 -1
  130. package/dist/index.d.mts +7 -7
  131. package/dist/index.d.ts +7 -7
  132. package/dist/index.js +80 -13
  133. package/dist/index.mjs +76 -9
  134. package/dist/install-integrity.json +114 -114
  135. package/dist/plays/bundle-play-file.d.mts +3 -3
  136. package/dist/plays/bundle-play-file.d.ts +3 -3
  137. package/dist/plays/play-description.d.mts +2 -2
  138. package/dist/plays/play-description.d.ts +2 -2
  139. package/dist/plays/run-request.d.mts +2 -2
  140. package/dist/plays/run-request.d.ts +2 -2
  141. package/dist/release.d.mts +1 -1
  142. package/dist/release.d.ts +1 -1
  143. package/dist/release.js +2 -2
  144. package/dist/release.mjs +1 -1
  145. package/dist/server.d.mts +4 -4
  146. package/dist/server.d.ts +4 -4
  147. package/dist/server.js +5 -5
  148. package/dist/server.mjs +3 -3
  149. package/package.json +1 -1
  150. package/dist/cli/auth-XPGKBJKB.js +0 -41
  151. package/dist/cli/chunk-NA4T3B62.js +0 -286
  152. package/dist/cli/chunk-TXZVVBQZ.mjs +0 -286
  153. package/dist/cli/describe-QUF7VTTR.js +0 -48
  154. package/dist/cli/git-UH653WHV.js +0 -25
  155. package/dist/cli/search-TIFNLRPM.js +0 -32
  156. package/dist/cli/skills-MWFRMG3H.js +0 -31
  157. package/dist/cli/tools-XEC4OD3R.js +0 -55
  158. package/dist/cli/update-DWYEYTZE.js +0 -33
@@ -0,0 +1,649 @@
1
+ // ../plays/extractor-targets.ts
2
+ var JOB_CHANGE_STATUS_VALUES = [
3
+ "moved",
4
+ "no_change",
5
+ "left_company",
6
+ "unknown",
7
+ "profile_unavailable",
8
+ "no_new_company"
9
+ ];
10
+ var JOB_CHANGE_JSON_SCHEMA = {
11
+ type: "object",
12
+ required: ["status", "date", "new_company", "new_title"],
13
+ properties: {
14
+ status: { type: "string", enum: JOB_CHANGE_STATUS_VALUES },
15
+ date: { type: ["string", "null"] },
16
+ new_company: { type: ["string", "null"] },
17
+ new_title: { type: ["string", "null"] }
18
+ }
19
+ };
20
+ var PHONE_STATUS_VALUES = ["valid", "invalid", "unknown"];
21
+ var DEEPLINE_EXTRACTOR_TARGET_DEFINITIONS = {
22
+ id: { identity: true, valueKind: "string" },
23
+ name: { identity: true, valueKind: "string" },
24
+ email: { identity: true, valueKind: "string" },
25
+ personal_email: { identity: true, valueKind: "string" },
26
+ phone: { identity: true, valueKind: "string" },
27
+ linkedin: { identity: true, valueKind: "string" },
28
+ linkedin_url: { identity: true, valueKind: "string" },
29
+ domain: { identity: true, valueKind: "string" },
30
+ website: { identity: true, valueKind: "string" },
31
+ first_name: { identity: true, valueKind: "string" },
32
+ last_name: { identity: true, valueKind: "string" },
33
+ full_name: { identity: true, valueKind: "string" },
34
+ company: { identity: true, valueKind: "string" },
35
+ company_name: { identity: true, valueKind: "string" },
36
+ organization_name: { identity: true, valueKind: "string" },
37
+ company_domain: { identity: true, valueKind: "string" },
38
+ company_website: { identity: true, valueKind: "string" },
39
+ company_linkedin_url: { identity: true, valueKind: "string" },
40
+ title: { identity: false, valueKind: "string" },
41
+ industry: { identity: false, valueKind: "string" },
42
+ status: { identity: false, valueKind: "string" },
43
+ job_change: { identity: false, valueKind: "job_change" },
44
+ job_change_status: {
45
+ identity: false,
46
+ valueKind: "job_change_status",
47
+ enum: JOB_CHANGE_STATUS_VALUES
48
+ },
49
+ email_status: { identity: false, valueKind: "email_status" },
50
+ phone_status: {
51
+ identity: false,
52
+ valueKind: "phone_status",
53
+ enum: PHONE_STATUS_VALUES
54
+ }
55
+ };
56
+ var DEEPLINE_EXTRACTOR_TARGETS = Object.keys(
57
+ DEEPLINE_EXTRACTOR_TARGET_DEFINITIONS
58
+ );
59
+ function isDeeplineExtractorTarget(value2) {
60
+ return value2 in DEEPLINE_EXTRACTOR_TARGET_DEFINITIONS;
61
+ }
62
+
63
+ // ../plays/email-status.ts
64
+ var nullable = (type) => ({ type: [type, "null"] });
65
+ var oneOf = (values) => ({ type: "string", enum: values });
66
+ var EMAIL_STATUS_JSON_SCHEMA = {
67
+ type: "object",
68
+ required: [
69
+ "verdict",
70
+ "status",
71
+ "verified",
72
+ "confidence",
73
+ "reasons",
74
+ "signals",
75
+ "provider"
76
+ ],
77
+ properties: {
78
+ verdict: oneOf([
79
+ "send",
80
+ "send_with_caution",
81
+ "verify_next",
82
+ "hold",
83
+ "drop"
84
+ ]),
85
+ status: oneOf([
86
+ "valid",
87
+ "invalid",
88
+ "catch_all",
89
+ "valid_catch_all",
90
+ "unknown",
91
+ "do_not_mail",
92
+ "spamtrap",
93
+ "abuse",
94
+ "disposable"
95
+ ]),
96
+ verified: { type: "boolean" },
97
+ confidence: nullable("number"),
98
+ reasons: { type: "array", items: { type: "string" } },
99
+ signals: {
100
+ type: "object",
101
+ required: [
102
+ "catch_all",
103
+ "deliverability",
104
+ "mx_class",
105
+ "mx_provider",
106
+ "mx_record",
107
+ "fraud_score",
108
+ "disposable",
109
+ "role_based",
110
+ "free_email",
111
+ "abuse",
112
+ "spamtrap",
113
+ "suspect",
114
+ "valid"
115
+ ],
116
+ properties: {
117
+ catch_all: nullable("boolean"),
118
+ deliverability: oneOf([
119
+ "high",
120
+ "medium",
121
+ "low",
122
+ "unknown"
123
+ ]),
124
+ mx_class: oneOf([
125
+ "consumer_mailbox",
126
+ "workspace_mailbox",
127
+ "security_gateway",
128
+ "on_prem",
129
+ "unknown"
130
+ ]),
131
+ mx_provider: nullable("string"),
132
+ mx_record: nullable("string"),
133
+ fraud_score: nullable("number"),
134
+ disposable: nullable("boolean"),
135
+ role_based: nullable("boolean"),
136
+ free_email: nullable("boolean"),
137
+ abuse: nullable("boolean"),
138
+ spamtrap: nullable("boolean"),
139
+ suspect: nullable("boolean"),
140
+ valid: nullable("boolean")
141
+ }
142
+ },
143
+ provider: {
144
+ type: "object",
145
+ required: ["name", "raw_status", "raw_score"],
146
+ properties: {
147
+ name: { type: "string" },
148
+ raw_status: { type: ["string", "boolean", "number", "null"] },
149
+ raw_score: nullable("number")
150
+ }
151
+ }
152
+ }
153
+ };
154
+ function normalizeKey(value2) {
155
+ if (value2 == null) return null;
156
+ if (typeof value2 === "boolean") return String(value2);
157
+ const normalized = String(value2).trim().toLowerCase().replace(/\s+/g, "_");
158
+ return normalized || null;
159
+ }
160
+ function boolish(value2) {
161
+ if (typeof value2 === "boolean") return value2;
162
+ if (typeof value2 === "number")
163
+ return value2 === 1 ? true : value2 === 0 ? false : null;
164
+ if (typeof value2 !== "string") return null;
165
+ const normalized = value2.trim().toLowerCase();
166
+ if (["true", "yes", "y", "1"].includes(normalized)) return true;
167
+ if (["false", "no", "n", "0"].includes(normalized)) return false;
168
+ return null;
169
+ }
170
+ function numberish(value2) {
171
+ if (typeof value2 === "number" && Number.isFinite(value2)) return value2;
172
+ if (typeof value2 !== "string" || value2.trim() === "") return null;
173
+ const parsed = Number(value2);
174
+ return Number.isFinite(parsed) ? parsed : null;
175
+ }
176
+ function stringish(value2) {
177
+ return typeof value2 === "string" && value2.trim() ? value2.trim() : null;
178
+ }
179
+ function deliverability(value2) {
180
+ const normalized = normalizeKey(value2);
181
+ return normalized === "high" || normalized === "medium" || normalized === "low" ? normalized : "unknown";
182
+ }
183
+ function mxClass(mxProvider, mxRecord) {
184
+ const haystack = `${stringish(mxProvider) ?? ""} ${stringish(mxRecord) ?? ""}`.toLowerCase();
185
+ if (!haystack.trim()) return "unknown";
186
+ if (/proofpoint|pphosted|mimecast|barracuda|ess\.barracudanetworks|ironport|cisco|iphmx|messagelabs|symantec/.test(
187
+ haystack
188
+ )) {
189
+ return "security_gateway";
190
+ }
191
+ if (/aspmx\.l\.google|google|g-suite|google workspace/.test(haystack)) {
192
+ return "workspace_mailbox";
193
+ }
194
+ if (/protection\.outlook|office365|microsoft|outlook|exchange online/.test(
195
+ haystack
196
+ )) {
197
+ return "workspace_mailbox";
198
+ }
199
+ if (/gmail|yahoo|icloud|aol|hotmail/.test(haystack))
200
+ return "consumer_mailbox";
201
+ if (/postfix|exim|sendmail|zimbra|plesk|cpanel|mail\./.test(haystack))
202
+ return "on_prem";
203
+ return "unknown";
204
+ }
205
+ function entryForStatus(key, map) {
206
+ if (!key) return null;
207
+ return map?.[key] ?? null;
208
+ }
209
+ function read(values, name) {
210
+ return values[name];
211
+ }
212
+ function matchesRule(rule, values) {
213
+ return Object.entries(rule.when).every(([key, expected]) => {
214
+ const actual = read(values, key);
215
+ if (key.endsWith("Lt")) {
216
+ const source = numberish(read(values, key.slice(0, -2)));
217
+ return typeof expected === "number" && source != null && source < expected;
218
+ }
219
+ if (typeof expected === "boolean") return boolish(actual) === expected;
220
+ if (typeof expected === "number") return numberish(actual) === expected;
221
+ return normalizeKey(actual) === normalizeKey(expected);
222
+ });
223
+ }
224
+ function buildEmailStatus({
225
+ config,
226
+ values
227
+ }) {
228
+ const rawStatus = read(values, "rawStatus");
229
+ const rawScore = numberish(read(values, "rawScore"));
230
+ const valid = boolish(read(values, "valid"));
231
+ const catchAll = boolish(read(values, "catchAll"));
232
+ const disposable = boolish(read(values, "disposable"));
233
+ const abuse = boolish(read(values, "abuse"));
234
+ const spamtrap = boolish(read(values, "spamtrap"));
235
+ const suspect = boolish(read(values, "suspect"));
236
+ const rawKey = normalizeKey(rawStatus);
237
+ const mapped = config.rules?.find((rule) => matchesRule(rule, values)) ?? entryForStatus(rawKey, config.statusMap) ?? entryForStatus(valid == null ? null : String(valid), config.statusMap);
238
+ const status = mapped?.status ?? (disposable ? "disposable" : abuse ? "abuse" : spamtrap ? "spamtrap" : catchAll ? "catch_all" : valid === true ? "valid" : valid === false ? "invalid" : "unknown");
239
+ const defaultVerdict = status === "valid" ? "send" : status === "valid_catch_all" ? "send_with_caution" : status === "catch_all" ? "verify_next" : status === "unknown" ? "hold" : "drop";
240
+ const verdict = mapped?.verdict ?? defaultVerdict;
241
+ const verified = mapped?.verified ?? (status === "valid" || status === "valid_catch_all" || verdict === "send");
242
+ const reasons = [
243
+ mapped?.reason,
244
+ catchAll ? "catch_all_domain" : null,
245
+ mxClass(read(values, "mxProvider"), read(values, "mxRecord")) === "security_gateway" ? "security_gateway_mx" : null,
246
+ suspect ? "provider_marked_suspect" : null
247
+ ].filter((reason) => typeof reason === "string");
248
+ return {
249
+ verdict,
250
+ status,
251
+ verified,
252
+ confidence: rawScore,
253
+ reasons,
254
+ signals: {
255
+ catch_all: catchAll,
256
+ deliverability: deliverability(read(values, "deliverability")),
257
+ mx_class: mxClass(read(values, "mxProvider"), read(values, "mxRecord")),
258
+ mx_provider: stringish(read(values, "mxProvider")),
259
+ mx_record: stringish(read(values, "mxRecord")),
260
+ fraud_score: numberish(read(values, "fraudScore")),
261
+ disposable,
262
+ role_based: boolish(read(values, "roleBased")),
263
+ free_email: boolish(read(values, "freeEmail")),
264
+ abuse,
265
+ spamtrap,
266
+ suspect,
267
+ valid
268
+ },
269
+ provider: {
270
+ name: config.provider,
271
+ raw_status: typeof rawStatus === "string" || typeof rawStatus === "boolean" || typeof rawStatus === "number" ? rawStatus : null,
272
+ raw_score: rawScore
273
+ }
274
+ };
275
+ }
276
+
277
+ // ../plays/field-catalog.ts
278
+ var value = (description) => ({ type: "string", description });
279
+ var SOURCE = {
280
+ type: "string",
281
+ description: "The provider or step that found it."
282
+ };
283
+ var FIELD_CATALOG = {
284
+ person: {
285
+ name: {
286
+ description: "The person's name. Without a kind, a name in some form.",
287
+ leaves: { value: value("The name.") },
288
+ kinds: {
289
+ full: "Their full name.",
290
+ first: "Their first (given) name.",
291
+ last: "Their last (family) name."
292
+ }
293
+ },
294
+ email: {
295
+ description: "An email address for the person.",
296
+ leaves: {
297
+ value: value("The address."),
298
+ validated: {
299
+ type: "boolean",
300
+ description: "Whether the address passed validation."
301
+ },
302
+ status: {
303
+ type: "EmailStatus",
304
+ description: "The validation verdict and its signals."
305
+ },
306
+ source: SOURCE
307
+ },
308
+ kinds: {
309
+ work: "At their employer.",
310
+ personal: "Their own, not tied to an employer."
311
+ }
312
+ },
313
+ phone: {
314
+ description: "A phone number for the person.",
315
+ leaves: {
316
+ value: value("The number."),
317
+ validated: {
318
+ type: "boolean",
319
+ description: "Whether the number passed validation."
320
+ },
321
+ status: {
322
+ type: '"valid" | "invalid" | "unknown"',
323
+ description: "The validation verdict."
324
+ },
325
+ line_type: value("Mobile, landline, VoIP and so on."),
326
+ carrier: value("The carrier serving the number."),
327
+ source: SOURCE
328
+ },
329
+ kinds: {
330
+ mobile: "Their mobile.",
331
+ work: "A direct line at their employer."
332
+ }
333
+ },
334
+ linkedin: {
335
+ description: "The person's LinkedIn profile.",
336
+ leaves: {
337
+ url: value("The profile URL."),
338
+ id: value("LinkedIn's id or public identifier for the profile.")
339
+ }
340
+ },
341
+ job: {
342
+ description: "The person's current role.",
343
+ groups: {
344
+ title: {
345
+ description: "What their role is called. Without a kind, a job title or, failing one, their profile headline.",
346
+ leaves: { value: value("The title.") },
347
+ kinds: {
348
+ exact: "Their job title, never a headline.",
349
+ headline: "Their profile headline, used as a title."
350
+ }
351
+ }
352
+ },
353
+ leaves: {
354
+ change: {
355
+ type: "JobChange",
356
+ description: "Whether they changed jobs, and to what."
357
+ },
358
+ change_status: {
359
+ type: "JobChangeStatus",
360
+ description: "The job-change verdict alone."
361
+ }
362
+ }
363
+ },
364
+ record: {
365
+ description: "A provider's own record of the person.",
366
+ leaves: { id: value("The provider's id for the person.") }
367
+ }
368
+ },
369
+ company: {
370
+ name: {
371
+ description: "The company's name.",
372
+ leaves: { value: value("The name.") },
373
+ kinds: { legal: "As registered with a government." }
374
+ },
375
+ domain: {
376
+ description: "The company's web domain.",
377
+ leaves: { value: value("The bare domain, such as example.com.") }
378
+ },
379
+ website: {
380
+ description: "The company's website.",
381
+ leaves: { url: value("The site URL.") }
382
+ },
383
+ linkedin: {
384
+ description: "The company's LinkedIn page.",
385
+ leaves: { url: value("The page URL.") }
386
+ },
387
+ phone: {
388
+ description: "A phone number for the company.",
389
+ leaves: { value: value("The number.") }
390
+ },
391
+ industry: {
392
+ description: "The industry the company is in.",
393
+ leaves: { value: value("The industry.") }
394
+ },
395
+ record: {
396
+ description: "A provider's own record of the company.",
397
+ leaves: { id: value("The provider's id for the company.") }
398
+ }
399
+ },
400
+ job: {
401
+ posting: {
402
+ description: "A job posting.",
403
+ groups: {
404
+ title: {
405
+ description: "The posting's title. Not a person's job title.",
406
+ leaves: { value: value("The title.") }
407
+ }
408
+ }
409
+ }
410
+ },
411
+ podcast: {
412
+ name: {
413
+ description: "A podcast's name.",
414
+ leaves: { value: value("The name.") }
415
+ },
416
+ website: {
417
+ description: "A podcast's own page.",
418
+ leaves: { url: value("The URL.") }
419
+ }
420
+ },
421
+ post: {
422
+ title: {
423
+ description: "A social or business post's title.",
424
+ leaves: { value: value("The title.") }
425
+ },
426
+ author: {
427
+ description: "A post's author, who may be a person or a company.",
428
+ groups: {
429
+ name: {
430
+ description: "The author's name.",
431
+ leaves: { value: value("The name.") }
432
+ }
433
+ }
434
+ }
435
+ },
436
+ page: {
437
+ title: {
438
+ description: "A web page's title.",
439
+ leaves: { value: value("The title.") }
440
+ }
441
+ },
442
+ // Some entity's value, when a tool cannot say whether it is a person's or a
443
+ // company's. Each field here is answered by the same field of either.
444
+ entity: {
445
+ name: {
446
+ description: "A person's or company's name.",
447
+ leaves: { value: value("The name.") }
448
+ },
449
+ email: {
450
+ description: "An email address for a person or company.",
451
+ leaves: { value: value("The address.") }
452
+ },
453
+ phone: {
454
+ description: "A phone number for a person or company.",
455
+ leaves: { value: value("The number.") }
456
+ },
457
+ linkedin: {
458
+ description: "A person's or company's LinkedIn page.",
459
+ leaves: { url: value("The page URL.") }
460
+ },
461
+ record: {
462
+ description: "A provider's own record of a person or company.",
463
+ leaves: { id: value("The provider's id for the record.") }
464
+ }
465
+ }
466
+ };
467
+ function fieldId(entity, group, kind, leaf) {
468
+ return [entity, group, kind, leaf === "value" ? void 0 : leaf, "value"].filter(Boolean).join(".");
469
+ }
470
+ function groupFields(entity, group, definition) {
471
+ const own = [void 0, ...Object.keys(definition.kinds ?? {})].flatMap(
472
+ (kind) => Object.entries(definition.leaves ?? {}).map(([leaf, described]) => ({
473
+ ...described,
474
+ id: fieldId(entity, group, kind, leaf),
475
+ entity,
476
+ group,
477
+ ...kind ? { kind } : {},
478
+ leaf
479
+ }))
480
+ );
481
+ const nested = Object.entries(definition.groups ?? {}).flatMap(
482
+ ([name, child]) => groupFields(entity, `${group}.${name}`, child)
483
+ );
484
+ return [...own, ...nested];
485
+ }
486
+ function catalogFields() {
487
+ return Object.entries(FIELD_CATALOG).flatMap(
488
+ ([entity, groups]) => Object.entries(groups).flatMap(
489
+ ([group, definition]) => groupFields(entity, group, definition)
490
+ )
491
+ );
492
+ }
493
+ var FIELDS_BY_ID = new Map(catalogFields().map((field) => [field.id, field]));
494
+ var PROVIDER_FIELD = /^provider\.[a-z0-9_-]+(\.[a-z0-9_]+)+\.value$/;
495
+ function isFieldId(id) {
496
+ return FIELDS_BY_ID.has(id) || PROVIDER_FIELD.test(id);
497
+ }
498
+ function generalField(id) {
499
+ const field = FIELDS_BY_ID.get(id);
500
+ return field?.kind ? fieldId(field.entity, field.group, void 0, field.leaf) : null;
501
+ }
502
+ function generalFields(id) {
503
+ const field = FIELDS_BY_ID.get(id);
504
+ if (!field) return [];
505
+ const general = generalField(id);
506
+ const entity = fieldId("entity", field.group, void 0, field.leaf);
507
+ return [
508
+ ...general ? [general] : [],
509
+ ...(field.entity === "person" || field.entity === "company") && FIELDS_BY_ID.has(entity) ? [entity] : []
510
+ ];
511
+ }
512
+ function fieldSatisfies(offered, wanted) {
513
+ return offered === wanted || generalFields(offered).includes(wanted);
514
+ }
515
+ var EXTRACTOR_TARGET_FIELDS = {
516
+ email: ["person.email.value"],
517
+ personal_email: ["person.email.personal.value"],
518
+ email_status: ["person.email.status.value"],
519
+ phone: ["person.phone.value", "company.phone.value"],
520
+ phone_status: ["person.phone.status.value"],
521
+ first_name: ["person.name.first.value"],
522
+ last_name: ["person.name.last.value"],
523
+ full_name: ["person.name.full.value"],
524
+ // Also used for a list name, a channel title and a search suggestion.
525
+ name: ["person.name.value", "company.name.value"],
526
+ linkedin: [
527
+ "person.linkedin.url.value",
528
+ "person.linkedin.id.value",
529
+ "company.linkedin.url.value"
530
+ ],
531
+ linkedin_url: ["person.linkedin.url.value"],
532
+ title: ["person.job.title.value"],
533
+ job_change: ["person.job.change.value"],
534
+ job_change_status: ["person.job.change_status.value"],
535
+ company: ["company.name.value"],
536
+ company_name: ["company.name.value"],
537
+ organization_name: ["company.name.value"],
538
+ company_domain: ["company.domain.value"],
539
+ domain: ["company.domain.value"],
540
+ company_website: ["company.website.url.value"],
541
+ // Also used for a podcast URL.
542
+ website: ["company.website.url.value"],
543
+ company_linkedin_url: ["company.linkedin.url.value"],
544
+ industry: ["company.industry.value"],
545
+ id: ["person.record.id.value", "company.record.id.value"],
546
+ // Used for unrelated provider statuses; none is a catalog field.
547
+ status: []
548
+ };
549
+ function fieldOfName(name, declared) {
550
+ const meanings = nameMeanings(name);
551
+ if (declared === void 0) {
552
+ return meanings.length === 1 ? meanings[0] : void 0;
553
+ }
554
+ return isOtherThing(declared) || meanings.some((meaning) => relatedFields(declared, meaning)) ? declared : void 0;
555
+ }
556
+ function nameMeanings(name) {
557
+ return EXTRACTOR_TARGET_FIELDS[name] ?? [];
558
+ }
559
+ function relatedFields(a, b) {
560
+ return fieldSatisfies(a, b) || fieldSatisfies(b, a);
561
+ }
562
+ function isOtherThing(id) {
563
+ if (PROVIDER_FIELD.test(id)) return true;
564
+ const entity = FIELDS_BY_ID.get(id)?.entity;
565
+ return entity !== void 0 && entity !== "person" && entity !== "company" && entity !== "entity";
566
+ }
567
+ function resolveFieldName(name, bindings, outputs = []) {
568
+ const byId = /* @__PURE__ */ new Map();
569
+ for (const binding of bindings) {
570
+ if (!byId.has(binding.id)) byId.set(binding.id, binding);
571
+ }
572
+ const fields = [...byId.values()];
573
+ const pick = (matches) => {
574
+ if (matches.length > 1) {
575
+ throw new Error(
576
+ `"${name}" could be ${matches.map((match) => `${match.id} (${match.name})`).join(" or ")}. Use one of those ids.`
577
+ );
578
+ }
579
+ return matches[0];
580
+ };
581
+ const viaId = (id) => byId.get(id) ?? pick(fields.filter((field) => fieldSatisfies(field.id, id)));
582
+ if (isFieldId(name)) return viaId(name);
583
+ const own = bindings.find((binding) => binding.name === name);
584
+ if (own) {
585
+ return nameMeanings(name).some((id) => relatedFields(own.id, id)) ? byId.get(own.id) : void 0;
586
+ }
587
+ if (outputs.includes(name)) return void 0;
588
+ const found = nameMeanings(name).flatMap((id) => {
589
+ const binding = viaId(id);
590
+ return binding ? [binding] : [];
591
+ });
592
+ return pick([...new Set(found)]);
593
+ }
594
+ function fieldPaths(bindings, outputs, lists) {
595
+ const names = /* @__PURE__ */ new Set();
596
+ for (const binding of bindings) {
597
+ names.add(binding.id);
598
+ for (const general of generalFields(binding.id)) names.add(general);
599
+ names.add(binding.name);
600
+ }
601
+ for (const [name, ids] of Object.entries(EXTRACTOR_TARGET_FIELDS)) {
602
+ if (ids.some(
603
+ (id) => bindings.some((binding) => fieldSatisfies(binding.id, id))
604
+ )) {
605
+ names.add(name);
606
+ }
607
+ }
608
+ const paths = [];
609
+ for (const name of names) {
610
+ let output;
611
+ try {
612
+ const binding = resolveFieldName(name, bindings, outputs);
613
+ if (!binding) continue;
614
+ output = binding.name;
615
+ } catch {
616
+ if (!isFieldId(name) || name.startsWith("entity.")) continue;
617
+ output = null;
618
+ }
619
+ if (!isFieldId(name) && lists.includes(name)) continue;
620
+ const path = isFieldId(name) ? name.split(".") : [name, "value"];
621
+ paths.push({ path, name, output, list: false });
622
+ }
623
+ for (const name of lists) {
624
+ paths.push({ path: [name, "value"], name, output: name, list: true });
625
+ }
626
+ const seen = /* @__PURE__ */ new Set();
627
+ for (const { path } of paths) {
628
+ const key = path.join(".");
629
+ if (seen.has(key) || paths.some((other) => other.path.join(".").startsWith(`${key}.`))) {
630
+ throw new Error(`Two outputs land on result.fields.${key}. Rename one.`);
631
+ }
632
+ seen.add(key);
633
+ }
634
+ return paths;
635
+ }
636
+
637
+ export {
638
+ EMAIL_STATUS_JSON_SCHEMA,
639
+ buildEmailStatus,
640
+ JOB_CHANGE_STATUS_VALUES,
641
+ JOB_CHANGE_JSON_SCHEMA,
642
+ PHONE_STATUS_VALUES,
643
+ DEEPLINE_EXTRACTOR_TARGET_DEFINITIONS,
644
+ DEEPLINE_EXTRACTOR_TARGETS,
645
+ isDeeplineExtractorTarget,
646
+ fieldOfName,
647
+ resolveFieldName,
648
+ fieldPaths
649
+ };