Repository navigation
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
cevheri
left a comment
There was a problem hiding this comment.
Thanks @Maaz2212, the core of this works, and it follows the plan agreed in #1422. We ran it end to end in a browser through Docs > AI Describe, on a Postgres database with 60 tables of 601 columns and an LLM stub that answers like llama.cpp:
- the request dropped from about 1 MB to 24 KB and the description came back;
- with a small-context model the refusal is tried once, not three times, and the banner shows a readable sentence instead of the raw provider text;
- a two-table schema sends the same request as before.
Three things before merge.
1. The context-length sentence must not say "schema" on every route
- Cause: the new branch in
createErrorResponse(src/lib/api/errors.ts) is shared by Explain, Query Safety and the agent routes, so all of them now answer "The schema is too large for the configured model's context." Explain with a long plan and no schema said exactly that. The wording came from our issue text, so that one is on us. - Change: use a neutral sentence, for example "The request is too large for the configured model's context.", and keep
retryable: false. - Done when:
tests/unit/api-errors.test.tsexpects the new sentence andretryable: false.
2. The route must refuse every oversized input, not only a string schemaContext
- Cause:
src/app/api/ai/describe-schema/route.tschecks the length only whenschemaContextis a string, and putsdatabaseTypeinto the system prompt with no check at all. Measured against the stub:{"schemaContext": ["x".repeat(200000)]}reached the provider (200,666 bytes upstream), and so did{"schemaContext": "t", "databaseType": "x".repeat(200000)}(200,664 bytes). #1422 step 2 asks the route to refuse an over-budget request before calling the provider. - Change: before
createLLMProvideris called, answer 400 with a plain sentence whenschemaContextis not a string, or whendatabaseTypeis present and is not a short string (for example up to 64 characters). Then keep your length check and its 413 as they are. - Done when: route tests in
tests/api/ai/describe-schema.test.tssend an arrayschemaContextand a 200,000-characterdatabaseType, each gets 400, and each asserts the provider was never created.
3. The 413 test must check what its name says
- Cause: the test named "refuses ... without calling provider" asserts the 413 but never checks the provider. #1422 asks for that assertion.
- Change: add
expect(mockCreateLLMProvider).not.toHaveBeenCalled()to it. - Done when: that assertion is in the test, and it fails if the guard is moved after the provider call.
Please run bun run test:coverage && bun run coverage:check again after the change. One small note on the PR body: a table that does not fit loses all of its columns (name and column count are kept), not only its trailing ones. The code is fine, only the description differs. We will file the follow-ups ourselves (tables past the 50th are still dropped without the note, and the user is never told the docs cover part of the schema).
|
Sure @cevheri i am doing this right now and fixing the PR description also. |
…on describe-schema route
cevheri
left a comment
There was a problem hiding this comment.
Thanks, all three points are done and CI is green. One thing we missed last round:
- Data Profiler loses its AI summary on larger schemas.
DataProfiler.tsx:92sends the wholeconn.schemaContext(the full schema as JSON) to this route. Above 30,000 characters the route now answers 413, andDataProfiler.tsx:110returns without a word, so the summary silently disappears where it worked on main.
Change: send only the profiled table's schema from Data Profiler, and show the error if the route still refuses.
Done when: a test with a schema context over 30,000 characters still gets a profiler summary request under the limit. - PR body. It still quotes the old "schema is too large" sentence and does not mention the new 400 checks on
schemaContextanddatabaseType.
Done when: the body matches the code.
|
Hey @cevheri Done! I’ve updated
Also updated the PR description to match the latest changes. Ready for another look! |
cevheri
left a comment
There was a problem hiding this comment.
Thanks @Maaz2212, the PR body now matches the code and the profiler shows the route's error. One thing is left from the last review.
- Send the profiled table's schema, not a name match.
Cause:resolveTableSchemaContextinDataProfiler.tsxparsesschemaContextand matches on the bare table name first, so withpublic.usersandapp.usersin the schema, profilingapp.userssendspublic.users. The new test does not catch it: replacing the helper call with the rawschemaContextkeeps all profiler tests green, because the 30,000 slice alone keeps the request under the limit.
Change: the component already hastableSchema, resolved on the full path. SendJSON.stringify(tableSchema)and drop theschemaContextparsing.
Done when: a test with two schemas that each hold auserstable sends only the profiled one's columns, and that test fails if the helper goes back to the rawschemaContext.
Closes #1422
Problem
When generating database documentation for wide schemas via Docs > AI Describe,
DatabaseDocs.tsxforwarded every column of up to 50 tables without a length budget. On databases with wide tables (e.g. 60 tables × 600 columns), this produced payloads exceeding 400,000 tokens. The LLM provider rejected the request with a context length error, whichisRetryableErrortreated as a retryable stream error—triggering 3 wasteful server-side retries before displaying raw provider error text.Additionally, the Data Profiler previously forwarded the entire multi-table database schema (
conn.schemaContext) to/api/ai/describe-schema, causing profiler requests on larger databases to exceed the context budget and silently fail without displaying an error.Summary of Changes
Shared Budget Constant & Helper (
src/lib/llm/types.ts):MAX_SCHEMA_CONTEXT_CHARS = 30_000as a single shared source of truth for both the client and the route.isContextLengthError(error)matching llama.cpp's"exceeds the available context size"error message.isRetryableError()to returnfalsewhenisContextLengthError(error)is true, halting the server retry loop immediately on attempt 1.Client-Side Truncation (
src/components/DatabaseDocs.tsx):schemaContextrespectingMAX_SCHEMA_CONTEXT_CHARS."\n\n[Note: Schema was truncated to fit model context limit]") and separator lengths from the budget upfront, guaranteeing that the serialized context never exceeds the budget.Table: name (N rows) - [M columns omitted for length]) to maximize schema coverage before falling back to dropping subsequent tables.Data Profiler Single-Table Scoping & Error Visibility (
src/components/DataProfiler.tsx):Route Guards & Validation (
src/app/api/ai/describe-schema/route.ts):schemaContextis a string (HTTP 400 if missing or not a string).databaseTypeis a short string up to 64 characters (HTTP 400 if invalid or oversized).schemaContextexceedingMAX_SCHEMA_CONTEXT_CHARSwith HTTP413 Payload Too Large.createLLMProvider()is called.Neutral Error Mapping (
src/lib/api/errors.ts):LLMStreamErroris caused by a context-length refusal, maps it to HTTP 502 withretryable: falseand the neutral copy:"The request is too large for the configured model's context."(shared cleanly across Describe Schema, Explain, and Query Safety routes).Tests
tests/unit/llm/retry.test.ts: Verified that context-length errors fail immediately without retrying (1 attempt), while standard stream errors are still retried up tomaxAttempts(3 attempts).tests/api/ai/describe-schema.test.ts: Verified HTTP 413 rejection for oversized contexts without calling provider, HTTP 400 rejection for non-string contexts and oversizeddatabaseTypewithout calling provider, and 200 for valid requests.tests/components/DatabaseDocs.test.tsx: Verified that wide schemas generate a boundedschemaContextwith the truncation notice and strictly withinMAX_SCHEMA_CONTEXT_CHARS.tests/components/DataProfiler.test.tsx: Verified that large schema contexts (>30,000 characters) still send profiler requests within the budget, and verified that route refusal errors are displayed in the AI Analysis card.tests/unit/api-errors.test.ts: Verified that context-length stream errors return 502 withretryable: falseand the neutral error message.bun run typecheckandbun run format.