Skip to content

Split search.ts runtime into focused modules - #883

Merged
kody-bot merged 2 commits into
mainfrom
cursor/kody-track-c-search-runtime-split-98c9
Jul 22, 2026
Merged

kody-bot merged 2 commits into
mainfrom
cursor/kody-track-c-search-runtime-split-98c9

Conversation

@kody-bot

@kody-bot kody-bot commented Jul 22, 2026 •

Copy link
Copy Markdown
Member

Summary

Mechanically splits remaining search.ts runtime into focused modules. search.ts becomes a thin barrel; MCP handler registration is thin. Includes the search-format split commits until that lands. No ranking/output changes. No production file under mcp/tools/ exceeds ~1000 lines.

Risk: MEDIUM — mechanical split; search unit tests prove unchanged behavior.

Test plan

  • search-format/search/search-handler/search-hidden-packages unit tests green
  • CI Validate green

Summary by CodeRabbit

  • New Features
    • Added a unified MCP search experience across capabilities, packages, values, integrations, secrets, and retriever results.
    • Added natural-language search, entity detail lookup, and batch entity lookup.
    • Improved relevance with lexical and semantic matching, ranking, and package hydration.
    • Added Markdown and structured result formats with usage guidance, related operations, telemetry, and timing details.
    • Added memory enrichment and remote connector status information where available.
    • Added response-size controls, truncation, warnings, and graceful offline or failure fallbacks.
    • Added clearer package, capability, integration, value, and secret details with actionable usage examples.

@kody-bot
kody-bot marked this pull request as ready for review July 22, 2026 20:41
@coderabbitai

coderabbitai Bot commented Jul 22, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR modularizes the MCP search tool into shared contracts, candidate generation, scoring, data loading, memory enrichment, entity resolution, formatting, response sizing, and tool registration modules. It supports unified query search, single-entity lookup, and batched entity lookup.

Changes

Unified MCP search

Layer / File(s) Summary
Search contracts and formatting primitives
packages/worker/src/mcp/tools/search-types.ts, search-format-types.ts, search-constants.ts, search-format-helpers.ts, search-format.ts
Defines search result, candidate, telemetry, memory, and entity-detail types, shared limits, entity-reference parsing, usage formatting, schedules, and barrel exports.
Candidate generation and reranking
packages/worker/src/mcp/tools/search-candidates.ts, search-descriptors.ts, search-scoring.ts, search-related-capabilities.ts, search-core.ts
Builds descriptors and candidates across entity types, combines lexical and vector package rankings, hydrates package matches, applies task/provider/constraint boosts, and produces unified results.
Data loading and bounded enrichment
packages/worker/src/mcp/tools/search-loaders.ts, search-package-rows.ts, search-memory.ts, search-timing.ts, search-response-size.ts
Loads user-scoped rows and connector statuses, lazily hydrates saved packages, bounds memory retrieval and acknowledgement, records timings, and trims serialized responses.
Entity resolution and result views
packages/worker/src/mcp/tools/search-detail.ts, search-format-detail.ts, search-format-list.ts, search-format-slim.ts
Resolves entity references and renders detailed Markdown, list Markdown, and slim structured matches for supported entity types.
Tool definition and execution
packages/worker/src/mcp/tools/search-tool-definition.ts, search-tool-runner.ts, search-register.ts, search.ts
Defines the Zod input contract, orchestrates query/entity/batch execution, handles errors and telemetry, registers the MCP tool, and re-exports the modular implementation.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant runSearchTool
  participant Loaders
  participant searchUnified
  participant Formatter
  Client->>runSearchTool: submit query or entity reference
  runSearchTool->>Loaders: load registry, rows, and connector statuses
  runSearchTool->>searchUnified: generate and rerank candidates
  searchUnified-->>runSearchTool: matches, intent, telemetry, timings
  runSearchTool->>Formatter: render Markdown and structured content
  Formatter-->>Client: formatted search response
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.03% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main refactor: splitting the search runtime into focused modules.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/kody-track-c-search-runtime-split-98c9

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-883.kody-a99.workers.dev

Worker: kody-pr-883
D1: kody-pr-883-db
KV: kody-pr-883-oauth-kv

Mocks:

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/worker/src/mcp/tools/search-tool-runner.ts`:
- Around line 455-471: The searchConversationIdsWithPreamble tracking in the
includePreamble block grows indefinitely, especially for generated conversation
IDs. Update this state update to bound the stored IDs by retaining only the most
recent configured limit, or restrict tracking to explicitly supplied
conversation IDs, while preserving preamble inclusion behavior.

In `@packages/worker/src/mcp/tools/search.ts`:
- Around line 1-16: Update the search barrel around the search-timing export to
re-export elapsedMs alongside settleWithBudget, preserving both timing helpers
for consumers importing from search.ts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4b9a2f4f-5fe1-447b-9134-bc94a7338083

📥 Commits

Reviewing files that changed from the base of the PR and between 218e768 and 6c5750d.

📒 Files selected for processing (23)
  • packages/worker/src/mcp/tools/search-candidates.ts
  • packages/worker/src/mcp/tools/search-constants.ts
  • packages/worker/src/mcp/tools/search-core.ts
  • packages/worker/src/mcp/tools/search-descriptors.ts
  • packages/worker/src/mcp/tools/search-detail.ts
  • packages/worker/src/mcp/tools/search-format-detail.ts
  • packages/worker/src/mcp/tools/search-format-helpers.ts
  • packages/worker/src/mcp/tools/search-format-list.ts
  • packages/worker/src/mcp/tools/search-format-slim.ts
  • packages/worker/src/mcp/tools/search-format-types.ts
  • packages/worker/src/mcp/tools/search-format.ts
  • packages/worker/src/mcp/tools/search-loaders.ts
  • packages/worker/src/mcp/tools/search-memory.ts
  • packages/worker/src/mcp/tools/search-package-rows.ts
  • packages/worker/src/mcp/tools/search-register.ts
  • packages/worker/src/mcp/tools/search-related-capabilities.ts
  • packages/worker/src/mcp/tools/search-response-size.ts
  • packages/worker/src/mcp/tools/search-scoring.ts
  • packages/worker/src/mcp/tools/search-timing.ts
  • packages/worker/src/mcp/tools/search-tool-definition.ts
  • packages/worker/src/mcp/tools/search-tool-runner.ts
  • packages/worker/src/mcp/tools/search-types.ts
  • packages/worker/src/mcp/tools/search.ts

Comment on lines +455 to +471
const searchConversationIdsWithPreamble = Array.isArray(
statefulAgent.state?.searchConversationIdsWithPreamble,
)
? (statefulAgent.state?.searchConversationIdsWithPreamble ?? [])
: []
const includePreamble =
!args.conversationId ||
!searchConversationIdsWithPreamble.includes(conversationId)
if (includePreamble && typeof statefulAgent.setState === 'function') {
statefulAgent.setState({
...(statefulAgent.state ?? {}),
searchConversationIdsWithPreamble: [
...searchConversationIdsWithPreamble,
conversationId,
],
})
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

searchConversationIdsWithPreamble grows without bound.

Every call with includePreamble true appends conversationId and it is never pruned. Since calls without an explicit conversationId generate a fresh id each time, this array accumulates indefinitely in Durable Object state, steadily inflating persisted state for long-lived agents. Consider capping it (e.g. keep the most recent N ids) or only tracking client-supplied conversation ids.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/worker/src/mcp/tools/search-tool-runner.ts` around lines 455 - 471,
The searchConversationIdsWithPreamble tracking in the includePreamble block
grows indefinitely, especially for generated conversation IDs. Update this state
update to bound the stored IDs by retaining only the most recent configured
limit, or restrict tracking to explicitly supplied conversation IDs, while
preserving preamble inclusion behavior.

Comment on lines +1 to +16
export * from './search-constants.ts'
export { settleWithBudget } from './search-timing.ts'
export type * from './search-types.ts'
export * from './search-package-rows.ts'
export * from './search-descriptors.ts'
export * from './search-scoring.ts'
export * from './search-candidates.ts'
export * from './search-related-capabilities.ts'
export * from './search-core.ts'
export * from './search-memory.ts'
export * from './search-response-size.ts'
export * from './search-loaders.ts'
export * from './search-detail.ts'
export * from './search-tool-definition.ts'
export * from './search-tool-runner.ts'
export * from './search-register.ts'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 1) Detect duplicate exported names across the wildcard-exported search-* modules.
fd -e ts 'search-.*' packages/worker/src/mcp/tools \
  | xargs rg -nP '^\s*export\s+(async\s+)?(function|const|class|type|interface|enum)\s+\w+' \
  | sed -E 's/.*(function|const|class|type|interface|enum)\s+(\w+).*/\2/' \
  | sort | uniq -d

# 2) Find consumers importing from the search.ts barrel to spot dropped symbols (e.g. elapsedMs).
rg -nP "from ['\"].*mcp/tools/search(\.ts)?['\"]" packages/worker/src -g '!**/search-*.ts'

Repository: kentcdodds/kody

Length of output: 153


🏁 Script executed:

#!/bin/bash
set -u

echo "== candidate search files =="
fd -e ts '^search-.*\.ts$' packages/worker/src/mcp/tools | sort

echo
echo "== barrel file =="
cat -n packages/worker/src/mcp/tools/search.ts

echo
echo "== direct consumers of search.ts barrel from packages/worker/src, excluding search-* modules =="
rg -n "from ['\"].*/search(\.ts)?['\"]" packages/worker/src/mcp packages/worker/src/routes packages/worker/src/lib || true

