@octocodeai/octocode-core 16.1.0 → 16.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/configLoader.d.ts +0 -4
  2. package/dist/data/compressed.js +1 -1
  3. package/dist/data/default.json +174 -176
  4. package/dist/resources/global.js +1 -1
  5. package/dist/resources/tools/{packageSearch.d.ts → ghCloneRepo.d.ts} +1 -1
  6. package/dist/resources/tools/ghCloneRepo.js +1 -0
  7. package/dist/resources/tools/{githubSearchCode.d.ts → ghGetFileContent.d.ts} +1 -1
  8. package/dist/resources/tools/ghGetFileContent.js +1 -0
  9. package/dist/resources/tools/{githubCloneRepo.d.ts → ghSearchCode.d.ts} +1 -1
  10. package/dist/resources/tools/ghSearchCode.js +1 -0
  11. package/dist/resources/tools/{githubGetFileContent.d.ts → ghSearchPRs.d.ts} +1 -1
  12. package/dist/resources/tools/ghSearchPRs.js +1 -0
  13. package/dist/resources/tools/ghSearchRepos.d.ts +2 -0
  14. package/dist/resources/tools/ghSearchRepos.js +1 -0
  15. package/dist/resources/tools/ghViewRepoStructure.d.ts +2 -0
  16. package/dist/resources/tools/ghViewRepoStructure.js +1 -0
  17. package/dist/resources/tools/localFindFiles.js +1 -1
  18. package/dist/resources/tools/localGetFileContent.js +1 -1
  19. package/dist/resources/tools/localSearchCode.js +1 -1
  20. package/dist/resources/tools/localViewStructure.js +1 -1
  21. package/dist/resources/tools/lspGetSemantics.d.ts +2 -0
  22. package/dist/resources/tools/lspGetSemantics.js +1 -0
  23. package/dist/resources/tools/npmSearch.d.ts +2 -0
  24. package/dist/resources/tools/npmSearch.js +1 -0
  25. package/dist/schemas/extraTypes.d.ts +0 -36
  26. package/dist/schemas/index.d.ts +4 -26
  27. package/dist/schemas/index.js +1 -1
  28. package/dist/schemas/outputs.d.ts +1 -13
  29. package/dist/schemas/outputs.js +1 -1
  30. package/dist/schemas/runtime.d.ts +0 -21
  31. package/dist/types/index.d.ts +9 -57
  32. package/package.json +1 -1
  33. package/dist/resources/tools/githubCloneRepo.js +0 -1
  34. package/dist/resources/tools/githubGetFileContent.js +0 -1
  35. package/dist/resources/tools/githubSearchCode.js +0 -1
  36. package/dist/resources/tools/githubSearchPullRequests.d.ts +0 -2
  37. package/dist/resources/tools/githubSearchPullRequests.js +0 -1
  38. package/dist/resources/tools/githubSearchRepositories.d.ts +0 -2
  39. package/dist/resources/tools/githubSearchRepositories.js +0 -1
  40. package/dist/resources/tools/githubViewRepoStructure.d.ts +0 -2
  41. package/dist/resources/tools/githubViewRepoStructure.js +0 -1
  42. package/dist/resources/tools/lspGetSemanticContent.d.ts +0 -2
  43. package/dist/resources/tools/lspGetSemanticContent.js +0 -1
  44. package/dist/resources/tools/packageSearch.js +0 -1
@@ -1,21 +1,16 @@
1
- /**
2
- * Maps constant keys (SCREAMING_SNAKE_CASE) to their canonical MCP tool name
3
- * strings. Adding a new tool means adding one entry here; consumers derive
4
- * key/value unions with `keyof ToolNames` and `ToolNames[keyof ToolNames]`.
5
- */
6
1
  export interface ToolNames {
7
- GITHUB_FETCH_CONTENT: "githubGetFileContent";
8
- GITHUB_SEARCH_CODE: "githubSearchCode";
9
- GITHUB_SEARCH_PULL_REQUESTS: "githubSearchPullRequests";
10
- GITHUB_SEARCH_REPOSITORIES: "githubSearchRepositories";
11
- GITHUB_VIEW_REPO_STRUCTURE: "githubViewRepoStructure";
12
- PACKAGE_SEARCH: "packageSearch";
13
- GITHUB_CLONE_REPO: "githubCloneRepo";
2
+ GITHUB_FETCH_CONTENT: "ghGetFileContent";
3
+ GITHUB_SEARCH_CODE: "ghSearchCode";
4
+ GITHUB_SEARCH_PULL_REQUESTS: "ghSearchPRs";
5
+ GITHUB_SEARCH_REPOSITORIES: "ghSearchRepos";
6
+ GITHUB_VIEW_REPO_STRUCTURE: "ghViewRepoStructure";
7
+ PACKAGE_SEARCH: "npmSearch";
8
+ GITHUB_CLONE_REPO: "ghCloneRepo";
14
9
  LOCAL_RIPGREP: "localSearchCode";
15
10
  LOCAL_FETCH_CONTENT: "localGetFileContent";
16
11
  LOCAL_FIND_FILES: "localFindFiles";
17
12
  LOCAL_VIEW_STRUCTURE: "localViewStructure";
18
- LSP_GET_SEMANTIC_CONTENT: "lspGetSemanticContent";
13
+ LSP_GET_SEMANTIC_CONTENT: "lspGetSemantics";
19
14
  }
20
15
  export interface ToolHints {
21
16
  readonly empty: readonly string[];
@@ -23,31 +18,13 @@ export interface ToolHints {
23
18
  export interface ToolSchema {
24
19
  readonly [param: string]: string;
25
20
  }
26
- /**
27
- * Authoring type for resource files — carries the static definition
28
- * (name, description, schema) plus optional empty-result hints authored
29
- * alongside the tool. Runtime hints from the MCP server response layer
30
- * are additive; these provide pre-call and empty-result guidance.
31
- */
32
21
  export interface ToolSpec {
33
22
  readonly name: string;
34
23
  readonly description: string;
35
24
  readonly schema: ToolSchema;
36
- /** Hints authored in the resource file. Defaults to `{ empty: [] }` when absent. */
37
25
  readonly hints?: ToolHints;
38
26
  }
39
- /**
40
- * Full tool descriptor stored in the config blob and consumed by MCP clients.
41
- * Extends ToolSpec with optional runtime hints (rarely populated — most
42
- * response-handling guidance now lives in the system prompt).
43
- */
44
27
  export interface ToolMetadata extends ToolSpec {
45
- /**
46
- * Runtime hint registry — always present (defaults to `{ empty: [] }`).
47
- * Consumers index into this without null-checking the property itself,
48
- * so it stays required even when the config blob ships no hints for the
49
- * tool.
50
- */
51
28
  readonly hints: ToolHints;
52
29
  }
53
30
  export interface BaseSchema {
@@ -55,7 +32,6 @@ export interface BaseSchema {
55
32
  readonly mainResearchGoal: string;
56
33
  readonly researchGoal: string;
57
34
  readonly reasoning: string;
58
- /** Description string for the boolean verbose field shown in tool schemas. */
59
35
  readonly verbose?: string;
60
36
  }
61
37
  export interface OctocodeConfig {
@@ -71,22 +47,14 @@ export interface CompleteMetadata {
71
47
  readonly toolNames: ToolNames;
72
48
  readonly baseSchema: BaseSchema;
73
49
  readonly tools: Record<string, ToolSpec | ToolMetadata>;
74
- /**
75
- * Shared hint registry — keys are result kinds (`"empty"`, …). Always
76
- * present (defaults to `{}`); consumers fall through to per-tool `hints`
77
- * for tools without a matching key.
78
- */
79
50
  readonly baseHints: Readonly<Record<string, readonly string[]>>;
80
- /** Generic-error hint list — surfaced on any unhandled tool error. Defaults to `[]`. */
81
51
  readonly genericErrorHints: readonly string[];
82
52
  }
83
- /** Envelope-level status — every tool's response carries this. */
84
53
  export declare enum ToolStatus {
85
54
  Empty = "empty",
86
55
  Error = "error"
87
56
  }
88
57
  export declare const STATUS_VALUES: readonly [ToolStatus.Empty, ToolStatus.Error];
89
- /** Row-level pagination — superset of every per-tool flavour. */
90
58
  export interface PaginationInfo {
91
59
  readonly currentPage: number;
92
60
  readonly totalPages: number;
@@ -100,7 +68,6 @@ export interface PaginationInfo {
100
68
  readonly filesPerPage?: number;
101
69
  readonly matchesPerPage?: number;
102
70
  }
103
- /** Rendered-payload pagination — used by `charOffset` / `charLength` paths. */
104
71
  export interface CharPagination {
105
72
  readonly currentPage: number;
106
73
  readonly totalPages: number;
@@ -108,25 +75,14 @@ export interface CharPagination {
108
75
  readonly charOffset: number;
109
76
  readonly charLength: number;
110
77
  readonly totalChars: number;
111
- /** How the page boundary was chosen.
112
- * `'semantic'` — snapped to a tree-sitter/heuristic block boundary.
113
- * `'char-limit'` — fixed char-size cut; may end mid-block (see nextBlockChar). */
114
78
  readonly chunkMode?: "semantic" | "char-limit";
115
- /** Set when `chunkMode` is `'char-limit'` and the cut is mid-block.
116
- * Char offset of the next top-level block start; extend charLength to reach it. */
117
79
  readonly nextBlockChar?: number;
118
80
  }
119
- /** LSP semantic vs. fallback mode marker. */
120
81
  export declare enum LspMode {
121
82
  Semantic = "semantic",
122
83
  Fallback = "fallback"
123
84
  }
124
85
  export declare const LSP_MODES: readonly [LspMode.Semantic, LspMode.Fallback];
125
- /**
126
- * Typed warning kinds emitted by tool responses. Discriminated by `kind`.
127
- * Add new kinds here when introducing new advisory categories — keeps the
128
- * agent-facing wire contract stable across consumers.
129
- */
130
86
  export interface ToolWarning {
131
87
  readonly kind: "match-value-truncated" | "content-truncated";
132
88
  readonly truncatedAt?: number;
@@ -134,7 +90,6 @@ export interface ToolWarning {
134
90
  readonly path?: string;
135
91
  readonly detail?: string;
136
92
  }
137
- /** Generic envelope every tool wraps its data in. */
138
93
  export interface ToolResultEnvelope<TData> {
139
94
  readonly status?: ToolStatus;
140
95
  readonly data?: TData;
@@ -143,7 +98,6 @@ export interface ToolResultEnvelope<TData> {
143
98
  readonly error?: string;
144
99
  }
145
100
  export type ContentView = "none" | "standard" | "symbols";
146
- /** Per-file match pagination — for paging matches *within* a single file. */
147
101
  export interface LocalSearchCodeMatchPagination {
148
102
  readonly currentPage: number;
149
103
  readonly totalPages: number;
@@ -158,9 +112,7 @@ export interface LocalSearchCodeMatch {
158
112
  }
159
113
  export interface LocalSearchCodeFile {
160
114
  path: string;
161
- /** Omitted in filesOnly/discovery mode — rg -l reports no per-file counts. */
162
115
  matchCount?: number;
163
- /** Omitted in discovery/filesOnly mode — empty arrays are noise. */
164
116
  matches?: LocalSearchCodeMatch[];
165
117
  modified?: string;
166
118
  pagination?: LocalSearchCodeMatchPagination;
@@ -370,6 +322,6 @@ export interface PackageItem {
370
322
  readonly downloads?: number;
371
323
  readonly recentVersions?: readonly string[];
372
324
  }
373
- export interface PackageSearchData {
325
+ export interface NpmSearchData {
374
326
  readonly packages: readonly PackageItem[];
375
327
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@octocodeai/octocode-core",
3
- "version": "16.1.0",
3
+ "version": "16.1.1",
4
4
  "description": "Core config, prompts, tools, and schemas for Octocode MCP",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1 +0,0 @@
1
- export const githubCloneRepo={name:"githubCloneRepo",description:"Clone GitHub repo/subtree for repeated reads, grep, or LSP; returns localPath.\nNext: localViewStructure(localPath), localSearchCode, localGetFileContent, lspGetSemanticContent.\nRequires ENABLE_CLONE=true.",schema:{owner:"GitHub repository owner or organization.",repo:"GitHub repository name without the owner.",branch:"Branch, tag, or commit SHA. Omit to resolve the repository branch.",forceRefresh:"Bypass the clone cache and re-clone from GitHub.",sparsePath:'Subdirectory sparse checkout ("packages/foo") — shrinks large monorepo clones.'}};
@@ -1 +0,0 @@
1
- export const githubGetFileContent={name:"githubGetFileContent",description:"Read GitHub file/region.\nUse matchString or startLine/endLine for focused reads; fullContent is for small whole-file reads.\nContinuation pages are cache-served; use pagination.nextBlockChar to avoid mid-block cuts or charOffset+charLength to advance.\nNext: githubSearchCode for usages, githubViewRepoStructure for surrounding paths.",schema:{owner:"GitHub owner or org.",repo:"Repository name (no owner).",branch:"Branch, tag, or commit SHA. Omit to resolve the repository branch.",path:"Repo-relative path — exact case, no leading slash (e.g. src/utils/foo.ts).",startLine:"1-based first line. Exclusive with fullContent/matchString.",endLine:"1-based last line. Exclusive with fullContent/matchString.",fullContent:"Whole file read. Exclusive with matchString/startLine/endLine.",matchString:'Anchor text or regex; all occurrences return as merged slices with matchRanges. Case-insensitive unless matchStringCaseSensitive is true. Not applied when minify:"symbols".',matchStringIsRegex:"Treat matchString as a regex pattern.",matchStringCaseSensitive:"Use case-sensitive matchString matching.",forceRefresh:"Bypass cache and re-fetch from GitHub.",type:"Content target: 'file' reads path; 'directory' materializes a subtree to disk and requires ENABLE_LOCAL=true plus ENABLE_CLONE=true.",contextLines:"Lines of context around each match.",charOffset:"Char offset for continuation pages. Use pagination.charOffset from a prior isPartial response.",charLength:"Page size in chars. Raise for a larger contiguous chunk.",minify:'"standard" strips comments+blanks; "none" keeps exact raw text/comments; "symbols" returns skeleton+gutter and skips matchString/charLength.'}};
@@ -1 +0,0 @@
1
- export const githubSearchCode={name:"githubSearchCode",description:"GitHub code/path search returning path+snippet; matchIndices are snippet char offsets, not file lines.\nEmpty owner+repo can mean unindexed repo; retry owner-only to confirm. Page with limit/page, no total pages.\nNext: githubGetFileContent(path,matchString) for source, githubViewRepoStructure for context, githubSearchRepositories if owner/repo unknown.",schema:{keywordsToSearch:"All terms are combined. Split independent terms into separate items; keep an exact phrase together when needed.",owner:"Owner/org scope — pair with repo to target one repository.",repo:"Repository name (without owner).",extension:'Extension filter, no dot ("ts"). Combines with keywords.',filename:'Filename filter (GitHub filename:) — name equals or contains the value ("Button.tsx", "jest.config").',path:"Directory-prefix filter (GitHub path:) — matches repo paths starting with this prefix, not a full file path.",match:'Search target: "file" searches file contents; "path" searches file paths/names.',limit:"Requested results per GitHub page. Output may have fewer; no total count is returned.",page:"GitHub result page (1-based).",verbose:"Set true to add per-file html url pinned to the matched commit."}};
@@ -1,2 +0,0 @@
1
- import type { ToolSpec } from "../../types/index.js";
2
- export declare const githubSearchPullRequests: ToolSpec;
@@ -1 +0,0 @@
1
- export const githubSearchPullRequests={name:"githubSearchPullRequests",description:'PR search/review. Broad search returns lean metadata; prNumber fetches requested surfaces; reviewMode="full" fetches all.\nSignals: bodyEmpty=requested empty body, absent=not fetched, sanitizationWarnings=filtered/redacted, in_reply_to_id=inline reply.\nUse lighter diffs for scans, raw diffs for quotes, matchString for known text.\nPagination: search page/limit, content filePage/commentPage/commitPage/itemsPerPage, body charOffset/charLength; page only on hasMore, else request narrower content selectors.\nNext: githubGetFileContent for current source, githubSearchCode for usages, prNumber+content.comments for discussion.',schema:{keywordsToSearch:"All keywords are combined across title/body/comments. Multi-word terms auto phrase-quoted. Use match to restrict scope.",query:'Raw GitHub search string appended after keywords. Use for exact phrases ("Partial Prerendering"), qualifiers (label:bug), or anything not exposed as a field.',match:"PR text fields for keyword search: title, body, and/or comments. Body/comments broaden the search.",prNumber:"Direct PR lookup; include it when requesting body, files, patches, comments, reviews, or commits.",owner:"Repo owner or org.",repo:"Repo name.",verbose:"Set true to add url/sourceBranch/sourceSha/updatedAt/bodyPreview to broad results. prNumber lookup already includes full metadata.",state:'PR state filter: "open", "closed", or "merged". If "merged" is sparse, retry "closed" and filter by mergedAt.',assignee:"Assigned user filter.",author:"Author filter.",commenter:"Commenter filter.",involves:"User involvement filter.",mentions:"Mentioned user filter.","review-requested":"Requested reviewer filter.","reviewed-by":"Reviewer filter.",label:"Label filter.","no-label":"Filter to PRs without labels.","no-milestone":"Filter to PRs without milestone.","no-project":"Filter to PRs without project.","no-assignee":"Filter to PRs without assignee.",head:"Source branch filter.",base:"Target branch filter.",created:"Creation date/window.",updated:"Update date/window.",closed:"Closed date/window.","merged-at":"Merged date/window.",comments:"Comment-count filter.",reactions:"Reaction-count filter.",interactions:"Comment+reaction-count filter.",draft:"Draft-state filter.",sort:"created, updated, best-match, comments, or reactions.",order:"Sort order.",archived:"Include archived repos when needed.",limit:"Broad-search result count.",page:"Result page.",filePage:"Pagination page for changedFiles list.",commentPage:"Pagination page for comments.",commitPage:"Pagination page for commits.",itemsPerPage:"Items per page for content selectors.",reviewMode:'"full" = body + changedFiles + patches + comments + reviews + commits in one call.',content:"Surface selector object. Include prNumber because broad searches return metadata.","content.metadata":"PR metadata fields.","content.body":"Full PR description (char-paginated).","content.changedFiles":"File list: path/status/additions/deletions (paged via filePage).","content.patches":"Patch/diff selector.","content.patches.mode":'Patch selection: "none", "selected" with files/ranges, or "all" for every diff.',"content.patches.files":'Non-empty file path list for mode:"selected".',"content.patches.ranges":'Non-empty per-file line ranges for mode:"selected".',"content.patches.ranges.file":"Changed file path for a selected patch range.","content.patches.ranges.additions":"Added-line numbers to include for this file.","content.patches.ranges.deletions":"Deleted-line numbers to include for this file.","content.comments":"PR discussion and inline review comment selector.","content.comments.discussion":"PR thread comments.","content.comments.reviewInline":"Inline code annotations (in_reply_to_id = reply thread).","content.comments.includeBots":"Set true to include CI/bot comments such as Vercel or CodeRabbit.","content.comments.file":"Filter inline comments to one file path.","content.reviews":"Review summaries: APPROVED / CHANGES_REQUESTED.","content.commits":"Commit selector.","content.commits.list":"Commit list (sha, message, author, date).","content.commits.includeFiles":"Per-commit changed-file list.",matchString:"Filter patch/body text — disables minify so matched lines stay visible.",charOffset:"Char offset for body pagination.",charLength:"Body page size in chars.",minify:'"standard" strips comment-only diff lines; "none" keeps raw exact diffs for quoting patch text.'}};
@@ -1,2 +0,0 @@
1
- import type { ToolSpec } from "../../types/index.js";
2
- export declare const githubSearchRepositories: ToolSpec;
@@ -1 +0,0 @@
1
- export const githubSearchRepositories={name:"githubSearchRepositories",description:"Discover GitHub repos by name, keywords, owner, topic, language, or popularity.\nOwner alone enumerates org repos; keywords combine together. Lean output is pipe-separated; verbose=true returns structured objects.\nNext: githubViewRepoStructure, githubSearchCode/githubGetFileContent, packageSearch for npm names.",schema:{keywordsToSearch:"Combined search terms. Use one term per element for broad matching; keep a phrase together for exact wording.",topicsToSearch:"Self-reported GitHub topics. Sparse — fewer repos tag topics than set a language.",language:"Repository language qualifier (GitHub detection).",owner:"Owner/org scope. Owner without keywords enumerates org repos; owner with keywords scopes repository search.",stars:"Star-count filter ('>100', '50..500').",size:"Repository size filter in KB.",created:"Repo creation date/window (e.g. '>2023-01-01').",updated:"Last code-push date/window. Maps to GitHub's `pushed:` qualifier (not `updated:`), so it filters by the date of the last commit push, not metadata updates. E.g. '>2024-01-01'.",match:"Repository text fields to search: name, description, and/or readme. Multiple values match any listed field.",sort:"Sort field: 'stars' | 'forks' | 'help-wanted-issues' | 'updated' | 'best-match'. 'help-wanted-issues' finds repos actively seeking contributors.",limit:"Repositories per page.",page:"Result page (1-based).",archived:"Set true to include archived repos; otherwise search excludes archived repos.",visibility:"'public' or 'private' (private requires repo scope token). Omit to include both.",forks:"Fork-count filter ('>10', '50..500').",license:"SPDX license identifier (e.g. 'mit', 'apache-2.0', 'gpl-3.0'). Exact lowercase SPDX key.",goodFirstIssues:"Filter by number of 'good first issue' labels ('>5').",verbose:"Set true for structured repository objects with owner/repo, metadata, topics, dates, and url."}};
@@ -1,2 +0,0 @@
1
- import type { ToolSpec } from "../../types/index.js";
2
- export declare const githubViewRepoStructure: ToolSpec;
@@ -1 +0,0 @@
1
- export const githubViewRepoStructure={name:"githubViewRepoStructure",description:"Inspect GitHub repo tree and separate implementation from tests, fixtures, docs, generated code.\nNext: githubGetFileContent(path), githubSearchCode, githubCloneRepo for local+LSP.",schema:{owner:"GitHub repository owner or organization.",repo:"GitHub repository name without the owner.",branch:"Branch, tag, or commit SHA. Omit to resolve the repository branch.",path:'Repo-relative directory to browse. Use "" or "." for the root.',depth:"Recursion depth for nested tree output; raise to expose deeper subtrees.",page:"Result page (1-based).",itemsPerPage:"Entries per page.",verbose:"Set true for per-entry file URLs, sizes, and last-modified dates."}};
@@ -1,2 +0,0 @@
1
- import type { ToolSpec } from "../../types/index.js";
2
- export declare const lspGetSemanticContent: ToolSpec;
@@ -1 +0,0 @@
1
- export const lspGetSemanticContent={name:"lspGetSemanticContent",description:'Typed LSP queries: definition, references, callers, callees, callHierarchy, hover, documentSymbols, typeDefinition, implementation.\nTS/JS built in; other languages need installed servers. callers/callees/callHierarchy work on functions.\ndocumentSymbols needs only uri; implementation symbolName is member name. Use format:"compact" for scans.\nNext: localGetFileContent(startLine/endLine), localSearchCode for uri/symbolName/lineHint.',schema:{uri:"Target source file as absolute path or file:/// URI.",type:"LSP operation such as definition, references, hover, documentSymbols, typeDefinition, or implementation.",symbolName:"Needed except for documentSymbols. Exact identifier at lineHint; case-sensitive, no parentheses.",lineHint:"Needed except for documentSymbols. 1-based line from a prior localSearchCode hit.",orderHint:"Nth (0-based) occurrence when symbolName repeats on lineHint.",depth:"Call-tree recursion depth for callHierarchy/callers/callees.",includeDeclaration:"references: set false to omit the declaration itself.",groupByFile:"references: compact per-file summary instead of a flat usage list.",page:"Result page (1-based) for documentSymbols and call-flow results.",itemsPerPage:"Items per page for documentSymbols and call-flow results.",contextLines:"Lines of context for call-flow previews (callers/callees/callHierarchy).",format:'Output format: "structured" typed objects or "compact" line-oriented strings.',workspaceRoot:"Override the workspace root. Omit to auto-detect from the file path."}};
@@ -1 +0,0 @@
1
- export const packageSearch={name:"packageSearch",description:"npm lookup returning package identity, metadata, and source-repo handoff when available.\nMode controls enrichment; smart keeps exact hits rich and broad searches lean.\nNext: githubViewRepoStructure, githubSearchCode, githubGetFileContent when owner/repo exists.",schema:{packageName:"Exact npm package name or keyword query.",mode:'Enrichment mode: "smart", "full", or "lean".',page:"Keyword-result page. Exact package names return one canonical package."}};