chore(agent): move agent runtime to a packages/agent workspace - #104123
charlesvien wants to merge 11 commits into
Conversation
🤖 CI report🚨 Trunk lane — universal laneThis PR is assigned to the universal lane. It cannot merge in parallel with other PRs, so it can take longer to merge. Ask dev-ex if you think this is wrong. ✅ Complexity (TypeScript) — cleanCyclomatic complexity above the limit in changed typescript files (10 for production files, 15 for test files). Warn only: worth simplifying when you next touch these functions.
|
| First copy | Second copy | Lines | Tokens |
|---|---|---|---|
posthog/hogql/database/schema/information_schema.py:1653 |
posthog/hogql/database/schema/information_schema.py:1750 |
11 | 71 |
⚠️ Duplication (TypeScript) — 47 new duplicated blocks (worst 463 tokens)
New TypeScript code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.
| First copy | Second copy | Lines | Tokens |
|---|---|---|---|
packages/agent/packages/agent/src/sagas/test-fixtures.ts:10 |
packages/agent/packages/agent/src/test/fixtures/api.ts:9 |
59 | 463 |
packages/agent/packages/agent/src/adapters/claude/claude-agent.streamed-text.test.ts:1 |
packages/agent/packages/agent/src/adapters/claude/claude-agent.task-notification.test.ts:1 |
41 | 310 |
packages/agent/packages/agent/src/adapters/claude/claude-agent.streamed-text.test.ts:43 |
packages/agent/packages/agent/src/adapters/claude/claude-agent.task-notification.test.ts:38 |
52 | 262 |
products/desktop/apps/code/vite-main-plugins.mts:622 |
products/desktop/apps/code/vite.main.config.mts:541 |
48 | 202 |
frontend/src/products.tsx:1262 |
products/customer_analytics/manifest.tsx:101 |
16 | 194 |
products/desktop/apps/code/vite-main-plugins.mts:244 |
products/desktop/apps/code/vite.main.config.mts:168 |
41 | 193 |
packages/agent/packages/agent/src/adapters/claude/claude-agent.permission-mode.test.ts:17 |
packages/agent/packages/agent/src/adapters/claude/claude-agent.slash-command.test.ts:14 |
27 | 189 |
packages/agent/packages/agent/src/server/agent-server.test.ts:4084 |
packages/agent/packages/agent/src/server/agent-server.test.ts:4185 |
40 | 189 |
packages/agent/packages/agent/src/server/question-relay.test.ts:928 |
packages/agent/packages/agent/src/server/question-relay.test.ts:980 |
30 | 181 |
packages/agent/packages/agent/src/server/agent-server.test.ts:192 |
packages/agent/packages/agent/src/test/mocks/claude-sdk.ts:85 |
15 | 175 |
packages/agent/packages/agent/src/sagas/test-fixtures.ts:73 |
packages/agent/packages/agent/src/test/fixtures/api.ts:63 |
37 | 173 |
packages/agent/packages/agent/src/adapters/claude/claude-agent.slash-command.test.ts:44 |
packages/agent/packages/agent/src/adapters/claude/claude-agent.turn-queue.test.ts:50 |
32 | 162 |
packages/agent/packages/git/src/gh.ts:47 |
packages/agent/packages/git/src/git-exec.ts:43 |
36 | 161 |
packages/agent/packages/agent/src/adapters/claude/claude-agent.streamed-text.test.ts:437 |
packages/agent/packages/agent/src/adapters/claude/claude-agent.streamed-text.test.ts:691 |
26 | 153 |
packages/agent/packages/agent/src/server/question-relay.test.ts:694 |
packages/agent/packages/agent/src/server/question-relay.test.ts:739 |
24 | 153 |
packages/agent/packages/agent/src/server/question-relay.test.ts:694 |
packages/agent/packages/agent/src/server/question-relay.test.ts:774 |
24 | 153 |
packages/agent/packages/enricher/src/call-detector.ts:810 |
packages/agent/packages/enricher/src/call-detector.ts:867 |
33 | 137 |
packages/agent/packages/enricher/src/variant-detector.ts:582 |
packages/agent/packages/enricher/src/variant-detector.ts:722 |
28 | 124 |
packages/agent/packages/agent/src/adapters/claude/session/jsonl-hydration.ts:133 |
packages/agent/packages/agent/src/sagas/resume-saga.ts:168 |
21 | 120 |
packages/agent/packages/agent/src/server/agent-server.configure-environment.test.ts:9 |
packages/agent/packages/agent/src/server/gateway-env.ts:14 |
19 | 120 |
packages/agent/packages/agent/src/sagas/resume-saga.ts:217 |
packages/agent/packages/agent/src/sagas/resume-saga.ts:239 |
25 | 113 |
packages/agent/packages/harness/src/extensions/posthog-provider/oauth.ts:55 |
products/desktop/packages/core/src/oauth/oauth.ts:437 |
11 | 108 |
packages/agent/packages/enricher/src/call-detector.ts:814 |
packages/agent/packages/enricher/src/call-detector.ts:1051 |
27 | 107 |
packages/agent/packages/enricher/src/call-detector.ts:782 |
packages/agent/packages/enricher/src/call-detector.ts:1021 |
21 | 104 |
packages/agent/packages/enricher/src/enrich-source.ts:87 |
packages/agent/packages/enricher/src/wrapper-integration.test.ts:40 |
16 | 103 |
packages/agent/packages/agent/src/server/agent-server.ts:3061 |
packages/agent/packages/agent/src/server/agent-server.ts:3457 |
19 | 101 |
packages/agent/packages/enricher/src/call-detector.ts:1196 |
packages/agent/packages/enricher/src/variant-detector.ts:24 |
19 | 101 |
packages/agent/packages/enricher/src/call-detector.ts:794 |
packages/agent/packages/enricher/src/call-detector.ts:856 |
14 | 98 |
packages/agent/packages/enricher/src/call-detector.ts:1214 |
packages/agent/packages/enricher/src/variant-detector.ts:42 |
12 | 95 |
packages/agent/packages/enricher/src/call-detector.ts:239 |
packages/agent/packages/enricher/src/call-detector.ts:290 |
26 | 93 |
packages/agent/packages/enricher/src/call-detector.ts:315 |
packages/agent/packages/enricher/src/call-detector.ts:347 |
12 | 89 |
packages/agent/packages/agent/src/adapters/claude/session/jsonl-hydration.ts:196 |
packages/agent/packages/agent/src/sagas/resume-saga.ts:219 |
21 | 88 |
packages/agent/packages/agent/src/server/pi-agent-server.ts:815 |
products/desktop/packages/ui/src/features/pi-sessions/piMcpPermission.ts:10 |
19 | 86 |
packages/agent/packages/agent-contracts/src/domain-types.ts:110 |
products/desktop/packages/api-client/src/posthog-client.ts:343 |
20 | 85 |
packages/agent/packages/git/src/queries.ts:819 |
products/desktop/packages/core/src/git-interaction/diffStats.ts:10 |
16 | 83 |
packages/agent/packages/agent-contracts/src/cloud-task-models.ts:60 |
products/desktop/packages/core/src/sessions/executionModes.ts:11 |
27 | 81 |
packages/agent/packages/harness/src/extensions/web-access/web-fetch.ts:151 |
products/desktop/apps/code/src/main/services/disk-cache/images.ts:49 |
14 | 81 |
packages/agent/packages/enricher/src/variant-detector.ts:665 |
packages/agent/packages/enricher/src/variant-detector.ts:806 |
14 | 80 |
packages/agent/packages/agent/src/adapters/claude/permissions/permission-handlers.ts:585 |
packages/agent/packages/agent/src/adapters/claude/permissions/permission-handlers.ts:650 |
21 | 78 |
packages/agent/packages/enricher/src/variant-detector.ts:765 |
packages/agent/packages/enricher/src/variant-detector.ts:827 |
16 | 77 |
packages/agent/packages/enricher/src/call-detector.ts:1223 |
packages/agent/packages/enricher/src/variant-detector.ts:53 |
21 | 76 |
packages/agent/packages/agent/src/server/agent-server.ts:5387 |
products/desktop/packages/workspace-server/src/services/agent/agent.ts:2580 |
15 | 74 |
packages/agent/packages/agent/src/adapters/claude/permissions/permission-handlers.ts:610 |
packages/agent/packages/agent/src/adapters/claude/permissions/permission-handlers.ts:681 |
14 | 72 |
packages/agent/packages/agent/src/adapters/claude/permissions/permission-handlers.ts:527 |
packages/agent/packages/agent/src/adapters/claude/permissions/permission-handlers.ts:610 |
14 | 71 |
packages/agent/packages/enricher/src/enriched-result.ts:108 |
packages/agent/packages/enricher/src/enriched-result.ts:155 |
11 | 71 |
packages/agent/packages/enricher/src/variant-detector.ts:269 |
packages/agent/packages/enricher/src/variant-detector.ts:413 |
17 | 71 |
packages/agent/packages/agent/src/adapters/claude/session/jsonl-hydration.ts:155 |
packages/agent/packages/agent/src/sagas/resume-saga.ts:191 |
18 | 70 |
⚠️ Bundle size — 🔺 +6.4 KiB (+0.0%)
Uncompressed size of every built .js bundle, compared against the base branch.
Total: 68.87 MiB · 🔺 +6.4 KiB (+0.0%)
| File | Size | Δ vs base |
|---|---|---|
posthog-app/_parent/products/customer_analytics/frontend/scenes/CustomerAnalyticsAccountScene/CustomerAnalyticsAccountScene.js |
29.6 KiB | 🔺 +5.9 KiB (+25.1%) |
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.57 MiB · 22 files | no change | █████████░ 85.5% of 1.84 MiB |
logged-out boot: index + App + bootApp (preloaded by every page, including /login)src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts |
3.51 MiB · 629 files | 🔺 +47 B (+0.0%) | █████████░ 87.2% of 4.03 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
7.33 MiB · 2,332 files | 🔺 +47 B (+0.0%) | █████████░ 87.9% of 8.34 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/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/layout/navigation-3000/navigationLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/dashboard/dashboardLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/lemon-ui/LemonMarkdown/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/RichContentEditor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/CodeSnippet/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 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
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts 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
🟢 [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/index.tsx |
| 1.3 KiB | src/RootErrorBoundary.tsx |
| 912 B | ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js |
| 854 B | src/scenes/ChunkLoadErrorBoundary.tsx |
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
| Size | File |
|---|---|
| 301.8 KiB | ../node_modules/.pnpm/posthog-js@1.434.14_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 216.0 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 |
| 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 |
| 100.4 KiB | src/lib/api.ts |
| 88.4 KiB | src/products.tsx |
| 69.4 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 40.1 KiB | src/lib/utils/eventUsageLogic.ts |
| 38.7 KiB | ../node_modules/.pnpm/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js |
| 33.9 KiB | ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js |
| 28.4 KiB | src/scenes/scenes.ts |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 301.8 KiB | ../node_modules/.pnpm/posthog-js@1.434.14_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 271.7 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 216.0 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 |
| 153.7 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 |
| 100.4 KiB | src/lib/api.ts |
| 98.5 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 |
| 88.4 KiB | src/products.tsx |
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.16 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.16 MiB · 19 files | no change | ████░░░░░░ 37.7% of 5.72 MiB |
| Deferred (lazy) | 2.10 MiB · 44 files | no change | n/a — loads on demand |
Loader dist/toolbar.js |
1.2 KiB | no change | █░░░░░░░░░ 6.0% of 19.5 KiB |
Largest eagerly-shipped chunks
| Size | File |
|---|---|
| 800.3 KiB | dist/toolbar/toolbar-app-BB53FERC.css |
| 651.5 KiB | dist/toolbar/chunk-chunk-DJ3DVXIY.js |
| 259.4 KiB | dist/toolbar/chunk-chunk-CV2VU6SQ.js |
| 138.3 KiB | dist/toolbar/chunk-chunk-TUPNHXOT.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-FDH2IBXT.js |
| 75.2 KiB | dist/toolbar/toolbar-app-QSMPSM2L.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-TSAL54PB.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-P5FAEBEQ.js |
| 21.0 KiB | dist/toolbar/chunk-chunk-W5LHFGNZ.js |
| 6.8 KiB | dist/toolbar/chunk-chunk-DV7IWQNF.js |
Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile
✅ Dist folder size — 🔺 +72.7 KiB (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 946.04 MiB · 🔺 +72.7 KiB (+0.0%)
ℹ️ Docs preview — preview build triggered
Docs from this PR will be published at posthog.com.
| Project | Preview | Updated (UTC) |
|---|---|---|
| posthog.com | Open preview | Sep 23, 2026, 5:57 AM |
The preview should be ready in about 10 minutes. Open the preview at /handbook/engineering/.
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
|
The PR appears safe to merge; no actionable new issue remains, and both previous findings were manually resolved after their fixes were applied. Reviews (2) · Last reviewed commit: "Fix Electron build and address review fi..." |
🦔 PostHog Review couldn't finish this reviewThe review run failed partway. It will run again on the next push to this pull request. |
|
🦔 Hogbox preview · ✅ ready▶ Open the preview
commit |
bde1d21 to
eee5700
Compare
eee5700 to
fe929fd
Compare
7084d57 to
8383815
Compare
2729ef3 to
c7274cb
Compare
c7274cb to
c4d063d
Compare
|
🕓 This approval covered an earlier revision. There are new visual changes to review in the newer comment below. ✅ Visual changes approved by @charlesvien — baseline updated in 2 new. |
976a63e to
3a7d9a7
Compare
3a7d9a7 to
0a4e3db
Compare
|
🕓 This approval covered an earlier revision. There are new visual changes to review in the newer comment below. ✅ Visual changes approved by @charlesvien — baseline updated in 2 changed. |
b0f2b54 to
704e955
Compare
|
✅ Visual changes approved by @charlesvien — baseline updated in 4 changed. |
be14656 to
e6ebb52
Compare
Problem
Cloud task sandboxes boot
@posthog/agentwithout the desktop app, yet the agent lived inside the desktop app's workspace. It looked like a desktop feature, and desktop's lockfile, lint and CI owned code that ships on its own release line.It could not move one package at a time. Turbo refuses a workspace member outside its root,
@posthog/agentbundlesharness,git,enricherandagent-contractsfrom source, and six desktop packages link the agent from source. So the whole group moves together.Top of the stack (#104121 → #104122 → #104123).
Changes
agent,agent-contracts,enricher,gitandharnessmove into their own pnpm workspace atpackages/agent/, next toagent-shadow. Same toolchain. Its lockfile was seeded from desktop's and resolves the same versions.link:paths instead ofworkspace:*. Nothing is published to npm. The app still builds against the agent at the same commit.products/desktop/scripts/build-agent-workspace.mjsbuilds the agent workspace and writes a stamp file that desktop'sturbo.jsontreats as a global dependency. Turbo cannot see files behind a path link, so without the stamp it would serve stale cache after an agent change.packages/agent. The tag workflow keeps the old path in itsrev-listpathspec so patch numbers keep counting up.desktop-*workflows trigger onpackages/agent/**and build or lint that workspace before desktop's own packages.packages/agent/**to the desktop lanes. The desktop/backend coupling guard still covers the bundled packages.hogli test,hogli ci:preflight,bin/start-desktopand the local sandbox build loop know about the new workspace.Nothing changes for users.
Warning
Two lockfiles now pin the same third-party dependencies.
packages/agent/pnpm-workspace.yamlmirrors desktop's catalog and overrides, so change them together. In desktop, runpnpm build:agentafter touching the agent workspace and before callingturbodirectly.How did you test this code?
pnpm typecheck(which builds and typechecks the agent workspace first),biome ciandpnpm testpass in both workspaces.electron-vite build) and the web host build pass.hogli lint:workflows, thetrunk-impacted-targetstests, the coupling guard cases and the hogli preflight and test runner tests pass.desktop-update-e2e, the live agent e2e job and the local sandbox Docker build. They need CI secrets or Docker. Thedesktop-*workflows cover the first three on this PR.