Skip to content

Commit a2adc21

Browse files
committed
fix: parameterize prompt slug in SQL queries, add ownership check to reactivateOverride, use nullish coalescing in updateOverride
1 parent 96e1426 commit a2adc21

File tree

2 files changed

+19
-13
lines changed

2 files changed

+19
-13
lines changed

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.prompts.$promptSlug/route.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,6 +1541,7 @@ function MetricsTab({
15411541
period,
15421542
from,
15431543
to,
1544+
promptSlugs: [prompt.slug],
15441545
responseModels: models.length > 0 ? models : undefined,
15451546
operations: operations.length > 0 ? operations : undefined,
15461547
providers: providers.length > 0 ? providers : undefined,
@@ -1554,7 +1555,7 @@ function MetricsTab({
15541555
<MetricWidget
15551556
widgetKey={`prompt-${prompt.slug}-generations`}
15561557
title="Total"
1557-
query={`SELECT count() AS generations FROM llm_metrics WHERE prompt_slug = '${prompt.slug}'${versionFilter}`}
1558+
query={`SELECT count() AS generations FROM llm_metrics WHERE 1=1${versionFilter}`}
15581559
config={{
15591560
type: "bignumber",
15601561
column: "generations",
@@ -1568,7 +1569,7 @@ function MetricsTab({
15681569
<MetricWidget
15691570
widgetKey={`prompt-${prompt.slug}-tokens`}
15701571
title="Avg input tokens"
1571-
query={`SELECT round(avg(input_tokens)) AS avg_input FROM llm_metrics WHERE prompt_slug = '${prompt.slug}'${versionFilter}`}
1572+
query={`SELECT round(avg(input_tokens)) AS avg_input FROM llm_metrics WHERE 1=1${versionFilter}`}
15721573
config={{
15731574
type: "bignumber",
15741575
column: "avg_input",
@@ -1582,7 +1583,7 @@ function MetricsTab({
15821583
<MetricWidget
15831584
widgetKey={`prompt-${prompt.slug}-cost`}
15841585
title="Avg input cost"
1585-
query={`SELECT avg(input_cost) AS avg_cost FROM llm_metrics WHERE prompt_slug = '${prompt.slug}'${versionFilter}`}
1586+
query={`SELECT avg(input_cost) AS avg_cost FROM llm_metrics WHERE 1=1${versionFilter}`}
15861587
config={{
15871588
type: "bignumber",
15881589
column: "avg_cost",
@@ -1596,7 +1597,7 @@ function MetricsTab({
15961597
<MetricWidget
15971598
widgetKey={`prompt-${prompt.slug}-latency`}
15981599
title="Avg latency"
1599-
query={`SELECT round(avg(duration) / 1000000, 1) AS avg_ms FROM llm_metrics WHERE prompt_slug = '${prompt.slug}'${versionFilter}`}
1600+
query={`SELECT round(avg(duration) / 1000000, 1) AS avg_ms FROM llm_metrics WHERE 1=1${versionFilter}`}
16001601
config={{
16011602
type: "bignumber",
16021603
column: "avg_ms",
@@ -1661,6 +1662,7 @@ function VersionPerformanceSection({
16611662
period,
16621663
from,
16631664
to,
1665+
promptSlugs: [promptSlug],
16641666
responseModels: models.length > 0 ? models : undefined,
16651667
operations: operations.length > 0 ? operations : undefined,
16661668
providers: providers.length > 0 ? providers : undefined,
@@ -1677,7 +1679,7 @@ function VersionPerformanceSection({
16771679
<MetricWidget
16781680
widgetKey={`prompt-${promptSlug}-perf-latency-${versionFilters.join(",")}`}
16791681
title="Latency p50 / p95"
1680-
query={`SELECT timeBucket(), round(quantile(0.5)(duration) / 1000000, 1) AS p50, round(quantile(0.95)(duration) / 1000000, 1) AS p95 FROM llm_metrics WHERE prompt_slug = '${promptSlug}'${versionFilter} GROUP BY timeBucket ORDER BY timeBucket`}
1682+
query={`SELECT timeBucket(), round(quantile(0.5)(duration) / 1000000, 1) AS p50, round(quantile(0.95)(duration) / 1000000, 1) AS p95 FROM llm_metrics WHERE 1=1${versionFilter} GROUP BY timeBucket ORDER BY timeBucket`}
16811683
config={{
16821684
type: "chart",
16831685
chartType: "line",
@@ -1696,7 +1698,7 @@ function VersionPerformanceSection({
16961698
<MetricWidget
16971699
widgetKey={`prompt-${promptSlug}-perf-ttfc-${versionFilters.join(",")}`}
16981700
title="TTFC p50 / p95"
1699-
query={`SELECT timeBucket(), round(quantile(0.5)(ms_to_first_chunk), 1) AS p50, round(quantile(0.95)(ms_to_first_chunk), 1) AS p95 FROM llm_metrics WHERE prompt_slug = '${promptSlug}' AND ms_to_first_chunk > 0${versionFilter} GROUP BY timeBucket ORDER BY timeBucket`}
1701+
query={`SELECT timeBucket(), round(quantile(0.5)(ms_to_first_chunk), 1) AS p50, round(quantile(0.95)(ms_to_first_chunk), 1) AS p95 FROM llm_metrics WHERE ms_to_first_chunk > 0${versionFilter} GROUP BY timeBucket ORDER BY timeBucket`}
17001702
config={{
17011703
type: "chart",
17021704
chartType: "line",
@@ -1716,7 +1718,7 @@ function VersionPerformanceSection({
17161718
<MetricWidget
17171719
widgetKey={`prompt-${promptSlug}-perf-input-tokens-${versionFilters.join(",")}`}
17181720
title="Input tokens p50 / p95"
1719-
query={`SELECT timeBucket(), round(quantile(0.5)(input_tokens)) AS p50, round(quantile(0.95)(input_tokens)) AS p95 FROM llm_metrics WHERE prompt_slug = '${promptSlug}'${versionFilter} GROUP BY timeBucket ORDER BY timeBucket`}
1721+
query={`SELECT timeBucket(), round(quantile(0.5)(input_tokens)) AS p50, round(quantile(0.95)(input_tokens)) AS p95 FROM llm_metrics WHERE 1=1${versionFilter} GROUP BY timeBucket ORDER BY timeBucket`}
17201722
config={{
17211723
type: "chart",
17221724
chartType: "line",
@@ -1735,7 +1737,7 @@ function VersionPerformanceSection({
17351737
<MetricWidget
17361738
widgetKey={`prompt-${promptSlug}-perf-input-cost-${versionFilters.join(",")}`}
17371739
title="Input cost per 1k tokens (p50 / p95)"
1738-
query={`SELECT timeBucket(), prettyFormat(quantile(0.5)(input_cost / input_tokens * 1000), 'costInDollars') AS p50, prettyFormat(quantile(0.95)(input_cost / input_tokens * 1000), 'costInDollars') AS p95 FROM llm_metrics WHERE prompt_slug = '${promptSlug}' AND input_tokens > 0${versionFilter} GROUP BY timeBucket ORDER BY timeBucket`}
1740+
query={`SELECT timeBucket(), prettyFormat(quantile(0.5)(input_cost / input_tokens * 1000), 'costInDollars') AS p50, prettyFormat(quantile(0.95)(input_cost / input_tokens * 1000), 'costInDollars') AS p95 FROM llm_metrics WHERE input_tokens > 0${versionFilter} GROUP BY timeBucket ORDER BY timeBucket`}
17391741
config={{
17401742
type: "chart",
17411743
chartType: "line",
@@ -1755,7 +1757,7 @@ function VersionPerformanceSection({
17551757
<MetricWidget
17561758
widgetKey={`prompt-${promptSlug}-perf-output-tokens-${versionFilters.join(",")}`}
17571759
title="Output tokens p50 / p95"
1758-
query={`SELECT timeBucket(), round(quantile(0.5)(output_tokens)) AS p50, round(quantile(0.95)(output_tokens)) AS p95 FROM llm_metrics WHERE prompt_slug = '${promptSlug}'${versionFilter} GROUP BY timeBucket ORDER BY timeBucket`}
1760+
query={`SELECT timeBucket(), round(quantile(0.5)(output_tokens)) AS p50, round(quantile(0.95)(output_tokens)) AS p95 FROM llm_metrics WHERE 1=1${versionFilter} GROUP BY timeBucket ORDER BY timeBucket`}
17591761
config={{
17601762
type: "chart",
17611763
chartType: "line",
@@ -1774,7 +1776,7 @@ function VersionPerformanceSection({
17741776
<MetricWidget
17751777
widgetKey={`prompt-${promptSlug}-perf-output-cost-${versionFilters.join(",")}`}
17761778
title="Output cost per 1k tokens (p50 / p95)"
1777-
query={`SELECT timeBucket(), prettyFormat(quantile(0.5)(output_cost / output_tokens * 1000), 'costInDollars') AS p50, prettyFormat(quantile(0.95)(output_cost / output_tokens * 1000), 'costInDollars') AS p95 FROM llm_metrics WHERE prompt_slug = '${promptSlug}' AND output_tokens > 0${versionFilter} GROUP BY timeBucket ORDER BY timeBucket`}
1779+
query={`SELECT timeBucket(), prettyFormat(quantile(0.5)(output_cost / output_tokens * 1000), 'costInDollars') AS p50, prettyFormat(quantile(0.95)(output_cost / output_tokens * 1000), 'costInDollars') AS p95 FROM llm_metrics WHERE output_tokens > 0${versionFilter} GROUP BY timeBucket ORDER BY timeBucket`}
17781780
config={{
17791781
type: "chart",
17801782
chartType: "line",
@@ -1795,7 +1797,7 @@ function VersionPerformanceSection({
17951797
<MetricWidget
17961798
widgetKey={`prompt-${promptSlug}-perf-versions-table-${versionFilters.join(",")}`}
17971799
title="Version summary"
1798-
query={`SELECT prompt_version, count() AS calls, round(avg(input_tokens)) AS avg_input_tokens, round(avg(output_tokens)) AS avg_output_tokens, prettyFormat(avg(total_cost), 'costInDollars') AS avg_total_cost, round(quantile(0.5)(duration) / 1000000, 1) AS p50_latency_ms, round(quantile(0.95)(duration) / 1000000, 1) AS p95_latency_ms FROM llm_metrics WHERE prompt_slug = '${promptSlug}'${versionFilter} GROUP BY prompt_version ORDER BY prompt_version DESC`}
1800+
query={`SELECT prompt_version, count() AS calls, round(avg(input_tokens)) AS avg_input_tokens, round(avg(output_tokens)) AS avg_output_tokens, prettyFormat(avg(total_cost), 'costInDollars') AS avg_total_cost, round(quantile(0.5)(duration) / 1000000, 1) AS p50_latency_ms, round(quantile(0.95)(duration) / 1000000, 1) AS p95_latency_ms FROM llm_metrics WHERE 1=1${versionFilter} GROUP BY prompt_version ORDER BY prompt_version DESC`}
17991801
config={{ type: "table", prettyFormatting: true, sorting: [] }}
18001802
{...widgetProps}
18011803
/>

apps/webapp/app/v3/services/promptService.server.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ export class PromptService extends BaseService {
106106
where: { id: overrideVer.id },
107107
data: {
108108
textContent: contentString,
109-
model: data.model || overrideVer.model,
110-
commitMessage: data.commitMessage || overrideVer.commitMessage,
109+
model: data.model ?? overrideVer.model,
110+
commitMessage: data.commitMessage ?? overrideVer.commitMessage,
111111
contentHash,
112112
},
113113
});
@@ -126,6 +126,10 @@ export class PromptService extends BaseService {
126126
throw new ServiceValidationError("Version not found", 404);
127127
}
128128

129+
if (target.promptId !== promptId) {
130+
throw new ServiceValidationError("Version does not belong to this prompt", 400);
131+
}
132+
129133
if (target.source === "code") {
130134
throw new ServiceValidationError(
131135
"Code-sourced versions cannot be reactivated as overrides",

0 commit comments

Comments
 (0)