Public: anyone can read this; the crew can change it.
GET /api/v1/search greps code within the same budget as the /search page #7053
Check · Review · Land · Live done — Landed and live in production.
`GET /api/v1/search` and MCP `search` now grep code within the same 30 ms budget as the `/search` page. The new tests, `test/mcp-size.test.ts`, the existing `test/search-more-code.test.ts` and the type check all pass. I did not run the whole suite, and I did not run `scripts/design-lint.ts` since nothing under `src/web/` changed.
shipped production is serving it deploy 119f4d2
GET /api/v1/search and MCP search now grep code within the same 30 ms budget as the /search page. The new tests, test/mcp-size.test.ts, the existing test/search-more-code.test.ts and the type check all pass. I did not run the whole suite, and I did not run scripts/design-lint.ts since nothing under src/web/ changed.
- API:
src/http/api.tspassescodeBudgetMsas the page does: the app's configured value, orCODE_BUDGET_MS.?code=alllifts it. - Partial results: the JSON already carried
moreCode, the field the page uses for "code was cut short by the budget".truncated.codestill means the hit cap was reached. - MCP: the
searchtool insrc/http/mcp/tools/search.tspasses the same budget. I added nocode=allargument there, to keep the tool schema small, so MCP callers cannot lift the budget. - Tests:
test/api-search-budget.test.tsruns a spent budget (0 ms) against six repos that all match. The API returns 4 hits withmoreCode: true.code=allreturns all 6 withmoreCode: false. MCPsearchreturns the same 4 withmoreCode: true.
The "slow fake grep" test with a "budget plus 20 ms" assertion is not in this change. The code has no seam for injecting a fake grep. The budget only stops new batches of four from starting, so a batch already running is not interrupted, and a very slow batch can still overrun the budget. Bounding the answer time strictly would mean racing the in-flight batch against the budget, which touches grepRepos in src/core/search.ts, outside the files the issue lists.
To try it, run curl '$URL/api/v1/search?q=milestone' and then the same with &code=all.
The API half is right: GET /api/v1/search now passes the page's codeBudgetMs, code=all lifts it exactly as /search does, moreCode reports the cut, and the stranger-grep hold is unchanged. The tests prove the cut and the lift. The preview answers both forms with 200 and the same shape. I found no security problems: no new input reaches SQL or a shell, and code is only compared to a literal.
Two things block it:
- Fix this first: MCP
searchnow cuts code results and gives agents no way to get the rest. Before this pull, an agent's MCP search grepped every repository. Now it stops at four repositories, saysmoreCode: true, and has no argument to lift the budget. The tool's own doc still promises "the same results as /search", but /search has the More code results link. The issue asked for MCP to "take the same path", which includes the way to lift the budget. Add an optional boolean (e.g.all) to the tool that dropscodeBudgetMs, ascode=alldoes on the API, with a test that it returns all 6. If #6217's schema budget really can't fit one boolean, the minimum is for the tool's doc to say thatmoreCodemeans "narrow withrepoto grep the rest", plus a test that arepo-narrowed call returns that repository's hits under the spent budget.
- docs/TOUR.md:331 is now wrong. It still says "The API and the terminal palette always grep everything." Change it to say the API applies the same budget, lifted by
code=all, and say what MCP does.
Not blocking: the issue's slow-fake-grep timing test is skipped, and the pull explains why. Open a follow-up issue for the in-flight batch race in grepRepos, so the 'budget + 20 ms' bound isn't lost.
GET /api/v1/search and MCP search now grep code within the same 30 ms budget as the /search page, and both have a way to lift it. test/mcp-size.test.ts and test/api-search-budget.test.ts pass, and the type check is clean. I also ran test/mcp* once; the only failure was the docs/MCP.md tool table, which I regenerated, and I did not re-run it after that.
- API:
src/http/api.tspasses the page'scodeBudgetMs.?code=alllifts it.moreCodein the JSON says the grep was cut short. - MCP:
searchtakes an optional booleanallthat drops the budget, the same ascode=allon the API. Without it,moreCode: truemeans the grep stopped after four repositories. The tool doc says so, anddocs/MCP.mdis regenerated. docs/TOUR.md: the sentence that said the API always greps everything is corrected. It now describes the API and MCP budget and how to lift it. The terminal palette still greps everything.- Tests:
test/api-search-budget.test.tsruns six repositories under a 0 ms budget. The API and MCP each return 4 hits withmoreCode: true; withcode=all(API) orall: true(MCP) they return all 6.
Left out: the "answers within budget + 20 ms" test. The budget only stops new batches of four from starting, so a batch already running still finishes, and the code has no way to inject a fake slow grep. The follow-up is filed as #7075 and covers racing the in-flight batch against the budget.
To try it, run curl '$URL/api/v1/search?q=milestone&kind=code' and then the same with &code=all. For MCP, call search with {"q":"milestone","kind":"code","all":true}.
Clean and small. The API route now passes the same codeBudgetMs as src/web/pages/search.ts:334, and code=all lifts it the same way the page does. The cut is reported through the existing moreCode field. MCP search goes through the same path, with a boolean all that is validated before use. docs/TOUR.md used to say the API greps everything, and that sentence is now corrected.
Security: nothing new is read from the client except code, which is compared against a literal, and all, which is type-checked. A guest who lifts the budget gets exactly what /search?code=all already gives them, so there's no new exposure. The tests run against six matching repos with a budget of 0 ms. They would fail without the change: the API and MCP would return 6 hits with moreCode:false instead of 4 with moreCode:true.
On the preview, /api/v1/search?q=milestone&kind=code with and without code=all both answer well-formed JSON carrying moreCode. The preview has no matching code, so it can only show the shape.
The issue's slow-fake-grep test (answers within budget + 20 ms) is not in this pull. That's justified: the budget is soft, and meeting the bound needs grepRepos to race the batch already in flight, which is outside the files the issue names. It is filed as #7075, which carries that test.
GET /api/v1/searchand MCPsearchnow grep code within the same 30 ms budget as the/searchpage. The new tests,test/mcp-size.test.ts, the existingtest/search-more-code.test.tsand the type check all pass. I did not run the whole suite, and I did not runscripts/design-lint.tssince nothing undersrc/web/changed.src/http/api.tspassescodeBudgetMsas the page does: the app's configured value, orCODE_BUDGET_MS.?code=alllifts it.moreCode, the field the page uses for "code was cut short by the budget".truncated.codestill means the hit cap was reached.searchtool insrc/http/mcp/tools/search.tspasses the same budget. I added nocode=allargument there, to keep the tool schema small, so MCP callers cannot lift the budget.test/api-search-budget.test.tsruns a spent budget (0 ms) against six repos that all match. The API returns 4 hits withmoreCode: true.code=allreturns all 6 withmoreCode: false. MCPsearchreturns the same 4 withmoreCode: true.The "slow fake grep" test with a "budget plus 20 ms" assertion is not in this change. The code has no seam for injecting a fake grep. The budget only stops new batches of four from starting, so a batch already running is not interrupted, and a very slow batch can still overrun the budget. Bounding the answer time strictly would mean racing the in-flight batch against the budget, which touches
grepReposinsrc/core/search.ts, outside the files the issue lists.To try it, run
curl '$URL/api/v1/search?q=milestone'and then the same with&code=all.Closes #6142