Skip to content

fix: eliminate TypeScript any types and enhance type safety - #73

Merged
murdore merged 1 commit into
releasefrom
fix/typescript-any-type-elimination
Aug 16, 2025
Merged

murdore merged 1 commit into
releasefrom
fix/typescript-any-type-elimination

Conversation

@murdore

@murdore murdore commented Aug 16, 2025 •

Copy link
Copy Markdown
Contributor

Summary

This PR eliminates all explicit any types from the codebase and significantly improves type safety across core components. The changes focus on proper typing for tool management, MCP integration, and provider functionality.

Changes Made

Type Safety Improvements

  • Eliminated 6 explicit any types across critical components
  • Enhanced type definitions for tool registration and execution
  • Improved interface contracts for MCP tool integration
  • Strengthened typing for provider tool management

Core Components Updated

  • src/lib/neurolink.ts - Fixed Map typing and tool transformation
  • src/lib/mcp/mcpClientFactory.ts - Removed unnecessary type assertions
  • src/lib/mcp/factory.ts - Updated Zod schema for better type safety
  • src/lib/core/baseProvider.ts - Enhanced provider tool type definitions
  • src/lib/mcp/contracts/mcpContract.ts - Improved interface definitions

Testing & Quality

  • Added comprehensive continuous test suite for ongoing validation
  • Updated existing tests to work with improved typing
  • Enhanced ESLint configuration for stricter type checking

Technical Details

Before

new Map<string, any>()
(childProcess as any).on(...)
z.record(z.any())

After

new Map<string, ToolInfo>()
childProcess.on(...)
z.record(z.unknown())

Verification

Build & Compilation

  • ✅ TypeScript compilation passes with strict mode
  • ✅ All build processes complete successfully
  • ✅ ESLint violations reduced significantly

Testing

  • ✅ Existing test suite passes
  • ✅ New continuous test suite validates tool integration
  • ✅ CLI and SDK functionality verified

Tool Integration

  • ✅ Custom tool registration works correctly
  • ✅ MCP tool discovery and execution functional
  • ✅ Provider tool management maintains compatibility

Impact

  • Type Safety: Eliminated all explicit any types (6 instances)
  • Code Quality: Improved maintainability through better typing
  • Developer Experience: Enhanced IDE support and error detection
  • Runtime Safety: Reduced potential type-related runtime errors

Files Changed

  • 10 TypeScript/JavaScript files modified
  • +1,246 additions, -213 deletions
  • Focus on core library components and testing infrastructure

Breaking Changes

None. All changes are internal type improvements that maintain existing API compatibility.

Testing Instructions

# Verify build passes
npm run build

# Run type checking
npx tsc --noEmit

# Execute test suite
npm test

# Test continuous integration
npx tsx test/continuous-test-suite.ts

Summary by CodeRabbit

  • New Features

    • Richer tool metadata now exposed in results and listings (name, description, parameters, server).
    • In-memory MCP server support: add and list servers for easier local testing.
    • Improved external MCP tool execution and JSON schema handling.
    • Fake streaming now forwards analytics and evaluation data.
  • Tests

    • Added a comprehensive continuous end-to-end test suite for CLI and SDK.
    • Updated tool registration tests to align with new schemas and naming.
  • Chores

    • Adjusted ESLint rules for stricter TypeScript checks and expanded ignore patterns.

@murdore
murdore requested a review from Copilot August 16, 2025 05:40

This comment was marked as outdated.

@murdore
murdore requested a review from Copilot August 16, 2025 06:04

This comment was marked as outdated.

@murdore
murdore force-pushed the fix/typescript-any-type-elimination branch from fe05aef to ae396f1 Compare August 16, 2025 06:25
@coderabbitai

coderabbitai Bot commented Aug 16, 2025 •

Copy link
Copy Markdown

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Updates tighten ESLint TypeScript rules, expand ignores, and add function/parameter limits. Core code refactors tool typing and MCP integration, adds availableTools to results, re-exports AnalyticsData, and introduces in-memory MCP servers and stricter JSON/unknown typing. MCP contracts/factory/client gain safer types. Tests add tool schema/name adjustments and a new continuous test suite.

Changes

Cohort / File(s) Summary
Linting configuration
eslint.config.js
Tightened TS rules (no-explicit-any: error in src, warn in tests), added max-lines-per-function and max-params, expanded ignore list.
Core generation and types
src/lib/core/baseProvider.ts, src/lib/core/types.ts
baseProvider: unified tool types, enriched availableTools in results, stricter JSON schema-to-Zod conversion, MCP tool handling via AI SDK path, improved typing/logging. types.ts: moved AnalyticsData to re-export from analytics module.
MCP contracts and factory
src/lib/mcp/contracts/mcpContract.ts, src/lib/mcp/factory.ts
mcpContract: ToolDefinition moved to shared type import. factory: expanded tool metadata, loosened schema types to unknown, execute may return sync or async, stricter zod unknown usage for metadata.
MCP client and discovery
src/lib/mcp/mcpClientFactory.ts, src/lib/mcp/toolDiscoveryService.ts
mcpClientFactory: removed any casts, strengthened types for server info and capabilities. toolDiscoveryService: validateToolOutput now uses unknown with guarded property access.
Neurolink API and tooling
src/lib/neurolink.ts
Added in-memory MCP server management methods, strengthened JSON/unknown typing, expanded tool discovery metadata (inputSchema/parameters), updated external MCP tool execution signature.
Tests
test/array-tool-registration.test.ts, test/continuous-test-suite.ts
Tests updated for name fields and inputSchema-based tools; new comprehensive continuous test suite script added.
Misc
time-log.txt
Cleared file content.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Neurolink
  participant MCPRegistry as In-Memory MCP Registry
  participant MCPServer
  participant AISDK as AI SDK Tools

  User->>Neurolink: generate(prompt, options)
  Neurolink->>MCPRegistry: getInMemoryServerInfos()
  Neurolink->>MCPServer: discover tools (external)
  Neurolink->>AISDK: convert MCP tools -> AI SDK tools
  Neurolink->>Neurolink: aggregate availableTools
  Neurolink-->>User: EnhancedGenerateResult (availableTools, streams/analytics)
Loading
sequenceDiagram
  participant Caller
  participant Neurolink
  participant MCPServer

  Caller->>Neurolink: executeExternalMCPTool(serverId, toolName, parameters: JsonObject)
  Neurolink->>MCPServer: invoke(toolName, parameters)
  MCPServer-->>Neurolink: result (unknown)
  Neurolink-->>Caller: result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

A rabbit taps its codey paws,
New tools now list their shiny draws.
MCPs in memory hop,
JSON fields go pop-pop-pop.
Lints grow strict, the types stay true—
Thump! I ship this PR to you. 🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/typescript-any-type-elimination

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@murdore
murdore requested a review from Copilot August 16, 2025 06:26

This comment was marked as outdated.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🔭 Outside diff range comments (1)
src/lib/mcp/factory.ts (1)

299-305: Bug: instanceof z.ZodSchema will always fail (and may throw); accept Zod or JSON Schema safely

z.ZodSchema is a TypeScript type, not a runtime constructor. Using it in instanceof can throw (“Right-hand side of instanceof is not an object”) and incorrectly rejects valid JSON Schema objects. Update validation to accept either Zod schemas or plain JSON objects.

Apply this diff:

-    // Validate optional schemas if present
-    if (tool.inputSchema && !(tool.inputSchema instanceof z.ZodSchema)) {
-      return false;
-    }
-    if (tool.outputSchema && !(tool.outputSchema instanceof z.ZodSchema)) {
-      return false;
-    }
+    // Validate optional schemas if present (accept Zod or plain JSON schema objects)
+    const isZodSchema = (s: unknown): boolean =>
+      typeof s === "object" &&
+      s !== null &&
+      // Most Zod schemas have an internal _def and a parse method
+      typeof (s as { parse?: unknown }).parse === "function";
+    const isJsonSchemaObject = (s: unknown): s is Record<string, unknown> =>
+      typeof s === "object" && s !== null && !Array.isArray(s);
+
+    if (
+      tool.inputSchema &&
+      !(isZodSchema(tool.inputSchema) || isJsonSchemaObject(tool.inputSchema))
+    ) {
+      return false;
+    }
+    if (
+      tool.outputSchema &&
+      !(isZodSchema(tool.outputSchema) || isJsonSchemaObject(tool.outputSchema))
+    ) {
+      return false;
+    }
♻️ Duplicate comments (3)
test/continuous-test-suite.ts (1)

