feat: per-agent compaction configuration overrides#60807
Conversation
Greptile SummaryThis PR adds per-agent compaction configuration overrides by extracting a shared
Confidence Score: 4/5Safe to merge after fixing the reserveTokensFloor gap; all other per-agent compaction fields are correctly threaded. One P1 defect: per-agent reserveTokensFloor is accepted by the schema but silently bypassed at runtime because resolveCompactionReserveTokensFloor does not take an agentId. The rest of the PR — shallow merge, timeout, mode/safeguard, postIndexSync, hooks, settings manager threading — is implemented correctly and consistently. src/agents/pi-settings.ts — resolveCompactionReserveTokensFloor needs an agentId parameter and should delegate to resolveAgentCompaction rather than reading agents.defaults directly.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4509604f6c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (!agentId || !cfg?.agents?.list) { | ||
| return defaults; | ||
| } | ||
| const agentEntry = cfg.agents.list.find((a) => a.id === agentId); |
There was a problem hiding this comment.
Apply agent ID normalization when selecting compaction overrides
resolveSessionAgentIds normalizes agent ids before they flow into compaction resolution, but this lookup compares raw config ids with a.id === agentId. If a configured id differs only by case or normalization (for example Main-Agent vs main-agent), the per-agent compaction block is never found and the code silently falls back to global defaults, so the new override feature does not work for those agents.
Useful? React with 👍 / 👎.
| timeoutMs: resolveRunTimeoutWithCompactionGraceMs({ | ||
| runTimeoutMs: params.timeoutMs, | ||
| compactionTimeoutMs: resolveCompactionTimeoutMs(params.config), | ||
| compactionTimeoutMs: resolveCompactionTimeoutMs(params.config, sessionAgentId), |
There was a problem hiding this comment.
Reuse one compaction timeout source for all run deadlines
This path now uses an agent-specific timeout for the session lock budget, but the same function still derives the abort/grace timer timeout from resolveCompactionTimeoutMs(params.config) later on. When an agent override differs from agents.defaults.compaction.timeoutSeconds, lock expiration and abort grace are computed from different values, which can cause premature aborts or mismatched lock hold windows during compaction.
Useful? React with 👍 / 👎.
1. Normalize agent IDs in resolveAgentCompaction for case-insensitive matching 2. Pass sessionAgentId to all resolveCompactionTimeoutMs calls in attempt.ts
Codex P1 Review — Addressed in 8aa3a2aP1: Agent ID normalization ✅ P1: Consistent compaction timeout in attempt.ts ✅ |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1521439796
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| sessionKey: params.sessionKey, | ||
| sessionFile, | ||
| mode: resolvePostCompactionIndexSyncMode(params.config), | ||
| mode: resolvePostCompactionIndexSyncMode(params.config, params.agentId), |
There was a problem hiding this comment.
Resolve sync mode from session key when agentId is absent
runPostCompactionSideEffects now computes post-index sync mode only from params.agentId, so callers that still provide only sessionKey (for example the owns-compaction timeout path in src/agents/pi-embedded-runner/run.ts) silently fall back to agents.defaults.compaction.postIndexSync. That means per-agent compaction.postIndexSync overrides are ignored for those runs, causing unexpected waiting/skipping behavior after compaction for non-default agents.
Useful? React with 👍 / 👎.
| const watchOptions = { | ||
| ...options, | ||
| nonInteractive: options.watch ? true : options.nonInteractive, | ||
| }; | ||
| const loopCtx = { ...ctx, options: watchOptions }; |
There was a problem hiding this comment.
Recreate prompter with watch-mode nonInteractive settings
Watch mode sets nonInteractive only in watchOptions, but the prompter was already constructed from the original options before this block. As a result, any contribution that uses ctx.prompter.confirm* can still prompt interactively, so doctor watch mode can block on user input instead of running unattended polling loops.
Useful? React with 👍 / 👎.
|
Closing this as duplicate or superseded after Codex automated review. Close #60807 as superseded by the newer active PR #69988. Current main still does not implement per-agent compaction overrides, but #69988 is now the canonical open implementation path for the same core config/runtime feature. #60807 is older, unmerged, based on an older main, and includes unrelated doctor/watch, agent-step, and cron test-harness changes alongside the compaction work. Best possible solution: Close #60807 as superseded by #69988. Keep the canonical per-agent compaction work concentrated in #69988 and land a focused implementation that adds What I checked:
So I’m closing this here and keeping the remaining discussion on the canonical linked item. Codex Review notes: model gpt-5.5, reasoning high; reviewed against e29d3516bf05. |
|
Acknowledged — the assessment is fair. #60807 did pick up some unrelated doctor/watch and cron test-harness changes from an older branch state, and #69988 is a cleaner focused implementation of the same Closing was the right call. I'll move support and any production validation context over to #69988. |
Summary
Closes #57174
Allow individual agents to override global
agents.defaults.compactionsettings, enabling different compaction tuning per agent based on model context window size.Motivation
Currently, compaction config is only available at
agents.defaultslevel. In multi-agent setups with different model providers (e.g., Opus 1M, GLM-5 200K, GPT-4o 128K), a singlereserveTokensvalue is suboptimal — models with larger context windows waste tokens on overly aggressive compaction, while smaller-context models may not compact aggressively enough.Changes
Schema & Types
zod-schema.compaction.ts— sharedCompactionConfigSchema(extracted from inline definition)AgentEntrySchema— added optionalcompactionfieldAgentConfigtype — addedcompaction?: AgentCompactionConfigAgentDefaultsSchema— now imports shared schema instead of inline definitionRuntime Resolution
resolveAgentCompaction(cfg, agentId)— shallow-merges agent-level compaction over defaultsresolveEffectiveCompaction(cfg, agentId)— public API inpi-settings.tsCall Sites Updated (8 files)
pi-settings.tsapplyPiCompactionSettingsFromConfigaccepts optionalagentIdpi-project-settings.tscreatePreparedEmbeddedPiSettingsManagerthreadsagentIdextensions.tsbuildEmbeddedExtensionFactoriesresolves per-agent mode/safeguard configcompaction-safety-timeout.tsresolveCompactionTimeoutMsacceptsagentIdcompaction-hooks.tsrunPostCompactionSideEffectsand postIndexSync resolve per-agentcompact.tsrun/attempt.tsschema.labels.tsExample Config
Testing
Design Decisions
Shallow merge — agent compaction merges on top of defaults. Nested objects like
qualityGuardandmemoryFlushare fully replaced (not deep-merged) to keep behavior predictable.No new config validation — reuses the exact same
CompactionConfigSchemafor both defaults and per-agent entries, ensuring validation parity.Minimal blast radius — only touches compaction-specific resolution. Other agent-level overrides (model, sandbox, heartbeat) already follow this pattern.