@octocodeai/octocode-core 16.1.1 → 16.2.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 (38) hide show
  1. package/dist/data/compressed.js +1 -1
  2. package/dist/data/default.json +263 -222
  3. package/dist/resources/global.js +1 -1
  4. package/dist/resources/tools/_toolkit.d.ts +55 -0
  5. package/dist/resources/tools/_toolkit.js +1 -0
  6. package/dist/resources/tools/ghCloneRepo.d.ts +25 -0
  7. package/dist/resources/tools/ghCloneRepo.js +1 -1
  8. package/dist/resources/tools/ghGetFileContent.d.ts +30 -0
  9. package/dist/resources/tools/ghGetFileContent.js +1 -1
  10. package/dist/resources/tools/ghHistoryResearch.d.ts +133 -0
  11. package/dist/resources/tools/ghHistoryResearch.js +1 -0
  12. package/dist/resources/tools/ghSearchCode.d.ts +21 -0
  13. package/dist/resources/tools/ghSearchCode.js +1 -1
  14. package/dist/resources/tools/ghSearchRepos.d.ts +38 -0
  15. package/dist/resources/tools/ghSearchRepos.js +1 -1
  16. package/dist/resources/tools/ghViewRepoStructure.d.ts +15 -0
  17. package/dist/resources/tools/ghViewRepoStructure.js +1 -1
  18. package/dist/resources/tools/localBinaryInspect.d.ts +40 -0
  19. package/dist/resources/tools/localBinaryInspect.js +1 -0
  20. package/dist/resources/tools/localFindFiles.d.ts +39 -0
  21. package/dist/resources/tools/localFindFiles.js +1 -1
  22. package/dist/resources/tools/localGetFileContent.d.ts +22 -0
  23. package/dist/resources/tools/localGetFileContent.js +1 -1
  24. package/dist/resources/tools/localSearchCode.d.ts +49 -0
  25. package/dist/resources/tools/localSearchCode.js +1 -1
  26. package/dist/resources/tools/localViewStructure.d.ts +27 -0
  27. package/dist/resources/tools/localViewStructure.js +1 -1
  28. package/dist/resources/tools/lspGetSemantics.d.ts +77 -0
  29. package/dist/resources/tools/lspGetSemantics.js +1 -1
  30. package/dist/resources/tools/npmSearch.d.ts +9 -0
  31. package/dist/resources/tools/npmSearch.js +1 -1
  32. package/dist/schemas/index.d.ts +13 -433
  33. package/dist/schemas/index.js +1 -1
  34. package/dist/schemas/runtime.js +1 -1
  35. package/dist/types/index.d.ts +2 -1
  36. package/package.json +1 -1
  37. package/dist/resources/tools/ghSearchPRs.d.ts +0 -2
  38. package/dist/resources/tools/ghSearchPRs.js +0 -1
@@ -1 +1 @@
1
- export const toolNames={GITHUB_FETCH_CONTENT:"ghGetFileContent",GITHUB_SEARCH_CODE:"ghSearchCode",GITHUB_SEARCH_PULL_REQUESTS:"ghSearchPRs",GITHUB_SEARCH_REPOSITORIES:"ghSearchRepos",GITHUB_VIEW_REPO_STRUCTURE:"ghViewRepoStructure",PACKAGE_SEARCH:"npmSearch",GITHUB_CLONE_REPO:"ghCloneRepo",LOCAL_RIPGREP:"localSearchCode",LOCAL_FETCH_CONTENT:"localGetFileContent",LOCAL_FIND_FILES:"localFindFiles",LOCAL_VIEW_STRUCTURE:"localViewStructure",LSP_GET_SEMANTIC_CONTENT:"lspGetSemantics"};export const baseSchema={id:"Query ID.",mainResearchGoal:"Shared goal across batched queries.",researchGoal:"Goal this query answers.",reasoning:"Why this query."};
1
+ export const toolNames={GITHUB_FETCH_CONTENT:"ghGetFileContent",GITHUB_SEARCH_CODE:"ghSearchCode",GITHUB_SEARCH_PULL_REQUESTS:"ghHistoryResearch",GITHUB_SEARCH_REPOSITORIES:"ghSearchRepos",GITHUB_VIEW_REPO_STRUCTURE:"ghViewRepoStructure",PACKAGE_SEARCH:"npmSearch",GITHUB_CLONE_REPO:"ghCloneRepo",LOCAL_RIPGREP:"localSearchCode",LOCAL_FETCH_CONTENT:"localGetFileContent",LOCAL_FIND_FILES:"localFindFiles",LOCAL_VIEW_STRUCTURE:"localViewStructure",LSP_GET_SEMANTIC_CONTENT:"lspGetSemantics",LOCAL_BINARY_INSPECT:"localBinaryInspect"};export const baseSchema={id:"Query ID.",mainResearchGoal:"Shared goal across batched queries.",researchGoal:"Goal this query answers.",reasoning:"Why this query."};
@@ -0,0 +1,55 @@
1
+ import { z } from "zod";
2
+ import type { ToolSchema } from "../../types/index.js";
3
+ export declare const MAX_CONTEXT_LINES = 100;
4
+ export declare const MAX_PAGE_NUMBER = 1000;
5
+ export declare const MAX_CHAR_OFFSET = 100000000;
6
+ export declare const MAX_CHAR_LENGTH = 50000;
7
+ export declare const MAX_LINE_NUMBER = 1000000000;
8
+ export declare const MAX_ORDER_HINT = 100000;
9
+ export declare const MAX_LOCAL_DEPTH = 20;
10
+ export declare const MAX_FIND_DEPTH = 100;
11
+ export declare const MAX_LOCAL_LIMIT = 10000;
12
+ export declare const MAX_LOCAL_ITEMS_PER_PAGE = 50;
13
+ export declare const MAX_GITHUB_SEARCH_LIMIT = 100;
14
+ export declare const DEFAULT_GITHUB_SEARCH_LIMIT = 30;
15
+ export declare const MAX_GITHUB_STRUCTURE_ITEMS_PER_PAGE = 200;
16
+ export declare const DEFAULT_GITHUB_STRUCTURE_ITEMS_PER_PAGE = 100;
17
+ export declare const MAX_PR_ITEMS_PER_PAGE = 100;
18
+ export declare const DEFAULT_PR_ITEMS_PER_PAGE = 20;
19
+ export declare const MAX_MATCH_CONTENT_LENGTH = 100000;
20
+ export declare const DEFAULT_MATCH_CONTENT_LENGTH = 500;
21
+ export declare function intRange(min: number, max: number): z.ZodNumber;
22
+ export declare const StringArray: z.ZodOptional<z.ZodArray<z.ZodString>>;
23
+ export declare function pageNumber(): z.ZodDefault<z.ZodNumber>;
24
+ export declare function optionalPageNumber(): z.ZodOptional<z.ZodNumber>;
25
+ export declare function contextLines(): z.ZodOptional<z.ZodNumber>;
26
+ export declare function lineNumber(): z.ZodOptional<z.ZodNumber>;
27
+ export declare function charOffset(): z.ZodOptional<z.ZodNumber>;
28
+ export declare function charLength(): z.ZodOptional<z.ZodNumber>;
29
+ export declare const metaFields: {
30
+ readonly id: z.ZodOptional<z.ZodString>;
31
+ readonly mainResearchGoal: z.ZodOptional<z.ZodString>;
32
+ readonly researchGoal: z.ZodOptional<z.ZodString>;
33
+ readonly reasoning: z.ZodOptional<z.ZodString>;
34
+ };
35
+ /**
36
+ * Attach the per-field prose from a tool's `schema` map onto its Zod shape,
37
+ * producing the validated query object. This is the single merge point between
38
+ * a tool's content (the prose map) and its scheme (the Zod shape): both live in
39
+ * the same tool file, and this guarantees they stay in lock-step.
40
+ *
41
+ * - `prefix` builds dotted paths (e.g. "content.patches.mode") for nested
42
+ * objects, matching the flat keys default.json ships.
43
+ * - Meta fields are described from `baseSchema`; a field with no entry in the
44
+ * prose map is left undescribed (it simply won't appear in default.json).
45
+ */
46
+ export declare function buildObject<S extends z.ZodRawShape>(prose: ToolSchema, shape: S, prefix?: string): z.ZodObject<S>;
47
+ /** Shared refinement: fullContent / matchString / startLine+endLine are
48
+ * mutually exclusive extraction modes, and endLine must be >= startLine. Used
49
+ * by both the local and GitHub file-content readers. */
50
+ export declare function validateFileContentExtractionMode(data: {
51
+ fullContent?: boolean | undefined;
52
+ matchString?: string | undefined;
53
+ startLine?: number | undefined;
54
+ endLine?: number | undefined;
55
+ }, ctx: z.RefinementCtx): void;
@@ -0,0 +1 @@
1
+ import{z as t}from"zod";import{baseSchema as e}from"../global.js";export const MAX_CONTEXT_LINES=100;export const MAX_PAGE_NUMBER=1e3;export const MAX_CHAR_OFFSET=1e8;export const MAX_CHAR_LENGTH=5e4;export const MAX_LINE_NUMBER=1e9;export const MAX_ORDER_HINT=1e5;export const MAX_LOCAL_DEPTH=20;export const MAX_FIND_DEPTH=100;export const MAX_LOCAL_LIMIT=1e4;export const MAX_LOCAL_ITEMS_PER_PAGE=50;export const MAX_GITHUB_SEARCH_LIMIT=100;export const DEFAULT_GITHUB_SEARCH_LIMIT=30;export const MAX_GITHUB_STRUCTURE_ITEMS_PER_PAGE=200;export const DEFAULT_GITHUB_STRUCTURE_ITEMS_PER_PAGE=100;export const MAX_PR_ITEMS_PER_PAGE=100;export const DEFAULT_PR_ITEMS_PER_PAGE=20;export const MAX_MATCH_CONTENT_LENGTH=1e5;export const DEFAULT_MATCH_CONTENT_LENGTH=500;export function intRange(e,n){return t.number().int().min(e).max(n)}export const StringArray=t.array(t.string()).optional();export function pageNumber(){return intRange(1,1e3).default(1)}export function optionalPageNumber(){return intRange(1,1e3).optional()}export function contextLines(){return intRange(0,100).optional()}export function lineNumber(){return intRange(1,1e9).optional()}export function charOffset(){return intRange(0,1e8).optional()}export function charLength(){return intRange(1,5e4).optional()}export const metaFields={id:t.string().optional(),mainResearchGoal:t.string().optional(),researchGoal:t.string().optional(),reasoning:t.string().optional()};const n=new Set(Object.keys(metaFields));export function buildObject(o,r,i=""){const s={};for(const t of Object.keys(r)){const a=r[t],c=i?`${i}.${t}`:t,_=""===i&&n.has(t)?e[c]:o[c];s[t]=_?a.describe(_):a}return t.object(s)}export function validateFileContentExtractionMode(t,e){const n=!0===t.fullContent,o=void 0!==t.matchString,r=void 0!==t.startLine||void 0!==t.endLine;n&&o&&e.addIssue({code:"custom",message:"Cannot use fullContent with matchString — these are mutually exclusive extraction methods.",path:["matchString"]}),n&&r&&e.addIssue({code:"custom",message:"Cannot use fullContent with startLine/endLine — these are mutually exclusive extraction methods.",path:["startLine"]}),o&&r&&e.addIssue({code:"custom",message:"Cannot use matchString with startLine/endLine — these are mutually exclusive extraction methods.",path:["startLine"]}),void 0!==t.startLine&&void 0!==t.endLine&&t.endLine<t.startLine&&e.addIssue({code:"custom",message:"Invalid line range: endLine must be greater than or equal to startLine.",path:["endLine"]})}
@@ -1,2 +1,27 @@
1
+ import { z } from "zod";
1
2
  import type { ToolSpec } from "../../types/index.js";
2
3
  export declare const ghCloneRepo: ToolSpec;
4
+ export declare const CloneRepoQuerySchema: z.ZodObject<{
5
+ owner: z.ZodString;
6
+ repo: z.ZodString;
7
+ branch: z.ZodOptional<z.ZodString>;
8
+ sparsePath: z.ZodOptional<z.ZodString>;
9
+ forceRefresh: z.ZodOptional<z.ZodBoolean>;
10
+ id: z.ZodOptional<z.ZodString>;
11
+ mainResearchGoal: z.ZodOptional<z.ZodString>;
12
+ researchGoal: z.ZodOptional<z.ZodString>;
13
+ reasoning: z.ZodOptional<z.ZodString>;
14
+ }, z.core.$strip>;
15
+ export declare const BulkCloneRepoSchema: z.ZodObject<{
16
+ queries: z.ZodArray<z.ZodObject<{
17
+ owner: z.ZodString;
18
+ repo: z.ZodString;
19
+ branch: z.ZodOptional<z.ZodString>;
20
+ sparsePath: z.ZodOptional<z.ZodString>;
21
+ forceRefresh: z.ZodOptional<z.ZodBoolean>;
22
+ id: z.ZodOptional<z.ZodString>;
23
+ mainResearchGoal: z.ZodOptional<z.ZodString>;
24
+ researchGoal: z.ZodOptional<z.ZodString>;
25
+ reasoning: z.ZodOptional<z.ZodString>;
26
+ }, z.core.$strip>>;
27
+ }, z.core.$strip>;
@@ -1 +1 @@
1
- export const ghCloneRepo={name:"ghCloneRepo",description:'Clone GitHub repo/subtree for repeated reads, grep, or LSP; returns localPath.\nAvailability: requires ENABLE_LOCAL + ENABLE_CLONE server config AND git on PATH. When unavailable, use ghViewRepoStructure + ghGetFileContent(type:"file") instead.\nsparsePath clones only a subdirectory — faster for large monorepos. Must exist in the repo — verify with ghViewRepoStructure first.\nClones are shallow (--depth 1) — no commit history. forceRefresh bypasses the 24h cache.\nPrefer over repeated ghGetFileContent calls when: doing LSP analysis, grepping across many files, or remote searches become expensive — clone once, then use local tools (localSearchCode, localGetFileContent, lspGetSemantics) for all subsequent reads.\nBulk: queries:[{owner,repo,...},{owner,repo,...}] to clone multiple repos in one call (max 5).\nNext: localViewStructure(path=localPath) to orient, localSearchCode(path=localPath), localGetFileContent, lspGetSemantics(uri=<file inside localPath>); evidence.answerReady:true — switch to local tools.',schema:{owner:"GitHub repository owner or organization.",repo:"GitHub repository name without the owner.",branch:"Branch, tag, or commit SHA. Omit to use the repository default branch.",forceRefresh:"Re-clone from GitHub, bypassing the 24h cache. Default: false (serve cached clone when available).",sparsePath:'Repo-relative subdirectory to sparse-clone (e.g. "packages/foo"). Must exist in the repo verify with ghViewRepoStructure first. Omit for a full shallow clone.'}};
1
+ import{z as e}from"zod";import{buildObject as o,metaFields as r}from"./_toolkit.js";export const ghCloneRepo={name:"ghCloneRepo",description:'Clone GitHub repo/subtree for repeated reads, search, or LSP; returns localPath.\nAvailability: requires ENABLE_LOCAL + ENABLE_CLONE server config. When unavailable, use ghViewRepoStructure + ghGetFileContent(type:"file") instead.\nsparsePath clones only a subdirectory — faster for large monorepos. Must exist in the repo — verify with ghViewRepoStructure first.\nClones are shallow — no commit history. forceRefresh bypasses the 24h cache.\nPrefer over repeated ghGetFileContent calls when: doing LSP analysis, searching across many files, or remote searches become expensive — clone once, then use local tools (localSearchCode, localGetFileContent, lspGetSemantics) for all subsequent reads.\nBulk: queries:[{owner,repo,...},{owner,repo,...}] to clone multiple repos in one call (max 5).\nNext: localViewStructure(path=localPath) to orient, localSearchCode(path=localPath), localGetFileContent, lspGetSemantics(uri=<file inside localPath>); evidence.answerReady:true — switch to local tools.',schema:{owner:"Repository owner or org.",repo:"Repository name, without the owner.",branch:"Branch, tag, or commit SHA to clone. Omit to use the repository's default branch.",forceRefresh:"Re-clones from GitHub, bypassing the 24h cache, instead of serving the cached clone.",sparsePath:'Repo-relative subdirectory to sparse-clone (e.g. "packages/foo") faster on large monorepos. Must exist (verify with ghViewRepoStructure first). Omit for a full shallow clone.'}};export const CloneRepoQuerySchema=o(ghCloneRepo.schema,{...r,owner:e.string(),repo:e.string(),branch:e.string().optional(),sparsePath:e.string().optional(),forceRefresh:e.boolean().optional()});export const BulkCloneRepoSchema=e.object({queries:e.array(CloneRepoQuerySchema).min(1)});
@@ -1,2 +1,32 @@
1
+ import { z } from "zod";
1
2
  import type { ToolSpec } from "../../types/index.js";
2
3
  export declare const ghGetFileContent: ToolSpec;
