@canonry/canonry 7.63.0 → 7.63.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.
- package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +10 -0
- package/dist/{backfill-HZU3BBOH.js → backfill-2BVFKQ6J.js} +2 -2
- package/dist/{chunk-Q4U2GJME.js → chunk-22ABGRB7.js} +112 -43
- package/dist/{chunk-I5QSS3CY.js → chunk-32KNDPD3.js} +14 -14
- package/dist/{chunk-TDWNONBU.js → chunk-5GMYD7UZ.js} +1 -1
- package/dist/{chunk-XWDCLX55.js → chunk-6ABOEN5D.js} +2 -2
- package/dist/{chunk-DBA374EM.js → chunk-AGSQWIE4.js} +9 -5
- package/dist/{chunk-W5TIRS4U.js → chunk-IRRONWF7.js} +1 -1
- package/dist/{chunk-QPTSZDHE.js → chunk-JM6OFCLX.js} +1 -1
- package/dist/{chunk-WYTRXYUR.js → chunk-V3QMOGZE.js} +1 -1
- package/dist/{cli-commands-6LZ5OIIP.js → cli-commands-ONFE63OB.js} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{dashboard-XJJ6NZ2L.js → dashboard-BC4NKAO2.js} +1 -1
- package/dist/{demo-X7LQ24GS.js → demo-ZRFZ5EBH.js} +1 -1
- package/dist/{demo-server-MBPBTJXG.js → demo-server-7R7NGWJA.js} +2 -2
- package/dist/index.d.ts +63 -63
- package/dist/index.js +5 -5
- package/dist/{init-JRGRHLYU.js → init-TU4VSGVU.js} +1 -1
- package/dist/{intelligence-service-7LCTJQDL.js → intelligence-service-MWTHUE7S.js} +2 -2
- package/dist/{serve-FTAFEEJD.js → serve-VIEGFGSK.js} +6 -6
- package/dist/{session-E4V5MRUE.js → session-JLH72BF5.js} +3 -3
- package/dist/{tools-XKGEC56T.js → tools-YOV2KHF2.js} +2 -2
- package/package.json +1 -1
|
@@ -295,6 +295,16 @@ Run `cnry traffic backfill <project> --source <id> --days N` (capped at
|
|
|
295
295
|
history. It's an explicit operator action; the connect flow never pulls
|
|
296
296
|
it implicitly.
|
|
297
297
|
|
|
298
|
+
A backfill holds the source's sync lease until it finishes, however long the
|
|
299
|
+
pull takes. Scheduled syncs for that source skip while it runs and resume
|
|
300
|
+
from the same watermark afterwards, so nothing commits into the window the
|
|
301
|
+
backfill replaces. A backfill requested while a sync is running returns
|
|
302
|
+
`OPERATION_IN_PROGRESS`; retry when that sync ends. A reset, reconnect or
|
|
303
|
+
deactivation during a backfill stops it within a minute: it releases the
|
|
304
|
+
source, stops pulling, and fails without writing. The CLI stops waiting
|
|
305
|
+
after 5 minutes, but the run continues on the server: follow it with
|
|
306
|
+
`cnry runs <project> --kind traffic-sync`.
|
|
307
|
+
|
|
298
308
|
## Connecting a Cloudflare source
|
|
299
309
|
|
|
300
310
|
Both Cloudflare modes run the same small ES-module Worker on the site's exact
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
backfillSnapshotAttributionCommand,
|
|
11
11
|
backfillTrafficClassificationCommand,
|
|
12
12
|
replayQueryAuditLog
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-6ABOEN5D.js";
|
|
14
14
|
import "./chunk-UYPBR3SF.js";
|
|
15
15
|
import "./chunk-A57HYHJ3.js";
|
|
16
16
|
import "./chunk-HGMYEDAQ.js";
|
|
@@ -18,7 +18,7 @@ import "./chunk-EHTSCLEL.js";
|
|
|
18
18
|
import {
|
|
19
19
|
backfillProjectAnswerMentions,
|
|
20
20
|
backfillProjectAnswerMentionsInChunks
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-22ABGRB7.js";
|
|
22
22
|
import "./chunk-SG2OPR7J.js";
|
|
23
23
|
import "./chunk-QNFX7ZCT.js";
|
|
24
24
|
import "./chunk-HNZQVIPS.js";
|
|
@@ -62187,6 +62187,9 @@ var CLOUDFLARE_QUEUE_RETENTION_READ_TIMEOUT_MS = 1e4;
|
|
|
62187
62187
|
var CLOUDFLARE_QUEUE_VISIBILITY_TIMEOUT_MS = 5 * 6e4;
|
|
62188
62188
|
var CLOUDFLARE_QUEUE_SYNC_LEASE_TTL_MS = 5 * 6e4;
|
|
62189
62189
|
var WORDPRESS_SYNC_LEASE_TTL_MS = 5 * 6e4;
|
|
62190
|
+
var PULL_SYNC_LEASE_TTL_MS = 10 * 6e4;
|
|
62191
|
+
var TRAFFIC_BACKFILL_LEASE_TTL_MS = 5 * 6e4;
|
|
62192
|
+
var TRAFFIC_BACKFILL_LEASE_RENEW_MS = 6e4;
|
|
62190
62193
|
var DEFAULT_CLOUDFLARE_INGEST_RATE_LIMIT_MAX = 6e3;
|
|
62191
62194
|
var SHA256_HEX_PATTERN = /^[0-9a-f]{64}$/i;
|
|
62192
62195
|
function sha256Hex3(value) {
|
|
@@ -62533,6 +62536,9 @@ function isAuthoritativeTrafficSource(db, source) {
|
|
|
62533
62536
|
function trafficConnectStatus(tx, projectId, existingSource) {
|
|
62534
62537
|
return existingSource?.status === TrafficSourceStatuses.paused || hasConnectedTrafficSourceSibling(tx, projectId, existingSource?.id ?? "") ? TrafficSourceStatuses.paused : TrafficSourceStatuses.connected;
|
|
62535
62538
|
}
|
|
62539
|
+
function isSameBackfillSource(current, started, leaseOwner) {
|
|
62540
|
+
return current.syncLeaseOwner === leaseOwner && isSameTrafficSourceGeneration(current, started);
|
|
62541
|
+
}
|
|
62536
62542
|
function isSameTrafficSourceGeneration(current, started) {
|
|
62537
62543
|
return isDeepStrictEqual(current.configJson, started.configJson) && current.updatedAt === started.updatedAt && current.lastSyncedAt === started.lastSyncedAt && current.lastCursor === started.lastCursor && current.wordpressPendingUntil === started.wordpressPendingUntil;
|
|
62538
62544
|
}
|
|
@@ -62586,6 +62592,42 @@ function vercelRetentionClampError(requestedStartMs, effectiveStartMs) {
|
|
|
62586
62592
|
return new VercelRetentionClampError(requestedStartMs, effectiveStartMs);
|
|
62587
62593
|
}
|
|
62588
62594
|
async function runBackfillTask(options) {
|
|
62595
|
+
const { app, sourceRow: sourceRow2, leaseOwner } = options;
|
|
62596
|
+
const stopped = new AbortController();
|
|
62597
|
+
const releaseLease = () => {
|
|
62598
|
+
try {
|
|
62599
|
+
releaseTrafficSyncLease({ db: app.db, sourceId: sourceRow2.id, owner: leaseOwner, now: (/* @__PURE__ */ new Date()).toISOString() });
|
|
62600
|
+
} catch {
|
|
62601
|
+
}
|
|
62602
|
+
};
|
|
62603
|
+
const renewLease2 = setInterval(() => {
|
|
62604
|
+
try {
|
|
62605
|
+
const latest = app.db.select().from(trafficSources).where(eq80(trafficSources.id, sourceRow2.id)).get();
|
|
62606
|
+
if (!latest || !isAuthoritativeTrafficSource(app.db, latest) || !isSameTrafficSourceGeneration(latest, sourceRow2)) {
|
|
62607
|
+
clearInterval(renewLease2);
|
|
62608
|
+
stopped.abort();
|
|
62609
|
+
releaseLease();
|
|
62610
|
+
return;
|
|
62611
|
+
}
|
|
62612
|
+
tryClaimTrafficSyncLease({
|
|
62613
|
+
db: app.db,
|
|
62614
|
+
sourceId: sourceRow2.id,
|
|
62615
|
+
owner: leaseOwner,
|
|
62616
|
+
now: (/* @__PURE__ */ new Date()).toISOString(),
|
|
62617
|
+
ttlMs: TRAFFIC_BACKFILL_LEASE_TTL_MS
|
|
62618
|
+
});
|
|
62619
|
+
} catch {
|
|
62620
|
+
}
|
|
62621
|
+
}, options.leaseRenewMs);
|
|
62622
|
+
renewLease2.unref?.();
|
|
62623
|
+
try {
|
|
62624
|
+
await runBackfillTaskHoldingLease(options, stopped.signal);
|
|
62625
|
+
} finally {
|
|
62626
|
+
clearInterval(renewLease2);
|
|
62627
|
+
releaseLease();
|
|
62628
|
+
}
|
|
62629
|
+
}
|
|
62630
|
+
async function runBackfillTaskHoldingLease(options, signal) {
|
|
62589
62631
|
const {
|
|
62590
62632
|
app,
|
|
62591
62633
|
runId,
|
|
@@ -62595,7 +62637,8 @@ async function runBackfillTask(options) {
|
|
|
62595
62637
|
windowEnd,
|
|
62596
62638
|
journeyKeySecret,
|
|
62597
62639
|
pullForBackfill,
|
|
62598
|
-
pullErrorPrefix
|
|
62640
|
+
pullErrorPrefix,
|
|
62641
|
+
leaseOwner
|
|
62599
62642
|
} = options;
|
|
62600
62643
|
const backfillStartedAt = Date.now();
|
|
62601
62644
|
const target = { feature: "server_traffic", operation: "backfill", attribution: currentOutcomeAttribution() };
|
|
@@ -62609,7 +62652,7 @@ async function runBackfillTask(options) {
|
|
|
62609
62652
|
app.db.transaction((tx) => {
|
|
62610
62653
|
tx.update(runs).set({ status: RunStatuses.failed, error: msg, finishedAt: failedAt }).where(eq80(runs.id, runId)).run();
|
|
62611
62654
|
const latestSource = tx.select().from(trafficSources).where(eq80(trafficSources.id, sourceRow2.id)).get();
|
|
62612
|
-
if (!preserveSourceState && latestSource && isAuthoritativeTrafficSource(tx, latestSource) &&
|
|
62655
|
+
if (!preserveSourceState && latestSource && isAuthoritativeTrafficSource(tx, latestSource) && isSameBackfillSource(latestSource, sourceRow2, leaseOwner)) {
|
|
62613
62656
|
tx.update(trafficSources).set({ status: TrafficSourceStatuses.error, lastError: msg, updatedAt: failedAt }).where(eq80(trafficSources.id, sourceRow2.id)).run();
|
|
62614
62657
|
}
|
|
62615
62658
|
});
|
|
@@ -62623,8 +62666,13 @@ async function runBackfillTask(options) {
|
|
|
62623
62666
|
}
|
|
62624
62667
|
let allEvents;
|
|
62625
62668
|
try {
|
|
62626
|
-
allEvents = await pullForBackfill();
|
|
62669
|
+
allEvents = await pullForBackfill(signal);
|
|
62627
62670
|
} catch (e) {
|
|
62671
|
+
if (signal.aborted) {
|
|
62672
|
+
markFailed("Backfill stopped: the traffic source was reset, reconnected or deactivated while it ran", true);
|
|
62673
|
+
reportBackfill({ status: OutcomeStatuses.failed, reasonCode: OutcomeReasonCodes.NOT_CONNECTED });
|
|
62674
|
+
return;
|
|
62675
|
+
}
|
|
62628
62676
|
markFailed(
|
|
62629
62677
|
`${pullErrorPrefix}: ${describeError(e)}`,
|
|
62630
62678
|
e instanceof VercelRetentionClampError
|
|
@@ -62638,7 +62686,7 @@ async function runBackfillTask(options) {
|
|
|
62638
62686
|
try {
|
|
62639
62687
|
const completed = app.db.transaction((tx) => {
|
|
62640
62688
|
const latestSource = tx.select().from(trafficSources).where(eq80(trafficSources.id, sourceRow2.id)).get();
|
|
62641
|
-
const stillAuthoritative = latestSource && isAuthoritativeTrafficSource(tx, latestSource) &&
|
|
62689
|
+
const stillAuthoritative = latestSource && isAuthoritativeTrafficSource(tx, latestSource) && isSameBackfillSource(latestSource, sourceRow2, leaseOwner);
|
|
62642
62690
|
if (stillAuthoritative) {
|
|
62643
62691
|
enforceRawEventSampleRetention(tx, sourceRow2.id, finishedAt2);
|
|
62644
62692
|
}
|
|
@@ -62681,7 +62729,7 @@ async function runBackfillTask(options) {
|
|
|
62681
62729
|
}).where(eq80(runs.id, runId)).run();
|
|
62682
62730
|
return "wordpress-backfill-unsupported";
|
|
62683
62731
|
}
|
|
62684
|
-
if (!latestSource || !isAuthoritativeTrafficSource(tx, latestSource) || !
|
|
62732
|
+
if (!latestSource || !isAuthoritativeTrafficSource(tx, latestSource) || !isSameBackfillSource(latestSource, sourceRow2, leaseOwner)) {
|
|
62685
62733
|
tx.update(runs).set({
|
|
62686
62734
|
status: RunStatuses.failed,
|
|
62687
62735
|
error: "Traffic source was deactivated or reconfigured during backfill",
|
|
@@ -64205,15 +64253,19 @@ async function trafficRoutes(app, opts) {
|
|
|
64205
64253
|
if (sourceRow2.status === TrafficSourceStatuses.paused || sourceRow2.status === TrafficSourceStatuses.archived || hasConnectedSibling) {
|
|
64206
64254
|
throw validationError("Traffic source must be active before it can sync");
|
|
64207
64255
|
}
|
|
64208
|
-
const
|
|
64209
|
-
|
|
64256
|
+
const isWordpressSource = sourceRow2.sourceType === TrafficSourceTypes.wordpress;
|
|
64257
|
+
const syncLeaseOwner = crypto52.randomUUID();
|
|
64258
|
+
if (!tryClaimTrafficSyncLease({
|
|
64210
64259
|
db: app.db,
|
|
64211
64260
|
sourceId: sourceRow2.id,
|
|
64212
|
-
owner:
|
|
64261
|
+
owner: syncLeaseOwner,
|
|
64213
64262
|
now: (/* @__PURE__ */ new Date()).toISOString(),
|
|
64214
|
-
ttlMs: WORDPRESS_SYNC_LEASE_TTL_MS
|
|
64263
|
+
ttlMs: isWordpressSource ? WORDPRESS_SYNC_LEASE_TTL_MS : PULL_SYNC_LEASE_TTL_MS
|
|
64215
64264
|
})) {
|
|
64216
|
-
throw operationInProgress(
|
|
64265
|
+
throw operationInProgress(
|
|
64266
|
+
isWordpressSource ? "WordPress source sync is already in progress" : "A sync or backfill is already running for this traffic source",
|
|
64267
|
+
{ sourceId: sourceRow2.id }
|
|
64268
|
+
);
|
|
64217
64269
|
}
|
|
64218
64270
|
try {
|
|
64219
64271
|
const syncWindowEnd = /* @__PURE__ */ new Date();
|
|
@@ -64236,7 +64288,7 @@ async function trafficRoutes(app, opts) {
|
|
|
64236
64288
|
app.db.transaction((tx) => {
|
|
64237
64289
|
tx.update(runs).set({ status: RunStatuses.failed, error: msg, finishedAt: failedAt }).where(eq80(runs.id, runId)).run();
|
|
64238
64290
|
const latestSource = tx.select().from(trafficSources).where(eq80(trafficSources.id, sourceRow2.id)).get();
|
|
64239
|
-
if (latestSource?.status === TrafficSourceStatuses.connected && isSameTrafficSourceGeneration(latestSource, sourceRow2) &&
|
|
64291
|
+
if (latestSource?.status === TrafficSourceStatuses.connected && isSameTrafficSourceGeneration(latestSource, sourceRow2) && latestSource.syncLeaseOwner === syncLeaseOwner) {
|
|
64240
64292
|
tx.update(trafficSources).set({ status: TrafficSourceStatuses.error, lastError: msg, updatedAt: failedAt }).where(eq80(trafficSources.id, sourceRow2.id)).run();
|
|
64241
64293
|
}
|
|
64242
64294
|
});
|
|
@@ -64257,11 +64309,11 @@ async function trafficRoutes(app, opts) {
|
|
|
64257
64309
|
}
|
|
64258
64310
|
};
|
|
64259
64311
|
const renewWordpressLease = () => {
|
|
64260
|
-
if (!
|
|
64312
|
+
if (!isWordpressSource) return;
|
|
64261
64313
|
if (!tryClaimTrafficSyncLease({
|
|
64262
64314
|
db: app.db,
|
|
64263
64315
|
sourceId: sourceRow2.id,
|
|
64264
|
-
owner:
|
|
64316
|
+
owner: syncLeaseOwner,
|
|
64265
64317
|
now: (/* @__PURE__ */ new Date()).toISOString(),
|
|
64266
64318
|
ttlMs: WORDPRESS_SYNC_LEASE_TTL_MS
|
|
64267
64319
|
})) {
|
|
@@ -64366,7 +64418,7 @@ async function trafficRoutes(app, opts) {
|
|
|
64366
64418
|
const reservedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
64367
64419
|
const reservedSource = app.db.transaction((tx) => {
|
|
64368
64420
|
const latestSource = tx.select().from(trafficSources).where(eq80(trafficSources.id, sourceRow2.id)).get();
|
|
64369
|
-
if (!latestSource || !isAuthoritativeTrafficSource(tx, latestSource) || !isSameTrafficSourceGeneration(latestSource, sourceRow2) || latestSource.syncLeaseOwner !==
|
|
64421
|
+
if (!latestSource || !isAuthoritativeTrafficSource(tx, latestSource) || !isSameTrafficSourceGeneration(latestSource, sourceRow2) || latestSource.syncLeaseOwner !== syncLeaseOwner || latestSource.lastCursor || latestSource.wordpressPendingUntil) return void 0;
|
|
64370
64422
|
tx.update(trafficSources).set({
|
|
64371
64423
|
lastSyncedAt: windowStartIso2,
|
|
64372
64424
|
wordpressPendingUntil: windowEndIso2,
|
|
@@ -64550,7 +64602,7 @@ async function trafficRoutes(app, opts) {
|
|
|
64550
64602
|
const commitOutcome = app.db.transaction((tx) => {
|
|
64551
64603
|
const latestRow = tx.select().from(trafficSources).where(eq80(trafficSources.id, sourceRow2.id)).get();
|
|
64552
64604
|
const latestHasConnectedSibling = tx.select().from(trafficSources).where(eq80(trafficSources.projectId, project.id)).all().some((row) => row.id !== sourceRow2.id && row.status === TrafficSourceStatuses.connected);
|
|
64553
|
-
if (!latestRow || latestRow.status !== TrafficSourceStatuses.connected && latestRow.status !== TrafficSourceStatuses.error || latestHasConnectedSibling ||
|
|
64605
|
+
if (!latestRow || latestRow.status !== TrafficSourceStatuses.connected && latestRow.status !== TrafficSourceStatuses.error || latestHasConnectedSibling || latestRow.syncLeaseOwner !== syncLeaseOwner || !isSameTrafficSourceGeneration(latestRow, sourceRow2)) {
|
|
64554
64606
|
const abortedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
64555
64607
|
tx.update(runs).set({
|
|
64556
64608
|
status: RunStatuses.failed,
|
|
@@ -64880,17 +64932,15 @@ async function trafficRoutes(app, opts) {
|
|
|
64880
64932
|
};
|
|
64881
64933
|
return response;
|
|
64882
64934
|
} finally {
|
|
64883
|
-
|
|
64884
|
-
|
|
64885
|
-
|
|
64886
|
-
|
|
64887
|
-
|
|
64888
|
-
|
|
64889
|
-
|
|
64890
|
-
|
|
64891
|
-
|
|
64892
|
-
request.log.warn({ sourceId: sourceRow2.id, error: describeError(error) }, "Failed to release WordPress sync lease");
|
|
64893
|
-
}
|
|
64935
|
+
try {
|
|
64936
|
+
releaseTrafficSyncLease({
|
|
64937
|
+
db: app.db,
|
|
64938
|
+
sourceId: sourceRow2.id,
|
|
64939
|
+
owner: syncLeaseOwner,
|
|
64940
|
+
now: (/* @__PURE__ */ new Date()).toISOString()
|
|
64941
|
+
});
|
|
64942
|
+
} catch (error) {
|
|
64943
|
+
request.log.warn({ sourceId: sourceRow2.id, error: describeError(error) }, "Failed to release traffic sync lease");
|
|
64894
64944
|
}
|
|
64895
64945
|
}
|
|
64896
64946
|
});
|
|
@@ -64976,11 +65026,12 @@ async function trafficRoutes(app, opts) {
|
|
|
64976
65026
|
const vercelTeamId = config.teamId ?? credential.teamId;
|
|
64977
65027
|
const vercelEnvironment = config.environment ?? credential.environment;
|
|
64978
65028
|
pullErrorPrefix = "Vercel pull failed";
|
|
64979
|
-
pullForBackfill = async () => {
|
|
65029
|
+
pullForBackfill = async (signal) => {
|
|
64980
65030
|
const collected = [];
|
|
64981
65031
|
const seenEventIds = /* @__PURE__ */ new Set();
|
|
64982
65032
|
const backfillEndMs = windowEnd.getTime();
|
|
64983
65033
|
for (let chunkStartMs = windowStart.getTime(); chunkStartMs < backfillEndMs; chunkStartMs += VERCEL_BACKFILL_CHUNK_MS) {
|
|
65034
|
+
signal.throwIfAborted();
|
|
64984
65035
|
const chunkEndMs = Math.min(chunkStartMs + VERCEL_BACKFILL_CHUNK_MS, backfillEndMs);
|
|
64985
65036
|
const drained = await drainVercelTrafficEvents({
|
|
64986
65037
|
pull: pullVercelEvents,
|
|
@@ -65008,25 +65059,42 @@ async function trafficRoutes(app, opts) {
|
|
|
65008
65059
|
}
|
|
65009
65060
|
const startedAt = windowEnd.toISOString();
|
|
65010
65061
|
const runId = crypto52.randomUUID();
|
|
65011
|
-
|
|
65012
|
-
|
|
65013
|
-
|
|
65014
|
-
|
|
65015
|
-
|
|
65016
|
-
|
|
65017
|
-
|
|
65018
|
-
|
|
65019
|
-
|
|
65020
|
-
|
|
65021
|
-
|
|
65022
|
-
|
|
65023
|
-
|
|
65024
|
-
|
|
65025
|
-
|
|
65026
|
-
|
|
65062
|
+
const leaseOwner = crypto52.randomUUID();
|
|
65063
|
+
if (!tryClaimTrafficSyncLease({
|
|
65064
|
+
db: app.db,
|
|
65065
|
+
sourceId: sourceRow2.id,
|
|
65066
|
+
owner: leaseOwner,
|
|
65067
|
+
now: (/* @__PURE__ */ new Date()).toISOString(),
|
|
65068
|
+
ttlMs: TRAFFIC_BACKFILL_LEASE_TTL_MS
|
|
65069
|
+
})) {
|
|
65070
|
+
throw operationInProgress("A sync or backfill is already running for this traffic source; retry when it finishes", { sourceId: sourceRow2.id });
|
|
65071
|
+
}
|
|
65072
|
+
try {
|
|
65073
|
+
app.db.transaction((tx) => {
|
|
65074
|
+
const latestSource = tx.select().from(trafficSources).where(eq80(trafficSources.id, sourceRow2.id)).get();
|
|
65075
|
+
if (!latestSource || !isAuthoritativeTrafficSource(tx, latestSource) || !isSameTrafficSourceGeneration(latestSource, sourceRow2)) {
|
|
65076
|
+
throw validationError("Traffic source must remain active and unchanged before it can backfill");
|
|
65077
|
+
}
|
|
65078
|
+
tx.insert(runs).values({
|
|
65079
|
+
id: runId,
|
|
65080
|
+
projectId: project.id,
|
|
65081
|
+
kind: RunKinds["traffic-sync"],
|
|
65082
|
+
status: RunStatuses.running,
|
|
65083
|
+
trigger: RunTriggers.backfill,
|
|
65084
|
+
sourceId: sourceRow2.id,
|
|
65085
|
+
startedAt,
|
|
65086
|
+
createdAt: startedAt
|
|
65087
|
+
}).run();
|
|
65088
|
+
});
|
|
65089
|
+
} catch (error) {
|
|
65090
|
+
releaseTrafficSyncLease({ db: app.db, sourceId: sourceRow2.id, owner: leaseOwner, now: (/* @__PURE__ */ new Date()).toISOString() });
|
|
65091
|
+
throw error;
|
|
65092
|
+
}
|
|
65027
65093
|
void runBackfillTask({
|
|
65028
65094
|
app,
|
|
65029
65095
|
runId,
|
|
65096
|
+
leaseOwner,
|
|
65097
|
+
leaseRenewMs: opts.trafficBackfillLeaseRenewMs ?? TRAFFIC_BACKFILL_LEASE_RENEW_MS,
|
|
65030
65098
|
project,
|
|
65031
65099
|
sourceRow: sourceRow2,
|
|
65032
65100
|
journeyKeySecret: opts.journeyKeySecret,
|
|
@@ -74342,6 +74410,7 @@ async function apiRoutes(app, opts) {
|
|
|
74342
74410
|
vercelTrafficCredentialStore: opts.vercelTrafficCredentialStore,
|
|
74343
74411
|
pullVercelTrafficEvents: opts.pullVercelTrafficEvents,
|
|
74344
74412
|
vercelSyncDeadlineMs: opts.vercelSyncDeadlineMs,
|
|
74413
|
+
trafficBackfillLeaseRenewMs: opts.trafficBackfillLeaseRenewMs,
|
|
74345
74414
|
cloudflareTrafficCredentialStore: opts.cloudflareTrafficCredentialStore,
|
|
74346
74415
|
pullCloudflareQueueMessages: opts.pullCloudflareQueueMessages,
|
|
74347
74416
|
ackCloudflareQueueMessages: opts.ackCloudflareQueueMessages,
|
|
@@ -599,7 +599,7 @@ var DEMO_CLI_COMMANDS = [{
|
|
|
599
599
|
options: { host: stringOption(), port: stringOption(), "trust-proxy": multiStringOption() },
|
|
600
600
|
allowPositionals: false,
|
|
601
601
|
run: async (input) => {
|
|
602
|
-
const { demoCommand } = await import("./demo-
|
|
602
|
+
const { demoCommand } = await import("./demo-ZRFZ5EBH.js");
|
|
603
603
|
await demoCommand({
|
|
604
604
|
host: getString(input.values, "host"),
|
|
605
605
|
port: getString(input.values, "port"),
|
|
@@ -620,7 +620,7 @@ var BACKFILL_CLI_COMMANDS = [
|
|
|
620
620
|
allowPositionals: false,
|
|
621
621
|
supportsDryRun: true,
|
|
622
622
|
run: async (input) => {
|
|
623
|
-
const { backfillAnswerVisibilityCommand } = await import("./backfill-
|
|
623
|
+
const { backfillAnswerVisibilityCommand } = await import("./backfill-2BVFKQ6J.js");
|
|
624
624
|
await backfillAnswerVisibilityCommand({
|
|
625
625
|
project: getString(input.values, "project"),
|
|
626
626
|
dryRun: input.dryRun,
|
|
@@ -637,7 +637,7 @@ var BACKFILL_CLI_COMMANDS = [
|
|
|
637
637
|
allowPositionals: false,
|
|
638
638
|
supportsDryRun: true,
|
|
639
639
|
run: async (input) => {
|
|
640
|
-
const { backfillAnswerMentionsCommand } = await import("./backfill-
|
|
640
|
+
const { backfillAnswerMentionsCommand } = await import("./backfill-2BVFKQ6J.js");
|
|
641
641
|
await backfillAnswerMentionsCommand({
|
|
642
642
|
project: getString(input.values, "project"),
|
|
643
643
|
dryRun: input.dryRun,
|
|
@@ -655,7 +655,7 @@ var BACKFILL_CLI_COMMANDS = [
|
|
|
655
655
|
},
|
|
656
656
|
supportsDryRun: true,
|
|
657
657
|
run: async (input) => {
|
|
658
|
-
const { backfillInsightsCommand } = await import("./backfill-
|
|
658
|
+
const { backfillInsightsCommand } = await import("./backfill-2BVFKQ6J.js");
|
|
659
659
|
const usage = "canonry backfill insights <project> [--from-run <id>] [--to-run <id>] [--since <date>] [--dry-run] [--format json]";
|
|
660
660
|
const project3 = requireProject(input, "backfill insights", usage);
|
|
661
661
|
await backfillInsightsCommand(project3, {
|
|
@@ -675,7 +675,7 @@ var BACKFILL_CLI_COMMANDS = [
|
|
|
675
675
|
},
|
|
676
676
|
allowPositionals: false,
|
|
677
677
|
run: async (input) => {
|
|
678
|
-
const { backfillNormalizedPathsCommand } = await import("./backfill-
|
|
678
|
+
const { backfillNormalizedPathsCommand } = await import("./backfill-2BVFKQ6J.js");
|
|
679
679
|
await backfillNormalizedPathsCommand({
|
|
680
680
|
project: getString(input.values, "project"),
|
|
681
681
|
format: input.format
|
|
@@ -690,7 +690,7 @@ var BACKFILL_CLI_COMMANDS = [
|
|
|
690
690
|
},
|
|
691
691
|
allowPositionals: false,
|
|
692
692
|
run: async (input) => {
|
|
693
|
-
const { backfillAiReferralPathsCommand } = await import("./backfill-
|
|
693
|
+
const { backfillAiReferralPathsCommand } = await import("./backfill-2BVFKQ6J.js");
|
|
694
694
|
await backfillAiReferralPathsCommand({
|
|
695
695
|
project: getString(input.values, "project"),
|
|
696
696
|
format: input.format
|
|
@@ -702,7 +702,7 @@ var BACKFILL_CLI_COMMANDS = [
|
|
|
702
702
|
usage: "canonry backfill snapshot-attribution <project> [--dry-run] [--format json]",
|
|
703
703
|
supportsDryRun: true,
|
|
704
704
|
run: async (input) => {
|
|
705
|
-
const { backfillSnapshotAttributionCommand } = await import("./backfill-
|
|
705
|
+
const { backfillSnapshotAttributionCommand } = await import("./backfill-2BVFKQ6J.js");
|
|
706
706
|
const usage = "canonry backfill snapshot-attribution <project> [--dry-run] [--format json]";
|
|
707
707
|
const project3 = requireProject(input, "backfill snapshot-attribution", usage);
|
|
708
708
|
await backfillSnapshotAttributionCommand({
|
|
@@ -721,7 +721,7 @@ var BACKFILL_CLI_COMMANDS = [
|
|
|
721
721
|
allowPositionals: false,
|
|
722
722
|
supportsDryRun: true,
|
|
723
723
|
run: async (input) => {
|
|
724
|
-
const { backfillTrafficClassificationCommand } = await import("./backfill-
|
|
724
|
+
const { backfillTrafficClassificationCommand } = await import("./backfill-2BVFKQ6J.js");
|
|
725
725
|
await backfillTrafficClassificationCommand({
|
|
726
726
|
project: getString(input.values, "project"),
|
|
727
727
|
dryRun: input.dryRun,
|
|
@@ -1163,7 +1163,7 @@ var DASHBOARD_CLI_COMMANDS = [
|
|
|
1163
1163
|
usage: "canonry dashboard reset-password [--format json]",
|
|
1164
1164
|
help: "Clears the dashboard password from config.yaml, so the dashboard asks for a new one after a restart.\nLocal only: it edits the config file under CANONRY_CONFIG_DIR and does not call the server.",
|
|
1165
1165
|
run: async (input) => {
|
|
1166
|
-
const { resetDashboardPassword } = await import("./dashboard-
|
|
1166
|
+
const { resetDashboardPassword } = await import("./dashboard-BC4NKAO2.js");
|
|
1167
1167
|
await resetDashboardPassword({ format: input.format });
|
|
1168
1168
|
}
|
|
1169
1169
|
},
|
|
@@ -6720,7 +6720,7 @@ var SYSTEM_CLI_COMMANDS = [
|
|
|
6720
6720
|
options: { access: stringOption() },
|
|
6721
6721
|
run: async (input) => {
|
|
6722
6722
|
if (input.positionals.length > 1) throw usageError("Expected at most one command group");
|
|
6723
|
-
const [{ printCliCatalog }, { REGISTERED_CLI_COMMANDS: REGISTERED_CLI_COMMANDS2 }] = await Promise.all([import("./cli-catalog-VRJS66GR.js"), import("./cli-commands-
|
|
6723
|
+
const [{ printCliCatalog }, { REGISTERED_CLI_COMMANDS: REGISTERED_CLI_COMMANDS2 }] = await Promise.all([import("./cli-catalog-VRJS66GR.js"), import("./cli-commands-ONFE63OB.js")]);
|
|
6724
6724
|
printCliCatalog(REGISTERED_CLI_COMMANDS2, input.format, input.positionals[0], getString(input.values, "access"));
|
|
6725
6725
|
}
|
|
6726
6726
|
},
|
|
@@ -6769,7 +6769,7 @@ var SYSTEM_CLI_COMMANDS = [
|
|
|
6769
6769
|
},
|
|
6770
6770
|
allowPositionals: false,
|
|
6771
6771
|
run: async (input) => {
|
|
6772
|
-
const { initCommand } = await import("./init-
|
|
6772
|
+
const { initCommand } = await import("./init-TU4VSGVU.js");
|
|
6773
6773
|
await initCommand({
|
|
6774
6774
|
force: getBoolean(input.values, "force"),
|
|
6775
6775
|
ref: getString(input.values, "ref"),
|
|
@@ -6824,7 +6824,7 @@ var SYSTEM_CLI_COMMANDS = [
|
|
|
6824
6824
|
allowPositionals: false,
|
|
6825
6825
|
run: async (input) => {
|
|
6826
6826
|
applyServerEnv(input.values);
|
|
6827
|
-
const { serveCommand } = await import("./serve-
|
|
6827
|
+
const { serveCommand } = await import("./serve-VIEGFGSK.js");
|
|
6828
6828
|
await serveCommand(input.format);
|
|
6829
6829
|
}
|
|
6830
6830
|
},
|
|
@@ -8132,8 +8132,8 @@ var AGENT_CLI_COMMANDS = [
|
|
|
8132
8132
|
"timeout-ms": stringOption()
|
|
8133
8133
|
},
|
|
8134
8134
|
run: async (input) => {
|
|
8135
|
-
const { coerceAgentProvider } = await import("./session-
|
|
8136
|
-
const { AERO_TOOL_PROFILES, isAeroToolProfile } = await import("./tools-
|
|
8135
|
+
const { coerceAgentProvider } = await import("./session-JLH72BF5.js");
|
|
8136
|
+
const { AERO_TOOL_PROFILES, isAeroToolProfile } = await import("./tools-YOV2KHF2.js");
|
|
8137
8137
|
const { agentAsk } = await import("./agent-ask-UEYN2SQX.js");
|
|
8138
8138
|
const usage = `canonry agent ask <project> "<prompt>" [--provider ${AGENT_PROVIDER_IDS.join("|")}] [--model <id>] [--scope all|read-only] [--profile default|ads-operator] [--context <json>] [--conversation <id>] [--max-tool-calls <n>] [--timeout-ms <ms>] [--format json]`;
|
|
8139
8139
|
const project3 = requireProject(input, "agent.ask", usage);
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
createRunCompetitorResolver,
|
|
24
24
|
readMarketCompetitorNames,
|
|
25
25
|
refreshSnapshotMentionIdentity
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-22ABGRB7.js";
|
|
27
27
|
import {
|
|
28
28
|
classifyAiUserFetch,
|
|
29
29
|
classifyCrawler
|
|
@@ -437,7 +437,7 @@ No DB writes performed. Re-run without --dry-run to apply.`);
|
|
|
437
437
|
}
|
|
438
438
|
}
|
|
439
439
|
async function backfillInsightsCommand(project, opts) {
|
|
440
|
-
const { IntelligenceService } = await import("./intelligence-service-
|
|
440
|
+
const { IntelligenceService } = await import("./intelligence-service-MWTHUE7S.js");
|
|
441
441
|
const config = loadConfig();
|
|
442
442
|
const db = createClient(config.database);
|
|
443
443
|
migrate(db);
|
|
@@ -27,14 +27,14 @@ import {
|
|
|
27
27
|
resolveConfiguredAgentProvider,
|
|
28
28
|
resolveSessionProviderAndModel,
|
|
29
29
|
setAeroSystemPrompt
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-V3QMOGZE.js";
|
|
31
31
|
import {
|
|
32
32
|
AeroToolProfiles,
|
|
33
33
|
AeroToolScopes,
|
|
34
34
|
buildAeroStateTools,
|
|
35
35
|
isAeroToolProfile,
|
|
36
36
|
truncateToolResult
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-JM6OFCLX.js";
|
|
38
38
|
import {
|
|
39
39
|
getGoogleAuthConfig,
|
|
40
40
|
getGoogleConnection,
|
|
@@ -162,7 +162,7 @@ import {
|
|
|
162
162
|
addLogListener,
|
|
163
163
|
createFastifyLogger,
|
|
164
164
|
createLogger
|
|
165
|
-
} from "./chunk-
|
|
165
|
+
} from "./chunk-5GMYD7UZ.js";
|
|
166
166
|
import {
|
|
167
167
|
computeCitedCompetitorDomains,
|
|
168
168
|
determineCitationState
|
|
@@ -285,7 +285,7 @@ import {
|
|
|
285
285
|
webhookResponseReason,
|
|
286
286
|
webhookTargetRefusalReason,
|
|
287
287
|
writeAuditLog
|
|
288
|
-
} from "./chunk-
|
|
288
|
+
} from "./chunk-22ABGRB7.js";
|
|
289
289
|
import {
|
|
290
290
|
OperationalLogStore,
|
|
291
291
|
SentimentIdempotencyConflict,
|
|
@@ -5658,7 +5658,7 @@ function nonBlank(value) {
|
|
|
5658
5658
|
return trimmed ? trimmed : void 0;
|
|
5659
5659
|
}
|
|
5660
5660
|
function resolveBuildCommit(env = process.env) {
|
|
5661
|
-
const embedded = true ? "
|
|
5661
|
+
const embedded = true ? "bf661eb5ab6eb02b455254b13b5cc8d0d8ca6536" : void 0;
|
|
5662
5662
|
return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
|
|
5663
5663
|
}
|
|
5664
5664
|
function resolveInstanceIdentity(env = process.env) {
|
|
@@ -19723,6 +19723,10 @@ async function createServer(opts) {
|
|
|
19723
19723
|
schedulerClient.trafficSync(projectName, sourceId).finally(() => {
|
|
19724
19724
|
scheduledSyncClaims.delete(syncRunClaimKey(projectName, RunKinds["traffic-sync"], sourceId));
|
|
19725
19725
|
}).catch((err) => {
|
|
19726
|
+
if (err instanceof CliError && err.code === "OPERATION_IN_PROGRESS") {
|
|
19727
|
+
app.log.info({ projectName, sourceId }, "Scheduled traffic sync skipped: the source is busy");
|
|
19728
|
+
return;
|
|
19729
|
+
}
|
|
19726
19730
|
app.log.error(
|
|
19727
19731
|
{
|
|
19728
19732
|
projectName,
|
|
@@ -47,7 +47,7 @@ function queueServeHandoff() {
|
|
|
47
47
|
async function runPendingServeHandoff(format) {
|
|
48
48
|
if (!pendingServeHandoff) return;
|
|
49
49
|
pendingServeHandoff = false;
|
|
50
|
-
const { serveCommand } = await import("./serve-
|
|
50
|
+
const { serveCommand } = await import("./serve-VIEGFGSK.js");
|
|
51
51
|
await serveCommand(format);
|
|
52
52
|
}
|
|
53
53
|
|
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node --import tsx
|
|
2
2
|
import {
|
|
3
3
|
REGISTERED_CLI_COMMANDS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-32KNDPD3.js";
|
|
5
5
|
import {
|
|
6
6
|
buildSetupState,
|
|
7
7
|
runPendingServeHandoff
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-IRRONWF7.js";
|
|
9
9
|
import "./chunk-6GO5VVAC.js";
|
|
10
10
|
import "./chunk-2LAL5W6J.js";
|
|
11
11
|
import "./chunk-VJWDBFSL.js";
|
|
@@ -40,7 +40,7 @@ function parseDemoTrustedProxies(values) {
|
|
|
40
40
|
async function demoCommand(options) {
|
|
41
41
|
const { host, port } = parseDemoListenOptions(options);
|
|
42
42
|
const trustProxy = parseDemoTrustedProxies(options.trustProxy);
|
|
43
|
-
const { createDemoServer } = await import("./demo-server-
|
|
43
|
+
const { createDemoServer } = await import("./demo-server-7R7NGWJA.js");
|
|
44
44
|
const app = await createDemoServer({ trustProxy });
|
|
45
45
|
let stopping = false;
|
|
46
46
|
const stop = () => {
|
|
@@ -18,14 +18,14 @@ import "./chunk-HGMYEDAQ.js";
|
|
|
18
18
|
import {
|
|
19
19
|
HISTORY_WINDOW_RUNS,
|
|
20
20
|
IntelligenceService
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-5GMYD7UZ.js";
|
|
22
22
|
import {
|
|
23
23
|
determineCitationState
|
|
24
24
|
} from "./chunk-EHTSCLEL.js";
|
|
25
25
|
import {
|
|
26
26
|
apiRoutes,
|
|
27
27
|
assessConversionTrackingIntegrity
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-22ABGRB7.js";
|
|
29
29
|
import "./chunk-SG2OPR7J.js";
|
|
30
30
|
import "./chunk-QNFX7ZCT.js";
|
|
31
31
|
import {
|