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

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`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

opened this

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.ts passes codeBudgetMs as the page does: the app's configured value, or CODE_BUDGET_MS. ?code=all lifts it.
  • Partial results: the JSON already carried moreCode, the field the page uses for "code was cut short by the budget". truncated.code still means the hit cap was reached.
  • MCP: the search tool in src/http/mcp/tools/search.ts passes the same budget. I added no code=all argument there, to keep the tool schema small, so MCP callers cannot lift the budget.
  • Tests: test/api-search-budget.test.ts runs a spent budget (0 ms) against six repos that all match. The API returns 4 hits with moreCode: true. code=all returns all 6 with moreCode: false. MCP search returns the same 4 with moreCode: 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.

Closes #6142

commented

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.ts passes codeBudgetMs as the page does: the app's configured value, or CODE_BUDGET_MS. ?code=all lifts it.
  • Partial results: the JSON already carried moreCode, the field the page uses for "code was cut short by the budget". truncated.code still means the hit cap was reached.
  • MCP: the search tool in src/http/mcp/tools/search.ts passes the same budget. I added no code=all argument there, to keep the tool schema small, so MCP callers cannot lift the budget.
  • Tests: test/api-search-budget.test.ts runs a spent budget (0 ms) against six repos that all match. The API returns 4 hits with moreCode: true. code=all returns all 6 with moreCode: false. MCP search returns the same 4 with moreCode: 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.

Changes requested — before the latest push

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:

  1. Fix this first: MCP search now 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, says moreCode: 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 drops codeBudgetMs, as code=all does 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 that moreCode means "narrow with repo to grep the rest", plus a test that a repo-narrowed call returns that repository's hits under the spent budget.
  1. 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.

commented

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.ts passes the page's codeBudgetMs. ?code=all lifts it. moreCode in the JSON says the grep was cut short.
  • MCP: search takes an optional boolean all that drops the budget, the same as code=all on the API. Without it, moreCode: true means the grep stopped after four repositories. The tool doc says so, and docs/MCP.md is 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.ts runs six repositories under a 0 ms budget. The API and MCP each return 4 hits with moreCode: true; with code=all (API) or all: 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}.

Approved

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.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs