feat(tasks): return artifact download URL + agent env guidance - #74118
Conversation
👀 Auto-assigned reviewersThese soft owners were skipped because they only have minor changes here. Nothing blocks merge, so self-assign if you'd like a look:
Soft owners come from each directory's |
The artifacts/finalize_upload response now includes a presigned download URL for each finalized artifact, so callers (e.g. the upload_artifact agent tool) can link to the uploaded file directly. The URL is minted per response via object_storage.get_presigned_url (mirroring the existing log_url presign pattern) and is deliberately not written back to the run manifest, since presigned URLs are time-limited. The new serializer field is optional, so responses that reuse TaskRunArtifactResponseSerializer without a URL are unaffected. Note: products/tasks/frontend/generated/* must be regenerated with `hogli build:openapi` to pick up the new field. I could not run codegen in this sandbox — schema generation requires a running Postgres/dev stack that wasn't provisioned. Generated-By: PostHog Code Task-Id: d3757c3d-15f3-485a-b4f3-d0b760f78963
Fold the AGENTS.md environment guidance (previously PR #74021) into this PR: treat the sandbox as a full dev environment — install missing deps and run tests/Storybook/the app to verify — worded as a method so it holds on a constrained sandbox too. Generated-By: PostHog Code Task-Id: d3757c3d-15f3-485a-b4f3-d0b760f78963
b5f1969 to
5478b91
Compare
🤖 CI report✅ Bundle size — no changeUncompressed size of every built Total: 65.43 MiB · no change No file changed by more than 1000 B. Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report ✅ Eager graph — within budgetHow 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
🟢 Largest files eagerly shipped from
|
| 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 |
|---|---|
| 285.3 KiB | ../node_modules/.pnpm/posthog-js@1.409.2/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 |
| 231.4 KiB | ../node_modules/.pnpm/posthog-js@1.409.2/node_modules/posthog-js/dist/module.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.2 KiB | src/lib/api.ts |
| 94.7 KiB | ../packages/quill/packages/quill/dist/index.js |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 90.6 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/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
✅ Toolbar bundle — eager 2.19 MiB within budget
What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.
| Metric | Size | Δ vs base | Budget |
|---|---|---|---|
| Eager (shipped) entry + static imports |
2.19 MiB · 17 files | no change | ████░░░░░░ 38.3% of 5.72 MiB |
| Deferred (lazy) | 2.08 MiB · 33 files | no change | n/a — loads on demand |
Loader dist/toolbar.js |
1.1 KiB | no change | █░░░░░░░░░ 5.8% of 19.5 KiB |
Largest eagerly-shipped chunks
| Size | File |
|---|---|
| 717.8 KiB | dist/toolbar/toolbar-app-2QFKEBT7.css |
| 551.1 KiB | dist/toolbar/chunk-chunk-5FDJUV5A.js |
| 484.6 KiB | dist/toolbar/chunk-chunk-QCKKTYHY.js |
| 133.6 KiB | dist/toolbar/chunk-chunk-UDBJ4EGL.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-T5KY5WYR.js |
| 71.0 KiB | dist/toolbar/toolbar-app-DBANC7W5.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-27JL52RE.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-QFZQEUXB.js |
| 20.9 KiB | dist/toolbar/chunk-chunk-HWIVFWBZ.js |
| 12.2 KiB | dist/toolbar/chunk-chunk-PIK3PADE.js |
Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile
✅ Dist folder size — 🔺 +636 B (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1371.02 MiB · 🔺 +636 B (+0.0%)
finalize_task_run_artifact_uploads now returns a presigned url on each response entry (not persisted to the manifest), so the idempotent-path test can no longer assert the response equals the stored manifest verbatim. Compare the stored fields separately from the URL and assert a URL is present, preserving the idempotency guarantee (existing entry returned unchanged, no re-head/re-tag). Generated-By: PostHog Code Task-Id: d3757c3d-15f3-485a-b4f3-d0b760f78963
|
stamphog does not review bot-authored PRs — removing the |
Problem
Two related agent-plumbing changes, combined into one PR:
artifacts/finalize_upload, but the response returned no link to the file. The agent-sideupload_artifacttool therefore couldn't hand back a URL, so an agent that produced a file had no way to reference or share it. This adds the backend half; the tool-side change is in a companion PostHog/code PR (Fix charts in dashboards #3862).AGENTS.mdimplied the sandbox was a restricted patch-editing environment ("use flox when available" with no counter-signal), which led agents to assume they couldn't run tests/Storybook/the app and to ship visual changes with a written caveat instead of actually verifying them. This reframes it as a full dev environment.Changes
Backend — presigned artifact URL
finalize_task_run_artifact_uploadsnow mints a presigned download URL per finalized artifact and attaches it to the response (url), mirroring the existinglog_urlpresign pattern (object_storage.get_presigned_url).urlfield toTaskRunArtifactResponseSerializer(withhelp_text). It's optional, so other responses reusing this serializer are unaffected — the field is simply omitted when absent.products/tasks/frontend/generated/*,services/mcp/src/api/generated.ts) were regenerated to pick up the field.AGENTS.md — environment guidance
How did you test this?
I (Claude) linted the Python (
ruffclean). The generated-type update was produced by the repo's OpenAPI codegen automation. I could not run the Django test suite in this sandbox (it needs a Postgres/dev stack that wasn't provisioned); the existingtest_upload_artifacts*suite inproducts/tasks/backend/tests/covers the finalize path and is where aurlassertion belongs. The companion PostHog/code PR'supload_artifactunit test (which asserts the URL is surfaced) passes there.Automatic notifications
Docs update
🤖 Agent context
Autonomy: Fully autonomous
Authored by Claude Code. Originated from a session where an agent (me) uploaded a Storybook screenshot via
upload_artifactand found the tool returns no URL — and, separately, had earlier wrongly assumed it couldn't run Storybook at all. The two fixes address both: return a URL from the backend, and correct the environment guidance that produced the wrong assumption. Both were previously separate PRs; folded together here at the maintainer's request (the AGENTS.md change was #74021, now closed).Design note: chose a presigned URL (matching the existing
log_urlpattern) over a durable auth-gated endpoint URL — immediately usable by the agent and publicly fetchable, with expiry as the tradeoff, noted in the code and the companion docs. Invoked the/improving-drf-endpointsskill before touching the serializer (optional field +help_text, no enum-collision-prone name). The backend change stays within the isolatedtasksproduct (facade + presentation), crosses no product boundary, and touches nocontracts.py. Companion: PostHog/code#3862.Created with PostHog Code from an inbox report.