359-366: Nice fix: secure temporary dirs via mkdtempSync

Switching to fs.mkdtempSync(os.tmpdir() + "/test-sdk-") addresses predictable tmp file concerns raised earlier. Same improvement is applied for the stream variant.

src/lib/mcp/factory.ts (1)

110-127: Good: Removed ToolDefinition extension to avoid execute-signature ambiguity

Defining NeuroLinkMCPTool standalone resolves the earlier confusion around execute signatures.

src/lib/neurolink.ts (1)

1411-1429: Centralize object type guards to reduce repetition

The repeated pattern for checking “object with keys” is scattered across the codebase. Consider a small utility like isObject(value: unknown): value is Record<string, unknown> to improve readability.

Example utility (ts):

export function isObject(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

Then here:

params: isObject(params) ? Object.keys(params).length + " params" : params
🧹 Nitpick comments (14)
eslint.config.js (1)

208-208: Verify ignore patterns for continuous test suite

You’re ignoring continuous-test-suite.cjs and cli-business-test.cjs, but the new continuous test is test/continuous-test-suite.ts. If the intent was to lint the TS suite with relaxed rules (as configured below), the .cjs ignores may be obsolete.

Consider dropping the .cjs ignores or adding/removing entries intentionally:

     "test-feature-gaps.cjs",
-    "cli-business-test.cjs",
-    "continuous-test-suite.cjs",
+    // If you keep these CJS harnesses around, leave them ignored.
+    // Otherwise remove these lines to avoid stale ignores.
+    // "cli-business-test.cjs",
+    // "continuous-test-suite.cjs",

Also applies to: 248-250

test/continuous-test-suite.ts (3)

84-127: Harden runCommand result handling (code null vs success, signal capture)

When a process exits due to a signal, code can be null. You currently coerce code || 0 while computing success as code === 0, which can be inconsistent. Also, capturing the signal improves diagnostics.

Apply:

-function runCommand(
+function runCommand(
   command: string,
   args: string[] = [],
   options: Record<string, unknown> = {},
 ): Promise<CommandResult> {
   return new Promise((resolve, reject) => {
-    const proc = spawn(command, args, {
+    const proc = spawn(command, args, {
       stdio: ["pipe", "pipe", "pipe"],
       ...options,
     });
 
     let stdout = "";
     let stderr = "";
 
-    proc.stdout.on("data", (data) => {
+    proc.stdout.on("data", (data) => {
       stdout += data.toString();
     });
 
-    proc.stderr.on("data", (data) => {
+    proc.stderr.on("data", (data) => {
       stderr += data.toString();
     });
 
     const timeoutId = setTimeout(() => {
       proc.kill("SIGKILL");
       reject(new Error(`Command timeout: ${command} ${args.join(" ")}`));
     }, TEST_CONFIG.timeout);
 
-    proc.on("close", (code) => {
+    proc.on("close", (code, signal) => {
       clearTimeout(timeoutId);
       resolve({
-        code: code || 0,
+        code: typeof code === "number" ? code : -1,
         stdout: stdout.trim(),
         stderr: stderr.trim(),
-        success: code === 0,
+        success: code === 0 && !signal,
+        // Optional: include signal for richer debugging
+        // @ts-expect-error augment shape if needed by callers
+        signal,
       });
     });

212-221: Avoid brittle version assertion; derive expected version and main from package.json

Hard-coding 7.14.0 and ./dist/index.js can cause false negatives when versions or entry paths change. Read package.json to compare against the real values.

Apply:

-    const response = fileResult.stdout.toLowerCase();
-    const hasCorrectData =
-      response.includes("7.14.0") && // NeuroLink version
-      (response.includes("./dist/index.js") ||
-        response.includes("dist/index.js")) && // main script
-      (response.includes("dependencies") || response.includes("depend")) && // mentions dependencies
-      (response.includes("dev dependencies") ||
-        response.includes("devdependencies")); // mentions devDependencies
+    const response = fileResult.stdout.toLowerCase();
+    // Derive expectations directly from package.json
+    const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
+    const expectedVersion = String(pkg.version || "").toLowerCase();
+    const expectedMain = String(pkg.main || "dist/index.js").toLowerCase();
+    const hasCorrectData =
+      (expectedVersion && response.includes(expectedVersion)) && // package version
+      (response.includes(expectedMain) ||
+        response.includes(expectedMain.replace(/^\.\//, ""))) && // main script (with/without leading ./)
+      (response.includes("dependencies") || response.includes("depend")) && // mentions dependencies
+      (response.includes("dev dependencies") ||
+        response.includes("devdependencies")); // mentions devDependencies

If you prefer to keep TEST_CONFIG static, compute and inject the expected values at runtime once and reuse them.


494-506: Streaming discovery chunk limit could miss tool listings

Breaking after 15 chunks may occasionally miss the section where tools are enumerated, depending on provider/model/output pacing. Consider a higher cap or a timeout-based loop.

For example, increase to 50 chunks or stop when a tool keyword is detected:

-    let toolsChunkCount = 0;
+    let toolsChunkCount = 0;
     for await (const chunk of toolsStreamResult.stream) {
       toolsChunks.push(chunk.content);
       toolsChunkCount++;
-      if (toolsChunkCount >= 15) break; // Enough to see tool list
+      if (toolsChunkCount >= 50) break; // Safer cap
+      const joined = toolsChunks.join("").toLowerCase();
+      if (
+        joined.includes("filesystem") ||
+        joined.includes("read_file") ||
+        joined.includes("tool")
+      ) {
+        break;
+      }
     }
src/lib/mcp/toolDiscoveryService.ts (1)

734-751: Type-safe output validation for unknown results

resultObj.error and resultObj.isError are unknown here; truthiness checks on unknown are unsafe and can be flagged. Narrow types before checking to keep strict typing intact and avoid false positives.

Apply:

-  private validateToolOutput(result: unknown): void {
+  private validateToolOutput(result: unknown): void {
     // Basic output validation
     if (!result) {
       throw new Error("Tool returned no result");
     }
 
     // Check for error indicators
-    if (typeof result === "object" && result !== null) {
-      const resultObj = result as Record<string, unknown>;
-      if (resultObj.error) {
-        throw new Error(`Tool execution error: ${resultObj.error}`);
-      }
-
-      if (resultObj.isError === true) {
-        throw new Error("Tool execution failed");
-      }
-    }
+    if (typeof result === "object" && result !== null) {
+      const resultObj = result as Record<string, unknown>;
+      const err = resultObj.error;
+      if (typeof err === "string" && err.length > 0) {
+        throw new Error(`Tool execution error: ${err}`);
+      }
+      if (
+        typeof err === "object" &&
+        err !== null &&
+        "message" in (err as Record<string, unknown>) &&
+        typeof (err as Record<string, unknown>).message === "string"
+      ) {
+        throw new Error(
+          `Tool execution error: ${(err as Record<string, unknown>).message as string}`,
+        );
+      }
+      const isError = resultObj.isError;
+      if (typeof isError === "boolean" && isError) {
+        throw new Error("Tool execution failed");
+      }
+    }
   }
src/lib/mcp/mcpClientFactory.ts (3)

412-421: Don’t override capabilities.tools with undefined; keep defaults unless you have a positive signal

You spread DEFAULT_CAPABILITIES and then set tools to undefined when serverInfo.tools is falsy, which unnecessarily erases the default empty object. Prefer conditional spread to only override when you have a positive signal.

Apply this diff:

-    return {
-      ...this.DEFAULT_CAPABILITIES,
-      tools: serverInfo.tools ? {} : undefined,
-    };
+    return {
+      ...this.DEFAULT_CAPABILITIES,
+      ...(serverInfo.tools ? { tools: {} } : {}),
+    };

365-372: Avoid the cast; type Promise.race to eliminate the as-cast

You can type the race to Record<string, unknown> and remove the cast at the call site. This tightens types without changing behavior.

-      const serverInfo = await Promise.race([
-        this.getServerInfo(client),
-        this.createTimeoutPromise(timeout, "Handshake timeout"),
-      ]);
+      const serverInfo = await Promise.race<Record<string, unknown>>([
+        this.getServerInfo(client),
+        // Explicitly type the timeout branch as never to keep the union tight
+        this.createTimeoutPromise<never>(timeout, "Handshake timeout"),
+      ]);

And then:

-      return this.extractCapabilities(serverInfo as Record<string, unknown>);
+      return this.extractCapabilities(serverInfo);

283-292: Ensure env values are strings for spawn; coerce non-strings

Node’s spawn expects env values to be strings. Currently you cast to Record<string, string> without coercion, which can let non-strings through at runtime. Coerce values to String() during construction.

-      env: Object.fromEntries(
-        Object.entries({
-          ...process.env,
-          ...config.env,
-        }).filter(([, value]) => value !== undefined),
-      ) as Record<string, string>,
+      env: Object.fromEntries(
+        Object.entries({
+          ...process.env,
+          ...config.env,
+        })
+          .filter(([, value]) => value !== undefined)
+          .map(([k, v]) => [k, String(v)]),
+      ) as Record<string, string>,
test/array-tool-registration.test.ts (2)

196-196: Rename test: it no longer uses Zod schemas

The test name still mentions Zod, but the tools now use JSON inputSchema objects. Rename for clarity.

-  test("should support Lighthouse tools with Zod schemas (Lighthouse compatibility)", async () => {
+  test("should support Lighthouse tools with JSON schemas (Lighthouse compatibility)", async () => {

6-9: Unused import: z

z is not used in this test after the inputSchema refactor. Consider removing it to keep tests minimal.

src/lib/neurolink.ts (2)

1812-1821: Consistent availableTools surface; minor nit on parameters/source

Returning both inputSchema and parameters (aliasing parameters to inputSchema) keeps downstream consumers stable. If you plan to differentiate in the future, consider preferring one canonical field to reduce ambiguity.


2872-2930: Optional Refactor: Align external tools with AI SDK’s Tool type

Since convertExternalMCPToolsToAISDKFormat isn’t referenced anywhere else (no call sites found), you can safely update its return value from Record<string, unknown> to Record<string, Tool> and include an explicit empty schema for future parameters. This will give you full type-safety when passing these tools into generateText (or similar) and make it easier to add real Zod schemas later.

Suggested changes in src/lib/neurolink.ts:

  • At the top of the file, add:
    import { Tool } from "ai";
    import { z } from "zod";
  • Update the method signature:
    private convertExternalMCPToolsToAISDKFormat(): Record<string, Tool> {
  • Inside the loop, build each definition as a Tool:
      const toolDefinition = {
        description: tool.description,
  • parameters: z.object({}),          // explicit empty schema
    execute: async (args) => { /* … */ },
    
    };
  • Change the accumulator to:
    const aiSDKTools: Record<string, Tool> = {};

This is optional but will surface any schema issues early and make future parameter additions straightforward. [optional_refactors_recommended]

src/lib/core/baseProvider.ts (2)

246-251: Log counts, not arrays, for clarity

You’re logging arrays where counts are likely intended (and more readable).

-      logger.debug(`[BaseProvider.generate] Tools for ${this.providerName}:`, {
-        directTools: Object.keys(baseTools),
-        externalTools: Object.keys(options.tools || {}),
-        totalTools: Object.keys(tools),
-      });
+      logger.debug(`[BaseProvider.generate] Tools for ${this.providerName}:`, {
+        directTools: Object.keys(baseTools).length,
+        externalTools: Object.keys(options.tools || {}).length,
+        totalTools: Object.keys(tools).length,
+      });

760-846: Optional: Enhance JSON Schema→Zod conversion (enum, array items, number constraints)

The converter safely falls back to z.object({}), which is fine. If you want more value from schemas, consider handling common cases:

  • enum: z.enum([...]) for string enums
  • array items: z.array(convertedItemType)
  • number constraints: min/max
  • string formats (basic): email/url/date-time as refinements

Illustrative snippet (outside selected lines):

if (prop.type === "string" && Array.isArray(prop.enum)) {
  zodType = z.enum(prop.enum as [string, ...string[]]);
}
if (prop.type === "array" && prop.items && typeof prop.items === "object") {
  zodType = z.array(await this.convertMCPSchemaToZod(prop.items as Record<string, unknown>));
}
if ((prop.type === "number" || prop.type === "integer") && typeof prop.minimum === "number") {
  zodType = (zodType as z.ZodNumber).min(prop.minimum);
}
if ((prop.type === "number" || prop.type === "integer") && typeof prop.maximum === "number") {
  zodType = (zodType as z.ZodNumber).max(prop.maximum);
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9da76eb and ae396f1.

📒 Files selected for processing (11)
  • eslint.config.js (4 hunks)
  • src/lib/core/baseProvider.ts (10 hunks)
  • src/lib/core/types.ts (2 hunks)
  • src/lib/mcp/contracts/mcpContract.ts (1 hunks)
  • src/lib/mcp/factory.ts (3 hunks)
  • src/lib/mcp/mcpClientFactory.ts (5 hunks)
  • src/lib/mcp/toolDiscoveryService.ts (1 hunks)
  • src/lib/neurolink.ts (11 hunks)
  • test/array-tool-registration.test.ts (9 hunks)
  • test/continuous-test-suite.ts (1 hunks)
  • time-log.txt (0 hunks)
💤 Files with no reviewable changes (1)
  • time-log.txt
🧰 Additional context used
🧬 Code Graph Analysis (4)
src/lib/mcp/mcpClientFactory.ts (1)
src/lib/types/providers.ts (2)
  • Client (199-206)
  • Client (222-228)
src/lib/mcp/factory.ts (2)
neurolink-demo/test-providers.js (1)
  • args (8-8)
src/lib/types/streamTypes.ts (1)
  • ToolResult (26-40)
src/lib/neurolink.ts (2)
src/lib/types/common.ts (1)
  • JsonObject (31-33)
src/lib/mcp/contracts/mcpContract.ts (1)
  • ToolInfo (50-58)
src/lib/core/baseProvider.ts (2)
src/lib/types/externalMcp.ts (1)
  • ExternalMCPToolInfo (137-167)
src/lib/types/common.ts (1)
  • JsonObject (31-33)
🔇 Additional comments (8)
src/lib/mcp/contracts/mcpContract.ts (1)

6-7: I've verified that ToolDefinition is neither referenced nor re-exported in src/lib/mcp/contracts/mcpContract.ts. It can be safely removed.

Action: Remove the unused import

--- a/src/lib/mcp/contracts/mcpContract.ts
+++ b/src/lib/mcp/contracts/mcpContract.ts
@@ -6,7 +6,6 @@
 import type { ExecutionContext } from "../../types/mcpTypes.js";
-import type { ToolDefinition } from "../../types/tools.js";

 /**
  * The shape of an MCP request
  ...
src/lib/core/types.ts (1)

7-7: Type centralization and re-export look good

Importing AnalyticsData from a single source and re-exporting it here reduces duplication and tightens the public type surface. No runtime impact. LGTM.

Also applies to: 189-189

eslint.config.js (1)

94-106: Good move: enforce no-explicit-any in src and keep it relaxed in tests

Shifting to "error" for @typescript-eslint/no-explicit-any under src/**/*.ts aligns with the PR objective and still keeps tests flexible. The additional function size/params warnings are reasonable.

src/lib/mcp/mcpClientFactory.ts (1)

252-268: Event handling looks good; direct ChildProcess property usage is correct

Directly binding childProcess.on("error"/"exit") and checking killed/exitCode avoids the previous any-casts and is idiomatic.

Also applies to: 276-279

src/lib/mcp/factory.ts (1)

171-194: z.record(z.unknown()) change is correct

Switching from z.any() to z.unknown() for metadata is a safer default that matches the PR goals.

src/lib/neurolink.ts (1)

1769-1785: Dedup by name into a typed map: solid approach

Using Map<string, ToolInfo> for deduplication by name balances type safety with flexibility (thanks to the index signature on ToolInfo). Looks good.

src/lib/core/baseProvider.ts (2)

413-422: availableTools shape is coherent and matches upstream usage

Exposing server via serverId and surfacing parameters directly aligns with how NeuroLink consumes this later. Good use of the ExtendedTool union to carry extra metadata.


697-700: args cast to JsonObject for external MCP calls is appropriate

Tightening the type from unknown to JsonObject at the execution boundary is aligned with the PR’s type-safety goals.

@murdore
murdore force-pushed the fix/typescript-any-type-elimination branch from ae396f1 to 9e01eaf Compare August 16, 2025 07:48
@murdore
murdore requested a review from Copilot August 16, 2025 07:55

This comment was marked as outdated.

@murdore
murdore force-pushed the fix/typescript-any-type-elimination branch from 9e01eaf to 1305dc4 Compare August 16, 2025 17:41
@murdore
murdore requested a review from Copilot August 16, 2025 17:43

This comment was marked as outdated.

@murdore
murdore force-pushed the fix/typescript-any-type-elimination branch 2 times, most recently from 1dd5461 to 5347c17 Compare August 16, 2025 18:37
@github-actions

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@murdore
murdore requested a review from Copilot August 16, 2025 18:38
@juspay juspay deleted a comment from github-actions Bot Aug 16, 2025
@juspay juspay deleted a comment from github-actions Bot Aug 16, 2025
@juspay juspay deleted a comment from github-actions Bot Aug 16, 2025
@juspay juspay deleted a comment from github-actions Bot Aug 16, 2025
@juspay juspay deleted a comment from github-actions Bot Aug 16, 2025
@juspay juspay deleted a comment from github-actions Bot Aug 16, 2025

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull Request Overview

This PR eliminates explicit any types throughout the codebase and significantly enhances type safety across core components. The changes focus on proper typing for tool management, MCP integration, and provider functionality while maintaining full API compatibility.

Key changes include:

  • Type safety improvements: Eliminated 6 explicit any types across critical components
  • Centralized type utilities: Added comprehensive type checking functions and transformation utilities
  • Enhanced parameter validation: Implemented robust validation system for tool parameters and options
  • Improved interface contracts: Strengthened typing for MCP tool integration and provider tool management

Reviewed Changes

Copilot reviewed 39 out of 39 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
vite.config.ts Fixed type assertion from any to proper UserConfig type with satisfies
test/shared/execWithTimeout.ts Changed timeout ID to definite assignment assertion pattern
test/continuous-test-suite.ts Added comprehensive end-to-end test suite for CLI and SDK validation
test/array-tool-registration.test.ts Updated tool registration tests for new schemas and naming patterns
src/lib/utils/typeUtils.ts Added centralized type checking utilities to replace inline type checks
src/lib/utils/transformationUtils.ts Created transformation utilities for object processing patterns
src/lib/utils/parameterValidation.ts Implemented comprehensive parameter validation system
src/lib/utils/factoryProcessing.ts Updated factory processing to use centralized type utilities
src/lib/types/typeAliases.ts Added comprehensive type alias library for commonly used complex types
src/lib/types/tools.ts Enhanced tool type definitions with proper Zod schema aliases
src/lib/types/streamTypes.ts Updated stream types to use centralized validation schemas
src/lib/types/generateTypes.ts Enhanced generate types with proper schema validation
src/lib/sdk/toolRegistration.ts Updated tool registration to use centralized validation utilities
src/lib/providers/*.ts Updated all providers to use proper type aliases instead of raw Zod types
src/lib/neurolink.ts Enhanced main SDK with proper typing and transformation utilities
src/lib/models/modelResolver.ts Updated model resolution to use centralized type checking
src/lib/mcp/*.ts Enhanced MCP components with proper typing and validation
src/lib/core/types.ts Updated core types to use centralized validation schemas

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Comment thread test/shared/execWithTimeout.ts
* @param value - Value to check
* @returns true if value is a function
*/
export function isFunction(value: unknown): value is Function {

Copilot AI Aug 16, 2025

Copy link

Choose a reason for hiding this comment

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

Using the 'Function' type is generally discouraged in TypeScript as it's too broad. Consider using a more specific function signature or (...args: unknown[]) => unknown for better type safety.

Suggested change
export function isFunction(value: unknown): value is Function {
export function isFunction(value: unknown): value is (...args: unknown[]) => unknown {

Copilot uses AI. Check for mistakes.

// Check if function appears to be async
const funcStr = value.toString();
const isAsync = funcStr.includes("async") || funcStr.includes("Promise");

Copilot AI Aug 16, 2025

Copy link

Choose a reason for hiding this comment

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

Calling toString() on functions and using string analysis to detect async functions is unreliable and can fail with minified code or transpiled functions. Consider using a more robust detection method or removing this check.

Suggested change
const isAsync = funcStr.includes("async") || funcStr.includes("Promise");
// Check if function is an async function using constructor name
const isAsync = value.constructor && value.constructor.name === "AsyncFunction";

Copilot uses AI. Check for mistakes.
Comment thread src/lib/neurolink.ts
// Try ES module import first
const toolRegistrationModule = require("./sdk/toolRegistration.js");
({ validateTool, isToolNameAvailable, suggestToolNames } =
toolRegistrationModule);

Copilot AI Aug 16, 2025

Copy link

Choose a reason for hiding this comment

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

The try-catch block for importing validation functions uses require() which is a CommonJS pattern. This could cause issues in ESM environments. Consider using dynamic import() or ensuring the module system is consistent.

Suggested change
toolRegistrationModule);
// Import validation functions dynamically - they are pure functions
let validateTool: (name: string, tool: unknown) => void;
let isToolNameAvailable: (name: string) => boolean;
let suggestToolNames: (name: string) => string[];
try {
// Try ES module dynamic import
const toolRegistrationModule = await import("./sdk/toolRegistration.js");
validateTool = toolRegistrationModule.validateTool;
isToolNameAvailable = toolRegistrationModule.isToolNameAvailable;
suggestToolNames = toolRegistrationModule.suggestToolNames;

Copilot uses AI. Check for mistakes.
@murdore
murdore force-pushed the fix/typescript-any-type-elimination branch from 5347c17 to 9ab7e79 Compare August 16, 2025 18:51
@github-actions

github-actions Bot commented Aug 16, 2025 •

Copy link
Copy Markdown
Contributor

✅ Single Commit Policy - COMPLIANT

Status: Policy requirements met • 1 commit • Valid format • Ready for merge

📊 View validation details

📝 Commit Details

  • Hash: fb853df7c20c0f01e898bbee0220a812bd1549eb
  • Message: fix(typescript): eliminate all TypeScript any types for improved type safety
  • Author: Sachin Sharma

✅ Validation Results

  • Single commit requirement met
  • No merge commits in branch
  • Semantic commit message format verified
  • Ready for squash merge to release branch

🤖 Automated validation by NeuroLink Single Commit Enforcement

@github-actions

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

… safety

- Complete TypeScript ANY type elimination and code improvements
- Address GitHub PR review comments for type safety
- Fix instanceof z.ZodSchema validation bugs
- Harden process handling and security
- Remove unused variables and improve code quality
@murdore
murdore force-pushed the fix/typescript-any-type-elimination branch from 9ab7e79 to fb853df Compare August 16, 2025 19:18
@github-actions

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@murdore
murdore merged commit 45043cb into release Aug 16, 2025
@murdore
murdore deleted the fix/typescript-any-type-elimination branch August 16, 2025 19:23
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 7.14.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants