octocode-cli 1.5.1 → 1.5.3

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 (112) hide show
  1. package/README.md +28 -9
  2. package/out/chunks/chunk-375ZNU3A.js +317 -0
  3. package/out/chunks/{chunk-V64AXUWB.js → chunk-AYILFPX4.js} +1 -1
  4. package/out/chunks/chunk-BRHVQB64.js +10 -0
  5. package/out/chunks/{command-help-specs-JZXVSLZ5.js → chunk-KWJUBVXJ.js} +1 -1
  6. package/out/chunks/chunk-OMXWZJBJ.js +100 -0
  7. package/out/chunks/command-help-specs-RVJK6V6M.js +8 -0
  8. package/out/chunks/commands-JFDCC4Q7.js +8 -0
  9. package/out/chunks/{help-P7TCOYAJ.js → help-H3WGUJO7.js} +1 -1
  10. package/out/chunks/main-help-BUTDD4IR.js +10 -0
  11. package/out/chunks/{spinner-URV2OX6O.js → spinner-DXD4JQIU.js} +1 -1
  12. package/out/chunks/tool-command-L6PVHUNS.js +8 -0
  13. package/out/octocode-cli.js +1 -1
  14. package/package.json +2 -2
  15. package/skills/octocode-brainstorming/scripts/tavily-search.mjs +1 -10
  16. package/skills/octocode-chrome-devtools/scripts/cdp-runner.mjs +0 -2
  17. package/skills/octocode-chrome-devtools/scripts/cdp-sandbox.mjs +1 -5
  18. package/skills/octocode-chrome-devtools/scripts/cdp-template.mjs +1 -10
  19. package/skills/octocode-chrome-devtools/scripts/open-browser.mjs +0 -3
  20. package/skills/octocode-chrome-devtools/scripts/sourcemap-resolver.mjs +1 -4
  21. package/skills/octocode-chrome-devtools/scripts/undercover.mjs +0 -2
  22. package/skills/octocode-engineer/SKILL.md +7 -33
  23. package/skills/octocode-engineer/references/cli-reference.md +5 -11
  24. package/skills/octocode-engineer/references/externals.md +0 -4
  25. package/skills/octocode-engineer/references/quality-indicators.md +10 -50
  26. package/skills/octocode-engineer/references/tool-workflows.md +10 -13
  27. package/skills/octocode-engineer/src/analysis/dependency-summary.test.ts +2 -2
  28. package/skills/octocode-engineer/src/ast/metrics.test.ts +2 -2
  29. package/skills/octocode-engineer/src/ast/search-main.ts +2 -15
  30. package/skills/octocode-engineer/src/ast/search.ts +1 -7
  31. package/skills/octocode-engineer/src/ast/tree-sitter.test.ts +4 -4
  32. package/skills/octocode-engineer/src/ast/tree-sitter.ts +2 -2
  33. package/skills/octocode-engineer/src/collectors/chains.ts +3 -10
  34. package/skills/octocode-engineer/src/collectors/prototype-pollution.ts +3 -3
  35. package/skills/octocode-engineer/src/collectors/security.ts +3 -3
  36. package/skills/octocode-engineer/src/common/ensure-deps.ts +3 -20
  37. package/skills/octocode-engineer/src/detectors/code-quality.ts +0 -1
  38. package/skills/octocode-engineer/src/index.test.ts +1 -1
  39. package/skills/octocode-engineer/src/index.ts +1 -11
  40. package/skills/octocode-engineer/src/pipeline/affected.ts +2 -7
  41. package/skills/octocode-engineer/src/pipeline/baseline.ts +2 -8
  42. package/skills/octocode-engineer/src/pipeline/cache.ts +2 -2
  43. package/skills/octocode-engineer/src/pipeline/config-loader.test.ts +1 -2
  44. package/skills/octocode-engineer/src/pipeline/config-loader.ts +0 -9
  45. package/skills/octocode-engineer/src/pipeline/create-options.ts +2 -15
  46. package/skills/octocode-engineer/src/pipeline/reporters.ts +2 -12
  47. package/skills/octocode-engineer/src/reporting/summary-md.test.ts +2 -2
  48. package/skills/octocode-engineer/src/run.ts +1 -7
  49. package/skills/octocode-engineer/src/types/constants.ts +0 -5
  50. package/skills/octocode-engineer/src/types/core.ts +0 -5
  51. package/skills/octocode-news/eslint.config.mjs +1 -6
  52. package/skills/octocode-news/src/rss-core.ts +2 -4
  53. package/skills/octocode-research/ecosystem.config.cjs +0 -31
  54. package/skills/octocode-research/package.json +1 -1
  55. package/skills/octocode-research/scripts/server.js +272 -230
  56. package/skills/octocode-research/src/__tests__/integration/circuitBreaker.test.ts +0 -24
  57. package/skills/octocode-research/src/__tests__/integration/routes.test.ts +0 -10
  58. package/skills/octocode-research/src/__tests__/integration/serverLifecycle.test.ts +5 -22
  59. package/skills/octocode-research/src/__tests__/integration/toolsRoutes.test.ts +0 -27
  60. package/skills/octocode-research/src/__tests__/unit/circuitBreaker.test.ts +0 -29
  61. package/skills/octocode-research/src/__tests__/unit/errorHandler.test.ts +1 -12
  62. package/skills/octocode-research/src/__tests__/unit/httpPreprocess.test.ts +1 -9
  63. package/skills/octocode-research/src/__tests__/unit/logger.test.ts +0 -7
  64. package/skills/octocode-research/src/__tests__/unit/queryParser.test.ts +1 -7
  65. package/skills/octocode-research/src/__tests__/unit/responseBuilder.test.ts +0 -11
  66. package/skills/octocode-research/src/__tests__/unit/retry.test.ts +1 -18
  67. package/skills/octocode-research/src/__tests__/unit/schemas.test.ts +2 -25
  68. package/skills/octocode-research/src/index.ts +0 -27
  69. package/skills/octocode-research/src/mcpCache.ts +3 -18
  70. package/skills/octocode-research/src/middleware/errorHandler.ts +1 -4
  71. package/skills/octocode-research/src/middleware/logger.ts +1 -6
  72. package/skills/octocode-research/src/middleware/queryParser.ts +3 -22
  73. package/skills/octocode-research/src/routes/github.ts +0 -11
  74. package/skills/octocode-research/src/routes/local.ts +0 -12
  75. package/skills/octocode-research/src/routes/lsp.ts +1 -10
  76. package/skills/octocode-research/src/routes/package.ts +0 -2
  77. package/skills/octocode-research/src/routes/prompts.ts +2 -32
  78. package/skills/octocode-research/src/routes/tools.ts +12 -177
  79. package/skills/octocode-research/src/server-init.ts +0 -32
  80. package/skills/octocode-research/src/server.ts +8 -37
  81. package/skills/octocode-research/src/types/errorGuards.ts +0 -15
  82. package/skills/octocode-research/src/types/guards.ts +6 -27
  83. package/skills/octocode-research/src/types/mcp.ts +1 -8
  84. package/skills/octocode-research/src/types/responses.ts +0 -15
  85. package/skills/octocode-research/src/utils/asyncTimeout.ts +1 -63
  86. package/skills/octocode-research/src/utils/circuitBreaker.ts +43 -166
  87. package/skills/octocode-research/src/utils/colors.ts +3 -17
  88. package/skills/octocode-research/src/utils/errorQueue.ts +6 -28
  89. package/skills/octocode-research/src/utils/logger.ts +11 -93
  90. package/skills/octocode-research/src/utils/resilience.ts +22 -77
  91. package/skills/octocode-research/src/utils/responseBuilder.ts +26 -78
  92. package/skills/octocode-research/src/utils/responseFactory.ts +0 -7
  93. package/skills/octocode-research/src/utils/responseParser.ts +11 -59
  94. package/skills/octocode-research/src/utils/retry.ts +12 -75
  95. package/skills/octocode-research/src/utils/routeFactory.ts +10 -61
  96. package/skills/octocode-research/src/utils/url.ts +0 -5
  97. package/skills/octocode-research/src/validation/httpPreprocess.ts +15 -61
  98. package/skills/octocode-research/src/validation/schemas.ts +14 -101
  99. package/skills/octocode-research/src/validation/toolCallSchema.ts +5 -65
  100. package/skills/octocode-research/tsdown.config.ts +2 -7
  101. package/skills/octocode-search-skill/SKILL.md +9 -2
  102. package/skills/octocode-search-skill/references/discovery-surfaces.md +2 -1
  103. package/skills/octocode-slides/scripts/navbridge.js +1 -14
  104. package/skills/octocode-slides/scripts/presenter.js +2 -61
  105. package/skills/octocode-stats/scripts/build_dashboard.mjs +1 -19
  106. package/out/chunks/chunk-7476PETK.js +0 -309
  107. package/out/chunks/chunk-OQBJTZWK.js +0 -60
  108. package/out/chunks/chunk-UCZCF3BQ.js +0 -9
  109. package/out/chunks/commands-XBFPLHSQ.js +0 -8
  110. package/out/chunks/main-help-ULF5PAQY.js +0 -10
  111. package/out/chunks/tool-command-M6VA7P2F.js +0 -8
  112. package/skills/octocode-research/AGENTS.md +0 -349
