@canonry/canonry 4.118.0 → 4.123.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 (34) hide show
  1. package/README.md +9 -0
  2. package/assets/agent-workspace/skills/canonry/SKILL.md +3 -0
  3. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +135 -28
  4. package/assets/assets/{AuditHistoryPanel-Yh7VEe4P.js → AuditHistoryPanel-BVQMDIhQ.js} +1 -1
  5. package/assets/assets/{BacklinksPage-BmO77kMs.js → BacklinksPage-nrHT9VMG.js} +1 -1
  6. package/assets/assets/ChartPrimitives-_8qLsQzI.js +1 -0
  7. package/assets/assets/{HistoryPage-DkLV_iRc.js → HistoryPage-DqsKKdyy.js} +1 -1
  8. package/assets/assets/ProjectPage-GyKoQUv_.js +7 -0
  9. package/assets/assets/{RunRow-BDH9agxQ.js → RunRow-BRZZcSjQ.js} +1 -1
  10. package/assets/assets/{RunsPage-D9YsEeT3.js → RunsPage-24aI8DKF.js} +1 -1
  11. package/assets/assets/{SettingsPage-o5as3Ixw.js → SettingsPage-BaNeTG1i.js} +1 -1
  12. package/assets/assets/{TrafficPage-BCK203aQ.js → TrafficPage-ByvcLSjv.js} +1 -1
  13. package/assets/assets/{TrafficSourceDetailPage-DsVMAZvS.js → TrafficSourceDetailPage-B-siTXVg.js} +1 -1
  14. package/assets/assets/{arrow-left-B7ZR6VC9.js → arrow-left-CBh1cZNH.js} +1 -1
  15. package/assets/assets/{extract-error-message-DeYDUpew.js → extract-error-message-DJZCPudR.js} +1 -1
  16. package/assets/assets/index-jymsMBpZ.css +1 -0
  17. package/assets/assets/index-mzLganDP.js +210 -0
  18. package/assets/assets/{trash-2-xxHTqWbF.js → trash-2-Bh-Yvkgc.js} +1 -1
  19. package/assets/assets/vendor-recharts-DSxTZhaH.js +36 -0
  20. package/assets/index.html +3 -3
  21. package/dist/{chunk-CMZIPFNQ.js → chunk-4AZ7VES6.js} +4915 -719
  22. package/dist/{chunk-75UBTCKS.js → chunk-HJIIJI7K.js} +321 -6
  23. package/dist/{chunk-HGNY5GL4.js → chunk-JYBNBK25.js} +273 -37
  24. package/dist/{chunk-KEZWLP4O.js → chunk-MMFSI3OG.js} +3281 -2341
  25. package/dist/cli.js +554 -35
  26. package/dist/index.js +4 -4
  27. package/dist/{intelligence-service-FWPXMAVK.js → intelligence-service-K35EN43I.js} +2 -2
  28. package/dist/mcp.js +4 -4
  29. package/package.json +7 -7
  30. package/assets/assets/ChartPrimitives-H0ICVpw_.js +0 -1
  31. package/assets/assets/ProjectPage-R3odr_eA.js +0 -7
  32. package/assets/assets/index-Bot6YiD6.css +0 -1
  33. package/assets/assets/index-QCFQv0xh.js +0 -210
  34. package/assets/assets/vendor-recharts-C9EZkgbP.js +0 -36
@@ -3,14 +3,18 @@ import {
3
3
  AGENT_MEMORY_VALUE_MAX_BYTES,
4
4
  DISCOVERY_MAX_PROBES_CAP,
5
5
  DISCOVERY_PROBE_CONCURRENCY_CAP,
6
+ adsActivateTreeRequestSchema,
6
7
  adsAdCreateRequestSchema,
7
8
  adsAdGroupCreateRequestSchema,
8
9
  adsAdGroupUpdateRequestSchema,
9
10
  adsAdUpdateRequestSchema,
10
11
  adsCampaignCreateRequestSchema,
11
12
  adsCampaignUpdateRequestSchema,
13
+ adsGeoSearchQuerySchema,
12
14
  adsImageUploadRequestSchema,
15
+ adsOperationReconcileRequestSchema,
13
16
  adsPauseRequestSchema,
17
+ adsUnresolvedOperationListQuerySchema,
14
18
  backlinkSourceSchema,
15
19
  competitorBatchRequestSchema,
16
20
  discoveryBucketSchema,
@@ -33,7 +37,7 @@ import {
33
37
  trafficConnectVercelRequestSchema,
34
38
  trafficConnectWordpressRequestSchema,
35
39
  trafficEventKindSchema
36
- } from "./chunk-KEZWLP4O.js";
40
+ } from "./chunk-MMFSI3OG.js";
37
41
 
