feat(prompts): Fetch prompts by label#71509
Conversation
🦔 Hogbox preview · ✅ ready▶ Open the preview
commit |
🤖 CI report
|
| File | Size | Δ vs base |
|---|---|---|
posthog-app/src/scenes/hog-functions/HogFunctionScene.js |
47.2 KiB | 🟢 -14.9 KiB (-24.0%) |
posthog-app/_parent/products/tracing/frontend/TracingScene.js |
84.8 KiB | 🟢 -13.4 KiB (-13.6%) |
exporter/src/exporter/scenes/ExporterDashboardScene.js |
275.4 KiB | 🔺 +8.3 KiB (+3.1%) |
posthog-app/_parent/products/engineering_analytics/frontend/scenes/EngineeringAnalyticsTeamScene.js |
8.2 KiB | 🔺 +8.2 KiB (new) |
render-query/src/render-query/render-query.js |
21.32 MiB | 🔺 +5.1 KiB (+0.0%) |
posthog-app/_parent/products/engineering_analytics/frontend/scenes/EngineeringAnalyticsScene.js |
70.2 KiB | 🔺 +3.3 KiB (+5.0%) |
posthog-app/_parent/products/review_hog/frontend/CodeReviewScene.js |
51.3 KiB | 🔺 +2.4 KiB (+4.9%) |
exporter/src/exporter/scenes/ExporterNotebookScene.js |
3.10 MiB | 🟢 -1.4 KiB (-0.0%) |
Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report
✅ Eager graph — within budget
How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.
| Root | Eager (shipped) | Δ vs base | Budget |
|---|---|---|---|
entry (logged-out pages, app bootstrap)src/index.tsx |
1.23 MiB · 22 files | 🔺 +125 B (+0.0%) | ███░░░░░░░ 28.6% of 4.29 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
8.15 MiB · 2,987 files | 🔺 +6.7 KiB (+0.1%) | █████████░ 88.1% of 9.25 MiB |
🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
Largest files eagerly shipped from src/index.tsx
| Size | File |
|---|---|
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 24.6 KiB | ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js |
| 6.3 KiB | ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js |
| 4.5 KiB | ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js |
| 3.9 KiB | ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js |
| 1.4 KiB | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.3 KiB | src/RootErrorBoundary.tsx |
| 912 B | ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js |
| 789 B | src/scenes/ChunkLoadErrorBoundary.tsx |
| 762 B | src/index.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 281.3 KiB | ../node_modules/.pnpm/posthog-js@1.404.0/node_modules/posthog-js/dist/rrweb.js |
| 267.7 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 235.5 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 223.2 KiB | ../node_modules/.pnpm/posthog-js@1.404.0/node_modules/posthog-js/dist/module.js |
| 164.0 KiB | src/queries/validators.js |
| 154.3 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 105.8 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 93.3 KiB | ../packages/quill/packages/quill/dist/index.js |
Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479
✅ Dist folder size — 🔺 +10.86 MiB (+0.8%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1333.77 MiB · 🔺 +10.86 MiB (+0.8%)
ℹ️ MCP UI apps size — 31 app(s), 16603.1 KB JS
Built size of each MCP UI app (main.js + styles.css).
| App | JS | CSS |
|---|---|---|
| debug | 599.5 KB | 187.4 KB |
| action | 457.8 KB | 187.4 KB |
| action-list | 564.3 KB | 187.4 KB |
| cohort | 456.8 KB | 187.4 KB |
| cohort-list | 563.3 KB | 187.4 KB |
| email-template | 456.6 KB | 187.4 KB |
| error-details | 472.4 KB | 187.4 KB |
| error-issue | 457.5 KB | 187.4 KB |
| error-issue-list | 564.2 KB | 187.4 KB |
| experiment | 561.5 KB | 187.4 KB |
| experiment-list | 565.1 KB | 187.4 KB |
| experiment-results | 563.2 KB | 187.4 KB |
| feature-flag | 567.1 KB | 187.4 KB |
| feature-flag-list | 570.9 KB | 187.4 KB |
| feature-flag-testing | 461.0 KB | 187.4 KB |
| insight-actors | 562.1 KB | 187.4 KB |
| invite-email-preview | 456.0 KB | 187.4 KB |
| llm-costs | 559.5 KB | 187.4 KB |
| session-recording | 458.6 KB | 187.4 KB |
| session-summary | 463.9 KB | 187.4 KB |
| survey | 458.4 KB | 187.4 KB |
| survey-global-stats | 562.2 KB | 187.4 KB |
| survey-list | 565.0 KB | 187.4 KB |
| survey-stats | 562.2 KB | 187.4 KB |
| trace-span | 457.2 KB | 187.4 KB |
| trace-span-list | 564.2 KB | 187.4 KB |
| workflow | 457.1 KB | 187.4 KB |
| workflow-list | 563.7 KB | 187.4 KB |
| query-results | 745.0 KB | 187.4 KB |
| render-ui | 825.6 KB | 187.4 KB |
| visual-review-snapshots | 461.6 KB | 187.4 KB |
⚠️ Playwright — 2 failed
🎭 Playwright report · View test results →
❌ 2 failed tests:
- view results, pause, resume, and ship (chromium)
- golden creation flow: click-to-create → filter → Enable anyway → flips to enabled (chromium)
These issues are not necessarily caused by your changes.
Annoyed by this section? Help fix flakies and failures and it will go green!
⚠️ Backend coverage — 81.0% of changed backend lines covered — 22 uncovered
🧪 Backend test coverage
Patch coverage — changed backend lines (products + core): ████████████████░░░░ 81.0% (94 / 116)
| File | Patch | Uncovered changed lines |
|---|---|---|
products/ai_observability/backend/models/llm_prompt.py |
23.1% | 172–174, 176–177, 179–182, 184 |
posthog/storage/llm_prompt_cache.py |
67.6% | 171–174, 176–183 |
🤖 Agents: add a test covering the lines above, or note why under "How did you test this code?". Machine-readable gap list: the patch-coverage artifact on this run (gh run download 29569480349 -n patch-coverage), or the coverage-data block at the end of this comment.
Per-product line coverage (touched products)
| Product | Coverage | Lines |
|---|---|---|
platform_features |
██░░░░░░░░░░░░░░░░░░ 12.1% |
7 / 58 |
batch_exports |
████████░░░░░░░░░░░░ 39.7% |
8,416 / 21,225 |
demo |
███████████░░░░░░░░░ 56.2% |
1,497 / 2,663 |
warehouse_sources_queue |
████████████░░░░░░░░ 59.2% |
148 / 250 |
tasks |
█████████████░░░░░░░ 67.1% |
25,926 / 38,648 |
data_tools |
██████████████░░░░░░ 70.0% |
63 / 90 |
ai_gateway |
███████████████░░░░░ 75.0% |
9 / 12 |
signals |
████████████████░░░░ 79.1% |
19,037 / 24,073 |
data_modeling |
████████████████░░░░ 80.0% |
4,834 / 6,045 |
cdp |
████████████████░░░░ 80.7% |
3,118 / 3,864 |
wizard |
████████████████░░░░ 82.5% |
772 / 936 |
notebooks |
█████████████████░░░ 84.8% |
6,903 / 8,141 |
cohorts |
█████████████████░░░ 86.2% |
4,065 / 4,717 |
agent_platform |
█████████████████░░░ 86.4% |
3,807 / 4,405 |
actions |
█████████████████░░░ 86.6% |
717 / 828 |
product_tours |
█████████████████░░░ 87.5% |
1,266 / 1,447 |
exports |
██████████████████░░ 88.4% |
6,904 / 7,813 |
visual_review |
██████████████████░░ 88.5% |
5,565 / 6,287 |
business_knowledge |
██████████████████░░ 88.5% |
4,400 / 4,969 |
conversations |
██████████████████░░ 89.0% |
16,164 / 18,167 |
mcp_analytics |
██████████████████░░ 89.2% |
2,514 / 2,819 |
dashboards |
██████████████████░░ 89.3% |
5,841 / 6,540 |
engineering_analytics |
██████████████████░░ 89.3% |
5,407 / 6,053 |
error_tracking |
██████████████████░░ 89.6% |
9,731 / 10,862 |
alerts |
██████████████████░░ 90.0% |
3,655 / 4,063 |
streamlit_apps |
██████████████████░░ 90.4% |
2,499 / 2,764 |
stamphog |
██████████████████░░ 90.4% |
3,503 / 3,874 |
slack_app |
██████████████████░░ 90.6% |
9,511 / 10,503 |
links |
██████████████████░░ 90.6% |
183 / 202 |
marketing_analytics |
██████████████████░░ 90.8% |
11,514 / 12,684 |
product_analytics |
██████████████████░░ 91.3% |
5,757 / 6,304 |
mcp_store |
██████████████████░░ 91.8% |
3,685 / 4,012 |
managed_migrations |
██████████████████░░ 91.9% |
908 / 988 |
data_warehouse |
██████████████████░░ 92.1% |
18,220 / 19,780 |
notifications |
███████████████████░ 92.7% |
1,031 / 1,112 |
web_analytics |
███████████████████░ 92.7% |
13,535 / 14,597 |
workflows |
███████████████████░ 92.8% |
5,477 / 5,904 |
ai_observability |
███████████████████░ 92.8% |
14,916 / 16,077 |
surveys |
███████████████████░ 92.9% |
5,689 / 6,122 |
posthog_ai |
███████████████████░ 93.2% |
1,322 / 1,418 |
tracing |
███████████████████░ 93.3% |
2,447 / 2,624 |
approvals |
███████████████████░ 93.3% |
3,395 / 3,640 |
reminders |
███████████████████░ 93.4% |
468 / 501 |
early_access_features |
███████████████████░ 93.8% |
848 / 904 |
legal_documents |
███████████████████░ 94.1% |
1,568 / 1,667 |
endpoints |
███████████████████░ 94.1% |
8,606 / 9,143 |
revenue_analytics |
███████████████████░ 94.5% |
3,598 / 3,809 |
skills |
███████████████████░ 94.5% |
2,881 / 3,049 |
messaging |
███████████████████░ 94.5% |
2,530 / 2,677 |
review_hog |
███████████████████░ 94.6% |
6,788 / 7,173 |
logs |
███████████████████░ 95.3% |
9,572 / 10,044 |
experiments |
███████████████████░ 95.7% |
24,421 / 25,531 |
replay_vision |
███████████████████░ 95.7% |
13,483 / 14,084 |
growth |
███████████████████░ 95.8% |
2,837 / 2,960 |
annotations |
███████████████████░ 96.2% |
732 / 761 |
feature_flags |
███████████████████░ 96.3% |
16,172 / 16,794 |
warehouse_sources |
███████████████████░ 96.4% |
262,618 / 272,387 |
user_interviews |
███████████████████░ 96.4% |
2,242 / 2,325 |
access_control |
███████████████████░ 96.8% |
849 / 877 |
data_catalog |
███████████████████░ 97.2% |
2,117 / 2,179 |
customer_analytics |
███████████████████░ 97.2% |
7,480 / 7,698 |
analytics_platform |
████████████████████ 98.0% |
2,102 / 2,145 |
metrics |
████████████████████ 98.2% |
2,404 / 2,448 |
pulse |
████████████████████ 98.4% |
2,012 / 2,044 |
live_debugger |
████████████████████ 99.2% |
613 / 618 |
field_notes |
████████████████████ 99.4% |
158 / 159 |
Report-only. Patch coverage = changed backend lines covered vs origin/master. Sorted lowest first.
Known gaps: lines covered only by Temporal tests show as uncovered; core line numbers may drift if master changed the same file.
⚠️ MCP snapshots — 1 updated (1 modified, 0 added, 0 deleted)
Snapshots: MCP unit test snapshots updated
Changes: 1 snapshots (1 modified, 0 added, 0 deleted)
What this means:
- Snapshots have been automatically updated to match current output
Next steps:
- Review the changes to ensure they're intentional
- If unexpected, investigate what caused the output to change
✅ Django migration risk — no migrations to analyze
No Django migrations need risk analysis.
|
Reviews (1): Last reviewed commit: "feat(aio): fetch prompts by label" | Re-trigger Greptile |
Adds ?label= to the prompt fetch endpoint, resolving through HyperCache with a per-label cache entry. Label moves, creates, and deletes clear the entry via model signals — a pointer change never touches LLMPrompt rows, so the existing invalidation could not cover it. The fetch event gains prompt_label so 'what was production serving at time X' is answerable from the event stream.
A cache fill racing a label-move invalidation can store an already-stale resolution the generation marker cannot detect. Label entries now use a 60s TTL (own HyperCache instance over the same keys) and stay out of S3, so any stale fill self-heals within a minute; signals remain the fast path.
Fetching writes miss sentinels under caller-controlled cache keys, so impossible label names are rejected before any cache touch. Also makes the label 404 message cover the missing-prompt case.
c15b5c9 to
74bda4b
Compare
|
|
||
| if label is not None: | ||
| label_key = prompt_label_cache_key(team.id, prompt_name, label) | ||
| labeled_prompt = llm_prompts_label_hypercache.get_from_cache(label_key) |
There was a problem hiding this comment.
Should we make this fetch skip the object storage?
There was a problem hiding this comment.
Yep, will do in a follow up!
|
|
||
|
|
||
| class LLMPromptGetByNameQuerySerializer(LLMPromptFetchQuerySerializer): | ||
| label = serializers.CharField( # type: ignore[assignment] |
There was a problem hiding this comment.
We should make this aware of the constraints from validate_prompt_label_name_value
Problem
#70862 added prompt labels (movable pointers to versions) and the endpoints to manage them, but there is no way to fetch a prompt through a label yet. Until that exists, moving a label has no effect on the apps that consume prompts.
Changes
Adds
?label=productionto the prompt fetch endpoint. The response is the version the label points to, plus alabelfield showing what was resolved. Stacked on #70862.?label=onGET .../llm_prompts/name/{name}/, mutually exclusive with?version=(400 if both are passed){team}:{name}:label:{label}). We cache the resolved prompt content, so a warm fetch is two Redis reads (the latest entry for metadata, then the label entry) with no Postgres lookupLLMPromptLabelclear that cache entry whenever a label is created, moved, or deletedprompt_labelproperty on the$llm_prompt_fetchedeventlabelparameterDesign notes:
How did you test this code?
New tests in
test_llm_prompt.py, all through the public API with the cache in the loop: fetching by label after a move returns the new version (this test fails if the invalidation breaks, and it caught a real gap during development), a label created after a cached 404 works immediately, label+version together returns 400, and fetches 404 after label delete and after prompt archive. Full prompt API + cache suites pass locally (119 tests), mypy clean on changed files.