@signaliz/sdk 1.0.60 → 1.0.61
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/README.md +18 -2
- package/dist/{chunk-MFY4KSQ6.mjs → chunk-ENA7AVFB.mjs} +73 -9
- package/dist/index.d.mts +46 -4
- package/dist/index.d.ts +46 -4
- package/dist/index.js +73 -9
- package/dist/index.mjs +1 -1
- package/dist/mcp-config.js +73 -9
- package/dist/mcp-config.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,6 +73,12 @@ const signalDiscovery = await signaliz.discoverSignals({
|
|
|
73
73
|
limit: 100,
|
|
74
74
|
sources: ['web', 'news'],
|
|
75
75
|
});
|
|
76
|
+
const painSignalDiscovery = await signaliz.discoverSignals({
|
|
77
|
+
query: 'companies showing signals they need account-signal automation',
|
|
78
|
+
icpContext: 'B2B SaaS companies with outbound sales teams and manual account research',
|
|
79
|
+
limit: 100,
|
|
80
|
+
sources: ['web', 'news'],
|
|
81
|
+
});
|
|
76
82
|
const completedDiscovery = signalDiscovery.signalSearchRunId
|
|
77
83
|
? await signaliz.discoverSignals({ signalSearchRunId: signalDiscovery.signalSearchRunId })
|
|
78
84
|
: signalDiscovery;
|
|
@@ -154,12 +160,15 @@ Signal to Copy also shares company research across copy recipients.
|
|
|
154
160
|
Signals Everything is query-first rather than a row batch. It defaults to 100
|
|
155
161
|
distinct companies and supports up to 1,000. Every returned signal contains a
|
|
156
162
|
company name, company domain, dated evidence, and a source URL. The typed
|
|
157
|
-
`costGuardrail` reports
|
|
163
|
+
`costGuardrail` reports projected and observed source acquisition cost plus
|
|
164
|
+
identity-resolution cost, receipt source, and fallback-provider request count;
|
|
158
165
|
Signaliz returns signals only when cost stays strictly below $0.01 per qualified
|
|
159
166
|
company. A request is a ceiling, not a promise: it can return fewer results
|
|
160
167
|
when public evidence cannot verify both a date and company identity. It is
|
|
161
168
|
included on Team and Agency plans and can be resumed with
|
|
162
|
-
`signalSearchRunId` without duplicate source acquisition.
|
|
169
|
+
`signalSearchRunId` without duplicate source acquisition. Pass `icpContext` to
|
|
170
|
+
ground an open-ended request such as “companies showing signals they need our
|
|
171
|
+
product” in the user's target market.
|
|
163
172
|
|
|
164
173
|
Company Signal Enrichment defaults `online` and `enableDeepSearch` to `true`
|
|
165
174
|
unless the caller explicitly disables them. Its `searchMode` defaults to
|
|
@@ -170,6 +179,13 @@ complete, evidence-backed email variations when supported signals are available.
|
|
|
170
179
|
Signal to Copy is cache-first and defaults `enableDeepSearch` to `false` so it
|
|
171
180
|
normally finishes within an agent turn; set `skipCache` or `enableDeepSearch`
|
|
172
181
|
only when fresh or deeper research is required.
|
|
182
|
+
Every core request uses the authenticated workspace. Find Email and Verify Email
|
|
183
|
+
honor that workspace's configured cache window; eligible hits cost 0 credits,
|
|
184
|
+
while fresh discovery or verification is charged on every plan. Team, Agency,
|
|
185
|
+
and Pay-As-You-Go include fresh Company Signals and Signal to Copy. Those plans
|
|
186
|
+
still check eligible workspace signal data first even when Company Signals is
|
|
187
|
+
set to No cache. `lookbackDays` remains a hard evidence-age bound for both
|
|
188
|
+
cached and fresh Company Signals and Signal to Copy results.
|
|
173
189
|
Unclassified evidence is returned by signal enrichment but is not used to
|
|
174
190
|
generate outreach copy.
|
|
175
191
|
Each normalized signal keeps `date` separate from crawl-time `detectedAt` and
|
|
@@ -9,17 +9,21 @@ var SignalizError = class extends Error {
|
|
|
9
9
|
this.details = data.details;
|
|
10
10
|
}
|
|
11
11
|
get isRetryable() {
|
|
12
|
+
if (typeof this.details?.retry_eligible === "boolean") {
|
|
13
|
+
return this.details.retry_eligible;
|
|
14
|
+
}
|
|
12
15
|
return this.errorType === "rate_limited" || this.errorType === "timeout" || this.errorType === "provider_error";
|
|
13
16
|
}
|
|
14
17
|
};
|
|
15
18
|
function parseError(status, body) {
|
|
16
19
|
if (body?.error && typeof body.error === "object") {
|
|
20
|
+
const nestedDetails = body.error.details && typeof body.error.details === "object" ? body.error.details : {};
|
|
17
21
|
return new SignalizError({
|
|
18
22
|
code: body.error.code || `HTTP_${status}`,
|
|
19
23
|
message: body.error.message || `Request failed with status ${status}`,
|
|
20
24
|
errorType: mapErrorType(body.error.code, status),
|
|
21
25
|
retryAfter: retryAfterSeconds(body.error),
|
|
22
|
-
details: body.error
|
|
26
|
+
details: mergePublicErrorDetails({ ...body, ...body.error }, nestedDetails)
|
|
23
27
|
});
|
|
24
28
|
}
|
|
25
29
|
const code = typeof body?.error_code === "string" && body.error_code.trim() ? body.error_code.trim() : `HTTP_${status}`;
|
|
@@ -28,7 +32,7 @@ function parseError(status, body) {
|
|
|
28
32
|
message: body?.message || body?.error || `Request failed with status ${status}`,
|
|
29
33
|
errorType: mapErrorType(code, status),
|
|
30
34
|
retryAfter: retryAfterSeconds(body),
|
|
31
|
-
details: body?.details
|
|
35
|
+
details: mergePublicErrorDetails(body, body?.details)
|
|
32
36
|
});
|
|
33
37
|
}
|
|
34
38
|
function retryAfterSeconds(body) {
|
|
@@ -40,13 +44,26 @@ function publicRetryDetails(body) {
|
|
|
40
44
|
...body?.retry_eligible !== void 0 ? { retry_eligible: body.retry_eligible } : {},
|
|
41
45
|
...body?.retry_after !== void 0 ? { retry_after: body.retry_after } : {},
|
|
42
46
|
...body?.retry_after_seconds !== void 0 ? { retry_after_seconds: body.retry_after_seconds } : {},
|
|
47
|
+
...body?.retry_strategy !== void 0 ? { retry_strategy: body.retry_strategy } : {},
|
|
48
|
+
...body?.credits_used !== void 0 ? { credits_used: body.credits_used } : {},
|
|
49
|
+
...body?.credits_charged !== void 0 ? { credits_charged: body.credits_charged } : {},
|
|
50
|
+
...body?.job_id !== void 0 ? { job_id: body.job_id } : {},
|
|
51
|
+
...body?.verification_run_id !== void 0 ? { verification_run_id: body.verification_run_id } : {},
|
|
43
52
|
...body?.run_id !== void 0 ? { run_id: body.run_id } : {},
|
|
53
|
+
...body?.suggested_action !== void 0 ? { suggested_action: body.suggested_action } : {},
|
|
44
54
|
...body?.signal_run_id !== void 0 ? { signal_run_id: body.signal_run_id } : {},
|
|
45
55
|
...body?.company_signal_run_id !== void 0 ? { company_signal_run_id: body.company_signal_run_id } : {},
|
|
46
56
|
...body?.resume_context_persisted !== void 0 ? { resume_context_persisted: body.resume_context_persisted } : {}
|
|
47
57
|
};
|
|
48
58
|
return Object.keys(details).length > 0 ? details : void 0;
|
|
49
59
|
}
|
|
60
|
+
function mergePublicErrorDetails(body, explicitDetails) {
|
|
61
|
+
const merged = { ...publicRetryDetails(body) || {} };
|
|
62
|
+
if (explicitDetails && typeof explicitDetails === "object" && !Array.isArray(explicitDetails)) {
|
|
63
|
+
Object.assign(merged, explicitDetails);
|
|
64
|
+
}
|
|
65
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
66
|
+
}
|
|
50
67
|
function mapErrorType(code, status) {
|
|
51
68
|
if (code === "RATE_LIMITED" || status === 429) return "rate_limited";
|
|
52
69
|
if (code === "VALIDATION_ERROR" || code === "SIGNAL_RUN_COMPANY_MISMATCH" || status === 400) return "validation";
|
|
@@ -108,7 +125,9 @@ var HttpClient = class {
|
|
|
108
125
|
const errBody = await res.json().catch(() => ({}));
|
|
109
126
|
const err = parseError(res.status, errBody);
|
|
110
127
|
if (err.isRetryable && attempt < this.maxRetries) {
|
|
111
|
-
const
|
|
128
|
+
const retryWithNewKey = err.details?.retry_strategy === "new_idempotency_key" && err.details?.credits_used === 0 && err.details?.credits_charged === 0;
|
|
129
|
+
if (retryWithNewKey) throw err;
|
|
130
|
+
const wait = err.retryAfter !== void 0 ? err.retryAfter * 1e3 : Math.min(1e3 * Math.pow(2, attempt), 1e4);
|
|
112
131
|
await sleep(wait);
|
|
113
132
|
lastError = err;
|
|
114
133
|
continue;
|
|
@@ -765,7 +784,10 @@ var Signaliz = class {
|
|
|
765
784
|
);
|
|
766
785
|
const uniqueTasks = deduplicated.uniqueItems;
|
|
767
786
|
const recoverableBatch = path === "api/v1/find-email" ? { label: "Find Email", pageSize: 500, maxWaitMs: 20 * 6e4 } : path === "api/v1/verify-email" ? { label: "Verify Email", pageSize: 500, maxWaitMs: 20 * 6e4 } : void 0;
|
|
768
|
-
|
|
787
|
+
const containsFindRecoveryReads = path === "api/v1/find-email" && uniqueTasks.some(
|
|
788
|
+
(task) => typeof task.request.run_id === "string" && task.request.run_id.trim()
|
|
789
|
+
);
|
|
790
|
+
if (path !== "api/v1/company-signals" && recoverableBatch && uniqueTasks.length > 25 && !containsFindRecoveryReads) {
|
|
769
791
|
const rows = await this.runRecoverableCoreBatchJob(
|
|
770
792
|
path,
|
|
771
793
|
uniqueTasks.map((task) => task.request),
|
|
@@ -891,13 +913,27 @@ function batchItemFailure(index, error, raw) {
|
|
|
891
913
|
raw?.retry_after_seconds ?? raw?.retry_after ?? raw?.retryAfterSeconds ?? (Number.isFinite(Number(raw?.retry_after_ms)) ? Number(raw?.retry_after_ms) / 1e3 : void 0)
|
|
892
914
|
);
|
|
893
915
|
const retryEligible = raw?.retry_eligible ?? raw?.retryEligible;
|
|
916
|
+
const retryStrategy = raw?.retry_strategy ?? raw?.retryStrategy;
|
|
917
|
+
const creditsUsed = raw?.credits_used ?? raw?.creditsUsed;
|
|
918
|
+
const creditsCharged = raw?.credits_charged ?? raw?.creditsCharged;
|
|
919
|
+
const runId = raw?.run_id ?? raw?.runId;
|
|
920
|
+
const verificationRunId = raw?.verification_run_id ?? raw?.verificationRunId;
|
|
921
|
+
const jobId = raw?.job_id ?? raw?.jobId;
|
|
922
|
+
const suggestedAction = raw?.suggested_action ?? raw?.suggestedAction;
|
|
894
923
|
return {
|
|
895
924
|
index,
|
|
896
925
|
success: false,
|
|
897
926
|
error,
|
|
898
927
|
...errorCode ? { errorCode } : {},
|
|
899
928
|
...typeof retryEligible === "boolean" ? { retryEligible } : {},
|
|
900
|
-
...Number.isFinite(retryAfterSeconds2) && retryAfterSeconds2 >= 0 ? { retryAfterSeconds: retryAfterSeconds2 } : {}
|
|
929
|
+
...Number.isFinite(retryAfterSeconds2) && retryAfterSeconds2 >= 0 ? { retryAfterSeconds: retryAfterSeconds2 } : {},
|
|
930
|
+
...retryStrategy === "new_idempotency_key" ? { retryStrategy } : {},
|
|
931
|
+
...creditsUsed === 0 ? { creditsUsed: 0 } : {},
|
|
932
|
+
...creditsCharged === 0 ? { creditsCharged: 0 } : {},
|
|
933
|
+
...typeof runId === "string" && runId.trim() ? { runId: runId.trim() } : {},
|
|
934
|
+
...typeof verificationRunId === "string" && verificationRunId.trim() ? { verificationRunId: verificationRunId.trim() } : {},
|
|
935
|
+
...typeof jobId === "string" && jobId.trim() ? { jobId: jobId.trim() } : {},
|
|
936
|
+
...typeof suggestedAction === "string" && suggestedAction.trim() ? { suggestedAction: suggestedAction.trim() } : {}
|
|
901
937
|
};
|
|
902
938
|
}
|
|
903
939
|
function recoverableJobRowFailed(row) {
|
|
@@ -912,6 +948,7 @@ function compact(input) {
|
|
|
912
948
|
}
|
|
913
949
|
function findEmailRequestBody(params) {
|
|
914
950
|
return compact({
|
|
951
|
+
run_id: params.runId,
|
|
915
952
|
company_domain: params.companyDomain,
|
|
916
953
|
full_name: params.fullName,
|
|
917
954
|
first_name: params.firstName,
|
|
@@ -951,6 +988,7 @@ function normalizeCoreProductDryRunResult(data) {
|
|
|
951
988
|
};
|
|
952
989
|
}
|
|
953
990
|
function normalizeFindEmailResult(data) {
|
|
991
|
+
const processing = String(data.status || "").toLowerCase() === "processing";
|
|
954
992
|
const failed = coreProductResponseFailed(data);
|
|
955
993
|
const rawEmail = typeof data.email === "string" && data.email.trim() ? data.email.trim() : null;
|
|
956
994
|
const email = failed ? null : rawEmail;
|
|
@@ -963,7 +1001,7 @@ function normalizeFindEmailResult(data) {
|
|
|
963
1001
|
const verified = !explicitlyNotSendSafe && (data.is_valid === true || data.isValid === true || data.email_verified === true || data.verified_for_sending === true || ["valid", "deliverable"].includes(String(verificationStatus).toLowerCase()));
|
|
964
1002
|
const verificationAgeDays = typeof data.verification_age_days === "number" && Number.isFinite(data.verification_age_days) ? data.verification_age_days : null;
|
|
965
1003
|
return {
|
|
966
|
-
success: !failed && found,
|
|
1004
|
+
success: processing || !failed && found,
|
|
967
1005
|
found,
|
|
968
1006
|
email,
|
|
969
1007
|
firstName: data.first_name,
|
|
@@ -990,8 +1028,12 @@ function normalizeFindEmailResult(data) {
|
|
|
990
1028
|
liveProviderCalled: data.live_provider_called,
|
|
991
1029
|
openrouterCalled: data.openrouter_called,
|
|
992
1030
|
byoOpenrouterUsed: data.byo_openrouter_used,
|
|
993
|
-
error: found ? void 0 : coreProductErrorMessage(data) ?? "No verified email found",
|
|
994
|
-
errorCode: found ? void 0 : coreProductErrorCode(data) ?? "EMAIL_NOT_FOUND",
|
|
1031
|
+
error: processing || found ? void 0 : coreProductErrorMessage(data) ?? "No verified email found",
|
|
1032
|
+
errorCode: processing || found ? void 0 : coreProductErrorCode(data) ?? "EMAIL_NOT_FOUND",
|
|
1033
|
+
status: processing ? "processing" : "completed",
|
|
1034
|
+
runId: data.run_id,
|
|
1035
|
+
nextPollAfterSeconds: data.next_poll_after_seconds,
|
|
1036
|
+
suggestedAction: data.suggested_action,
|
|
995
1037
|
raw: data
|
|
996
1038
|
};
|
|
997
1039
|
}
|
|
@@ -1127,6 +1169,12 @@ function validateSignalDiscoveryParams(params) {
|
|
|
1127
1169
|
if (query && (query.length < 2 || query.length > 2e3)) {
|
|
1128
1170
|
throw new RangeError("query must contain between 2 and 2000 characters");
|
|
1129
1171
|
}
|
|
1172
|
+
if (params.icpContext !== void 0) {
|
|
1173
|
+
const icpContext = typeof params.icpContext === "string" ? params.icpContext.trim() : "";
|
|
1174
|
+
if (icpContext.length < 2 || icpContext.length > 4e3) {
|
|
1175
|
+
throw new RangeError("icpContext must contain between 2 and 4000 characters");
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1130
1178
|
if (params.limit !== void 0 && (!Number.isInteger(params.limit) || params.limit < 1 || params.limit > 1e3)) {
|
|
1131
1179
|
throw new RangeError("limit must be an integer between 1 and 1000");
|
|
1132
1180
|
}
|
|
@@ -1151,6 +1199,7 @@ function signalDiscoveryRequestBody(params) {
|
|
|
1151
1199
|
}
|
|
1152
1200
|
return compact({
|
|
1153
1201
|
query: params.query?.trim(),
|
|
1202
|
+
icp_context: params.icpContext?.trim(),
|
|
1154
1203
|
limit: params.limit ?? 100,
|
|
1155
1204
|
sources: params.sources,
|
|
1156
1205
|
lookback_days: params.lookbackDays,
|
|
@@ -1176,6 +1225,8 @@ function normalizeSignalDiscoveryResult(params, data) {
|
|
|
1176
1225
|
availableCompanySignalCount: Number.isFinite(Number(data.available_company_signal_count)) ? Number(data.available_company_signal_count) : void 0,
|
|
1177
1226
|
sourceLanes: Array.isArray(data.source_lanes) ? data.source_lanes.filter((lane) => typeof lane === "string") : void 0,
|
|
1178
1227
|
evidenceValidation: data.evidence_validation && typeof data.evidence_validation === "object" ? data.evidence_validation : void 0,
|
|
1228
|
+
discoveryDiagnostics: data.discovery_diagnostics && typeof data.discovery_diagnostics === "object" ? data.discovery_diagnostics : void 0,
|
|
1229
|
+
identityResolution: data.identity_resolution && typeof data.identity_resolution === "object" ? data.identity_resolution : void 0,
|
|
1179
1230
|
costGuardrail: normalizeSignalDiscoveryCostGuardrail(data.cost_guardrail),
|
|
1180
1231
|
warnings: Array.isArray(data.warnings) ? data.warnings.filter((warning) => typeof warning === "string") : void 0,
|
|
1181
1232
|
raw: data
|
|
@@ -1204,7 +1255,15 @@ function normalizeSignalDiscoveryCostGuardrail(value) {
|
|
|
1204
1255
|
guardrail.projected_cost_per_requested_company_signal_usd
|
|
1205
1256
|
),
|
|
1206
1257
|
sourceCostUsd: numberOrNullable(guardrail.source_cost_usd),
|
|
1207
|
-
costSource: ["observed", "catalog_bounded", "mixed", "unavailable"].includes(String(guardrail.cost_source)) ? String(guardrail.cost_source) : void 0,
|
|
1258
|
+
costSource: ["observed", "catalog_preflight", "catalog_bounded", "mixed", "unavailable"].includes(String(guardrail.cost_source)) ? String(guardrail.cost_source) : void 0,
|
|
1259
|
+
identityResolutionCostUsd: numberOrNullable(guardrail.identity_resolution_cost_usd),
|
|
1260
|
+
identityCostSource: [
|
|
1261
|
+
"observed_zero_credit_receipts",
|
|
1262
|
+
"contractual_zero_cost",
|
|
1263
|
+
"not_used",
|
|
1264
|
+
"unavailable"
|
|
1265
|
+
].includes(String(guardrail.identity_cost_source)) ? String(guardrail.identity_cost_source) : void 0,
|
|
1266
|
+
identityProviderRequests: numberOrUndefined(guardrail.identity_provider_requests),
|
|
1208
1267
|
qualifiedCompanySignalCount: numberOrUndefined(guardrail.qualified_company_signal_count),
|
|
1209
1268
|
returnedCompanySignalCount: numberOrUndefined(guardrail.returned_company_signal_count),
|
|
1210
1269
|
availableCompanySignalCount: numberOrUndefined(guardrail.available_company_signal_count),
|
|
@@ -1308,6 +1367,7 @@ function normalizedFindEmailBatchName(request) {
|
|
|
1308
1367
|
function coreProductBatchRequestKey(path, request) {
|
|
1309
1368
|
if (path === "api/v1/find-email") {
|
|
1310
1369
|
return JSON.stringify([
|
|
1370
|
+
normalizedBatchText(request.run_id),
|
|
1311
1371
|
normalizedFindEmailBatchName(request),
|
|
1312
1372
|
normalizedBatchDomain(request.company_domain),
|
|
1313
1373
|
normalizedBatchLinkedIn(request.linkedin_url),
|
|
@@ -1413,6 +1473,7 @@ function signalToCopyRequestBody(params) {
|
|
|
1413
1473
|
title: params.title,
|
|
1414
1474
|
campaign_offer: params.campaignOffer,
|
|
1415
1475
|
research_prompt: params.researchPrompt,
|
|
1476
|
+
lookback_days: params.lookbackDays,
|
|
1416
1477
|
signal_run_id: params.signalRunId,
|
|
1417
1478
|
skip_cache: params.skipCache,
|
|
1418
1479
|
enable_deep_search: params.enableDeepSearch,
|
|
@@ -1423,6 +1484,9 @@ function signalToCopyRequestBody(params) {
|
|
|
1423
1484
|
}
|
|
1424
1485
|
function validateSignalToCopyParams(params) {
|
|
1425
1486
|
validateCoreProductMaxWaitMs(params.maxWaitMs);
|
|
1487
|
+
if (params.lookbackDays !== void 0 && (!Number.isInteger(params.lookbackDays) || params.lookbackDays < 1 || params.lookbackDays > 365)) {
|
|
1488
|
+
throw new RangeError("lookbackDays must be an integer between 1 and 365");
|
|
1489
|
+
}
|
|
1426
1490
|
if (typeof params.signalRunId === "string" && params.signalRunId.trim()) return;
|
|
1427
1491
|
const missing = [
|
|
1428
1492
|
["companyDomain", params.companyDomain],
|
package/dist/index.d.mts
CHANGED
|
@@ -27,6 +27,20 @@ interface BatchItemResult<T> {
|
|
|
27
27
|
retryEligible?: boolean;
|
|
28
28
|
/** Server-provided delay before retrying the failed row. */
|
|
29
29
|
retryAfterSeconds?: number;
|
|
30
|
+
/** Explicit recovery strategy. A fresh key can repeat provider work and is never automatic. */
|
|
31
|
+
retryStrategy?: 'new_idempotency_key';
|
|
32
|
+
/** Present only when the server proves the failed row consumed zero Signaliz credits. */
|
|
33
|
+
creditsUsed?: 0;
|
|
34
|
+
/** Present only when the server proves the failed row charged zero Signaliz credits. */
|
|
35
|
+
creditsCharged?: 0;
|
|
36
|
+
/** Existing provider run that can be resumed without dispatching new work. */
|
|
37
|
+
runId?: string;
|
|
38
|
+
/** Existing Verify Email run that can be resumed without dispatching new work. */
|
|
39
|
+
verificationRunId?: string;
|
|
40
|
+
/** Existing recoverable batch job. */
|
|
41
|
+
jobId?: string;
|
|
42
|
+
/** Machine-readable recovery action returned by Signaliz. */
|
|
43
|
+
suggestedAction?: string;
|
|
30
44
|
/** Zero-based input index containing the full result for this exact duplicate. */
|
|
31
45
|
duplicateOf?: number;
|
|
32
46
|
}
|
|
@@ -66,8 +80,7 @@ interface CoreProductDryRunResult {
|
|
|
66
80
|
sideEffects: unknown[];
|
|
67
81
|
raw: Record<string, unknown>;
|
|
68
82
|
}
|
|
69
|
-
interface
|
|
70
|
-
companyDomain: string;
|
|
83
|
+
interface FindEmailCommonParams {
|
|
71
84
|
fullName?: string;
|
|
72
85
|
firstName?: string;
|
|
73
86
|
lastName?: string;
|
|
@@ -80,6 +93,15 @@ interface FindEmailParams {
|
|
|
80
93
|
/** Stable retry key for recovering the same request after an ambiguous response. */
|
|
81
94
|
idempotencyKey?: string;
|
|
82
95
|
}
|
|
96
|
+
type FindEmailParams = FindEmailCommonParams & ({
|
|
97
|
+
companyDomain: string;
|
|
98
|
+
/** Omit for a new lookup. */
|
|
99
|
+
runId?: undefined;
|
|
100
|
+
} | {
|
|
101
|
+
/** Resume one existing Find Email run without dispatching a new finder. */
|
|
102
|
+
runId: string;
|
|
103
|
+
companyDomain?: string;
|
|
104
|
+
});
|
|
83
105
|
interface FindEmailResult {
|
|
84
106
|
success: boolean;
|
|
85
107
|
found: boolean;
|
|
@@ -112,6 +134,12 @@ interface FindEmailResult {
|
|
|
112
134
|
byoOpenrouterUsed?: boolean;
|
|
113
135
|
error?: string;
|
|
114
136
|
errorCode?: string;
|
|
137
|
+
/** Processing while an existing provider run is still active; otherwise completed. */
|
|
138
|
+
status?: 'processing' | 'completed';
|
|
139
|
+
/** Durable Find Email run ID for polling without duplicate spend. */
|
|
140
|
+
runId?: string;
|
|
141
|
+
nextPollAfterSeconds?: number;
|
|
142
|
+
suggestedAction?: string;
|
|
115
143
|
raw: Record<string, unknown>;
|
|
116
144
|
}
|
|
117
145
|
interface VerifyEmailResult {
|
|
@@ -250,8 +278,10 @@ interface CompanySignalEnrichmentResult {
|
|
|
250
278
|
type SignalDiscoverySource = 'web' | 'news';
|
|
251
279
|
type SignalDiscoveryStatus = 'planned' | 'queued' | 'processing' | 'completed' | 'completed_with_warnings' | 'failed';
|
|
252
280
|
interface SignalDiscoveryParams {
|
|
253
|
-
/**
|
|
281
|
+
/** Any natural-language signal question. Required for a new search. */
|
|
254
282
|
query?: string;
|
|
283
|
+
/** Optional natural-language ICP, product, or pain context that returned signals must support. */
|
|
284
|
+
icpContext?: string;
|
|
255
285
|
/** Number of qualified company signals requested. Defaults to 100; allowed range is 1-1,000. */
|
|
256
286
|
limit?: number;
|
|
257
287
|
/** Restrict discovery to selected source families. */
|
|
@@ -300,7 +330,13 @@ interface SignalDiscoveryCostGuardrail {
|
|
|
300
330
|
maxSourceCostUsd?: number | null;
|
|
301
331
|
projectedCostPerRequestedCompanySignalUsd?: number | null;
|
|
302
332
|
sourceCostUsd?: number | null;
|
|
303
|
-
costSource?: 'observed' | 'catalog_bounded' | 'mixed' | 'unavailable';
|
|
333
|
+
costSource?: 'observed' | 'catalog_preflight' | 'catalog_bounded' | 'mixed' | 'unavailable';
|
|
334
|
+
/** Separately reported company identity-resolution cost; null when receipts are incomplete. */
|
|
335
|
+
identityResolutionCostUsd?: number | null;
|
|
336
|
+
/** Evidence used to account for company identity-resolution cost. */
|
|
337
|
+
identityCostSource?: 'observed_zero_credit_receipts' | 'contractual_zero_cost' | 'not_used' | 'unavailable';
|
|
338
|
+
/** Zero-cost fallback identity-provider requests covered by identityResolutionCostUsd. */
|
|
339
|
+
identityProviderRequests?: number;
|
|
304
340
|
qualifiedCompanySignalCount?: number;
|
|
305
341
|
returnedCompanySignalCount?: number;
|
|
306
342
|
/** Qualified signals retained on the same search run for later expansion. */
|
|
@@ -326,6 +362,10 @@ interface SignalDiscoveryResult {
|
|
|
326
362
|
availableCompanySignalCount?: number;
|
|
327
363
|
sourceLanes?: string[];
|
|
328
364
|
evidenceValidation?: Record<string, unknown>;
|
|
365
|
+
/** Search, reachability, date, classifier, and rejection counts for diagnosis. */
|
|
366
|
+
discoveryDiagnostics?: Record<string, unknown>;
|
|
367
|
+
/** Company-domain verification counts for the retained cohort. */
|
|
368
|
+
identityResolution?: Record<string, unknown>;
|
|
329
369
|
costGuardrail?: SignalDiscoveryCostGuardrail;
|
|
330
370
|
warnings?: string[];
|
|
331
371
|
raw: Record<string, unknown>;
|
|
@@ -336,6 +376,8 @@ interface SignalToCopyParams {
|
|
|
336
376
|
title?: string;
|
|
337
377
|
campaignOffer?: string;
|
|
338
378
|
researchPrompt?: string;
|
|
379
|
+
/** Maximum signal age used for cache reuse and fresh research. Defaults to 90 days. */
|
|
380
|
+
lookbackDays?: number;
|
|
339
381
|
signalRunId?: string;
|
|
340
382
|
/** Bypass cached company signals and start fresh research. */
|
|
341
383
|
skipCache?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,20 @@ interface BatchItemResult<T> {
|
|
|
27
27
|
retryEligible?: boolean;
|
|
28
28
|
/** Server-provided delay before retrying the failed row. */
|
|
29
29
|
retryAfterSeconds?: number;
|
|
30
|
+
/** Explicit recovery strategy. A fresh key can repeat provider work and is never automatic. */
|
|
31
|
+
retryStrategy?: 'new_idempotency_key';
|
|
32
|
+
/** Present only when the server proves the failed row consumed zero Signaliz credits. */
|
|
33
|
+
creditsUsed?: 0;
|
|
34
|
+
/** Present only when the server proves the failed row charged zero Signaliz credits. */
|
|
35
|
+
creditsCharged?: 0;
|
|
36
|
+
/** Existing provider run that can be resumed without dispatching new work. */
|
|
37
|
+
runId?: string;
|
|
38
|
+
/** Existing Verify Email run that can be resumed without dispatching new work. */
|
|
39
|
+
verificationRunId?: string;
|
|
40
|
+
/** Existing recoverable batch job. */
|
|
41
|
+
jobId?: string;
|
|
42
|
+
/** Machine-readable recovery action returned by Signaliz. */
|
|
43
|
+
suggestedAction?: string;
|
|
30
44
|
/** Zero-based input index containing the full result for this exact duplicate. */
|
|
31
45
|
duplicateOf?: number;
|
|
32
46
|
}
|
|
@@ -66,8 +80,7 @@ interface CoreProductDryRunResult {
|
|
|
66
80
|
sideEffects: unknown[];
|
|
67
81
|
raw: Record<string, unknown>;
|
|
68
82
|
}
|
|
69
|
-
interface
|
|
70
|
-
companyDomain: string;
|
|
83
|
+
interface FindEmailCommonParams {
|
|
71
84
|
fullName?: string;
|
|
72
85
|
firstName?: string;
|
|
73
86
|
lastName?: string;
|
|
@@ -80,6 +93,15 @@ interface FindEmailParams {
|
|
|
80
93
|
/** Stable retry key for recovering the same request after an ambiguous response. */
|
|
81
94
|
idempotencyKey?: string;
|
|
82
95
|
}
|
|
96
|
+
type FindEmailParams = FindEmailCommonParams & ({
|
|
97
|
+
companyDomain: string;
|
|
98
|
+
/** Omit for a new lookup. */
|
|
99
|
+
runId?: undefined;
|
|
100
|
+
} | {
|
|
101
|
+
/** Resume one existing Find Email run without dispatching a new finder. */
|
|
102
|
+
runId: string;
|
|
103
|
+
companyDomain?: string;
|
|
104
|
+
});
|
|
83
105
|
interface FindEmailResult {
|
|
84
106
|
success: boolean;
|
|
85
107
|
found: boolean;
|
|
@@ -112,6 +134,12 @@ interface FindEmailResult {
|
|
|
112
134
|
byoOpenrouterUsed?: boolean;
|
|
113
135
|
error?: string;
|
|
114
136
|
errorCode?: string;
|
|
137
|
+
/** Processing while an existing provider run is still active; otherwise completed. */
|
|
138
|
+
status?: 'processing' | 'completed';
|
|
139
|
+
/** Durable Find Email run ID for polling without duplicate spend. */
|
|
140
|
+
runId?: string;
|
|
141
|
+
nextPollAfterSeconds?: number;
|
|
142
|
+
suggestedAction?: string;
|
|
115
143
|
raw: Record<string, unknown>;
|
|
116
144
|
}
|
|
117
145
|
interface VerifyEmailResult {
|
|
@@ -250,8 +278,10 @@ interface CompanySignalEnrichmentResult {
|
|
|
250
278
|
type SignalDiscoverySource = 'web' | 'news';
|
|
251
279
|
type SignalDiscoveryStatus = 'planned' | 'queued' | 'processing' | 'completed' | 'completed_with_warnings' | 'failed';
|
|
252
280
|
interface SignalDiscoveryParams {
|
|
253
|
-
/**
|
|
281
|
+
/** Any natural-language signal question. Required for a new search. */
|
|
254
282
|
query?: string;
|
|
283
|
+
/** Optional natural-language ICP, product, or pain context that returned signals must support. */
|
|
284
|
+
icpContext?: string;
|
|
255
285
|
/** Number of qualified company signals requested. Defaults to 100; allowed range is 1-1,000. */
|
|
256
286
|
limit?: number;
|
|
257
287
|
/** Restrict discovery to selected source families. */
|
|
@@ -300,7 +330,13 @@ interface SignalDiscoveryCostGuardrail {
|
|
|
300
330
|
maxSourceCostUsd?: number | null;
|
|
301
331
|
projectedCostPerRequestedCompanySignalUsd?: number | null;
|
|
302
332
|
sourceCostUsd?: number | null;
|
|
303
|
-
costSource?: 'observed' | 'catalog_bounded' | 'mixed' | 'unavailable';
|
|
333
|
+
costSource?: 'observed' | 'catalog_preflight' | 'catalog_bounded' | 'mixed' | 'unavailable';
|
|
334
|
+
/** Separately reported company identity-resolution cost; null when receipts are incomplete. */
|
|
335
|
+
identityResolutionCostUsd?: number | null;
|
|
336
|
+
/** Evidence used to account for company identity-resolution cost. */
|
|
337
|
+
identityCostSource?: 'observed_zero_credit_receipts' | 'contractual_zero_cost' | 'not_used' | 'unavailable';
|
|
338
|
+
/** Zero-cost fallback identity-provider requests covered by identityResolutionCostUsd. */
|
|
339
|
+
identityProviderRequests?: number;
|
|
304
340
|
qualifiedCompanySignalCount?: number;
|
|
305
341
|
returnedCompanySignalCount?: number;
|
|
306
342
|
/** Qualified signals retained on the same search run for later expansion. */
|
|
@@ -326,6 +362,10 @@ interface SignalDiscoveryResult {
|
|
|
326
362
|
availableCompanySignalCount?: number;
|
|
327
363
|
sourceLanes?: string[];
|
|
328
364
|
evidenceValidation?: Record<string, unknown>;
|
|
365
|
+
/** Search, reachability, date, classifier, and rejection counts for diagnosis. */
|
|
366
|
+
discoveryDiagnostics?: Record<string, unknown>;
|
|
367
|
+
/** Company-domain verification counts for the retained cohort. */
|
|
368
|
+
identityResolution?: Record<string, unknown>;
|
|
329
369
|
costGuardrail?: SignalDiscoveryCostGuardrail;
|
|
330
370
|
warnings?: string[];
|
|
331
371
|
raw: Record<string, unknown>;
|
|
@@ -336,6 +376,8 @@ interface SignalToCopyParams {
|
|
|
336
376
|
title?: string;
|
|
337
377
|
campaignOffer?: string;
|
|
338
378
|
researchPrompt?: string;
|
|
379
|
+
/** Maximum signal age used for cache reuse and fresh research. Defaults to 90 days. */
|
|
380
|
+
lookbackDays?: number;
|
|
339
381
|
signalRunId?: string;
|
|
340
382
|
/** Bypass cached company signals and start fresh research. */
|
|
341
383
|
skipCache?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -36,17 +36,21 @@ var SignalizError = class extends Error {
|
|
|
36
36
|
this.details = data.details;
|
|
37
37
|
}
|
|
38
38
|
get isRetryable() {
|
|
39
|
+
if (typeof this.details?.retry_eligible === "boolean") {
|
|
40
|
+
return this.details.retry_eligible;
|
|
41
|
+
}
|
|
39
42
|
return this.errorType === "rate_limited" || this.errorType === "timeout" || this.errorType === "provider_error";
|
|
40
43
|
}
|
|
41
44
|
};
|
|
42
45
|
function parseError(status, body) {
|
|
43
46
|
if (body?.error && typeof body.error === "object") {
|
|
47
|
+
const nestedDetails = body.error.details && typeof body.error.details === "object" ? body.error.details : {};
|
|
44
48
|
return new SignalizError({
|
|
45
49
|
code: body.error.code || `HTTP_${status}`,
|
|
46
50
|
message: body.error.message || `Request failed with status ${status}`,
|
|
47
51
|
errorType: mapErrorType(body.error.code, status),
|
|
48
52
|
retryAfter: retryAfterSeconds(body.error),
|
|
49
|
-
details: body.error
|
|
53
|
+
details: mergePublicErrorDetails({ ...body, ...body.error }, nestedDetails)
|
|
50
54
|
});
|
|
51
55
|
}
|
|
52
56
|
const code = typeof body?.error_code === "string" && body.error_code.trim() ? body.error_code.trim() : `HTTP_${status}`;
|
|
@@ -55,7 +59,7 @@ function parseError(status, body) {
|
|
|
55
59
|
message: body?.message || body?.error || `Request failed with status ${status}`,
|
|
56
60
|
errorType: mapErrorType(code, status),
|
|
57
61
|
retryAfter: retryAfterSeconds(body),
|
|
58
|
-
details: body?.details
|
|
62
|
+
details: mergePublicErrorDetails(body, body?.details)
|
|
59
63
|
});
|
|
60
64
|
}
|
|
61
65
|
function retryAfterSeconds(body) {
|
|
@@ -67,13 +71,26 @@ function publicRetryDetails(body) {
|
|
|
67
71
|
...body?.retry_eligible !== void 0 ? { retry_eligible: body.retry_eligible } : {},
|
|
68
72
|
...body?.retry_after !== void 0 ? { retry_after: body.retry_after } : {},
|
|
69
73
|
...body?.retry_after_seconds !== void 0 ? { retry_after_seconds: body.retry_after_seconds } : {},
|
|
74
|
+
...body?.retry_strategy !== void 0 ? { retry_strategy: body.retry_strategy } : {},
|
|
75
|
+
...body?.credits_used !== void 0 ? { credits_used: body.credits_used } : {},
|
|
76
|
+
...body?.credits_charged !== void 0 ? { credits_charged: body.credits_charged } : {},
|
|
77
|
+
...body?.job_id !== void 0 ? { job_id: body.job_id } : {},
|
|
78
|
+
...body?.verification_run_id !== void 0 ? { verification_run_id: body.verification_run_id } : {},
|
|
70
79
|
...body?.run_id !== void 0 ? { run_id: body.run_id } : {},
|
|
80
|
+
...body?.suggested_action !== void 0 ? { suggested_action: body.suggested_action } : {},
|
|
71
81
|
...body?.signal_run_id !== void 0 ? { signal_run_id: body.signal_run_id } : {},
|
|
72
82
|
...body?.company_signal_run_id !== void 0 ? { company_signal_run_id: body.company_signal_run_id } : {},
|
|
73
83
|
...body?.resume_context_persisted !== void 0 ? { resume_context_persisted: body.resume_context_persisted } : {}
|
|
74
84
|
};
|
|
75
85
|
return Object.keys(details).length > 0 ? details : void 0;
|
|
76
86
|
}
|
|
87
|
+
function mergePublicErrorDetails(body, explicitDetails) {
|
|
88
|
+
const merged = { ...publicRetryDetails(body) || {} };
|
|
89
|
+
if (explicitDetails && typeof explicitDetails === "object" && !Array.isArray(explicitDetails)) {
|
|
90
|
+
Object.assign(merged, explicitDetails);
|
|
91
|
+
}
|
|
92
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
93
|
+
}
|
|
77
94
|
function mapErrorType(code, status) {
|
|
78
95
|
if (code === "RATE_LIMITED" || status === 429) return "rate_limited";
|
|
79
96
|
if (code === "VALIDATION_ERROR" || code === "SIGNAL_RUN_COMPANY_MISMATCH" || status === 400) return "validation";
|
|
@@ -135,7 +152,9 @@ var HttpClient = class {
|
|
|
135
152
|
const errBody = await res.json().catch(() => ({}));
|
|
136
153
|
const err = parseError(res.status, errBody);
|
|
137
154
|
if (err.isRetryable && attempt < this.maxRetries) {
|
|
138
|
-
const
|
|
155
|
+
const retryWithNewKey = err.details?.retry_strategy === "new_idempotency_key" && err.details?.credits_used === 0 && err.details?.credits_charged === 0;
|
|
156
|
+
if (retryWithNewKey) throw err;
|
|
157
|
+
const wait = err.retryAfter !== void 0 ? err.retryAfter * 1e3 : Math.min(1e3 * Math.pow(2, attempt), 1e4);
|
|
139
158
|
await sleep(wait);
|
|
140
159
|
lastError = err;
|
|
141
160
|
continue;
|
|
@@ -792,7 +811,10 @@ var Signaliz = class {
|
|
|
792
811
|
);
|
|
793
812
|
const uniqueTasks = deduplicated.uniqueItems;
|
|
794
813
|
const recoverableBatch = path === "api/v1/find-email" ? { label: "Find Email", pageSize: 500, maxWaitMs: 20 * 6e4 } : path === "api/v1/verify-email" ? { label: "Verify Email", pageSize: 500, maxWaitMs: 20 * 6e4 } : void 0;
|
|
795
|
-
|
|
814
|
+
const containsFindRecoveryReads = path === "api/v1/find-email" && uniqueTasks.some(
|
|
815
|
+
(task) => typeof task.request.run_id === "string" && task.request.run_id.trim()
|
|
816
|
+
);
|
|
817
|
+
if (path !== "api/v1/company-signals" && recoverableBatch && uniqueTasks.length > 25 && !containsFindRecoveryReads) {
|
|
796
818
|
const rows = await this.runRecoverableCoreBatchJob(
|
|
797
819
|
path,
|
|
798
820
|
uniqueTasks.map((task) => task.request),
|
|
@@ -918,13 +940,27 @@ function batchItemFailure(index, error, raw) {
|
|
|
918
940
|
raw?.retry_after_seconds ?? raw?.retry_after ?? raw?.retryAfterSeconds ?? (Number.isFinite(Number(raw?.retry_after_ms)) ? Number(raw?.retry_after_ms) / 1e3 : void 0)
|
|
919
941
|
);
|
|
920
942
|
const retryEligible = raw?.retry_eligible ?? raw?.retryEligible;
|
|
943
|
+
const retryStrategy = raw?.retry_strategy ?? raw?.retryStrategy;
|
|
944
|
+
const creditsUsed = raw?.credits_used ?? raw?.creditsUsed;
|
|
945
|
+
const creditsCharged = raw?.credits_charged ?? raw?.creditsCharged;
|
|
946
|
+
const runId = raw?.run_id ?? raw?.runId;
|
|
947
|
+
const verificationRunId = raw?.verification_run_id ?? raw?.verificationRunId;
|
|
948
|
+
const jobId = raw?.job_id ?? raw?.jobId;
|
|
949
|
+
const suggestedAction = raw?.suggested_action ?? raw?.suggestedAction;
|
|
921
950
|
return {
|
|
922
951
|
index,
|
|
923
952
|
success: false,
|
|
924
953
|
error,
|
|
925
954
|
...errorCode ? { errorCode } : {},
|
|
926
955
|
...typeof retryEligible === "boolean" ? { retryEligible } : {},
|
|
927
|
-
...Number.isFinite(retryAfterSeconds2) && retryAfterSeconds2 >= 0 ? { retryAfterSeconds: retryAfterSeconds2 } : {}
|
|
956
|
+
...Number.isFinite(retryAfterSeconds2) && retryAfterSeconds2 >= 0 ? { retryAfterSeconds: retryAfterSeconds2 } : {},
|
|
957
|
+
...retryStrategy === "new_idempotency_key" ? { retryStrategy } : {},
|
|
958
|
+
...creditsUsed === 0 ? { creditsUsed: 0 } : {},
|
|
959
|
+
...creditsCharged === 0 ? { creditsCharged: 0 } : {},
|
|
960
|
+
...typeof runId === "string" && runId.trim() ? { runId: runId.trim() } : {},
|
|
961
|
+
...typeof verificationRunId === "string" && verificationRunId.trim() ? { verificationRunId: verificationRunId.trim() } : {},
|
|
962
|
+
...typeof jobId === "string" && jobId.trim() ? { jobId: jobId.trim() } : {},
|
|
963
|
+
...typeof suggestedAction === "string" && suggestedAction.trim() ? { suggestedAction: suggestedAction.trim() } : {}
|
|
928
964
|
};
|
|
929
965
|
}
|
|
930
966
|
function recoverableJobRowFailed(row) {
|
|
@@ -939,6 +975,7 @@ function compact(input) {
|
|
|
939
975
|
}
|
|
940
976
|
function findEmailRequestBody(params) {
|
|
941
977
|
return compact({
|
|
978
|
+
run_id: params.runId,
|
|
942
979
|
company_domain: params.companyDomain,
|
|
943
980
|
full_name: params.fullName,
|
|
944
981
|
first_name: params.firstName,
|
|
@@ -978,6 +1015,7 @@ function normalizeCoreProductDryRunResult(data) {
|
|
|
978
1015
|
};
|
|
979
1016
|
}
|
|
980
1017
|
function normalizeFindEmailResult(data) {
|
|
1018
|
+
const processing = String(data.status || "").toLowerCase() === "processing";
|
|
981
1019
|
const failed = coreProductResponseFailed(data);
|
|
982
1020
|
const rawEmail = typeof data.email === "string" && data.email.trim() ? data.email.trim() : null;
|
|
983
1021
|
const email = failed ? null : rawEmail;
|
|
@@ -990,7 +1028,7 @@ function normalizeFindEmailResult(data) {
|
|
|
990
1028
|
const verified = !explicitlyNotSendSafe && (data.is_valid === true || data.isValid === true || data.email_verified === true || data.verified_for_sending === true || ["valid", "deliverable"].includes(String(verificationStatus).toLowerCase()));
|
|
991
1029
|
const verificationAgeDays = typeof data.verification_age_days === "number" && Number.isFinite(data.verification_age_days) ? data.verification_age_days : null;
|
|
992
1030
|
return {
|
|
993
|
-
success: !failed && found,
|
|
1031
|
+
success: processing || !failed && found,
|
|
994
1032
|
found,
|
|
995
1033
|
email,
|
|
996
1034
|
firstName: data.first_name,
|
|
@@ -1017,8 +1055,12 @@ function normalizeFindEmailResult(data) {
|
|
|
1017
1055
|
liveProviderCalled: data.live_provider_called,
|
|
1018
1056
|
openrouterCalled: data.openrouter_called,
|
|
1019
1057
|
byoOpenrouterUsed: data.byo_openrouter_used,
|
|
1020
|
-
error: found ? void 0 : coreProductErrorMessage(data) ?? "No verified email found",
|
|
1021
|
-
errorCode: found ? void 0 : coreProductErrorCode(data) ?? "EMAIL_NOT_FOUND",
|
|
1058
|
+
error: processing || found ? void 0 : coreProductErrorMessage(data) ?? "No verified email found",
|
|
1059
|
+
errorCode: processing || found ? void 0 : coreProductErrorCode(data) ?? "EMAIL_NOT_FOUND",
|
|
1060
|
+
status: processing ? "processing" : "completed",
|
|
1061
|
+
runId: data.run_id,
|
|
1062
|
+
nextPollAfterSeconds: data.next_poll_after_seconds,
|
|
1063
|
+
suggestedAction: data.suggested_action,
|
|
1022
1064
|
raw: data
|
|
1023
1065
|
};
|
|
1024
1066
|
}
|
|
@@ -1154,6 +1196,12 @@ function validateSignalDiscoveryParams(params) {
|
|
|
1154
1196
|
if (query && (query.length < 2 || query.length > 2e3)) {
|
|
1155
1197
|
throw new RangeError("query must contain between 2 and 2000 characters");
|
|
1156
1198
|
}
|
|
1199
|
+
if (params.icpContext !== void 0) {
|
|
1200
|
+
const icpContext = typeof params.icpContext === "string" ? params.icpContext.trim() : "";
|
|
1201
|
+
if (icpContext.length < 2 || icpContext.length > 4e3) {
|
|
1202
|
+
throw new RangeError("icpContext must contain between 2 and 4000 characters");
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1157
1205
|
if (params.limit !== void 0 && (!Number.isInteger(params.limit) || params.limit < 1 || params.limit > 1e3)) {
|
|
1158
1206
|
throw new RangeError("limit must be an integer between 1 and 1000");
|
|
1159
1207
|
}
|
|
@@ -1178,6 +1226,7 @@ function signalDiscoveryRequestBody(params) {
|
|
|
1178
1226
|
}
|
|
1179
1227
|
return compact({
|
|
1180
1228
|
query: params.query?.trim(),
|
|
1229
|
+
icp_context: params.icpContext?.trim(),
|
|
1181
1230
|
limit: params.limit ?? 100,
|
|
1182
1231
|
sources: params.sources,
|
|
1183
1232
|
lookback_days: params.lookbackDays,
|
|
@@ -1203,6 +1252,8 @@ function normalizeSignalDiscoveryResult(params, data) {
|
|
|
1203
1252
|
availableCompanySignalCount: Number.isFinite(Number(data.available_company_signal_count)) ? Number(data.available_company_signal_count) : void 0,
|
|
1204
1253
|
sourceLanes: Array.isArray(data.source_lanes) ? data.source_lanes.filter((lane) => typeof lane === "string") : void 0,
|
|
1205
1254
|
evidenceValidation: data.evidence_validation && typeof data.evidence_validation === "object" ? data.evidence_validation : void 0,
|
|
1255
|
+
discoveryDiagnostics: data.discovery_diagnostics && typeof data.discovery_diagnostics === "object" ? data.discovery_diagnostics : void 0,
|
|
1256
|
+
identityResolution: data.identity_resolution && typeof data.identity_resolution === "object" ? data.identity_resolution : void 0,
|
|
1206
1257
|
costGuardrail: normalizeSignalDiscoveryCostGuardrail(data.cost_guardrail),
|
|
1207
1258
|
warnings: Array.isArray(data.warnings) ? data.warnings.filter((warning) => typeof warning === "string") : void 0,
|
|
1208
1259
|
raw: data
|
|
@@ -1231,7 +1282,15 @@ function normalizeSignalDiscoveryCostGuardrail(value) {
|
|
|
1231
1282
|
guardrail.projected_cost_per_requested_company_signal_usd
|
|
1232
1283
|
),
|
|
1233
1284
|
sourceCostUsd: numberOrNullable(guardrail.source_cost_usd),
|
|
1234
|
-
costSource: ["observed", "catalog_bounded", "mixed", "unavailable"].includes(String(guardrail.cost_source)) ? String(guardrail.cost_source) : void 0,
|
|
1285
|
+
costSource: ["observed", "catalog_preflight", "catalog_bounded", "mixed", "unavailable"].includes(String(guardrail.cost_source)) ? String(guardrail.cost_source) : void 0,
|
|
1286
|
+
identityResolutionCostUsd: numberOrNullable(guardrail.identity_resolution_cost_usd),
|
|
1287
|
+
identityCostSource: [
|
|
1288
|
+
"observed_zero_credit_receipts",
|
|
1289
|
+
"contractual_zero_cost",
|
|
1290
|
+
"not_used",
|
|
1291
|
+
"unavailable"
|
|
1292
|
+
].includes(String(guardrail.identity_cost_source)) ? String(guardrail.identity_cost_source) : void 0,
|
|
1293
|
+
identityProviderRequests: numberOrUndefined(guardrail.identity_provider_requests),
|
|
1235
1294
|
qualifiedCompanySignalCount: numberOrUndefined(guardrail.qualified_company_signal_count),
|
|
1236
1295
|
returnedCompanySignalCount: numberOrUndefined(guardrail.returned_company_signal_count),
|
|
1237
1296
|
availableCompanySignalCount: numberOrUndefined(guardrail.available_company_signal_count),
|
|
@@ -1335,6 +1394,7 @@ function normalizedFindEmailBatchName(request) {
|
|
|
1335
1394
|
function coreProductBatchRequestKey(path, request) {
|
|
1336
1395
|
if (path === "api/v1/find-email") {
|
|
1337
1396
|
return JSON.stringify([
|
|
1397
|
+
normalizedBatchText(request.run_id),
|
|
1338
1398
|
normalizedFindEmailBatchName(request),
|
|
1339
1399
|
normalizedBatchDomain(request.company_domain),
|
|
1340
1400
|
normalizedBatchLinkedIn(request.linkedin_url),
|
|
@@ -1440,6 +1500,7 @@ function signalToCopyRequestBody(params) {
|
|
|
1440
1500
|
title: params.title,
|
|
1441
1501
|
campaign_offer: params.campaignOffer,
|
|
1442
1502
|
research_prompt: params.researchPrompt,
|
|
1503
|
+
lookback_days: params.lookbackDays,
|
|
1443
1504
|
signal_run_id: params.signalRunId,
|
|
1444
1505
|
skip_cache: params.skipCache,
|
|
1445
1506
|
enable_deep_search: params.enableDeepSearch,
|
|
@@ -1450,6 +1511,9 @@ function signalToCopyRequestBody(params) {
|
|
|
1450
1511
|
}
|
|
1451
1512
|
function validateSignalToCopyParams(params) {
|
|
1452
1513
|
validateCoreProductMaxWaitMs(params.maxWaitMs);
|
|
1514
|
+
if (params.lookbackDays !== void 0 && (!Number.isInteger(params.lookbackDays) || params.lookbackDays < 1 || params.lookbackDays > 365)) {
|
|
1515
|
+
throw new RangeError("lookbackDays must be an integer between 1 and 365");
|
|
1516
|
+
}
|
|
1453
1517
|
if (typeof params.signalRunId === "string" && params.signalRunId.trim()) return;
|
|
1454
1518
|
const missing = [
|
|
1455
1519
|
["companyDomain", params.companyDomain],
|
package/dist/index.mjs
CHANGED
package/dist/mcp-config.js
CHANGED
|
@@ -40,17 +40,21 @@ var SignalizError = class extends Error {
|
|
|
40
40
|
this.details = data.details;
|
|
41
41
|
}
|
|
42
42
|
get isRetryable() {
|
|
43
|
+
if (typeof this.details?.retry_eligible === "boolean") {
|
|
44
|
+
return this.details.retry_eligible;
|
|
45
|
+
}
|
|
43
46
|
return this.errorType === "rate_limited" || this.errorType === "timeout" || this.errorType === "provider_error";
|
|
44
47
|
}
|
|
45
48
|
};
|
|
46
49
|
function parseError(status, body) {
|
|
47
50
|
if (body?.error && typeof body.error === "object") {
|
|
51
|
+
const nestedDetails = body.error.details && typeof body.error.details === "object" ? body.error.details : {};
|
|
48
52
|
return new SignalizError({
|
|
49
53
|
code: body.error.code || `HTTP_${status}`,
|
|
50
54
|
message: body.error.message || `Request failed with status ${status}`,
|
|
51
55
|
errorType: mapErrorType(body.error.code, status),
|
|
52
56
|
retryAfter: retryAfterSeconds(body.error),
|
|
53
|
-
details: body.error
|
|
57
|
+
details: mergePublicErrorDetails({ ...body, ...body.error }, nestedDetails)
|
|
54
58
|
});
|
|
55
59
|
}
|
|
56
60
|
const code = typeof body?.error_code === "string" && body.error_code.trim() ? body.error_code.trim() : `HTTP_${status}`;
|
|
@@ -59,7 +63,7 @@ function parseError(status, body) {
|
|
|
59
63
|
message: body?.message || body?.error || `Request failed with status ${status}`,
|
|
60
64
|
errorType: mapErrorType(code, status),
|
|
61
65
|
retryAfter: retryAfterSeconds(body),
|
|
62
|
-
details: body?.details
|
|
66
|
+
details: mergePublicErrorDetails(body, body?.details)
|
|
63
67
|
});
|
|
64
68
|
}
|
|
65
69
|
function retryAfterSeconds(body) {
|
|
@@ -71,13 +75,26 @@ function publicRetryDetails(body) {
|
|
|
71
75
|
...body?.retry_eligible !== void 0 ? { retry_eligible: body.retry_eligible } : {},
|
|
72
76
|
...body?.retry_after !== void 0 ? { retry_after: body.retry_after } : {},
|
|
73
77
|
...body?.retry_after_seconds !== void 0 ? { retry_after_seconds: body.retry_after_seconds } : {},
|
|
78
|
+
...body?.retry_strategy !== void 0 ? { retry_strategy: body.retry_strategy } : {},
|
|
79
|
+
...body?.credits_used !== void 0 ? { credits_used: body.credits_used } : {},
|
|
80
|
+
...body?.credits_charged !== void 0 ? { credits_charged: body.credits_charged } : {},
|
|
81
|
+
...body?.job_id !== void 0 ? { job_id: body.job_id } : {},
|
|
82
|
+
...body?.verification_run_id !== void 0 ? { verification_run_id: body.verification_run_id } : {},
|
|
74
83
|
...body?.run_id !== void 0 ? { run_id: body.run_id } : {},
|
|
84
|
+
...body?.suggested_action !== void 0 ? { suggested_action: body.suggested_action } : {},
|
|
75
85
|
...body?.signal_run_id !== void 0 ? { signal_run_id: body.signal_run_id } : {},
|
|
76
86
|
...body?.company_signal_run_id !== void 0 ? { company_signal_run_id: body.company_signal_run_id } : {},
|
|
77
87
|
...body?.resume_context_persisted !== void 0 ? { resume_context_persisted: body.resume_context_persisted } : {}
|
|
78
88
|
};
|
|
79
89
|
return Object.keys(details).length > 0 ? details : void 0;
|
|
80
90
|
}
|
|
91
|
+
function mergePublicErrorDetails(body, explicitDetails) {
|
|
92
|
+
const merged = { ...publicRetryDetails(body) || {} };
|
|
93
|
+
if (explicitDetails && typeof explicitDetails === "object" && !Array.isArray(explicitDetails)) {
|
|
94
|
+
Object.assign(merged, explicitDetails);
|
|
95
|
+
}
|
|
96
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
97
|
+
}
|
|
81
98
|
function mapErrorType(code, status) {
|
|
82
99
|
if (code === "RATE_LIMITED" || status === 429) return "rate_limited";
|
|
83
100
|
if (code === "VALIDATION_ERROR" || code === "SIGNAL_RUN_COMPANY_MISMATCH" || status === 400) return "validation";
|
|
@@ -139,7 +156,9 @@ var HttpClient = class {
|
|
|
139
156
|
const errBody = await res.json().catch(() => ({}));
|
|
140
157
|
const err = parseError(res.status, errBody);
|
|
141
158
|
if (err.isRetryable && attempt < this.maxRetries) {
|
|
142
|
-
const
|
|
159
|
+
const retryWithNewKey = err.details?.retry_strategy === "new_idempotency_key" && err.details?.credits_used === 0 && err.details?.credits_charged === 0;
|
|
160
|
+
if (retryWithNewKey) throw err;
|
|
161
|
+
const wait = err.retryAfter !== void 0 ? err.retryAfter * 1e3 : Math.min(1e3 * Math.pow(2, attempt), 1e4);
|
|
143
162
|
await sleep(wait);
|
|
144
163
|
lastError = err;
|
|
145
164
|
continue;
|
|
@@ -796,7 +815,10 @@ var Signaliz = class {
|
|
|
796
815
|
);
|
|
797
816
|
const uniqueTasks = deduplicated.uniqueItems;
|
|
798
817
|
const recoverableBatch = path2 === "api/v1/find-email" ? { label: "Find Email", pageSize: 500, maxWaitMs: 20 * 6e4 } : path2 === "api/v1/verify-email" ? { label: "Verify Email", pageSize: 500, maxWaitMs: 20 * 6e4 } : void 0;
|
|
799
|
-
|
|
818
|
+
const containsFindRecoveryReads = path2 === "api/v1/find-email" && uniqueTasks.some(
|
|
819
|
+
(task) => typeof task.request.run_id === "string" && task.request.run_id.trim()
|
|
820
|
+
);
|
|
821
|
+
if (path2 !== "api/v1/company-signals" && recoverableBatch && uniqueTasks.length > 25 && !containsFindRecoveryReads) {
|
|
800
822
|
const rows = await this.runRecoverableCoreBatchJob(
|
|
801
823
|
path2,
|
|
802
824
|
uniqueTasks.map((task) => task.request),
|
|
@@ -922,13 +944,27 @@ function batchItemFailure(index, error, raw) {
|
|
|
922
944
|
raw?.retry_after_seconds ?? raw?.retry_after ?? raw?.retryAfterSeconds ?? (Number.isFinite(Number(raw?.retry_after_ms)) ? Number(raw?.retry_after_ms) / 1e3 : void 0)
|
|
923
945
|
);
|
|
924
946
|
const retryEligible = raw?.retry_eligible ?? raw?.retryEligible;
|
|
947
|
+
const retryStrategy = raw?.retry_strategy ?? raw?.retryStrategy;
|
|
948
|
+
const creditsUsed = raw?.credits_used ?? raw?.creditsUsed;
|
|
949
|
+
const creditsCharged = raw?.credits_charged ?? raw?.creditsCharged;
|
|
950
|
+
const runId = raw?.run_id ?? raw?.runId;
|
|
951
|
+
const verificationRunId = raw?.verification_run_id ?? raw?.verificationRunId;
|
|
952
|
+
const jobId = raw?.job_id ?? raw?.jobId;
|
|
953
|
+
const suggestedAction = raw?.suggested_action ?? raw?.suggestedAction;
|
|
925
954
|
return {
|
|
926
955
|
index,
|
|
927
956
|
success: false,
|
|
928
957
|
error,
|
|
929
958
|
...errorCode ? { errorCode } : {},
|
|
930
959
|
...typeof retryEligible === "boolean" ? { retryEligible } : {},
|
|
931
|
-
...Number.isFinite(retryAfterSeconds2) && retryAfterSeconds2 >= 0 ? { retryAfterSeconds: retryAfterSeconds2 } : {}
|
|
960
|
+
...Number.isFinite(retryAfterSeconds2) && retryAfterSeconds2 >= 0 ? { retryAfterSeconds: retryAfterSeconds2 } : {},
|
|
961
|
+
...retryStrategy === "new_idempotency_key" ? { retryStrategy } : {},
|
|
962
|
+
...creditsUsed === 0 ? { creditsUsed: 0 } : {},
|
|
963
|
+
...creditsCharged === 0 ? { creditsCharged: 0 } : {},
|
|
964
|
+
...typeof runId === "string" && runId.trim() ? { runId: runId.trim() } : {},
|
|
965
|
+
...typeof verificationRunId === "string" && verificationRunId.trim() ? { verificationRunId: verificationRunId.trim() } : {},
|
|
966
|
+
...typeof jobId === "string" && jobId.trim() ? { jobId: jobId.trim() } : {},
|
|
967
|
+
...typeof suggestedAction === "string" && suggestedAction.trim() ? { suggestedAction: suggestedAction.trim() } : {}
|
|
932
968
|
};
|
|
933
969
|
}
|
|
934
970
|
function recoverableJobRowFailed(row) {
|
|
@@ -943,6 +979,7 @@ function compact(input) {
|
|
|
943
979
|
}
|
|
944
980
|
function findEmailRequestBody(params) {
|
|
945
981
|
return compact({
|
|
982
|
+
run_id: params.runId,
|
|
946
983
|
company_domain: params.companyDomain,
|
|
947
984
|
full_name: params.fullName,
|
|
948
985
|
first_name: params.firstName,
|
|
@@ -982,6 +1019,7 @@ function normalizeCoreProductDryRunResult(data) {
|
|
|
982
1019
|
};
|
|
983
1020
|
}
|
|
984
1021
|
function normalizeFindEmailResult(data) {
|
|
1022
|
+
const processing = String(data.status || "").toLowerCase() === "processing";
|
|
985
1023
|
const failed = coreProductResponseFailed(data);
|
|
986
1024
|
const rawEmail = typeof data.email === "string" && data.email.trim() ? data.email.trim() : null;
|
|
987
1025
|
const email = failed ? null : rawEmail;
|
|
@@ -994,7 +1032,7 @@ function normalizeFindEmailResult(data) {
|
|
|
994
1032
|
const verified = !explicitlyNotSendSafe && (data.is_valid === true || data.isValid === true || data.email_verified === true || data.verified_for_sending === true || ["valid", "deliverable"].includes(String(verificationStatus).toLowerCase()));
|
|
995
1033
|
const verificationAgeDays = typeof data.verification_age_days === "number" && Number.isFinite(data.verification_age_days) ? data.verification_age_days : null;
|
|
996
1034
|
return {
|
|
997
|
-
success: !failed && found,
|
|
1035
|
+
success: processing || !failed && found,
|
|
998
1036
|
found,
|
|
999
1037
|
email,
|
|
1000
1038
|
firstName: data.first_name,
|
|
@@ -1021,8 +1059,12 @@ function normalizeFindEmailResult(data) {
|
|
|
1021
1059
|
liveProviderCalled: data.live_provider_called,
|
|
1022
1060
|
openrouterCalled: data.openrouter_called,
|
|
1023
1061
|
byoOpenrouterUsed: data.byo_openrouter_used,
|
|
1024
|
-
error: found ? void 0 : coreProductErrorMessage(data) ?? "No verified email found",
|
|
1025
|
-
errorCode: found ? void 0 : coreProductErrorCode(data) ?? "EMAIL_NOT_FOUND",
|
|
1062
|
+
error: processing || found ? void 0 : coreProductErrorMessage(data) ?? "No verified email found",
|
|
1063
|
+
errorCode: processing || found ? void 0 : coreProductErrorCode(data) ?? "EMAIL_NOT_FOUND",
|
|
1064
|
+
status: processing ? "processing" : "completed",
|
|
1065
|
+
runId: data.run_id,
|
|
1066
|
+
nextPollAfterSeconds: data.next_poll_after_seconds,
|
|
1067
|
+
suggestedAction: data.suggested_action,
|
|
1026
1068
|
raw: data
|
|
1027
1069
|
};
|
|
1028
1070
|
}
|
|
@@ -1158,6 +1200,12 @@ function validateSignalDiscoveryParams(params) {
|
|
|
1158
1200
|
if (query && (query.length < 2 || query.length > 2e3)) {
|
|
1159
1201
|
throw new RangeError("query must contain between 2 and 2000 characters");
|
|
1160
1202
|
}
|
|
1203
|
+
if (params.icpContext !== void 0) {
|
|
1204
|
+
const icpContext = typeof params.icpContext === "string" ? params.icpContext.trim() : "";
|
|
1205
|
+
if (icpContext.length < 2 || icpContext.length > 4e3) {
|
|
1206
|
+
throw new RangeError("icpContext must contain between 2 and 4000 characters");
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1161
1209
|
if (params.limit !== void 0 && (!Number.isInteger(params.limit) || params.limit < 1 || params.limit > 1e3)) {
|
|
1162
1210
|
throw new RangeError("limit must be an integer between 1 and 1000");
|
|
1163
1211
|
}
|
|
@@ -1182,6 +1230,7 @@ function signalDiscoveryRequestBody(params) {
|
|
|
1182
1230
|
}
|
|
1183
1231
|
return compact({
|
|
1184
1232
|
query: params.query?.trim(),
|
|
1233
|
+
icp_context: params.icpContext?.trim(),
|
|
1185
1234
|
limit: params.limit ?? 100,
|
|
1186
1235
|
sources: params.sources,
|
|
1187
1236
|
lookback_days: params.lookbackDays,
|
|
@@ -1207,6 +1256,8 @@ function normalizeSignalDiscoveryResult(params, data) {
|
|
|
1207
1256
|
availableCompanySignalCount: Number.isFinite(Number(data.available_company_signal_count)) ? Number(data.available_company_signal_count) : void 0,
|
|
1208
1257
|
sourceLanes: Array.isArray(data.source_lanes) ? data.source_lanes.filter((lane) => typeof lane === "string") : void 0,
|
|
1209
1258
|
evidenceValidation: data.evidence_validation && typeof data.evidence_validation === "object" ? data.evidence_validation : void 0,
|
|
1259
|
+
discoveryDiagnostics: data.discovery_diagnostics && typeof data.discovery_diagnostics === "object" ? data.discovery_diagnostics : void 0,
|
|
1260
|
+
identityResolution: data.identity_resolution && typeof data.identity_resolution === "object" ? data.identity_resolution : void 0,
|
|
1210
1261
|
costGuardrail: normalizeSignalDiscoveryCostGuardrail(data.cost_guardrail),
|
|
1211
1262
|
warnings: Array.isArray(data.warnings) ? data.warnings.filter((warning) => typeof warning === "string") : void 0,
|
|
1212
1263
|
raw: data
|
|
@@ -1235,7 +1286,15 @@ function normalizeSignalDiscoveryCostGuardrail(value) {
|
|
|
1235
1286
|
guardrail.projected_cost_per_requested_company_signal_usd
|
|
1236
1287
|
),
|
|
1237
1288
|
sourceCostUsd: numberOrNullable(guardrail.source_cost_usd),
|
|
1238
|
-
costSource: ["observed", "catalog_bounded", "mixed", "unavailable"].includes(String(guardrail.cost_source)) ? String(guardrail.cost_source) : void 0,
|
|
1289
|
+
costSource: ["observed", "catalog_preflight", "catalog_bounded", "mixed", "unavailable"].includes(String(guardrail.cost_source)) ? String(guardrail.cost_source) : void 0,
|
|
1290
|
+
identityResolutionCostUsd: numberOrNullable(guardrail.identity_resolution_cost_usd),
|
|
1291
|
+
identityCostSource: [
|
|
1292
|
+
"observed_zero_credit_receipts",
|
|
1293
|
+
"contractual_zero_cost",
|
|
1294
|
+
"not_used",
|
|
1295
|
+
"unavailable"
|
|
1296
|
+
].includes(String(guardrail.identity_cost_source)) ? String(guardrail.identity_cost_source) : void 0,
|
|
1297
|
+
identityProviderRequests: numberOrUndefined(guardrail.identity_provider_requests),
|
|
1239
1298
|
qualifiedCompanySignalCount: numberOrUndefined(guardrail.qualified_company_signal_count),
|
|
1240
1299
|
returnedCompanySignalCount: numberOrUndefined(guardrail.returned_company_signal_count),
|
|
1241
1300
|
availableCompanySignalCount: numberOrUndefined(guardrail.available_company_signal_count),
|
|
@@ -1339,6 +1398,7 @@ function normalizedFindEmailBatchName(request) {
|
|
|
1339
1398
|
function coreProductBatchRequestKey(path2, request) {
|
|
1340
1399
|
if (path2 === "api/v1/find-email") {
|
|
1341
1400
|
return JSON.stringify([
|
|
1401
|
+
normalizedBatchText(request.run_id),
|
|
1342
1402
|
normalizedFindEmailBatchName(request),
|
|
1343
1403
|
normalizedBatchDomain(request.company_domain),
|
|
1344
1404
|
normalizedBatchLinkedIn(request.linkedin_url),
|
|
@@ -1444,6 +1504,7 @@ function signalToCopyRequestBody(params) {
|
|
|
1444
1504
|
title: params.title,
|
|
1445
1505
|
campaign_offer: params.campaignOffer,
|
|
1446
1506
|
research_prompt: params.researchPrompt,
|
|
1507
|
+
lookback_days: params.lookbackDays,
|
|
1447
1508
|
signal_run_id: params.signalRunId,
|
|
1448
1509
|
skip_cache: params.skipCache,
|
|
1449
1510
|
enable_deep_search: params.enableDeepSearch,
|
|
@@ -1454,6 +1515,9 @@ function signalToCopyRequestBody(params) {
|
|
|
1454
1515
|
}
|
|
1455
1516
|
function validateSignalToCopyParams(params) {
|
|
1456
1517
|
validateCoreProductMaxWaitMs(params.maxWaitMs);
|
|
1518
|
+
if (params.lookbackDays !== void 0 && (!Number.isInteger(params.lookbackDays) || params.lookbackDays < 1 || params.lookbackDays > 365)) {
|
|
1519
|
+
throw new RangeError("lookbackDays must be an integer between 1 and 365");
|
|
1520
|
+
}
|
|
1457
1521
|
if (typeof params.signalRunId === "string" && params.signalRunId.trim()) return;
|
|
1458
1522
|
const missing = [
|
|
1459
1523
|
["companyDomain", params.companyDomain],
|
package/dist/mcp-config.mjs
CHANGED
package/package.json
CHANGED