@canonry/canonry 4.117.2 → 4.118.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.
Files changed (30) hide show
  1. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +53 -1
  2. package/assets/assets/AuditHistoryPanel-Yh7VEe4P.js +1 -0
  3. package/assets/assets/{BacklinksPage-CschVQxC.js → BacklinksPage-BmO77kMs.js} +1 -1
  4. package/assets/assets/{ChartPrimitives-D4782Ifx.js → ChartPrimitives-H0ICVpw_.js} +1 -1
  5. package/assets/assets/HistoryPage-DkLV_iRc.js +1 -0
  6. package/assets/assets/ProjectPage-R3odr_eA.js +7 -0
  7. package/assets/assets/{RunRow-ggNGlwdN.js → RunRow-BDH9agxQ.js} +1 -1
  8. package/assets/assets/RunsPage-D9YsEeT3.js +1 -0
  9. package/assets/assets/{SettingsPage-Cy9SlBJX.js → SettingsPage-o5as3Ixw.js} +1 -1
  10. package/assets/assets/{TrafficPage-1S2PzSHB.js → TrafficPage-BCK203aQ.js} +1 -1
  11. package/assets/assets/{TrafficSourceDetailPage-CqXCoaod.js → TrafficSourceDetailPage-DsVMAZvS.js} +1 -1
  12. package/assets/assets/{arrow-left-kCK5M8Bp.js → arrow-left-B7ZR6VC9.js} +1 -1
  13. package/assets/assets/{extract-error-message-C82LAW6q.js → extract-error-message-DeYDUpew.js} +1 -1
  14. package/assets/assets/index-Bot6YiD6.css +1 -0
  15. package/assets/assets/index-QCFQv0xh.js +210 -0
  16. package/assets/assets/{trash-2-8Pe4v1T0.js → trash-2-xxHTqWbF.js} +1 -1
  17. package/assets/index.html +2 -2
  18. package/dist/{chunk-4PMMEFME.js → chunk-75UBTCKS.js} +499 -16
  19. package/dist/{chunk-BMPIV35C.js → chunk-CMZIPFNQ.js} +937 -104
  20. package/dist/{chunk-F2SRZJMY.js → chunk-HGNY5GL4.js} +384 -15
  21. package/dist/{chunk-EZME2J2G.js → chunk-KEZWLP4O.js} +1196 -1012
  22. package/dist/cli.js +319 -86
  23. package/dist/index.js +4 -4
  24. package/dist/{intelligence-service-GNOE4J35.js → intelligence-service-FWPXMAVK.js} +2 -2
  25. package/dist/mcp.js +2 -2
  26. package/package.json +8 -8
  27. package/assets/assets/ProjectPage-BSGTpBUJ.js +0 -7
  28. package/assets/assets/RunsPage-Bfp0K6Ry.js +0 -1
  29. package/assets/assets/index-DrDNyUhv.css +0 -1
  30. package/assets/assets/index-i-t64RXw.js +0 -210
@@ -10,7 +10,7 @@ import {
10
10
  loadConfig,
11
11
  loadConfigRaw,
12
12
  saveConfigPatch
13
- } from "./chunk-4PMMEFME.js";
13
+ } from "./chunk-75UBTCKS.js";
14
14
  import {
15
15
  CC_CACHE_DIR,
16
16
  DUCKDB_SPEC,
@@ -115,7 +115,7 @@ import {
115
115
  siteAuditPages,
116
116
  siteAuditSnapshots,
117
117
  usageCounters
118
- } from "./chunk-BMPIV35C.js";
118
+ } from "./chunk-CMZIPFNQ.js";
119
119
  import {
120
120
  AGENT_MEMORY_VALUE_MAX_BYTES,
121
121
  AGENT_PROVIDER_IDS,
@@ -178,7 +178,7 @@ import {
178
178
  validationError,
179
179
  winnabilityClassLabel,
180
180
  withRetry
181
- } from "./chunk-EZME2J2G.js";
181
+ } from "./chunk-KEZWLP4O.js";
182
182
 
183
183
  // src/telemetry.ts
184
184
  import crypto from "crypto";
@@ -4241,6 +4241,16 @@ var OPENAI_ADS_REQUEST_TIMEOUT_MS = 3e4;
4241
4241
  var OPENAI_ADS_MAX_PAGES = 100;
4242
4242
 
4243
4243
  // ../integration-openai-ads/src/types.ts
