Skip to content

Commit ca2bacd

Browse files
committed
merge: base-misc review fixes (M2, M10a, H8, H13, M10r, ai-help, sweep-cron gate)
2 parents 3f1eec6 + 237f01a commit ca2bacd

14 files changed

Lines changed: 84 additions & 15 deletions
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: fix
4+
---
5+
6+
Triggering a task whose id contains "dashboard-agent" is no longer subject to the smaller chat request size limit, so larger payloads go through as expected.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: fix
4+
---
5+
6+
Health reports no longer show as "fresh" when the underlying data is actually older than the freshness window.

apps/webapp/app/presenters/v3/reports/ReportPresenter.server.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@ import {
66
type UnkeyCache,
77
} from "@internal/cache";
88
import { type AuthenticatedEnvironment } from "~/services/apiAuth.server";
9+
import { HEALTH_THRESHOLDS } from "./health/health-core";
910
import { REPORT_REGISTRY, type ReportLoader } from "./report-registry";
1011
import { type ReportViewModel } from "./report-view-model";
1112

1213
const DEFAULT_PERIOD = "1h";
1314

14-
/** How long a finished report stays reusable. */
15-
export const REPORT_CACHE_TTL_MS = 90_000;
15+
/**
16+
* How long a finished report stays reusable. Capped at the liveness fresh window so a
17+
* cached report can never render "fresh" while its telemetry is already stale.
18+
*/
19+
export const REPORT_CACHE_TTL_MS = HEALTH_THRESHOLDS.liveness.freshMs;
1620

1721
/** How many report, environment and period triples one instance keeps. */
1822
const REPORT_CACHE_MAX_ENTRIES = 500;

apps/webapp/app/presenters/v3/reports/health/health-messages.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const FINDING_REASONS: Record<string, string> = {
3434
"flow/unknown": "flow can't be assessed — the telemetry is stale",
3535
"flow/flow_unmeasured": "flow can't be assessed — the queue depth couldn't be measured",
3636
"execution/healthy": "completing normally", // collapsed
37-
"execution/healthy@expanded": "the runs that DO start are fine",
37+
"execution/healthy@expanded": "runs are executing normally",
3838
// liveness is telemetry freshness
3939
"liveness/fresh": "fresh — telemetry current, updated {age} ago",
4040
"liveness/lagging": "lagging — telemetry last updated {age} ago",

apps/webapp/app/routes/projects.$projectRef.ai-help.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
3838
const query = url.searchParams.get("q");
3939

4040
if (!query) {
41-
return new Response("No query", { status: 404 });
41+
return new Response("No query", { status: 400 });
4242
}
4343

4444
const newUrl = new URL(

apps/webapp/app/services/dashboardAgentBodyCap.server.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ const INGRESS_SLACK_BYTES = 8 * 1024;
1616

1717
export const DASHBOARD_AGENT_MAX_INGRESS_BYTES = MAX_MESSAGE_BODY_BYTES + INGRESS_SLACK_BYTES;
1818

19-
const AGENT_PATH = /\/dashboard-agent(\/|$)/;
19+
// The agent's own routes only: the `/api/v1/dashboard-agent/…` endpoints and the
20+
// `/…/env/<env>/dashboard-agent…` chat resources. Anchored so a task named
21+
// `dashboard-agent` (`/api/v1/tasks/dashboard-agent/trigger`) is not capped.
22+
const AGENT_PATH = /^\/api\/v1\/dashboard-agent(\/|$)|\/env\/[^/]+\/dashboard-agent(\/|$)/;
2023

2124
/** Methods that can carry one. GET and HEAD cannot, and streaming them would be wasted work. */
2225
const BODY_METHODS = new Set(["POST", "PUT", "PATCH", "DELETE"]);

apps/webapp/app/v3/commonWorker.server.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ function initializeWorker() {
3939

4040
logger.debug(`👨‍🏭 Initializing common worker at host ${env.COMMON_WORKER_REDIS_HOST}`);
4141

42+
// Only schedule the agent maintenance cron where the agent is actually set up. Otherwise
43+
// its sweeps hit a missing schema and drip a dead-letter entry every run.
44+
const dashboardAgentConfigured =
45+
env.DASHBOARD_AGENT_ENABLED === "1" || Boolean(env.DASHBOARD_AGENT_DATABASE_URL);
46+
4247
const worker = new RedisWorker({
4348
name: "common-worker",
4449
redisOptions,
@@ -152,8 +157,7 @@ function initializeWorker() {
152157
"dashboardAgent.maintenance": {
153158
schema: CronSchema,
154159
visibilityTimeoutMs: 60_000 * 5,
155-
cron: "*/5 * * * *",
156-
jitterInMs: 30_000,
160+
...(dashboardAgentConfigured ? { cron: "*/5 * * * *", jitterInMs: 30_000 } : {}),
157161
retry: {
158162
maxAttempts: 1,
159163
},

apps/webapp/app/v3/detectQueryTables.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ export function detectQueryTables(query: string, allowedTableNames: Set<string>)
103103
visitSelectSet(tableExpr as SelectSetQuery);
104104
}
105105
}
106+
// The `ON expr` can embed a SELECT that reads a real table, e.g.
107+
// `JOIN x ON id IN (SELECT … FROM runs)`.
108+
scanForSubqueries(node.constraint);
106109
if (node.next_join) visitJoin(node.next_join);
107110
}
108111

apps/webapp/test/__snapshots__/reportRenderParity.test.ts.snap

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/webapp/test/dashboardAgentBodyCap.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,17 @@ describe("the dashboard agent's ingress cap", () => {
148148
expect(response.status).toBe(200);
149149
expect(buffered()).toBe(size);
150150
});
151+
152+
it("does not cap a task whose id is literally dashboard-agent", async () => {
153+
const { url, buffered } = await listen();
154+
const size = DASHBOARD_AGENT_MAX_INGRESS_BYTES + 1024;
155+
156+
const response = await fetch(`${url}/api/v1/tasks/dashboard-agent/trigger`, {
157+
method: "POST",
158+
body: "x".repeat(size),
159+
});
160+
161+
expect(response.status).toBe(200);
162+
expect(buffered()).toBe(size);
163+
});
151164
});

0 commit comments

Comments
 (0)