feat(kb): storage usage bar with byte cap on the KB card - #1108
Merged
Merged
Conversation
Fold KB storage usage into the documents-list response so the agent's knowledge-base card can show how much of the byte cap is in use. Backend: - Add KbUsage model (engine, storedBytes, reservedBytes, cap, elevated) to DocumentsListResponse. - _resolve_kb_usage reads the KB_Record once: managed KBs report their bytes and the binding effective_cap (min of owner tier and per-KB ceiling); legacy S3-Vectors KBs are uncapped (cap=null). Best-effort so a record-read failure never breaks the documents list. Frontend: - Usage bar on the KB card: 'X of Y used' for managed KBs, green/yellow/red at <75/75-90/>=90% of the cap; legacy KBs show 'X stored', always green, no denominator. Tests: backend route tests for managed/legacy/failure paths; frontend component specs for the thresholds and the uncapped legacy case.
philmerrell
added a commit
that referenced
this pull request
Sep 15, 2026
`_resolve_kb_usage` interpolated `assistant_id` — a user-controlled path parameter — straight into a `logger.warning` f-string, so `\r`/`\n` in it could forge additional log lines (CodeQL `py/log-injection`, alert #864, medium). New in this release: the sink arrived with the KB storage usage bar (8fb4f8f, #1108), on a branch parallel to the #1098 sweep that sanitized every other instance — so the release was about to ship a regression against a rule it enforces elsewhere. Fixed to that sweep's own convention: `%s` lazy formatting with `scrub_log()` on each user-influenced value. Scanned every logger call this release ADDED for the same shape; the rest carry exceptions, ints, or already-scrubbed values. The pre-existing f-string logger calls elsewhere in the tree are deliberately left alone — that is a sweep, not release-branch work. Backend suite: 8626 passed, 3 skipped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 15, 2026
Merged
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.
What
Shows a storage usage bar on each agent's knowledge-base card so users can see how much of their managed-KB byte cap they are consuming — part of keeping managed-KB storage cost visible (Req 12.11).
The cap
There are two configured limits (per-owner tier: 100 MB standard / 1 GB elevated; per-KB ceiling: 500 MB). The binding one is
effective_cap = min(owner tier, per-KB ceiling), already computed inbyte_cap.py. Since it is one KB per agent this phase, that single number is what the bar shows against.Backend
KbUsagemodel (engine,storedBytes,reservedBytes,cap,elevated) added toDocumentsListResponse— folded into the existingGET /assistants/{id}/documentsresponse, no extra round-trip._resolve_kb_usagereads the KB_Record once. Managed → reports bytes +effective_cap; legacy S3-Vectors →cap: null(uncapped), zeroed counters. Best-effort: a record-read failure returnsnullrather than failing the documents list.elevatedis READ fromelevatedByteCap, never written.Frontend
X of Y used, fill turns green < 75%, yellow 75–90%, red ≥ 90%.X storedwith a small green sliver — no misleading full/empty bar.Tests
tests/routes/test_documents.py): managed-with-cap, elevated flag, legacy-uncapped, and the read-failure-doesn't-break-the-list path. Run locally — all green; adjacent byte-cap/chunk-inspector route tests still green; ruff clean.knowledge-base-section.component.spec.ts): green/yellow/red thresholds, reserved-bytes counted, uncapped-legacy, render + create-mode gating.Verification note
Backend tests were run locally (green). The frontend spec was not runnable locally on this host (fresh worktree, and the borrowed node_modules store broke type resolution) — relying on CI to run the Angular suite. Not deployed.