@@ -1,88 +1,42 @@
1
- /**
2
- * Route handler factory for reducing boilerplate in route files.
3
- *
4
- * Abstracts the common pattern:
5
- * 1. Parse and validate query params
6
- * 2. Execute tool with resilience wrapper
7
- * 3. Parse tool response
8
- * 4. Transform data to response format
9
- * 5. Send response with appropriate status
10
- *
11
- * @module utils/routeFactory
12
- */
13
-
14
1
  import type { Request, Response, NextFunction, RequestHandler } from 'express';
15
- import type { z } from 'zod/v4';
2
+ import type { z } from 'zod';
16
3
  import { parseAndValidate } from '../middleware/queryParser.js';
17
4
  import { parseToolResponse, type ParsedResponse } from './responseParser.js';
18
5
 
19
- /**
20
- * Resilience wrapper type - matches the signature of withLocalResilience, withGitHubResilience, etc.
21
- */
6
+
22
7
  type ResilienceWrapper = <T>(
23
8
  fn: () => Promise<T>,
24
9
  toolName: string
25
10
  ) => Promise<T>;
26
11
 
27
- /**
28
- * Transformer function type - converts parsed tool response to final response
29
- */
12
+
30
13
  type ResponseTransformer<TQuery, TResponse> = (
31
14
  parsed: ParsedResponse,
32
15
  queries: TQuery[]
33
16
  ) => TResponse;
34
17
 
35
- /**
36
- * MCP tool function type for the route factory.
37
- *
38
- * Uses `any` for the params intentionally: HTTP schemas produce slightly different
39
- * types than MCP tool functions expect (optional vs required fields, auto-generated id).
40
- * Type safety is enforced by Zod schema validation at runtime, not by static types
41
- * at this HTTP→MCP boundary.
42
- */
18
+
43
19
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
20
  type McpToolFn = (params: any) => Promise<any>;
45
21
 
46
- /**
47
- * Route configuration options.
48
- * TQuery flows from schema validation through to response transformation.
49
- * The toolFn boundary uses McpToolFn because the schema's runtime transforms
50
- * (defaults, id generation) produce MCP-compatible data that TypeScript can't verify.
51
- */
22
+
52
23
  interface RouteConfig<TQuery, TResponse> {
53
- /** Zod schema for query validation - accepts schemas with transforms */
24
+
54
25
  schema: z.ZodType<TQuery>;
55
26
 
56
- /** The MCP tool function to execute */
27
+
57
28
  toolFn: McpToolFn;
58
29
 
59
- /** Tool name for logging/resilience */
30
+
60
31
  toolName: string;
61
32
 
62
- /** Resilience wrapper (withLocalResilience, withGitHubResilience, etc.) */
33
+
63
34
  resilience: ResilienceWrapper;
64
35
 
65
- /** Transform parsed response to final format */
36
+
66
37
  transform: ResponseTransformer<TQuery, TResponse>;
67
38
  }
68
39
 
