@dench.com/cli 2.8.1-staging.110 → 2.8.3-staging.117
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.
- package/crm.ts +41 -1
- package/dench.ts +92 -14
- package/leads.ts +1035 -0
- package/lib/api-schemas.ts +163 -14
- package/lib/command-registry.ts +105 -2
- package/lib/crm-enrichment.ts +24 -1
- package/lib/enrichment-gateway.ts +6 -0
- package/lib/find-filter-options.generated.ts +206 -0
- package/package.json +2 -1
- package/tools.ts +13 -13
package/lib/api-schemas.ts
CHANGED
|
@@ -1187,27 +1187,136 @@ const composioToolRun = z.object({
|
|
|
1187
1187
|
account: z.string().optional(),
|
|
1188
1188
|
});
|
|
1189
1189
|
|
|
1190
|
+
/**
|
|
1191
|
+
* One list-filter entry: a plain string includes the value; the object
|
|
1192
|
+
* form supports per-value `exclude` / `exactMatch`.
|
|
1193
|
+
*/
|
|
1194
|
+
const searchFilterItem = z.union([
|
|
1195
|
+
z.string(),
|
|
1196
|
+
z.object({
|
|
1197
|
+
value: z.string(),
|
|
1198
|
+
exclude: z.boolean().optional(),
|
|
1199
|
+
exactMatch: z.boolean().optional(),
|
|
1200
|
+
}),
|
|
1201
|
+
]);
|
|
1202
|
+
|
|
1203
|
+
const FILTER_OPTIONS_NOTE =
|
|
1204
|
+
"Accepted values: see `dench leads filters` or https://dench.com/references/find-filter-options.json.";
|
|
1205
|
+
|
|
1206
|
+
const searchRange = z.object({
|
|
1207
|
+
min: z.number().int().nonnegative().optional(),
|
|
1208
|
+
max: z.number().int().nonnegative().optional(),
|
|
1209
|
+
});
|
|
1210
|
+
|
|
1190
1211
|
const peopleSearch = z.object({
|
|
1191
1212
|
linkedinUrl: z.string().optional(),
|
|
1192
1213
|
fullName: z.string().optional(),
|
|
1193
1214
|
firstName: z.string().optional(),
|
|
1194
1215
|
lastName: z.string().optional(),
|
|
1195
|
-
keywords: z
|
|
1216
|
+
keywords: z
|
|
1217
|
+
.string()
|
|
1218
|
+
.optional()
|
|
1219
|
+
.describe(`Free-text query, e.g. "fintech, AI". ${FILTER_OPTIONS_NOTE}`),
|
|
1196
1220
|
companyDomain: z.string().optional(),
|
|
1197
1221
|
companyName: z.string().optional(),
|
|
1198
|
-
titles: z
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1222
|
+
titles: z
|
|
1223
|
+
.array(searchFilterItem)
|
|
1224
|
+
.max(50)
|
|
1225
|
+
.optional()
|
|
1226
|
+
.describe(`Current job titles (free text). ${FILTER_OPTIONS_NOTE}`),
|
|
1227
|
+
pastTitles: z
|
|
1228
|
+
.array(searchFilterItem)
|
|
1229
|
+
.max(50)
|
|
1230
|
+
.optional()
|
|
1231
|
+
.describe("Past job titles (free text)."),
|
|
1232
|
+
personNames: z.array(searchFilterItem).max(20).optional(),
|
|
1233
|
+
seniorities: z
|
|
1234
|
+
.array(searchFilterItem)
|
|
1235
|
+
.max(20)
|
|
1236
|
+
.optional()
|
|
1237
|
+
.describe(
|
|
1238
|
+
"Exact enum: Owner, Founder, C-level, Partner, VP, Head, Director, Manager, Senior.",
|
|
1239
|
+
),
|
|
1240
|
+
jobFunctions: z
|
|
1241
|
+
.array(searchFilterItem)
|
|
1242
|
+
.max(20)
|
|
1243
|
+
.optional()
|
|
1244
|
+
.describe(
|
|
1245
|
+
`Exact enum, e.g. Sales, Marketing, Software. ${FILTER_OPTIONS_NOTE}`,
|
|
1246
|
+
),
|
|
1247
|
+
subFunctions: z
|
|
1248
|
+
.array(searchFilterItem)
|
|
1249
|
+
.max(50)
|
|
1250
|
+
.optional()
|
|
1251
|
+
.describe(
|
|
1252
|
+
`Exact enum, e.g. SDR/BDR, Demand Generation. ${FILTER_OPTIONS_NOTE}`,
|
|
1253
|
+
),
|
|
1254
|
+
industries: z
|
|
1255
|
+
.array(searchFilterItem)
|
|
1256
|
+
.max(50)
|
|
1257
|
+
.optional()
|
|
1258
|
+
.describe(`Exact enum, e.g. Software Development. ${FILTER_OPTIONS_NOTE}`),
|
|
1259
|
+
locations: z
|
|
1260
|
+
.array(searchFilterItem)
|
|
1261
|
+
.max(50)
|
|
1262
|
+
.optional()
|
|
1263
|
+
.describe(
|
|
1264
|
+
`Person locations — cities, states, countries, or metros (free text). ${FILTER_OPTIONS_NOTE}`,
|
|
1265
|
+
),
|
|
1266
|
+
headcountRanges: z
|
|
1267
|
+
.array(searchFilterItem)
|
|
1268
|
+
.max(20)
|
|
1269
|
+
.optional()
|
|
1270
|
+
.describe(
|
|
1271
|
+
"Exact buckets: 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, 10001+.",
|
|
1272
|
+
),
|
|
1273
|
+
companyNames: z.array(searchFilterItem).max(50).optional(),
|
|
1274
|
+
pastCompanyNames: z.array(searchFilterItem).max(50).optional(),
|
|
1275
|
+
companyDomains: z.array(searchFilterItem).max(50).optional(),
|
|
1276
|
+
companyHeadquarters: z
|
|
1277
|
+
.array(searchFilterItem)
|
|
1278
|
+
.max(50)
|
|
1279
|
+
.optional()
|
|
1280
|
+
.describe(
|
|
1281
|
+
`Company HQ locations — cities, states, countries, or metros (free text). ${FILTER_OPTIONS_NOTE}`,
|
|
1282
|
+
),
|
|
1283
|
+
companyTypes: z
|
|
1284
|
+
.array(searchFilterItem)
|
|
1285
|
+
.max(10)
|
|
1286
|
+
.optional()
|
|
1287
|
+
.describe(
|
|
1288
|
+
"Exact enum: Partnership, Nonprofit, Educational, Privately Held, Public Company, Self-Owned, Self-Employed, Government Agency.",
|
|
1289
|
+
),
|
|
1290
|
+
universities: z
|
|
1291
|
+
.array(searchFilterItem)
|
|
1292
|
+
.max(50)
|
|
1293
|
+
.optional()
|
|
1294
|
+
.describe(`Universities attended (free text). ${FILTER_OPTIONS_NOTE}`),
|
|
1295
|
+
skills: z
|
|
1296
|
+
.array(searchFilterItem)
|
|
1297
|
+
.max(50)
|
|
1298
|
+
.optional()
|
|
1299
|
+
.describe(`Profile skills (free text). ${FILTER_OPTIONS_NOTE}`),
|
|
1300
|
+
languages: z
|
|
1301
|
+
.array(searchFilterItem)
|
|
1302
|
+
.max(20)
|
|
1303
|
+
.optional()
|
|
1304
|
+
.describe(`Spoken languages, e.g. English, German. ${FILTER_OPTIONS_NOTE}`),
|
|
1305
|
+
yearsInRole: searchRange.optional(),
|
|
1306
|
+
yearsAtCompany: searchRange.optional(),
|
|
1307
|
+
daysSinceJobChange: searchRange.optional(),
|
|
1308
|
+
foundedYears: searchRange
|
|
1309
|
+
.optional()
|
|
1310
|
+
.describe("Company founded-year range, e.g. {min: 2015, max: 2024}."),
|
|
1204
1311
|
exactMatch: z.boolean().optional(),
|
|
1205
1312
|
limit: z.number().int().positive().max(5000).optional(),
|
|
1206
1313
|
offset: z.number().int().nonnegative().optional(),
|
|
1207
1314
|
pageToken: z
|
|
1208
1315
|
.string()
|
|
1209
1316
|
.optional()
|
|
1210
|
-
.describe(
|
|
1317
|
+
.describe(
|
|
1318
|
+
"Opaque token from a previous response's metadata.nextPageToken.",
|
|
1319
|
+
),
|
|
1211
1320
|
preferCache: z.boolean().optional(),
|
|
1212
1321
|
});
|
|
1213
1322
|
|
|
@@ -1215,19 +1324,51 @@ const companySearch = z.object({
|
|
|
1215
1324
|
domain: z.string().optional(),
|
|
1216
1325
|
name: z.string().optional(),
|
|
1217
1326
|
linkedinUrl: z.string().optional(),
|
|
1327
|
+
keywords: z.string().optional(),
|
|
1328
|
+
industries: z
|
|
1329
|
+
.array(z.string())
|
|
1330
|
+
.max(50)
|
|
1331
|
+
.optional()
|
|
1332
|
+
.describe(`Exact enum, e.g. Software Development. ${FILTER_OPTIONS_NOTE}`),
|
|
1333
|
+
locations: z
|
|
1334
|
+
.array(z.string())
|
|
1335
|
+
.max(50)
|
|
1336
|
+
.optional()
|
|
1337
|
+
.describe(
|
|
1338
|
+
`Cities, states, countries, or metros (free text). ${FILTER_OPTIONS_NOTE}`,
|
|
1339
|
+
),
|
|
1340
|
+
headcountRanges: z
|
|
1341
|
+
.array(z.string())
|
|
1342
|
+
.max(20)
|
|
1343
|
+
.optional()
|
|
1344
|
+
.describe(
|
|
1345
|
+
"Exact buckets: 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, 10001+.",
|
|
1346
|
+
),
|
|
1218
1347
|
exactMatch: z.boolean().optional(),
|
|
1219
1348
|
limit: z.number().int().positive().max(5000).optional(),
|
|
1220
1349
|
offset: z.number().int().nonnegative().optional(),
|
|
1221
1350
|
pageToken: z
|
|
1222
1351
|
.string()
|
|
1223
1352
|
.optional()
|
|
1224
|
-
.describe(
|
|
1353
|
+
.describe(
|
|
1354
|
+
"Opaque token from a previous response's metadata.nextPageToken.",
|
|
1355
|
+
),
|
|
1225
1356
|
preferCache: z.boolean().optional(),
|
|
1226
1357
|
});
|
|
1227
1358
|
|
|
1228
1359
|
const jobsSearch = z.object({
|
|
1229
|
-
titles: z
|
|
1230
|
-
|
|
1360
|
+
titles: z
|
|
1361
|
+
.array(z.string())
|
|
1362
|
+
.max(50)
|
|
1363
|
+
.optional()
|
|
1364
|
+
.describe(`Job titles (free text). ${FILTER_OPTIONS_NOTE}`),
|
|
1365
|
+
locations: z
|
|
1366
|
+
.array(z.string())
|
|
1367
|
+
.max(50)
|
|
1368
|
+
.optional()
|
|
1369
|
+
.describe(
|
|
1370
|
+
`Cities, states, countries, or metros (free text). ${FILTER_OPTIONS_NOTE}`,
|
|
1371
|
+
),
|
|
1231
1372
|
companyDomain: z.string().optional(),
|
|
1232
1373
|
companyName: z.string().optional(),
|
|
1233
1374
|
companyLinkedinUrl: z.string().optional(),
|
|
@@ -1237,7 +1378,9 @@ const jobsSearch = z.object({
|
|
|
1237
1378
|
pageToken: z
|
|
1238
1379
|
.string()
|
|
1239
1380
|
.optional()
|
|
1240
|
-
.describe(
|
|
1381
|
+
.describe(
|
|
1382
|
+
"Opaque token from a previous response's metadata.nextPageToken.",
|
|
1383
|
+
),
|
|
1241
1384
|
preferCache: z.boolean().optional(),
|
|
1242
1385
|
});
|
|
1243
1386
|
|
|
@@ -1450,7 +1593,7 @@ export const requestSchemas: Record<string, ZodTypeAny> = {
|
|
|
1450
1593
|
icon: z
|
|
1451
1594
|
.string()
|
|
1452
1595
|
.optional()
|
|
1453
|
-
.describe("Lucide icon name, e.g.
|
|
1596
|
+
.describe("Hugeicons (or legacy Lucide) icon name, e.g. user-multiple, target-01."),
|
|
1454
1597
|
}),
|
|
1455
1598
|
"crm.objects.update": z.object({
|
|
1456
1599
|
name: z.string(),
|
|
@@ -3068,7 +3211,11 @@ export const requestExamples: Record<string, unknown> = {
|
|
|
3068
3211
|
"web.brand": { input: { domain: "stripe.com" } },
|
|
3069
3212
|
"web.sitemap": { input: { domain: "example.com", maxLinks: 1000 } },
|
|
3070
3213
|
"web.crawl": {
|
|
3071
|
-
input: {
|
|
3214
|
+
input: {
|
|
3215
|
+
url: "https://example.com",
|
|
3216
|
+
maxPages: 15,
|
|
3217
|
+
useMainContentOnly: true,
|
|
3218
|
+
},
|
|
3072
3219
|
},
|
|
3073
3220
|
"web.screenshot": {
|
|
3074
3221
|
input: { directUrl: "https://example.com", fullScreenshot: false },
|
|
@@ -3103,12 +3250,14 @@ export const requestExamples: Record<string, unknown> = {
|
|
|
3103
3250
|
"crm.people.search": {
|
|
3104
3251
|
titles: ["Head of Sales"],
|
|
3105
3252
|
industries: ["SaaS"],
|
|
3253
|
+
companyDomains: ["acme.com", "globex.com"],
|
|
3106
3254
|
limit: 10,
|
|
3107
3255
|
},
|
|
3108
3256
|
"crm.companies.search": { domain: "example.com" },
|
|
3109
3257
|
"enrichment.jobs.search": {
|
|
3110
3258
|
titles: ["Account Executive"],
|
|
3111
3259
|
locations: ["San Francisco"],
|
|
3260
|
+
companyDomains: ["acme.com", "globex.com"],
|
|
3112
3261
|
limit: 50,
|
|
3113
3262
|
},
|
|
3114
3263
|
"enrichment.search.preview": { kind: "people", titles: ["VP Sales"] },
|
package/lib/command-registry.ts
CHANGED
|
@@ -316,6 +316,81 @@ const rawApiOperations = [
|
|
|
316
316
|
backend: convex("query", "functions/agentWorkspace:agentListArtifacts"),
|
|
317
317
|
}),
|
|
318
318
|
|
|
319
|
+
// Lists (saved searches). Find results persist as named list artifacts;
|
|
320
|
+
// these ops give agents the same full management the sidebar has.
|
|
321
|
+
// CRM lists (saved views) are managed through the `crm.views.*` ops.
|
|
322
|
+
op({
|
|
323
|
+
id: "lists.list",
|
|
324
|
+
group: "lists",
|
|
325
|
+
summary:
|
|
326
|
+
"List saved searches (find-result lists) in the workspace, newest first.",
|
|
327
|
+
cli: "dench lists",
|
|
328
|
+
aliases: ["dench lists list"],
|
|
329
|
+
method: "GET",
|
|
330
|
+
path: "/lists",
|
|
331
|
+
requestSchema: noBody,
|
|
332
|
+
responseSchema: anyResponse,
|
|
333
|
+
backend: convex("query", "functions/workspaceArtifacts:list"),
|
|
334
|
+
}),
|
|
335
|
+
op({
|
|
336
|
+
id: "lists.get",
|
|
337
|
+
group: "lists",
|
|
338
|
+
summary: "Get one saved search / list by artifact id.",
|
|
339
|
+
cli: "dench lists show",
|
|
340
|
+
method: "GET",
|
|
341
|
+
path: "/lists/{artifactId}",
|
|
342
|
+
requestSchema: noBody,
|
|
343
|
+
responseSchema: anyResponse,
|
|
344
|
+
backend: convex("query", "functions/workspaceArtifacts:get"),
|
|
345
|
+
}),
|
|
346
|
+
op({
|
|
347
|
+
id: "lists.save",
|
|
348
|
+
group: "lists",
|
|
349
|
+
summary:
|
|
350
|
+
"Save find results as a named list (rows + filters become a workspace artifact).",
|
|
351
|
+
cli: 'dench leads find --save-as "Name"',
|
|
352
|
+
method: "POST",
|
|
353
|
+
path: "/lists",
|
|
354
|
+
requestSchema: anyObject,
|
|
355
|
+
responseSchema: anyResponse,
|
|
356
|
+
backend: convex("action", "functions/workspaceArtifacts:saveFind"),
|
|
357
|
+
}),
|
|
358
|
+
op({
|
|
359
|
+
id: "lists.update",
|
|
360
|
+
group: "lists",
|
|
361
|
+
summary:
|
|
362
|
+
"Update a saved list in place (title, filters, and/or replacement rows).",
|
|
363
|
+
cli: "dench lists update",
|
|
364
|
+
method: "PATCH",
|
|
365
|
+
path: "/lists/{artifactId}",
|
|
366
|
+
requestSchema: anyObject,
|
|
367
|
+
responseSchema: anyResponse,
|
|
368
|
+
backend: convex("action", "functions/workspaceArtifacts:updateFind"),
|
|
369
|
+
}),
|
|
370
|
+
op({
|
|
371
|
+
id: "lists.rename",
|
|
372
|
+
group: "lists",
|
|
373
|
+
summary: "Rename a saved search / list.",
|
|
374
|
+
cli: "dench lists rename",
|
|
375
|
+
method: "POST",
|
|
376
|
+
path: "/lists/{artifactId}/rename",
|
|
377
|
+
requestSchema: anyObject,
|
|
378
|
+
responseSchema: anyResponse,
|
|
379
|
+
backend: convex("mutation", "functions/workspaceArtifacts:rename"),
|
|
380
|
+
}),
|
|
381
|
+
op({
|
|
382
|
+
id: "lists.delete",
|
|
383
|
+
group: "lists",
|
|
384
|
+
summary:
|
|
385
|
+
"Delete a saved search / list, its exported CSV/JSONL files, and any linked watch.",
|
|
386
|
+
cli: "dench lists delete",
|
|
387
|
+
method: "DELETE",
|
|
388
|
+
path: "/lists/{artifactId}",
|
|
389
|
+
requestSchema: anyObject,
|
|
390
|
+
responseSchema: anyResponse,
|
|
391
|
+
backend: convex("mutation", "functions/workspaceArtifacts:remove"),
|
|
392
|
+
}),
|
|
393
|
+
|
|
319
394
|
// Memory and approvals.
|
|
320
395
|
op({
|
|
321
396
|
id: "memory.search",
|
|
@@ -666,6 +741,18 @@ const rawApiOperations = [
|
|
|
666
741
|
responseSchema: anyResponse,
|
|
667
742
|
backend: convex("mutation", "functions/crm/objects:saveView"),
|
|
668
743
|
}),
|
|
744
|
+
op({
|
|
745
|
+
id: "crm.views.rename",
|
|
746
|
+
group: "crm",
|
|
747
|
+
summary:
|
|
748
|
+
"Rename a saved view in place — keeps its filters, pins, and sidebar slot.",
|
|
749
|
+
cli: "dench crm views rename",
|
|
750
|
+
method: "POST",
|
|
751
|
+
path: "/crm/objects/{objectName}/views/{viewName}/rename",
|
|
752
|
+
requestSchema: anyObject,
|
|
753
|
+
responseSchema: anyResponse,
|
|
754
|
+
backend: convex("mutation", "functions/crm/objects:renameView"),
|
|
755
|
+
}),
|
|
669
756
|
op({
|
|
670
757
|
id: "crm.views.delete",
|
|
671
758
|
group: "crm",
|
|
@@ -1357,7 +1444,8 @@ const rawApiOperations = [
|
|
|
1357
1444
|
op({
|
|
1358
1445
|
id: "crm.people.search",
|
|
1359
1446
|
group: "crm",
|
|
1360
|
-
summary:
|
|
1447
|
+
summary:
|
|
1448
|
+
"Search for people through the enrichment gateway. `companyDomains` takes up to 1000 domains (e.g. a resolved company list; `dench leads find --company-list <id|view>` resolves one for you) — the gateway fans large lists out as sequential vendor-safe chunks behind one `nextPageToken` stream.",
|
|
1361
1449
|
cli: "dench crm people search",
|
|
1362
1450
|
method: "POST",
|
|
1363
1451
|
path: "/enrichment/people/search",
|
|
@@ -1390,7 +1478,8 @@ const rawApiOperations = [
|
|
|
1390
1478
|
op({
|
|
1391
1479
|
id: "enrichment.jobs.search",
|
|
1392
1480
|
group: "crm",
|
|
1393
|
-
summary:
|
|
1481
|
+
summary:
|
|
1482
|
+
"Search job postings through Dench find. `companyDomains` takes up to 1000 domains (chunked automatically); `dench jobs find --company-list <id|view>` resolves a saved company list into it.",
|
|
1394
1483
|
cli: "dench jobs find",
|
|
1395
1484
|
method: "POST",
|
|
1396
1485
|
path: "/enrichment/jobs/search",
|
|
@@ -1442,6 +1531,20 @@ const rawApiOperations = [
|
|
|
1442
1531
|
responseSchema: anyResponse,
|
|
1443
1532
|
backend: gateway("POST", "/enrichment/search/preview"),
|
|
1444
1533
|
}),
|
|
1534
|
+
op({
|
|
1535
|
+
id: "enrichment.filters.options",
|
|
1536
|
+
group: "crm",
|
|
1537
|
+
summary:
|
|
1538
|
+
"List Lead Finder filter vocabularies: exact enum values (seniorities, functions, industries, headcount, company types, languages) and curated suggestions (titles, locations, company HQ, universities, skills, keywords).",
|
|
1539
|
+
cli: "dench leads filters",
|
|
1540
|
+
method: "GET",
|
|
1541
|
+
path: "/local/enrichment/filter-options",
|
|
1542
|
+
requestSchema: noBody,
|
|
1543
|
+
responseSchema: anyResponse,
|
|
1544
|
+
backend: local(
|
|
1545
|
+
"Catalogs are bundled with the CLI. Over HTTPS, fetch https://dench.com/references/find-filter-options.json instead.",
|
|
1546
|
+
),
|
|
1547
|
+
}),
|
|
1445
1548
|
op({
|
|
1446
1549
|
id: "crm.templates.list",
|
|
1447
1550
|
group: "crm",
|
package/lib/crm-enrichment.ts
CHANGED
|
@@ -91,6 +91,22 @@ export const PEOPLE_ENRICHMENT_COLUMNS: readonly EnrichmentColumnDef[] = [
|
|
|
91
91
|
extractionFallbacks: ["email"],
|
|
92
92
|
enrichFields: ["work_emails"],
|
|
93
93
|
},
|
|
94
|
+
{
|
|
95
|
+
label: "Work Email",
|
|
96
|
+
key: "person.work_email",
|
|
97
|
+
fieldType: "email",
|
|
98
|
+
apolloPath: "person.work_email",
|
|
99
|
+
requiredFields: ["work_email"],
|
|
100
|
+
enrichFields: ["work_emails"],
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
label: "Personal Email",
|
|
104
|
+
key: "person.personal_email",
|
|
105
|
+
fieldType: "email",
|
|
106
|
+
apolloPath: "person.personal_email",
|
|
107
|
+
requiredFields: ["personal_email"],
|
|
108
|
+
enrichFields: ["personal_emails"],
|
|
109
|
+
},
|
|
94
110
|
{
|
|
95
111
|
label: "Headline",
|
|
96
112
|
key: "person.headline",
|
|
@@ -336,7 +352,14 @@ export function getRequiredFieldsForApolloPath(
|
|
|
336
352
|
const column = getEnrichmentColumns(category).find(
|
|
337
353
|
(candidate) => candidate.apolloPath === apolloPath,
|
|
338
354
|
);
|
|
339
|
-
return column
|
|
355
|
+
if (column) return column.requiredFields;
|
|
356
|
+
if (category !== "people") return [];
|
|
357
|
+
if (apolloPath.includes("personal_email")) return ["personal_email"];
|
|
358
|
+
if (apolloPath.includes("phone")) return ["phone"];
|
|
359
|
+
if (apolloPath.includes("work_email") || /(^|\.)email$/.test(apolloPath)) {
|
|
360
|
+
return ["work_email"];
|
|
361
|
+
}
|
|
362
|
+
return [];
|
|
340
363
|
}
|
|
341
364
|
|
|
342
365
|
export function buildEnrichmentMeta(
|
|
@@ -114,7 +114,11 @@ export type SearchJobsBody = {
|
|
|
114
114
|
titles?: string[];
|
|
115
115
|
locations?: string[];
|
|
116
116
|
companyDomain?: string;
|
|
117
|
+
/** Multiple company domains (e.g. a resolved company list); the gateway
|
|
118
|
+
* fans lists past ~50 domains out as sequential vendor-safe chunks. */
|
|
119
|
+
companyDomains?: string[];
|
|
117
120
|
companyName?: string;
|
|
121
|
+
companyNames?: string[];
|
|
118
122
|
companyLinkedinUrl?: string;
|
|
119
123
|
keywords?: string;
|
|
120
124
|
postedAfter?: string;
|
|
@@ -1361,7 +1365,9 @@ export async function searchJobs(
|
|
|
1361
1365
|
if (body.titles?.length) payload.titles = body.titles;
|
|
1362
1366
|
if (body.locations?.length) payload.locations = body.locations;
|
|
1363
1367
|
if (body.companyDomain) payload.companyDomain = body.companyDomain;
|
|
1368
|
+
if (body.companyDomains?.length) payload.companyDomains = body.companyDomains;
|
|
1364
1369
|
if (body.companyName) payload.companyName = body.companyName;
|
|
1370
|
+
if (body.companyNames?.length) payload.companyNames = body.companyNames;
|
|
1365
1371
|
if (body.companyLinkedinUrl)
|
|
1366
1372
|
payload.companyLinkedinUrl = body.companyLinkedinUrl;
|
|
1367
1373
|
if (body.keywords) payload.keywords = body.keywords;
|