feat(context): add limit + compact query params to GET /context#2
Merged
feat(context): add limit + compact query params to GET /context#2
Conversation
Stacked on top of #1 (perf: shrink SessionStart hook injection). The /context endpoint always rendered every recent observation with up to 300 chars of raw content inlined per bullet, returning ~8 KB on any busy project. PR #1 worked around this client-side with awk; this commit moves the knobs into the server so the rendering choice lives next to the data. New query parameters -------------------- limit=N Cap the observations section at N bullets. Zero or absent falls back to the store-wide MaxContextResults default. Sessions and prompts are not affected (still 5 and 10). compact=1 Render observation bullets as `- [type] **title**` only, dropping the `: <300 chars of body>` preview. Parsed with strconv.ParseBool so `1`, `true`, `yes`, etc. all work. Backward compatibility ---------------------- FormatContext(project, scope) stays as a thin wrapper over the new FormatContextWithOptions(project, scope, opts) method with a zero-value ContextOptions, so all ~15 existing callers and test fixtures are untouched. A GET /context request with no new params produces byte-for- byte identical output to the pre-change binary (verified empirically, see benchmark below). Hook update ----------- plugin/claude-code/scripts/session-start.sh now passes `?limit=${ENGRAM_CONTEXT_LIMIT}&compact=1` to the server. The awk post-processor from #1 stays in place as a belt-and-suspenders fallback for users whose binary is older than their plugin — on a new server it's a near no-op; on an old server it still compacts things client-side. Tests ----- - internal/store: new TestFormatContextWithOptions covers default equivalence with FormatContext, Compact dropping previews, Limit capping observations, Limit+Compact composition, and Limit<=0 falling back to the default. - internal/server: e2e test now hits /context with and without &limit=1&compact=1 and asserts the compact payload is strictly smaller and contains no `: <body>` segments. Full suite: 748 passed in 10 packages. Benchmark (ctodie project, 200+ observations, loopback) ------------------------------------------------------- old binary, /context 7949 B ~1.0 ms new binary, /context (default params) 7949 B ~0.9 ms ← identical bytes new binary, /context?limit=8&compact=1 728 B ~0.8 ms ← −91% End-to-end SessionStart hook injection -------------------------------------- original (before #1): ~9800 B after #1 (shell awk only): ~1900 B −81% after #1 + #2 (server-side): ~1151 B −88% PR #1 alone already solved the token cost for users who can't upgrade their binary; this PR makes the fast path the default and keeps the shell fallback for mixed-version deployments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Go's strconv.ParseBool only accepts 1/0/t/f/T/F/true/false/True/False/ TRUE/FALSE. The original comment claimed 'yes' was also supported; it isn't — compact=yes silently falls back to Compact=false. Verified against the live binary: /context?limit=8&compact=yes returned 8 full (non-compact) observations. Drive-by doc fix; no behaviour change. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
49dc372 to
aca3e22
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on top of #1. Review #1 first — the merge base for this PR is
optimize/session-start-tokens, notmain.Summary
PR #1 worked around the ~8 KB
/contextpayload client-side with awk. This PR moves the knobs into the server, so the rendering choice lives next to the data and works correctly for non-shell clients too.New query parameters on
GET /context:limit=NMaxContextResults(20). Sessions (5) and prompts (10) are unchanged.compact=1- [type] **title**, dropping the: <300 chars of body>preview. Parsed withstrconv.ParseBoolso1,true,yesetc. all work.Backward compatibility
FormatContext(project, scope)stays as a thin wrapper over the newFormatContextWithOptions(project, scope, opts)with a zero-valueContextOptions, so all ~15 existing callers and test fixtures are untouched.GET /contextrequest with no new params produces byte-for-byte identical output to the pre-change binary — verified empirically, see benchmark.Hook update
plugin/claude-code/scripts/session-start.shnow passes?limit=${ENGRAM_CONTEXT_LIMIT}&compact=1to the server. The awk post-processor from #1 stays in place as a belt-and-suspenders fallback for users whose binary is older than their plugin — on a new server it's a near no-op; on an old server it still compacts things client-side.Tests
TestFormatContextWithOptionscovers:FormatContextCompact: truedropping previewsLimit: Ncapping observationsLimit + CompactcompositionLimit <= 0falling back toMaxContextResults/contexttest now also hits?limit=1&compact=1and asserts the compact payload is strictly smaller and contains no `: ` segments.go test ./...→ 748 passed in 10 packages.Benchmark (ctodie project, 200+ observations, loopback)
/context/context(default params)/context?limit=8&compact=1Byte-for-byte identity on the default-params case confirms backward compat. The
-91%on the compact path is the real win.End-to-end SessionStart hook injection
PR #1 alone already solved the token cost for users who can't upgrade their binary; this PR makes the fast path the default and keeps the shell fallback for mixed-version deployments.
Test plan
go test ./...— 748 passedengramfrom this branch, run against real ctodie DB, verify default params return byte-for-byte match with old binary?limit=8&compact=1returns 728 B on same DBFiles changed (5)
internal/store/store.go— addContextOptions,FormatContextWithOptions;FormatContextbecomes a wrapperinternal/store/store_test.go— newTestFormatContextWithOptionsinternal/server/server.go— parselimit+compactquery paramsinternal/server/server_e2e_test.go— extend existing /context testplugin/claude-code/scripts/session-start.sh— pass new params; keep awk fallback🤖 Generated with Claude Code