4244
+ var OpenAiAdsWriteStatuses = {
4245
+ active: "active",
4246
+ paused: "paused"
4247
+ };
4248
+ var OpenAiAdsBillingEventTypes = {
4249
+ impression: "impression"
4250
+ };
4251
+ var OpenAiAdsCreativeTypes = {
4252
+ chatCard: "chat_card"
4253
+ };
4244
4254
  var OpenAiAdsApiError = class extends Error {
4245
4255
  status;
4246
4256
  code;
@@ -4264,6 +4274,16 @@ function parseErrorEnvelope(body) {
4264
4274
  }
4265
4275
 
4266
4276
  // ../integration-openai-ads/src/ads-client.ts
4277
+ var MIN_ENTITY_NAME_LENGTH = 3;
4278
+ var MAX_ENTITY_NAME_LENGTH = 1e3;
4279
+ var MIN_CAMPAIGN_TIMESTAMP = 946684800;
4280
+ var MAX_CAMPAIGN_TIMESTAMP = 4102444800;
4281
+ var MIN_LIFETIME_BUDGET_MICROS = 1e6;
4282
+ var MIN_BID_MICROS = 1;
4283
+ var MAX_BID_MICROS = 1e8;
4284
+ var MIN_AD_TITLE_LENGTH = 3;
4285
+ var MAX_AD_TITLE_LENGTH = 50;
4286
+ var MAX_AD_BODY_LENGTH = 100;
4267
4287
  function validateApiKey(apiKey) {
4268
4288
  if (!apiKey || typeof apiKey !== "string" || apiKey.trim().length === 0) {
4269
4289
  throw new OpenAiAdsApiError("API key is required and must be a non-empty string", 400);
@@ -4274,6 +4294,174 @@ function validateId(value, label) {
4274
4294
  throw new OpenAiAdsApiError(`${label} is required and must be a non-empty string`, 400);
4275
4295
  }
4276
4296
  }
4297
+ function isRecord(value) {
4298
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4299
+ }
4300
+ function validateRequestObject(value, label) {
4301
+ if (!isRecord(value)) {
4302
+ throw new OpenAiAdsApiError(`${label} must be a JSON object`, 400);
4303
+ }
4304
+ }
4305
+ function validateNonEmptyRequest(value, label) {
4306
+ validateRequestObject(value, label);
4307
+ if (Object.keys(value).length === 0) {
4308
+ throw new OpenAiAdsApiError(`${label} must include at least one field`, 400);
4309
+ }
4310
+ }
4311
+ function snapshotJsonRequest(value, label) {
4312
+ try {
4313
+ const serialized = JSON.stringify(value);
4314
+ return JSON.parse(serialized);
4315
+ } catch {
4316
+ throw new OpenAiAdsApiError(`${label} must be JSON-serializable`, 400);
4317
+ }
4318
+ }
4319
+ function validateEntityName(value, label) {
4320
+ if (typeof value !== "string" || value.trim().length < MIN_ENTITY_NAME_LENGTH || value.length > MAX_ENTITY_NAME_LENGTH) {
4321
+ throw new OpenAiAdsApiError(
4322
+ `${label} must be ${MIN_ENTITY_NAME_LENGTH}-${MAX_ENTITY_NAME_LENGTH} characters and include a non-space character`,
4323
+ 400
4324
+ );
4325
+ }
4326
+ }
4327
+ function validatePausedCreateStatus(value, label) {
4328
+ if (value !== OpenAiAdsWriteStatuses.paused) {
4329
+ throw new OpenAiAdsApiError(`${label} status must be paused`, 400);
4330
+ }
4331
+ }
4332
+ function validatePublicUpdateRequest(value, label) {
4333
+ validateNonEmptyRequest(value, label);
4334
+ if (Object.hasOwn(value, "status")) {
4335
+ throw new OpenAiAdsApiError(`${label} cannot include status; use an explicit lifecycle action`, 400);
4336
+ }
4337
+ }
4338
+ function validateCampaignTimestamp(value, label) {
4339
+ if (value === void 0 || value === null) return;
4340
+ if (!Number.isInteger(value) || value < MIN_CAMPAIGN_TIMESTAMP || value > MAX_CAMPAIGN_TIMESTAMP) {
4341
+ throw new OpenAiAdsApiError(
4342
+ `${label} must be a Unix timestamp between ${MIN_CAMPAIGN_TIMESTAMP} and ${MAX_CAMPAIGN_TIMESTAMP}`,
4343
+ 400
4344
+ );
4345
+ }
4346
+ }
4347
+ function validateCampaignBudget(value) {
4348
+ validateRequestObject(value, "Campaign budget");
4349
+ const limit = value.lifetime_spend_limit_micros;
4350
+ if (!Number.isInteger(limit) || limit < MIN_LIFETIME_BUDGET_MICROS) {
4351
+ throw new OpenAiAdsApiError(
4352
+ `Campaign budget lifetime_spend_limit_micros must be an integer of at least ${MIN_LIFETIME_BUDGET_MICROS}`,
4353
+ 400
4354
+ );
4355
+ }
4356
+ }
4357
+ function validateCampaignTargeting(value) {
4358
+ if (value === void 0) return;
4359
+ if (value === null) {
4360
+ throw new OpenAiAdsApiError("Campaign targeting cannot be null; omit it to preserve existing targeting", 400);
4361
+ }
4362
+ validateRequestObject(value, "Campaign targeting");
4363
+ validateRequestObject(value.locations, "Campaign targeting locations");
4364
+ const include = value.locations.include;
4365
+ if (!Array.isArray(include) || include.length === 0) {
4366
+ throw new OpenAiAdsApiError("Campaign targeting locations include must be a non-empty array", 400);
4367
+ }
4368
+ for (const target of include) {
4369
+ validateRequestObject(target, "Campaign location target");
4370
+ validateId(target.id, "Campaign location id");
4371
+ }
4372
+ }
4373
+ function validateBiddingConfig(value) {
4374
+ validateRequestObject(value, "Ad group bidding_config");
4375
+ if (value.billing_event_type !== OpenAiAdsBillingEventTypes.impression) {
4376
+ throw new OpenAiAdsApiError("Ad group billing_event_type must be impression", 400);
4377
+ }
4378
+ const maxBid = value.max_bid_micros;
4379
+ if (!Number.isInteger(maxBid) || maxBid < MIN_BID_MICROS || maxBid > MAX_BID_MICROS) {
4380
+ throw new OpenAiAdsApiError(
4381
+ `Ad group max_bid_micros must be an integer between ${MIN_BID_MICROS} and ${MAX_BID_MICROS}`,
4382
+ 400
4383
+ );
4384
+ }
4385
+ }
4386
+ function validateContextHints(value) {
4387
+ if (value === void 0) return;
4388
+ if (!Array.isArray(value) || value.some((hint) => typeof hint !== "string" || hint.trim().length === 0)) {
4389
+ throw new OpenAiAdsApiError("Ad group context_hints must be an array of non-empty strings", 400);
4390
+ }
4391
+ }
4392
+ function validateHttpUrl(value, label) {
4393
+ if (typeof value !== "string" || value.trim().length === 0) {
4394
+ throw new OpenAiAdsApiError(`${label} is required and must be a non-empty URL`, 400);
4395
+ }
4396
+ try {
4397
+ const parsed = new URL(value);
4398
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
4399
+ throw new Error("unsupported protocol");
4400
+ }
4401
+ } catch {
4402
+ throw new OpenAiAdsApiError(`${label} must be an absolute HTTP or HTTPS URL`, 400);
4403
+ }
4404
+ }
4405
+ function validateChatCardCreative(value) {
4406
+ validateRequestObject(value, "Ad creative");
4407
+ if (value.type !== OpenAiAdsCreativeTypes.chatCard) {
4408
+ throw new OpenAiAdsApiError("Ad creative type must be chat_card", 400);
4409
+ }
4410
+ if (typeof value.title !== "string" || value.title.trim().length < MIN_AD_TITLE_LENGTH || value.title.length > MAX_AD_TITLE_LENGTH) {
4411
+ throw new OpenAiAdsApiError(
4412
+ `Ad creative title must be ${MIN_AD_TITLE_LENGTH}-${MAX_AD_TITLE_LENGTH} characters`,
4413
+ 400
4414
+ );
4415
+ }
4416
+ if (typeof value.body !== "string" || value.body.trim().length === 0 || value.body.length > MAX_AD_BODY_LENGTH) {
4417
+ throw new OpenAiAdsApiError(`Ad creative body must be 1-${MAX_AD_BODY_LENGTH} characters`, 400);
4418
+ }
4419
+ validateId(value.file_id, "Ad creative file id");
4420
+ validateHttpUrl(value.target_url, "Ad creative target URL");
4421
+ }
4422
+ function validateCreateCampaignRequest(request) {
4423
+ validateRequestObject(request, "Campaign create request");
4424
+ validateEntityName(request.name, "Campaign name");
4425
+ validatePausedCreateStatus(request.status, "Campaign create request");
4426
+ validateCampaignBudget(request.budget);
4427
+ validateCampaignTimestamp(request.start_time, "Campaign start_time");
4428
+ validateCampaignTimestamp(request.end_time, "Campaign end_time");
4429
+ validateCampaignTargeting(request.targeting);
4430
+ }
4431
+ function validateUpdateCampaignRequest(request) {
4432
+ validatePublicUpdateRequest(request, "Campaign update request");
4433
+ if (request.name !== void 0) validateEntityName(request.name, "Campaign name");
4434
+ if (request.budget !== void 0) validateCampaignBudget(request.budget);
4435
+ validateCampaignTimestamp(request.start_time, "Campaign start_time");
4436
+ validateCampaignTimestamp(request.end_time, "Campaign end_time");
4437
+ validateCampaignTargeting(request.targeting);
4438
+ }
4439
+ function validateCreateAdGroupRequest(request) {
4440
+ validateRequestObject(request, "Ad group create request");
4441
+ validateId(request.campaign_id, "Campaign id");
4442
+ validateEntityName(request.name, "Ad group name");
4443
+ validatePausedCreateStatus(request.status, "Ad group create request");
4444
+ validateContextHints(request.context_hints);
4445
+ validateBiddingConfig(request.bidding_config);
4446
+ }
4447
+ function validateUpdateAdGroupRequest(request) {
4448
+ validatePublicUpdateRequest(request, "Ad group update request");
4449
+ if (request.name !== void 0) validateEntityName(request.name, "Ad group name");
4450
+ validateContextHints(request.context_hints);
4451
+ if (request.bidding_config !== void 0) validateBiddingConfig(request.bidding_config);
4452
+ }
4453
+ function validateCreateAdRequest(request) {
4454
+ validateRequestObject(request, "Ad create request");
4455
+ validateId(request.ad_group_id, "Ad group id");
4456
+ validateEntityName(request.name, "Ad name");
4457
+ validatePausedCreateStatus(request.status, "Ad create request");
4458
+ validateChatCardCreative(request.creative);
4459
+ }
4460
+ function validateUpdateAdRequest(request) {
4461
+ validatePublicUpdateRequest(request, "Ad update request");
4462
+ if (request.name !== void 0) validateEntityName(request.name, "Ad name");
4463
+ if (request.creative !== void 0) validateChatCardCreative(request.creative);
4464
+ }
4277
4465
  function adsClientLog(level, action, ctx) {
4278
4466
  const entry = {
4279
4467
  ts: (/* @__PURE__ */ new Date()).toISOString(),
@@ -4290,14 +4478,15 @@ function buildUrl(path10, queryPairs) {
4290
4478
  const qs = queryPairs.join("&");
4291
4479
  return qs ? `${OPENAI_ADS_API_BASE}/${path10}?${qs}` : `${OPENAI_ADS_API_BASE}/${path10}`;
4292
4480
  }
4293
- async function adsFetch(apiKey, path10, queryPairs = []) {
4481
+ async function adsFetch(apiKey, path10, queryPairs = [], method = "GET", body) {
4294
4482
  const url = buildUrl(path10, queryPairs);
4295
4483
  const res = await fetch(url, {
4296
- method: "GET",
4484
+ method,
4297
4485
  headers: {
4298
4486
  Authorization: `Bearer ${apiKey}`,
4299
4487
  "Content-Type": "application/json"
4300
4488
  },
4489
+ body: body === void 0 ? void 0 : JSON.stringify(body),
4301
4490
  signal: AbortSignal.timeout(OPENAI_ADS_REQUEST_TIMEOUT_MS)
4302
4491
  });
4303
4492
  if (res.status === 401 || res.status === 403) {
@@ -4311,10 +4500,10 @@ async function adsFetch(apiKey, path10, queryPairs = []) {
4311
4500
  throw new OpenAiAdsApiError("OpenAI Ads API rate limit exceeded", 429, code);
4312
4501
  }
4313
4502
  if (!res.ok) {
4314
- const body = await res.text();
4315
- const { message, code } = parseErrorEnvelope(body);
4503
+ const body2 = await res.text();
4504
+ const { message, code } = parseErrorEnvelope(body2);
4316
4505
  adsClientLog("error", "http.error", { path: path10, httpStatus: res.status, code });
4317
- const detail = message ?? (body.length <= 500 ? body : `${body.slice(0, 500)}... [truncated]`);
4506
+ const detail = message ?? (body2.length <= 500 ? body2 : `${body2.slice(0, 500)}... [truncated]`);
4318
4507
  throw new OpenAiAdsApiError(`OpenAI Ads API error (${res.status}): ${detail}`, res.status, code);
4319
4508
  }
4320
4509
  const text = await res.text();
@@ -4350,16 +4539,91 @@ async function listCampaigns(apiKey) {
4350
4539
  validateApiKey(apiKey);
4351
4540
  return fetchAllPages(apiKey, "campaigns", []);
4352
4541
  }
4542
+ async function getCampaign(apiKey, campaignId) {
4543
+ validateApiKey(apiKey);
4544
+ validateId(campaignId, "Campaign id");
4545
+ return adsFetch(apiKey, `campaigns/${encodeURIComponent(campaignId)}`);
4546
+ }
4547
+ async function createCampaign(apiKey, request) {
4548
+ validateApiKey(apiKey);
4549
+ const outbound = snapshotJsonRequest(request, "Campaign create request");
4550
+ validateCreateCampaignRequest(outbound);
4551
+ return adsFetch(apiKey, "campaigns", [], "POST", outbound);
4552
+ }
4553
+ async function updateCampaign(apiKey, campaignId, request) {
4554
+ validateApiKey(apiKey);
4555
+ validateId(campaignId, "Campaign id");
4556
+ const outbound = snapshotJsonRequest(request, "Campaign update request");
4557
+ validateUpdateCampaignRequest(outbound);
4558
+ return adsFetch(apiKey, `campaigns/${encodeURIComponent(campaignId)}`, [], "POST", outbound);
4559
+ }
4560
+ async function pauseCampaign(apiKey, campaignId) {
4561
+ validateApiKey(apiKey);
4562
+ validateId(campaignId, "Campaign id");
4563
+ return adsFetch(apiKey, `campaigns/${encodeURIComponent(campaignId)}/pause`, [], "POST");
4564
+ }
4353
4565
  async function listAdGroups(apiKey, campaignId) {
4354
4566
  validateApiKey(apiKey);
4355
4567
  validateId(campaignId, "Campaign id");
4356
4568
  return fetchAllPages(apiKey, "ad_groups", [`campaign_id=${encodeURIComponent(campaignId)}`]);
4357
4569
  }
4570
+ async function getAdGroup(apiKey, adGroupId) {
4571
+ validateApiKey(apiKey);
4572
+ validateId(adGroupId, "Ad group id");
4573
+ return adsFetch(apiKey, `ad_groups/${encodeURIComponent(adGroupId)}`);
4574
+ }
4575
+ async function createAdGroup(apiKey, request) {
4576
+ validateApiKey(apiKey);
4577
+ const outbound = snapshotJsonRequest(request, "Ad group create request");
4578
+ validateCreateAdGroupRequest(outbound);
4579
+ return adsFetch(apiKey, "ad_groups", [], "POST", outbound);
4580
+ }
4581
+ async function updateAdGroup(apiKey, adGroupId, request) {
4582
+ validateApiKey(apiKey);
4583
+ validateId(adGroupId, "Ad group id");
4584
+ const outbound = snapshotJsonRequest(request, "Ad group update request");
4585
+ validateUpdateAdGroupRequest(outbound);
4586
+ return adsFetch(apiKey, `ad_groups/${encodeURIComponent(adGroupId)}`, [], "POST", outbound);
4587
+ }
4588
+ async function pauseAdGroup(apiKey, adGroupId) {
4589
+ validateApiKey(apiKey);
4590
+ validateId(adGroupId, "Ad group id");
4591
+ return adsFetch(apiKey, `ad_groups/${encodeURIComponent(adGroupId)}/pause`, [], "POST");
4592
+ }
4358
4593
  async function listAds(apiKey, adGroupId) {
4359
4594
  validateApiKey(apiKey);
4360
4595
  validateId(adGroupId, "Ad group id");
4361
4596
  return fetchAllPages(apiKey, "ads", [`ad_group_id=${encodeURIComponent(adGroupId)}`]);
4362
4597
  }
4598
+ async function getAd(apiKey, adId) {
4599
+ validateApiKey(apiKey);
4600
+ validateId(adId, "Ad id");
4601
+ return adsFetch(apiKey, `ads/${encodeURIComponent(adId)}`);
4602
+ }
4603
+ async function createAd(apiKey, request) {
4604
+ validateApiKey(apiKey);
4605
+ const outbound = snapshotJsonRequest(request, "Ad create request");
4606
+ validateCreateAdRequest(outbound);
4607
+ return adsFetch(apiKey, "ads", [], "POST", outbound);
4608
+ }
4609
+ async function updateAd(apiKey, adId, request) {
4610
+ validateApiKey(apiKey);
4611
+ validateId(adId, "Ad id");
4612
+ const outbound = snapshotJsonRequest(request, "Ad update request");
4613
+ validateUpdateAdRequest(outbound);
4614
+ return adsFetch(apiKey, `ads/${encodeURIComponent(adId)}`, [], "POST", outbound);
4615
+ }
4616
+ async function pauseAd(apiKey, adId) {
4617
+ validateApiKey(apiKey);
4618
+ validateId(adId, "Ad id");
4619
+ return adsFetch(apiKey, `ads/${encodeURIComponent(adId)}/pause`, [], "POST");
4620
+ }
4621
+ async function uploadImageFromUrl(apiKey, imageUrl) {
4622
+ validateApiKey(apiKey);
4623
+ validateHttpUrl(imageUrl, "Image URL");
4624
+ const request = { image_url: imageUrl };
4625
+ return adsFetch(apiKey, "upload", [], "POST", request);
4626
+ }
4363
4627
  async function getCampaignInsights(apiKey, campaignId, opts) {
4364
4628
  validateApiKey(apiKey);
4365
4629
  validateId(campaignId, "Campaign id");
@@ -4491,7 +4755,10 @@ async function executeAdsSync(db, runId, projectId, opts) {
4491
4755
  id: campaign.id,
4492
4756
  projectId,
4493
4757
  name: campaign.name,
4758
+ description: campaign.description ?? null,
4494
4759
  status: campaign.status,
4760
+ startTime: campaign.start_time ?? null,
4761
+ endTime: campaign.end_time ?? null,
4495
4762
  biddingType: campaign.bidding_type,
4496
4763
  dailySpendLimitMicros: campaign.budget?.daily_spend_limit_micros ?? null,
4497
4764
  lifetimeSpendLimitMicros: campaign.budget?.lifetime_spend_limit_micros ?? null,
@@ -4507,6 +4774,7 @@ async function executeAdsSync(db, runId, projectId, opts) {
4507
4774
  projectId,
4508
4775
  campaignId: campaign.id,
4509
4776
  name: group.name,
4777
+ description: group.description ?? null,
4510
4778
  status: group.status,
4511
4779
  billingEventType: group.bidding_config?.billing_event_type ?? null,
4512
4780
  maxBidMicros: group.bidding_config?.max_bid_micros ?? null,
@@ -6515,7 +6783,7 @@ function readStoredGroundingSources(rawResponse) {
6515
6783
  return result;
6516
6784
  }
6517
6785
  async function backfillInsightsCommand(project, opts) {
6518
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-GNOE4J35.js");
6786
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-FWPXMAVK.js");
6519
6787
  const config = loadConfig();
6520
6788
  const db = createClient(config.database);
6521
6789
  migrate(db);
@@ -8605,6 +8873,17 @@ var AERO_ADS_OPERATOR_MCP_TOOL_NAMES = /* @__PURE__ */ new Set([
8605
8873
  CanonryMcpToolNames.canonry_ads_campaigns,
8606
8874
  CanonryMcpToolNames.canonry_ads_insights,
8607
8875
  CanonryMcpToolNames.canonry_ads_summary,
8876
+ CanonryMcpToolNames.canonry_ads_operation_get,
8877
+ CanonryMcpToolNames.canonry_ads_image_upload,
8878
+ CanonryMcpToolNames.canonry_ads_campaign_create,
8879
+ CanonryMcpToolNames.canonry_ads_campaign_update,
8880
+ CanonryMcpToolNames.canonry_ads_campaign_pause,
8881
+ CanonryMcpToolNames.canonry_ads_ad_group_create,
8882
+ CanonryMcpToolNames.canonry_ads_ad_group_update,
8883
+ CanonryMcpToolNames.canonry_ads_ad_group_pause,
8884
+ CanonryMcpToolNames.canonry_ads_ad_create,
8885
+ CanonryMcpToolNames.canonry_ads_ad_update,
8886
+ CanonryMcpToolNames.canonry_ads_ad_pause,
8608
8887
  CanonryMcpToolNames.canonry_ads_sync
8609
8888
  ]);
8610
8889
  function toolResult(details) {
@@ -8666,6 +8945,7 @@ function compactCampaigns(response, limit) {
8666
8945
  adGroups: campaign.adGroups.slice(0, 8).map((group) => ({
8667
8946
  id: group.id,
8668
8947
  name: group.name,
8948
+ description: group.description,
8669
8949
  status: group.status,
8670
8950
  billingEventType: group.billingEventType,
8671
8951
  maxBidMicros: group.maxBidMicros,
@@ -8677,14 +8957,25 @@ function compactCampaigns(response, limit) {
8677
8957
  name: ad.name,
8678
8958
  status: ad.status,
8679
8959
  reviewStatus: ad.reviewStatus,
8960
+ upstreamUpdatedAt: ad.upstreamUpdatedAt,
8961
+ syncedAt: ad.syncedAt,
8680
8962
  creative: ad.creative ? {
8681
8963
  type: ad.creative.type,
8682
8964
  title: ad.creative.title,
8683
8965
  body: ad.creative.body,
8684
- targetUrl: ad.creative.targetUrl
8966
+ targetUrl: ad.creative.targetUrl,
8967
+ fileId: ad.creative.fileId
8685
8968
  } : ad.creative
8686
- }))
8687
- }))
8969
+ })),
8970
+ upstreamUpdatedAt: group.upstreamUpdatedAt,
8971
+ syncedAt: group.syncedAt
8972
+ })),
8973
+ description: campaign.description,
8974
+ startTime: campaign.startTime,
8975
+ endTime: campaign.endTime,
8976
+ locationIds: campaign.locationIds ?? [],
8977
+ upstreamUpdatedAt: campaign.upstreamUpdatedAt,
8978
+ syncedAt: campaign.syncedAt
8688
8979
  }))
8689
8980
  };
