@ainyc/canonry 4.50.0 → 4.51.1

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 (29) hide show
  1. package/assets/assets/BacklinksPage-DIZCcqsP.js +1 -0
  2. package/assets/assets/ChartPrimitives-9Kx3gzQL.js +1 -0
  3. package/assets/assets/ProjectPage-R2cxJb5Y.js +6 -0
  4. package/assets/assets/RunRow-DqezNIUy.js +1 -0
  5. package/assets/assets/RunsPage-CfvTJ9Ny.js +1 -0
  6. package/assets/assets/SettingsPage-HfMGIa5v.js +1 -0
  7. package/assets/assets/TrafficPage-DV_Dvpl3.js +1 -0
  8. package/assets/assets/TrafficSourceDetailPage-lefreKBO.js +1 -0
  9. package/assets/assets/arrow-left-DpxpMUNt.js +1 -0
  10. package/assets/assets/index-DKBPD33e.js +210 -0
  11. package/assets/assets/{index-DOP3oQmw.css → index-DeGyEwik.css} +1 -1
  12. package/assets/assets/server-traffic-Bm8iKtXK.js +1 -0
  13. package/assets/assets/trash-2-CnBiLbiZ.js +1 -0
  14. package/assets/assets/{vendor-markdown-DN2199pt.js → vendor-markdown-DK7fbRNb.js} +1 -1
  15. package/assets/assets/{vendor-radix-Bvy4KXTI.js → vendor-radix-B57xfQbP.js} +1 -1
  16. package/assets/assets/{vendor-recharts-DPeiXMwW.js → vendor-recharts-DWvKDyBF.js} +1 -1
  17. package/assets/assets/vendor-tanstack-Dq7p98wZ.js +1 -0
  18. package/assets/index.html +6 -6
  19. package/dist/{chunk-QIG3TKL4.js → chunk-2ARCCG5E.js} +72 -1
  20. package/dist/{chunk-M4USKXJ4.js → chunk-DLDLDWH4.js} +128 -40
  21. package/dist/{chunk-MYDJ25GO.js → chunk-GGXU5VKI.js} +111 -77
  22. package/dist/{chunk-YVP5CTSV.js → chunk-JOKPYAEL.js} +2178 -1624
  23. package/dist/cli.js +6 -6
  24. package/dist/index.js +4 -4
  25. package/dist/{intelligence-service-TY7IPRST.js → intelligence-service-XMZEWLCW.js} +2 -2
  26. package/dist/mcp.js +2 -2
  27. package/package.json +9 -9
  28. package/assets/assets/index-DVK0M62U.js +0 -214
  29. package/assets/assets/vendor-tanstack-DPXTJtWt.js +0 -1
@@ -10,7 +10,7 @@ import {
10
10
  categoryLabel,
11
11
  determineAnswerMentioned,
12
12
  normalizeProjectDomain
13
- } from "./chunk-QIG3TKL4.js";
13
+ } from "./chunk-2ARCCG5E.js";
14
14
 
15
15
  // src/intelligence-service.ts
16
16
  import { eq, desc, asc, and, ne, or, inArray } from "drizzle-orm";