38
42
  // src/config.ts
39
43
  import fs from "fs";
@@ -2330,6 +2334,66 @@ var getApiV1ProjectsByNameAdsStatus = (options) => {
2330
2334
  ...options
2331
2335
  });
2332
2336
  };
2337
+ var getApiV1ProjectsByNameAdsAccount = (options) => {
2338
+ return (options.client ?? client).get({
2339
+ security: [
2340
+ {
2341
+ scheme: "bearer",
2342
+ type: "http"
2343
+ }
2344
+ ],
2345
+ url: "/api/v1/projects/{name}/ads/account",
2346
+ ...options
2347
+ });
2348
+ };
2349
+ var getApiV1ProjectsByNameAdsGeoSearch = (options) => {
2350
+ return (options.client ?? client).get({
2351
+ security: [
2352
+ {
2353
+ scheme: "bearer",
2354
+ type: "http"
2355
+ }
2356
+ ],
2357
+ url: "/api/v1/projects/{name}/ads/geo/search",
2358
+ ...options
2359
+ });
2360
+ };
2361
+ var getApiV1ProjectsByNameAdsConversionsPixels = (options) => {
2362
+ return (options.client ?? client).get({
2363
+ security: [
2364
+ {
2365
+ scheme: "bearer",
2366
+ type: "http"
2367
+ }
2368
+ ],
2369
+ url: "/api/v1/projects/{name}/ads/conversions/pixels",
2370
+ ...options
2371
+ });
2372
+ };
2373
+ var getApiV1ProjectsByNameAdsConversionsEventSettings = (options) => {
2374
+ return (options.client ?? client).get({
2375
+ security: [
2376
+ {
2377
+ scheme: "bearer",
2378
+ type: "http"
2379
+ }
2380
+ ],
2381
+ url: "/api/v1/projects/{name}/ads/conversions/event-settings",
2382
+ ...options
2383
+ });
2384
+ };
2385
+ var getApiV1ProjectsByNameAdsOperations = (options) => {
2386
+ return (options.client ?? client).get({
2387
+ security: [
2388
+ {
2389
+ scheme: "bearer",
2390
+ type: "http"
2391
+ }
2392
+ ],
2393
+ url: "/api/v1/projects/{name}/ads/operations",
2394
+ ...options
2395
+ });
2396
+ };
2333
2397
  var getApiV1ProjectsByNameAdsOperationsByOperationKey = (options) => {
2334
2398
  return (options.client ?? client).get({
2335
2399
  security: [
@@ -2342,6 +2406,74 @@ var getApiV1ProjectsByNameAdsOperationsByOperationKey = (options) => {
2342
2406
  ...options
2343
2407
  });
2344
2408
  };
2409
+ var postApiV1ProjectsByNameAdsOperationsByOperationKeyReconcile = (options) => {
2410
+ return (options.client ?? client).post({
2411
+ security: [
2412
+ {
2413
+ scheme: "bearer",
2414
+ type: "http"
2415
+ }
2416
+ ],
2417
+ url: "/api/v1/projects/{name}/ads/operations/{operationKey}/reconcile",
2418
+ ...options
2419
+ });
2420
+ };
2421
+ var postApiV1ProjectsByNameAdsOperationsByOperationKeyResumeActivation = (options) => {
2422
+ return (options.client ?? client).post({
2423
+ security: [
2424
+ {
2425
+ scheme: "bearer",
2426
+ type: "http"
2427
+ }
2428
+ ],
2429
+ url: "/api/v1/projects/{name}/ads/operations/{operationKey}/resume-activation",
2430
+ ...options
2431
+ });
2432
+ };
2433
+ var postApiV1ProjectsByNameAdsActivationGrants = (options) => {
2434
+ return (options.client ?? client).post({
2435
+ security: [
2436
+ {
2437
+ scheme: "bearer",
2438
+ type: "http"
2439
+ }
2440
+ ],
2441
+ url: "/api/v1/projects/{name}/ads/activation-grants",
2442
+ ...options,
2443
+ headers: {
2444
+ "Content-Type": "application/json",
2445
+ ...options.headers
2446
+ }
2447
+ });
2448
+ };
2449
+ var postApiV1ProjectsByNameAdsActivationGrantsByGrantIdRevoke = (options) => {
2450
+ return (options.client ?? client).post({
2451
+ security: [
2452
+ {
2453
+ scheme: "bearer",
2454
+ type: "http"
2455
+ }
2456
+ ],
2457
+ url: "/api/v1/projects/{name}/ads/activation-grants/{grantId}/revoke",
2458
+ ...options
2459
+ });
2460
+ };
2461
+ var postApiV1ProjectsByNameAdsCampaignsByIdActivateTree = (options) => {
2462
+ return (options.client ?? client).post({
2463
+ security: [
2464
+ {
2465
+ scheme: "bearer",
2466
+ type: "http"
2467
+ }
2468
+ ],
2469
+ url: "/api/v1/projects/{name}/ads/campaigns/{id}/activate-tree",
2470
+ ...options,
2471
+ headers: {
2472
+ "Content-Type": "application/json",
2473
+ ...options.headers
2474
+ }
2475
+ });
2476
+ };
2345
2477
  var postApiV1ProjectsByNameAdsFiles = (options) => {
2346
2478
  return (options.client ?? client).post({
2347
2479
  security: [
@@ -4604,6 +4736,26 @@ var ApiClient = class {
4604
4736
  () => getApiV1ProjectsByNameAdsStatus({ client: this.heyClient, path: { name: project } })
4605
4737
  );
4606
4738
  }
4739
+ async getAdsAccount(project) {
4740
+ return this.invoke(
4741
+ () => getApiV1ProjectsByNameAdsAccount({ client: this.heyClient, path: { name: project } })
4742
+ );
4743
+ }
4744
+ async searchAdsGeo(project, query) {
4745
+ return this.invoke(
4746
+ () => getApiV1ProjectsByNameAdsGeoSearch({ client: this.heyClient, path: { name: project }, query })
4747
+ );
4748
+ }
4749
+ async getAdsConversionPixels(project) {
4750
+ return this.invoke(
4751
+ () => getApiV1ProjectsByNameAdsConversionsPixels({ client: this.heyClient, path: { name: project } })
4752
+ );
4753
+ }
4754
+ async getAdsConversionEventSettings(project) {
4755
+ return this.invoke(
4756
+ () => getApiV1ProjectsByNameAdsConversionsEventSettings({ client: this.heyClient, path: { name: project } })
4757
+ );
4758
+ }
4607
4759
  async triggerAdsSync(project) {
4608
4760
  return this.invoke(
4609
4761
  () => postApiV1ProjectsByNameAdsSync({ client: this.heyClient, path: { name: project } })
@@ -4632,6 +4784,52 @@ var ApiClient = class {
4632
4784
  })
4633
4785
  );
4634
4786
  }
4787
+ async getUnresolvedAdsOperations(project, query) {
4788
+ return this.invoke(
4789
+ () => getApiV1ProjectsByNameAdsOperations({
4790
+ client: this.heyClient,
4791
+ path: { name: project },
4792
+ query: query ? {
4793
+ state: query.state?.join(","),
4794
+ limit: query.limit,
4795
+ cursor: query.cursor
4796
+ } : void 0
4797
+ })
4798
+ );
4799
+ }
4800
+ async reconcileAdsOperation(project, operationKey) {
4801
+ return this.invoke(
4802
+ () => postApiV1ProjectsByNameAdsOperationsByOperationKeyReconcile({
4803
+ client: this.heyClient,
4804
+ path: { name: project, operationKey }
4805
+ })
4806
+ );
4807
+ }
4808
+ async resumeAdsActivation(project, operationKey) {
4809
+ return this.invoke(
4810
+ () => postApiV1ProjectsByNameAdsOperationsByOperationKeyResumeActivation({
4811
+ client: this.heyClient,
4812
+ path: { name: project, operationKey }
4813
+ })
4814
+ );
4815
+ }
4816
+ async createAdsActivationGrant(project, body) {
4817
+ return this.invoke(
4818
+ () => postApiV1ProjectsByNameAdsActivationGrants({
4819
+ client: this.heyClient,
4820
+ path: { name: project },
4821
+ body
4822
+ })
4823
+ );
4824
+ }
4825
+ async revokeAdsActivationGrant(project, grantId) {
4826
+ return this.invoke(
4827
+ () => postApiV1ProjectsByNameAdsActivationGrantsByGrantIdRevoke({
4828
+ client: this.heyClient,
4829
+ path: { name: project, grantId }
4830
+ })
4831
+ );
4832
+ }
4635
4833
  async uploadAdsImage(project, body) {
4636
4834
  return this.invoke(
4637
4835
  () => postApiV1ProjectsByNameAdsFiles({ client: this.heyClient, path: { name: project }, body })
@@ -4660,6 +4858,15 @@ var ApiClient = class {
4660
4858
  })
4661
4859
  );
4662
4860
  }
4861
+ async activateAdsCampaignTree(project, campaignId, body) {
4862
+ return this.invoke(
4863
+ () => postApiV1ProjectsByNameAdsCampaignsByIdActivateTree({
4864
+ client: this.heyClient,
4865
+ path: { name: project, id: campaignId },
4866
+ body
4867
+ })
4868
+ );
4869
+ }
4663
4870
  async createAdsAdGroup(project, body) {
4664
4871
  return this.invoke(
4665
4872
  () => postApiV1ProjectsByNameAdsAdGroups({ client: this.heyClient, path: { name: project }, body })
@@ -5816,10 +6023,21 @@ var adsInsightsInputSchema = z2.object({
5816
6023
  from: z2.string().optional(),
5817
6024
  to: z2.string().optional()
5818
6025
  });
6026
+ var adsGeoSearchInputSchema = adsGeoSearchQuerySchema.extend({
6027
+ project: projectNameSchema
6028
+ });
5819
6029
  var adsOperationInputSchema = z2.object({
5820
6030
  project: projectNameSchema,
5821
6031
  operationKey: z2.string().min(8).max(128)
5822
6032
  });
6033
+ var adsOperationResumeActivationInputSchema = adsOperationInputSchema.strict();
6034
+ var adsUnresolvedOperationsInputSchema = adsUnresolvedOperationListQuerySchema.extend({
6035
+ project: projectNameSchema
6036
+ });
6037
+ var adsOperationReconcileInputSchema = adsOperationReconcileRequestSchema.extend({
6038
+ project: projectNameSchema,
6039
+ operationKey: z2.string().min(8).max(128)
6040
+ });
5823
6041
  var adsImageUploadInputSchema = z2.object({
5824
6042
  project: projectNameSchema,
5825
6043
  request: adsImageUploadRequestSchema
@@ -5833,6 +6051,11 @@ var adsCampaignUpdateInputSchema = z2.object({
5833
6051
  campaignId: z2.string().min(1),
5834
6052
  request: adsCampaignUpdateRequestSchema
5835
6053
  });
6054
+ var adsCampaignActivateTreeInputSchema = z2.object({
6055
+ project: projectNameSchema,
6056
+ campaignId: z2.string().min(1),
6057
+ request: adsActivateTreeRequestSchema
6058
+ });
5836
6059
  var adsCampaignPauseInputSchema = z2.object({
5837
6060
  project: projectNameSchema,
5838
6061
  campaignId: z2.string().min(1),
@@ -7411,6 +7634,50 @@ var canonryMcpTools = [
7411
7634
  openApiOperations: ["GET /api/v1/projects/{name}/ads/status"],
7412
7635
  handler: (client2, input) => client2.getAdsStatus(input.project)
7413
7636
  }),
7637
+ defineTool({
7638
+ name: "canonry_ads_account",
7639
+ title: "Read the live OpenAI ads account",
7640
+ description: "Read live OpenAI Ads account metadata, currency, timezone, status, and account-integrity review state. Use before planning or launch to confirm the connected advertiser account is the intended one and is eligible to serve.",
7641
+ access: "read",
7642
+ tier: "ads",
7643
+ inputSchema: projectInputSchema,
7644
+ annotations: readAnnotations(true),
7645
+ openApiOperations: ["GET /api/v1/projects/{name}/ads/account"],
7646
+ handler: (client2, input) => client2.getAdsAccount(input.project)
7647
+ }),
7648
+ defineTool({
7649
+ name: "canonry_ads_geo_search",
7650
+ title: "Search OpenAI ads locations",
7651
+ description: "Search the live OpenAI Ads geo catalog by place name. Returns provider location IDs and canonical labels; use those IDs in campaign locationIds instead of inventing or guessing targeting identifiers.",
7652
+ access: "read",
7653
+ tier: "ads",
7654
+ inputSchema: adsGeoSearchInputSchema,
7655
+ annotations: readAnnotations(true),
7656
+ openApiOperations: ["GET /api/v1/projects/{name}/ads/geo/search"],
7657
+ handler: (client2, input) => client2.searchAdsGeo(input.project, { q: input.q, limit: input.limit })
7658
+ }),
7659
+ defineTool({
7660
+ name: "canonry_ads_conversion_pixels",
7661
+ title: "List OpenAI ads conversion pixels",
7662
+ description: "List conversion pixels from the live OpenAI ad account. Use with conversion event settings to verify that measurable conversion infrastructure exists before recommending activation or budget changes.",
7663
+ access: "read",
7664
+ tier: "ads",
7665
+ inputSchema: projectInputSchema,
7666
+ annotations: readAnnotations(true),
7667
+ openApiOperations: ["GET /api/v1/projects/{name}/ads/conversions/pixels"],
7668
+ handler: (client2, input) => client2.getAdsConversionPixels(input.project)
7669
+ }),
7670
+ defineTool({
7671
+ name: "canonry_ads_conversion_event_settings",
7672
+ title: "List OpenAI ads conversion event settings",
7673
+ description: "List live OpenAI Ads conversion event settings, attribution windows, and attached pixel or CAPI sources. Use to select and verify the conversion goal before launch.",
7674
+ access: "read",
7675
+ tier: "ads",
7676
+ inputSchema: projectInputSchema,
7677
+ annotations: readAnnotations(true),
7678
+ openApiOperations: ["GET /api/v1/projects/{name}/ads/conversions/event-settings"],
7679
+ handler: (client2, input) => client2.getAdsConversionEventSettings(input.project)
7680
+ }),
7414
7681
  defineTool({
7415
7682
  name: "canonry_ads_campaigns",
7416
7683
  title: "List synced ad campaigns",
@@ -7444,10 +7711,25 @@ var canonryMcpTools = [
7444
7711
  openApiOperations: ["GET /api/v1/projects/{name}/ads/summary"],
7445
7712
  handler: (client2, input) => client2.getAdsSummary(input.project)
7446
7713
  }),
7714
+ defineTool({
7715
+ name: "canonry_ads_operations_unresolved",
7716
+ title: "List unresolved ads mutation receipts",
7717
+ description: "List pending, unknown, or actively reconciling OpenAI Ads mutation receipts that need recovery. Pass nextCursor back as cursor to advance past permanent rows. Use this before new lifecycle work so an ambiguous earlier outcome is settled instead of retried under another key. Route campaign_tree_activate receipts to canonry_ads_operation_resume_activation; use generic reconciliation only for other supported receipt kinds.",
7718
+ access: "read",
7719
+ tier: "ads",
7720
+ inputSchema: adsUnresolvedOperationsInputSchema,
7721
+ annotations: readAnnotations(),
7722
+ openApiOperations: ["GET /api/v1/projects/{name}/ads/operations"],
7723
+ handler: (client2, input) => client2.getUnresolvedAdsOperations(input.project, {
7724
+ state: input.state,
7725
+ limit: input.limit,
7726
+ cursor: input.cursor
7727
+ })
7728
+ }),
7447
7729
  defineTool({
7448
7730
  name: "canonry_ads_operation_get",
7449
7731
  title: "Get an ads mutation receipt",
7450
- description: "Read the durable receipt for an OpenAI Ads mutation by its caller-supplied operation key. A pending or unknown receipt must be reconciled by a human; never retry it with a new key because the upstream request may already have succeeded.",
7732
+ description: "Read the durable receipt for an OpenAI Ads mutation by its caller-supplied operation key. Never retry a pending or unknown receipt with a new key because the upstream request may already have succeeded. Resume campaign_tree_activate receipts through canonry_ads_operation_resume_activation; send other supported receipt kinds to generic reconciliation.",
7451
7733
  access: "read",
7452
7734
  tier: "ads",
7453
7735
  inputSchema: adsOperationInputSchema,
@@ -7455,6 +7737,28 @@ var canonryMcpTools = [
7455
7737
  openApiOperations: ["GET /api/v1/projects/{name}/ads/operations/{operationKey}"],
7456
7738
  handler: (client2, input) => client2.getAdsOperation(input.project, input.operationKey)
7457
7739
  }),
7740
+ defineTool({
7741
+ name: "canonry_ads_operation_reconcile",
7742
+ title: "Reconcile an ads mutation receipt",
7743
+ description: "Verify a checkpointed provider entity against the receipt-bound OpenAI ad account without retrying the original mutation. Uncheckpointed creates remain unresolved because mutable-field matching cannot prove provenance. This generic tool rejects campaign_tree_activate receipts; use canonry_ads_operation_resume_activation for those.",
7744
+ access: "write",
7745
+ tier: "ads",
7746
+ inputSchema: adsOperationReconcileInputSchema,
7747
+ annotations: writeAnnotations({ idempotentHint: true, openWorldHint: true }),
7748
+ openApiOperations: ["POST /api/v1/projects/{name}/ads/operations/{operationKey}/reconcile"],
7749
+ handler: (client2, input) => client2.reconcileAdsOperation(input.project, input.operationKey)
7750
+ }),
7751
+ defineTool({
7752
+ name: "canonry_ads_operation_resume_activation",
7753
+ title: "Resume an ads activation receipt",
7754
+ description: "Resume recovery for an existing campaign_tree_activate receipt using its durable approval grant and ordered step ledger. The request is bodyless, requires ads.activate on the exact executor key already bound to the grant, and cannot replace the operation, grant, manifest, campaign, or account. Canonry inspects provider state and never blindly resends an ambiguous activation mutation.",
7755
+ access: "write",
7756
+ tier: "ads",
7757
+ inputSchema: adsOperationResumeActivationInputSchema,
7758
+ annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true, openWorldHint: true }),
7759
+ openApiOperations: ["POST /api/v1/projects/{name}/ads/operations/{operationKey}/resume-activation"],
7760
+ handler: (client2, input) => client2.resumeAdsActivation(input.project, input.operationKey)
7761
+ }),
7458
7762
  defineTool({
7459
7763
  name: "canonry_ads_image_upload",
7460
7764
  title: "Upload an ads image from URL",
@@ -7469,7 +7773,7 @@ var canonryMcpTools = [
7469
7773
  defineTool({
7470
7774
  name: "canonry_ads_campaign_create",
7471
7775
  title: "Create a paused ads campaign",
7472
- description: "Create an OpenAI Ads campaign PAUSED with an explicit lifetime spend limit and location allowlist. The server ignores any status concept and always sends paused. Inspect the receipt, then create paused ad groups and ads. Activation is deliberately human-only for the beta.",
7776
+ description: "Create an OpenAI Ads campaign PAUSED with an explicit lifetime spend limit and location allowlist. Set biddingType=clicks with one or more provider-issued conversionEventSettingIds for conversion-optimized delivery; omit both for legacy impressions bidding. The server ignores any status concept and always sends paused. Inspect the receipt, then create matching paused ad groups and ads. A human must separately approve the exact tree before this operator can activate it.",
7473
7777
  access: "write",
7474
7778
  tier: "ads",
7475
7779
  inputSchema: adsCampaignCreateInputSchema,
@@ -7480,7 +7784,7 @@ var canonryMcpTools = [
7480
7784
  defineTool({
7481
7785
  name: "canonry_ads_campaign_update",
7482
7786
  title: "Update an ads campaign",
7483
- description: "Update a PAUSED campaign copy, dates, lifetime spend limit, or locations without changing status. Active campaigns fail closed: pause first, sync, and use the refreshed upstreamUpdatedAt. A human must reactivate after reviewing the change. Uses a durable operation key.",
7787
+ description: "Update a PAUSED campaign copy, dates, lifetime spend limit, or locations without changing status. Active campaigns fail closed: pause first, sync, and use the refreshed upstreamUpdatedAt. A human must approve the exact updated tree before this operator can reactivate it. Uses a durable operation key.",
7484
7788
  access: "write",
7485
7789
  tier: "ads",
7486
7790
  inputSchema: adsCampaignUpdateInputSchema,
@@ -7488,6 +7792,17 @@ var canonryMcpTools = [
7488
7792
  openApiOperations: ["POST /api/v1/projects/{name}/ads/campaigns/{id}"],
7489
7793
  handler: (client2, input) => client2.updateAdsCampaign(input.project, input.campaignId, input.request)
7490
7794
  }),
7795
+ defineTool({
7796
+ name: "canonry_ads_campaign_activate_tree",
7797
+ title: "Activate an approved ads campaign tree",
7798
+ description: "Execute one short-lived human approval grant for the exact paused campaign, ad groups, and reviewed ads named by its manifest. The grant is bound to this executor key and manifest hash. Canonry checkpoints every step, activates ads before parents, verifies active state, and rolls back parent-first on failure. This tool cannot create or widen an approval.",
7799
+ access: "write",
7800
+ tier: "ads",
7801
+ inputSchema: adsCampaignActivateTreeInputSchema,
7802
+ annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true, openWorldHint: true }),
7803
+ openApiOperations: ["POST /api/v1/projects/{name}/ads/campaigns/{id}/activate-tree"],
7804
+ handler: (client2, input) => client2.activateAdsCampaignTree(input.project, input.campaignId, input.request)
7805
+ }),
7491
7806
  defineTool({
7492
7807
  name: "canonry_ads_campaign_pause",
7493
7808
  title: "Pause an ads campaign",
@@ -7502,7 +7817,7 @@ var canonryMcpTools = [
7502
7817
  defineTool({
7503
7818
  name: "canonry_ads_ad_group_create",
7504
7819
  title: "Create a paused ads ad group",
7505
- description: "Create a PAUSED ad group under a reviewed campaign. Context hints describe when the audit offer is useful; maxBidMicros is an impression bid. The server fixes the billing event to impression.",
7820
+ description: "Create a PAUSED ad group under a reviewed campaign. Context hints describe when the audit offer is useful. Set billingEventType=click under a clicks campaign; omit it for the legacy impression mode. Canonry reads the live parent and rejects a billing/bidding mismatch before mutation.",
7506
7821
  access: "write",
7507
7822
  tier: "ads",
7508
7823
  inputSchema: adsAdGroupCreateInputSchema,
@@ -7513,7 +7828,7 @@ var canonryMcpTools = [
7513
7828
  defineTool({
7514
7829
  name: "canonry_ads_ad_group_update",
7515
7830
  title: "Update an ads ad group",
7516
- description: "Update a PAUSED ad group name, description, context hints, or impression bid without changing status. Active ad groups fail closed: pause first, sync, and use the refreshed upstreamUpdatedAt. A human must reactivate after review. Uses a durable operation key.",
7831
+ description: "Update a PAUSED ad group name, description, context hints, or max bid without changing its billing event or status. Active ad groups fail closed: pause first, sync, and use the refreshed upstreamUpdatedAt. A human must reactivate after review. Uses a durable operation key.",
7517
7832
  access: "write",
7518
7833
  tier: "ads",
7519
7834
  inputSchema: adsAdGroupUpdateInputSchema,