8690
8981
  }
@@ -8845,11 +9136,11 @@ function recordLlmUsageEvent(args) {
8845
9136
  var AERO_MEMORY_SEPARATOR = "\n\n---\n\n";
8846
9137
  var AERO_MEMORY_BLOCK_PREFIX = `${AERO_MEMORY_SEPARATOR}<memory>
8847
9138
  `;
8848
- function isRecord(value) {
9139
+ function isRecord2(value) {
8849
9140
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
8850
9141
  }
8851
9142
  function isTextSystemBlock(value) {
8852
- return isRecord(value) && value.type === "text" && typeof value.text === "string";
9143
+ return isRecord2(value) && value.type === "text" && typeof value.text === "string";
8853
9144
  }
8854
9145
  function splitAeroHydratedSystemPrompt(systemPrompt) {
8855
9146
  const idx = systemPrompt.lastIndexOf(AERO_MEMORY_BLOCK_PREFIX);
@@ -8861,7 +9152,7 @@ function splitAeroHydratedSystemPrompt(systemPrompt) {
8861
9152
  }
8862
9153
  function splitAeroAnthropicSystemCachePayload(payload, model) {
8863
9154
  if (model.api !== "anthropic-messages") return void 0;
8864
- if (!isRecord(payload) || !Array.isArray(payload.system)) return void 0;
9155
+ if (!isRecord2(payload) || !Array.isArray(payload.system)) return void 0;
8865
9156
  let changed = false;
8866
9157
  const nextSystem = [];
8867
9158
  for (const block of payload.system) {
@@ -11371,6 +11662,83 @@ async function createServer(opts) {
11371
11662
  timezone: account.timezone ?? null
11372
11663
  };
11373
11664
  };
11665
+ const adsEntityResult = (entity) => ({
11666
+ id: entity.id,
11667
+ status: entity.status,
11668
+ updatedAt: entity.updated_at,
11669
+ reviewStatus: entity.review_status ?? null
11670
+ });
11671
+ const adsOperator = {
11672
+ uploadImage: async (apiKey, imageUrl) => {
11673
+ const result = await uploadImageFromUrl(apiKey, imageUrl);
11674
+ return { fileId: result.file_id };
11675
+ },
11676
+ getCampaign: async (apiKey, id) => adsEntityResult(await getCampaign(apiKey, id)),
11677
+ createCampaign: async (apiKey, input) => adsEntityResult(await createCampaign(apiKey, {
11678
+ name: input.name,
11679
+ description: input.description,
11680
+ start_time: input.startTime,
11681
+ end_time: input.endTime,
11682
+ status: OpenAiAdsWriteStatuses.paused,
11683
+ budget: { lifetime_spend_limit_micros: input.lifetimeSpendLimitMicros },
11684
+ targeting: { locations: { include: input.locationIds.map((id) => ({ id })) } }
11685
+ })),
11686
+ updateCampaign: async (apiKey, id, input) => adsEntityResult(await updateCampaign(apiKey, id, {
11687
+ name: input.name,
11688
+ description: input.description,
11689
+ start_time: input.startTime,
11690
+ end_time: input.endTime,
11691
+ budget: input.lifetimeSpendLimitMicros === void 0 ? void 0 : { lifetime_spend_limit_micros: input.lifetimeSpendLimitMicros },
11692
+ targeting: input.locationIds === void 0 ? void 0 : { locations: { include: input.locationIds.map((locationId) => ({ id: locationId })) } }
11693
+ })),
11694
+ pauseCampaign: async (apiKey, id) => adsEntityResult(await pauseCampaign(apiKey, id)),
11695
+ getAdGroup: async (apiKey, id) => adsEntityResult(await getAdGroup(apiKey, id)),
11696
+ createAdGroup: async (apiKey, input) => adsEntityResult(await createAdGroup(apiKey, {
11697
+ campaign_id: input.campaignId,
11698
+ name: input.name,
11699
+ description: input.description,
11700
+ context_hints: input.contextHints,
11701
+ status: OpenAiAdsWriteStatuses.paused,
11702
+ bidding_config: {
11703
+ billing_event_type: OpenAiAdsBillingEventTypes.impression,
11704
+ max_bid_micros: input.maxBidMicros
11705
+ }
11706
+ })),
11707
+ updateAdGroup: async (apiKey, id, input) => adsEntityResult(await updateAdGroup(apiKey, id, {
11708
+ name: input.name,
11709
+ description: input.description,
11710
+ context_hints: input.contextHints,
11711
+ bidding_config: input.maxBidMicros === void 0 ? void 0 : {
11712
+ billing_event_type: OpenAiAdsBillingEventTypes.impression,
11713
+ max_bid_micros: input.maxBidMicros
11714
+ }
11715
+ })),
11716
+ pauseAdGroup: async (apiKey, id) => adsEntityResult(await pauseAdGroup(apiKey, id)),
11717
+ getAd: async (apiKey, id) => adsEntityResult(await getAd(apiKey, id)),
11718
+ createAd: async (apiKey, input) => adsEntityResult(await createAd(apiKey, {
11719
+ ad_group_id: input.adGroupId,
11720
+ name: input.name,
11721
+ status: OpenAiAdsWriteStatuses.paused,
11722
+ creative: {
11723
+ type: OpenAiAdsCreativeTypes.chatCard,
11724
+ title: input.creative.title,
11725
+ body: input.creative.body,
11726
+ target_url: input.creative.targetUrl,
11727
+ file_id: input.creative.fileId
11728
+ }
11729
+ })),
11730
+ updateAd: async (apiKey, id, input) => adsEntityResult(await updateAd(apiKey, id, {
11731
+ name: input.name,
11732
+ creative: input.creative ? {
11733
+ type: OpenAiAdsCreativeTypes.chatCard,
11734
+ title: input.creative.title,
11735
+ body: input.creative.body,
11736
+ target_url: input.creative.targetUrl,
11737
+ file_id: input.creative.fileId
11738
+ } : void 0
11739
+ })),
11740
+ pauseAd: async (apiKey, id) => adsEntityResult(await pauseAd(apiKey, id))
11741
+ };
11374
11742
  const scheduler = new Scheduler(opts.db, {
11375
11743
  onRunCreated: (runId, projectId, providers2, location) => {
11376
11744
  jobRunner.executeRun(runId, projectId, providers2, location).catch((err) => {
@@ -11963,6 +12331,7 @@ async function createServer(opts) {
11963
12331
  },
11964
12332
  adsCredentialStore,
11965
12333
  verifyAdsAccount,
12334
+ adsOperator,
11966
12335
  onAdsSyncRequested: (runId, projectId) => {
11967
12336
  runAdsSync(runId, projectId);
11968
12337
  },