@@ -37,6 +37,7 @@ __export(schema_exports, {
37
37
  bingUrlInspections: () => bingUrlInspections,
38
38
  ccReleaseSyncs: () => ccReleaseSyncs,
39
39
  competitors: () => competitors,
40
+ contentTargetDismissals: () => contentTargetDismissals,
40
41
  crawlerEventsHourly: () => crawlerEventsHourly,
41
42
  discoveryProbes: () => discoveryProbes,
42
43
  discoverySessions: () => discoverySessions,
@@ -58,6 +59,7 @@ __export(schema_exports, {
58
59
  queries: () => queries,
59
60
  querySnapshots: () => querySnapshots,
60
61
  rawEventSamples: () => rawEventSamples,
62
+ recommendationExplanations: () => recommendationExplanations,
61
63
  runs: () => runs,
62
64
  schedules: () => schedules,
63
65
  trafficSources: () => trafficSources,
@@ -69,16 +71,16 @@ var projects = sqliteTable("projects", {
69
71
  name: text("name").notNull().unique(),
70
72
  displayName: text("display_name").notNull(),
71
73
  canonicalDomain: text("canonical_domain").notNull(),
72
- ownedDomains: text("owned_domains").notNull().default("[]"),
73
- aliases: text("aliases").notNull().default("[]"),
74
+ ownedDomains: text("owned_domains", { mode: "json" }).$type().notNull().default([]),
75
+ aliases: text("aliases", { mode: "json" }).$type().notNull().default([]),
74
76
  country: text("country").notNull(),
75
77
  language: text("language").notNull(),
76
- tags: text("tags").notNull().default("[]"),
77
- labels: text("labels").notNull().default("{}"),
78
- providers: text("providers").notNull().default("[]"),
79
- locations: text("locations").notNull().default("[]"),
78
+ tags: text("tags", { mode: "json" }).$type().notNull().default([]),
79
+ labels: text("labels", { mode: "json" }).$type().notNull().default({}),
80
+ providers: text("providers", { mode: "json" }).$type().notNull().default([]),
81
+ locations: text("locations", { mode: "json" }).$type().notNull().default([]),
80
82
  defaultLocation: text("default_location"),
81
- autoExtractBacklinks: integer("auto_extract_backlinks").notNull().default(0),
83
+ autoExtractBacklinks: integer("auto_extract_backlinks", { mode: "boolean" }).notNull().default(false),
82
84
  configSource: text("config_source").notNull().default("cli"),
83
85
  configRevision: integer("config_revision").notNull().default(1),
84
86
  icpDescription: text("icp_description"),
@@ -112,7 +114,7 @@ var runs = sqliteTable("runs", {
112
114
  status: text("status").notNull().default("queued"),
113
115
  trigger: text("trigger").notNull().default("manual"),
114
116
  location: text("location"),
115
- queries: text("queries"),
117
+ queries: text("queries", { mode: "json" }).$type(),
116
118
  sourceId: text("source_id"),
117
119
  startedAt: text("started_at"),
118
120
  finishedAt: text("finished_at"),
@@ -139,9 +141,9 @@ var querySnapshots = sqliteTable("query_snapshots", {
139
141
  citationState: text("citation_state").notNull(),
140
142
  answerMentioned: integer("answer_mentioned", { mode: "boolean" }),
141
143
  answerText: text("answer_text"),
142
- citedDomains: text("cited_domains").notNull().default("[]"),
143
- competitorOverlap: text("competitor_overlap").notNull().default("[]"),
144
- recommendedCompetitors: text("recommended_competitors").notNull().default("[]"),
144
+ citedDomains: text("cited_domains", { mode: "json" }).$type().notNull().default([]),
145
+ competitorOverlap: text("competitor_overlap", { mode: "json" }).$type().notNull().default([]),
146
+ recommendedCompetitors: text("recommended_competitors", { mode: "json" }).$type().notNull().default([]),
145
147
  location: text("location"),
146
148
  screenshotPath: text("screenshot_path"),
147
149
  rawResponse: text("raw_response"),
@@ -177,7 +179,7 @@ var apiKeys = sqliteTable("api_keys", {
177
179
  name: text("name").notNull(),
178
180
  keyHash: text("key_hash").notNull().unique(),
179
181
  keyPrefix: text("key_prefix").notNull(),
180
- scopes: text("scopes").notNull().default('["*"]'),
182
+ scopes: text("scopes", { mode: "json" }).$type().notNull().default(["*"]),
181
183
  createdAt: text("created_at").notNull(),
182
184
  lastUsedAt: text("last_used_at"),
183
185
  revokedAt: text("revoked_at")
@@ -195,8 +197,8 @@ var schedules = sqliteTable("schedules", {
195
197
  cronExpr: text("cron_expr").notNull(),
196
198
  preset: text("preset"),
197
199
  timezone: text("timezone").notNull().default("UTC"),
198
- enabled: integer("enabled").notNull().default(1),
199
- providers: text("providers").notNull().default("[]"),
200
+ enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
201
+ providers: text("providers", { mode: "json" }).$type().notNull().default([]),
200
202
  /** Optional traffic-source UUID for traffic-sync schedules. Null for other kinds. */
201
203
  sourceId: text("source_id"),
202
204
  lastRunAt: text("last_run_at"),
@@ -210,9 +212,9 @@ var notifications = sqliteTable("notifications", {
210
212
  id: text("id").primaryKey(),
211
213
  projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
212
214
  channel: text("channel").notNull(),
213
- config: text("config").notNull(),
215
+ config: text("config", { mode: "json" }).$type().notNull(),
214
216
  webhookSecret: text("webhook_secret"),
215
- enabled: integer("enabled").notNull().default(1),
217
+ enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
216
218
  createdAt: text("created_at").notNull(),
217
219
  updatedAt: text("updated_at").notNull()
218
220
  }, (table) => [
@@ -224,7 +226,7 @@ var googleConnections = sqliteTable("google_connections", {
224
226
  connectionType: text("connection_type").notNull(),
225
227
  propertyId: text("property_id"),
226
228
  sitemapUrl: text("sitemap_url"),
227
- scopes: text("scopes").notNull().default("[]"),
229
+ scopes: text("scopes", { mode: "json" }).$type().notNull().default([]),
228
230
  createdAt: text("created_at").notNull(),
229
231
  updatedAt: text("updated_at").notNull()
230
232
  }, (table) => [
@@ -261,9 +263,9 @@ var gscUrlInspections = sqliteTable("gsc_url_inspections", {
261
263
  robotsTxtState: text("robots_txt_state"),
262
264
  crawlTime: text("crawl_time"),
263
265
  lastCrawlResult: text("last_crawl_result"),
264
- isMobileFriendly: integer("is_mobile_friendly"),
265
- richResults: text("rich_results").notNull().default("[]"),
266
- referringUrls: text("referring_urls").notNull().default("[]"),
266
+ isMobileFriendly: integer("is_mobile_friendly", { mode: "boolean" }),
267
+ richResults: text("rich_results", { mode: "json" }).$type().notNull().default([]),
268
+ referringUrls: text("referring_urls", { mode: "json" }).$type().notNull().default([]),
267
269
  inspectedAt: text("inspected_at").notNull(),
268
270
  createdAt: text("created_at").notNull()
269
271
  }, (table) => [
@@ -278,7 +280,7 @@ var gscCoverageSnapshots = sqliteTable("gsc_coverage_snapshots", {
278
280
  date: text("date").notNull(),
279
281
  indexed: integer("indexed").notNull().default(0),
280
282
  notIndexed: integer("not_indexed").notNull().default(0),
281
- reasonBreakdown: text("reason_breakdown").notNull().default("{}"),
283
+ reasonBreakdown: text("reason_breakdown", { mode: "json" }).$type().notNull().default({}),
282
284
  createdAt: text("created_at").notNull()
283
285
  }, (table) => [
284
286
  index("idx_gsc_coverage_snap_project_date").on(table.projectId, table.date),
@@ -311,7 +313,7 @@ var bingUrlInspections = sqliteTable("bing_url_inspections", {
311
313
  projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
312
314
  url: text("url").notNull(),
313
315
  httpCode: integer("http_code"),
314
- inIndex: integer("in_index"),
316
+ inIndex: integer("in_index", { mode: "boolean" }),
315
317
  lastCrawledDate: text("last_crawled_date"),
316
318
  inIndexDate: text("in_index_date"),
317
319
  inspectedAt: text("inspected_at").notNull(),
@@ -472,8 +474,8 @@ var insights = sqliteTable("insights", {
472
474
  title: text("title").notNull(),
473
475
  query: text("query").notNull(),
474
476
  provider: text("provider").notNull(),
475
- recommendation: text("recommendation"),
476
- cause: text("cause"),
477
+ recommendation: text("recommendation", { mode: "json" }).$type(),
478
+ cause: text("cause", { mode: "json" }).$type(),
477
479
  dismissed: integer("dismissed", { mode: "boolean" }).notNull().default(false),
478
480
  createdAt: text("created_at").notNull()
479
481
  }, (table) => [
@@ -489,7 +491,7 @@ var healthSnapshots = sqliteTable("health_snapshots", {
489
491
  overallCitedRate: text("overall_cited_rate").notNull(),
490
492
  totalPairs: integer("total_pairs").notNull(),
491
493
  citedPairs: integer("cited_pairs").notNull(),
492
- providerBreakdown: text("provider_breakdown").notNull().default("{}"),
494
+ providerBreakdown: text("provider_breakdown", { mode: "json" }).$type().notNull().default({}),
493
495
  createdAt: text("created_at").notNull()
494
496
  }, (table) => [
495
497
  index("idx_health_snapshots_project").on(table.projectId),
@@ -589,9 +591,9 @@ var trafficSources = sqliteTable("traffic_sources", {
589
591
  // observed in the most recent successful sync. Bounded ring buffer used to
590
592
  // dedupe across sync runs at the boundary timestamp where lastSyncedAt
591
593
  // clamping alone leaves a small overlap window.
592
- lastEventIds: text("last_event_ids"),
594
+ lastEventIds: text("last_event_ids", { mode: "json" }).$type(),
593
595
  archivedAt: text("archived_at"),
594
- configJson: text("config_json").notNull().default("{}"),
596
+ configJson: text("config_json", { mode: "json" }).$type().notNull().default({}),
595
597
  createdAt: text("created_at").notNull(),
596
598
  updatedAt: text("updated_at").notNull()
597
599
  }, (table) => [
@@ -667,7 +669,7 @@ var rawEventSamples = sqliteTable("raw_event_samples", {
667
669
  pathNormalized: text("path_normalized").notNull(),
668
670
  status: integer("status"),
669
671
  refererHost: text("referer_host"),
670
- classifierDetailsJson: text("classifier_details_json").notNull().default("{}"),
672
+ classifierDetailsJson: text("classifier_details_json", { mode: "json" }).$type().notNull().default({}),
671
673
  createdAt: text("created_at").notNull()
672
674
  }, (table) => [
673
675
  index("idx_raw_event_samples_project_ts").on(table.projectId, table.ts),
@@ -688,7 +690,7 @@ var discoverySessions = sqliteTable("discovery_sessions", {
688
690
  citedCount: integer("cited_count"),
689
691
  aspirationalCount: integer("aspirational_count"),
690
692
  wastedCount: integer("wasted_count"),
691
- competitorMap: text("competitor_map").notNull().default("[]"),
693
+ competitorMap: text("competitor_map", { mode: "json" }).$type().notNull().default([]),
692
694
  error: text("error"),
693
695
  startedAt: text("started_at"),
694
696
  finishedAt: text("finished_at"),
@@ -704,13 +706,43 @@ var discoveryProbes = sqliteTable("discovery_probes", {
704
706
  query: text("query").notNull(),
705
707
  bucket: text("bucket"),
706
708
  citationState: text("citation_state").notNull(),
707
- citedDomains: text("cited_domains").notNull().default("[]"),
709
+ citedDomains: text("cited_domains", { mode: "json" }).$type().notNull().default([]),
708
710
  rawResponse: text("raw_response"),
709
711
  createdAt: text("created_at").notNull()
710
712
  }, (table) => [
711
713
  index("idx_discovery_probes_session").on(table.sessionId),
712
714
  index("idx_discovery_probes_project").on(table.projectId)
713
715
  ]);
716
+ var contentTargetDismissals = sqliteTable("content_target_dismissals", {
717
+ id: text("id").primaryKey(),
718
+ projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
719
+ targetRef: text("target_ref").notNull(),
720
+ addressedUrl: text("addressed_url"),
721
+ note: text("note"),
722
+ dismissedAt: text("dismissed_at").notNull()
723
+ }, (table) => [
724
+ uniqueIndex("idx_content_target_dismissals_project_ref").on(table.projectId, table.targetRef),
725
+ index("idx_content_target_dismissals_project").on(table.projectId)
726
+ ]);
727
+ var recommendationExplanations = sqliteTable("recommendation_explanations", {
728
+ id: text("id").primaryKey(),
729
+ projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
730
+ targetRef: text("target_ref").notNull(),
731
+ promptVersion: text("prompt_version").notNull(),
732
+ provider: text("provider").notNull(),
733
+ model: text("model").notNull(),
734
+ responseText: text("response_text").notNull(),
735
+ /** Estimated cost in millicents (1/100 of a cent) for audit; 0 if unknown. */
736
+ costMillicents: integer("cost_millicents").notNull().default(0),
737
+ generatedAt: text("generated_at").notNull()
738
+ }, (table) => [
739
+ uniqueIndex("idx_recommendation_explanations_unique").on(
740
+ table.projectId,
741
+ table.targetRef,
742
+ table.promptVersion
743
+ ),
744
+ index("idx_recommendation_explanations_project").on(table.projectId)
745
+ ]);
714
746
  var migrationsTable = sqliteTable("_migrations", {
715
747
  version: integer("version").primaryKey(),
716
748
  name: text("name").notNull(),
@@ -1942,6 +1974,55 @@ var MIGRATION_VERSIONS = [
1942
1974
  `CREATE INDEX IF NOT EXISTS idx_audit_log_project ON audit_log(project_id)`,
1943
1975
  `CREATE INDEX IF NOT EXISTS idx_audit_log_created ON audit_log(created_at)`
1944
1976
  ]
1977
+ },
1978
+ {
1979
+ version: 61,
1980
+ name: "content-target-dismissals",
1981
+ // Persistent per-recommendation dismissal so users can mark a content
1982
+ // opportunity "addressed" after they ship the page. The orchestrator
1983
+ // recomputes opportunities on every report load from live GSC / GA
1984
+ // inventory; without persistent dismissal, a recommendation lingers
1985
+ // until the next sync surfaces the new page (days–weeks of lag).
1986
+ //
1987
+ // Keyed by `(project_id, target_ref)` where `target_ref` is the stable
1988
+ // hash that `computeTargetRef()` already produces — same value the
1989
+ // ContentTargetRowDto exposes, so the client passes back the ref it
1990
+ // sees.
1991
+ statements: [
1992
+ `CREATE TABLE IF NOT EXISTS content_target_dismissals (
1993
+ id TEXT PRIMARY KEY,
1994
+ project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
1995
+ target_ref TEXT NOT NULL,
1996
+ addressed_url TEXT,
1997
+ note TEXT,
1998
+ dismissed_at TEXT NOT NULL
1999
+ )`,
2000
+ `CREATE UNIQUE INDEX IF NOT EXISTS idx_content_target_dismissals_project_ref ON content_target_dismissals(project_id, target_ref)`,
2001
+ `CREATE INDEX IF NOT EXISTS idx_content_target_dismissals_project ON content_target_dismissals(project_id)`
2002
+ ]
2003
+ },
2004
+ {
2005
+ version: 62,
2006
+ name: "recommendation-explanations",
2007
+ // LLM-generated rationale for content recommendations. Cached per
2008
+ // (project, target_ref, prompt_version) so repeat clicks are free.
2009
+ // Bumping the prompt version invalidates the cache forward without
2010
+ // touching the table.
2011
+ statements: [
2012
+ `CREATE TABLE IF NOT EXISTS recommendation_explanations (
2013
+ id TEXT PRIMARY KEY,
2014
+ project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
2015
+ target_ref TEXT NOT NULL,
2016
+ prompt_version TEXT NOT NULL,
2017
+ provider TEXT NOT NULL,
2018
+ model TEXT NOT NULL,
2019
+ response_text TEXT NOT NULL,
2020
+ cost_millicents INTEGER NOT NULL DEFAULT 0,
2021
+ generated_at TEXT NOT NULL
2022
+ )`,
2023
+ `CREATE UNIQUE INDEX IF NOT EXISTS idx_recommendation_explanations_unique ON recommendation_explanations(project_id, target_ref, prompt_version)`,
2024
+ `CREATE INDEX IF NOT EXISTS idx_recommendation_explanations_project ON recommendation_explanations(project_id)`
2025
+ ]
1945
2026
  }
1946
2027
  ];
1947
2028
  function isDuplicateColumnError(err) {
@@ -2636,9 +2717,15 @@ function isBlogShaped(path) {
2636
2717
  // ../intelligence/src/content-classifier.ts
2637
2718
  var SEO_STRONG_THRESHOLD = 10;
2638
2719
  var SEO_WEAK_THRESHOLD = 30;
2720
+ function isHomepageOnly(url) {
2721
+ if (url === "/" || url === "") return true;
2722
+ const stripped = url.split("?")[0].replace(/\/+$/, "");
2723
+ return stripped === "" || stripped === "/";
2724
+ }
2639
2725
  function classifyContentAction(input) {
2640
2726
  const { ourPage, ourPageInGroundingSources, ourPageHasSchema } = input;
2641
2727
  if (!ourPage) return "create";
2728
+ if (isHomepageOnly(ourPage.url)) return "create";
2642
2729
  if (ourPageInGroundingSources) {
2643
2730
  if (ourPageHasSchema === false) return "add-schema";
2644
2731
  return null;
@@ -2783,8 +2870,7 @@ function buildContentTargetRows(input) {
2783
2870
  const targetRef = computeTargetRef({
2784
2871
  projectId: input.projectId,
2785
2872
  query: cq.query,
2786
- action,
2787
- targetPage: ourPage?.url ?? null
2873
+ action
2788
2874
  });
2789
2875
  const winningCompetitor = pickTopCompetitor(cq.competitorGroundingUrls);
2790
2876
  const ourBestPage = ourPage ? {
@@ -2936,7 +3022,7 @@ function pickTopCompetitor(competitors2) {
2936
3022
  };
2937
3023
  }
2938
3024
  function computeTargetRef(input) {
2939
- const key = [input.projectId, input.query, input.action, input.targetPage ?? ""].join("|");
3025
+ const key = [input.projectId, input.query, input.action].join("|");
2940
3026
  let hash = 0;
2941
3027
  for (let i = 0; i < key.length; i++) {
2942
3028
  hash = (hash << 5) - hash + key.charCodeAt(i) | 0;
@@ -4136,8 +4222,8 @@ var IntelligenceService = class {
4136
4222
  title: insight.title,
4137
4223
  query: insight.query,
4138
4224
  provider: insight.provider,
4139
- recommendation: insight.recommendation ? JSON.stringify(insight.recommendation) : null,
4140
- cause: insight.cause ? JSON.stringify(insight.cause) : null,
4225
+ recommendation: insight.recommendation ?? null,
4226
+ cause: insight.cause ?? null,
4141
4227
  dismissed: wasDismissed,
4142
4228
  createdAt: insight.createdAt
4143
4229
  }).run();
@@ -4149,7 +4235,7 @@ var IntelligenceService = class {
4149
4235
  overallCitedRate: String(result.health.overallCitedRate),
4150
4236
  totalPairs: result.health.totalPairs,
4151
4237
  citedPairs: result.health.citedPairs,
4152
- providerBreakdown: JSON.stringify(result.health.providerBreakdown),
4238
+ providerBreakdown: result.health.providerBreakdown,
4153
4239
  createdAt: now
4154
4240
  }).run();
4155
4241
  });
@@ -4184,7 +4270,7 @@ var IntelligenceService = class {
4184
4270
  const projectRow = this.db.select({ locations: projects.locations }).from(projects).where(eq(projects.id, projectId)).get();
4185
4271
  const locationCount = Math.max(
4186
4272
  1,
4187
- parseJsonColumn(projectRow?.locations ?? null, []).length
4273
+ (projectRow?.locations ?? []).length
4188
4274
  );
4189
4275
  const ROWS_PER_GROUP_BUDGET = Math.max(2, locationCount);
4190
4276
  const recentRunRows = this.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(
@@ -4260,8 +4346,8 @@ var IntelligenceService = class {
4260
4346
  orphanCount++;
4261
4347
  continue;
4262
4348
  }
4263
- const domains = parseJsonColumn(r.citedDomains, []);
4264
- const competitors2 = parseJsonColumn(r.competitorOverlap, []);
4349
+ const domains = r.citedDomains;
4350
+ const competitors2 = r.competitorOverlap;
4265
4351
  snapshots.push({
4266
4352
  query: resolvedQuery,
4267
4353
  provider: r.provider,
@@ -4321,6 +4407,8 @@ export {
4321
4407
  rawEventSamples,
4322
4408
  discoverySessions,
4323
4409
  discoveryProbes,
4410
+ contentTargetDismissals,
4411
+ recommendationExplanations,
4324
4412
  createClient,
4325
4413
  parseJsonColumn,
4326
4414
  extractLegacyCredentials,
@@ -22,7 +22,7 @@ import {
22
22
  trafficConnectVercelRequestSchema,
23
23
  trafficConnectWordpressRequestSchema,
24
24
  trafficEventKindSchema
25
- } from "./chunk-QIG3TKL4.js";
25
+ } from "./chunk-2ARCCG5E.js";
26
26
 
27
27
  // src/config.ts
28
28
  import fs from "fs";
@@ -3117,6 +3117,86 @@ var postApiV1ProjectsByNameDiscoverSessionsByIdPromote = (options) => {
3117
3117
  }
3118
3118
  });
3119
3119
  };
3120
+ var deleteApiV1ProjectsByNameAgentTranscript = (options) => {
3121
+ return (options.client ?? client).delete({
3122
+ security: [
3123
+ {
3124
+ scheme: "bearer",
3125
+ type: "http"
3126
+ }
3127
+ ],
3128
+ url: "/api/v1/projects/{name}/agent/transcript",
3129
+ ...options
3130
+ });
3131
+ };
3132
+ var getApiV1ProjectsByNameAgentTranscript = (options) => {
3133
+ return (options.client ?? client).get({
3134
+ security: [
3135
+ {
3136
+ scheme: "bearer",
3137
+ type: "http"
3138
+ }
3139
+ ],
3140
+ url: "/api/v1/projects/{name}/agent/transcript",
3141
+ ...options
3142
+ });
3143
+ };
3144
+ var deleteApiV1ProjectsByNameAgentMemory = (options) => {
3145
+ return (options.client ?? client).delete({
3146
+ security: [
3147
+ {
3148
+ scheme: "bearer",
3149
+ type: "http"
3150
+ }
3151
+ ],
3152
+ url: "/api/v1/projects/{name}/agent/memory",
3153
+ ...options,
3154
+ headers: {
3155
+ "Content-Type": "application/json",
3156
+ ...options.headers
3157
+ }
3158
+ });
3159
+ };
3160
+ var getApiV1ProjectsByNameAgentMemory = (options) => {
3161
+ return (options.client ?? client).get({
3162
+ security: [
3163
+ {
3164
+ scheme: "bearer",
3165
+ type: "http"
3166
+ }
3167
+ ],
3168
+ url: "/api/v1/projects/{name}/agent/memory",
3169
+ ...options
3170
+ });
3171
+ };
3172
+ var putApiV1ProjectsByNameAgentMemory = (options) => {
3173
+ return (options.client ?? client).put({
3174
+ security: [
3175
+ {
3176
+ scheme: "bearer",
3177
+ type: "http"
3178
+ }
3179
+ ],
3180
+ url: "/api/v1/projects/{name}/agent/memory",
3181
+ ...options,
3182
+ headers: {
3183
+ "Content-Type": "application/json",
3184
+ ...options.headers
3185
+ }
3186
+ });
3187
+ };
3188
+ var getApiV1ProjectsByNameAgentProviders = (options) => {
3189
+ return (options.client ?? client).get({
3190
+ security: [
3191
+ {
3192
+ scheme: "bearer",
3193
+ type: "http"
3194
+ }
3195
+ ],
3196
+ url: "/api/v1/projects/{name}/agent/providers",
3197
+ ...options
3198
+ });
3199
+ };
3120
3200
 
3121
3201
  // ../api-client-generated/src/index.ts
3122
3202
  function createClient2(opts) {
@@ -3239,94 +3319,48 @@ var ApiClient = class {
3239
3319
  }
3240
3320
  return result.data;
3241
3321
  }
3242
- /**
3243
- * Raw HTTP call — used for the agent transcript / providers / memory routes,
3244
- * which are registered locally in `packages/canonry/src/agent/agent-routes.ts`
3245
- * and aren't (yet) emitted by the OpenAPI spec. Once they're in the spec we
3246
- * regen the client and migrate these to `invoke()` like every other method.
3247
- */
3248
- async request(method, path2, body) {
3249
- await this.probeBasePath();
3250
- const url = `${this.originUrl}/api/v1${path2}`;
3251
- const serializedBody = body != null ? JSON.stringify(body) : void 0;
3252
- const headers = {
3253
- Authorization: `Bearer ${this.apiKey}`,
3254
- Accept: "application/json",
3255
- ...serializedBody != null ? { "Content-Type": "application/json" } : {}
3256
- };
3257
- const traceEnabled = process.env.CANONRY_TRACE === "1";
3258
- const traceStart = traceEnabled ? Date.now() : 0;
3259
- let res;
3260
- try {
3261
- res = await fetch(url, { method, headers, body: serializedBody });
3262
- } catch (err) {
3263
- if (traceEnabled) {
3264
- const durMs = Date.now() - traceStart;
3265
- process.stderr.write(`[trace] ${method} ${url} \u2192 ERROR (${durMs}ms)
3266
- `);
3267
- }
3268
- if (err instanceof CliError) throw err;
3269
- const msg = err instanceof Error ? err.message : String(err);
3270
- if (msg.includes("fetch failed") || msg.includes("ECONNREFUSED") || msg.includes("connect ECONNREFUSED")) {
3271
- throw new CliError({
3272
- code: "CONNECTION_ERROR",
3273
- message: `Could not connect to canonry server at ${this.originUrl}. Start it with "canonry serve" (or "canonry serve &" to run in background).`,
3274
- exitCode: EXIT_SYSTEM_ERROR
3275
- });
3276
- }
3277
- throw new CliError({ code: "CONNECTION_ERROR", message: msg, exitCode: EXIT_SYSTEM_ERROR });
3278
- }
3279
- if (!res.ok) {
3280
- let errorBody;
3281
- try {
3282
- errorBody = await res.json();
3283
- } catch {
3284
- errorBody = { error: { code: "UNKNOWN", message: res.statusText } };
3285
- }
3286
- const errorObj = errorBody && typeof errorBody === "object" && "error" in errorBody && errorBody.error && typeof errorBody.error === "object" ? errorBody.error : null;
3287
- const msg = errorObj?.message ? String(errorObj.message) : `HTTP ${res.status}: ${res.statusText}`;
3288
- const code = errorObj?.code ? String(errorObj.code) : "API_ERROR";
3289
- const exitCode = res.status >= 500 ? EXIT_SYSTEM_ERROR : EXIT_USER_ERROR;
3290
- throw new CliError({
3291
- code,
3292
- message: msg,
3293
- exitCode,
3294
- details: { ...errorObj?.details ?? {}, httpStatus: res.status }
3295
- });
3296
- }
3297
- if (traceEnabled) {
3298
- const durMs = Date.now() - traceStart;
3299
- process.stderr.write(`[trace] ${method} ${url} \u2192 ${res.status} (${durMs}ms)
3300
- `);
3301
- }
3302
- if (res.status === 204) return void 0;
3303
- return await res.json();
3304
- }
3305
- // ── Agent (routes not in OpenAPI spec — raw request<T>) ─────────────────
3322
+ // ── Agent (canonry-local routes — SDK-typed since v4.50.0) ─────────────
3323
+ //
3324
+ // These endpoints live in `packages/canonry/src/agent/agent-routes.ts` and
3325
+ // are registered through `apiRoutes.registerAuthenticatedRoutes`, not the
3326
+ // shared `routeCatalog`. They appear in the OpenAPI spec only when the
3327
+ // caller passes `includeCanonryLocal: true` to `buildOpenApiDocument` —
3328
+ // which canonry's own server and the codegen both do, so they're in the
3329
+ // generated SDK and we route them through `invoke()` like every other
3330
+ // endpoint. The SSE `POST /agent/prompt` is intentionally not here — it
3331
+ // stays on `streamPost()` below since the SDK can't represent SSE cleanly.
3306
3332
  async getAgentTranscript(project) {
3307
- return this.request("GET", `/projects/${encodeURIComponent(project)}/agent/transcript`);
3333
+ return this.invoke(
3334
+ () => getApiV1ProjectsByNameAgentTranscript({ client: this.heyClient, path: { name: project } })
3335
+ );
3308
3336
  }
3309
3337
  async resetAgentTranscript(project) {
3310
- await this.request("DELETE", `/projects/${encodeURIComponent(project)}/agent/transcript`);
3338
+ await this.invoke(
3339
+ () => deleteApiV1ProjectsByNameAgentTranscript({ client: this.heyClient, path: { name: project } })
3340
+ );
3311
3341
  }
3312
3342
  async listAgentProviders(project) {
3313
- return this.request("GET", `/projects/${encodeURIComponent(project)}/agent/providers`);
3343
+ return this.invoke(
3344
+ () => getApiV1ProjectsByNameAgentProviders({ client: this.heyClient, path: { name: project } })
3345
+ );
3314
3346
  }
3315
3347
  async listAgentMemory(project) {
3316
- return this.request("GET", `/projects/${encodeURIComponent(project)}/agent/memory`);
3348
+ return this.invoke(
3349
+ () => getApiV1ProjectsByNameAgentMemory({ client: this.heyClient, path: { name: project } })
3350
+ );
3317
3351
  }
3318
3352
  async setAgentMemory(project, body) {
3319
- return this.request(
3320
- "PUT",
3321
- `/projects/${encodeURIComponent(project)}/agent/memory`,
3322
- body
3353
+ return this.invoke(
3354
+ () => putApiV1ProjectsByNameAgentMemory({ client: this.heyClient, path: { name: project }, body })
3323
3355
  );
3324
3356
  }
3325
3357
  async forgetAgentMemory(project, key) {
3326
- return this.request(
3327
- "DELETE",
3328
- `/projects/${encodeURIComponent(project)}/agent/memory`,
3329
- { key }
3358
+ return this.invoke(
3359
+ () => deleteApiV1ProjectsByNameAgentMemory({
3360
+ client: this.heyClient,
3361
+ path: { name: project },
3362
+ body: { key }
3363
+ })
3330
3364
  );
3331
3365
  }
3332
3366
  /**