@coldiq/mcp 0.5.2 → 0.5.4
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/dist/executor.js +1 -1
- package/dist/executor.js.map +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +27 -5
- package/dist/registry.js.map +1 -1
- package/dist/tools/call-endpoint.d.ts +1 -0
- package/dist/tools/call-endpoint.d.ts.map +1 -1
- package/dist/tools/call-endpoint.js +3 -1
- package/dist/tools/call-endpoint.js.map +1 -1
- package/dist/tools/extract-post-engagement.d.ts +0 -7
- package/dist/tools/extract-post-engagement.d.ts.map +1 -1
- package/dist/tools/extract-post-engagement.js +205 -21
- package/dist/tools/extract-post-engagement.js.map +1 -1
- package/dist/tools/get-endpoint-details.d.ts +1 -0
- package/dist/tools/get-endpoint-details.d.ts.map +1 -1
- package/dist/tools/get-endpoint-details.js +3 -1
- package/dist/tools/get-endpoint-details.js.map +1 -1
- package/dist/tools/search-web.d.ts +1 -1
- package/dist/tools/search-web.js +2 -2
- package/dist/tools/search-web.js.map +1 -1
- package/package.json +1 -1
- package/src/executor.ts +1 -1
- package/src/registry.ts +25 -5
- package/src/tools/call-endpoint.ts +3 -1
- package/src/tools/extract-post-engagement.ts +229 -27
- package/src/tools/get-endpoint-details.ts +3 -1
- package/src/tools/search-web.ts +2 -2
- package/tests/registry-enrich-person.test.ts +16 -14
- package/tests/registry.test.ts +7 -0
- package/tests/search-web-exa-compat.test.ts +11 -0
- package/tests/tools/call-endpoint.test.ts +16 -0
- package/tests/tools/extract-post-engagement.test.ts +167 -3
- package/tests/tools/get-endpoint-details.test.ts +12 -0
|
@@ -4,6 +4,7 @@ export declare const callEndpointDescription: string;
|
|
|
4
4
|
export declare const callEndpointSchema: {
|
|
5
5
|
api: z.ZodString;
|
|
6
6
|
path: z.ZodString;
|
|
7
|
+
method: z.ZodOptional<z.ZodEnum<["GET", "POST", "PUT", "PATCH", "DELETE"]>>;
|
|
7
8
|
params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
8
9
|
};
|
|
9
10
|
export declare function callEndpointHandler(input: Record<string, unknown>): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call-endpoint.d.ts","sourceRoot":"","sources":["../../src/tools/call-endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,gBAAgB,kBAAkB,CAAA;AAE/C,eAAO,MAAM,uBAAuB,QAKgB,CAAA;AAEpD,eAAO,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"call-endpoint.d.ts","sourceRoot":"","sources":["../../src/tools/call-endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,gBAAgB,kBAAkB,CAAA;AAE/C,eAAO,MAAM,uBAAuB,QAKgB,CAAA;AAEpD,eAAO,MAAM,kBAAkB;;;;;CAS9B,CAAA;AAED,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;GASvE"}
|
|
@@ -9,13 +9,15 @@ export const callEndpointDescription = 'Call any ColdIQ marketplace endpoint dir
|
|
|
9
9
|
export const callEndpointSchema = {
|
|
10
10
|
api: z.string().describe('Provider key from search_endpoints / get_endpoint_details, e.g. "coldiq".'),
|
|
11
11
|
path: z.string().describe('Endpoint path without the /v1 prefix, e.g. "/limadata/prospect/people/filter".'),
|
|
12
|
+
method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']).optional()
|
|
13
|
+
.describe('HTTP method from search_endpoints. Set this when one path supports more than one method.'),
|
|
12
14
|
params: z
|
|
13
15
|
.record(z.unknown())
|
|
14
16
|
.optional()
|
|
15
17
|
.describe('Provider-native request params (request body fields, plus any path/query params), as shown in get_endpoint_details.'),
|
|
16
18
|
};
|
|
17
19
|
export async function callEndpointHandler(input) {
|
|
18
|
-
const res = await callApi('POST', '/endpoints/use', { api: input.api, path: input.path, params: input.params });
|
|
20
|
+
const res = await callApi('POST', '/endpoints/use', { api: input.api, path: input.path, method: input.method, params: input.params });
|
|
19
21
|
if (!res.ok) {
|
|
20
22
|
return {
|
|
21
23
|
content: [{ type: 'text', text: JSON.stringify({ error: 'Endpoint call failed', status: res.status, data: res.data }) }],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call-endpoint.js","sourceRoot":"","sources":["../../src/tools/call-endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,CAAC,MAAM,gBAAgB,GAAG,eAAe,CAAA;AAE/C,MAAM,CAAC,MAAM,uBAAuB,GAClC,yGAAyG;IACzG,mGAAmG;IACnG,6FAA6F;IAC7F,0GAA0G;IAC1G,kDAAkD,CAAA;AAEpD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2EAA2E,CAAC;IACrG,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gFAAgF,CAAC;IAC3G,MAAM,EAAE,CAAC;SACN,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;SACnB,QAAQ,EAAE;SACV,QAAQ,CAAC,qHAAqH,CAAC;CACnI,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,KAA8B;IACtE,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,gBAAgB,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"call-endpoint.js","sourceRoot":"","sources":["../../src/tools/call-endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,CAAC,MAAM,gBAAgB,GAAG,eAAe,CAAA;AAE/C,MAAM,CAAC,MAAM,uBAAuB,GAClC,yGAAyG;IACzG,mGAAmG;IACnG,6FAA6F;IAC7F,0GAA0G;IAC1G,kDAAkD,CAAA;AAEpD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2EAA2E,CAAC;IACrG,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gFAAgF,CAAC;IAC3G,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE;SACjE,QAAQ,CAAC,0FAA0F,CAAC;IACvG,MAAM,EAAE,CAAC;SACN,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;SACnB,QAAQ,EAAE;SACV,QAAQ,CAAC,qHAAqH,CAAC;CACnI,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,KAA8B;IACtE,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,gBAAgB,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;IACrI,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YACjI,OAAO,EAAE,IAAI;SACd,CAAA;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAA;AACjF,CAAC"}
|
|
@@ -4,18 +4,11 @@ export declare const extractPostEngagementDescription: string;
|
|
|
4
4
|
export declare const extractPostEngagementSchema: {
|
|
5
5
|
post_url: z.ZodString;
|
|
6
6
|
type: z.ZodDefault<z.ZodEnum<["comments", "reactions", "both"]>>;
|
|
7
|
-
include_replies: z.ZodOptional<z.ZodBoolean>;
|
|
8
7
|
};
|
|
9
8
|
export declare function extractPostEngagementHandler(input: Record<string, unknown>): Promise<{
|
|
10
9
|
content: {
|
|
11
10
|
type: "text";
|
|
12
11
|
text: string;
|
|
13
12
|
}[];
|
|
14
|
-
isError: boolean;
|
|
15
|
-
} | {
|
|
16
|
-
content: {
|
|
17
|
-
type: "text";
|
|
18
|
-
text: string;
|
|
19
|
-
}[];
|
|
20
13
|
}>;
|
|
21
14
|
//# sourceMappingURL=extract-post-engagement.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract-post-engagement.d.ts","sourceRoot":"","sources":["../../src/tools/extract-post-engagement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,yBAAyB,4BAA4B,CAAA;AAElE,eAAO,MAAM,gCAAgC,
|
|
1
|
+
{"version":3,"file":"extract-post-engagement.d.ts","sourceRoot":"","sources":["../../src/tools/extract-post-engagement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,yBAAyB,4BAA4B,CAAA;AAElE,eAAO,MAAM,gCAAgC,QAIoO,CAAA;AAEjR,eAAO,MAAM,2BAA2B;;;CAavC,CAAA;AAmLD,wBAAsB,4BAA4B,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;GAqIhF"}
|
|
@@ -3,7 +3,8 @@ import { callApi } from '../client.js';
|
|
|
3
3
|
export const extractPostEngagementName = 'extract_post_engagement';
|
|
4
4
|
export const extractPostEngagementDescription = 'Extract the people who engaged with a LinkedIn post — commenters and/or reactors — as a deduplicated list of contacts (name, profile URL, headline). ' +
|
|
5
5
|
'Use this for social-signal prospecting: pull everyone who engaged with a viral post, then chain the results into enrich_person / find_email to get roles and work emails. ' +
|
|
6
|
-
'Runs an async extraction job (typically
|
|
6
|
+
'Runs an async extraction job (typically 1–3 minutes; longer for posts with 1000+ interactions) and returns every extracted person once ready. ' +
|
|
7
|
+
'If the primary source fails or its account is out of credits, automatically retries on a second provider and says so in `_meta.provider` — those records carry name/profile URL/headline only, so enrich them before use. Pricing is returned in the response credit headers.';
|
|
7
8
|
export const extractPostEngagementSchema = {
|
|
8
9
|
post_url: z
|
|
9
10
|
.string()
|
|
@@ -13,14 +14,132 @@ export const extractPostEngagementSchema = {
|
|
|
13
14
|
.enum(['comments', 'reactions', 'both'])
|
|
14
15
|
.default('both')
|
|
15
16
|
.describe('Which engagement to extract: "comments" (people who commented), "reactions" (people who reacted), or "both" (default — deduplicated across both).'),
|
|
16
|
-
include_replies:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
// `include_replies` was removed: this tool returns a DEDUPLICATED contact list,
|
|
18
|
+
// where a person is one entry regardless of whether they commented or replied,
|
|
19
|
+
// so the flag never changed the result. Use GET /v1/jungler/workbooks/{id}/comments
|
|
20
|
+
// to work with individual comments and their reply metadata.
|
|
20
21
|
};
|
|
22
|
+
// One page covers most posts; the loop below still walks the rest when it doesn't.
|
|
23
|
+
const CONTACTS_PAGE_SIZE = 500;
|
|
24
|
+
// Backstop so a mis-paginating upstream can't spin this tool forever.
|
|
25
|
+
const MAX_CONTACT_PAGES = 20;
|
|
26
|
+
/**
|
|
27
|
+
* True unless the contact demonstrably engaged with nothing.
|
|
28
|
+
*
|
|
29
|
+
* The workbook always collects the post itself, so the post's AUTHOR comes back
|
|
30
|
+
* as a contact with `stats: {comments: 0, reactions: 0}` even when nobody
|
|
31
|
+
* engaged. This tool promises the people who engaged, so a zero/zero contact is
|
|
32
|
+
* not one of them. Anything without usable stats is kept — never drop a contact
|
|
33
|
+
* on ambiguity.
|
|
34
|
+
*/
|
|
35
|
+
function engaged(contact) {
|
|
36
|
+
if (!contact || typeof contact !== 'object')
|
|
37
|
+
return true;
|
|
38
|
+
const stats = contact.stats;
|
|
39
|
+
if (!stats || typeof stats !== 'object')
|
|
40
|
+
return true;
|
|
41
|
+
const { comments, reactions } = stats;
|
|
42
|
+
if (typeof comments !== 'number' || typeof reactions !== 'number')
|
|
43
|
+
return true;
|
|
44
|
+
return comments > 0 || reactions > 0;
|
|
45
|
+
}
|
|
46
|
+
/** Read one page of the contacts envelope, tolerating a bare-array response. */
|
|
47
|
+
function readContactsPage(data) {
|
|
48
|
+
if (Array.isArray(data))
|
|
49
|
+
return { items: data, pages: 1 };
|
|
50
|
+
if (data && typeof data === 'object') {
|
|
51
|
+
const obj = data;
|
|
52
|
+
if (Array.isArray(obj.items)) {
|
|
53
|
+
return {
|
|
54
|
+
items: obj.items,
|
|
55
|
+
total: typeof obj.total === 'number' ? obj.total : undefined,
|
|
56
|
+
pages: typeof obj.pages === 'number' ? obj.pages : undefined,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return { items: [], pages: 1 };
|
|
61
|
+
}
|
|
21
62
|
function sleep(ms) {
|
|
22
63
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
23
64
|
}
|
|
65
|
+
// ── Fallback provider ───────────────────────────────────────────────────────
|
|
66
|
+
//
|
|
67
|
+
// Jungler is the primary: it charges a flat rate per post regardless of size and
|
|
68
|
+
// returns enriched contacts (work email, company domain, title, seniority). Lima
|
|
69
|
+
// Data costs the same per post but returns profile URLs only, so it needs a
|
|
70
|
+
// separate enrichment pass — hence second, not first.
|
|
71
|
+
//
|
|
72
|
+
// We reach for it ONLY when Jungler failed for a reason that is ours, not the
|
|
73
|
+
// post's: a failed run, or an upstream account out of credits. A genuinely empty
|
|
74
|
+
// post must NOT fall through — Lima would return empty too, for another charge.
|
|
75
|
+
// Same env knobs as the primary poll, so a caller (or a test) can tighten both.
|
|
76
|
+
const fallbackPollMs = () => parseInt(process.env.COLDIQ_ENGAGEMENT_POLL_MS ?? '5000', 10);
|
|
77
|
+
const fallbackTimeoutMs = () => parseInt(process.env.COLDIQ_ENGAGEMENT_FALLBACK_TIMEOUT_MS ?? '240000', 10);
|
|
78
|
+
/** Flatten Lima's `{commenters:{comments:[{actor}]}, reactors:{reactions:[{actor}]}}` into contacts. */
|
|
79
|
+
function limaEngagersToPeople(data, type) {
|
|
80
|
+
if (!data || typeof data !== 'object')
|
|
81
|
+
return [];
|
|
82
|
+
const d = data;
|
|
83
|
+
const rows = [];
|
|
84
|
+
if (type !== 'reactions') {
|
|
85
|
+
for (const c of d.commenters?.comments ?? [])
|
|
86
|
+
rows.push({ ...c, engagement: 'COMMENT' });
|
|
87
|
+
}
|
|
88
|
+
if (type !== 'comments') {
|
|
89
|
+
for (const r of d.reactors?.reactions ?? [])
|
|
90
|
+
rows.push({ ...r, engagement: 'REACTION' });
|
|
91
|
+
}
|
|
92
|
+
// Deduplicate by profile URL: someone who both commented and reacted is one person.
|
|
93
|
+
const byProfile = new Map();
|
|
94
|
+
for (const row of rows) {
|
|
95
|
+
const actor = (row.actor ?? {});
|
|
96
|
+
const key = String(actor.profile_url ?? actor.name ?? Math.random());
|
|
97
|
+
const existing = byProfile.get(key);
|
|
98
|
+
if (existing) {
|
|
99
|
+
const seen = existing.engagement_types;
|
|
100
|
+
if (!seen.includes(row.engagement))
|
|
101
|
+
seen.push(row.engagement);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
byProfile.set(key, {
|
|
105
|
+
name: actor.name ?? null,
|
|
106
|
+
profile_url: actor.profile_url ?? null,
|
|
107
|
+
description: actor.headline ?? null,
|
|
108
|
+
profile_image_url: actor.image_url ?? null,
|
|
109
|
+
engagement_types: [row.engagement],
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return [...byProfile.values()];
|
|
113
|
+
}
|
|
114
|
+
async function extractViaLimaData(postUrl, type) {
|
|
115
|
+
const submit = await callApi('POST', '/limadata/batch/post-engagements', { urls: [postUrl] });
|
|
116
|
+
if (!submit.ok) {
|
|
117
|
+
return { ok: false, error: extractErrorMessage(submit.data) ?? `Fallback provider failed to start (status ${submit.status})` };
|
|
118
|
+
}
|
|
119
|
+
const batchId = submit.data.batch_id;
|
|
120
|
+
if (batchId === undefined)
|
|
121
|
+
return { ok: false, error: 'Fallback provider did not return a batch id' };
|
|
122
|
+
const creditsCharged = Number(submit.headers['x-coldiq-credits-charged']);
|
|
123
|
+
const timeoutMs = fallbackTimeoutMs();
|
|
124
|
+
const deadline = Date.now() + timeoutMs;
|
|
125
|
+
while (Date.now() < deadline) {
|
|
126
|
+
await sleep(fallbackPollMs());
|
|
127
|
+
const poll = await callApi('POST', '/limadata/batch/results', { batch_id: String(batchId) });
|
|
128
|
+
if (!poll.ok)
|
|
129
|
+
continue;
|
|
130
|
+
const body = poll.data;
|
|
131
|
+
const item = body.items?.[0];
|
|
132
|
+
if (!item || String(item.status).toLowerCase() !== 'completed')
|
|
133
|
+
continue;
|
|
134
|
+
return {
|
|
135
|
+
ok: true,
|
|
136
|
+
people: limaEngagersToPeople(item.data, type),
|
|
137
|
+
creditsCharged: Number.isFinite(creditsCharged) ? creditsCharged : undefined,
|
|
138
|
+
batchId,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return { ok: false, error: `Fallback provider did not finish within ${Math.round(timeoutMs / 1000)}s`, batchId };
|
|
142
|
+
}
|
|
24
143
|
function errorResult(error, extra) {
|
|
25
144
|
return {
|
|
26
145
|
content: [{ type: 'text', text: JSON.stringify({ error, ...extra }) }],
|
|
@@ -34,10 +153,43 @@ function extractErrorMessage(data) {
|
|
|
34
153
|
}
|
|
35
154
|
return undefined;
|
|
36
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Try the fallback provider after the primary failed; if it also fails, report
|
|
158
|
+
* the ORIGINAL failure (that is the one the caller can act on) with the
|
|
159
|
+
* fallback's outcome attached.
|
|
160
|
+
*
|
|
161
|
+
* Set COLDIQ_ENGAGEMENT_FALLBACK=0 to disable — the fallback is a second billable
|
|
162
|
+
* provider, so anyone running to a strict budget must be able to opt out.
|
|
163
|
+
*/
|
|
164
|
+
async function fallbackOr(postUrl, type, primaryError, extra) {
|
|
165
|
+
if (process.env.COLDIQ_ENGAGEMENT_FALLBACK === '0') {
|
|
166
|
+
return errorResult(primaryError, { post_url: postUrl, ...extra });
|
|
167
|
+
}
|
|
168
|
+
const fb = await extractViaLimaData(postUrl, type);
|
|
169
|
+
if (!fb.ok) {
|
|
170
|
+
return errorResult(primaryError, { post_url: postUrl, ...extra, fallback_error: fb.error });
|
|
171
|
+
}
|
|
172
|
+
const meta = { provider: 'limadata', primary_error: primaryError };
|
|
173
|
+
if (fb.creditsCharged !== undefined)
|
|
174
|
+
meta.credits_charged = fb.creditsCharged;
|
|
175
|
+
return {
|
|
176
|
+
content: [{
|
|
177
|
+
type: 'text',
|
|
178
|
+
text: JSON.stringify({
|
|
179
|
+
data: { post_url: postUrl, type, people: fb.people, count: fb.people.length },
|
|
180
|
+
// Say plainly that these records are thinner than the primary's, so the
|
|
181
|
+
// caller knows to run enrichment before treating them as contacts.
|
|
182
|
+
_meta: {
|
|
183
|
+
...meta,
|
|
184
|
+
note: 'Served by the fallback provider after the primary failed. These records carry name, profile URL and headline only — no work email or company data. Run enrich_person / find_email on them if you need contact details.',
|
|
185
|
+
},
|
|
186
|
+
}),
|
|
187
|
+
}],
|
|
188
|
+
};
|
|
189
|
+
}
|
|
37
190
|
export async function extractPostEngagementHandler(input) {
|
|
38
191
|
const postUrl = input.post_url;
|
|
39
192
|
const type = input.type ?? 'both';
|
|
40
|
-
const includeReplies = input.include_replies;
|
|
41
193
|
const dataTypes = type === 'comments' ? ['comment'] : type === 'reactions' ? ['reaction'] : ['comment', 'reaction'];
|
|
42
194
|
// Step 1 — create the extraction task. Billing happens here.
|
|
43
195
|
const createRes = await callApi('POST', '/jungler/workbooks', {
|
|
@@ -45,20 +197,26 @@ export async function extractPostEngagementHandler(input) {
|
|
|
45
197
|
data_types: dataTypes,
|
|
46
198
|
});
|
|
47
199
|
if (!createRes.ok) {
|
|
48
|
-
return
|
|
200
|
+
return fallbackOr(postUrl, type, extractErrorMessage(createRes.data) ?? `Failed to start extraction (status ${createRes.status})`);
|
|
49
201
|
}
|
|
50
202
|
const createData = createRes.data;
|
|
51
203
|
const taskId = createData.task_id;
|
|
52
204
|
if (!taskId) {
|
|
53
|
-
return
|
|
205
|
+
return fallbackOr(postUrl, type, 'Extraction job did not return a task id');
|
|
54
206
|
}
|
|
207
|
+
// Kept so a timeout can still hand the caller a way to collect what they paid
|
|
208
|
+
// for — the workbook stays readable upstream for 12 hours.
|
|
209
|
+
const createWorkbookId = createData.workbook_id;
|
|
55
210
|
// Credit headers are emitted on the create call (the only billed step).
|
|
56
211
|
const creditsCharged = Number(createRes.headers['x-coldiq-credits-charged']);
|
|
57
212
|
const creditsRemaining = Number(createRes.headers['x-coldiq-credits-remaining']);
|
|
58
213
|
// Step 2 — poll task status until it resolves. The status endpoint is free, so
|
|
59
214
|
// polling does not bill; only the create call above charged credits.
|
|
60
|
-
|
|
61
|
-
|
|
215
|
+
// Upstream quotes 1-3 minutes and explicitly warns that large posts (1000+
|
|
216
|
+
// interactions) take longer — which is exactly the viral post this tool is for.
|
|
217
|
+
// A 180s deadline cut those off mid-extraction and reported a bogus timeout.
|
|
218
|
+
const pollIntervalMs = parseInt(process.env.COLDIQ_ENGAGEMENT_POLL_MS ?? '5000', 10);
|
|
219
|
+
const timeoutMs = parseInt(process.env.COLDIQ_ENGAGEMENT_TIMEOUT_MS ?? '600000', 10);
|
|
62
220
|
const maxPollErrors = 3;
|
|
63
221
|
const deadline = Date.now() + timeoutMs;
|
|
64
222
|
let workbookId;
|
|
@@ -74,41 +232,67 @@ export async function extractPostEngagementHandler(input) {
|
|
|
74
232
|
continue;
|
|
75
233
|
}
|
|
76
234
|
consecutivePollErrors = 0;
|
|
77
|
-
const
|
|
235
|
+
const statusData = statusRes.data;
|
|
236
|
+
const status = statusData.status;
|
|
78
237
|
if (status === 'success') {
|
|
79
|
-
|
|
238
|
+
// A credits-exhausted run is terminal but collected little or nothing
|
|
239
|
+
// because OUR provider account ran dry — the caller's request is sound, so
|
|
240
|
+
// route it to the fallback rather than handing back a hollow result. This
|
|
241
|
+
// charge is refunded server-side.
|
|
242
|
+
if (statusData.credits_exhausted) {
|
|
243
|
+
return fallbackOr(postUrl, type, 'Engagement extraction stopped early — the data provider account is out of credits (this request was refunded)', { task_id: taskId });
|
|
244
|
+
}
|
|
245
|
+
workbookId = statusData.workbook_id;
|
|
80
246
|
break;
|
|
81
247
|
}
|
|
82
248
|
if (status === 'failure') {
|
|
83
|
-
|
|
249
|
+
// The status route refunds the create charge when a run reaches failure,
|
|
250
|
+
// so the user is made whole — say so rather than leaving them to wonder.
|
|
251
|
+
return fallbackOr(postUrl, type, 'Engagement extraction failed upstream — the post may be private, deleted, or have no engagement. The credits for this task have been refunded.', { task_id: taskId });
|
|
84
252
|
}
|
|
85
253
|
}
|
|
86
254
|
if (!workbookId) {
|
|
87
|
-
|
|
255
|
+
// Giving up here does NOT cancel the run, and the create call was already
|
|
256
|
+
// billed. Never drop that on the floor: hand back the ids so the caller can
|
|
257
|
+
// collect the results (upstream keeps the workbook for 12 hours) instead of
|
|
258
|
+
// paying again for a re-run that is probably still in flight.
|
|
259
|
+
return errorResult(`Engagement extraction is still running after ${Math.round(timeoutMs / 1000)}s. It has NOT been cancelled and no re-run is needed — poll GET /v1/jungler/tasks/${taskId}/status until it reports success, then fetch the people from GET /v1/jungler/workbooks/${createWorkbookId ?? '{workbook_id}'}/contacts. Results stay available for 12 hours after the task was created.`, { post_url: postUrl, task_id: taskId, workbook_id: createWorkbookId, status: 'running' });
|
|
88
260
|
}
|
|
89
261
|
// Step 3 — fetch the deduplicated people. activity_filter narrows to commenters
|
|
90
262
|
// or reactors; omitted for "both" so the upstream returns all unique contacts.
|
|
91
|
-
|
|
263
|
+
// Contacts are paginated, and a viral post — the case this tool exists for —
|
|
264
|
+
// routinely exceeds one page, so walk every page rather than truncating to the
|
|
265
|
+
// first. Reads are free, so pagination costs the caller nothing.
|
|
266
|
+
const queryParams = { page_size: String(CONTACTS_PAGE_SIZE) };
|
|
92
267
|
if (type === 'comments')
|
|
93
268
|
queryParams.activity_filter = 'commenters';
|
|
94
269
|
else if (type === 'reactions')
|
|
95
270
|
queryParams.activity_filter = 'reactors';
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
271
|
+
const people = [];
|
|
272
|
+
let totalContacts;
|
|
273
|
+
for (let page = 1; page <= MAX_CONTACT_PAGES; page++) {
|
|
274
|
+
const contactsRes = await callApi('GET', `/jungler/workbooks/${workbookId}/contacts`, undefined, { ...queryParams, page: String(page) });
|
|
275
|
+
if (!contactsRes.ok) {
|
|
276
|
+
return errorResult(extractErrorMessage(contactsRes.data) ?? 'Failed to fetch extracted people', { post_url: postUrl, task_id: taskId, workbook_id: workbookId });
|
|
277
|
+
}
|
|
278
|
+
const { items, total, pages } = readContactsPage(contactsRes.data);
|
|
279
|
+
people.push(...items.filter(engaged));
|
|
280
|
+
totalContacts = total;
|
|
281
|
+
if (items.length === 0 || (pages !== undefined && page >= pages))
|
|
282
|
+
break;
|
|
101
283
|
}
|
|
102
284
|
const meta = {};
|
|
103
285
|
if (Number.isFinite(creditsCharged))
|
|
104
286
|
meta.credits_charged = creditsCharged;
|
|
105
287
|
if (Number.isFinite(creditsRemaining))
|
|
106
288
|
meta.credits_remaining = creditsRemaining;
|
|
289
|
+
if (totalContacts !== undefined && totalContacts > people.length)
|
|
290
|
+
meta.truncated_from = totalContacts;
|
|
107
291
|
return {
|
|
108
292
|
content: [{
|
|
109
293
|
type: 'text',
|
|
110
294
|
text: JSON.stringify({
|
|
111
|
-
data: { post_url: postUrl, type, people:
|
|
295
|
+
data: { post_url: postUrl, type, people, count: people.length },
|
|
112
296
|
_meta: meta,
|
|
113
297
|
}),
|
|
114
298
|
}],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract-post-engagement.js","sourceRoot":"","sources":["../../src/tools/extract-post-engagement.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extract-post-engagement.js","sourceRoot":"","sources":["../../src/tools/extract-post-engagement.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ export declare const getEndpointDetailsDescription: string;
|
|
|
4
4
|
export declare const getEndpointDetailsSchema: {
|
|
5
5
|
api: z.ZodString;
|
|
6
6
|
path: z.ZodString;
|
|
7
|
+
method: z.ZodOptional<z.ZodEnum<["GET", "POST", "PUT", "PATCH", "DELETE"]>>;
|
|
7
8
|
};
|
|
8
9
|
export declare function getEndpointDetailsHandler(input: Record<string, unknown>): Promise<{
|
|
9
10
|
content: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-endpoint-details.d.ts","sourceRoot":"","sources":["../../src/tools/get-endpoint-details.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,sBAAsB,yBAAyB,CAAA;AAE5D,eAAO,MAAM,6BAA6B,QAGV,CAAA;AAEhC,eAAO,MAAM,wBAAwB
|
|
1
|
+
{"version":3,"file":"get-endpoint-details.d.ts","sourceRoot":"","sources":["../../src/tools/get-endpoint-details.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,sBAAsB,yBAAyB,CAAA;AAE5D,eAAO,MAAM,6BAA6B,QAGV,CAAA;AAEhC,eAAO,MAAM,wBAAwB;;;;CAKpC,CAAA;AAED,wBAAsB,yBAAyB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;GAS7E"}
|
|
@@ -7,9 +7,11 @@ export const getEndpointDetailsDescription = 'Get the real request schema, param
|
|
|
7
7
|
export const getEndpointDetailsSchema = {
|
|
8
8
|
api: z.string().describe('Provider key from search_endpoints, e.g. "coldiq" (Lima Data), "apollo", or "exa".'),
|
|
9
9
|
path: z.string().describe('Endpoint path without the /v1 prefix, e.g. "/limadata/prospect/people/filter".'),
|
|
10
|
+
method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']).optional()
|
|
11
|
+
.describe('HTTP method from search_endpoints. Set this when one path supports more than one method.'),
|
|
10
12
|
};
|
|
11
13
|
export async function getEndpointDetailsHandler(input) {
|
|
12
|
-
const res = await callApi('POST', '/endpoints/details', { api: input.api, path: input.path });
|
|
14
|
+
const res = await callApi('POST', '/endpoints/details', { api: input.api, path: input.path, method: input.method });
|
|
13
15
|
if (!res.ok) {
|
|
14
16
|
return {
|
|
15
17
|
content: [{ type: 'text', text: JSON.stringify({ error: 'Endpoint not found or details unavailable', status: res.status, data: res.data }) }],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-endpoint-details.js","sourceRoot":"","sources":["../../src/tools/get-endpoint-details.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,CAAC,MAAM,sBAAsB,GAAG,sBAAsB,CAAA;AAE5D,MAAM,CAAC,MAAM,6BAA6B,GACxC,6GAA6G;IAC7G,uGAAuG;IACvG,8BAA8B,CAAA;AAEhC,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oFAAoF,CAAC;IAC9G,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gFAAgF,CAAC;
|
|
1
|
+
{"version":3,"file":"get-endpoint-details.js","sourceRoot":"","sources":["../../src/tools/get-endpoint-details.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,CAAC,MAAM,sBAAsB,GAAG,sBAAsB,CAAA;AAE5D,MAAM,CAAC,MAAM,6BAA6B,GACxC,6GAA6G;IAC7G,uGAAuG;IACvG,8BAA8B,CAAA;AAEhC,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oFAAoF,CAAC;IAC9G,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gFAAgF,CAAC;IAC3G,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE;SACjE,QAAQ,CAAC,0FAA0F,CAAC;CACxG,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,KAA8B;IAC5E,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,oBAAoB,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;IACnH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,2CAA2C,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YACtJ,OAAO,EAAE,IAAI;SACd,CAAA;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAA;AACjF,CAAC"}
|
|
@@ -5,7 +5,7 @@ export declare const searchWebSchema: {
|
|
|
5
5
|
query: z.ZodString;
|
|
6
6
|
num_results: z.ZodDefault<z.ZodNumber>;
|
|
7
7
|
country: z.ZodOptional<z.ZodString>;
|
|
8
|
-
search_type: z.ZodDefault<z.ZodEnum<["general", "neural"]>>;
|
|
8
|
+
search_type: z.ZodDefault<z.ZodEnum<["general", "neural", "deep", "deep-reasoning"]>>;
|
|
9
9
|
use_providers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
10
10
|
};
|
|
11
11
|
export declare function searchWebHandler(input: Record<string, unknown>): Promise<{
|
package/dist/tools/search-web.js
CHANGED
|
@@ -2,7 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { callVerb } from '../verb-client.js';
|
|
3
3
|
import { getProvidersForCapability } from '../utils/provider-resolver.js';
|
|
4
4
|
export const searchWebName = 'search_web';
|
|
5
|
-
export const searchWebDescription = 'Search the web for market research, company news, or general lookups. Supports Google search (default)
|
|
5
|
+
export const searchWebDescription = 'Search the web for market research, company news, or general lookups. Supports Google search (default), Exa auto through the neural compatibility alias, and Exa deep modes. ' +
|
|
6
6
|
'NEVER use this to find, verify, or look up people, contacts, LinkedIn profiles, or executives — even as a fallback when find_people returns uncertain results. ' +
|
|
7
7
|
'find_people is the only tool for people lookups; do not supplement or replace it with web search. ' +
|
|
8
8
|
'ColdIQ automatically picks the best provider — pass use_providers only if you need a specific tool.';
|
|
@@ -10,7 +10,7 @@ export const searchWebSchema = {
|
|
|
10
10
|
query: z.string().describe('Search query'),
|
|
11
11
|
num_results: z.number().min(1).max(100).default(10).describe('Number of results (default: 10, max: 100)'),
|
|
12
12
|
country: z.string().optional().describe('Country code for geo-targeting (e.g. "us", "fr")'),
|
|
13
|
-
search_type: z.enum(['general', 'neural']).default('general').describe('"general" for
|
|
13
|
+
search_type: z.enum(['general', 'neural', 'deep', 'deep-reasoning']).default('general').describe('"general" for the default web search, "neural" for Exa auto compatibility, or an Exa deep mode'),
|
|
14
14
|
use_providers: z.array(z.string()).optional().describe(`Optional ordered list of providers to use. Leave empty to let ColdIQ automatically pick the best tool for your inputs — recommended for most use cases. Available providers: ${getProvidersForCapability('search_web').join(', ')}. Provider names are matched fuzzily, so minor typos are tolerated.`),
|
|
15
15
|
};
|
|
16
16
|
export async function searchWebHandler(input) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-web.js","sourceRoot":"","sources":["../../src/tools/search-web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAA;AAEzE,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAA;AAEzC,MAAM,CAAC,MAAM,oBAAoB,GAC/B
|
|
1
|
+
{"version":3,"file":"search-web.js","sourceRoot":"","sources":["../../src/tools/search-web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAA;AAEzE,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAA;AAEzC,MAAM,CAAC,MAAM,oBAAoB,GAC/B,+KAA+K;IAC/K,iKAAiK;IACjK,oGAAoG;IACpG,qGAAqG,CAAA;AAEvG,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;IAC1C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,2CAA2C,CAAC;IACzG,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC;IAC3F,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,gGAAgG,CAAC;IAClM,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gLAAgL,yBAAyB,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,qEAAqE,CAAC;CAChW,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAA8B;IACnE,OAAO,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,CAAA;AACvC,CAAC"}
|
package/package.json
CHANGED
package/src/executor.ts
CHANGED
|
@@ -261,7 +261,7 @@ export async function executeWithFallback(
|
|
|
261
261
|
|
|
262
262
|
let allProviders =
|
|
263
263
|
capability === 'search_web'
|
|
264
|
-
? getSearchWebProviders(input.search_type
|
|
264
|
+
? getSearchWebProviders(input.search_type !== undefined && input.search_type !== 'general')
|
|
265
265
|
: getProviders(capability)
|
|
266
266
|
|
|
267
267
|
// When the caller pinned specific providers, filter to those in order.
|
package/src/registry.ts
CHANGED
|
@@ -71,6 +71,27 @@ function isNonEmptyArray(v: unknown): boolean {
|
|
|
71
71
|
return Array.isArray(v) && v.length > 0
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
// Keep this standalone-package mirror in sync with
|
|
75
|
+
// src/providers/icypeas/reverse-email-classify.ts.
|
|
76
|
+
function isIcypeasReverseEmailFound(body: unknown): boolean {
|
|
77
|
+
if (!body || typeof body !== 'object' || Array.isArray(body)) return false
|
|
78
|
+
const response = body as Record<string, unknown>
|
|
79
|
+
const status = typeof response.status === 'string' ? response.status : ''
|
|
80
|
+
if (status !== 'FOUND' && status !== 'DEBITED') return false
|
|
81
|
+
if (response.success !== true || typeof response.results !== 'string') return false
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const url = new URL(response.results)
|
|
85
|
+
const hostname = url.hostname.toLowerCase()
|
|
86
|
+
const isLinkedInHost = hostname === 'linkedin.com' || hostname.endsWith('.linkedin.com')
|
|
87
|
+
return (url.protocol === 'http:' || url.protocol === 'https:')
|
|
88
|
+
&& isLinkedInHost
|
|
89
|
+
&& url.pathname.startsWith('/in/')
|
|
90
|
+
} catch {
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
74
95
|
// TheirStack attaches a per-job `company_object` whose enrichment arrays dominate the
|
|
75
96
|
// payload (e.g. ~1,600-element technology_slugs/technology_names, plus long_description) —
|
|
76
97
|
// tens of KB per job. Drop these heavy fields while keeping company identity (name, domain,
|
|
@@ -2295,7 +2316,9 @@ const searchWebProviders: ProviderEntry[] = [
|
|
|
2295
2316
|
body: {
|
|
2296
2317
|
query: input.query,
|
|
2297
2318
|
numResults: input.num_results ?? 10,
|
|
2298
|
-
type: input.search_type === '
|
|
2319
|
+
type: input.search_type === 'deep' || input.search_type === 'deep-reasoning'
|
|
2320
|
+
? input.search_type
|
|
2321
|
+
: 'auto',
|
|
2299
2322
|
},
|
|
2300
2323
|
}),
|
|
2301
2324
|
hasResult: (data) => {
|
|
@@ -3410,10 +3433,7 @@ const enrichPersonProviders: ProviderEntry[] = [
|
|
|
3410
3433
|
priority: 11,
|
|
3411
3434
|
isApplicable: (input) => typeof input.email === 'string' && (input.email as string).includes('@'),
|
|
3412
3435
|
mapParams: (input) => ({ body: { email: input.email } }),
|
|
3413
|
-
hasResult:
|
|
3414
|
-
const d = data as Record<string, unknown>
|
|
3415
|
-
return isNonEmptyArray(d.profiles) || (d.success === true && !!d.data)
|
|
3416
|
-
},
|
|
3436
|
+
hasResult: isIcypeasReverseEmailFound,
|
|
3417
3437
|
},
|
|
3418
3438
|
{
|
|
3419
3439
|
id: 'pdl-person-identify',
|
|
@@ -13,6 +13,8 @@ export const callEndpointDescription =
|
|
|
13
13
|
export const callEndpointSchema = {
|
|
14
14
|
api: z.string().describe('Provider key from search_endpoints / get_endpoint_details, e.g. "coldiq".'),
|
|
15
15
|
path: z.string().describe('Endpoint path without the /v1 prefix, e.g. "/limadata/prospect/people/filter".'),
|
|
16
|
+
method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']).optional()
|
|
17
|
+
.describe('HTTP method from search_endpoints. Set this when one path supports more than one method.'),
|
|
16
18
|
params: z
|
|
17
19
|
.record(z.unknown())
|
|
18
20
|
.optional()
|
|
@@ -20,7 +22,7 @@ export const callEndpointSchema = {
|
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export async function callEndpointHandler(input: Record<string, unknown>) {
|
|
23
|
-
const res = await callApi('POST', '/endpoints/use', { api: input.api, path: input.path, params: input.params })
|
|
25
|
+
const res = await callApi('POST', '/endpoints/use', { api: input.api, path: input.path, method: input.method, params: input.params })
|
|
24
26
|
if (!res.ok) {
|
|
25
27
|
return {
|
|
26
28
|
content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Endpoint call failed', status: res.status, data: res.data }) }],
|