@ainyc/canonry 4.100.0 → 4.101.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.
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +0 -12
- package/assets/assets/{BacklinksPage-DWZdWEm3.js → BacklinksPage-aysk_iGy.js} +1 -1
- package/assets/assets/{ChartPrimitives-C-ky5206.js → ChartPrimitives-CmKqxndA.js} +1 -1
- package/assets/assets/ProjectPage-dduZrrBr.js +7 -0
- package/assets/assets/{RunRow-Bj-D4kZe.js → RunRow-Ba77hJ4d.js} +1 -1
- package/assets/assets/{RunsPage-GktitsAV.js → RunsPage-D3IAdQMB.js} +1 -1
- package/assets/assets/{SettingsPage-AsFLFDS3.js → SettingsPage-Y54JtLw-.js} +1 -1
- package/assets/assets/{TrafficPage-Cf3uCkxs.js → TrafficPage-DawzPWdt.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-B5t7nf9C.js → TrafficSourceDetailPage-DAhQwFVb.js} +1 -1
- package/assets/assets/{arrow-left-CZFQuQO_.js → arrow-left-NsJbgqmV.js} +1 -1
- package/assets/assets/{extract-error-message--bieZ2IX.js → extract-error-message-u00ggxeK.js} +1 -1
- package/assets/assets/index-4YArcfwj.js +210 -0
- package/assets/assets/index-BCuWbxUj.css +1 -0
- package/assets/assets/{trash-2-sKO0k75f.js → trash-2-BBdbbe60.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-UVIHWF45.js → chunk-2YPVK75M.js} +6 -28
- package/dist/{chunk-SNHYRSUF.js → chunk-AV3DHH6B.js} +153 -369
- package/dist/{chunk-ADLS64PG.js → chunk-HUL5FUBD.js} +6 -105
- package/dist/{chunk-74SOIAIY.js → chunk-O3SFVGDF.js} +531 -49
- package/dist/cli.js +26 -114
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-3CRNJLUZ.js → intelligence-service-R6QJ3KC2.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +7 -7
- package/assets/assets/ProjectPage-CpbFpi6J.js +0 -6
- package/assets/assets/index-9hI0ODQU.css +0 -1
- package/assets/assets/index-Cb2h7KkD.js +0 -210
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
DiscoveryBuckets,
|
|
19
19
|
DiscoveryCompetitorTypes,
|
|
20
20
|
DiscoverySessionStatuses,
|
|
21
|
-
PortfolioChangeTypes,
|
|
22
21
|
RunKinds,
|
|
23
22
|
RunStatuses,
|
|
24
23
|
RunTriggers,
|
|
@@ -132,7 +131,6 @@ import {
|
|
|
132
131
|
formatIsoDate,
|
|
133
132
|
formatNumber,
|
|
134
133
|
formatRatio,
|
|
135
|
-
formatRunErrorOneLine,
|
|
136
134
|
formatWindowCountDelta,
|
|
137
135
|
ga4AiReferralHistoryEntrySchema,
|
|
138
136
|
ga4SessionHistoryEntrySchema,
|
|
@@ -186,7 +184,6 @@ import {
|
|
|
186
184
|
parseRunError,
|
|
187
185
|
parseWindow,
|
|
188
186
|
pickClusterRepresentative,
|
|
189
|
-
portfolioDtoSchema,
|
|
190
187
|
projectConfigSchema,
|
|
191
188
|
projectDtoSchema,
|
|
192
189
|
projectOverviewDtoSchema,
|
|
@@ -266,10 +263,10 @@ import {
|
|
|
266
263
|
wordpressSchemaDeployResultDtoSchema,
|
|
267
264
|
wordpressSchemaStatusResultDtoSchema,
|
|
268
265
|
wordpressStatusDtoSchema
|
|
269
|
-
} from "./chunk-
|
|
266
|
+
} from "./chunk-HUL5FUBD.js";
|
|
270
267
|
|
|
271
268
|
// src/intelligence-service.ts
|
|
272
|
-
import { eq as eq37, desc as desc18, asc as
|
|
269
|
+
import { eq as eq37, desc as desc18, asc as asc5, and as and27, ne as ne5, or as or5, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
|
|
273
270
|
|
|
274
271
|
// ../db/src/client.ts
|
|
275
272
|
import { mkdirSync } from "fs";
|
|
@@ -287,6 +284,7 @@ __export(schema_exports, {
|
|
|
287
284
|
adsInsightsDaily: () => adsInsightsDaily,
|
|
288
285
|
agentMemory: () => agentMemory,
|
|
289
286
|
agentSessions: () => agentSessions,
|
|
287
|
+
agentToolEvents: () => agentToolEvents,
|
|
290
288
|
aiReferralEventsHourly: () => aiReferralEventsHourly,
|
|
291
289
|
aiUserFetchEventsHourly: () => aiUserFetchEventsHourly,
|
|
292
290
|
apiKeys: () => apiKeys,
|
|
@@ -324,6 +322,7 @@ __export(schema_exports, {
|
|
|
324
322
|
gscUrlInspections: () => gscUrlInspections,
|
|
325
323
|
healthSnapshots: () => healthSnapshots,
|
|
326
324
|
insights: () => insights,
|
|
325
|
+
llmUsageEvents: () => llmUsageEvents,
|
|
327
326
|
migrationsTable: () => migrationsTable,
|
|
328
327
|
notifications: () => notifications,
|
|
329
328
|
projects: () => projects,
|
|
@@ -927,6 +926,53 @@ var agentMemory = sqliteTable("agent_memory", {
|
|
|
927
926
|
uniqueIndex("uniq_agent_memory_project_key").on(table.projectId, table.key),
|
|
928
927
|
index("idx_agent_memory_project_updated").on(table.projectId, table.updatedAt)
|
|
929
928
|
]);
|
|
929
|
+
var llmUsageEvents = sqliteTable("llm_usage_events", {
|
|
930
|
+
id: text("id").primaryKey(),
|
|
931
|
+
projectId: text("project_id").references(() => projects.id, { onDelete: "cascade" }),
|
|
932
|
+
runId: text("run_id").references(() => runs.id, { onDelete: "set null" }),
|
|
933
|
+
agentSessionId: text("agent_session_id").references(() => agentSessions.id, { onDelete: "set null" }),
|
|
934
|
+
feature: text("feature").notNull(),
|
|
935
|
+
provider: text("provider").notNull(),
|
|
936
|
+
model: text("model").notNull(),
|
|
937
|
+
responseId: text("response_id"),
|
|
938
|
+
inputTokens: integer("input_tokens").notNull().default(0),
|
|
939
|
+
outputTokens: integer("output_tokens").notNull().default(0),
|
|
940
|
+
cacheReadTokens: integer("cache_read_tokens").notNull().default(0),
|
|
941
|
+
cacheWriteTokens: integer("cache_write_tokens").notNull().default(0),
|
|
942
|
+
totalTokens: integer("total_tokens").notNull().default(0),
|
|
943
|
+
costMillicents: integer("cost_millicents").notNull().default(0),
|
|
944
|
+
promptFamily: text("prompt_family"),
|
|
945
|
+
promptVersion: text("prompt_version"),
|
|
946
|
+
metadata: text("metadata", { mode: "json" }).$type(),
|
|
947
|
+
createdAt: text("created_at").notNull()
|
|
948
|
+
}, (table) => [
|
|
949
|
+
index("idx_llm_usage_project_created").on(table.projectId, table.createdAt),
|
|
950
|
+
index("idx_llm_usage_feature_created").on(table.feature, table.createdAt),
|
|
951
|
+
index("idx_llm_usage_session_created").on(table.agentSessionId, table.createdAt),
|
|
952
|
+
index("idx_llm_usage_run_created").on(table.runId, table.createdAt)
|
|
953
|
+
]);
|
|
954
|
+
var agentToolEvents = sqliteTable("agent_tool_events", {
|
|
955
|
+
id: text("id").primaryKey(),
|
|
956
|
+
projectId: text("project_id").references(() => projects.id, { onDelete: "cascade" }),
|
|
957
|
+
agentSessionId: text("agent_session_id").references(() => agentSessions.id, { onDelete: "set null" }),
|
|
958
|
+
toolCallId: text("tool_call_id").notNull(),
|
|
959
|
+
toolName: text("tool_name").notNull(),
|
|
960
|
+
assistantResponseId: text("assistant_response_id"),
|
|
961
|
+
provider: text("provider"),
|
|
962
|
+
model: text("model"),
|
|
963
|
+
status: text("status").notNull(),
|
|
964
|
+
durationMs: integer("duration_ms").notNull().default(0),
|
|
965
|
+
argsBytes: integer("args_bytes").notNull().default(0),
|
|
966
|
+
resultTextChars: integer("result_text_chars").notNull().default(0),
|
|
967
|
+
resultBytes: integer("result_bytes").notNull().default(0),
|
|
968
|
+
metadata: text("metadata", { mode: "json" }).$type(),
|
|
969
|
+
createdAt: text("created_at").notNull()
|
|
970
|
+
}, (table) => [
|
|
971
|
+
index("idx_agent_tool_events_project_created").on(table.projectId, table.createdAt),
|
|
972
|
+
index("idx_agent_tool_events_session_created").on(table.agentSessionId, table.createdAt),
|
|
973
|
+
index("idx_agent_tool_events_tool_created").on(table.toolName, table.createdAt),
|
|
974
|
+
index("idx_agent_tool_events_status_created").on(table.status, table.createdAt)
|
|
975
|
+
]);
|
|
930
976
|
var trafficSources = sqliteTable("traffic_sources", {
|
|
931
977
|
id: text("id").primaryKey(),
|
|
932
978
|
projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
|
|
@@ -3214,6 +3260,63 @@ var MIGRATION_VERSIONS = [
|
|
|
3214
3260
|
`ALTER TABLE ads_insights_daily ADD COLUMN conversions INTEGER NOT NULL DEFAULT 0`,
|
|
3215
3261
|
`ALTER TABLE ads_connections ADD COLUMN conversion_tracking_configured INTEGER NOT NULL DEFAULT 0`
|
|
3216
3262
|
]
|
|
3263
|
+
},
|
|
3264
|
+
{
|
|
3265
|
+
version: 84,
|
|
3266
|
+
name: "llm-usage-events",
|
|
3267
|
+
statements: [
|
|
3268
|
+
`CREATE TABLE IF NOT EXISTS llm_usage_events (
|
|
3269
|
+
id TEXT PRIMARY KEY,
|
|
3270
|
+
project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
|
|
3271
|
+
run_id TEXT REFERENCES runs(id) ON DELETE SET NULL,
|
|
3272
|
+
agent_session_id TEXT REFERENCES agent_sessions(id) ON DELETE SET NULL,
|
|
3273
|
+
feature TEXT NOT NULL,
|
|
3274
|
+
provider TEXT NOT NULL,
|
|
3275
|
+
model TEXT NOT NULL,
|
|
3276
|
+
response_id TEXT,
|
|
3277
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
3278
|
+
output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
3279
|
+
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
|
|
3280
|
+
cache_write_tokens INTEGER NOT NULL DEFAULT 0,
|
|
3281
|
+
total_tokens INTEGER NOT NULL DEFAULT 0,
|
|
3282
|
+
cost_millicents INTEGER NOT NULL DEFAULT 0,
|
|
3283
|
+
prompt_family TEXT,
|
|
3284
|
+
prompt_version TEXT,
|
|
3285
|
+
metadata TEXT,
|
|
3286
|
+
created_at TEXT NOT NULL
|
|
3287
|
+
)`,
|
|
3288
|
+
`CREATE INDEX IF NOT EXISTS idx_llm_usage_project_created ON llm_usage_events(project_id, created_at)`,
|
|
3289
|
+
`CREATE INDEX IF NOT EXISTS idx_llm_usage_feature_created ON llm_usage_events(feature, created_at)`,
|
|
3290
|
+
`CREATE INDEX IF NOT EXISTS idx_llm_usage_session_created ON llm_usage_events(agent_session_id, created_at)`,
|
|
3291
|
+
`CREATE INDEX IF NOT EXISTS idx_llm_usage_run_created ON llm_usage_events(run_id, created_at)`
|
|
3292
|
+
]
|
|
3293
|
+
},
|
|
3294
|
+
{
|
|
3295
|
+
version: 85,
|
|
3296
|
+
name: "agent-tool-events",
|
|
3297
|
+
statements: [
|
|
3298
|
+
`CREATE TABLE IF NOT EXISTS agent_tool_events (
|
|
3299
|
+
id TEXT PRIMARY KEY,
|
|
3300
|
+
project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
|
|
3301
|
+
agent_session_id TEXT REFERENCES agent_sessions(id) ON DELETE SET NULL,
|
|
3302
|
+
tool_call_id TEXT NOT NULL,
|
|
3303
|
+
tool_name TEXT NOT NULL,
|
|
3304
|
+
assistant_response_id TEXT,
|
|
3305
|
+
provider TEXT,
|
|
3306
|
+
model TEXT,
|
|
3307
|
+
status TEXT NOT NULL,
|
|
3308
|
+
duration_ms INTEGER NOT NULL DEFAULT 0,
|
|
3309
|
+
args_bytes INTEGER NOT NULL DEFAULT 0,
|
|
3310
|
+
result_text_chars INTEGER NOT NULL DEFAULT 0,
|
|
3311
|
+
result_bytes INTEGER NOT NULL DEFAULT 0,
|
|
3312
|
+
metadata TEXT,
|
|
3313
|
+
created_at TEXT NOT NULL
|
|
3314
|
+
)`,
|
|
3315
|
+
`CREATE INDEX IF NOT EXISTS idx_agent_tool_events_project_created ON agent_tool_events(project_id, created_at)`,
|
|
3316
|
+
`CREATE INDEX IF NOT EXISTS idx_agent_tool_events_session_created ON agent_tool_events(agent_session_id, created_at)`,
|
|
3317
|
+
`CREATE INDEX IF NOT EXISTS idx_agent_tool_events_tool_created ON agent_tool_events(tool_name, created_at)`,
|
|
3318
|
+
`CREATE INDEX IF NOT EXISTS idx_agent_tool_events_status_created ON agent_tool_events(status, created_at)`
|
|
3319
|
+
]
|
|
3217
3320
|
}
|
|
3218
3321
|
];
|
|
3219
3322
|
function rebuildBacklinkTableWithSource(tx, table) {
|
|
@@ -5048,233 +5151,6 @@ function buildRunHistory(runs2, snapshotsByRunId, limit = DEFAULT_RUN_HISTORY_LI
|
|
|
5048
5151
|
});
|
|
5049
5152
|
}
|
|
5050
5153
|
|
|
5051
|
-
// ../intelligence/src/portfolio-change-feed.ts
|
|
5052
|
-
var PORTFOLIO_CHANGE_FEED_LIMIT = 12;
|
|
5053
|
-
var TONE_SEVERITY = {
|
|
5054
|
-
negative: 0,
|
|
5055
|
-
caution: 1,
|
|
5056
|
-
positive: 2,
|
|
5057
|
-
neutral: 3
|
|
5058
|
-
};
|
|
5059
|
-
function pluralizeQueries(n) {
|
|
5060
|
-
return n === 1 ? "query" : "queries";
|
|
5061
|
-
}
|
|
5062
|
-
function pluralizeAnswers(n) {
|
|
5063
|
-
return n === 1 ? "answer" : "answers";
|
|
5064
|
-
}
|
|
5065
|
-
function affectedDetail(queries2, max = 3) {
|
|
5066
|
-
const list = queries2 ?? [];
|
|
5067
|
-
if (list.length === 0) return "";
|
|
5068
|
-
const shown = list.slice(0, max).map((q) => `"${q}"`).join(", ");
|
|
5069
|
-
const remaining = list.length - max;
|
|
5070
|
-
return remaining > 0 ? `${shown} +${remaining} more` : shown;
|
|
5071
|
-
}
|
|
5072
|
-
function buildProjectChanges(input) {
|
|
5073
|
-
const {
|
|
5074
|
-
projectName,
|
|
5075
|
-
projectSlug,
|
|
5076
|
-
citationMovement,
|
|
5077
|
-
mentionMovement,
|
|
5078
|
-
movementComparison,
|
|
5079
|
-
attentionItems,
|
|
5080
|
-
latestRun
|
|
5081
|
-
} = input;
|
|
5082
|
-
const href = `/projects/${encodeURIComponent(projectSlug)}`;
|
|
5083
|
-
const rows = [];
|
|
5084
|
-
if (!latestRun) {
|
|
5085
|
-
rows.push({
|
|
5086
|
-
id: `${projectSlug}:${PortfolioChangeTypes["project-never-run"]}`,
|
|
5087
|
-
projectName,
|
|
5088
|
-
projectSlug,
|
|
5089
|
-
changeType: PortfolioChangeTypes["project-never-run"],
|
|
5090
|
-
tone: "neutral",
|
|
5091
|
-
title: `${projectName} has no completed sweep yet`,
|
|
5092
|
-
detail: `${input.trackedQueryCount} ${pluralizeQueries(input.trackedQueryCount)} tracked \u2014 run a sweep to start measuring.`,
|
|
5093
|
-
occurredAt: input.projectCreatedAt,
|
|
5094
|
-
href,
|
|
5095
|
-
actionLabel: "Run sweep",
|
|
5096
|
-
comparable: false
|
|
5097
|
-
});
|
|
5098
|
-
return rows;
|
|
5099
|
-
}
|
|
5100
|
-
const { runId, occurredAt } = latestRun;
|
|
5101
|
-
const comparable = movementComparison.comparable;
|
|
5102
|
-
if (latestRun.status === RunStatuses.failed) {
|
|
5103
|
-
rows.push({
|
|
5104
|
-
id: `${projectSlug}:${PortfolioChangeTypes["run-failed"]}:${runId}`,
|
|
5105
|
-
projectName,
|
|
5106
|
-
projectSlug,
|
|
5107
|
-
changeType: PortfolioChangeTypes["run-failed"],
|
|
5108
|
-
tone: "negative",
|
|
5109
|
-
title: `${projectName} sweep failed`,
|
|
5110
|
-
detail: latestRun.error ? formatRunErrorOneLine(latestRun.error) : "The latest visibility sweep failed.",
|
|
5111
|
-
occurredAt,
|
|
5112
|
-
href,
|
|
5113
|
-
actionLabel: "View run",
|
|
5114
|
-
comparable
|
|
5115
|
-
});
|
|
5116
|
-
}
|
|
5117
|
-
if (comparable) {
|
|
5118
|
-
if (citationMovement.lost > 0) {
|
|
5119
|
-
rows.push({
|
|
5120
|
-
id: `${projectSlug}:${PortfolioChangeTypes["citation-lost"]}:${runId}`,
|
|
5121
|
-
projectName,
|
|
5122
|
-
projectSlug,
|
|
5123
|
-
changeType: PortfolioChangeTypes["citation-lost"],
|
|
5124
|
-
tone: "negative",
|
|
5125
|
-
title: `${projectName} lost ${citationMovement.lost} cited ${pluralizeQueries(citationMovement.lost)}`,
|
|
5126
|
-
detail: affectedDetail(citationMovement.lostQueries),
|
|
5127
|
-
occurredAt,
|
|
5128
|
-
href,
|
|
5129
|
-
actionLabel: "Open project",
|
|
5130
|
-
comparable: true
|
|
5131
|
-
});
|
|
5132
|
-
}
|
|
5133
|
-
if (citationMovement.gained > 0) {
|
|
5134
|
-
rows.push({
|
|
5135
|
-
id: `${projectSlug}:${PortfolioChangeTypes["citation-gained"]}:${runId}`,
|
|
5136
|
-
projectName,
|
|
5137
|
-
projectSlug,
|
|
5138
|
-
changeType: PortfolioChangeTypes["citation-gained"],
|
|
5139
|
-
tone: "positive",
|
|
5140
|
-
title: `${projectName} gained ${citationMovement.gained} cited ${pluralizeQueries(citationMovement.gained)}`,
|
|
5141
|
-
detail: affectedDetail(citationMovement.gainedQueries),
|
|
5142
|
-
occurredAt,
|
|
5143
|
-
href,
|
|
5144
|
-
actionLabel: "Open project",
|
|
5145
|
-
comparable: true
|
|
5146
|
-
});
|
|
5147
|
-
}
|
|
5148
|
-
if (mentionMovement.lost > 0) {
|
|
5149
|
-
const queries2 = affectedDetail(mentionMovement.lostQueries);
|
|
5150
|
-
rows.push({
|
|
5151
|
-
id: `${projectSlug}:${PortfolioChangeTypes["mention-lost"]}:${runId}`,
|
|
5152
|
-
projectName,
|
|
5153
|
-
projectSlug,
|
|
5154
|
-
changeType: PortfolioChangeTypes["mention-lost"],
|
|
5155
|
-
tone: "negative",
|
|
5156
|
-
title: `${projectName} dropped from ${mentionMovement.lost} ${pluralizeAnswers(mentionMovement.lost)}`,
|
|
5157
|
-
detail: queries2 ? `No longer mentioned for ${queries2}` : "",
|
|
5158
|
-
occurredAt,
|
|
5159
|
-
href,
|
|
5160
|
-
actionLabel: "Open project",
|
|
5161
|
-
comparable: true
|
|
5162
|
-
});
|
|
5163
|
-
}
|
|
5164
|
-
if (mentionMovement.gained > 0) {
|
|
5165
|
-
rows.push({
|
|
5166
|
-
id: `${projectSlug}:${PortfolioChangeTypes["mention-gained"]}:${runId}`,
|
|
5167
|
-
projectName,
|
|
5168
|
-
projectSlug,
|
|
5169
|
-
changeType: PortfolioChangeTypes["mention-gained"],
|
|
5170
|
-
tone: "positive",
|
|
5171
|
-
title: `${projectName} now mentioned in ${mentionMovement.gained} more ${pluralizeAnswers(mentionMovement.gained)}`,
|
|
5172
|
-
detail: affectedDetail(mentionMovement.gainedQueries),
|
|
5173
|
-
occurredAt,
|
|
5174
|
-
href,
|
|
5175
|
-
actionLabel: "Open project",
|
|
5176
|
-
comparable: true
|
|
5177
|
-
});
|
|
5178
|
-
}
|
|
5179
|
-
} else if (movementComparison.hasPreviousRun && movementComparison.querySetChanged) {
|
|
5180
|
-
rows.push({
|
|
5181
|
-
id: `${projectSlug}:${PortfolioChangeTypes["query-set-changed"]}:${runId}`,
|
|
5182
|
-
projectName,
|
|
5183
|
-
projectSlug,
|
|
5184
|
-
changeType: PortfolioChangeTypes["query-set-changed"],
|
|
5185
|
-
tone: "neutral",
|
|
5186
|
-
title: `${projectName} query set changed`,
|
|
5187
|
-
detail: `+${movementComparison.addedQueryCount} added \xB7 \u2212${movementComparison.removedQueryCount} removed since last sweep \u2014 movement compares the shared queries`,
|
|
5188
|
-
occurredAt,
|
|
5189
|
-
href,
|
|
5190
|
-
actionLabel: "Open project",
|
|
5191
|
-
comparable: false
|
|
5192
|
-
});
|
|
5193
|
-
}
|
|
5194
|
-
for (const item of attentionItems) {
|
|
5195
|
-
if (item.id.startsWith("insight_")) {
|
|
5196
|
-
const isCritical = item.tone === "negative";
|
|
5197
|
-
const changeType = isCritical ? PortfolioChangeTypes["insight-critical"] : PortfolioChangeTypes["insight-high"];
|
|
5198
|
-
rows.push({
|
|
5199
|
-
id: `${projectSlug}:${changeType}:${item.id}`,
|
|
5200
|
-
projectName,
|
|
5201
|
-
projectSlug,
|
|
5202
|
-
changeType,
|
|
5203
|
-
tone: item.tone,
|
|
5204
|
-
title: item.title,
|
|
5205
|
-
detail: item.detail,
|
|
5206
|
-
occurredAt,
|
|
5207
|
-
href,
|
|
5208
|
-
actionLabel: isCritical ? "Critical" : "High",
|
|
5209
|
-
comparable
|
|
5210
|
-
});
|
|
5211
|
-
} else if (item.id === "stale_visibility") {
|
|
5212
|
-
rows.push({
|
|
5213
|
-
id: `${projectSlug}:${PortfolioChangeTypes["stale-visibility"]}:${runId}`,
|
|
5214
|
-
projectName,
|
|
5215
|
-
projectSlug,
|
|
5216
|
-
changeType: PortfolioChangeTypes["stale-visibility"],
|
|
5217
|
-
tone: "caution",
|
|
5218
|
-
title: `${projectName} visibility data is stale`,
|
|
5219
|
-
detail: "Integration syncs have run since the last sweep.",
|
|
5220
|
-
occurredAt,
|
|
5221
|
-
href,
|
|
5222
|
-
actionLabel: "Re-sweep",
|
|
5223
|
-
comparable
|
|
5224
|
-
});
|
|
5225
|
-
}
|
|
5226
|
-
}
|
|
5227
|
-
return rows;
|
|
5228
|
-
}
|
|
5229
|
-
function resolveEmptyState(projectCount, comparableProjectCount) {
|
|
5230
|
-
if (comparableProjectCount === 0) {
|
|
5231
|
-
return {
|
|
5232
|
-
kind: "awaiting-second-sweep",
|
|
5233
|
-
title: "No changes to compare yet",
|
|
5234
|
-
detail: "Visibility movement appears after a second sweep."
|
|
5235
|
-
};
|
|
5236
|
-
}
|
|
5237
|
-
return {
|
|
5238
|
-
kind: "all-clear",
|
|
5239
|
-
title: "No changes since the last sweep",
|
|
5240
|
-
detail: `All ${projectCount} project${projectCount === 1 ? "" : "s"} held their mention and citation coverage.`
|
|
5241
|
-
};
|
|
5242
|
-
}
|
|
5243
|
-
function buildPortfolioChangeFeed(inputs, _nowIso) {
|
|
5244
|
-
const all = [];
|
|
5245
|
-
let comparableProjectCount = 0;
|
|
5246
|
-
let firstSweepProjectCount = 0;
|
|
5247
|
-
for (const input of inputs) {
|
|
5248
|
-
if (input.latestRun) {
|
|
5249
|
-
if (input.movementComparison.comparable) comparableProjectCount += 1;
|
|
5250
|
-
if (!input.movementComparison.hasPreviousRun) firstSweepProjectCount += 1;
|
|
5251
|
-
}
|
|
5252
|
-
all.push(...buildProjectChanges(input));
|
|
5253
|
-
}
|
|
5254
|
-
const byId = /* @__PURE__ */ new Map();
|
|
5255
|
-
for (const row of all) {
|
|
5256
|
-
if (!byId.has(row.id)) byId.set(row.id, row);
|
|
5257
|
-
}
|
|
5258
|
-
const deduped = [...byId.values()];
|
|
5259
|
-
deduped.sort((a, b) => {
|
|
5260
|
-
if (a.occurredAt !== b.occurredAt) return a.occurredAt < b.occurredAt ? 1 : -1;
|
|
5261
|
-
const severity = TONE_SEVERITY[a.tone] - TONE_SEVERITY[b.tone];
|
|
5262
|
-
if (severity !== 0) return severity;
|
|
5263
|
-
if (a.projectName !== b.projectName) return a.projectName < b.projectName ? -1 : 1;
|
|
5264
|
-
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
5265
|
-
});
|
|
5266
|
-
const changeFeedTotal = deduped.length;
|
|
5267
|
-
const changeFeed = deduped.slice(0, PORTFOLIO_CHANGE_FEED_LIMIT);
|
|
5268
|
-
const feedEmptyState = changeFeedTotal === 0 ? resolveEmptyState(inputs.length, comparableProjectCount) : null;
|
|
5269
|
-
return {
|
|
5270
|
-
changeFeed,
|
|
5271
|
-
changeFeedTotal,
|
|
5272
|
-
feedEmptyState,
|
|
5273
|
-
comparableProjectCount,
|
|
5274
|
-
firstSweepProjectCount
|
|
5275
|
-
};
|
|
5276
|
-
}
|
|
5277
|
-
|
|
5278
5154
|
// ../intelligence/src/provider-trends.ts
|
|
5279
5155
|
function buildProviderTrends(runs2, snapshotsByRunId, limit = 12) {
|
|
5280
5156
|
const recent = [...runs2].sort((a, b) => b.createdAt.localeCompare(a.createdAt)).slice(0, limit).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
@@ -7966,6 +7842,10 @@ async function analyticsRoutes(app) {
|
|
|
7966
7842
|
}));
|
|
7967
7843
|
const projectQueries = app.db.select({ id: queries.id, createdAt: queries.createdAt }).from(queries).where(eq10(queries.projectId, project.id)).all();
|
|
7968
7844
|
const queryCreatedAt = new Map(projectQueries.map((q) => [q.id, q.createdAt]));
|
|
7845
|
+
const mentionShareCompetitors = app.db.select({ domain: competitors.domain }).from(competitors).where(eq10(competitors.projectId, project.id)).all().map((c) => ({
|
|
7846
|
+
domain: c.domain,
|
|
7847
|
+
brandTokens: [brandLabelFromDomain(c.domain)].filter((t) => t.length >= 3)
|
|
7848
|
+
}));
|
|
7969
7849
|
const overall = computeProviderMetric(allSnapshots);
|
|
7970
7850
|
const byProvider = {};
|
|
7971
7851
|
const providers = new Set(allSnapshots.map((s) => s.provider));
|
|
@@ -7976,7 +7856,7 @@ async function analyticsRoutes(app) {
|
|
|
7976
7856
|
const latest = new Date(projectRuns[projectRuns.length - 1].createdAt);
|
|
7977
7857
|
const spanDays = Math.max(1, Math.ceil((latest.getTime() - earliest.getTime()) / 864e5));
|
|
7978
7858
|
const bucketSize = bucketSizeForSpan(spanDays);
|
|
7979
|
-
const buckets = computeBuckets(allSnapshots, projectRuns, bucketSize, queryCreatedAt);
|
|
7859
|
+
const buckets = computeBuckets(allSnapshots, projectRuns, bucketSize, queryCreatedAt, mentionShareCompetitors);
|
|
7980
7860
|
const trend = computeTrend(buckets, "citationRate");
|
|
7981
7861
|
const mentionTrend = computeTrend(buckets, "mentionRate");
|
|
7982
7862
|
const queryChanges = computeQueryChanges(projectQueries, cutoff);
|
|
@@ -8223,7 +8103,7 @@ function computeProviderMetric(snapshots) {
|
|
|
8223
8103
|
mentionedCount
|
|
8224
8104
|
};
|
|
8225
8105
|
}
|
|
8226
|
-
function computeBuckets(snapshots, projectRuns, bucketDays, queryCreatedAt) {
|
|
8106
|
+
function computeBuckets(snapshots, projectRuns, bucketDays, queryCreatedAt, mentionShareCompetitors = []) {
|
|
8227
8107
|
if (projectRuns.length === 0) return [];
|
|
8228
8108
|
const earliest = new Date(projectRuns[0].createdAt);
|
|
8229
8109
|
const latest = new Date(projectRuns[projectRuns.length - 1].createdAt);
|
|
@@ -8260,6 +8140,7 @@ function computeBuckets(snapshots, projectRuns, bucketDays, queryCreatedAt) {
|
|
|
8260
8140
|
queryCount,
|
|
8261
8141
|
mentionRate: metric.mentionRate,
|
|
8262
8142
|
mentionedCount: metric.mentionedCount,
|
|
8143
|
+
mentionShare: computeMentionShareBucketMetric(usable, mentionShareCompetitors),
|
|
8263
8144
|
byProvider
|
|
8264
8145
|
});
|
|
8265
8146
|
}
|
|
@@ -8267,6 +8148,26 @@ function computeBuckets(snapshots, projectRuns, bucketDays, queryCreatedAt) {
|
|
|
8267
8148
|
}
|
|
8268
8149
|
return buckets;
|
|
8269
8150
|
}
|
|
8151
|
+
function computeMentionShareBucketMetric(snapshots, mentionShareCompetitors) {
|
|
8152
|
+
if (mentionShareCompetitors.length === 0) {
|
|
8153
|
+
return { rate: null, projectMentionSnapshots: 0, competitorMentionSnapshots: 0 };
|
|
8154
|
+
}
|
|
8155
|
+
const result = buildMentionShare(
|
|
8156
|
+
snapshots.map((s) => ({
|
|
8157
|
+
projectMentioned: s.resolvedMentioned,
|
|
8158
|
+
answerText: s.answerText
|
|
8159
|
+
})),
|
|
8160
|
+
{ competitors: mentionShareCompetitors }
|
|
8161
|
+
);
|
|
8162
|
+
const projectMentionSnapshots = result.breakdown.projectMentionSnapshots;
|
|
8163
|
+
const competitorMentionSnapshots = result.breakdown.competitorMentionSnapshots;
|
|
8164
|
+
const denominator = projectMentionSnapshots + competitorMentionSnapshots;
|
|
8165
|
+
return {
|
|
8166
|
+
rate: denominator > 0 ? round4(projectMentionSnapshots / denominator) : null,
|
|
8167
|
+
projectMentionSnapshots,
|
|
8168
|
+
competitorMentionSnapshots
|
|
8169
|
+
};
|
|
8170
|
+
}
|
|
8270
8171
|
function computeQueryChanges(projectQueries, cutoff) {
|
|
8271
8172
|
const byDay = /* @__PURE__ */ new Map();
|
|
8272
8173
|
for (const q of projectQueries) {
|
|
@@ -13337,9 +13238,8 @@ async function visibilityStatsRoutes(app) {
|
|
|
13337
13238
|
}
|
|
13338
13239
|
|
|
13339
13240
|
// ../api-routes/src/composites.ts
|
|
13340
|
-
import { eq as eq17, and as and12,
|
|
13241
|
+
import { eq as eq17, and as and12, desc as desc9, sql as sql7, like as like2, or as or4, inArray as inArray9 } from "drizzle-orm";
|
|
13341
13242
|
var TOP_INSIGHT_LIMIT = 5;
|
|
13342
|
-
var PORTFOLIO_RECENT_RUNS_LIMIT = 8;
|
|
13343
13243
|
var SEARCH_HIT_HARD_LIMIT = 50;
|
|
13344
13244
|
var SEARCH_SNIPPET_RADIUS = 80;
|
|
13345
13245
|
var INTEGRATION_SYNC_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -13356,14 +13256,6 @@ async function compositeRoutes(app) {
|
|
|
13356
13256
|
const project = resolveProject(app.db, request.params.name);
|
|
13357
13257
|
const filterLocation = (request.query.location ?? "").trim() || null;
|
|
13358
13258
|
const sinceIso = parseSinceFilter(request.query.since);
|
|
13359
|
-
return reply.send(computeProjectOverview(project, { filterLocation, sinceIso }));
|
|
13360
|
-
});
|
|
13361
|
-
app.get("/portfolio", async (_request, reply) => {
|
|
13362
|
-
return reply.send(buildPortfolioOverview());
|
|
13363
|
-
});
|
|
13364
|
-
function computeProjectOverview(project, opts = {}) {
|
|
13365
|
-
const filterLocation = opts.filterLocation ?? null;
|
|
13366
|
-
const sinceIso = opts.sinceIso ?? null;
|
|
13367
13259
|
const allRunsRaw = app.db.select().from(runs).where(and12(eq17(runs.projectId, project.id), notProbeRun())).orderBy(desc9(runs.createdAt), desc9(runs.id)).all();
|
|
13368
13260
|
const allRuns = allRunsRaw.filter((r) => runMatchesFilters(r, filterLocation, sinceIso));
|
|
13369
13261
|
const totalRuns = allRuns.length;
|
|
@@ -13496,111 +13388,8 @@ async function compositeRoutes(app) {
|
|
|
13496
13388
|
dateRangeLabel: "All time",
|
|
13497
13389
|
contextLabel: `${project.country} / ${project.language.toUpperCase()}`
|
|
13498
13390
|
};
|
|
13499
|
-
return result;
|
|
13500
|
-
}
|
|
13501
|
-
function buildPortfolioOverview() {
|
|
13502
|
-
const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
13503
|
-
const projectRows = app.db.select().from(projects).orderBy(asc2(projects.name)).all();
|
|
13504
|
-
const trackedCountRows = app.db.select({ projectId: queries.projectId, total: sql7`COUNT(*)` }).from(queries).groupBy(queries.projectId).all();
|
|
13505
|
-
const trackedCountByProject = new Map(trackedCountRows.map((r) => [r.projectId, Number(r.total)]));
|
|
13506
|
-
const lastSweepRow = app.db.select({ createdAt: runs.createdAt, finishedAt: runs.finishedAt }).from(runs).where(and12(
|
|
13507
|
-
eq17(runs.kind, RunKinds["answer-visibility"]),
|
|
13508
|
-
notProbeRun(),
|
|
13509
|
-
inArray9(runs.status, [RunStatuses.completed, RunStatuses.partial])
|
|
13510
|
-
)).orderBy(desc9(runs.createdAt), desc9(runs.id)).limit(1).get();
|
|
13511
|
-
const lastSweepAt = lastSweepRow ? lastSweepRow.finishedAt ?? lastSweepRow.createdAt : null;
|
|
13512
|
-
const feedInputs = [];
|
|
13513
|
-
const projectRowDtos = [];
|
|
13514
|
-
const runHistoryById = /* @__PURE__ */ new Map();
|
|
13515
|
-
for (const projectRow of projectRows) {
|
|
13516
|
-
const overview = computeProjectOverview(projectRow);
|
|
13517
|
-
for (const point of overview.runHistory) runHistoryById.set(point.runId, point);
|
|
13518
|
-
const latestVisRunRow = app.db.select().from(runs).where(and12(
|
|
13519
|
-
eq17(runs.projectId, projectRow.id),
|
|
13520
|
-
eq17(runs.kind, RunKinds["answer-visibility"]),
|
|
13521
|
-
notProbeRun()
|
|
13522
|
-
)).orderBy(desc9(runs.createdAt), desc9(runs.id)).limit(1).get();
|
|
13523
|
-
const projectName = projectRow.displayName || projectRow.name;
|
|
13524
|
-
feedInputs.push({
|
|
13525
|
-
projectName,
|
|
13526
|
-
projectSlug: projectRow.name,
|
|
13527
|
-
citationMovement: overview.citationMovement,
|
|
13528
|
-
mentionMovement: overview.mentionMovement,
|
|
13529
|
-
movementComparison: overview.movementComparison,
|
|
13530
|
-
attentionItems: overview.attentionItems,
|
|
13531
|
-
latestRun: latestVisRunRow ? {
|
|
13532
|
-
runId: latestVisRunRow.id,
|
|
13533
|
-
status: latestVisRunRow.status,
|
|
13534
|
-
occurredAt: latestVisRunRow.finishedAt ?? latestVisRunRow.createdAt,
|
|
13535
|
-
error: parseRunError(latestVisRunRow.error)
|
|
13536
|
-
} : null,
|
|
13537
|
-
trackedQueryCount: trackedCountByProject.get(projectRow.id) ?? 0,
|
|
13538
|
-
projectCreatedAt: projectRow.createdAt
|
|
13539
|
-
});
|
|
13540
|
-
const mention = overview.scores.mention;
|
|
13541
|
-
projectRowDtos.push({
|
|
13542
|
-
projectSlug: projectRow.name,
|
|
13543
|
-
projectName,
|
|
13544
|
-
canonicalDomain: projectRow.canonicalDomain,
|
|
13545
|
-
mentionScore: mention.progress ?? 0,
|
|
13546
|
-
mentionTone: mention.tone,
|
|
13547
|
-
mentionedOfTotal: { mentioned: overview.queryCounts.mentionedQueries, total: overview.queryCounts.totalQueries },
|
|
13548
|
-
citedOfTotal: { cited: overview.queryCounts.citedQueries, total: overview.queryCounts.totalQueries },
|
|
13549
|
-
mentionDelta: {
|
|
13550
|
-
gained: overview.mentionMovement.gained,
|
|
13551
|
-
lost: overview.mentionMovement.lost,
|
|
13552
|
-
comparable: overview.movementComparison.comparable
|
|
13553
|
-
},
|
|
13554
|
-
citationDelta: {
|
|
13555
|
-
gained: overview.citationMovement.gained,
|
|
13556
|
-
lost: overview.citationMovement.lost,
|
|
13557
|
-
comparable: overview.movementComparison.comparable
|
|
13558
|
-
},
|
|
13559
|
-
competitorPressureLabel: overview.scores.competitorPressure.value,
|
|
13560
|
-
mentionTrend: mention.trend,
|
|
13561
|
-
lastRunAt: latestVisRunRow ? latestVisRunRow.finishedAt ?? latestVisRunRow.createdAt : null,
|
|
13562
|
-
hasEverRun: latestVisRunRow != null
|
|
13563
|
-
});
|
|
13564
|
-
}
|
|
13565
|
-
const feed = buildPortfolioChangeFeed(feedInputs, generatedAt);
|
|
13566
|
-
const projectById = new Map(projectRows.map((p) => [p.id, p]));
|
|
13567
|
-
const recentRunRows = app.db.select().from(runs).where(and12(eq17(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).orderBy(desc9(runs.createdAt), desc9(runs.id)).limit(PORTFOLIO_RECENT_RUNS_LIMIT).all();
|
|
13568
|
-
const recentRuns = [];
|
|
13569
|
-
for (const run of recentRunRows) {
|
|
13570
|
-
const projectRow = projectById.get(run.projectId);
|
|
13571
|
-
if (!projectRow) continue;
|
|
13572
|
-
const point = runHistoryById.get(run.id);
|
|
13573
|
-
const countable = run.status === RunStatuses.completed || run.status === RunStatuses.partial;
|
|
13574
|
-
const error = parseRunError(run.error);
|
|
13575
|
-
recentRuns.push({
|
|
13576
|
-
runId: run.id,
|
|
13577
|
-
projectName: projectRow.displayName || projectRow.name,
|
|
13578
|
-
projectSlug: projectRow.name,
|
|
13579
|
-
kindLabel: "Answer visibility sweep",
|
|
13580
|
-
status: run.status,
|
|
13581
|
-
createdAt: run.createdAt,
|
|
13582
|
-
startedAt: run.startedAt ?? null,
|
|
13583
|
-
finishedAt: run.finishedAt ?? null,
|
|
13584
|
-
durationMs: run.startedAt && run.finishedAt ? new Date(run.finishedAt).getTime() - new Date(run.startedAt).getTime() : null,
|
|
13585
|
-
mentionedCount: countable && point ? point.mentionedCount : null,
|
|
13586
|
-
citedCount: countable && point ? point.citedCount : null,
|
|
13587
|
-
totalCount: countable && point ? point.totalCount : null,
|
|
13588
|
-
errorSummary: error ? formatRunErrorOneLine(error) : null
|
|
13589
|
-
});
|
|
13590
|
-
}
|
|
13591
|
-
return {
|
|
13592
|
-
generatedAt,
|
|
13593
|
-
lastSweepAt,
|
|
13594
|
-
projectCount: projectRows.length,
|
|
13595
|
-
comparableProjectCount: feed.comparableProjectCount,
|
|
13596
|
-
firstSweepProjectCount: feed.firstSweepProjectCount,
|
|
13597
|
-
changeFeed: feed.changeFeed,
|
|
13598
|
-
changeFeedTotal: feed.changeFeedTotal,
|
|
13599
|
-
feedEmptyState: feed.feedEmptyState,
|
|
13600
|
-
recentRuns,
|
|
13601
|
-
projects: projectRowDtos
|
|
13602
|
-
};
|
|
13603
|
-
}
|
|
13391
|
+
return reply.send(result);
|
|
13392
|
+
});
|
|
13604
13393
|
app.get("/projects/:name/search", async (request, reply) => {
|
|
13605
13394
|
const project = resolveProject(app.db, request.params.name);
|
|
13606
13395
|
const rawQuery = (request.query.q ?? "").trim();
|
|
@@ -14227,7 +14016,6 @@ var SCHEMA_TABLE = {
|
|
|
14227
14016
|
LatestProjectRunDto: latestProjectRunDtoSchema,
|
|
14228
14017
|
LocationContext: locationContextSchema,
|
|
14229
14018
|
NotificationDto: notificationDtoSchema,
|
|
14230
|
-
PortfolioDto: portfolioDtoSchema,
|
|
14231
14019
|
ProjectDto: projectDtoSchema,
|
|
14232
14020
|
ProjectOverviewDto: projectOverviewDtoSchema,
|
|
14233
14021
|
ProjectReportDto: projectReportDtoSchema,
|
|
@@ -17482,17 +17270,6 @@ var routeCatalog = [
|
|
|
17482
17270
|
404: errorResponse("Project not found.")
|
|
17483
17271
|
}
|
|
17484
17272
|
},
|
|
17485
|
-
{
|
|
17486
|
-
method: "get",
|
|
17487
|
-
path: "/api/v1/portfolio",
|
|
17488
|
-
summary: "Cross-project portfolio: what changed, recent runs, project state",
|
|
17489
|
-
description: 'One call for the dashboard Portfolio page and `canonry portfolio`. Returns a server-ordered "what changed" feed (citation/mention gains and losses over each project\'s comparable basket, failed sweeps, critical/high insight echoes, stale-visibility, query-set changes, and never-run projects \u2014 recency then severity), a timestamped recent-runs log with independent mention and cited result counts, and a per-project state table. Probe runs are excluded. `generatedAt` is the freshness anchor for every relative timestamp.',
|
|
17490
|
-
tags: ["intelligence"],
|
|
17491
|
-
parameters: [],
|
|
17492
|
-
responses: {
|
|
17493
|
-
200: jsonResponse("Portfolio overview returned.", "PortfolioDto")
|
|
17494
|
-
}
|
|
17495
|
-
},
|
|
17496
17273
|
{
|
|
17497
17274
|
method: "get",
|
|
17498
17275
|
path: "/api/v1/projects/{name}/overview",
|
|
@@ -18346,7 +18123,7 @@ var canonryLocalRouteCatalog = [
|
|
|
18346
18123
|
method: "post",
|
|
18347
18124
|
path: "/api/v1/projects/{name}/agent/prompt",
|
|
18348
18125
|
summary: "Send a prompt to Aero and stream events back as SSE",
|
|
18349
|
-
description: 'Posts a prompt into the project\'s Aero session and streams `AgentEvent` frames as `text/event-stream`. Each frame is `data: <JSON>\\n\\n`. The server brackets the stream with `{"type":"stream_open"}` and `{"type":"stream_close"}` control frames; `{"type":"error","message":"..."}` surfaces in-stream failures without collapsing the stream. Returns 409 `AGENT_BUSY` if another turn is already in flight for this project. Body field `scope` accepts "all" | "read-only"; omitted defaults to "read-only" (safe dashboard surface). The CLI passes "all" to keep write tools available.',
|
|
18126
|
+
description: 'Posts a prompt into the project\'s Aero session and streams `AgentEvent` frames as `text/event-stream`. Each frame is `data: <JSON>\\n\\n`. The server brackets the stream with `{"type":"stream_open"}` and `{"type":"stream_close"}` control frames; `{"type":"error","message":"..."}` surfaces in-stream failures without collapsing the stream. Returns 409 `AGENT_BUSY` if another turn is already in flight for this project. Body field `scope` accepts "all" | "read-only"; omitted defaults to "read-only" (safe dashboard surface). Body field `profile` accepts "default" | "ads-operator"; omitted keeps the default full Canonry operator surface. The CLI passes "all" to keep write tools available.',
|
|
18350
18127
|
tags: ["agent"],
|
|
18351
18128
|
parameters: [nameParameter],
|
|
18352
18129
|
requestBody: {
|
|
@@ -18371,6 +18148,11 @@ var canonryLocalRouteCatalog = [
|
|
|
18371
18148
|
type: "string",
|
|
18372
18149
|
enum: ["all", "read-only"],
|
|
18373
18150
|
description: 'Tool surface scope. Default "read-only". Set "all" to enable write tools.'
|
|
18151
|
+
},
|
|
18152
|
+
profile: {
|
|
18153
|
+
type: "string",
|
|
18154
|
+
enum: ["default", "ads-operator"],
|
|
18155
|
+
description: 'Tool profile. Default "default". Set "ads-operator" to use the narrower ads SaaS operator surface plus the ads context tool.'
|
|
18374
18156
|
}
|
|
18375
18157
|
}
|
|
18376
18158
|
}
|
|
@@ -21888,7 +21670,7 @@ async function googleRoutes(app, opts) {
|
|
|
21888
21670
|
|
|
21889
21671
|
// ../api-routes/src/ads.ts
|
|
21890
21672
|
import crypto19 from "crypto";
|
|
21891
|
-
import { eq as eq22, and as and15, asc as
|
|
21673
|
+
import { eq as eq22, and as and15, asc as asc2, gte as gte3, lte as lte2, inArray as inArray11 } from "drizzle-orm";
|
|
21892
21674
|
function statusDto(row) {
|
|
21893
21675
|
if (!row) return { connected: false };
|
|
21894
21676
|
return {
|
|
@@ -22089,7 +21871,7 @@ async function adsRoutes(app, opts) {
|
|
|
22089
21871
|
if (entityId) conditions.push(eq22(adsInsightsDaily.entityId, entityId));
|
|
22090
21872
|
if (from) conditions.push(gte3(adsInsightsDaily.date, from));
|
|
22091
21873
|
if (to) conditions.push(lte2(adsInsightsDaily.date, to));
|
|
22092
|
-
const rows = app.db.select().from(adsInsightsDaily).where(and15(...conditions)).orderBy(
|
|
21874
|
+
const rows = app.db.select().from(adsInsightsDaily).where(and15(...conditions)).orderBy(asc2(adsInsightsDaily.date)).all();
|
|
22093
21875
|
const dtoRows = rows.map((row) => ({
|
|
22094
21876
|
level: row.level,
|
|
22095
21877
|
entityId: row.entityId,
|
|
@@ -25498,7 +25280,7 @@ async function wordpressRoutes(app, opts) {
|
|
|
25498
25280
|
|
|
25499
25281
|
// ../api-routes/src/backlinks.ts
|
|
25500
25282
|
import crypto23 from "crypto";
|
|
25501
|
-
import { and as and20, asc as
|
|
25283
|
+
import { and as and20, asc as asc3, desc as desc14, eq as eq26, sql as sql10 } from "drizzle-orm";
|
|
25502
25284
|
|
|
25503
25285
|
// ../integration-commoncrawl/src/constants.ts
|
|
25504
25286
|
import os2 from "os";
|
|
@@ -26257,7 +26039,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
26257
26039
|
async (request, reply) => {
|
|
26258
26040
|
const project = resolveProject(app.db, request.params.name);
|
|
26259
26041
|
const source = parseSourceParam(request.query.source);
|
|
26260
|
-
const rows = app.db.select().from(backlinkSummaries).where(and20(eq26(backlinkSummaries.projectId, project.id), eq26(backlinkSummaries.source, source))).orderBy(
|
|
26042
|
+
const rows = app.db.select().from(backlinkSummaries).where(and20(eq26(backlinkSummaries.projectId, project.id), eq26(backlinkSummaries.source, source))).orderBy(asc3(backlinkSummaries.queriedAt)).all();
|
|
26261
26043
|
const response = rows.map((r) => ({
|
|
26262
26044
|
release: r.release,
|
|
26263
26045
|
totalLinkingDomains: r.totalLinkingDomains,
|
|
@@ -34222,7 +34004,7 @@ function dedupeStrings(input) {
|
|
|
34222
34004
|
|
|
34223
34005
|
// ../api-routes/src/technical-aeo.ts
|
|
34224
34006
|
import crypto29 from "crypto";
|
|
34225
|
-
import { and as and26, asc as
|
|
34007
|
+
import { and as and26, asc as asc4, count, desc as desc17, eq as eq36, inArray as inArray13 } from "drizzle-orm";
|
|
34226
34008
|
var SURFACEABLE_STATUSES = [RunStatuses.completed, RunStatuses.partial];
|
|
34227
34009
|
function emptyScore(projectName) {
|
|
34228
34010
|
return {
|
|
@@ -34306,7 +34088,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
34306
34088
|
const total = totalRow?.value ?? 0;
|
|
34307
34089
|
const limit = parsePositiveInt(request.query.limit, 100, 500);
|
|
34308
34090
|
const offset = parsePositiveInt(request.query.offset, 0, Number.MAX_SAFE_INTEGER);
|
|
34309
|
-
const orderBy = request.query.sort === "score-desc" ? desc17(siteAuditPages.overallScore) : request.query.sort === "url" ?
|
|
34091
|
+
const orderBy = request.query.sort === "score-desc" ? desc17(siteAuditPages.overallScore) : request.query.sort === "url" ? asc4(siteAuditPages.url) : asc4(siteAuditPages.overallScore);
|
|
34310
34092
|
const rows = app.db.select().from(siteAuditPages).where(where).orderBy(orderBy).limit(limit).offset(offset).all();
|
|
34311
34093
|
const pages = rows.map((row) => ({
|
|
34312
34094
|
url: row.url,
|
|
@@ -35241,7 +35023,7 @@ var IntelligenceService = class {
|
|
|
35241
35023
|
// Backfill must not replay probe runs as if they were real sweeps.
|
|
35242
35024
|
ne5(runs.trigger, RunTriggers.probe)
|
|
35243
35025
|
)
|
|
35244
|
-
).orderBy(
|
|
35026
|
+
).orderBy(asc5(runs.finishedAt)).all();
|
|
35245
35027
|
let startIdx = 0;
|
|
35246
35028
|
let endIdx = allRuns.length;
|
|
35247
35029
|
if (opts?.fromRunId) {
|
|
@@ -35549,6 +35331,8 @@ export {
|
|
|
35549
35331
|
backlinkDomains,
|
|
35550
35332
|
backlinkSummaries,
|
|
35551
35333
|
agentMemory,
|
|
35334
|
+
llmUsageEvents,
|
|
35335
|
+
agentToolEvents,
|
|
35552
35336
|
crawlerEventsHourly,
|
|
35553
35337
|
aiUserFetchEventsHourly,
|
|
35554
35338
|
rawEventSamples,
|