4
+ export declare const FileContentQuerySchema: z.ZodObject<{
5
+ owner: z.ZodString;
6
+ repo: z.ZodString;
7
+ branch: z.ZodOptional<z.ZodString>;
8
+ path: z.ZodString;
9
+ startLine: z.ZodOptional<z.ZodNumber>;
10
+ endLine: z.ZodOptional<z.ZodNumber>;
11
+ fullContent: z.ZodOptional<z.ZodBoolean>;
12
+ matchString: z.ZodOptional<z.ZodString>;
13
+ matchStringIsRegex: z.ZodOptional<z.ZodBoolean>;
14
+ matchStringCaseSensitive: z.ZodOptional<z.ZodBoolean>;
15
+ forceRefresh: z.ZodOptional<z.ZodBoolean>;
16
+ type: z.ZodDefault<z.ZodEnum<{
17
+ file: "file";
18
+ directory: "directory";
19
+ }>>;
20
+ contextLines: z.ZodDefault<z.ZodNumber>;
21
+ charOffset: z.ZodOptional<z.ZodNumber>;
22
+ charLength: z.ZodOptional<z.ZodNumber>;
23
+ minify: z.ZodDefault<z.ZodEnum<{
24
+ none: "none";
25
+ standard: "standard";
26
+ symbols: "symbols";
27
+ }>>;
28
+ id: z.ZodOptional<z.ZodString>;
29
+ mainResearchGoal: z.ZodOptional<z.ZodString>;
30
+ researchGoal: z.ZodOptional<z.ZodString>;
31
+ reasoning: z.ZodOptional<z.ZodString>;
32
+ }, z.core.$strip>;
@@ -1 +1 @@
1
- export const ghGetFileContent={name:"ghGetFileContent",description:'Read a GitHub file or region.\nChoose one extraction mode — mutually exclusive: matchString (find all occurrences, returns matchRanges line numbers) | startLine/endLine (line range) | fullContent (entire file, small files only) | default (first charLength chars from line 1).\nPick minify by goal (see the minify field): "symbols" to orient on an unknown file, "standard" to read, "none" to quote/diff.\nMutual exclusions: fullContent XOR matchString XOR startLine/endLine; endLine must be >= startLine.\ntype:"directory" materializes a subtree to a local path for LSP work — only available when the server has clone enabled; use ghViewRepoStructure otherwise.\nOutput signals: isPartial:true → check hints[] for the next charOffset value (emitted as \'charOffset=N\' in hints — not a named field); matchRanges[].start/end are 1-based line numbers → use as lineHint for lspGetSemantics; warnings[] → content was sanitized or symbols mode fell back to standard.\nNext: lspGetSemantics(uri, symbolName, lineHint=matchRanges[0].start) for semantics; re-read with startLine=matchRanges[0].start, endLine=matchRanges[0].end to fetch the full matched body; ghSearchCode for usages; ghViewRepoStructure for surrounding paths. When you have N known file paths to read, batch them: queries:[{path:f1,...},{path:f2,...}] (hard limit: max 5 per call — split into multiple calls if N>5).',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. Mutually exclusive with fullContent and matchString.",endLine:"1-based last line. Mutually exclusive with fullContent and matchString. Must be >= startLine.",fullContent:"Read the entire file. Mutually exclusive with matchString and startLine/endLine. Reserve for files you know are small use matchString or startLine/endLine for large files.",matchString:'Text or regex anchor. All occurrences returned as merged slices. matchRanges[].start/end are 1-based line numbers use as lineHint for lspGetSemantics. Mutually exclusive with startLine/endLine and fullContent. Case-insensitive by default; set matchStringCaseSensitive:true for exact case. Set matchStringIsRegex:true for regex. Not applied when minify:"symbols".',matchStringIsRegex:"Treat matchString as a regex pattern. Use for flexible anchoring (e.g. function signatures, import patterns).",matchStringCaseSensitive:"Use case-sensitive matchString matching. Default is case-insensitive.",forceRefresh:"Bypass the server-side cache and re-fetch from GitHub. Use when you need the latest commit version, not a cached snapshot.",type:"Content target. 'file' (default) reads a single file. 'directory' materializes a subtree to a local path for LSP analysis — only available when the server has clone enabled; if unavailable, use ghViewRepoStructure instead.",contextLines:"Lines of source context returned around each matchString hit — extends the snippet beyond the match itself. Raise to capture a full function body without a follow-up read. Only applies when matchString is set.",charOffset:"Char offset for continuation reads. Read from hints[] in the prior response (emitted as 'charOffset=N') — do not compute this value manually.",charLength:"Page size in chars. Set higher for files larger than ~800 lines. Check isPartial:true for truncation.",minify:'"symbols": structural skeleton with line numbers in the gutter — much smaller. Use for orientation on any unknown file before reading details. Skips matchString and charLength. "standard" (default): strips comments and blank lines. "none": exact raw text — use when quoting or matching whitespace precisely.'}};
1
+ import{z as e}from"zod";import{buildObject as t,charLength as n,charOffset as a,intRange as i,lineNumber as r,MAX_CONTEXT_LINES as s,metaFields as o,validateFileContentExtractionMode as l}from"./_toolkit.js";export const ghGetFileContent={name:"ghGetFileContent",description:'Read a GitHub file or region.\nChoose one extraction mode — mutually exclusive: matchString (find all occurrences, returns matchRanges line numbers) | startLine/endLine (line range) | fullContent (entire file, small files only) | default (first charLength chars from line 1).\nPick minify by goal (see the minify field): "symbols" to orient on an unknown file, "standard" to read, "none" to quote/diff.\nMutual exclusions: fullContent XOR matchString XOR startLine/endLine; endLine must be >= startLine.\ntype:"directory" materializes a subtree to a local path for LSP work — only available when the server has clone enabled; use ghViewRepoStructure otherwise.\nOutput signals: isPartial:true → check hints[] for the next charOffset value (emitted as \'charOffset=N\' in hints — not a named field); matchRanges[].start/end are 1-based line numbers → use as lineHint for lspGetSemantics; warnings[] → content was sanitized or symbols mode fell back to standard.\nNext: lspGetSemantics(uri, symbolName, lineHint=matchRanges[0].start) for semantics; re-read with startLine=matchRanges[0].start, endLine=matchRanges[0].end to fetch the full matched body; ghSearchCode for usages; ghViewRepoStructure for surrounding paths. When you have N known file paths to read, batch them: queries:[{path:f1,...},{path:f2,...}] (hard limit: max 5 per call — split into multiple calls if N>5).',schema:{owner:"Repository owner or org.",repo:"Repository name, without the owner.",branch:"Branch, tag, or commit SHA to read from. Omit to use the repository's default branch.",path:"Repo-relative file path — exact case, no leading slash (e.g. src/utils/foo.ts).",startLine:"First line of the range. Mutually exclusive with fullContent and matchString.",endLine:"Last line of the range; must be >= startLine. Mutually exclusive with fullContent and matchString.",fullContent:"Returns the whole file. Reserve for files known to be small; for large files use matchString or startLine/endLine. Mutually exclusive with both.",matchString:'Anchor text (or regex) to locate; all occurrences come back as merged slices, with matchRanges[].start/end as 1-based line numbers you can pass as lineHint to lspGetSemantics. Case-insensitive unless matchStringCaseSensitive:true; treated as regex when matchStringIsRegex:true. Mutually exclusive with startLine/endLine and fullContent; ignored when minify:"symbols".',matchStringIsRegex:"Treats matchString as a regex use for flexible anchors like function signatures or import patterns.",matchStringCaseSensitive:"Makes matchString matching case-sensitive (case-insensitive otherwise).",forceRefresh:"Bypasses the server cache and re-fetches from GitHub. Use when you need the latest commit, not a cached snapshot.",type:"What to read. 'file' reads one file. 'directory' materializes a subtree to a local path for LSP work — only when the server has clone enabled; otherwise use ghViewRepoStructure.",contextLines:"Extra source lines returned around each matchString hit. Raise to capture a full function body without a follow-up read. Applies only with matchString.",charOffset:"Continuation offset for the next page; take it from hints[] in the prior response ('charOffset=N') — do not compute it yourself.",charLength:"Page size in characters. Raise for large files; check isPartial:true for truncation.",minify:'"symbols": structural skeleton with line numbers in the gutter — much smaller. Use for orientation on any unknown file before reading details. Skips matchString and charLength. "standard": strips comments and blank lines. "none": exact raw text — use when quoting or matching whitespace precisely.'}};export const FileContentQuerySchema=t(ghGetFileContent.schema,{...o,owner:e.string(),repo:e.string(),branch:e.string().optional(),path:e.string(),startLine:r(),endLine:r(),fullContent:e.boolean().optional(),matchString:e.string().optional(),matchStringIsRegex:e.boolean().optional(),matchStringCaseSensitive:e.boolean().optional(),forceRefresh:e.boolean().optional(),type:e.enum(["file","directory"]).default("file"),contextLines:i(0,s).default(5),charOffset:a(),charLength:n(),minify:e.enum(["none","standard","symbols"]).default("standard")}).superRefine(l);
@@ -0,0 +1,133 @@
1
+ import { z } from "zod";
2
+ import type { ToolSpec } from "../../types/index.js";
3
+ export declare const ghHistoryResearch: ToolSpec;
4
+ export declare const GitHubPullRequestSearchQuerySchema: z.ZodObject<{
5
+ type: z.ZodDefault<z.ZodEnum<{
6
+ prs: "prs";
7
+ commits: "commits";
8
+ }>>;
9
+ since: z.ZodOptional<z.ZodString>;
10
+ until: z.ZodOptional<z.ZodString>;
11
+ path: z.ZodOptional<z.ZodString>;
12
+ branch: z.ZodOptional<z.ZodString>;
13
+ perPage: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
14
+ includeDiff: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
15
+ keywordsToSearch: z.ZodOptional<z.ZodArray<z.ZodString>>;
16
+ query: z.ZodOptional<z.ZodString>;
17
+ prNumber: z.ZodOptional<z.ZodNumber>;
18
+ owner: z.ZodOptional<z.ZodString>;
19
+ repo: z.ZodOptional<z.ZodString>;
20
+ concise: z.ZodOptional<z.ZodBoolean>;
21
+ state: z.ZodOptional<z.ZodEnum<{
22
+ open: "open";
23
+ closed: "closed";
24
+ merged: "merged";
25
+ }>>;
26
+ assignee: z.ZodOptional<z.ZodString>;
27
+ author: z.ZodOptional<z.ZodString>;
28
+ commenter: z.ZodOptional<z.ZodString>;
29
+ involves: z.ZodOptional<z.ZodString>;
30
+ mentions: z.ZodOptional<z.ZodString>;
31
+ "review-requested": z.ZodOptional<z.ZodString>;
32
+ "reviewed-by": z.ZodOptional<z.ZodString>;
33
+ label: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
34
+ milestone: z.ZodOptional<z.ZodString>;
35
+ language: z.ZodOptional<z.ZodString>;
36
+ checks: z.ZodOptional<z.ZodEnum<{
37
+ success: "success";
38
+ failure: "failure";
39
+ pending: "pending";
40
+ }>>;
41
+ review: z.ZodOptional<z.ZodEnum<{
42
+ none: "none";
43
+ approved: "approved";
44
+ changes_requested: "changes_requested";
45
+ required: "required";
46
+ }>>;
47
+ locked: z.ZodOptional<z.ZodBoolean>;
48
+ visibility: z.ZodOptional<z.ZodEnum<{
49
+ public: "public";
50
+ private: "private";
51
+ }>>;
52
+ "team-mentions": z.ZodOptional<z.ZodString>;
53
+ project: z.ZodOptional<z.ZodString>;
54
+ "no-label": z.ZodOptional<z.ZodBoolean>;
55
+ "no-milestone": z.ZodOptional<z.ZodBoolean>;
56
+ "no-project": z.ZodOptional<z.ZodBoolean>;
57
+ "no-assignee": z.ZodOptional<z.ZodBoolean>;
58
+ head: z.ZodOptional<z.ZodString>;
59
+ base: z.ZodOptional<z.ZodString>;
60
+ created: z.ZodOptional<z.ZodString>;
61
+ updated: z.ZodOptional<z.ZodString>;
62
+ closed: z.ZodOptional<z.ZodString>;
63
+ "merged-at": z.ZodOptional<z.ZodString>;
64
+ comments: z.ZodOptional<z.ZodString>;
65
+ reactions: z.ZodOptional<z.ZodString>;
66
+ interactions: z.ZodOptional<z.ZodString>;
67
+ draft: z.ZodOptional<z.ZodBoolean>;
68
+ match: z.ZodOptional<z.ZodArray<z.ZodEnum<{
69
+ comments: "comments";
70
+ title: "title";
71
+ body: "body";
72
+ }>>>;
73
+ sort: z.ZodOptional<z.ZodEnum<{
74
+ created: "created";
75
+ updated: "updated";
76
+ "best-match": "best-match";
77
+ comments: "comments";
78
+ reactions: "reactions";
79
+ }>>;
80
+ order: z.ZodOptional<z.ZodEnum<{
81
+ asc: "asc";
82
+ desc: "desc";
83
+ }>>;
84
+ limit: z.ZodDefault<z.ZodNumber>;
85
+ page: z.ZodDefault<z.ZodNumber>;
86
+ archived: z.ZodOptional<z.ZodBoolean>;
87
+ filePage: z.ZodOptional<z.ZodNumber>;
88
+ commentPage: z.ZodOptional<z.ZodNumber>;
89
+ commitPage: z.ZodOptional<z.ZodNumber>;
90
+ itemsPerPage: z.ZodDefault<z.ZodNumber>;
91
+ reviewMode: z.ZodOptional<z.ZodLiteral<"full">>;
92
+ content: z.ZodOptional<z.ZodObject<{
93
+ metadata: z.ZodOptional<z.ZodBoolean>;
94
+ body: z.ZodOptional<z.ZodBoolean>;
95
+ changedFiles: z.ZodOptional<z.ZodBoolean>;
96
+ patches: z.ZodOptional<z.ZodObject<{
97
+ mode: z.ZodDefault<z.ZodEnum<{
98
+ none: "none";
99
+ selected: "selected";
100
+ all: "all";
101
+ }>>;
102
+ files: z.ZodOptional<z.ZodArray<z.ZodString>>;
103
+ ranges: z.ZodOptional<z.ZodArray<z.ZodObject<{
104
+ file: z.ZodString;
105
+ additions: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
106
+ deletions: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
107
+ }, z.core.$strip>>>;
108
+ }, z.core.$strip>>;
109
+ comments: z.ZodOptional<z.ZodObject<{
110
+ discussion: z.ZodOptional<z.ZodBoolean>;
111
+ reviewInline: z.ZodOptional<z.ZodBoolean>;
112
+ includeBots: z.ZodDefault<z.ZodBoolean>;
113
+ file: z.ZodOptional<z.ZodString>;
114
+ }, z.core.$strip>>;
115
+ reviews: z.ZodOptional<z.ZodBoolean>;
116
+ commits: z.ZodOptional<z.ZodObject<{
117
+ list: z.ZodOptional<z.ZodBoolean>;
118
+ includeFiles: z.ZodOptional<z.ZodBoolean>;
119
+ }, z.core.$strip>>;
120
+ }, z.core.$strip>>;
121
+ matchString: z.ZodOptional<z.ZodString>;
122
+ commentBodyOffset: z.ZodOptional<z.ZodNumber>;
123
+ charOffset: z.ZodOptional<z.ZodNumber>;
124
+ charLength: z.ZodOptional<z.ZodNumber>;
125
+ minify: z.ZodDefault<z.ZodEnum<{
126
+ none: "none";
127
+ standard: "standard";
128
+ }>>;
129
+ id: z.ZodOptional<z.ZodString>;
130
+ mainResearchGoal: z.ZodOptional<z.ZodString>;
131
+ researchGoal: z.ZodOptional<z.ZodString>;
132
+ reasoning: z.ZodOptional<z.ZodString>;
133
+ }, z.core.$strip>;
@@ -0,0 +1 @@
1
+ import{z as e}from"zod";import{buildObject as t,charLength as o,charOffset as n,DEFAULT_GITHUB_SEARCH_LIMIT as a,DEFAULT_PR_ITEMS_PER_PAGE as i,intRange as s,MAX_GITHUB_SEARCH_LIMIT as r,MAX_LINE_NUMBER as l,MAX_PR_ITEMS_PER_PAGE as c,metaFields as m,optionalPageNumber as d,pageNumber as p,StringArray as h}from"./_toolkit.js";export const ghHistoryResearch={name:"ghHistoryResearch",description:'Unified PR and commit history tool for GitHub research. Two modes, one tool.\nTYPE:"prs" — PR search and deep read.\n LIST MODE (no prNumber): search PRs by keyword, author, label, date, review state, CI status and more — returns lean metadata. Re-call with prNumber to deep-read a result.\n DETAIL MODE (prNumber required): fetch body, changedFiles, patches, comments, reviews, commits. Use reviewMode:"full" to fetch all surfaces in one call. Content selectors are silently ignored without prNumber.\nTYPE:"commits" — file or repo commit history.\n Provide owner+repo and optionally path (file), path ending in "/" (directory subtree), or omit path for whole-repo history. Returns commit log with sha, message, author, date, url. Use since/until for date range, author for contributor filter, includeDiff for per-commit diffs.\n Commit messageHeadline often embeds a PR ref like "#420" — extract it and re-call with prNumber:420 for the full PR.\n Batch multiple paths in one call: queries:[{type:"commits",path:"A",...},{type:"commits",path:"B",...}] (max 5 per call).\nPR SEARCH FLOW (type:"prs"):\n- Keyword: keywordsToSearch:["pagination"] + match:["title"] for title-only; query field for raw GitHub qualifiers.\n- Archaeology (find PR that introduced X): state:"merged" sort:"created" order:"asc" — oldest merged first.\n- Filter by: state, author, label, milestone, language, checks, review, draft, locked, visibility, base branch, date ranges.\n- All list results include next:{} map of content surfaces to fetch. Re-call with prNumber to deep-read.\nCONTENT PAGINATION (detail mode):\n- PR body / patches: charOffset+charLength sliding window; advance charOffset on hasMore.\n- Comment bodies: commentBodyOffset+charLength; advance commentBodyOffset on contentPagination.commentBody.hasMore.\n- File list / comments / commits: page-based (filePage, commentPage, commitPage+itemsPerPage).\n- contentPagination in the response shows all surfaces with hasMore=true and their nextQuery ready to use.\nSIGNALS: bodyEmpty=requested but empty; absent field=surface not requested (not missing data); sanitizationWarnings=content redacted; in_reply_to_id=reply in a thread.\nSIZE CONTROL: patches.mode:"selected" with files/ranges for targeted diffs. Set charLength to cap windows. Set itemsPerPage for comments/commits/files.\nOUTPUT: minify "standard" (default) strips patch comments and blank lines; minify "none" returns raw exact diff text. "symbols" is not available for PR content.',schema:{type:'Mode selector. "prs": search or deep-read pull requests. "commits": file or repo commit history — use owner+repo+path.',keywordsToSearch:"Keywords combined across title/body/comments (multi-word terms are auto phrase-quoted). Pair with match to restrict scope. Ignored in commits mode.",query:'Raw GitHub search string appended verbatim after keywords. Use for exact phrases ("Partial Prerendering"), qualifiers (label:bug), or anything not exposed as a first-class field. Ignored in commits mode.',match:'Fields to match keywords against: "title", "body", "comments". Default searches all three. Use ["title"] for the most precise and fastest match.',prNumber:"Direct PR lookup by number. Required to fetch body, files, patches, comments, reviews, or commits — content/reviewMode are silently ignored without it. Requires owner+repo.",owner:"Repo owner or org (required for commits mode; optional but recommended for PR search).",repo:"Repo name (required for commits mode).",concise:'List mode: set true for minimal orientation — a flat list of "#number title" strings to triage; then re-call with prNumber to deep-read the chosen PR. Default returns structured PR objects. Ignored with prNumber (detail mode).',state:'"open", "closed", or "merged". "merged" maps to GitHub search is:merged — returns merged PRs only. Ignored in commits mode.',author:"PR author or commit author filter.",assignee:"Assigned user filter (PR mode only).",commenter:"User who commented on the PR (PR mode only).",involves:"Any user involvement — author, assignee, mention, or commenter (PR mode only).",mentions:"User mentioned via @mention in the PR (PR mode only).","review-requested":"User or team whose review was requested (PR mode only).","reviewed-by":"User who reviewed the PR (PR mode only).",label:'Label name or array. Example: "bug", ["enhancement","breaking"]. PR mode only.',milestone:'Milestone title (exact match). Example: "v2.0". PR mode only.',language:'Repository language filter. Example: "typescript", "rust". PR mode only.',checks:'"success" (all CI passed), "failure" (any check failed), "pending" (checks running). PR mode only.',review:'"approved" (has approval), "changes_requested", "required" (review required but pending), "none" (no reviews yet). PR mode only.',locked:"true = only locked conversations; false = only unlocked. PR mode only.",visibility:'"public" or "private" — filter by repo visibility. PR mode only.',"team-mentions":'Filter PRs that mention a GitHub team. Format: "org/team-slug". PR mode only.',project:'Filter PRs linked to a project board. Format: "owner/project-number". PR mode only.',"no-label":"Filter to PRs without any labels.","no-milestone":"Filter to PRs without a milestone.","no-project":"Filter to PRs without a project.","no-assignee":"Filter to PRs without an assignee.",head:"Source branch filter (PR mode). Example: feature/my-branch.",base:'Target branch filter (PR mode). Example: "main".',created:'Creation date filter. Format: ">2024-01-01", "<2023-06-01", "2023-01-01..2024-01-01". PR mode only.',updated:"Last updated filter (tracks comments, pushes). Same date format as created. PR mode only.",closed:"Closed date filter. Same format as created. PR mode only.","merged-at":"Merged date filter. Same format as created. PR mode only.",since:'Commit start date (commits mode only). ISO 8601. Example: "2024-01-01T00:00:00Z".',until:"Commit end date (commits mode only). ISO 8601.",path:'File path or directory prefix (commits mode). Omit for whole-repo history. A trailing "/" scopes to a directory subtree.',branch:"Branch name or SHA to walk history from (commits mode). Defaults to the repo default branch.",perPage:"Commits per page (commits mode).",includeDiff:"Include per-commit file diffs (additions, deletions, patch) in commits mode. Increases response size — use sparingly.",comments:'SEARCH FILTER: comment-count range qualifier. Example: ">5", "0..10". Not for fetching PR comment content — use content.comments for that.',reactions:'SEARCH FILTER: reaction-count range qualifier. Example: ">10".',interactions:'SEARCH FILTER: combined comment+reaction count. Example: ">20".',draft:"true: drafts only; false: non-drafts only; omit: both.",archived:"Include PRs from archived repositories. Defaults to false.",sort:'"created" (newest first), "updated" (recently active), "comments" (most discussed), "reactions" (most reacted), "best-match" (GitHub relevance score).',order:'"desc" (newest/highest first), "asc" (oldest/lowest first). Pair asc+sort:created for archaeology.',limit:"PR results per page (list mode).",page:"Result page for list-mode PR search. Use only on hasMore:true.",filePage:"Page through the changed-files list (detail mode). Use on contentPagination.changedFiles.hasMore.",commentPage:"Page through PR comments (detail mode). Use on contentPagination.comments.hasMore.",commitPage:"Page through PR-bound commits (detail mode). Use on contentPagination.commits.hasMore.",itemsPerPage:"Items per page for file, comment, and commit lists.",reviewMode:'"full": fetch all content surfaces (body + changedFiles + patches + comments + reviews + commits) in one call. Only valid with prNumber.',content:"Content selector object. Only applied in detail mode (prNumber required). Select only what you need — each surface adds response size.","content.metadata":"Ensure PR metadata fields (number, title, state, author, dates) are included.","content.body":"Full PR description text. Paginated via charOffset/charLength. Check contentPagination.body.hasMore for continuation.","content.changedFiles":"File list: path, status, additions, deletions. Paginated via filePage.","content.patches":"Diff/patch selector.","content.patches.mode":'"none" (no diffs), "selected" (targeted files/ranges — cheapest), "all" (every diff). Use selected + files/ranges to read specific files without fetching the entire diff.',"content.patches.files":'Non-empty list of file paths to fetch when mode:"selected". Example: ["src/foo.ts","src/bar.ts"].',"content.patches.ranges":'Per-file line ranges for mode:"selected". Each entry: { file, additions?: number[], deletions?: number[] }. Returns only the specified line numbers.',"content.patches.ranges.file":"File path for this range entry.","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 comment selector.","content.comments.discussion":"Include PR-level discussion comments.","content.comments.reviewInline":"Include inline code review comments. in_reply_to_id marks replies in a thread.","content.comments.includeBots":"Set true to include CI/bot comments (Vercel preview, CodeRabbit, etc.). Default false.","content.comments.file":"Filter inline comments to a single file path.","content.reviews":"Review summaries: APPROVED / CHANGES_REQUESTED state per reviewer.","content.commits":'PR-bound commit selector. These are commits that belong to the PR — not the repo commit log (use type:"commits" for that).',"content.commits.list":"Commit list: sha, message, author, date.","content.commits.includeFiles":"Per-commit file change list (path, status, additions, deletions).",matchString:"Substring filter — narrows patch/body/comment text to sections containing this string.",charOffset:"Char window start for body or patch content. Advance to contentPagination.body.nextQuery.charOffset when hasMore:true.",commentBodyOffset:"Char window start for comment bodies. Advance to contentPagination.commentBody.nextQuery.commentBodyOffset when hasMore:true.",charLength:"Char window size for body, patches, and comment bodies. Controls how much text is returned per page.",minify:'"standard" (default): strips blank lines and comment-only lines from patches — smaller responses. "none": raw exact diff text — use when quoting or matching whitespace. "symbols" is not available for PR content.'}};const u=ghHistoryResearch.schema;export const GitHubPullRequestSearchQuerySchema=t(u,{...m,type:e.enum(["prs","commits"]).default("prs"),since:e.string().optional(),until:e.string().optional(),path:e.string().optional(),branch:e.string().optional(),perPage:s(1,100).optional().default(30),includeDiff:e.boolean().optional().default(!1),keywordsToSearch:e.array(e.string()).optional(),query:e.string().optional(),prNumber:s(1,l).optional(),owner:e.string().optional(),repo:e.string().optional(),concise:e.boolean().optional(),state:e.enum(["open","closed","merged"]).optional(),assignee:e.string().optional(),author:e.string().optional(),commenter:e.string().optional(),involves:e.string().optional(),mentions:e.string().optional(),"review-requested":e.string().optional(),"reviewed-by":e.string().optional(),label:e.union([e.string(),e.array(e.string())]).optional(),milestone:e.string().optional(),language:e.string().optional(),checks:e.enum(["success","failure","pending"]).optional(),review:e.enum(["approved","changes_requested","required","none"]).optional(),locked:e.boolean().optional(),visibility:e.enum(["public","private"]).optional(),"team-mentions":e.string().optional(),project:e.string().optional(),"no-label":e.boolean().optional(),"no-milestone":e.boolean().optional(),"no-project":e.boolean().optional(),"no-assignee":e.boolean().optional(),head:e.string().optional(),base:e.string().optional(),created:e.string().optional(),updated:e.string().optional(),closed:e.string().optional(),"merged-at":e.string().optional(),comments:e.string().optional(),reactions:e.string().optional(),interactions:e.string().optional(),draft:e.boolean().optional(),match:e.array(e.enum(["title","body","comments"])).optional(),sort:e.enum(["created","updated","best-match","comments","reactions"]).optional(),order:e.enum(["asc","desc"]).optional(),limit:s(1,r).default(a),page:p(),archived:e.boolean().optional(),filePage:d(),commentPage:d(),commitPage:d(),itemsPerPage:s(1,c).default(i),reviewMode:e.literal("full").optional(),content:t(u,{metadata:e.boolean().optional(),body:e.boolean().optional(),changedFiles:e.boolean().optional(),patches:t(u,{mode:e.enum(["none","selected","all"]).default("none"),files:h,ranges:e.array(t(u,{file:e.string(),additions:e.array(s(1,l)).optional(),deletions:e.array(s(1,l)).optional()},"content.patches.ranges")).optional()},"content.patches").optional(),comments:t(u,{discussion:e.boolean().optional(),reviewInline:e.boolean().optional(),includeBots:e.boolean().default(!1),file:e.string().optional()},"content.comments").optional(),reviews:e.boolean().optional(),commits:t(u,{list:e.boolean().optional(),includeFiles:e.boolean().optional()},"content.commits").optional()},"content").optional(),matchString:e.string().optional(),commentBodyOffset:n(),charOffset:n(),charLength:o(),minify:e.enum(["none","standard"]).default("standard")}).superRefine((e,t)=>{const o=e.content?.patches;if(!o)return;const n=(o.files?.length??0)>0,a=(o.ranges?.length??0)>0,i=n||a;"selected"!==o.mode||i||t.addIssue({code:"custom",message:'content.patches.mode="selected" requires non-empty files or ranges.',path:["content","patches","files"]}),"selected"!==o.mode&&i&&t.addIssue({code:"custom",message:'content.patches.files and content.patches.ranges require mode="selected".',path:["content","patches","mode"]})});
@@ -1,2 +1,23 @@
1
+ import { z } from "zod";
1
2
  import type { ToolSpec } from "../../types/index.js";
2
3
  export declare const ghSearchCode: ToolSpec;
4
+ export declare const GitHubCodeSearchQuerySchema: z.ZodObject<{
5
+ keywords: z.ZodOptional<z.ZodArray<z.ZodString>>;
6
+ owner: z.ZodOptional<z.ZodString>;
7
+ repo: z.ZodOptional<z.ZodString>;
8
+ extension: z.ZodOptional<z.ZodString>;
9
+ filename: z.ZodOptional<z.ZodString>;
10
+ path: z.ZodOptional<z.ZodString>;
11
+ language: z.ZodOptional<z.ZodString>;
12
+ match: z.ZodDefault<z.ZodEnum<{
13
+ file: "file";
14
+ path: "path";
15
+ }>>;
16
+ limit: z.ZodDefault<z.ZodNumber>;
17
+ page: z.ZodDefault<z.ZodNumber>;
18
+ concise: z.ZodOptional<z.ZodBoolean>;
19
+ id: z.ZodOptional<z.ZodString>;
20
+ mainResearchGoal: z.ZodOptional<z.ZodString>;
21
+ researchGoal: z.ZodOptional<z.ZodString>;
22
+ reasoning: z.ZodOptional<z.ZodString>;
23
+ }, z.core.$strip>;
@@ -1 +1 @@
1
- export const ghSearchCode={name:"ghSearchCode",description:'GitHub code and path search.\nmatch:"file" (default) searches file contents, returns snippets with matchIndices. match:"path" searches file paths/names only — no snippet, much cheaper, use to verify a file exists before reading it.\nmatchIndices are char offsets inside the snippet string — NOT file line numbers, NOT usable as lineHint. Get lineHint from ghGetFileContent(matchString=same-keyword).\nEmpty with owner+repo: repo may not be indexed (new or private). Fall back to ghGetFileContent with a known path.\nNext: ghGetFileContent(path, matchString=same-keyword) to read — use files[0].startLine as rough lineHint; ghViewRepoStructure for context; ghSearchRepos if owner/repo unknown.',schema:{keywordsToSearch:"Search keywords. All terms are ANDed — every keyword must appear. Split independent alternatives into separate query objects in the same queries:[q1,q2,...] call (max 5 per call not separate tool calls). Keep an exact phrase in one item. Use match:'path' instead when searching for a file by name.",owner:"Owner/org scope. Alone: restricts to all repos of that org/user. With repo: targets a single repository.",repo:"Repository name (without owner). owner must also be set omitting it returns a scope error.",extension:'Extension filter, no dot ("ts"). Combines with keywords.',language:'GitHub language qualifier (e.g. "TypeScript", "Python"). Matches GitHub\'s language detection broader than extension (covers all relevant extensions for a language).',filename:'Exact filename filter. Matches files whose name equals or contains this value. More precise than keywordsToSearch for known filenames — use instead of keyword search when you know the file name. Examples: "Button.tsx", "jest.config".',path:"Directory-prefix filter (GitHub path:) — matches repo paths starting with this prefix, not a full file path.",match:'"file" (default): searches file contents, returns snippets with matchIndices. "path": searches file paths/names only — no snippets, much cheaper. Use "path" to verify a file exists before reading it.',limit:"Requested results per page.",page:"GitHub result page (1-based). Max page 10 (GitHub caps at 1000 total results).",verbose:"Set true to add html_url per file pinned to the matched commit SHA. Default false lean output. Only enable when you need to surface clickable links."}};
1
+ import{z as e}from"zod";import{buildObject as t,DEFAULT_GITHUB_SEARCH_LIMIT as a,intRange as n,MAX_GITHUB_SEARCH_LIMIT as o,metaFields as i,pageNumber as r,StringArray as s}from"./_toolkit.js";export const ghSearchCode={name:"ghSearchCode",description:'GitHub code and path search. Note: GitHub is deprecating this search API (planned removal ~Sep 2026); prefer ghGetFileContent or ghViewRepoStructure for known paths.\nmatch:"file" searches file contents, returns snippets with matchIndices. match:"path" searches file paths/names only — no snippet, much cheaper, use to verify a file exists before reading it.\nmatchIndices are char offsets inside the snippet string — NOT file line numbers, NOT usable as lineHint. Get lineHint from ghGetFileContent(matchString=same-keyword).\nCaps: ~20 reachable matches per search (1000/~10 pages total) and default-branch only — when the response flags unreachable matches, narrow with owner/repo/path/extension/filename rather than paging; pass a non-default ref via ghGetFileContent/ghViewRepoStructure.\nEmpty with owner+repo: repo may not be indexed (new or private). Fall back to ghGetFileContent with a known path.\nNext: ghGetFileContent(path, matchString=same-keyword) to read — use files[0].startLine as rough lineHint; ghViewRepoStructure for context; ghSearchRepos if owner/repo unknown.',schema:{keywords:"Search terms, all ANDed — every term must appear in a match. One concept per array item; keep a multi-word phrase as one item. Send unrelated alternatives as separate query objects in one queries:[...] call (max 5 per call), not separate tool calls. To find a file by name, use match:'path'.",owner:"Scopes the search to a user/org. Alone it spans all their repos; with repo it targets one repository.",repo:"Repository name without the owner. Requires owner — sending it alone returns a scope error.",extension:'File extension to match, without the leading dot ("ts"). Combines with keywords.',language:'GitHub language qualifier (e.g. "TypeScript", "Python"). Uses GitHub\'s language detection, so it is broader than extension — it covers every extension mapped to that language.',filename:'Matches by file name (equals or contains). Prefer over keywords when you already know the name, e.g. "Button.tsx" or "jest.config".',path:"Matches repo paths beginning with this directory prefix (GitHub path: qualifier) — a prefix, not a full file path.",match:'"file" searches file contents and returns snippets with matchIndices. "path" searches only file paths/names — no snippets, far cheaper; use it to confirm a file exists before reading it.',limit:"Results to return per page.",page:"Result page to fetch. GitHub serves at most 1000 results (~10 pages).",concise:'Set true for minimal orientation: a flat list of "owner/repo:path" strings (no snippets). Cheapest way to locate files; then ghGetFileContent(path) to read. Default returns snippet objects with matchIndices.'}};export const GitHubCodeSearchQuerySchema=t(ghSearchCode.schema,{...i,keywords:s,owner:e.string().optional(),repo:e.string().optional(),extension:e.string().optional(),filename:e.string().optional(),path:e.string().optional(),language:e.string().optional(),match:e.enum(["file","path"]).default("file"),limit:n(1,o).default(a),page:r(),concise:e.boolean().optional()});
@@ -1,2 +1,40 @@
1
+ import { z } from "zod";
1
2
  import type { ToolSpec } from "../../types/index.js";
2
3
  export declare const ghSearchRepos: ToolSpec;
4
+ export declare const GitHubReposSearchSingleQuerySchema: z.ZodObject<{
5
+ keywords: z.ZodOptional<z.ZodArray<z.ZodString>>;
6
+ topicsToSearch: z.ZodOptional<z.ZodArray<z.ZodString>>;
7
+ language: z.ZodOptional<z.ZodString>;
8
+ owner: z.ZodOptional<z.ZodString>;
9
+ stars: z.ZodOptional<z.ZodString>;
10
+ size: z.ZodOptional<z.ZodString>;
11
+ created: z.ZodOptional<z.ZodString>;
12
+ updated: z.ZodOptional<z.ZodString>;
13
+ match: z.ZodOptional<z.ZodArray<z.ZodEnum<{
14
+ description: "description";
15
+ name: "name";
16
+ readme: "readme";
17
+ }>>>;
18
+ sort: z.ZodDefault<z.ZodEnum<{
19
+ stars: "stars";
20
+ updated: "updated";
21
+ forks: "forks";
22
+ "help-wanted-issues": "help-wanted-issues";
23
+ "best-match": "best-match";
24
+ }>>;
25
+ limit: z.ZodDefault<z.ZodNumber>;
26
+ page: z.ZodDefault<z.ZodNumber>;
27
+ archived: z.ZodOptional<z.ZodBoolean>;
28
+ visibility: z.ZodOptional<z.ZodEnum<{
29
+ public: "public";
30
+ private: "private";
31
+ }>>;
32
+ forks: z.ZodOptional<z.ZodString>;
33
+ license: z.ZodOptional<z.ZodString>;
34
+ goodFirstIssues: z.ZodOptional<z.ZodString>;
35
+ concise: z.ZodOptional<z.ZodBoolean>;
36
+ id: z.ZodOptional<z.ZodString>;
37
+ mainResearchGoal: z.ZodOptional<z.ZodString>;
38
+ researchGoal: z.ZodOptional<z.ZodString>;
39
+ reasoning: z.ZodOptional<z.ZodString>;
40
+ }, z.core.$strip>;
@@ -1 +1 @@
1
- export const ghSearchRepos={name:"ghSearchRepos",description:"Discover GitHub repos by name, keywords, owner, topic, language, or popularity.\nOutput modes: verbose:false (default) returns lean pipe-separated strings — fast, for discovery; verbose:true returns structured objects with stars, forks, language, license, topics, dates — required when filtering or comparing programmatically.\nOwner alone enumerates org repos; keywords combine together. topicsToSearch is sparse fewer repos tag topics than set a language.\nFilters use GitHub query format: stars/forks/size accept '>100', '50..500'; created/updated accept '>2023-01-01'.\nNote: providing both topicsToSearch and keywordsToSearch issues two parallel searches (merged, deduplicated) — check evidence.confidence for partial failures.\nBulk: pass multiple independent discovery queries as queries:[{...},{...}] (max 5) e.g. compare several owners/keyword sets in one call instead of one search at a time.\nNext: ghViewRepoStructure, ghSearchCode/ghGetFileContent, npmSearch for npm names.",schema:{keywordsToSearch:"Combined search terms. Use one term per element for broad matching; keep a phrase together for exact wording.",topicsToSearch:"GitHub topic tags to filter by. All listed topics must be present. Sparse most repos don't tag topics. Best combined with keywords or language, not used alone.",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. Format: '>100', '<1000', '50..500', '>=500'. Use to narrow to established or niche repos.",size:"Repository total size in KB (source files + history). '<1000' for small repos; '>10000' for large codebases.",created:"Repo creation date. Format: '>2023-01-01', '<2020-01-01', '2022-01-01..2023-01-01'.",updated:"Last commit push date. Maps to GitHub's pushed: qualifier not a metadata update date. Format: '>2024-01-01'. Use to find actively maintained repos.",match:"Repository text fields to search: name, description, and/or readme. Default searches name and description. Add 'readme' to search README text — broader, slower.",sort:"Sort results. 'stars': most popular first. 'forks': most forked first. 'updated': recently pushed first. 'help-wanted-issues': repos seeking contributors. 'best-match' (default): GitHub relevance.",limit:"Results 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. Format: '>100', '<1000', '50..500', '>=500'.",license:"SPDX license identifier (e.g. 'mit', 'apache-2.0', 'gpl-3.0'). Exact lowercase SPDX key.",goodFirstIssues:"Filter by number of open 'good first issue' labels ('>5'). Use to find repos actively inviting contributors.",verbose:"Output mode. false (default): lean strings. true: structured objects use when filtering programmatically by stars, language, or date."}};
1
+ import{z as e}from"zod";import{buildObject as t,DEFAULT_GITHUB_SEARCH_LIMIT as s,intRange as r,MAX_GITHUB_SEARCH_LIMIT as o,metaFields as a,pageNumber as i,StringArray as n}from"./_toolkit.js";export const ghSearchRepos={name:"ghSearchRepos",description:"Discover GitHub repos by name, keywords, owner, topic, language, or popularity.\nOutput modes: concise:true returns a flat list of \"owner/repo\" strings — minimal orientation, then dive into a chosen repo; default (concise:false) returns structured objects with stars, forks, language, license, topics, dates — required when filtering or comparing programmatically.\nBulk: pass multiple independent discovery queries as queries:[{...},{...}] (max 5) — e.g. compare several owners/keyword sets in one call instead of one search at a time.\nOwner alone enumerates org repos; keywords combine together. topicsToSearch AND semantics: all listed topics must be present (GitHub topic:react topic:typescript). Providing both topicsToSearch and keywords issues two separate parallel searches (merged, deduplicated, OR semantics across them) — use a single set of keywords for strict AND. topicsToSearch is sparse fewer repos tag topics than set a language. Filters use GitHub query format: stars/forks/size accept '>100', '50..500'; created/updated accept '>2023-01-01'.\nNext: ghViewRepoStructure, ghSearchCode/ghGetFileContent, npmSearch for npm names.",schema:{keywords:"Search terms. One term per array item for broad matching; keep a phrase in one item for exact wording.",topicsToSearch:"GitHub topic tags to require all listed topics must be present. Sparse (most repos set no topics), so pair with keywords or language rather than using alone.",language:"Repository language qualifier (GitHub detection).",owner:"User/org scope. Without keywords it enumerates that owner's repos; with keywords it scopes the search to them.",stars:"Star-count filter using GitHub range syntax: '>100', '<1000', '50..500', '>=500'.",size:"Repository size in KB (sources + history): '<1000' for small repos, '>10000' for large codebases.",created:"Creation-date filter (GitHub range syntax): '>2023-01-01', '<2020-01-01', '2022-01-01..2023-01-01'.",updated:"Last-push-date filter (GitHub's pushed: qualifier, not metadata updates): '>2024-01-01'. Finds actively maintained repos.",match:"Which text fields to search: name, description, and/or readme. Defaults to name+description; add 'readme' for broader, slower full-text search.",sort:"Result ordering. 'stars': most-starred first. 'forks': most-forked first. 'updated': most-recently-pushed first. 'help-wanted-issues': repos seeking contributors. 'best-match': GitHub relevance.",limit:"Results to return per page.",page:"Result page.",archived:"Include archived repos (excluded by default).",visibility:"'public' or 'private' (private needs a repo-scoped token). Omit to include both.",forks:"Fork-count filter (GitHub range syntax): '>100', '<1000', '50..500'.",license:"Exact lowercase SPDX license id, e.g. 'mit', 'apache-2.0', 'gpl-3.0'.",goodFirstIssues:"Filters by count of open 'good first issue' labels ('>5') finds repos inviting contributors.",concise:'Set true for minimal orientation: a flat list of "owner/repo" strings only. Cheapest way to scan candidates; then re-run without concise (or ghViewRepoStructure) on the one you pick. Default returns structured objects with stars, language, topics, dates.'}};export const GitHubReposSearchSingleQuerySchema=t(ghSearchRepos.schema,{...a,keywords:n,topicsToSearch:n,language:e.string().optional(),owner:e.string().optional(),stars:e.string().optional(),size:e.string().optional(),created:e.string().optional(),updated:e.string().optional(),match:e.array(e.enum(["name","description","readme"])).optional(),sort:e.enum(["stars","forks","help-wanted-issues","updated","best-match"]).default("best-match"),limit:r(1,o).default(s),page:i(),archived:e.boolean().optional(),visibility:e.enum(["public","private"]).optional(),forks:e.string().optional(),license:e.string().optional(),goodFirstIssues:e.string().optional(),concise:e.boolean().optional()});
@@ -1,2 +1,17 @@
1
+ import { z } from "zod";
1
2
  import type { ToolSpec } from "../../types/index.js";
2
3
  export declare const ghViewRepoStructure: ToolSpec;
4
+ export declare const GitHubViewRepoStructureQuerySchema: z.ZodObject<{
5
+ owner: z.ZodString;
6
+ repo: z.ZodString;
7
+ branch: z.ZodOptional<z.ZodString>;
8
+ path: z.ZodOptional<z.ZodString>;
9
+ maxDepth: z.ZodOptional<z.ZodNumber>;
10
+ page: z.ZodDefault<z.ZodNumber>;
11
+ itemsPerPage: z.ZodDefault<z.ZodNumber>;
12
+ includeSizes: z.ZodOptional<z.ZodBoolean>;
13
+ id: z.ZodOptional<z.ZodString>;
14
+ mainResearchGoal: z.ZodOptional<z.ZodString>;
15
+ researchGoal: z.ZodOptional<z.ZodString>;
16
+ reasoning: z.ZodOptional<z.ZodString>;
17
+ }, z.core.$strip>;
@@ -1 +1 @@
1
- export const ghViewRepoStructure={name:"ghViewRepoStructure",description:'Browse a GitHub repository\'s directory tree. Returns files[], folders[], and a summary at each level.\nUse this to map an unknown repo before searching. Use ghSearchCode(match:"path") when you know a partial filename — faster.\nSet path to browse a subtree; omit for repo root. Set depth to control recursion (immediate children only unless raised).\nIgnored paths: node_modules, .git, dist, build, and other artifacts are automatically excluded from results.\nOutput key is structure[] (array of {dir, files[], folders[]}). Paginate with page=N when pagination.hasMore is true.\nBulk: pass multiple {owner,repo,path} objects as queries:[{...},{...}] (max 5) to explore several paths in one call.\nNext: ghGetFileContent(path) to read files; ghSearchCode to search within a known path.',schema:{owner:"GitHub repository owner or organization.",repo:"GitHub repository name without the owner.",branch:"Branch, tag, or commit SHA. Omit to use the repository default branch. If not found, the default branch is used and a warning hint is emitted.",path:'Repo-relative directory to browse. Use "" or "." for the root. Use a subdirectory path (e.g. "src/utils") to scope the tree. No leading slash.',depth:"Recursion depth — immediate children only unless raised. Set 2+ to recurse into subdirectories.",page:"Result page (1-based). Advance only when pagination.hasMore is true.",itemsPerPage:"Entries per page. Raise to reduce round-trips on large repos."}};
1
+ import{z as e}from"zod";import{buildObject as t,DEFAULT_GITHUB_STRUCTURE_ITEMS_PER_PAGE as r,intRange as o,MAX_GITHUB_STRUCTURE_ITEMS_PER_PAGE as a,MAX_LOCAL_DEPTH as i,metaFields as s,pageNumber as n}from"./_toolkit.js";export const ghViewRepoStructure={name:"ghViewRepoStructure",description:'Browse a GitHub repository\'s directory tree. Returns files[], folders[], and a summary at each level.\nUse this to map an unknown repo before searching. Use ghSearchCode(match:"path") when you know a partial filename — faster.\nSet path to browse a subtree; omit for repo root. Set maxDepth to control recursion (immediate children only unless raised).\nIgnored paths: node_modules, .git, dist, build, and other artifacts are automatically excluded from results.\nOutput key is structure[] (array of {dir, files[], folders[]}). Paginate with page=N when pagination.hasMore is true.\nBulk: pass multiple {owner,repo,path} objects as queries:[{...},{...}] (max 5) to explore several paths in one call.\nNext: ghGetFileContent(path) to read files; ghSearchCode to search within a known path.',schema:{owner:"Repository owner or org.",repo:"Repository name, without the owner.",branch:"Branch, tag, or commit SHA. Omit for the default branch; if the ref isn't found the default branch is used and a warning hint is emitted.",path:'Repo-relative directory to browse. "" or "." for the root, or a subdirectory (e.g. "src/utils") to scope the tree. No leading slash.',maxDepth:"How deep to recurse — immediate children only unless raised. Set 2+ to descend into subdirectories.",page:"Result page. Advance only when pagination.hasMore is true.",itemsPerPage:"Entries per page. Raise to cut round-trips on large repos.",includeSizes:"Adds file sizes (bytes) in a fileSizes field alongside the structure."}};export const GitHubViewRepoStructureQuerySchema=t(ghViewRepoStructure.schema,{...s,owner:e.string(),repo:e.string(),branch:e.string().optional(),path:e.string().optional(),maxDepth:o(0,i).optional(),page:n(),itemsPerPage:o(1,a).default(r),includeSizes:e.boolean().optional()});
@@ -0,0 +1,40 @@
1
+ import { z } from "zod";
2
+ import type { ToolSpec } from "../../types/index.js";
3
+ export declare const localBinaryInspect: ToolSpec;
4
+ export declare const LocalBinaryInspectQuerySchema: z.ZodObject<{
5
+ path: z.ZodString;
6
+ mode: z.ZodEnum<{
7
+ list: "list";
8
+ identify: "identify";
9
+ extract: "extract";
10
+ decompress: "decompress";
11
+ strings: "strings";
12
+ unpack: "unpack";
13
+ }>;
14
+ verbose: z.ZodOptional<z.ZodBoolean>;
15
+ maxEntries: z.ZodDefault<z.ZodNumber>;
16
+ entriesPerPage: z.ZodOptional<z.ZodNumber>;
17
+ entryPageNumber: z.ZodDefault<z.ZodNumber>;
18
+ archiveFile: z.ZodOptional<z.ZodString>;
19
+ matchString: z.ZodOptional<z.ZodString>;
20
+ matchStringContextLines: z.ZodDefault<z.ZodNumber>;
21
+ charOffset: z.ZodOptional<z.ZodNumber>;
22
+ charLength: z.ZodOptional<z.ZodNumber>;
23
+ format: z.ZodDefault<z.ZodEnum<{
24
+ auto: "auto";
25
+ gzip: "gzip";
26
+ bzip2: "bzip2";
27
+ xz: "xz";
28
+ lzma: "lzma";
29
+ zstd: "zstd";
30
+ lz4: "lz4";
31
+ brotli: "brotli";
32
+ lzfse: "lzfse";
33
+ }>>;
34
+ minLength: z.ZodDefault<z.ZodNumber>;
35
+ includeOffsets: z.ZodOptional<z.ZodBoolean>;
36
+ id: z.ZodOptional<z.ZodString>;
37
+ mainResearchGoal: z.ZodOptional<z.ZodString>;
38
+ researchGoal: z.ZodOptional<z.ZodString>;
39
+ reasoning: z.ZodOptional<z.ZodString>;
40
+ }, z.core.$strip>;
@@ -0,0 +1 @@
1
+ import{z as e}from"zod";import{buildObject as t,charLength as a,charOffset as r,intRange as s,metaFields as i,pageNumber as n}from"./_toolkit.js";export const localBinaryInspect={name:"localBinaryInspect",description:"Look inside an archive, a compressed stream, or a binary. Requires ENABLE_BINARY=true + ENABLE_LOCAL=true; when disabled, use localSearchCode(searchBinary:true) for pattern sweeps.\nUse when a file is binary, packed, or unknown — pick the mode for the job (see the mode field). Not for plain text (use localGetFileContent) or searching across many entries (use localSearchCode).\nFlow inside this tool: identify (what is it) → list (archive structure) → extract an entry or decompress a stream (its content) → unpack (whole archive to disk for multi-file work) → strings (symbols/URLs in a native binary).\nFull chain across local tools — this tool only unpacks: discover (localFindFiles / localViewStructure) → unpack (localBinaryInspect) → read (localGetFileContent) → search (localSearchCode) → analyze (lspGetSemantics).\nOutput signals: totalEntries above the returned count = truncated (page with entryPageNumber); extract/decompress/strings output is char-paginated — advance charOffset from hints; content may be binary. unpack returns localPath of the extracted tree — then point localViewStructure/localSearchCode/localGetFileContent at it. If decompress rejects a multi-entry archive, use list/extract or unpack instead.",schema:{path:"Path to the archive, compressed file, or binary — absolute or workspace-relative.",mode:'Pick by what you have and what you want back. "identify": unknown file → its type + magic bytes; start here when you are not sure what the file is. "list": an archive (.zip/.jar/.tar.*/.7z/.deb/.dmg…) → its entry names, so you can see what is inside before pulling anything out. "extract": an archive → one entry\'s content; set archiveFile to an exact name from a prior list. "decompress": a single-stream compressed file (.gz/.bz2/.xz/.zst/.lz4/.br/.lzfse — one payload, not a multi-entry archive) → its text. "strings": a native binary (.so/.dylib/.node/.exe/.wasm) → its readable strings (symbols, URLs, version markers). "unpack": an archive → ALL entries extracted to a cached local directory; returns localPath so you can then run localViewStructure / localSearchCode / localGetFileContent on the unpacked tree. Use for multi-file work inside an archive (extract is for a single entry). Required — there is no default.',verbose:"list: include each entry's size and mtime (names only otherwise).",maxEntries:"list: caps how many entries are returned; totalEntries still reports the full archive count.",entriesPerPage:"list: entries per page; pair with entryPageNumber.",entryPageNumber:"list: which entry page to return; pair with entriesPerPage.",archiveFile:'extract: exact entry path to stream out (case-sensitive, must not start with "-"). Run mode="list" first — do not guess entry names.',matchString:"extract/decompress: keeps only streamed lines matching this text, with matchStringContextLines around each.",matchStringContextLines:"extract/decompress: context lines kept around each matchString hit.",charOffset:"extract/decompress: continuation offset for the next page; take it from hints[] — do not compute it yourself.",charLength:"extract/decompress: page size in characters. Auto-paginates when unset.",format:'decompress: compression format. "auto" detects from the file extension; override when the extension is wrong: gzip|bzip2|xz|lzma|zstd|lz4|brotli|lzfse.',minLength:"strings: shortest printable run to keep. Raise (e.g. 12–16) to surface only symbols/URLs.",includeOffsets:"strings: prefixes each string with its hex byte offset — handy for pivoting to localSearchCode(searchBinary:true)."}};const o=[".tar.gz",".tgz",".tar.bz2",".tbz2",".tbz",".tar.xz",".txz",".tar.zst",".tzst",".zip",".jar",".war",".apk",".7z"];export const LocalBinaryInspectQuerySchema=t(localBinaryInspect.schema,{...i,path:e.string(),mode:e.enum(["identify","list","extract","decompress","strings","unpack"]),verbose:e.boolean().optional(),maxEntries:s(1,1e4).default(1e3),entriesPerPage:s(1,100).optional(),entryPageNumber:n(),archiveFile:e.string().optional(),matchString:e.string().optional(),matchStringContextLines:s(0,50).default(3),charOffset:r(),charLength:a(),format:e.enum(["auto","gzip","bzip2","xz","lzma","zstd","lz4","brotli","lzfse"]).default("auto"),minLength:s(1,128).default(8),includeOffsets:e.boolean().optional()}).superRefine((e,t)=>{"extract"!==e.mode||e.archiveFile||t.addIssue({code:"custom",path:["archiveFile"],message:'archiveFile is required for mode="extract" — run mode="list" first to get exact entry names'}),e.archiveFile?.startsWith("-")&&t.addIssue({code:"custom",path:["archiveFile"],message:'archiveFile must not start with "-" (prevents flag injection)'}),"decompress"===e.mode&&o.some(t=>e.path.toLowerCase().endsWith(t))&&t.addIssue({code:"custom",path:["mode"],message:'This path looks like a multi-entry archive — use mode="list" or mode="extract" instead of mode="decompress". decompress is for single-stream files only (.gz, .bz2, .xz, .zst, .lz4, .br, .lzfse).'})});
@@ -1,2 +1,41 @@
1
+ import { z } from "zod";
1
2
  import type { ToolSpec } from "../../types/index.js";
2
3
  export declare const localFindFiles: ToolSpec;
4
+ export declare const FindFilesQuerySchema: z.ZodObject<{
5
+ path: z.ZodString;
6
+ maxDepth: z.ZodOptional<z.ZodNumber>;
7
+ minDepth: z.ZodOptional<z.ZodNumber>;
8
+ names: z.ZodOptional<z.ZodArray<z.ZodString>>;
9
+ pathPattern: z.ZodOptional<z.ZodString>;
10
+ regex: z.ZodOptional<z.ZodString>;
11
+ empty: z.ZodOptional<z.ZodBoolean>;
12
+ modifiedWithin: z.ZodOptional<z.ZodString>;
13
+ modifiedBefore: z.ZodOptional<z.ZodString>;
14
+ accessedWithin: z.ZodOptional<z.ZodString>;
15
+ sizeGreater: z.ZodOptional<z.ZodString>;
16
+ sizeLess: z.ZodOptional<z.ZodString>;
17
+ permissions: z.ZodOptional<z.ZodString>;
18
+ executable: z.ZodOptional<z.ZodBoolean>;
19
+ readable: z.ZodOptional<z.ZodBoolean>;
20
+ writable: z.ZodOptional<z.ZodBoolean>;
21
+ excludeDir: z.ZodOptional<z.ZodArray<z.ZodString>>;
22
+ limit: z.ZodOptional<z.ZodNumber>;
23
+ details: z.ZodOptional<z.ZodBoolean>;
24
+ showFileLastModified: z.ZodOptional<z.ZodBoolean>;
25
+ sortBy: z.ZodDefault<z.ZodEnum<{
26
+ path: "path";
27
+ modified: "modified";
28
+ size: "size";
29
+ name: "name";
30
+ }>>;
31
+ entryType: z.ZodOptional<z.ZodEnum<{
32
+ f: "f";
33
+ d: "d";
34
+ }>>;
35
+ page: z.ZodDefault<z.ZodNumber>;
36
+ itemsPerPage: z.ZodOptional<z.ZodNumber>;
37
+ id: z.ZodOptional<z.ZodString>;
38
+ mainResearchGoal: z.ZodOptional<z.ZodString>;
39
+ researchGoal: z.ZodOptional<z.ZodString>;
40
+ reasoning: z.ZodOptional<z.ZodString>;
41
+ }, z.core.$strip>;
@@ -1 +1 @@
1
- export const localFindFiles={name:"localFindFiles",description:'Find local files and directories by metadata — name pattern, path glob, size, modification time, permissions. Returns paths and metadata, not file content. More efficient than localSearchCode when you only need file locations.\nUse cases: "what changed recently?" → modifiedWithin:"24h", sortBy:"modified", showFileLastModified:true; "find test files" → names:["*.test.ts"], pathPattern:"src/**"; "find large files" → sizeGreater:"1m", sortBy:"size"; "find all index files" → regex:"^index\\."; "find directories" → entryType:"d".\nDefault excludeDir: node_modules, dist, .git, build, .next, coverage, and IDE/tool dirs — pass excludeDir:[] to disable. Time units: d=days, h=hours, w=weeks, m=minutes.\nBulk: up to 5 independent query objects in one call.\nValidation: minDepth must be <= maxDepth.\nNext: localGetFileContent(path) to read a found file; localSearchCode(keywords, path) to search content; localViewStructure(path) for directory tree browsing.',schema:{path:"Search root, absolute or workspace-relative.",maxDepth:"Upper directory depth bound. maxDepth:0 = root only; maxDepth:1 = root and immediate children. Pair with minDepth for a depth window.",minDepth:"Lower directory depth bound. Pair with maxDepth for a depth window (e.g. minDepth:2 + maxDepth:2 = exactly two levels deep). Must be <= maxDepth.",names:'Basename glob array. Any listed glob may match (OR logic). Example: ["*.ts", "*.tsx", "package.json"]. Use for extension-based or name-pattern file discovery.',pathPattern:"Full-path glob filter. Matches files whose full path matches this glob. Use for monorepo slice filtering: 'packages/*/src/**' finds src directories across all packages.",regex:"Rust regex against the basename only (not full path). More powerful than names[] for precise matching. Example: '^(index|main)\\.(ts|js)$' matches index.ts, main.js.",empty:"Match empty files (0 bytes) or directories with no children.",modifiedWithin:"Only files modified within the past N. Format: '7d' (days), '2h' (hours), '1w' (weeks), '30m' (minutes). Use for 'what changed recently' queries.",modifiedBefore:"Only files NOT modified in the past N — last touched more than N ago. Format same as modifiedWithin. Use to find stale or abandoned files.",accessedWithin:"Only files accessed within the past N. Format same as modifiedWithin.",sizeGreater:"Only files larger than this size. Format: '100k', '1m', '500b'. Use to find large generated files, bundles, or assets.",sizeLess:"Only files smaller than this size. Same format as sizeGreater.",executable:"Filter to files executable by the current process (-x).",readable:"Filter to files readable by the current process (-r).",writable:"Filter to files writable by the current process (-w).",excludeDir:"Directory names to skip. Default when omitted: [node_modules, dist, .git, build, .next, coverage, and IDE dirs]. Pass [] to search all directories.",limit:"Pre-pagination cap on discovered entries. Distinct from page size.",details:"Set true to add size and permissions per entry. Does NOT include timestamps — use showFileLastModified:true separately.",showFileLastModified:"Set true to include last-modified timestamps per entry. Required to see modification dates when sortBy:'modified'. Independent of details.",sortBy:"'modified' (default): newest-modified first — requires showFileLastModified:true for actual time ordering; without it falls back to path sort. 'size': largest first. 'name': alphabetical basename. 'path': full path alphabetical.",entryType:'"f" for files only, "d" for directories only. Omit to match both.',permissions:"Unix permission filter in find -perm format (e.g. '755', '-u+x'). Omit unless you need to filter by exact permission bits.",page:"Result page (1-based).",itemsPerPage:"Entries per page."}};
1
+ import{z as e}from"zod";import{buildObject as t,intRange as i,MAX_FIND_DEPTH as s,MAX_LOCAL_ITEMS_PER_PAGE as o,MAX_LOCAL_LIMIT as a,metaFields as n,pageNumber as r,StringArray as l}from"./_toolkit.js";export const localFindFiles={name:"localFindFiles",description:'Find local files and directories by metadata — name pattern, path glob, size, modification time, permissions. Returns paths and metadata, not file content. More efficient than localSearchCode when you only need file locations.\nUse cases: "what changed recently?" → modifiedWithin:"24h", sortBy:"modified", showFileLastModified:true; "find test files" → names:["*.test.ts"], pathPattern:"src/**"; "find large files" → sizeGreater:"1m", sortBy:"size"; "find all index files" → regex:"^index\\."; "find directories" → entryType:"d".\nDefault excludeDir: node_modules, dist, .git, build, .next, coverage, and IDE/tool dirs — pass excludeDir:[] to disable. Time units: d=days, h=hours, w=weeks, m=minutes.\nBulk: up to 5 independent query objects in one call.\nValidation: minDepth must be <= maxDepth.\nNext: localGetFileContent(path) to read a found file; localSearchCode(keywords, path) to search content; localViewStructure(path) for directory tree browsing.',schema:{path:"Directory to search from (absolute or workspace-relative).",maxDepth:"Deepest directory level to descend (0 = root only, 1 = root + immediate children). Pair with minDepth for a depth window.",minDepth:"Shallowest level to include; must be <= maxDepth. Pair with maxDepth for an exact band (e.g. minDepth:2 + maxDepth:2 = exactly two levels deep).",names:'Basename globs; a file matches if it matches ANY listed glob (OR). E.g. ["*.ts", "*.tsx", "package.json"]. Use for extension- or name-pattern discovery.',pathPattern:"Glob over the full path. Use for monorepo slicing, e.g. 'packages/*/src/**' to reach src across all packages.",regex:"Rust regex over the basename only (not the full path) more precise than names[]. E.g. '^(index|main)\\.(ts|js)$'.",empty:"Matches empty files (0 bytes) or childless directories.",modifiedWithin:"Keeps files modified within the past window: '7d', '2h', '1w', '30m'. Use for 'what changed recently'.",modifiedBefore:"Keeps files last modified longer ago than the window (same format as modifiedWithin) finds stale or abandoned files.",accessedWithin:"Keeps files accessed within the past window (same format as modifiedWithin).",sizeGreater:"Keeps files larger than this size: '100k', '1m', '500b'. Use to find bundles, generated files, or assets.",sizeLess:"Keeps files smaller than this size (same format as sizeGreater).",executable:"Keeps files executable by the current process.",readable:"Keeps files readable by the current process.",writable:"Keeps files writable by the current process.",excludeDir:"Directory names to skip. Defaults to [node_modules, dist, .git, build, .next, coverage, IDE dirs] when omitted; pass [] to search everything.",limit:"Caps how many entries are discovered before pagination. Distinct from page size.",details:"Adds size and permissions per entry. Does NOT add timestamps — set showFileLastModified for those.",showFileLastModified:"Adds last-modified timestamps per entry. Required for real time ordering with sortBy:'modified'. Independent of details.",sortBy:"Ordering. 'modified': newest first — needs showFileLastModified for true time order, else falls back to path. 'size': largest first. 'name': basename A–Z. 'path': full path A–Z.",entryType:'"f" matches files only, "d" directories only; omit to match both.',permissions:"Permission filter (e.g. '755', '-u+x'). Omit unless filtering by exact permission bits.",page:"Result page.",itemsPerPage:"Entries per page."}};export const FindFilesQuerySchema=t(localFindFiles.schema,{...n,path:e.string(),maxDepth:i(0,s).optional(),minDepth:i(0,s).optional(),names:l,pathPattern:e.string().optional(),regex:e.string().optional(),empty:e.boolean().optional(),modifiedWithin:e.string().optional(),modifiedBefore:e.string().optional(),accessedWithin:e.string().optional(),sizeGreater:e.string().optional(),sizeLess:e.string().optional(),permissions:e.string().optional(),executable:e.boolean().optional(),readable:e.boolean().optional(),writable:e.boolean().optional(),excludeDir:l,limit:i(1,a).optional(),details:e.boolean().optional(),showFileLastModified:e.boolean().optional(),sortBy:e.enum(["modified","name","path","size"]).default("modified"),entryType:e.enum(["f","d"]).optional(),page:r(),itemsPerPage:i(1,o).optional()}).superRefine((e,t)=>{void 0!==e.minDepth&&void 0!==e.maxDepth&&e.minDepth>e.maxDepth&&t.addIssue({code:"custom",message:"minDepth must be less than or equal to maxDepth.",path:["minDepth"]})});