echo
echo "== exports naming probe for wildcard modules (selected common decorators/statements) =="
python3 - <<'PY'
import re, subprocess, pathlib
files = subprocess.check_output(['fd','-e','ts','^search-.*\\.ts$','packages/worker/src/mcp/tools'], text=True).splitlines()
pat = re.compile(r'(?:export\s+(?:const|let|var|function|class|enum|async\s+function)\s+([A-Za-z_$][\w$]*))|(?:(?:type|interface)\s+([A-Za-z_$][\w$]*))')
names={}
for f in files:
    text=pathlib.Path(f).read_text(encoding='utf-8')
    matches=[g for g in pat.findall(text) if g[0]|g[1]]
    for a,b in matches:
        name=a or b
        # ignore inline block-local exports like export { X } from './X.ts'
        if re.search(r'export\s*\{\s*\S*\b'+re.escape(name)+r'\b[^}]*\}', text):
            continue
        names.setdefault(name,[]).append(f)
dups={name:fs for name,fs in names.items() if len(fs)>1}
print("duplicate_export_names:")
for name,fs in sorted(dups.items()):
    print(name, ":", sorted(fs))
print("no_duplicate_export_names_found") if not dups else None
PY

Repository: kentcdodds/kody

Length of output: 3191


🏁 Script executed:

#!/bin/bash
set -u

echo "== direct consumers of search.ts barrel from packages/worker/src, excluding search-* modules (full) =="
rg -n "from ['\"].*['\"]" packages/worker/src/mcp packages/worker/src/lib packages/worker/src/routes packages/worker/src/worker 2>/dev/null | rg "from ['\"].*/search(\.ts)?['\"]" || true

echo
echo "== imports of settleWithBudget/elapsedMs from anywhere =="
rg -n "settleWithBudget|elapsedMs" . --glob '!**/node_modules/**' --glob '!**/dist/**' || true

echo
echo "== exports and import of elapsedMs/settleWithBudget in timing =="
cat -n packages/worker/src/mcp/tools/search-timing.ts | sed -n '1,220p'

Repository: kentcdodds/kody

Length of output: 6254


🏁 Script executed:

#!/bin/bash
set -u

python3 - <<'PY'
from pathlib import Path
import re

files = list(Path('packages/worker/src/mcp/tools').glob('search-*.ts'))
specifiers = set()
names = {}
for path in sorted(files):
    text = path.read_text(encoding='utf-8')
    hits = []
    pat = re.compile(
        r'export\s+(?:async\s+)?(?:function|const|let|var|class|enum|type|interface)\s+([A-Za-z_$][\w$]*)'
        r'|export\s+type\s+([A-Za-z_$][\w$]*)'
        r'|export\s*\{\s*([A-Za-z_$][\w$]*(?:\s+as\s+[A-Za-z_$][\w$]*)?)\b'
        r'|from\s+(?:\.\./)?(?:\.\/)?search-timing\.ts|from\s+["\']\.\/search-timing\.ts["\']',
        re.M,
    )
    for m in pat.finditer(text):
        if 'from' in m.group(0):
            hits.append(m.group(0))
        elif m.group(3):
            name = m.group(3).split()
            hits.append((name[0], 'from ' + name[-1] if name[-1] != name[0] else None))
        else:
            hits.append((m.group(1) or m.group(2), 'decl'))
    lines = {
        line: text[:line.start()+1].count('\n')
        for line in hits
        if isinstance(line, (tuple, str))
    }
    names[path] = []
    for item, origin in lines:
        if isinstance(item, str):
            specifiers.add(item)
        else:
            specifiers.add(item)
        names[path].append((item, origin, lines[item]))
for path, entries in names.items():
    print(f'{path}:')
    for item, origin, line in entries:
        print(f'  line {line}: {origin!r}: {item}')
dup = [name for name in specifiers if sum(1 for entries in names.values() for item, _, _ in entries if item == name) > 1]
print("duplicate_export_items:")
print(sorted(dup))
PY

Repository: kentcdodds/kody

Length of output: 324


Keep the dropped elapsedMs re-export if you want the search barrel to preserve its public timing helpers.

elapsedMs is exported from search-timing.ts and used by core/tool runner memory paths, but this barrel only re-exports settleWithBudget; direct imports from ./search.ts that still rely on elapsedMs will fail.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/worker/src/mcp/tools/search.ts` around lines 1 - 16, Update the
search barrel around the search-timing export to re-export elapsedMs alongside
settleWithBudget, preserving both timing helpers for consumers importing from
search.ts.

@kody-bot
kody-bot merged commit ac6b973 into main Jul 22, 2026
7 checks passed
@kody-bot
kody-bot deleted the cursor/kody-track-c-search-runtime-split-98c9 branch July 22, 2026 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants