@synterai/sdk-js 0.1.1 → 0.2.0
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/CHANGELOG.md +11 -0
- package/README.md +66 -4
- package/dist/index.d.mts +187 -11
- package/dist/index.d.ts +187 -11
- package/dist/index.js +222 -19
- package/dist/index.mjs +217 -19
- package/package.json +9 -8
package/dist/index.d.ts
CHANGED
|
@@ -153,6 +153,34 @@ declare class CampaignsResource {
|
|
|
153
153
|
* dispatches with `platform=google` regardless of input.
|
|
154
154
|
*/
|
|
155
155
|
updateBudget(input: UpdateCampaignBudgetInput): Promise<Record<string, unknown>>;
|
|
156
|
+
/**
|
|
157
|
+
* Update campaign budget with deterministic readback verification.
|
|
158
|
+
*
|
|
159
|
+
* Executes the budget update, waits for propagation, and reads back
|
|
160
|
+
* campaign status from the platform to verify the update succeeded on the wire.
|
|
161
|
+
*/
|
|
162
|
+
updateBudgetAndVerify(input: UpdateCampaignBudgetInput & {
|
|
163
|
+
maxWaitMs?: number;
|
|
164
|
+
pollIntervalMs?: number;
|
|
165
|
+
}): Promise<{
|
|
166
|
+
mutation: Record<string, unknown>;
|
|
167
|
+
verified: boolean;
|
|
168
|
+
readback?: Record<string, unknown>;
|
|
169
|
+
}>;
|
|
170
|
+
/**
|
|
171
|
+
* Pause a campaign with deterministic readback verification.
|
|
172
|
+
*
|
|
173
|
+
* Executes the pause command, waits for propagation, and reads back
|
|
174
|
+
* campaign status from the platform to verify status === 'PAUSED' on the wire.
|
|
175
|
+
*/
|
|
176
|
+
pauseAndVerify(input: PauseCampaignInput & {
|
|
177
|
+
maxWaitMs?: number;
|
|
178
|
+
pollIntervalMs?: number;
|
|
179
|
+
}): Promise<{
|
|
180
|
+
mutation: Record<string, unknown>;
|
|
181
|
+
verified: boolean;
|
|
182
|
+
readback?: Record<string, unknown>;
|
|
183
|
+
}>;
|
|
156
184
|
}
|
|
157
185
|
|
|
158
186
|
/**
|
|
@@ -161,9 +189,7 @@ declare class CampaignsResource {
|
|
|
161
189
|
* Both are custom-dispatch per SPEC.md's testing bar (not forced through
|
|
162
190
|
* the generic argMapping-only path): get_performance has a platform-scoped
|
|
163
191
|
* `onlyForPlatform` flag and a `dateRangeToDays` transform; get_daily_spend
|
|
164
|
-
*
|
|
165
|
-
* any other tool) also re-emits that resolved platform as an uppercased
|
|
166
|
-
* CLI flag.
|
|
192
|
+
* uses the same platform-routed pull scripts with `--days` (default 7).
|
|
167
193
|
*/
|
|
168
194
|
|
|
169
195
|
interface GetPerformanceInput {
|
|
@@ -219,7 +245,8 @@ declare class KeywordsResource {
|
|
|
219
245
|
|
|
220
246
|
/**
|
|
221
247
|
* `conversions` category — catalog.json tools: create_conversion,
|
|
222
|
-
* list_conversions, diagnose_tracking
|
|
248
|
+
* list_conversions, diagnose_tracking, get_pixel_health,
|
|
249
|
+
* list_event_deliveries, get_click_attribution.
|
|
223
250
|
*/
|
|
224
251
|
|
|
225
252
|
interface CreateConversionInput {
|
|
@@ -234,6 +261,21 @@ interface DiagnoseTrackingInput {
|
|
|
234
261
|
/** Website URL to check. */
|
|
235
262
|
url: string;
|
|
236
263
|
}
|
|
264
|
+
interface GetPixelHealthInput {
|
|
265
|
+
site_key?: string;
|
|
266
|
+
}
|
|
267
|
+
interface ListEventDeliveriesInput {
|
|
268
|
+
site_key?: string;
|
|
269
|
+
status?: 'PENDING' | 'SUCCESS' | 'RETRYING' | 'FAILED';
|
|
270
|
+
platform?: string;
|
|
271
|
+
limit?: number;
|
|
272
|
+
}
|
|
273
|
+
interface GetClickAttributionInput {
|
|
274
|
+
site_key?: string;
|
|
275
|
+
user_id?: number;
|
|
276
|
+
email?: string;
|
|
277
|
+
limit?: number;
|
|
278
|
+
}
|
|
237
279
|
declare class ConversionsResource {
|
|
238
280
|
private readonly client;
|
|
239
281
|
constructor(client: Synter);
|
|
@@ -252,6 +294,9 @@ declare class ConversionsResource {
|
|
|
252
294
|
* credentials (SPEC.md's "Platform resolution" rule 3).
|
|
253
295
|
*/
|
|
254
296
|
diagnoseTracking(input: DiagnoseTrackingInput): Promise<Record<string, unknown>>;
|
|
297
|
+
getPixelHealth(input?: GetPixelHealthInput): Promise<Record<string, unknown>>;
|
|
298
|
+
listEventDeliveries(input?: ListEventDeliveriesInput): Promise<Record<string, unknown>>;
|
|
299
|
+
getClickAttribution(input?: GetClickAttributionInput): Promise<Record<string, unknown>>;
|
|
255
300
|
}
|
|
256
301
|
|
|
257
302
|
/**
|
|
@@ -421,7 +466,7 @@ declare class AudiencesResource {
|
|
|
421
466
|
* identifiers inline when over ~500 entries.
|
|
422
467
|
*
|
|
423
468
|
* Bypasses the primary `tools/run` dispatcher: different host
|
|
424
|
-
* (`https://api.
|
|
469
|
+
* (`https://api.synterai.com`) and a different auth header
|
|
425
470
|
* (`X-Synter-Key`, not `Authorization: Bearer`) — see SPEC.md/catalog.json
|
|
426
471
|
* `transport.special`.
|
|
427
472
|
*/
|
|
@@ -444,6 +489,127 @@ declare class AudiencesResource {
|
|
|
444
489
|
manage(input: ManageAudienceInput): Promise<Record<string, unknown>>;
|
|
445
490
|
}
|
|
446
491
|
|
|
492
|
+
/**
|
|
493
|
+
* `shield` category — Agent Shield spend limits, burst thresholds,
|
|
494
|
+
* circuit breakers, and kill-switch inspection.
|
|
495
|
+
*/
|
|
496
|
+
|
|
497
|
+
interface InspectShieldInput {
|
|
498
|
+
platform?: AdPlatform;
|
|
499
|
+
}
|
|
500
|
+
interface AgentShieldPolicy {
|
|
501
|
+
policy_id: string;
|
|
502
|
+
name: string;
|
|
503
|
+
enforced: boolean;
|
|
504
|
+
max_daily_spend_usd: number;
|
|
505
|
+
max_hourly_spend_usd: number;
|
|
506
|
+
burst_threshold_multiplier: number;
|
|
507
|
+
circuit_breaker_active: boolean;
|
|
508
|
+
kill_switch_engaged: boolean;
|
|
509
|
+
}
|
|
510
|
+
declare class ShieldResource {
|
|
511
|
+
private readonly client;
|
|
512
|
+
constructor(client: Synter);
|
|
513
|
+
/**
|
|
514
|
+
* Inspect Agent Shield velocity limits, burst thresholds, circuit breakers,
|
|
515
|
+
* and kill-switch status before executing ad-spend mutations.
|
|
516
|
+
*/
|
|
517
|
+
inspect(input?: InspectShieldInput): Promise<{
|
|
518
|
+
status: 'ACTIVE' | 'TRIPPED' | 'PAUSED';
|
|
519
|
+
policies: AgentShieldPolicy[];
|
|
520
|
+
kill_switch_engaged: boolean;
|
|
521
|
+
notice: string;
|
|
522
|
+
}>;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* `angstrom` category — Synter Ångström attribution claim verification.
|
|
527
|
+
*/
|
|
528
|
+
|
|
529
|
+
interface VerifyAngstromClaimInput {
|
|
530
|
+
platform?: AdPlatform;
|
|
531
|
+
claimed_conversions?: number;
|
|
532
|
+
claimed_revenue_usd?: number;
|
|
533
|
+
touchpoint_ids?: string[];
|
|
534
|
+
}
|
|
535
|
+
interface AngstromVerificationResult {
|
|
536
|
+
confidence_score: number;
|
|
537
|
+
verdict: 'VERIFIED' | 'DISPUTED' | 'UNVERIFIABLE';
|
|
538
|
+
incremental_lift_multiplier: number;
|
|
539
|
+
deterministic_touchpoints_verified: number;
|
|
540
|
+
rubric: {
|
|
541
|
+
single_touch_discount: number;
|
|
542
|
+
cross_network_dedup_factor: number;
|
|
543
|
+
latency_decay_score: number;
|
|
544
|
+
};
|
|
545
|
+
explanation: string;
|
|
546
|
+
}
|
|
547
|
+
declare class AngstromResource {
|
|
548
|
+
private readonly client;
|
|
549
|
+
constructor(client: Synter);
|
|
550
|
+
/**
|
|
551
|
+
* Verify attribution claims against Synter Ångström's deterministic confidence rubric.
|
|
552
|
+
*/
|
|
553
|
+
verify(input?: VerifyAngstromClaimInput): Promise<AngstromVerificationResult>;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* `skills` category — Core autonomous growth playbooks.
|
|
558
|
+
*/
|
|
559
|
+
|
|
560
|
+
type GrowthSkillId = 'pmax-brand-cannibalization' | 'search-hygiene-shield' | 'marginal-cpa-budget-rebalancer' | 'meta-asc-dark-pool-auditor' | 'single-truth-attribution';
|
|
561
|
+
interface GrowthSkillPlaybook {
|
|
562
|
+
skill_id: GrowthSkillId;
|
|
563
|
+
name: string;
|
|
564
|
+
category: string;
|
|
565
|
+
description: string;
|
|
566
|
+
required_tools: string[];
|
|
567
|
+
execution_steps: string[];
|
|
568
|
+
safety_checks: string[];
|
|
569
|
+
expected_outcome: string;
|
|
570
|
+
}
|
|
571
|
+
declare class SkillsResource {
|
|
572
|
+
private readonly client;
|
|
573
|
+
constructor(client: Synter);
|
|
574
|
+
/**
|
|
575
|
+
* Load an autonomous growth runbook by ID.
|
|
576
|
+
*/
|
|
577
|
+
get(skillId: GrowthSkillId): Promise<GrowthSkillPlaybook>;
|
|
578
|
+
/**
|
|
579
|
+
* List available autonomous growth runbook IDs.
|
|
580
|
+
*/
|
|
581
|
+
list(): GrowthSkillId[];
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* `visibility` category — LLM search brand visibility and AEO share of voice.
|
|
586
|
+
*/
|
|
587
|
+
|
|
588
|
+
interface GetVisibilityInput {
|
|
589
|
+
query?: string;
|
|
590
|
+
competitor_domains?: string[];
|
|
591
|
+
}
|
|
592
|
+
interface EngineVisibilityScore {
|
|
593
|
+
engine: 'chatgpt' | 'claude' | 'perplexity' | 'gemini';
|
|
594
|
+
share_of_voice_pct: number;
|
|
595
|
+
mention_count: number;
|
|
596
|
+
ranking_position_avg: number;
|
|
597
|
+
}
|
|
598
|
+
interface VisibilityReportResult {
|
|
599
|
+
brand: string;
|
|
600
|
+
overall_aeo_score: number;
|
|
601
|
+
engines: EngineVisibilityScore[];
|
|
602
|
+
recommendations: string[];
|
|
603
|
+
}
|
|
604
|
+
declare class VisibilityResource {
|
|
605
|
+
private readonly client;
|
|
606
|
+
constructor(client: Synter);
|
|
607
|
+
/**
|
|
608
|
+
* Read AI search brand visibility and AEO share of voice across ChatGPT, Claude, Perplexity, and Gemini.
|
|
609
|
+
*/
|
|
610
|
+
get(input?: GetVisibilityInput): Promise<VisibilityReportResult>;
|
|
611
|
+
}
|
|
612
|
+
|
|
447
613
|
/**
|
|
448
614
|
* Amp Custom Advertising Toolbox
|
|
449
615
|
*
|
|
@@ -963,19 +1129,22 @@ declare class SynterValidationError extends Error {
|
|
|
963
1129
|
* Main Synter SDK client.
|
|
964
1130
|
*
|
|
965
1131
|
* Transport per SPEC.md: nearly every tool dispatches through
|
|
966
|
-
* `POST /api/v1/tools/run` on `https://
|
|
1132
|
+
* `POST /api/v1/tools/run` on `https://synterai.com` with
|
|
967
1133
|
* `{ script_name, args, platform? }`, auth via `Authorization: Bearer <key>`.
|
|
968
1134
|
* Two tools bypass that dispatcher (`list_landing_pages`, `stage_audience_artifact`)
|
|
969
1135
|
* — see `resources/audiences.ts` and `listLandingPages` below.
|
|
970
1136
|
*/
|
|
971
1137
|
|
|
972
1138
|
/** Real, production base URL — see SPEC.md's "Transport" section. */
|
|
973
|
-
declare const DEFAULT_BASE_URL = "https://
|
|
1139
|
+
declare const DEFAULT_BASE_URL = "https://synterai.com";
|
|
1140
|
+
declare const DEFAULT_ARTIFACT_BASE_URL = "https://api.synterai.com";
|
|
974
1141
|
interface SynterConfig {
|
|
975
|
-
/** `syn_` + 32 base64url characters, issued at
|
|
1142
|
+
/** `syn_` + 32 base64url characters, issued at synterai.com/developer. */
|
|
976
1143
|
apiKey: string;
|
|
977
|
-
/**
|
|
1144
|
+
/** Primary API URL. Takes precedence over SYNTER_API_URL in Node.js. */
|
|
978
1145
|
baseUrl?: string;
|
|
1146
|
+
/** Artifact API URL. Takes precedence over SYNTER_ARTIFACT_API_URL in Node.js. */
|
|
1147
|
+
artifactBaseUrl?: string;
|
|
979
1148
|
/** Request timeout in ms. Default 30000 (30s), per SPEC.md. */
|
|
980
1149
|
timeout?: number;
|
|
981
1150
|
/** Max retry attempts for 429s and network/timeout errors. Default 3, per SPEC.md. */
|
|
@@ -1000,6 +1169,7 @@ interface UploadImageInput {
|
|
|
1000
1169
|
declare class Synter {
|
|
1001
1170
|
private readonly apiKey;
|
|
1002
1171
|
private readonly baseUrl;
|
|
1172
|
+
private readonly artifactBaseUrl;
|
|
1003
1173
|
private readonly timeout;
|
|
1004
1174
|
private readonly maxRetries;
|
|
1005
1175
|
private readonly fetchImpl;
|
|
@@ -1012,6 +1182,10 @@ declare class Synter {
|
|
|
1012
1182
|
readonly linkedin: LinkedInResource;
|
|
1013
1183
|
readonly reddit: RedditResource;
|
|
1014
1184
|
readonly audiences: AudiencesResource;
|
|
1185
|
+
readonly shield: ShieldResource;
|
|
1186
|
+
readonly angstrom: AngstromResource;
|
|
1187
|
+
readonly skills: SkillsResource;
|
|
1188
|
+
readonly visibility: VisibilityResource;
|
|
1015
1189
|
/** AI-powered advertising toolbox for Amp integration — unchanged, out of scope for the transport rewrite. */
|
|
1016
1190
|
readonly amp: AmpToolbox;
|
|
1017
1191
|
constructor(config: SynterConfig | string, ampConfig?: AmpToolboxConfig);
|
|
@@ -1045,7 +1219,9 @@ declare class Synter {
|
|
|
1045
1219
|
*/
|
|
1046
1220
|
listLandingPages(): Promise<Record<string, unknown>>;
|
|
1047
1221
|
private authHeaders;
|
|
1048
|
-
/**
|
|
1222
|
+
/** Artifact host used by audience staging. */
|
|
1223
|
+
getArtifactBaseUrl(): string;
|
|
1224
|
+
/** The raw API key, for tools that need a non-Bearer header. */
|
|
1049
1225
|
getApiKey(): string;
|
|
1050
1226
|
/**
|
|
1051
1227
|
* Low-level generic HTTP helper retained for `AmpToolbox` and any other
|
|
@@ -1257,4 +1433,4 @@ declare function normalizeConversionEvent(params: {
|
|
|
1257
1433
|
metadata?: Record<string, any>;
|
|
1258
1434
|
}): AnalyticsEvent;
|
|
1259
1435
|
|
|
1260
|
-
export { type AdPlatform, type AddKeywordsInput, type AddNegativeKeywordsInput, AmpToolbox, type AmpToolboxConfig, type AnalyticsEvent, type AnalyticsIntegration, type AnalyticsIntegrationConfig, AnalyticsIntegrationManager, type AnalyticsPlatform, AnalyticsResource, AudiencesResource, type CampaignBriefInput, CampaignsResource, type ConversionPayload, ConversionsResource, type CreateConversionInput, type CreateDisplayCampaignInput, type CreateLinkedInCampaignInput, type CreateMetaCampaignInput, type CreatePmaxCampaignInput, type CreateRedditCampaignInput, type CreateSearchCampaignInput, CreativeResource, type CreativeVariant, DEFAULT_BASE_URL, type DateRange, type DiagnoseTrackingInput, type GenerateImageInput, type GenerateVideoInput, type GeneratedCampaign, type GetDailySpendInput, type GetPerformanceInput, KeywordsResource, LinkedInResource, type ListCampaignsInput, type ManageAudienceInput, MetaResource, type OptimizationRecommendation, type PauseCampaignInput, type Platform, type PlatformConnection, type PlatformStatus, RedditResource, type StageAudienceArtifactInput, type StageAudienceArtifactResult, type SyncAudienceInput, Synter, type SynterConfig, SynterError, SynterValidationError, type TrackingParams, type UTMParameters, type UTMTemplate, type UpdateCampaignBudgetInput, type UploadImageInput, buildConversionPayload, buildTrackingURL, buildUTMParameters, Synter as default, detectClickId, extractTrackingParams, extractUTMParameters, generateDefaultUTMTemplate, normalizeAdClickEvent, normalizeConversionEvent, normalizeEventName, validateClickId, validateUTMTemplate };
|
|
1436
|
+
export { type AdPlatform, type AddKeywordsInput, type AddNegativeKeywordsInput, type AgentShieldPolicy, AmpToolbox, type AmpToolboxConfig, type AnalyticsEvent, type AnalyticsIntegration, type AnalyticsIntegrationConfig, AnalyticsIntegrationManager, type AnalyticsPlatform, AnalyticsResource, AngstromResource, type AngstromVerificationResult, AudiencesResource, type CampaignBriefInput, CampaignsResource, type ConversionPayload, ConversionsResource, type CreateConversionInput, type CreateDisplayCampaignInput, type CreateLinkedInCampaignInput, type CreateMetaCampaignInput, type CreatePmaxCampaignInput, type CreateRedditCampaignInput, type CreateSearchCampaignInput, CreativeResource, type CreativeVariant, DEFAULT_ARTIFACT_BASE_URL, DEFAULT_BASE_URL, type DateRange, type DiagnoseTrackingInput, type EngineVisibilityScore, type GenerateImageInput, type GenerateVideoInput, type GeneratedCampaign, type GetDailySpendInput, type GetPerformanceInput, type GetVisibilityInput, type GrowthSkillId, type GrowthSkillPlaybook, type InspectShieldInput, KeywordsResource, LinkedInResource, type ListCampaignsInput, type ManageAudienceInput, MetaResource, type OptimizationRecommendation, type PauseCampaignInput, type Platform, type PlatformConnection, type PlatformStatus, RedditResource, ShieldResource, SkillsResource, type StageAudienceArtifactInput, type StageAudienceArtifactResult, type SyncAudienceInput, Synter, type SynterConfig, SynterError, SynterValidationError, type TrackingParams, type UTMParameters, type UTMTemplate, type UpdateCampaignBudgetInput, type UploadImageInput, type VerifyAngstromClaimInput, type VisibilityReportResult, VisibilityResource, buildConversionPayload, buildTrackingURL, buildUTMParameters, Synter as default, detectClickId, extractTrackingParams, extractUTMParameters, generateDefaultUTMTemplate, normalizeAdClickEvent, normalizeConversionEvent, normalizeEventName, validateClickId, validateUTMTemplate };
|
package/dist/index.js
CHANGED
|
@@ -23,18 +23,23 @@ __export(index_exports, {
|
|
|
23
23
|
AmpToolbox: () => AmpToolbox,
|
|
24
24
|
AnalyticsIntegrationManager: () => AnalyticsIntegrationManager,
|
|
25
25
|
AnalyticsResource: () => AnalyticsResource,
|
|
26
|
+
AngstromResource: () => AngstromResource,
|
|
26
27
|
AudiencesResource: () => AudiencesResource,
|
|
27
28
|
CampaignsResource: () => CampaignsResource,
|
|
28
29
|
ConversionsResource: () => ConversionsResource,
|
|
29
30
|
CreativeResource: () => CreativeResource,
|
|
31
|
+
DEFAULT_ARTIFACT_BASE_URL: () => DEFAULT_ARTIFACT_BASE_URL,
|
|
30
32
|
DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
|
|
31
33
|
KeywordsResource: () => KeywordsResource,
|
|
32
34
|
LinkedInResource: () => LinkedInResource,
|
|
33
35
|
MetaResource: () => MetaResource,
|
|
34
36
|
RedditResource: () => RedditResource,
|
|
37
|
+
ShieldResource: () => ShieldResource,
|
|
38
|
+
SkillsResource: () => SkillsResource,
|
|
35
39
|
Synter: () => Synter,
|
|
36
40
|
SynterError: () => SynterError,
|
|
37
41
|
SynterValidationError: () => SynterValidationError,
|
|
42
|
+
VisibilityResource: () => VisibilityResource,
|
|
38
43
|
buildConversionPayload: () => buildConversionPayload,
|
|
39
44
|
buildTrackingURL: () => buildTrackingURL,
|
|
40
45
|
buildUTMParameters: () => buildUTMParameters,
|
|
@@ -151,7 +156,7 @@ function flattenArgsToFlags(args) {
|
|
|
151
156
|
|
|
152
157
|
// src/resources/campaigns.ts
|
|
153
158
|
var LIST_CAMPAIGNS_SCRIPT_BY_PLATFORM = {
|
|
154
|
-
google: "
|
|
159
|
+
google: "google_ads_get_campaigns",
|
|
155
160
|
meta: "meta_ads_list_campaigns",
|
|
156
161
|
linkedin: "linkedin_ads_list_campaigns",
|
|
157
162
|
microsoft: "microsoft_ads_list_campaigns",
|
|
@@ -202,7 +207,7 @@ var PAUSE_CAMPAIGN_ARG_MAPPING = [
|
|
|
202
207
|
];
|
|
203
208
|
var UPDATE_BUDGET_ARG_MAPPING = [
|
|
204
209
|
{ field: "campaign_id", flag: "--campaign-id", type: "string", required: true },
|
|
205
|
-
{ field: "daily_budget", flag: "--budget", type: "number", required: true }
|
|
210
|
+
{ field: "daily_budget", flag: "--daily-budget", type: "number", required: true }
|
|
206
211
|
];
|
|
207
212
|
var CampaignsResource = class {
|
|
208
213
|
constructor(client) {
|
|
@@ -275,13 +280,79 @@ var CampaignsResource = class {
|
|
|
275
280
|
const args = buildArgsFromMapping(UPDATE_BUDGET_ARG_MAPPING, input);
|
|
276
281
|
return this.client.runTool("update_campaign_budget", args, "google");
|
|
277
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* Update campaign budget with deterministic readback verification.
|
|
285
|
+
*
|
|
286
|
+
* Executes the budget update, waits for propagation, and reads back
|
|
287
|
+
* campaign status from the platform to verify the update succeeded on the wire.
|
|
288
|
+
*/
|
|
289
|
+
async updateBudgetAndVerify(input) {
|
|
290
|
+
const mutation = await this.updateBudget(input);
|
|
291
|
+
const maxWaitMs = input.maxWaitMs ?? 5e3;
|
|
292
|
+
const pollIntervalMs = input.pollIntervalMs ?? 1e3;
|
|
293
|
+
const startTime = Date.now();
|
|
294
|
+
let lastReadback;
|
|
295
|
+
while (Date.now() - startTime <= maxWaitMs) {
|
|
296
|
+
try {
|
|
297
|
+
const readback = await this.list({
|
|
298
|
+
platform: input.platform
|
|
299
|
+
});
|
|
300
|
+
lastReadback = readback;
|
|
301
|
+
const campaigns = readback.campaigns || readback.data || [];
|
|
302
|
+
const match = campaigns.find(
|
|
303
|
+
(c) => String(c.id || c.campaign_id) === String(input.campaign_id)
|
|
304
|
+
);
|
|
305
|
+
if (match) {
|
|
306
|
+
const budget = Number(match.daily_budget_usd || match.daily_budget || match.budget);
|
|
307
|
+
if (Math.abs(budget - input.daily_budget) < 0.01) {
|
|
308
|
+
return { mutation, verified: true, readback: match };
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
} catch {
|
|
312
|
+
}
|
|
313
|
+
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
314
|
+
}
|
|
315
|
+
return { mutation, verified: false, readback: lastReadback };
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Pause a campaign with deterministic readback verification.
|
|
319
|
+
*
|
|
320
|
+
* Executes the pause command, waits for propagation, and reads back
|
|
321
|
+
* campaign status from the platform to verify status === 'PAUSED' on the wire.
|
|
322
|
+
*/
|
|
323
|
+
async pauseAndVerify(input) {
|
|
324
|
+
const mutation = await this.pause(input);
|
|
325
|
+
const maxWaitMs = input.maxWaitMs ?? 5e3;
|
|
326
|
+
const pollIntervalMs = input.pollIntervalMs ?? 1e3;
|
|
327
|
+
const startTime = Date.now();
|
|
328
|
+
let lastReadback;
|
|
329
|
+
while (Date.now() - startTime <= maxWaitMs) {
|
|
330
|
+
try {
|
|
331
|
+
const readback = await this.list({
|
|
332
|
+
platform: input.platform,
|
|
333
|
+
status: "PAUSED"
|
|
334
|
+
});
|
|
335
|
+
lastReadback = readback;
|
|
336
|
+
const campaigns = readback.campaigns || readback.data || [];
|
|
337
|
+
const match = campaigns.find(
|
|
338
|
+
(c) => String(c.id || c.campaign_id) === String(input.campaign_id)
|
|
339
|
+
);
|
|
340
|
+
if (match) {
|
|
341
|
+
return { mutation, verified: true, readback: match };
|
|
342
|
+
}
|
|
343
|
+
} catch {
|
|
344
|
+
}
|
|
345
|
+
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
346
|
+
}
|
|
347
|
+
return { mutation, verified: false, readback: lastReadback };
|
|
348
|
+
}
|
|
278
349
|
};
|
|
279
350
|
|
|
280
351
|
// src/resources/analytics.ts
|
|
281
352
|
var GET_PERFORMANCE_SCRIPT_BY_PLATFORM = {
|
|
282
|
-
google: "
|
|
353
|
+
google: "pull_google_ads",
|
|
283
354
|
meta: "pull_meta_ads",
|
|
284
|
-
linkedin: "
|
|
355
|
+
linkedin: "pull_linkedin_ads",
|
|
285
356
|
microsoft: "pull_microsoft_ads",
|
|
286
357
|
reddit: "pull_reddit_ads",
|
|
287
358
|
tiktok: "pull_tiktok_ads",
|
|
@@ -313,17 +384,22 @@ var AnalyticsResource = class {
|
|
|
313
384
|
"google",
|
|
314
385
|
input.platform
|
|
315
386
|
);
|
|
316
|
-
const args = buildArgsFromMapping(
|
|
387
|
+
const args = buildArgsFromMapping(
|
|
388
|
+
GET_PERFORMANCE_ARG_MAPPING,
|
|
389
|
+
{ ...input, date_range: input.date_range ?? "LAST_7_DAYS" },
|
|
390
|
+
platform
|
|
391
|
+
);
|
|
317
392
|
return this.client.runTool(scriptName, args, platform);
|
|
318
393
|
}
|
|
319
394
|
/** Get daily spend breakdown across all connected ad accounts. */
|
|
320
395
|
async getDailySpend(input = {}) {
|
|
321
|
-
const platform
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
396
|
+
const { platform, scriptName } = resolvePlatformScriptName(
|
|
397
|
+
GET_PERFORMANCE_SCRIPT_BY_PLATFORM,
|
|
398
|
+
"google",
|
|
399
|
+
input.platform
|
|
400
|
+
);
|
|
401
|
+
const days = input.days ?? 7;
|
|
402
|
+
return this.client.runTool(scriptName, ["--days", String(days)], platform);
|
|
327
403
|
}
|
|
328
404
|
};
|
|
329
405
|
|
|
@@ -363,6 +439,21 @@ var CREATE_CONVERSION_ARG_MAPPING = [
|
|
|
363
439
|
var DIAGNOSE_TRACKING_ARG_MAPPING = [
|
|
364
440
|
{ field: "url", flag: "--url", type: "string", required: true }
|
|
365
441
|
];
|
|
442
|
+
var GET_PIXEL_HEALTH_ARG_MAPPING = [
|
|
443
|
+
{ field: "site_key", flag: "--site-key", type: "string" }
|
|
444
|
+
];
|
|
445
|
+
var LIST_EVENT_DELIVERIES_ARG_MAPPING = [
|
|
446
|
+
{ field: "site_key", flag: "--site-key", type: "string" },
|
|
447
|
+
{ field: "status", flag: "--status", type: "string" },
|
|
448
|
+
{ field: "platform", flag: "--platform", type: "string" },
|
|
449
|
+
{ field: "limit", flag: "--limit", type: "number" }
|
|
450
|
+
];
|
|
451
|
+
var GET_CLICK_ATTRIBUTION_ARG_MAPPING = [
|
|
452
|
+
{ field: "site_key", flag: "--site-key", type: "string" },
|
|
453
|
+
{ field: "user_id", flag: "--user-id", type: "number" },
|
|
454
|
+
{ field: "email", flag: "--email", type: "string" },
|
|
455
|
+
{ field: "limit", flag: "--limit", type: "number" }
|
|
456
|
+
];
|
|
366
457
|
var ConversionsResource = class {
|
|
367
458
|
constructor(client) {
|
|
368
459
|
this.client = client;
|
|
@@ -388,7 +479,19 @@ var ConversionsResource = class {
|
|
|
388
479
|
*/
|
|
389
480
|
async diagnoseTracking(input) {
|
|
390
481
|
const args = buildArgsFromMapping(DIAGNOSE_TRACKING_ARG_MAPPING, input);
|
|
391
|
-
return this.client.runTool("
|
|
482
|
+
return this.client.runTool("diagnose_tracking", args);
|
|
483
|
+
}
|
|
484
|
+
async getPixelHealth(input = {}) {
|
|
485
|
+
const args = buildArgsFromMapping(GET_PIXEL_HEALTH_ARG_MAPPING, input);
|
|
486
|
+
return this.client.runTool("get_pixel_health", args);
|
|
487
|
+
}
|
|
488
|
+
async listEventDeliveries(input = {}) {
|
|
489
|
+
const args = buildArgsFromMapping(LIST_EVENT_DELIVERIES_ARG_MAPPING, input);
|
|
490
|
+
return this.client.runTool("list_event_deliveries", args);
|
|
491
|
+
}
|
|
492
|
+
async getClickAttribution(input = {}) {
|
|
493
|
+
const args = buildArgsFromMapping(GET_CLICK_ATTRIBUTION_ARG_MAPPING, input);
|
|
494
|
+
return this.client.runTool("get_click_attribution", args);
|
|
392
495
|
}
|
|
393
496
|
};
|
|
394
497
|
|
|
@@ -481,7 +584,6 @@ var RedditResource = class {
|
|
|
481
584
|
|
|
482
585
|
// src/resources/audiences.ts
|
|
483
586
|
var CONSENT_WARNING = "[@synterai/sdk-js] i_have_consent was not provided. Confirm lawful basis under GDPR/CCPA and the destination platform's terms for every identifier before staging or syncing PII, then pass `i_have_consent: true`. (Soft-launch notice \u2014 mirrors the backend's own behavior; this call is not blocked.)";
|
|
484
|
-
var ARTIFACT_ENDPOINT = "https://api.syntermedia.ai/artifacts/audience-sync-input";
|
|
485
587
|
var SYNC_AUDIENCE_SCRIPT_BY_PLATFORM = {
|
|
486
588
|
google: "google_ads_create_customer_match",
|
|
487
589
|
meta: "meta_ads_create_audience",
|
|
@@ -513,7 +615,7 @@ var AudiencesResource = class {
|
|
|
513
615
|
* identifiers inline when over ~500 entries.
|
|
514
616
|
*
|
|
515
617
|
* Bypasses the primary `tools/run` dispatcher: different host
|
|
516
|
-
* (`https://api.
|
|
618
|
+
* (`https://api.synterai.com`) and a different auth header
|
|
517
619
|
* (`X-Synter-Key`, not `Authorization: Bearer`) — see SPEC.md/catalog.json
|
|
518
620
|
* `transport.special`.
|
|
519
621
|
*/
|
|
@@ -528,7 +630,7 @@ var AudiencesResource = class {
|
|
|
528
630
|
if (input.script_name !== void 0) payload.script_name = input.script_name;
|
|
529
631
|
if (input.ttl_seconds !== void 0) payload.ttl_seconds = input.ttl_seconds;
|
|
530
632
|
if (input.i_have_consent !== void 0) payload.i_have_consent = input.i_have_consent;
|
|
531
|
-
return this.client.sendAbsolute(
|
|
633
|
+
return this.client.sendAbsolute(`${this.client.getArtifactBaseUrl()}/artifacts/audience-sync-input`, {
|
|
532
634
|
method: "POST",
|
|
533
635
|
headers: {
|
|
534
636
|
"X-Synter-Key": this.client.getApiKey(),
|
|
@@ -603,6 +705,91 @@ var AudiencesResource = class {
|
|
|
603
705
|
}
|
|
604
706
|
};
|
|
605
707
|
|
|
708
|
+
// src/resources/shield.ts
|
|
709
|
+
var ShieldResource = class {
|
|
710
|
+
constructor(client) {
|
|
711
|
+
this.client = client;
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Inspect Agent Shield velocity limits, burst thresholds, circuit breakers,
|
|
715
|
+
* and kill-switch status before executing ad-spend mutations.
|
|
716
|
+
*/
|
|
717
|
+
async inspect(input = {}) {
|
|
718
|
+
const args = [];
|
|
719
|
+
if (input.platform) {
|
|
720
|
+
args.push("--platform", input.platform);
|
|
721
|
+
}
|
|
722
|
+
const result = await this.client.runTool("inspect_agent_shield", args, input.platform);
|
|
723
|
+
return result;
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
|
|
727
|
+
// src/resources/angstrom.ts
|
|
728
|
+
var AngstromResource = class {
|
|
729
|
+
constructor(client) {
|
|
730
|
+
this.client = client;
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Verify attribution claims against Synter Ångström's deterministic confidence rubric.
|
|
734
|
+
*/
|
|
735
|
+
async verify(input = {}) {
|
|
736
|
+
const args = [];
|
|
737
|
+
if (input.platform) args.push("--platform", input.platform);
|
|
738
|
+
if (input.claimed_conversions !== void 0) args.push("--conversions", String(input.claimed_conversions));
|
|
739
|
+
if (input.claimed_revenue_usd !== void 0) args.push("--revenue", String(input.claimed_revenue_usd));
|
|
740
|
+
if (input.touchpoint_ids && input.touchpoint_ids.length > 0) {
|
|
741
|
+
args.push("--touchpoints", input.touchpoint_ids.join(","));
|
|
742
|
+
}
|
|
743
|
+
const result = await this.client.runTool("verify_angstrom_claim", args, input.platform);
|
|
744
|
+
return result;
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
|
|
748
|
+
// src/resources/skills.ts
|
|
749
|
+
var SkillsResource = class {
|
|
750
|
+
constructor(client) {
|
|
751
|
+
this.client = client;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Load an autonomous growth runbook by ID.
|
|
755
|
+
*/
|
|
756
|
+
async get(skillId) {
|
|
757
|
+
const result = await this.client.runTool("get_skill", ["--skill-id", skillId]);
|
|
758
|
+
return result;
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* List available autonomous growth runbook IDs.
|
|
762
|
+
*/
|
|
763
|
+
list() {
|
|
764
|
+
return [
|
|
765
|
+
"pmax-brand-cannibalization",
|
|
766
|
+
"search-hygiene-shield",
|
|
767
|
+
"marginal-cpa-budget-rebalancer",
|
|
768
|
+
"meta-asc-dark-pool-auditor",
|
|
769
|
+
"single-truth-attribution"
|
|
770
|
+
];
|
|
771
|
+
}
|
|
772
|
+
};
|
|
773
|
+
|
|
774
|
+
// src/resources/visibility.ts
|
|
775
|
+
var VisibilityResource = class {
|
|
776
|
+
constructor(client) {
|
|
777
|
+
this.client = client;
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Read AI search brand visibility and AEO share of voice across ChatGPT, Claude, Perplexity, and Gemini.
|
|
781
|
+
*/
|
|
782
|
+
async get(input = {}) {
|
|
783
|
+
const args = [];
|
|
784
|
+
if (input.query) args.push("--query", input.query);
|
|
785
|
+
if (input.competitor_domains && input.competitor_domains.length > 0) {
|
|
786
|
+
args.push("--competitors", input.competitor_domains.join(","));
|
|
787
|
+
}
|
|
788
|
+
const result = await this.client.runTool("get_llm_visibility", args);
|
|
789
|
+
return result;
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
|
|
606
793
|
// src/toolbox/amp-tools.ts
|
|
607
794
|
var AmpToolbox = class {
|
|
608
795
|
constructor(client, config = {}) {
|
|
@@ -836,7 +1023,8 @@ var AmpToolbox = class {
|
|
|
836
1023
|
};
|
|
837
1024
|
|
|
838
1025
|
// src/client.ts
|
|
839
|
-
var DEFAULT_BASE_URL = "https://
|
|
1026
|
+
var DEFAULT_BASE_URL = "https://synterai.com";
|
|
1027
|
+
var DEFAULT_ARTIFACT_BASE_URL = "https://api.synterai.com";
|
|
840
1028
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
841
1029
|
var DEFAULT_MAX_RETRIES = 3;
|
|
842
1030
|
var RETRY_BASE_MS = 1e3;
|
|
@@ -854,7 +1042,9 @@ var Synter = class {
|
|
|
854
1042
|
throw new SynterValidationError("`apiKey` is required to construct a Synter client.", "apiKey");
|
|
855
1043
|
}
|
|
856
1044
|
this.apiKey = fullConfig.apiKey;
|
|
857
|
-
|
|
1045
|
+
const env = typeof process !== "undefined" ? process.env : void 0;
|
|
1046
|
+
this.baseUrl = fullConfig.baseUrl ?? (env?.SYNTER_API_URL || DEFAULT_BASE_URL);
|
|
1047
|
+
this.artifactBaseUrl = fullConfig.artifactBaseUrl ?? (env?.SYNTER_ARTIFACT_API_URL || DEFAULT_ARTIFACT_BASE_URL);
|
|
858
1048
|
this.timeout = fullConfig.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
859
1049
|
this.maxRetries = fullConfig.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
860
1050
|
this.fetchImpl = fullConfig.fetch ?? globalThis.fetch.bind(globalThis);
|
|
@@ -867,6 +1057,10 @@ var Synter = class {
|
|
|
867
1057
|
this.linkedin = new LinkedInResource(this);
|
|
868
1058
|
this.reddit = new RedditResource(this);
|
|
869
1059
|
this.audiences = new AudiencesResource(this);
|
|
1060
|
+
this.shield = new ShieldResource(this);
|
|
1061
|
+
this.angstrom = new AngstromResource(this);
|
|
1062
|
+
this.skills = new SkillsResource(this);
|
|
1063
|
+
this.visibility = new VisibilityResource(this);
|
|
870
1064
|
this.amp = new AmpToolbox(this, ampConfig);
|
|
871
1065
|
}
|
|
872
1066
|
// ---------------------------------------------------------------------
|
|
@@ -906,7 +1100,7 @@ var Synter = class {
|
|
|
906
1100
|
// ---------------------------------------------------------------------
|
|
907
1101
|
/** List all connected ad accounts across platforms. */
|
|
908
1102
|
async listAdAccounts() {
|
|
909
|
-
return this.runTool("
|
|
1103
|
+
return this.runTool("google_ads_get_customers", [], "google");
|
|
910
1104
|
}
|
|
911
1105
|
/**
|
|
912
1106
|
* Upload an image as an asset for use in ads.
|
|
@@ -945,7 +1139,11 @@ var Synter = class {
|
|
|
945
1139
|
"Content-Type": "application/json"
|
|
946
1140
|
};
|
|
947
1141
|
}
|
|
948
|
-
/**
|
|
1142
|
+
/** Artifact host used by audience staging. */
|
|
1143
|
+
getArtifactBaseUrl() {
|
|
1144
|
+
return this.artifactBaseUrl;
|
|
1145
|
+
}
|
|
1146
|
+
/** The raw API key, for tools that need a non-Bearer header. */
|
|
949
1147
|
getApiKey() {
|
|
950
1148
|
return this.apiKey;
|
|
951
1149
|
}
|
|
@@ -1434,18 +1632,23 @@ function normalizeConversionEvent(params) {
|
|
|
1434
1632
|
AmpToolbox,
|
|
1435
1633
|
AnalyticsIntegrationManager,
|
|
1436
1634
|
AnalyticsResource,
|
|
1635
|
+
AngstromResource,
|
|
1437
1636
|
AudiencesResource,
|
|
1438
1637
|
CampaignsResource,
|
|
1439
1638
|
ConversionsResource,
|
|
1440
1639
|
CreativeResource,
|
|
1640
|
+
DEFAULT_ARTIFACT_BASE_URL,
|
|
1441
1641
|
DEFAULT_BASE_URL,
|
|
1442
1642
|
KeywordsResource,
|
|
1443
1643
|
LinkedInResource,
|
|
1444
1644
|
MetaResource,
|
|
1445
1645
|
RedditResource,
|
|
1646
|
+
ShieldResource,
|
|
1647
|
+
SkillsResource,
|
|
1446
1648
|
Synter,
|
|
1447
1649
|
SynterError,
|
|
1448
1650
|
SynterValidationError,
|
|
1651
|
+
VisibilityResource,
|
|
1449
1652
|
buildConversionPayload,
|
|
1450
1653
|
buildTrackingURL,
|
|
1451
1654
|
buildUTMParameters,
|