69
- /**
70
- * Create a route handler with standard error handling, validation, and resilience.
71
- *
72
- * @example
73
- * ```typescript
74
- * localRoutes.get('/search', createRouteHandler({
75
- * schema: localSearchSchema,
76
- * toolFn: localSearchCode,
77
- * toolName: 'localSearchCode',
78
- * resilience: withLocalResilience,
79
- * transform: (parsed, queries) => {
80
- * // Custom transformation logic
81
- * return ResearchResponse.searchResults({ ... });
82
- * },
83
- * }));
84
- * ```
85
- */
86
40
  export function createRouteHandler<TQuery, TResponse>(
87
41
  config: RouteConfig<TQuery, TResponse>
88
42
  ): RequestHandler {
@@ -90,25 +44,20 @@ export function createRouteHandler<TQuery, TResponse>(
90
44
 
91
45
  return async (req: Request, res: Response, next: NextFunction): Promise<void> => {
92
46
  try {
93
- // 1. Parse and validate query params
94
47
  const queries = parseAndValidate(
95
48
  req.query as Record<string, unknown>,
96
49
  schema as z.ZodType<TQuery>
97
50
  ) as TQuery[];
98
51
 
99
- // 2. Execute tool with resilience wrapper
100
52
  const rawResult = await resilience(
101
53
  () => toolFn({ queries }),
102
54
  toolName
103
55
  );
104
56
 
105
- // 3. Parse tool response
106
57
  const parsed = parseToolResponse(rawResult as { content: Array<{ type: string; text: string }> });
107
58
 
108
- // 4. Transform to final response format
109
59
  const response = transform(parsed, queries);
110
60
 
111
- // 5. Send response with appropriate status
112
61
  res.status(parsed.isError ? 500 : 200).json(response);
113
62
  } catch (error) {
114
63
  next(error);
@@ -1,16 +1,11 @@
1
1
  export function extractToolName(path: string): string {
2
- // Handle /tools/call/:toolName format
3
2
  const toolCallMatch = path.match(/^\/tools\/call\/(\w+)$/);
4
3
  if (toolCallMatch) {
5
4
  return toolCallMatch[1];
6
5
  }
7
6
 
8
- // Fallback: extract from path segments
9
7
  const parts = path.split('/').filter(Boolean);
10
8
  if (parts.length >= 2) {
11
- // e.g., /tools/list -> toolsList (camelCase)
12
- // or just return the second part if it looks like a tool name
13
- // But typically we want the tool name if it's in the URL
14
9
  if (parts[0] === 'tools' && parts[1] === 'call' && parts[2]) {
15
10
  return parts[2];
16
11
  }
@@ -1,32 +1,15 @@
1
- /**
2
- * HTTP Query String Preprocessing Utilities
3
- *
4
- * HTTP query strings are always strings. These utilities convert them
5
- * to proper types before Zod schema validation.
6
- *
7
- * @module validation/httpPreprocess
8
- */
9
-
10
- import { z } from 'zod/v4';
1
+ import { z } from 'zod';
11
2
  import path from 'path';
12
3
  import os from 'os';
13
4
 
14
- // =============================================================================
15
- // Preprocessors - Convert HTTP query strings to proper types
16
- // =============================================================================
17
5
 
18
- /**
19
- * Preprocess string to number (for query params)
20
- */
21
6
  export const toNumber = (val: unknown): unknown => {
22
7
  if (typeof val === 'number') return val;
23
8
  if (typeof val === 'string' && /^\d+$/.test(val)) return parseInt(val, 10);
24
9
  return val;
25
10
  };
26
11
 
27
- /**
28
- * Preprocess string to boolean
29
- */
12
+
30
13
  export const toBoolean = (val: unknown): unknown => {
31
14
  if (typeof val === 'boolean') return val;
32
15
  if (val === 'true') return true;
@@ -34,9 +17,7 @@ export const toBoolean = (val: unknown): unknown => {
34
17
  return val;
35
18
  };
36
19
 
37
- /**
38
- * Preprocess comma-separated string to array
39
- */
20
+
40
21
  export const toArray = (val: unknown): unknown => {
41
22
  if (Array.isArray(val)) return val;
42
23
  if (typeof val === 'string') {
@@ -46,56 +27,38 @@ export const toArray = (val: unknown): unknown => {
46
27
  return val;
47
28
  };
48
29
 
49
- // =============================================================================
50
- // Reusable Schema Parts for HTTP
51
- // =============================================================================
52
30
 
53
- /** Numeric string that gets converted to number */
54
31
  export const numericString = z.preprocess(toNumber, z.number().optional());
55
32
 
56
- /** Required numeric string */
33
+
57
34
  export const requiredNumber = z.preprocess(toNumber, z.number());
58
35
 
59
- /** Boolean string that gets converted to boolean */
36
+
60
37
  export const booleanString = z.preprocess(toBoolean, z.boolean().optional());
61
38
 
62
- /** Comma-separated string that gets converted to array */
39
+
63
40
  export const stringArray = z.preprocess(toArray, z.array(z.string()));
64
41
 
65
- /**
66
- * URL-encoded traversal patterns to detect
67
- */
42
+
68
43
  const URL_ENCODED_TRAVERSAL = [
69
- '%2e%2e', // ..
70
- '%2e%2e%2f', // ../
71
- '%2e%2e%5c', // ..\
72
- '%252e', // double-encoded .
73
- '%2f', // /
74
- '%5c', // \
44
+ '%2e%2e',
45
+ '%2e%2e%2f',
46
+ '%2e%2e%5c',
47
+ '%252e',
48
+ '%2f',
49
+ '%5c',
75
50
  ] as const;
76
51
 
77
- /**
78
- * Safe path that blocks traversal attacks.
79
- *
80
- * Validates:
81
- * - No directory traversal (..)
82
- * - No null bytes
83
- * - No Windows backslashes on non-Windows systems
84
- * - No URL-encoded traversal patterns
85
- */
52
+
86
53
  export const safePath = z.string().refine(
87
54
  (p) => {
88
- // Check for null bytes
89
55
  if (p.includes('\0')) return false;
90
56
 
91
- // Normalize and check for traversal
92
57
  const normalized = path.normalize(p);
93
58
  if (normalized.includes('..')) return false;
94
59
 
95
- // Reject Windows backslashes on non-Windows (can bypass checks)
96
60
  if (os.platform() !== 'win32' && p.includes('\\')) return false;
97
61
 
98
- // Check for URL-encoded traversal patterns (case-insensitive)
99
62
  const lowerPath = p.toLowerCase();
100
63
  if (URL_ENCODED_TRAVERSAL.some((pattern) => lowerPath.includes(pattern))) {
101
64
  return false;
@@ -110,13 +73,7 @@ export const safePath = z.string().refine(
110
73
  }
111
74
  );
112
75
 
113
- // =============================================================================
114
- // Default Research Context
115
- // =============================================================================
116
76
 
117
- /**
118
- * Default research context values for HTTP requests
119
- */
120
77
  const RESEARCH_DEFAULTS = {
121
78
  mainResearchGoal: 'HTTP API request',
122
79
  researchGoal: 'Execute tool via HTTP',
@@ -125,10 +82,7 @@ const RESEARCH_DEFAULTS = {
125
82
 
126
83
  let httpQueryCounter = 0;
127
84
 
128
- /**
129
- * Apply research defaults and auto-generate `id`, ensuring structural compatibility
130
- * with MCP tool query types (which require `id`, `mainResearchGoal`, `researchGoal`, `reasoning`).
131
- */
85
+
132
86
  export function withResearchDefaults<T extends Record<string, unknown>>(
133
87
  data: T
134
88
  ): Omit<T, 'id' | 'mainResearchGoal' | 'researchGoal' | 'reasoning'> & {
@@ -1,17 +1,5 @@
1
- /**
2
- * HTTP-compatible Zod schemas for octocode-research routes.
3
- *
4
- * These schemas wrap the authoritative schemas from octocode-mcp/public
5
- * with HTTP query string preprocessing (string → number/boolean/array).
6
- *
7
- * @module validation/schemas
8
- */
9
-
10
- import { z } from 'zod/v4';
11
-
12
- // =============================================================================
13
- // Import HTTP preprocessing utilities
14
- // =============================================================================
1
+ import { z } from 'zod';
2
+
15
3
  import {
16
4
  toArray,
17
5
  safePath,
@@ -22,52 +10,37 @@ import {
22
10
  withResearchDefaults,
23
11
  } from './httpPreprocess.js';
24
12
 
25
- // =============================================================================
26
- // Local Route Schemas
27
- // =============================================================================
28
13
 
29
- /**
30
- * HTTP schema for localSearchCode (ripgrep)
31
- * Wraps RipgrepQuerySchema with HTTP preprocessing
32
- */
33
14
  export const localSearchSchema = z
34
15
  .object({
35
- // Required
36
16
  pattern: z.string().min(1, 'Pattern is required'),
37
17
  path: safePath,
38
18
 
39
- // Workflow mode preset
40
19
  mode: z.enum(['discovery', 'paginated', 'detailed']).optional(),
41
20
 
42
- // Pattern interpretation
43
21
  fixedString: booleanString,
44
22
  perlRegex: booleanString,
45
23
 
46
- // Case sensitivity
47
24
  smartCase: booleanString,
48
25
  caseInsensitive: booleanString,
49
26
  caseSensitive: booleanString,
50
27
 
51
- // Match behavior
52
28
  wholeWord: booleanString,
53
29
  invertMatch: booleanString,
54
30
  multiline: booleanString,
55
31
  multilineDotall: booleanString,
56
32
  lineRegexp: booleanString,
57
33
 
58
- // File filtering
59
34
  type: z.string().optional(),
60
35
  include: stringArray.optional(),
61
36
  exclude: stringArray.optional(),
62
37
  excludeDir: stringArray.optional(),
63
38
  binaryFiles: z.enum(['text', 'without-match', 'binary']).optional(),
64
39
 
65
- // Ignore control
66
40
  noIgnore: booleanString,
67
41
  hidden: booleanString,
68
42
  followSymlinks: booleanString,
69
43
 
70
- // Output control
71
44
  filesOnly: booleanString,
72
45
  filesWithoutMatch: booleanString,
73
46
  count: booleanString,
@@ -75,31 +48,26 @@ export const localSearchSchema = z
75
48
  lineNumbers: booleanString,
76
49
  column: booleanString,
77
50
 
78
- // Context control
79
51
  contextLines: numericString,
80
52
  beforeContext: numericString,
81
53
  afterContext: numericString,
82
- context: numericString, // deprecated alias
54
+ context: numericString,
83
55
  matchContentLength: numericString,
84
56
 
85
- // Match limiting
86
57
  maxMatchesPerFile: numericString,
87
58
  maxFiles: numericString,
88
- maxResults: numericString, // deprecated alias
59
+ maxResults: numericString,
89
60
 
90
- // Pagination
91
61
  limit: numericString,
92
62
  filesPerPage: numericString,
93
63
  filePageNumber: numericString,
94
64
  matchesPerPage: numericString,
95
65
 
96
- // Stats & output format
97
66
  includeStats: booleanString,
98
67
  includeDistribution: booleanString,
99
68
  jsonOutput: booleanString,
100
69
  vimgrepFormat: booleanString,
101
70
 
102
- // Advanced options
103
71
  threads: numericString,
104
72
  mmap: booleanString,
105
73
  noUnicode: booleanString,
@@ -111,7 +79,6 @@ export const localSearchSchema = z
111
79
  debug: booleanString,
112
80
  showFileLastModified: booleanString,
113
81
 
114
- // Research context (optional for HTTP)
115
82
  mainResearchGoal: z.string().optional(),
116
83
  researchGoal: z.string().optional(),
117
84
  reasoning: z.string().optional(),
@@ -127,39 +94,30 @@ export const localSearchSchema = z
127
94
  return result;
128
95
  });
129
96
 
130
- /**
131
- * HTTP schema for localGetFileContent
132
- * Wraps FetchContentQuerySchema with HTTP preprocessing
133
- */
97
+
134
98
  export const localContentSchema = z
135
99
  .object({
136
100
  path: safePath,
137
101
 
138
- // Line-based pagination
139
102
  startLine: numericString,
140
103
  endLine: numericString,
141
104
  fullContent: booleanString,
142
105
 
143
- // Pattern matching within file
144
106
  matchString: z.string().optional(),
145
107
  matchStringContextLines: numericString,
146
108
  matchStringIsRegex: booleanString,
147
109
  matchStringCaseSensitive: booleanString,
148
110
 
149
- // Character-based pagination
150
111
  charOffset: numericString,
151
112
  charLength: numericString,
152
113
 
153
- // Research context
154
114
  mainResearchGoal: z.string().optional(),
155
115
  researchGoal: z.string().optional(),
156
116
  reasoning: z.string().optional(),
157
117
  })
158
118
  .transform(withResearchDefaults);
159
119
 
160
- /**
161
- * Transform human-readable file type to MCP's Unix-style type codes
162
- */
120
+
163
121
  const fileTypeTransform = (val: string | undefined) => {
164
122
  if (!val) return undefined;
165
123
  const typeMap: Record<string, string | undefined> = {
@@ -182,10 +140,7 @@ const fileTypeTransform = (val: string | undefined) => {
182
140
  return typeMap[val] ?? val;
183
141
  };
184
142
 
185
- /**
186
- * HTTP schema for localFindFiles
187
- * Wraps FindFilesQuerySchema with HTTP preprocessing
188
- */
143
+
189
144
  export const localFindSchema = z
190
145
  .object({
191
146
  path: safePath,
@@ -239,10 +194,7 @@ export const localFindSchema = z
239
194
  return result;
240
195
  });
241
196
 
242
- /**
243
- * HTTP schema for localViewStructure
244
- * Wraps ViewStructureQuerySchema with HTTP preprocessing
245
- */
197
+
246
198
  export const localStructureSchema = z
247
199
  .object({
248
200
  path: safePath,
@@ -281,14 +233,7 @@ export const localStructureSchema = z
281
233
  return result;
282
234
  });
283
235
 
284
- // =============================================================================
285
- // LSP Route Schemas
286
- // =============================================================================
287
236
 
288
- /**
289
- * HTTP schema for lspGotoDefinition
290
- * Wraps LSPGotoDefinitionQuerySchema with HTTP preprocessing
291
- */
292
237
  export const lspDefinitionSchema = z
293
238
  .object({
294
239
  uri: safePath,
@@ -302,10 +247,7 @@ export const lspDefinitionSchema = z
302
247
  })
303
248
  .transform(withResearchDefaults);
304
249
 
305
- /**
306
- * HTTP schema for lspFindReferences
307
- * Wraps LSPFindReferencesQuerySchema with HTTP preprocessing
308
- */
250
+
309
251
  export const lspReferencesSchema = z
310
252
  .object({
311
253
  uri: safePath,
@@ -322,10 +264,7 @@ export const lspReferencesSchema = z
322
264
  })
323
265
  .transform(withResearchDefaults);
324
266
 
325
- /**
326
- * HTTP schema for lspCallHierarchy
327
- * Wraps LSPCallHierarchyQuerySchema with HTTP preprocessing
328
- */
267
+
329
268
  export const lspCallsSchema = z
330
269
  .object({
331
270
  uri: safePath,
@@ -345,14 +284,7 @@ export const lspCallsSchema = z
345
284
  })
346
285
  .transform(withResearchDefaults);
347
286
 
348
- // =============================================================================
349
- // GitHub Route Schemas
350
- // =============================================================================
351
287
 
352
- /**
353
- * HTTP schema for githubSearchCode
354
- * Wraps GitHubCodeSearchQuerySchema with HTTP preprocessing
355
- */
356
288
  export const githubSearchSchema = z
357
289
  .object({
358
290
  keywordsToSearch: stringArray,
@@ -370,10 +302,7 @@ export const githubSearchSchema = z
370
302
  })
371
303
  .transform(withResearchDefaults);
372
304
 
373
- /**
374
- * HTTP schema for githubGetFileContent
375
- * Wraps FileContentQuerySchema with HTTP preprocessing
376
- */
305
+
377
306
  export const githubContentSchema = z
378
307
  .object({
379
308
  owner: z.string().min(1, 'Owner is required'),
@@ -393,10 +322,7 @@ export const githubContentSchema = z
393
322
  })
394
323
  .transform(withResearchDefaults);
395
324
 
396
- /**
397
- * HTTP schema for githubSearchRepositories
398
- * Wraps GitHubReposSearchSingleQuerySchema with HTTP preprocessing
399
- */
325
+
400
326
  export const githubReposSchema = z
401
327
  .object({
402
328
  keywordsToSearch: stringArray.optional(),
@@ -425,10 +351,7 @@ export const githubReposSchema = z
425
351
  )
426
352
  .transform(withResearchDefaults);
427
353
 
428
- /**
429
- * HTTP schema for githubViewRepoStructure
430
- * Wraps GitHubViewRepoStructureQuerySchema with HTTP preprocessing
431
- */
354
+
432
355
  export const githubStructureSchema = z
433
356
  .object({
434
357
  owner: z.string().min(1, 'Owner is required'),
@@ -444,10 +367,7 @@ export const githubStructureSchema = z
444
367
  })
445
368
  .transform(withResearchDefaults);
446
369
 
447
- /**
448
- * HTTP schema for githubSearchPullRequests
449
- * Wraps GitHubPullRequestSearchQuerySchema with HTTP preprocessing
450
- */
370
+
451
371
  export const githubPRsSchema = z
452
372
  .object({
453
373
  query: z.string().optional(),
@@ -492,14 +412,7 @@ export const githubPRsSchema = z
492
412
  })
493
413
  .transform(withResearchDefaults);
494
414
 
495
- // =============================================================================
496
- // Package Route Schemas
497
- // =============================================================================
498
415
 
499
- /**
500
- * HTTP schema for packageSearch
501
- * Wraps PackageSearchQuerySchema with HTTP preprocessing
502
- */
503
416
  export const packageSearchSchema = z
504
417
  .object({
505
418
  name: z.string().min(1, 'Package name is required'),
@@ -1,40 +1,15 @@
1
- /**
2
- * Shared Zod schema for tool call body validation.
3
- *
4
- * Centralizes validation logic to avoid duplication across routes.
5
- *
6
- * @module validation/toolCallSchema
7
- */
8
-
9
- import { z } from 'zod/v4';
10
-
11
- // =============================================================================
12
- // Constants
13
- // =============================================================================
14
-
15
- /**
16
- * Maximum number of queries per tool call.
17
- * Limits parallel execution to prevent resource exhaustion.
18
- */
1
+ import { z } from 'zod';
2
+
3
+
19
4
  export const MAX_QUERIES = 3;
20
5
 
21
- // =============================================================================
22
- // Schemas
23
- // =============================================================================
24
6
 
25
- /**
26
- * Schema for individual query objects.
27
- * Each query must be a non-empty object with arbitrary key-value pairs.
28
- */
29
7
  const querySchema = z.record(z.string(), z.unknown()).refine(
30
8
  (obj) => Object.keys(obj).length > 0,
31
9
  { message: 'Query object cannot be empty' }
32
10
  );
33
11
 
34
- /**
35
- * Schema for tool call request body.
36
- * Requires a queries array with 1-3 items.
37
- */
12
+
38
13
  const toolCallBodySchema = z.object({
39
14
  queries: z
40
15
  .array(querySchema)
@@ -42,18 +17,10 @@ const toolCallBodySchema = z.object({
42
17
  .max(MAX_QUERIES, `Maximum ${MAX_QUERIES} queries per request`),
43
18
  });
44
19
 
45
- /**
46
- * Inferred type from the schema
47
- */
20
+
48
21
  type ToolCallBody = z.infer<typeof toolCallBodySchema>;
49
22
 
50
- // =============================================================================
51
- // Validation Function
52
- // =============================================================================
53
23
 
54
- /**
55
- * Validation result type
56
- */
57
24
  interface ValidationResult<T> {
58
25
  success: boolean;
59
26
  data?: T;
@@ -63,25 +30,6 @@ interface ValidationResult<T> {
63
30
  };
64
31
  }
65
32
 
66
- /**
67
- * Validate tool call body against schema.
68
- *
69
- * @param body - Request body to validate
70
- * @returns Validation result with data or error details
71
- *
72
- * @example
73
- * ```typescript
74
- * const result = validateToolCallBody(req.body);
75
- * if (!result.success) {
76
- * res.status(400).json({
77
- * success: false,
78
- * hints: [result.error.message, ...result.error.details.map(d => d.message)]
79
- * });
80
- * return;
81
- * }
82
- * const { queries } = result.data;
83
- * ```
84
- */
85
33
  export function validateToolCallBody(body: unknown): ValidationResult<ToolCallBody> {
86
34
  const result = toolCallBodySchema.safeParse(body);
87
35
 
@@ -104,20 +52,12 @@ export function validateToolCallBody(body: unknown): ValidationResult<ToolCallBo
104
52
  };
105
53
  }
106
54
 
107
- /**
108
- * Generate user-friendly hints for validation errors.
109
- *
110
- * @param toolName - Name of the tool being called
111
- * @param error - Validation error details
112
- * @returns Array of hint strings for the user
113
- */
114
55
  export function getValidationHints(
115
56
  toolName: string,
116
57
  error: { message: string; details: z.core.$ZodIssue[] }
117
58
  ): string[] {
118
59
  const hints = [error.message];
119
60
 
120
- // Add specific hints based on error type
121
61
  const hasQueriesError = error.details.some(
122
62
  (d) => d.path.includes('queries') || d.message.includes('queries')
123
63
  );