@ainyc/canonry 4.15.2 → 4.18.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.
@@ -8,7 +8,7 @@ import {
8
8
  categoryLabel,
9
9
  determineAnswerMentioned,
10
10
  normalizeProjectDomain
11
- } from "./chunk-ONI3TX2A.js";
11
+ } from "./chunk-SBZTDECX.js";
12
12
 
13
13
  // src/intelligence-service.ts
14
14
  import { eq, desc, asc, and, or, inArray } from "drizzle-orm";
@@ -166,17 +166,24 @@ var apiKeys = sqliteTable("api_keys", {
166
166
  var schedules = sqliteTable("schedules", {
167
167
  id: text("id").primaryKey(),
168
168
  projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
169
+ // Run kind dispatched by this schedule. Must be a value of `RunKinds` —
170
+ // currently 'answer-visibility' and 'traffic-sync' are user-facing schedulable kinds.
171
+ // Defaults to 'answer-visibility' for backward compatibility with rows
172
+ // created before migration 53.
173
+ kind: text("kind").notNull().default("answer-visibility"),
169
174
  cronExpr: text("cron_expr").notNull(),
170
175
  preset: text("preset"),
171
176
  timezone: text("timezone").notNull().default("UTC"),
172
177
  enabled: integer("enabled").notNull().default(1),
173
178
  providers: text("providers").notNull().default("[]"),
179
+ /** Optional traffic-source UUID for traffic-sync schedules. Null for other kinds. */
180
+ sourceId: text("source_id"),
174
181
  lastRunAt: text("last_run_at"),
175
182
  nextRunAt: text("next_run_at"),
176
183
  createdAt: text("created_at").notNull(),
177
184
  updatedAt: text("updated_at").notNull()
178
185
  }, (table) => [
179
- uniqueIndex("idx_schedules_project").on(table.projectId)
186
+ uniqueIndex("idx_schedules_project_kind").on(table.projectId, table.kind)
180
187
  ]);
181
188
  var notifications = sqliteTable("notifications", {
182
189
  id: text("id").primaryKey(),
@@ -800,7 +807,10 @@ CREATE TABLE IF NOT EXISTS notifications (
800
807
 
801
808
  CREATE INDEX IF NOT EXISTS idx_api_keys_prefix ON api_keys(key_prefix);
802
809
  CREATE INDEX IF NOT EXISTS idx_usage_scope_period ON usage_counters(scope, period);
803
- CREATE UNIQUE INDEX IF NOT EXISTS idx_schedules_project ON schedules(project_id);
810
+ -- NOTE: the (project_id) UNIQUE INDEX that used to live here was replaced by
811
+ -- v53's (project_id, kind) index. MIGRATION_SQL re-runs on every boot, so we
812
+ -- must NOT recreate the single-column index \u2014 it would conflict with v53 and
813
+ -- break traffic-sync schedule creation.
804
814
  CREATE INDEX IF NOT EXISTS idx_notifications_project ON notifications(project_id);
805
815
 
806
816
  -- Migration tracking: records which version has been applied.
@@ -1611,6 +1621,66 @@ var MIGRATION_VERSIONS = [
1611
1621
  // sync window (or any overlapping re-sync) cannot double-count.
1612
1622
  `ALTER TABLE traffic_sources ADD COLUMN last_event_ids TEXT`
1613
1623
  ]
1624
+ },
1625
+ {
1626
+ version: 53,
1627
+ name: "schedules-kind-and-source",
1628
+ // The legacy schedules table carries an inline `UNIQUE(project_id)`
1629
+ // constraint (see MIGRATION_SQL). SQLite doesn't support dropping inline
1630
+ // table constraints, so we use the canonical table-rebuild pattern:
1631
+ // create a new table with the desired schema, copy the data, drop the
1632
+ // old, rename. All 4 statements run inside the migration runner's
1633
+ // single transaction so a partial failure rolls everything back.
1634
+ statements: [
1635
+ // (project_id, kind) uniqueness is enforced by the explicit
1636
+ // `CREATE UNIQUE INDEX idx_schedules_project_kind` below — that's the
1637
+ // canonical drizzle-side index name (see schema.ts), so don't duplicate
1638
+ // it as an inline UNIQUE() in CREATE TABLE.
1639
+ `CREATE TABLE IF NOT EXISTS schedules_v53 (
1640
+ id TEXT PRIMARY KEY,
1641
+ project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
1642
+ kind TEXT NOT NULL DEFAULT 'answer-visibility',
1643
+ cron_expr TEXT NOT NULL,
1644
+ preset TEXT,
1645
+ timezone TEXT NOT NULL DEFAULT 'UTC',
1646
+ enabled INTEGER NOT NULL DEFAULT 1,
1647
+ providers TEXT NOT NULL DEFAULT '[]',
1648
+ source_id TEXT,
1649
+ last_run_at TEXT,
1650
+ next_run_at TEXT,
1651
+ created_at TEXT NOT NULL,
1652
+ updated_at TEXT NOT NULL
1653
+ )`,
1654
+ `INSERT INTO schedules_v53 (
1655
+ id, project_id, kind, cron_expr, preset, timezone, enabled,
1656
+ providers, source_id, last_run_at, next_run_at, created_at, updated_at
1657
+ )
1658
+ SELECT id, project_id, 'answer-visibility', cron_expr, preset, timezone, enabled,
1659
+ providers, NULL, last_run_at, next_run_at, created_at, updated_at
1660
+ FROM schedules`,
1661
+ `DROP TABLE schedules`,
1662
+ `ALTER TABLE schedules_v53 RENAME TO schedules`,
1663
+ // The legacy single-column unique index doesn't survive the table
1664
+ // rename, but explicitly DROP IF EXISTS to keep the migration
1665
+ // idempotent across edge-case re-runs.
1666
+ `DROP INDEX IF EXISTS idx_schedules_project`,
1667
+ `CREATE UNIQUE INDEX IF NOT EXISTS idx_schedules_project_kind ON schedules(project_id, kind)`
1668
+ ]
1669
+ },
1670
+ {
1671
+ version: 54,
1672
+ name: "drop-resurrected-schedules-project-index",
1673
+ // v53 dropped `idx_schedules_project`, but `MIGRATION_SQL` (which runs on
1674
+ // every boot, before versioned migrations) was still creating it. On any
1675
+ // boot AFTER the one that applied v53, Phase 1 re-created the legacy
1676
+ // single-column UNIQUE index, which then collided with the new
1677
+ // (project_id, kind) semantics and broke traffic-sync schedule creation
1678
+ // (`UNIQUE constraint failed: schedules.project_id`). MIGRATION_SQL no
1679
+ // longer creates that index; this migration removes it from any DB that
1680
+ // already booted past v53 with the resurrected index.
1681
+ statements: [
1682
+ `DROP INDEX IF EXISTS idx_schedules_project`
1683
+ ]
1614
1684
  }
1615
1685
  ];
1616
1686
  function isDuplicateColumnError(err) {
@@ -11,10 +11,11 @@ import {
11
11
  queryBatchRequestSchema,
12
12
  queryGenerateRequestSchema,
13
13
  runTriggerRequestSchema,
14
+ schedulableRunKindSchema,
14
15
  scheduleUpsertRequestSchema,
15
16
  trafficConnectCloudRunRequestSchema,
16
17
  trafficEventKindSchema
17
- } from "./chunk-ONI3TX2A.js";
18
+ } from "./chunk-SBZTDECX.js";
18
19
 
19
20
  // src/config.ts
20
21
  import fs from "fs";
@@ -547,11 +548,13 @@ var ApiClient = class {
547
548
  async putSchedule(project, body) {
548
549
  return this.request("PUT", `/projects/${encodeURIComponent(project)}/schedule`, body);
549
550
  }
550
- async getSchedule(project) {
551
- return this.request("GET", `/projects/${encodeURIComponent(project)}/schedule`);
551
+ async getSchedule(project, kind) {
552
+ const qs = kind ? `?kind=${encodeURIComponent(kind)}` : "";
553
+ return this.request("GET", `/projects/${encodeURIComponent(project)}/schedule${qs}`);
552
554
  }
553
- async deleteSchedule(project) {
554
- await this.request("DELETE", `/projects/${encodeURIComponent(project)}/schedule`);
555
+ async deleteSchedule(project, kind) {
556
+ const qs = kind ? `?kind=${encodeURIComponent(kind)}` : "";
557
+ await this.request("DELETE", `/projects/${encodeURIComponent(project)}/schedule${qs}`);
555
558
  }
556
559
  async createNotification(project, body) {
557
560
  return this.request("POST", `/projects/${encodeURIComponent(project)}/notifications`, body);
@@ -1147,6 +1150,10 @@ var scheduleSetInputSchema = z2.object({
1147
1150
  project: projectNameSchema,
1148
1151
  schedule: scheduleUpsertRequestSchema
1149
1152
  });
1153
+ var scheduleReadInputSchema = z2.object({
1154
+ project: projectNameSchema,
1155
+ kind: schedulableRunKindSchema.optional().describe('Schedulable run kind. Defaults to "answer-visibility" if omitted.')
1156
+ });
1150
1157
  var agentWebhookAttachInputSchema = z2.object({
1151
1158
  project: projectNameSchema,
1152
1159
  url: z2.string().url()
@@ -1498,13 +1505,13 @@ var canonryMcpTools = [
1498
1505
  defineTool({
1499
1506
  name: "canonry_schedule_get",
1500
1507
  title: "Get schedule",
1501
- description: "Get the scheduled run configuration for a Canonry project.",
1508
+ description: 'Get the scheduled run configuration for a Canonry project. Pass `kind` to read a non-default schedule (e.g. "traffic-sync"); defaults to "answer-visibility".',
1502
1509
  access: "read",
1503
1510
  tier: "setup",
1504
- inputSchema: projectInputSchema,
1511
+ inputSchema: scheduleReadInputSchema,
1505
1512
  annotations: readAnnotations(),
1506
1513
  openApiOperations: ["GET /api/v1/projects/{name}/schedule"],
1507
- handler: (client, input) => client.getSchedule(input.project)
1514
+ handler: (client, input) => client.getSchedule(input.project, input.kind)
1508
1515
  }),
1509
1516
  defineTool({
1510
1517
  name: "canonry_backlinks_latest_release",
@@ -1966,14 +1973,14 @@ var canonryMcpTools = [
1966
1973
  defineTool({
1967
1974
  name: "canonry_schedule_delete",
1968
1975
  title: "Delete schedule",
1969
- description: "Delete the scheduled run configuration for a Canonry project.",
1976
+ description: 'Delete the scheduled run configuration for a Canonry project. Pass `kind` to delete a non-default schedule (e.g. "traffic-sync"); defaults to "answer-visibility".',
1970
1977
  access: "write",
1971
1978
  tier: "setup",
1972
- inputSchema: projectInputSchema,
1979
+ inputSchema: scheduleReadInputSchema,
1973
1980
  annotations: writeAnnotations({ idempotentHint: false, destructiveHint: true }),
1974
1981
  openApiOperations: ["DELETE /api/v1/projects/{name}/schedule"],
1975
1982
  handler: async (client, input) => {
1976
- await client.deleteSchedule(input.project);
1983
+ await client.deleteSchedule(input.project, input.kind);
1977
1984
  }
1978
1985
  }),
1979
1986
  defineTool({
@@ -1022,25 +1022,35 @@ var snapshotReportSchema = z9.object({
1022
1022
 
1023
1023
  // ../contracts/src/schedule.ts
1024
1024
  import { z as z10 } from "zod";
1025
+ var schedulableRunKindSchema = z10.enum(["answer-visibility", "traffic-sync"]);
1026
+ var SchedulableRunKinds = schedulableRunKindSchema.enum;
1025
1027
  var scheduleDtoSchema = z10.object({
1026
1028
  id: z10.string(),
1027
1029
  projectId: z10.string(),
1030
+ /** Run kind dispatched when this schedule fires. Defaults to 'answer-visibility' for legacy rows. */
1031
+ kind: schedulableRunKindSchema,
1028
1032
  cronExpr: z10.string(),
1029
1033
  preset: z10.string().nullable().optional(),
1030
1034
  timezone: z10.string().default("UTC"),
1031
1035
  enabled: z10.boolean().default(true),
1032
1036
  providers: z10.array(providerNameSchema).default([]),
1037
+ /** Traffic-source UUID for `kind === 'traffic-sync'` schedules. Null otherwise. */
1038
+ sourceId: z10.string().nullable().optional(),
1033
1039
  lastRunAt: z10.string().nullable().optional(),
1034
1040
  nextRunAt: z10.string().nullable().optional(),
1035
1041
  createdAt: z10.string(),
1036
1042
  updatedAt: z10.string()
1037
1043
  });
1038
1044
  var scheduleUpsertRequestSchema = z10.object({
1045
+ /** Run kind. Defaults to 'answer-visibility' so existing callers don't have to change. */
1046
+ kind: schedulableRunKindSchema.optional(),
1039
1047
  preset: z10.string().optional(),
1040
1048
  cron: z10.string().optional(),
1041
1049
  timezone: z10.string().optional().default("UTC"),
1042
1050
  enabled: z10.boolean().optional().default(true),
1043
- providers: z10.array(providerNameSchema).optional().default([])
1051
+ providers: z10.array(providerNameSchema).optional().default([]),
1052
+ /** Required when kind === 'traffic-sync'. Forbidden for other kinds. Validated server-side. */
1053
+ sourceId: z10.string().optional()
1044
1054
  }).refine(
1045
1055
  (data) => data.preset && !data.cron || !data.preset && data.cron,
1046
1056
  { message: 'Exactly one of "preset" or "cron" must be provided' }
@@ -2209,6 +2219,8 @@ var trafficSourceStatusSchema = z20.enum(["connected", "paused", "error", "archi
2209
2219
  var TrafficSourceStatuses = trafficSourceStatusSchema.enum;
2210
2220
  var trafficSourceAuthModeSchema = z20.enum(["oauth", "service-account"]);
2211
2221
  var TrafficSourceAuthModes = trafficSourceAuthModeSchema.enum;
2222
+ var verificationStatusSchema = z20.enum(["verified", "claimed_unverified", "unknown_ai_like"]);
2223
+ var VerificationStatuses = verificationStatusSchema.enum;
2212
2224
  var cloudRunSourceConfigSchema = z20.object({
2213
2225
  gcpProjectId: z20.string().min(1),
2214
2226
  serviceName: z20.string().nullable().optional(),
@@ -2352,6 +2364,22 @@ function formatDateRange(start, end) {
2352
2364
  if (start && end) return `${formatDate(start)} \u2192 ${formatDate(end)}`;
2353
2365
  return formatDate(start || end);
2354
2366
  }
2367
+ function deltaPercent(current, prior) {
2368
+ if (prior <= 0) return null;
2369
+ return Math.round((current - prior) / prior * 100);
2370
+ }
2371
+ function deltaTone(deltaPct) {
2372
+ if (deltaPct === null || deltaPct === 0) return "neutral";
2373
+ return deltaPct > 0 ? "positive" : "negative";
2374
+ }
2375
+ function formatDeltaCopy(d, suffix, windowLabel = "vs prior 7 days") {
2376
+ if (d.deltaPct === null) {
2377
+ return d.prior === 0 ? "First baseline week" : "";
2378
+ }
2379
+ if (d.deltaPct > 0) return `Up ${d.deltaPct}% ${windowLabel} (${formatNumber(d.prior)} ${suffix})`;
2380
+ if (d.deltaPct < 0) return `Down ${Math.abs(d.deltaPct)}% ${windowLabel} (${formatNumber(d.prior)} ${suffix})`;
2381
+ return `Flat ${windowLabel} (${formatNumber(d.prior)} ${suffix})`;
2382
+ }
2355
2383
 
2356
2384
  export {
2357
2385
  __export,
@@ -2406,6 +2434,8 @@ export {
2406
2434
  formatRunErrorOneLine,
2407
2435
  snapshotRequestSchema,
2408
2436
  resolveSnapshotRequestQueries,
2437
+ schedulableRunKindSchema,
2438
+ SchedulableRunKinds,
2409
2439
  scheduleUpsertRequestSchema,
2410
2440
  parseWindow,
2411
2441
  windowCutoff,
@@ -2448,6 +2478,7 @@ export {
2448
2478
  TrafficEventConfidences,
2449
2479
  TrafficSourceStatuses,
2450
2480
  TrafficSourceAuthModes,
2481
+ VerificationStatuses,
2451
2482
  trafficConnectCloudRunRequestSchema,
2452
2483
  trafficEventKindSchema,
2453
2484
  TrafficEventKinds,
@@ -2455,5 +2486,8 @@ export {
2455
2486
  formatNumber,
2456
2487
  formatDate,
2457
2488
  formatIsoDate,
2458
- formatDateRange
2489
+ formatDateRange,
2490
+ deltaPercent,
2491
+ deltaTone,
2492
+ formatDeltaCopy
2459
2493
  };
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  setTelemetrySource,
21
21
  showFirstRunNotice,
22
22
  trackEvent
23
- } from "./chunk-IVNWS2YU.js";
23
+ } from "./chunk-7VDM3JBI.js";
24
24
  import {
25
25
  CliError,
26
26
  EXIT_SYSTEM_ERROR,
@@ -36,7 +36,7 @@ import {
36
36
  saveConfig,
37
37
  saveConfigPatch,
38
38
  usageError
39
- } from "./chunk-7SRKUAZO.js";
39
+ } from "./chunk-P3SFTXHG.js";
40
40
  import {
41
41
  apiKeys,
42
42
  competitors,
@@ -49,7 +49,7 @@ import {
49
49
  queries,
50
50
  querySnapshots,
51
51
  runs
52
- } from "./chunk-MI33SQL6.js";
52
+ } from "./chunk-BN2VQDZ2.js";
53
53
  import {
54
54
  CcReleaseSyncStatuses,
55
55
  CheckScopes,
@@ -69,7 +69,7 @@ import {
69
69
  providerQuotaPolicySchema,
70
70
  resolveProviderInput,
71
71
  skillsClientSchema
72
- } from "./chunk-ONI3TX2A.js";
72
+ } from "./chunk-SBZTDECX.js";
73
73
 
74
74
  // src/cli.ts
75
75
  import { pathToFileURL } from "url";
@@ -621,7 +621,7 @@ function readStoredGroundingSources(rawResponse) {
621
621
  return result;
622
622
  }
623
623
  async function backfillInsightsCommand(project, opts) {
624
- const { IntelligenceService } = await import("./intelligence-service-JYV3CO4H.js");
624
+ const { IntelligenceService } = await import("./intelligence-service-6CX5HH27.js");
625
625
  const config = loadConfig();
626
626
  const db = createClient(config.database);
627
627
  migrate(db);
@@ -6260,6 +6260,8 @@ function getClient17() {
6260
6260
  async function setSchedule(project, opts) {
6261
6261
  const client = getClient17();
6262
6262
  const body = {};
6263
+ if (opts.kind) body.kind = opts.kind;
6264
+ if (opts.sourceId) body.sourceId = opts.sourceId;
6263
6265
  if (opts.preset) body.preset = opts.preset;
6264
6266
  if (opts.cron) body.cron = opts.cron;
6265
6267
  if (opts.timezone) body.timezone = opts.timezone;
@@ -6269,61 +6271,68 @@ async function setSchedule(project, opts) {
6269
6271
  console.log(JSON.stringify(result, null, 2));
6270
6272
  return;
6271
6273
  }
6272
- console.log(`Schedule set for "${project}":`);
6274
+ console.log(`Schedule set for "${project}" (kind: ${result.kind}):`);
6273
6275
  printSchedule(result);
6274
6276
  }
6275
- async function showSchedule(project, format) {
6277
+ async function showSchedule(project, format, kind) {
6276
6278
  const client = getClient17();
6277
- const result = await client.getSchedule(project);
6279
+ const result = await client.getSchedule(project, kind);
6278
6280
  if (format === "json") {
6279
6281
  console.log(JSON.stringify(result, null, 2));
6280
6282
  return;
6281
6283
  }
6282
6284
  printSchedule(result);
6283
6285
  }
6284
- async function enableSchedule(project, format) {
6286
+ async function enableSchedule(project, format, kind) {
6285
6287
  const client = getClient17();
6286
- const current = await client.getSchedule(project);
6287
- const body = { timezone: current.timezone, enabled: true };
6288
+ const current = await client.getSchedule(project, kind);
6289
+ const body = { kind: current.kind, timezone: current.timezone, enabled: true };
6288
6290
  if (current.preset) body.preset = current.preset;
6289
6291
  else body.cron = current.cronExpr;
6290
6292
  if (current.providers.length) body.providers = current.providers;
6293
+ if (current.sourceId) body.sourceId = current.sourceId;
6291
6294
  const result = await client.putSchedule(project, body);
6292
6295
  if (format === "json") {
6293
6296
  console.log(JSON.stringify(result, null, 2));
6294
6297
  return;
6295
6298
  }
6296
- console.log(`Schedule enabled for "${project}"`);
6299
+ console.log(`Schedule enabled for "${project}" (kind: ${result.kind})`);
6297
6300
  }
6298
- async function disableSchedule(project, format) {
6301
+ async function disableSchedule(project, format, kind) {
6299
6302
  const client = getClient17();
6300
- const current = await client.getSchedule(project);
6301
- const body = { timezone: current.timezone, enabled: false };
6303
+ const current = await client.getSchedule(project, kind);
6304
+ const body = { kind: current.kind, timezone: current.timezone, enabled: false };
6302
6305
  if (current.preset) body.preset = current.preset;
6303
6306
  else body.cron = current.cronExpr;
6304
6307
  if (current.providers.length) body.providers = current.providers;
6308
+ if (current.sourceId) body.sourceId = current.sourceId;
6305
6309
  const result = await client.putSchedule(project, body);
6306
6310
  if (format === "json") {
6307
6311
  console.log(JSON.stringify(result, null, 2));
6308
6312
  return;
6309
6313
  }
6310
- console.log(`Schedule disabled for "${project}"`);
6314
+ console.log(`Schedule disabled for "${project}" (kind: ${result.kind})`);
6311
6315
  }
6312
- async function removeSchedule(project, format) {
6316
+ async function removeSchedule(project, format, kind) {
6313
6317
  const client = getClient17();
6314
- await client.deleteSchedule(project);
6318
+ await client.deleteSchedule(project, kind);
6319
+ const resolvedKind = kind ?? "answer-visibility";
6315
6320
  if (format === "json") {
6316
- console.log(JSON.stringify({ project, removed: true }, null, 2));
6321
+ console.log(JSON.stringify({ project, kind: resolvedKind, removed: true }, null, 2));
6317
6322
  return;
6318
6323
  }
6319
- console.log(`Schedule removed for "${project}"`);
6324
+ console.log(`Schedule removed for "${project}" (kind: ${resolvedKind})`);
6320
6325
  }
6321
6326
  function printSchedule(s) {
6322
6327
  const label = s.preset ?? s.cronExpr;
6328
+ console.log(` Kind: ${s.kind}`);
6323
6329
  console.log(` Schedule: ${label}`);
6324
6330
  console.log(` Cron: ${s.cronExpr}`);
6325
6331
  console.log(` Timezone: ${s.timezone}`);
6326
6332
  console.log(` Enabled: ${s.enabled ? "yes" : "no"}`);
6333
+ if (s.kind === "traffic-sync" && s.sourceId) {
6334
+ console.log(` Source: ${s.sourceId}`);
6335
+ }
6327
6336
  if (s.providers.length) {
6328
6337
  console.log(` Providers: ${s.providers.join(", ")}`);
6329
6338
  }
@@ -6339,30 +6348,31 @@ function printSchedule(s) {
6339
6348
  var SCHEDULE_CLI_COMMANDS = [
6340
6349
  {
6341
6350
  path: ["schedule", "set"],
6342
- usage: "canonry schedule set <project> (--preset <preset> | --cron <expr>) [--timezone <tz>] [--provider <name>...] [--format json]",
6351
+ usage: "canonry schedule set <project> (--preset <preset> | --cron <expr>) [--kind answer-visibility|traffic-sync] [--source <id>] [--timezone <tz>] [--provider <name>...] [--format json]",
6343
6352
  options: {
6344
6353
  preset: stringOption(),
6345
6354
  cron: stringOption(),
6355
+ kind: stringOption(),
6356
+ source: stringOption(),
6346
6357
  timezone: stringOption(),
6347
6358
  provider: multiStringOption()
6348
6359
  },
6349
6360
  run: async (input) => {
6350
- const project = requireProject(
6351
- input,
6352
- "schedule.set",
6353
- "canonry schedule set <project> (--preset <preset> | --cron <expr>) [--timezone <tz>] [--provider <name>...] [--format json]"
6354
- );
6361
+ const usage = "canonry schedule set <project> (--preset <preset> | --cron <expr>) [--kind answer-visibility|traffic-sync] [--source <id>] [--timezone <tz>] [--provider <name>...] [--format json]";
6362
+ const project = requireProject(input, "schedule.set", usage);
6355
6363
  if (!getString(input.values, "preset") && !getString(input.values, "cron")) {
6356
6364
  throw usageError("Error: --preset or --cron is required", {
6357
6365
  message: "schedule preset or cron is required",
6358
6366
  details: {
6359
6367
  command: "schedule.set",
6360
- usage: "canonry schedule set <project> (--preset <preset> | --cron <expr>) [--timezone <tz>] [--provider <name>...] [--format json]",
6368
+ usage,
6361
6369
  required: ["preset | cron"]
6362
6370
  }
6363
6371
  });
6364
6372
  }
6365
6373
  await setSchedule(project, {
6374
+ kind: getString(input.values, "kind"),
6375
+ sourceId: getString(input.values, "source"),
6366
6376
  preset: getString(input.values, "preset"),
6367
6377
  cron: getString(input.values, "cron"),
6368
6378
  timezone: getString(input.values, "timezone"),
@@ -6373,34 +6383,38 @@ var SCHEDULE_CLI_COMMANDS = [
6373
6383
  },
6374
6384
  {
6375
6385
  path: ["schedule", "show"],
6376
- usage: "canonry schedule show <project> [--format json]",
6386
+ usage: "canonry schedule show <project> [--kind answer-visibility|traffic-sync] [--format json]",
6387
+ options: { kind: stringOption() },
6377
6388
  run: async (input) => {
6378
- const project = requireProject(input, "schedule.show", "canonry schedule show <project> [--format json]");
6379
- await showSchedule(project, input.format);
6389
+ const project = requireProject(input, "schedule.show", "canonry schedule show <project> [--kind ...]");
6390
+ await showSchedule(project, input.format, getString(input.values, "kind"));
6380
6391
  }
6381
6392
  },
6382
6393
  {
6383
6394
  path: ["schedule", "enable"],
6384
- usage: "canonry schedule enable <project> [--format json]",
6395
+ usage: "canonry schedule enable <project> [--kind answer-visibility|traffic-sync] [--format json]",
6396
+ options: { kind: stringOption() },
6385
6397
  run: async (input) => {
6386
- const project = requireProject(input, "schedule.enable", "canonry schedule enable <project> [--format json]");
6387
- await enableSchedule(project, input.format);
6398
+ const project = requireProject(input, "schedule.enable", "canonry schedule enable <project> [--kind ...]");
6399
+ await enableSchedule(project, input.format, getString(input.values, "kind"));
6388
6400
  }
6389
6401
  },
6390
6402
  {
6391
6403
  path: ["schedule", "disable"],
6392
- usage: "canonry schedule disable <project> [--format json]",
6404
+ usage: "canonry schedule disable <project> [--kind answer-visibility|traffic-sync] [--format json]",
6405
+ options: { kind: stringOption() },
6393
6406
  run: async (input) => {
6394
- const project = requireProject(input, "schedule.disable", "canonry schedule disable <project> [--format json]");
6395
- await disableSchedule(project, input.format);
6407
+ const project = requireProject(input, "schedule.disable", "canonry schedule disable <project> [--kind ...]");
6408
+ await disableSchedule(project, input.format, getString(input.values, "kind"));
6396
6409
  }
6397
6410
  },
6398
6411
  {
6399
6412
  path: ["schedule", "remove"],
6400
- usage: "canonry schedule remove <project> [--format json]",
6413
+ usage: "canonry schedule remove <project> [--kind answer-visibility|traffic-sync] [--format json]",
6414
+ options: { kind: stringOption() },
6401
6415
  run: async (input) => {
6402
- const project = requireProject(input, "schedule.remove", "canonry schedule remove <project> [--format json]");
6403
- await removeSchedule(project, input.format);
6416
+ const project = requireProject(input, "schedule.remove", "canonry schedule remove <project> [--kind ...]");
6417
+ await removeSchedule(project, input.format, getString(input.values, "kind"));
6404
6418
  }
6405
6419
  },
6406
6420
  {
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-IVNWS2YU.js";
3
+ } from "./chunk-7VDM3JBI.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-7SRKUAZO.js";
7
- import "./chunk-MI33SQL6.js";
8
- import "./chunk-ONI3TX2A.js";
6
+ } from "./chunk-P3SFTXHG.js";
7
+ import "./chunk-BN2VQDZ2.js";
8
+ import "./chunk-SBZTDECX.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-MI33SQL6.js";
4
- import "./chunk-ONI3TX2A.js";
3
+ } from "./chunk-BN2VQDZ2.js";
4
+ import "./chunk-SBZTDECX.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  CliError,
3
3
  canonryMcpTools,
4
4
  createApiClient
5
- } from "./chunk-7SRKUAZO.js";
6
- import "./chunk-ONI3TX2A.js";
5
+ } from "./chunk-P3SFTXHG.js";
6
+ import "./chunk-SBZTDECX.js";
7
7
 
8
8
  // src/mcp/cli.ts
9
9
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainyc/canonry",
3
- "version": "4.15.2",
3
+ "version": "4.18.1",
4
4
  "type": "module",
5
5
  "description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
6
6
  "license": "FSL-1.1-ALv2",
@@ -59,23 +59,23 @@
59
59
  "@types/node-cron": "^3.0.11",
60
60
  "tsup": "^8.5.1",
61
61
  "tsx": "^4.19.0",
62
- "@ainyc/canonry-api-routes": "0.0.0",
63
62
  "@ainyc/canonry-config": "0.0.0",
64
- "@ainyc/canonry-intelligence": "0.0.0",
65
63
  "@ainyc/canonry-db": "0.0.0",
66
- "@ainyc/canonry-contracts": "0.0.0",
67
- "@ainyc/canonry-integration-cloud-run": "0.0.0",
64
+ "@ainyc/canonry-intelligence": "0.0.0",
65
+ "@ainyc/canonry-integration-bing": "0.0.0",
66
+ "@ainyc/canonry-api-routes": "0.0.0",
68
67
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
68
+ "@ainyc/canonry-integration-cloud-run": "0.0.0",
69
+ "@ainyc/canonry-contracts": "0.0.0",
69
70
  "@ainyc/canonry-integration-google": "0.0.0",
71
+ "@ainyc/canonry-integration-traffic": "0.0.0",
70
72
  "@ainyc/canonry-integration-wordpress": "0.0.0",
71
73
  "@ainyc/canonry-provider-cdp": "0.0.0",
72
- "@ainyc/canonry-integration-traffic": "0.0.0",
73
74
  "@ainyc/canonry-provider-claude": "0.0.0",
74
- "@ainyc/canonry-integration-bing": "0.0.0",
75
- "@ainyc/canonry-provider-openai": "0.0.0",
76
- "@ainyc/canonry-provider-local": "0.0.0",
77
75
  "@ainyc/canonry-provider-gemini": "0.0.0",
78
- "@ainyc/canonry-provider-perplexity": "0.0.0"
76
+ "@ainyc/canonry-provider-local": "0.0.0",
77
+ "@ainyc/canonry-provider-perplexity": "0.0.0",
78
+ "@ainyc/canonry-provider-openai": "0.0.0"
79
79
  },
80
80
  "scripts": {
81
81
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",