@coldiq/mcp 0.5.1 → 0.5.3
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 +65 -7
- 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/find-signals.js +4 -4
- package/dist/tools/find-signals.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 +58 -6
- package/src/tools/call-endpoint.ts +3 -1
- package/src/tools/find-signals.ts +4 -4
- 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-find-signals.test.ts +2 -2
- 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/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"}
|
|
@@ -7,7 +7,7 @@ export const findSignalsDescription = 'Retrieve sales intelligence signals — f
|
|
|
7
7
|
'Company-targeted (funding | acquisition | hiring | job_change | intent): accepts companies/domains/industries/countries/since filters. ' +
|
|
8
8
|
'funding additionally accepts `round_type` (e.g. ["Series A", "Seed"]). ' +
|
|
9
9
|
'intent has two modes: (a) DISCOVERY — pass `topics` (e.g. ["sales-automation"]) with no companies/domains to find companies showing intent on those topics; (b) VERIFY — pass companies/domains to check intent on known companies. Requires topics OR companies/domains. ' +
|
|
10
|
-
'Feed-style
|
|
10
|
+
'Feed-style: news accepts country only; startup_post accepts country and since. Neither filters by company or domain. ' +
|
|
11
11
|
'hiring returns individual job postings with company context (title, location, descriptionText, company industries) — for richer job-board queries with description/seniority/easy-apply filters use search_jobs instead.';
|
|
12
12
|
export const findSignalsSchema = {
|
|
13
13
|
signal_type: z
|
|
@@ -15,7 +15,7 @@ export const findSignalsSchema = {
|
|
|
15
15
|
.describe('Signal type to retrieve. ' +
|
|
16
16
|
'Company-targeted: "funding" (fundraising rounds), "acquisition" (M&A), "hiring" (individual job postings indexed by Signalbase, with company context), ' +
|
|
17
17
|
'"job_change" (people who recently changed roles), "intent" (companies showing buying intent — discover by `topics` or verify on known companies/domains). ' +
|
|
18
|
-
'Feed-style
|
|
18
|
+
'Feed-style: "news" (country filter only), "startup_post" (Product Hunt, Hacker News, etc.)'),
|
|
19
19
|
companies: z
|
|
20
20
|
.array(z.string())
|
|
21
21
|
.optional()
|
|
@@ -23,11 +23,11 @@ export const findSignalsSchema = {
|
|
|
23
23
|
domains: z
|
|
24
24
|
.array(z.string())
|
|
25
25
|
.optional()
|
|
26
|
-
.describe('Company domains to filter signals for (e.g. ["coldiq.com"]). Used by
|
|
26
|
+
.describe('Company domains to filter signals for (e.g. ["coldiq.com"]). Used by hiring and intent. For intent DISCOVERY mode: omit domains and pass topics instead. News and startup_post do not support domain filtering.'),
|
|
27
27
|
since: z
|
|
28
28
|
.string()
|
|
29
29
|
.optional()
|
|
30
|
-
.describe('Return signals after this date. ISO date format, e.g. "2026-01-01". Honored by funding, acquisition, hiring, job_change, and startup_post.
|
|
30
|
+
.describe('Return signals after this date. ISO date format, e.g. "2026-01-01". Honored by funding, acquisition, hiring, job_change, and startup_post. PredictLeads news discovery has no date filter.'),
|
|
31
31
|
industries: z
|
|
32
32
|
.array(z.string())
|
|
33
33
|
.optional()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-signals.js","sourceRoot":"","sources":["../../src/tools/find-signals.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,eAAe,GAAG,cAAc,CAAA;AAE7C,MAAM,CAAC,MAAM,sBAAsB,GACjC,4IAA4I;IAC5I,gDAAgD;IAChD,yIAAyI;IACzI,yEAAyE;IACzE,4QAA4Q;IAC5Q,
|
|
1
|
+
{"version":3,"file":"find-signals.js","sourceRoot":"","sources":["../../src/tools/find-signals.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,eAAe,GAAG,cAAc,CAAA;AAE7C,MAAM,CAAC,MAAM,sBAAsB,GACjC,4IAA4I;IAC5I,gDAAgD;IAChD,yIAAyI;IACzI,yEAAyE;IACzE,4QAA4Q;IAC5Q,uHAAuH;IACvH,0NAA0N,CAAA;AAE5N,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,WAAW,EAAE,CAAC;SACX,IAAI,CAAC,CAAC,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;SAC1F,QAAQ,CACP,2BAA2B;QAC3B,yJAAyJ;QACzJ,4JAA4J;QAC5J,4FAA4F,CAC7F;IACH,SAAS,EAAE,CAAC;SACT,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CAAC,4YAA4Y,CAAC;IACzZ,OAAO,EAAE,CAAC;SACP,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CAAC,iNAAiN,CAAC;IAC9N,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,4LAA4L,CAAC;IACzM,UAAU,EAAE,CAAC;SACV,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CAAC,6hBAA6hB,CAAC;IAC1iB,SAAS,EAAE,CAAC;SACT,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CAAC,0FAA0F,CAAC;IACvG,UAAU,EAAE,CAAC;SACV,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CAAC,6RAA6R,CAAC;IAC1S,MAAM,EAAE,CAAC;SACN,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CAAC,6bAA6b,CAAC;IAC1c,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,OAAO,CAAC,EAAE,CAAC;SACX,QAAQ,CAAC,8CAA8C,CAAC;IAC3D,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gLAAgL,yBAAyB,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,qEAAqE,CAAC;CAClW,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAA8B;IACrE,OAAO,QAAQ,CAAC,eAAe,EAAE,KAAK,CAAC,CAAA;AACzC,CAAC"}
|
|
@@ -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',
|
|
@@ -3442,6 +3462,36 @@ const enrichPersonProviders: ProviderEntry[] = [
|
|
|
3442
3462
|
// find_signals
|
|
3443
3463
|
// ---------------------------------------------------------------------------
|
|
3444
3464
|
|
|
3465
|
+
const PREDICTLEADS_COUNTRY_NAMES: Record<string, string> = {
|
|
3466
|
+
US: 'United States', GB: 'United Kingdom', UK: 'United Kingdom', CA: 'Canada',
|
|
3467
|
+
AU: 'Australia', DE: 'Germany', FR: 'France', NL: 'Netherlands', IN: 'India',
|
|
3468
|
+
SG: 'Singapore', JP: 'Japan', BR: 'Brazil', MX: 'Mexico', ZA: 'South Africa',
|
|
3469
|
+
}
|
|
3470
|
+
|
|
3471
|
+
function predictLeadsCompanyLocation(countries: unknown): string | undefined {
|
|
3472
|
+
if (!isNonEmptyArray(countries)) return undefined
|
|
3473
|
+
const value = String((countries as string[])[0]).trim()
|
|
3474
|
+
if (!value) return undefined
|
|
3475
|
+
return value.length > 3 ? value : PREDICTLEADS_COUNTRY_NAMES[value.toUpperCase()]
|
|
3476
|
+
}
|
|
3477
|
+
|
|
3478
|
+
function truncatePredictLeadsNews(data: unknown): unknown {
|
|
3479
|
+
if (!data || typeof data !== 'object') return data
|
|
3480
|
+
const value = data as Record<string, unknown>
|
|
3481
|
+
if (!Array.isArray(value.included)) return data
|
|
3482
|
+
return {
|
|
3483
|
+
...value,
|
|
3484
|
+
included: value.included.map((item) => {
|
|
3485
|
+
if (!item || typeof item !== 'object') return item
|
|
3486
|
+
const attributes = (item as Record<string, unknown>).attributes
|
|
3487
|
+
if (!attributes || typeof attributes !== 'object') return item
|
|
3488
|
+
const body = (attributes as Record<string, unknown>).body
|
|
3489
|
+
if (typeof body !== 'string' || body.length <= 500) return item
|
|
3490
|
+
return { ...item as Record<string, unknown>, attributes: { ...attributes, body: `${body.slice(0, 500)}…`, body_truncated: true } }
|
|
3491
|
+
}),
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3494
|
+
|
|
3445
3495
|
const findSignalsProviders: ProviderEntry[] = [
|
|
3446
3496
|
{
|
|
3447
3497
|
id: 'signalbase-funding',
|
|
@@ -3647,11 +3697,13 @@ const findSignalsProviders: ProviderEntry[] = [
|
|
|
3647
3697
|
isApplicable: (input) => input.signal_type === 'news',
|
|
3648
3698
|
mapParams: (input) => {
|
|
3649
3699
|
const qp: Record<string, string> = {}
|
|
3650
|
-
|
|
3700
|
+
const location = predictLeadsCompanyLocation(input.countries)
|
|
3701
|
+
if (location) qp.company_location = location
|
|
3651
3702
|
qp.limit = String(Math.min((input.limit as number | undefined) ?? 25, 100))
|
|
3652
3703
|
return { queryParams: qp }
|
|
3653
3704
|
},
|
|
3654
3705
|
hasResult: (data) => isNonEmptyArray((data as Record<string, unknown>).data),
|
|
3706
|
+
postFilter: (data) => truncatePredictLeadsNews(data),
|
|
3655
3707
|
},
|
|
3656
3708
|
{
|
|
3657
3709
|
id: 'predictleads-startup-posts',
|
|
@@ -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 }) }],
|
|
@@ -10,7 +10,7 @@ export const findSignalsDescription =
|
|
|
10
10
|
'Company-targeted (funding | acquisition | hiring | job_change | intent): accepts companies/domains/industries/countries/since filters. ' +
|
|
11
11
|
'funding additionally accepts `round_type` (e.g. ["Series A", "Seed"]). ' +
|
|
12
12
|
'intent has two modes: (a) DISCOVERY — pass `topics` (e.g. ["sales-automation"]) with no companies/domains to find companies showing intent on those topics; (b) VERIFY — pass companies/domains to check intent on known companies. Requires topics OR companies/domains. ' +
|
|
13
|
-
'Feed-style
|
|
13
|
+
'Feed-style: news accepts country only; startup_post accepts country and since. Neither filters by company or domain. ' +
|
|
14
14
|
'hiring returns individual job postings with company context (title, location, descriptionText, company industries) — for richer job-board queries with description/seniority/easy-apply filters use search_jobs instead.'
|
|
15
15
|
|
|
16
16
|
export const findSignalsSchema = {
|
|
@@ -20,7 +20,7 @@ export const findSignalsSchema = {
|
|
|
20
20
|
'Signal type to retrieve. ' +
|
|
21
21
|
'Company-targeted: "funding" (fundraising rounds), "acquisition" (M&A), "hiring" (individual job postings indexed by Signalbase, with company context), ' +
|
|
22
22
|
'"job_change" (people who recently changed roles), "intent" (companies showing buying intent — discover by `topics` or verify on known companies/domains). ' +
|
|
23
|
-
'Feed-style
|
|
23
|
+
'Feed-style: "news" (country filter only), "startup_post" (Product Hunt, Hacker News, etc.)'
|
|
24
24
|
),
|
|
25
25
|
companies: z
|
|
26
26
|
.array(z.string())
|
|
@@ -29,11 +29,11 @@ export const findSignalsSchema = {
|
|
|
29
29
|
domains: z
|
|
30
30
|
.array(z.string())
|
|
31
31
|
.optional()
|
|
32
|
-
.describe('Company domains to filter signals for (e.g. ["coldiq.com"]). Used by
|
|
32
|
+
.describe('Company domains to filter signals for (e.g. ["coldiq.com"]). Used by hiring and intent. For intent DISCOVERY mode: omit domains and pass topics instead. News and startup_post do not support domain filtering.'),
|
|
33
33
|
since: z
|
|
34
34
|
.string()
|
|
35
35
|
.optional()
|
|
36
|
-
.describe('Return signals after this date. ISO date format, e.g. "2026-01-01". Honored by funding, acquisition, hiring, job_change, and startup_post.
|
|
36
|
+
.describe('Return signals after this date. ISO date format, e.g. "2026-01-01". Honored by funding, acquisition, hiring, job_change, and startup_post. PredictLeads news discovery has no date filter.'),
|
|
37
37
|
industries: z
|
|
38
38
|
.array(z.string())
|
|
39
39
|
.optional()
|
|
@@ -11,10 +11,12 @@ export const getEndpointDetailsDescription =
|
|
|
11
11
|
export const getEndpointDetailsSchema = {
|
|
12
12
|
api: z.string().describe('Provider key from search_endpoints, e.g. "coldiq" (Lima Data), "apollo", or "exa".'),
|
|
13
13
|
path: z.string().describe('Endpoint path without the /v1 prefix, e.g. "/limadata/prospect/people/filter".'),
|
|
14
|
+
method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']).optional()
|
|
15
|
+
.describe('HTTP method from search_endpoints. Set this when one path supports more than one method.'),
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
export async function getEndpointDetailsHandler(input: Record<string, unknown>) {
|
|
17
|
-
const res = await callApi('POST', '/endpoints/details', { api: input.api, path: input.path })
|
|
19
|
+
const res = await callApi('POST', '/endpoints/details', { api: input.api, path: input.path, method: input.method })
|
|
18
20
|
if (!res.ok) {
|
|
19
21
|
return {
|
|
20
22
|
content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Endpoint not found or details unavailable', status: res.status, data: res.data }) }],
|
package/src/tools/search-web.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { getProvidersForCapability } from '../utils/provider-resolver.js'
|
|
|
5
5
|
export const searchWebName = 'search_web'
|
|
6
6
|
|
|
7
7
|
export const searchWebDescription =
|
|
8
|
-
'Search the web for market research, company news, or general lookups. Supports Google search (default)
|
|
8
|
+
'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. ' +
|
|
9
9
|
'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. ' +
|
|
10
10
|
'find_people is the only tool for people lookups; do not supplement or replace it with web search. ' +
|
|
11
11
|
'ColdIQ automatically picks the best provider — pass use_providers only if you need a specific tool.'
|
|
@@ -14,7 +14,7 @@ export const searchWebSchema = {
|
|
|
14
14
|
query: z.string().describe('Search query'),
|
|
15
15
|
num_results: z.number().min(1).max(100).default(10).describe('Number of results (default: 10, max: 100)'),
|
|
16
16
|
country: z.string().optional().describe('Country code for geo-targeting (e.g. "us", "fr")'),
|
|
17
|
-
search_type: z.enum(['general', 'neural']).default('general').describe('"general" for
|
|
17
|
+
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'),
|
|
18
18
|
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.`),
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -390,20 +390,22 @@ describe('icypeas-reverse-email-lookup', () => {
|
|
|
390
390
|
})
|
|
391
391
|
})
|
|
392
392
|
|
|
393
|
-
it('hasResult: true
|
|
394
|
-
expect(p().hasResult({
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
})
|
|
400
|
-
|
|
401
|
-
it(
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
393
|
+
it('hasResult: true for the documented hit shape', () => {
|
|
394
|
+
expect(p().hasResult({
|
|
395
|
+
success: true,
|
|
396
|
+
status: 'FOUND',
|
|
397
|
+
results: 'https://www.linkedin.com/in/michel-lieben',
|
|
398
|
+
})).toBe(true)
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
it.each([
|
|
402
|
+
{ success: true, status: 'NOT_FOUND', results: 'https://www.linkedin.com/in/michel-lieben' },
|
|
403
|
+
{ success: false, validationErrors: ['Invalid email'] },
|
|
404
|
+
{ success: true },
|
|
405
|
+
{ profiles: [{ name: 'Michel Lieben' }] },
|
|
406
|
+
{ success: true, data: { name: 'Michel Lieben' } },
|
|
407
|
+
])('hasResult: false for a miss, invalid, or unknown body', (body) => {
|
|
408
|
+
expect(p().hasResult(body)).toBe(false)
|
|
407
409
|
})
|
|
408
410
|
})
|
|
409
411
|
|
|
@@ -616,8 +616,8 @@ describe('find_signals priority ordering', () => {
|
|
|
616
616
|
}
|
|
617
617
|
})
|
|
618
618
|
|
|
619
|
-
it('
|
|
620
|
-
expect(providers()
|
|
619
|
+
it('contains only pull-based providers', () => {
|
|
620
|
+
expect(providers().some((provider) => provider.id === 'coldiq-signal-feed')).toBe(false)
|
|
621
621
|
})
|
|
622
622
|
|
|
623
623
|
it('predictleads-startup-posts is last (priority 8)', () => {
|
package/tests/registry.test.ts
CHANGED
|
@@ -20,6 +20,13 @@ const ALL_CAPABILITIES: Capability[] = [
|
|
|
20
20
|
]
|
|
21
21
|
|
|
22
22
|
describe('registry', () => {
|
|
23
|
+
it('maps the neural compatibility alias to Exa auto and preserves deep modes', () => {
|
|
24
|
+
const exa = getConfiguredProviders('search_web').find((provider) => provider.id === 'exa')!
|
|
25
|
+
expect(exa.mapParams({ query: 'ColdIQ', search_type: 'neural' }).body).toMatchObject({ type: 'auto' })
|
|
26
|
+
expect(exa.mapParams({ query: 'ColdIQ', search_type: 'deep' }).body).toMatchObject({ type: 'deep' })
|
|
27
|
+
expect(exa.mapParams({ query: 'ColdIQ', search_type: 'deep-reasoning' }).body).toMatchObject({ type: 'deep-reasoning' })
|
|
28
|
+
})
|
|
29
|
+
|
|
23
30
|
it('every capability has at least one provider', () => {
|
|
24
31
|
for (const cap of ALL_CAPABILITIES) {
|
|
25
32
|
const providers = getProviders(cap)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
import { searchWebSchema } from '../src/tools/search-web.js'
|
|
4
|
+
|
|
5
|
+
const schema = z.object(searchWebSchema)
|
|
6
|
+
|
|
7
|
+
describe('search_web Exa compatibility', () => {
|
|
8
|
+
it.each(['general', 'neural', 'deep', 'deep-reasoning'])('accepts %s', (search_type) => {
|
|
9
|
+
expect(schema.safeParse({ query: 'ColdIQ', search_type }).success).toBe(true)
|
|
10
|
+
})
|
|
11
|
+
})
|
|
@@ -38,4 +38,20 @@ describe('call_endpoint handler', () => {
|
|
|
38
38
|
expect(parsed.status).toBe(404)
|
|
39
39
|
expect(parsed.error).toBe('Endpoint call failed')
|
|
40
40
|
})
|
|
41
|
+
|
|
42
|
+
it('forwards the HTTP method for a shared endpoint path', async () => {
|
|
43
|
+
let capturedBody: unknown
|
|
44
|
+
globalThis.fetch = vi.fn(async (_url: string | URL | Request, opts?: RequestInit) => {
|
|
45
|
+
capturedBody = opts?.body ? JSON.parse(opts.body as string) : undefined
|
|
46
|
+
return new Response(JSON.stringify({ ok: true, status: 201, data: { id: 'run_1' } }), { status: 200 })
|
|
47
|
+
}) as typeof fetch
|
|
48
|
+
|
|
49
|
+
await callEndpointHandler({
|
|
50
|
+
api: 'exa', path: '/exa/agent/runs', method: 'POST', params: { query: 'Research ColdIQ' },
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
expect(capturedBody).toEqual({
|
|
54
|
+
api: 'exa', path: '/exa/agent/runs', method: 'POST', params: { query: 'Research ColdIQ' },
|
|
55
|
+
})
|
|
56
|
+
})
|
|
41
57
|
})
|
|
@@ -34,4 +34,16 @@ describe('get_endpoint_details handler', () => {
|
|
|
34
34
|
expect(parsed.status).toBe(404)
|
|
35
35
|
expect(parsed.error).toBe('Endpoint not found or details unavailable')
|
|
36
36
|
})
|
|
37
|
+
|
|
38
|
+
it('forwards the HTTP method for a shared endpoint path', async () => {
|
|
39
|
+
let capturedBody: unknown
|
|
40
|
+
globalThis.fetch = vi.fn(async (_url: string | URL | Request, opts?: RequestInit) => {
|
|
41
|
+
capturedBody = opts?.body ? JSON.parse(opts.body as string) : undefined
|
|
42
|
+
return new Response(JSON.stringify({ path: '/exa/agent/runs', method: 'POST' }), { status: 200 })
|
|
43
|
+
}) as typeof fetch
|
|
44
|
+
|
|
45
|
+
await getEndpointDetailsHandler({ api: 'exa', path: '/exa/agent/runs', method: 'POST' })
|
|
46
|
+
|
|
47
|
+
expect(capturedBody).toEqual({ api: 'exa', path: '/exa/agent/runs', method: 'POST' })
|
|
48
|
+
})
|
|
37
49
|
})
|