Skip to content

feat: add agent tab component and development sign-in script#35

Merged
ssdeanx merged 1 commit intomainfrom
develop
Dec 11, 2025
Merged

feat: add agent tab component and development sign-in script#35
ssdeanx merged 1 commit intomainfrom
develop

Conversation

@ssdeanx
Copy link
Copy Markdown
Owner

@ssdeanx ssdeanx commented Dec 11, 2025

  • Created a new AgentTab component that displays agent details including name, description, model, status, instructions, and tools.
  • Implemented loading and error states for the AgentTab component using LoadingSkeleton and EmptyState.
  • Added a new development-only sign-in script auth-dev.ts to facilitate signing in as a development user using environment variables.
  • The sign-in script checks for USER_EMAIL and USER_PASSWORD environment variables and logs the result of the sign-in attempt.

- Created a new `AgentTab` component that displays agent details including name, description, model, status, instructions, and tools.
- Implemented loading and error states for the `AgentTab` component using `LoadingSkeleton` and `EmptyState`.
- Added a new development-only sign-in script `auth-dev.ts` to facilitate signing in as a development user using environment variables.
- The sign-in script checks for `USER_EMAIL` and `USER_PASSWORD` environment variables and logs the result of the sign-in attempt.
Copilot AI review requested due to automatic review settings December 11, 2025 16:09
@continue
Copy link
Copy Markdown

continue Bot commented Dec 11, 2025

All Green - Keep your PRs mergeable

Learn more

All Green is an AI agent that automatically:

✅ Addresses code review comments

✅ Fixes failing CI checks

✅ Resolves merge conflicts

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Sorry @ssdeanx, your pull request is larger than the review limit of 150000 diff characters

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 11, 2025

Summary by CodeRabbit

  • New Features

    • Added specialized agents: Accessibility Expert, Debug Mode, PRD Generator, Task Planner, and Technical Spike Researcher with comprehensive workflows.
    • Added SVG-to-Excalidraw conversion tools.
    • Enhanced code analysis and search capabilities with new detection patterns.
  • Improvements

    • Refactored agent details UI with improved tab navigation.
    • Enhanced telemetry and observability with MLflow integration.
    • Improved null/undefined safety across dashboard components.
    • Updated AI SDK versions for better language model compatibility.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

This PR introduces comprehensive agent configurations and tooling infrastructure, including new debugging, planning, and research-focused agents. It refactors authentication and API integration layers, updates dashboard UI components, and significantly expands code analysis capabilities with semantic search and symbol resolution tools.

Changes

Cohort / File(s) Summary
Agent Configurations
.github/agents/*.agent.md
Added new agent workflows for accessibility expert, critical thinking mode, debugging, PRD generation, technical spike research, task planning/research, and content evaluation. Updated existing agents with expanded tool sets, infer flags, and autonomous problem-solving directives.
ESLint & Project Configuration
.eslintignore, eslint.config.cjs
Expanded ESLint ignore patterns to exclude build artifacts, dependencies, caches, and tooling directories.
Documentation & Instructions
.github/copilot-instructions.md, .github/commands/code-review-generic.instructions.md, .github/instructions/github-actions-ci-cd-best-practices.instructions.md, AGENTS.md, README.md
Updated Copilot guidance for tool usage and debugging workflow. Added comprehensive code review template and GitHub Actions CI/CD best practices. Updated project metrics, architecture documentation, and dashboard descriptions.
Authentication
lib/auth.ts, lib/auth-dev.ts
Introduced helper functions for password and OAuth sign-in, role management, and development-mode authentication script.
API & Client Library
lib/mastra-client.ts, lib/client-stream-to-ai-sdk.ts
Added shared AbortController for request cancellation. Updated message streaming to accept MessageListInput and conditionally use AI SDK's toUIMessageStreamResponse().
Hooks & Queries
lib/hooks/use-mastra.ts, lib/hooks/use-dashboard-queries.ts
Refactored to use list/get variants instead of legacy endpoints. Enhanced data transformations for agents, workflows, tools, traces, and memory threads. Removed telemetry/evals hooks in favor of trace-based queries.
Type Definitions
lib/types/mastra-api.ts
Added ModelSchema. Extended AgentSchema with modelId/model fields and flexible tool arrays. Updated WorkflowSchema steps, MessageSchema content handling, and LogEntrySchema with runId support.
Dashboard Components
app/dashboard/agents/_components/{agent-details.tsx, agent-evals-tab.tsx, agent-tab.tsx, agent-list.tsx, agent-list-item.tsx, index.ts}
Refactored agent evals tab into unified AgentTab component. Updated nullish coalescing operators (\?\?) and conditional rendering.
Dashboard Pages
app/dashboard/{memory/page.tsx, telemetry/page.tsx, workflows/page.tsx}
Updated hook usage (useAITraces replacing useTelemetry). Modified API calls to object-based parameters. Enhanced nullish coalescing and method invocations (createRun vs createRunAsync).
Code Analysis & Semantic Tools
src/mastra/tools/{code-analysis.tool.ts, code-search.tool.ts, find-references.tool.ts, find-symbol.tool.ts, multi-string-edit.tool.ts}
Switched to fast-glob for file discovery. Added progress event emissions via writer. Extended find-references and find-symbol with case sensitivity, dependency inclusion, context/kind metadata, and performance tracking. Enhanced code-analysis with language-specific complexity estimation and comment stripping.
Data & Processing Tools
src/mastra/tools/{data-file-manager.ts, data-processing-tools.ts, semantic-utils.ts, web-scraper-tool.ts, diff-review.tool.ts}
Introduced centralized data directory (./data). Migrated XML parsing from xmldom to fast-xml-parser. Added Excalidraw↔SVG conversion tools. Enhanced semantic utils with ProjectCache cleanup, per-project metadata, and Python result typing.
Tool Configuration & Types
src/mastra/index.ts, src/mastra/types/excalidraw-to-svg.d.ts
Added OpenTelemetry/MLflow exporter integration. Reordered index signature in ExcalidrawElement type definition.
Dependencies
package.json
Updated AI SDK versions (google, openai-compatible, react). Added fast-glob, strip-comments, tslab, and related TypeScript tooling. Removed xmldom.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • src/mastra/tools/find-references.tool.ts — Complex semantic analysis with new context/kind extraction, file filtering, progressive messaging, and performance tracking. Requires validation of TS/Python reference gathering logic.
  • src/mastra/tools/find-symbol.tool.ts — Extensive refactoring introducing module detection, export classification, new symbol kinds (method, property, enum), and caching metrics. Multiple new helper functions and schema extensions.
  • lib/hooks/use-mastra.ts — Significant refactoring from legacy getX endpoints to listX variants with comprehensive data transformations. Removal of evals/telemetry hooks and extension of tool execution parameters.
  • src/mastra/tools/data-processing-tools.ts — Migration from xmldom to fast-xml-parser, introduction of new Excalidraw/SVG conversion tools, and schema updates with defaults.
  • lib/auth.ts — New authentication flow helpers (signInWithPassword, signInWithOAuth, role management) requiring validation of Supabase integration and error handling.
  • Dashboard component refactoring — Replacement of AgentEvalsTab with unified AgentTab across multiple import/export sites.

Possibly related PRs

Suggested reviewers

  • sourcery-ai

🐰 A sprawling web of agents takes shape,
With tools that seek, analyze, and escape;
From auth to search, from types to trace,
A symphony of features finds its place!
Fast-glob now globs, and XML bows low,
While Excalidraw and SVG steal the show.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.18% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main changes: addition of an AgentTab component and a development sign-in script (auth-dev.ts). Both are significant new additions clearly summarized.
Description check ✅ Passed The description is comprehensive and directly related to the changeset. It details the AgentTab component features, loading/error states, the auth-dev.ts script, and environment variable usage—all present in the raw summary.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch develop

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

❤️ Share

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

@github-actions
Copy link
Copy Markdown

🤖 Hi @ssdeanx, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown

🤖 I'm sorry @ssdeanx, but I was unable to process your request. Please see the logs for more details.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @ssdeanx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new UI component for displaying agent details within the dashboard and a dedicated script for development-time user authentication. It also includes a substantial overhaul and expansion of agent definitions, core tools for code analysis, search, and data processing, and significant improvements to the dashboard's data fetching mechanisms. Furthermore, it adds detailed documentation on GitHub Actions CI/CD best practices, aiming to enhance the framework's capabilities, usability, and development workflow.

Highlights

  • New Agent Tab Component: A new AgentTab component has been introduced in the dashboard, designed to display comprehensive details of an agent, including its name, description, model, status, instructions, and associated tools. This component also incorporates loading and error states using LoadingSkeleton and EmptyState for a better user experience.
  • Development Sign-In Script: A new development-only script, auth-dev.ts, has been added to streamline the sign-in process for development users. This script leverages USER_EMAIL and USER_PASSWORD environment variables to facilitate quick authentication during development, logging the outcome of the sign-in attempt.
  • Enhanced Agent and Tool Definitions: Several new agent definitions have been added, including 'Accessibility Expert', 'Critical Thinking', 'Debug Agent', 'PRD Generator', 'Technical Spike Researcher', 'Task Planner', and 'Task Researcher'. Existing agent definitions like '4.1 Beast Mode', 'Architect', 'Code Reviewer', and 'Thinking Beast Mode' have been updated with expanded toolsets, reflecting a broader range of capabilities.
  • Improved Dashboard Data Fetching: The dashboard's data fetching logic has been significantly refactored, particularly in use-dashboard-queries.ts and use-mastra.ts. This includes updates to how agent, workflow, tool, and trace data are retrieved and parsed, with enhanced handling for model and tool structures, and improved null/undefined checks for robustness.
  • Advanced Code Analysis and Manipulation Tools: Several core tools have received substantial upgrades. code-analysis.tool.ts and code-search.tool.ts now utilize fast-glob for more efficient file pattern matching and include detailed progress reporting. data-processing-tools.ts replaces xmldom with fast-xml-parser and introduces new excalidrawToSVGTool and svgToExcalidrawTool for diagram conversions. find-references.tool.ts, find-symbol.tool.ts, and multi-string-edit.tool.ts have been enhanced with more granular control, detailed output, and better error handling, including progress reporting for long-running operations.
  • GitHub Actions CI/CD Best Practices: A comprehensive guide for GitHub Actions CI/CD best practices has been added, covering workflow structure, jobs, steps, security (secrets, OIDC, least privilege), optimization (caching, matrix strategies), testing (unit, integration, E2E, performance), and advanced deployment strategies (staging, production, blue/green, canary, rollback).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Dec 11, 2025

Greptile Overview

Greptile Summary

This PR introduces a development sign-in script and appears to add an agent tab component, but contains a critical bug that breaks the agent evaluations feature.

Key Changes

  • New auth-dev.ts script: Provides a development-only authentication helper using environment variables USER_EMAIL and USER_PASSWORD
  • New AgentTab component: Displays agent details (name, description, model, status, instructions, tools)
  • Deleted agent-evals-tab.tsx: Removed the component that displayed CI and live agent evaluations
  • Removed useAgentEvalsQuery hook: Deleted from use-dashboard-queries.ts without replacement

Critical Issue

The export mapping in app/dashboard/agents/_components/index.ts:5 incorrectly exports AgentTab as AgentEvalsTab. This causes the "Evaluations" tab in the agent details page to display agent details instead of evaluations, completely breaking the evaluations feature.

Additional Issues

  • Type safety violation: agent-tab.tsx:49 uses (agent.model as any) to access model properties, bypassing TypeScript's type checking
  • Component naming confusion: AgentTab is a generic name but displays specific agent details, not evaluations

Impact

Users clicking the "Evaluations" tab will see duplicate agent details instead of CI/live evaluation results. The evaluation functionality that existed before this PR is now completely broken.

Confidence Score: 0/5

  • This PR contains a critical bug that breaks existing evaluation functionality and should not be merged
  • Score reflects the severity of the export mapping bug that completely breaks the agent evaluations feature. The incorrect export causes wrong component rendering, making the Evaluations tab non-functional. Additionally, the removal of useAgentEvalsQuery without replacement eliminates evaluation data fetching capability.
  • app/dashboard/agents/_components/index.ts has critical export bug, agent-tab.tsx needs type safety fixes, and agent-evals-tab.tsx needs restoration or proper replacement

Important Files Changed

File Analysis

Filename Score Overview
app/dashboard/agents/_components/index.ts 0/5 Critical bug: exports AgentTab as AgentEvalsTab, breaking the Evaluations tab functionality
app/dashboard/agents/_components/agent-tab.tsx 2/5 New component with unsafe type assertions and misnamed (shows details, not evals)
lib/auth-dev.ts 4/5 Dev-only auth script with minor security consideration regarding import prevention
app/dashboard/agents/_components/agent-details.tsx 3/5 Updated to use AgentTab instead of AgentEvalsTab, breaking evaluation display
lib/hooks/use-dashboard-queries.ts 3/5 Removed useAgentEvalsQuery hook without providing replacement evaluation functionality

Sequence Diagram

sequenceDiagram
    participant User
    participant AgentDetails
    participant AgentTab
    participant useAgentQuery
    participant MastraClient
    participant DevScript as auth-dev.ts

    Note over User,DevScript: PR Changes Flow

    rect rgb(240, 240, 250)
        Note over DevScript: Development Sign-In (New)
        DevScript->>DevScript: Check USER_EMAIL & USER_PASSWORD env vars
        DevScript->>MastraClient: signInWithPassword(email, password)
        MastraClient-->>DevScript: Return auth result
    end

    rect rgb(250, 240, 240)
        Note over User,MastraClient: Agent Details Display (Modified)
        User->>AgentDetails: View agent details
        AgentDetails->>useAgentQuery: Query agent by ID
        useAgentQuery->>MastraClient: getAgent(agentId).details()
        MastraClient-->>useAgentQuery: Return agent data
        useAgentQuery-->>AgentDetails: Return formatted agent
        
        AgentDetails->>AgentDetails: Render tabs (Details, Tools, Evaluations)
        
        Note over AgentDetails,AgentTab: BUG: Evaluations tab uses wrong component
        User->>AgentDetails: Click "Evaluations" tab
        AgentDetails->>AgentTab: Render AgentTab (should be AgentEvalsTab)
        AgentTab->>useAgentQuery: Query agent details again
        useAgentQuery->>MastraClient: getAgent(agentId).details()
        MastraClient-->>useAgentQuery: Return agent data
        useAgentQuery-->>AgentTab: Return agent
        AgentTab-->>User: Display agent details (NOT evaluations)
    end

    Note over AgentDetails,AgentTab: Expected: Should call useAgentEvalsQuery<br/>and display CI/Live evaluations
Loading

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

52 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

export { AgentDetails } from "./agent-details"
export { AgentToolsTab } from "./agent-tools-tab"
export { AgentEvalsTab } from "./agent-evals-tab"
export { AgentEvalsTab } from "./agent-tab"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

logic: incorrect export - AgentTab should display agent details, but it's being exported as AgentEvalsTab which should display evaluations

The PR deleted agent-evals-tab.tsx (which used useAgentEvalsQuery) but the export still maps AgentEvalsTab to the new agent-tab.tsx. This causes the Evaluations tab in agent-details.tsx:98 to show agent details instead of evaluations.

Suggested change
export { AgentEvalsTab } from "./agent-tab"
export { AgentEvalsTab } from "./agent-evals-tab"

Also need to restore agent-evals-tab.tsx or create a proper evaluations component.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/dashboard/agents/_components/index.ts
Line: 5:5

Comment:
**logic:** incorrect export - `AgentTab` should display agent details, but it's being exported as `AgentEvalsTab` which should display evaluations

The PR deleted `agent-evals-tab.tsx` (which used `useAgentEvalsQuery`) but the export still maps `AgentEvalsTab` to the new `agent-tab.tsx`. This causes the Evaluations tab in `agent-details.tsx:98` to show agent details instead of evaluations.

```suggestion
export { AgentEvalsTab } from "./agent-evals-tab"
```

Also need to restore `agent-evals-tab.tsx` or create a proper evaluations component.

How can I resolve this? If you propose a fix, please make it concise.

<div className="grid gap-4 md:grid-cols-2">
<div>
<h4 className="text-sm font-medium mb-2">Model</h4>
<Badge variant="outline">{(agent.model as any).provider}/{(agent.model as any).name}</Badge>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

logic: unsafe type assertion - (agent.model as any) bypasses TypeScript checking

According to lib/types/mastra-api.ts:13-15, model can be string | ModelSchema | undefined. Handle this properly:

Suggested change
<Badge variant="outline">{(agent.model as any).provider}/{(agent.model as any).name}</Badge>
<Badge variant="outline">
{typeof agent.model === 'object' && agent.model
? `${agent.model.provider}/${agent.model.name}`
: agent.model ?? 'Unknown'}
</Badge>
Prompt To Fix With AI
This is a comment left during a code review.
Path: app/dashboard/agents/_components/agent-tab.tsx
Line: 49:49

Comment:
**logic:** unsafe type assertion - `(agent.model as any)` bypasses TypeScript checking

According to `lib/types/mastra-api.ts:13-15`, `model` can be `string | ModelSchema | undefined`. Handle this properly:

```suggestion
          <Badge variant="outline">
            {typeof agent.model === 'object' && agent.model 
              ? `${agent.model.provider}/${agent.model.name}` 
              : agent.model ?? 'Unknown'}
          </Badge>
```

How can I resolve this? If you propose a fix, please make it concise.

Comment thread lib/auth-dev.ts
* Use this script to sign in as a development user using environment variables.
* Run manually (e.g. `node -r dotenv/config ./lib/auth-dev.ts` or via ts-node) — do not import this into the app code.
*/
import { signInWithPassword } from './auth'
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

style: security risk - imports authentication function at module level

The file header says "do not import this into the app code" but nothing prevents accidental import. If auth-dev.ts is imported into app code, it executes signInWithPassword import which could create unwanted side effects.

safer approach - use dynamic import inside the main() function

Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/auth-dev.ts
Line: 6:6

Comment:
**style:** security risk - imports authentication function at module level

The file header says "do not import this into the app code" but nothing prevents accidental import. If `auth-dev.ts` is imported into app code, it executes `signInWithPassword` import which could create unwanted side effects.

safer approach - use dynamic import inside the `main()` function

How can I resolve this? If you propose a fix, please make it concise.

@ssdeanx ssdeanx merged commit bb4a128 into main Dec 11, 2025
43 of 47 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request introduces a new AgentTab component for displaying agent details in the dashboard, adds a development sign-in script for easier local authentication, and includes extensive refactoring across the codebase. Key improvements include migrating from xmldom to fast-xml-parser for XML processing, replacing glob with fast-glob for better performance, enhancing type safety with updated Zod schemas, and refactoring authentication utilities to be more modular.

Key Changes:

  • New AgentTab component with loading/error states for agent information display
  • Development sign-in utility (auth-dev.ts) for local development authentication
  • Migration from xmldom to fast-xml-parser for XML parsing across data processing tools
  • Migration from glob to fast-glob for file globbing operations
  • Enhanced type safety in MastraClient SDK integration with flexible schema handling
  • Updated authentication utilities with exported helper functions
  • Improved dashboard components with better null-coalescing and type handling

Reviewed changes

Copilot reviewed 51 out of 53 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
app/dashboard/agents/_components/agent-tab.tsx New component displaying agent details (name, model, status, instructions, tools)
lib/auth-dev.ts New development-only sign-in script using environment variables
lib/auth.ts Refactored to export helper functions instead of executing on import
lib/types/mastra-api.ts Enhanced Zod schemas to handle flexible API response formats
lib/mastra-client.ts Added AbortController support for request cancellation
lib/hooks/*.ts Updated to handle new MastraClient SDK v1 API methods
src/mastra/tools/*.ts Migrated to fast-xml-parser, fast-glob, and centralized DATA_DIR
package.json Updated dependencies, removed xmldom, added fast-glob and strip-comments
Multiple dashboard components Improved null-coalescing operators and type safety

Comment thread src/mastra/index.ts
import { specGenerationWorkflow } from './workflows/spec-generation-workflow';
import { ResearchRuntimeContext } from './agents/index';

const ml = process.env.MLFLOW_EXPERIMENT_ID
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

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

Unused variable ml.

Copilot uses AI. Check for mistakes.
import { ProjectCache, PythonParser } from './semantic-utils';
import { Node } from 'ts-morph';
import type { SourceFile } from 'ts-morph';
import { Node, SyntaxKind } from 'ts-morph';
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

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

Unused import SyntaxKind.

Copilot uses AI. Check for mistakes.
return lines.slice(start, end).join('\n');
}

function getPythonContext(lines: string[], lineIndex: number, contextLines: number): string {
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

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

Unused function getPythonContext.

Copilot uses AI. Check for mistakes.
import { ProjectCache, PythonParser } from './semantic-utils';
import { Node } from 'ts-morph';
import type { SourceFile } from 'ts-morph';
import { Node, SyntaxKind } from 'ts-morph';
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

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

Unused import SyntaxKind.

Copilot uses AI. Check for mistakes.
/**
* Parse XML content using fast-xml-parser
*/
function parseXmlContent(xmlContent: string): Record<string, unknown> {
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

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

Unused function parseXmlContent.

Copilot uses AI. Check for mistakes.
if (!trimmed) {continue}
function calculateLoc(content: string): { loc: number; totalLines: number } {
const totalLines = content.split('\n').length
let sanitized = content
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

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

The initial value of sanitized is unused, since it is always overwritten.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new AgentTab component, a development sign-in script, and includes a significant number of updates to existing agents, tools, and documentation. The changes also involve a large refactoring of data-fetching hooks to align with a new version of the Mastra client SDK, making them more robust. My review focuses on improving code quality, fixing potential UI bugs, and addressing anti-patterns in the new and modified components.

<div className="grid gap-4 md:grid-cols-2">
<div>
<h4 className="text-sm font-medium mb-2">Model</h4>
<Badge variant="outline">{(agent.model as any).provider}/{(agent.model as any).name}</Badge>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

Using as any is a code smell and bypasses TypeScript's type safety. The useAgentQuery hook appears to normalize the agent.model property to a string. However, this code attempts to access properties (.provider, .name) on it as if it were an object, which will cause a runtime error. You should render the agent.model string directly.

Suggested change
<Badge variant="outline">{(agent.model as any).provider}/{(agent.model as any).name}</Badge>
<Badge variant="outline">{agent.model}</Badge>

const msg = typeof m === "string" ? { role: "user", content: m } : (m as unknown as { role?: string; content?: string; text?: string });
const role = (msg.role as 'user' | 'assistant' | 'system') ?? 'user';
const text = msg.content ?? msg.text ?? "";
const id = `original-${i}-${Date.now()}`;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Using Date.now() to generate a key for React components is an anti-pattern. This will cause the key to be different on every render, forcing React to unmount and re-mount the component, which leads to performance degradation and loss of component state. If the incoming message m has a stable unique identifier, it should be used instead. If not, this is a deeper issue, but at least I can point out the problem with Date.now(). A simple fix is to just use the index i, but that's also not ideal if the list order changes. A better approach if no ID is available is to generate IDs once and store them, but that's more complex. Given the context, I'll point out the issue and suggest using a stable ID if possible.

Comment thread .eslintignore
Comment on lines +7 to +21
coverage/
build/
out/
logs/
/.vscode/
/.mastra/
/.kilocode/
/.github/
/*.log
memory-bank/
memories/
docs/
components/ui/
docker/
coverage/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

There are duplicate entries for coverage/ in this file. To keep the configuration clean and avoid redundancy, one of them should be removed.

Comment on lines +40 to 42
{agent.description !== null && (
<p className="text-sm text-muted-foreground">{agent.description}</p>
)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The condition agent.description !== null could lead to rendering an empty <p> tag if agent.description is an empty string (""), which is not ideal for layout. The previous logic using agent.description && ... was safer as it would correctly handle empty strings as falsy and not render the element. For clarity and correctness, it's better to check for a non-empty string.

Suggested change
{agent.description !== null && (
<p className="text-sm text-muted-foreground">{agent.description}</p>
)}
{agent.description && (
<p className="text-sm text-muted-foreground">{agent.description}</p>
)}

@@ -95,7 +95,7 @@ export function AgentDetails({ agentId }: AgentDetailsProps) {
</TabsContent>

<TabsContent value="evals" className="mt-4">
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The tab's value is set to "evals", but it now renders the AgentTab component which displays general agent details, not evaluations. This is misleading for users. Consider renaming the value to something more descriptive like "overview" or "details" to accurately reflect the content of the tab.

Comment on lines 24 to 29
return agents.filter(
(agent) =>
agent.id.toLowerCase().includes(searchLower) ||
agent.name?.toLowerCase().includes(searchLower) ||
agent.description?.toLowerCase().includes(searchLower)
(agent.id.toLowerCase().includes(searchLower) ||
((agent.name?.toLowerCase().includes(searchLower)) ?? false) ||
agent.description?.toLowerCase().includes(searchLower)) ?? false
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The filtering logic here is a bit complex and can be simplified for better readability. The outer ?? false is redundant since Array.prototype.filter already treats falsy values correctly. The optional chaining (?.) combined with the logical OR (||) operator is sufficient to handle cases where name or description might be null or undefined.

Suggested change
return agents.filter(
(agent) =>
agent.id.toLowerCase().includes(searchLower) ||
agent.name?.toLowerCase().includes(searchLower) ||
agent.description?.toLowerCase().includes(searchLower)
(agent.id.toLowerCase().includes(searchLower) ||
((agent.name?.toLowerCase().includes(searchLower)) ?? false) ||
agent.description?.toLowerCase().includes(searchLower)) ?? false
)
return agents.filter(
(agent) =>
agent.id.toLowerCase().includes(searchLower) ||
agent.name?.toLowerCase().includes(searchLower) ||
agent.description?.toLowerCase().includes(searchLower)
)

Comment on lines +69 to +71
{agent.tools.map((tool, index) => (
<Badge key={index} variant="secondary">{tool.name}</Badge>
))}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Using the index as a key for a list is an anti-pattern in React, especially if the list can be re-ordered, or items can be added or removed. This can lead to incorrect component state and rendering issues. Since each tool object has a unique id, it should be used as the key.

Suggested change
{agent.tools.map((tool, index) => (
<Badge key={index} variant="secondary">{tool.name}</Badge>
))}
{agent.tools.map((tool) => (
<Badge key={tool.id} variant="secondary">{tool.name}</Badge>
))}


const filteredWorkflows = workflowList.filter((wf) =>
wf.id.toLowerCase().includes(searchQuery.toLowerCase())
Boolean(wf.id.toLowerCase().includes(searchQuery.toLowerCase()))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The Boolean() wrapper is redundant here, as String.prototype.includes() already returns a boolean value. The code can be simplified by removing the wrapper.

Suggested change
Boolean(wf.id.toLowerCase().includes(searchQuery.toLowerCase()))
wf.id.toLowerCase().includes(searchQuery.toLowerCase())

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 48

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (11)
src/mastra/tools/find-symbol.tool.ts (1)

22-31: Consider adding TSDoc comments to the SymbolInfo interface.

Per coding guidelines, interface properties should be documented with /** */ comments explaining each field's purpose and constraints.

+/**
+ * Information about a found symbol in the codebase.
+ */
 interface SymbolInfo {
+  /** Symbol name (function, class, variable name, etc.) */
   name: string;
+  /** Symbol kind (function, class, interface, variable, type, enum, property) */
   kind: string;
+  /** Absolute file path where the symbol is defined */
   filePath: string;
+  /** Line number (1-indexed) of the symbol definition */
   line: number;
+  /** Column number of the symbol definition */
   column: number;
+  /** Preview text of the symbol definition (truncated to 100 chars) */
   preview: string;
+  /** Module path relative to project root */
   module?: string;
+  /** Whether the symbol is exported from its module */
   isExported?: boolean;
 }
src/mastra/tools/code-search.tool.ts (1)

162-164: Consider logging skipped files for observability.

The empty catch block silently discards all file-read errors. While skipping binary/unreadable files is appropriate, logging at debug level would aid troubleshooting without impacting normal operation.

       } catch {
-        // Skip binary or unreadable files
+        // Skip binary or unreadable files (could add debug logging here if needed)
       }

Alternatively, emit a debug-level trace span event for skipped files if you want full observability in distributed tracing.

src/mastra/tools/find-references.tool.ts (3)

116-124: Inconsistent context and kind fields in precise lookup path.

The precise lookup path sets context and kind to empty strings, while the name-based search path (line 269-270) properly populates these fields using getCodeContext and getReferenceKind. This leads to inconsistent output depending on which code path is taken.

+                    const refContext = getCodeContext(refSourceFile, pos.line, 2);
+                    const refKind = getReferenceKind(refNode);
+
                     allReferences.push({
                       filePath: refSourceFile.getFilePath(),
                       line: pos.line,
                       column: pos.column,
                       text: refNode.getParent()?.getText().substring(0, 100) ?? refNode.getText(),
                       isDefinition: reference.isDefinition() ?? false,
-                      context: '',
-                      kind: ''
+                      context: refContext,
+                      kind: refKind
                     });

182-190: Python references also have empty context and kind fields.

Similar to the precise lookup path, Python references have empty context and kind. The unused getPythonContext helper (line 295) appears to have been written for this purpose but is never called.

Consider populating these fields for consistency:

             for (const ref of references) {
+              const lines = content.split('\n');
+              const context = getPythonContext(lines, ref.line - 1, 2);
               allReferences.push({
                 filePath: pyFile,
                 line: ref.line,
                 column: ref.column + 1,
                 text: ref.text.substring(0, 100),
                 isDefinition: ref.isDefinition,
-                context: '',
-                kind: ''
+                context,
+                kind: ref.isDefinition ? 'definition' : 'usage'
               });
             }

58-62: Add TSDoc documentation for the exported tool.

Per coding guidelines, public APIs should have TSDoc comments including parameter descriptions, return types, and examples.

+/**
+ * Finds all references to a symbol across TypeScript/JavaScript and Python files.
+ * 
+ * @example
+ * ```typescript
+ * const result = await findReferencesTool.execute({
+ *   symbolName: 'MyClass',
+ *   projectPath: '/path/to/project'
+ * });
+ * ```
+ */
 export const findReferencesTool = createTool({

Similarly, consider adding TSDoc to the exported ReferenceContext type at line 19.

src/mastra/tools/web-scraper-tool.ts (1)

1377-1389: Inconsistent file write pattern.

Other tools in this file use the fs.open + fileHandle.writeFile pattern for security, but siteMapExtractorTool uses fs.writeFile directly. Consider aligning with the safer pattern used elsewhere.

-          await fs.writeFile(
-            fullPath,
-            JSON.stringify(
-              {
-                baseUrl: inputData.url,
-                crawledAt: new Date().toISOString(),
-                pages,
-              },
-              null,
-              2
-            ),
-            'utf-8'
-          )
+          const fileHandle = await fs.open(fullPath, 'w')
+          try {
+            await fileHandle.writeFile(
+              JSON.stringify(
+                {
+                  baseUrl: inputData.url,
+                  crawledAt: new Date().toISOString(),
+                  pages,
+                },
+                null,
+                2
+              ),
+              'utf-8'
+            )
+          } finally {
+            await fileHandle.close()
+          }
src/mastra/tools/data-file-manager.ts (1)

151-169: fs.realpath will fail for new files.

At line 155, fs.realpath(fullPath) is called before the file is created. For new files, this throws ENOENT because realpath requires the target to exist. This breaks the tool's primary use case of creating new files.

Consider validating the directory path instead, or only using realpath if the file already exists:

      const { fileName, content } = inputData
      const fullPath = validateDataPath(fileName)
-      // Resolve the real path to protect against symlink/relative attacks, then validate it is inside DATA_DIR.
-      const realFullPath = await fs.realpath(fullPath)
-      if (!realFullPath.startsWith(DATA_DIR)) {
-        throw new Error(
-          `Access denied: File path "${fileName}" is outside the allowed data directory.`
-        )
-      }
-      const realDirPath = path.dirname(realFullPath)
+      const realDirPath = path.dirname(fullPath)
       // Defensive: Ensure realDirPath is within DATA_DIR before creating directory
       if (!realDirPath.startsWith(DATA_DIR)) {
         throw new Error(
           `Access denied: Directory path "${realDirPath}" is outside the allowed data directory.`
         )
       }
       await fs.mkdir(realDirPath, { recursive: true })
-      await fs.writeFile(realFullPath, content, 'utf-8')
+      await fs.writeFile(fullPath, content, 'utf-8')
app/dashboard/memory/page.tsx (1)

255-265: Missing UI feedback after thread deletion.

The handleDeleteThread function deletes the thread but doesn't clear selectedThreadId or trigger a refetch, leaving the UI in an inconsistent state showing a deleted thread's details.

   const handleDeleteThread = async () => {
     setDeleting(true)
     try {
       const thread = mastraClient.getMemoryThread({ threadId, agentId })
       await thread.delete()
+      // Clear selection and notify parent to refetch - consider lifting state or using a callback
     } catch (err) {
       console.error("Failed to delete thread:", err)
     } finally {
       setDeleting(false)
     }
   }
lib/types/mastra-api.ts (1)

126-140: Consider adding discriminated union for better type safety.

The content union works but could benefit from a discriminated union pattern for clearer type narrowing in consuming code.

 export const MessageSchema = z.object({
   id: z.string(),
   role: z.enum(["user", "assistant", "system"]),
-  // Content can be a raw string or a richer structured object with 'content' or 'parts'
-  content: z.union([
-    z.string(),
-    z.object({ content: z.string() }),
-    z.object({ parts: z.array(z.object({ text: z.string().optional(), type: z.string().optional() })) }),
-  ]),
+  content: z.union([
+    z.string(),
+    z.object({ type: z.literal("text"), content: z.string() }),
+    z.object({ type: z.literal("parts"), parts: z.array(z.object({ text: z.string().optional(), type: z.string().optional() })) }),
+  ]),
   format: z.number().optional(),
app/dashboard/telemetry/page.tsx (1)

64-72: Remove or disable the scope filter input since it's not functional.

The scope filter input is displayed to users but the filter is commented out in line 33. This creates a confusing UX where users can enter a scope filter that has no effect.

Consider either removing the scope input entirely or adding a disabled state with a tooltip explaining the limitation:

           <div className="w-64">
-            <Label className="text-xs text-muted-foreground">Scope</Label>
+            <Label className="text-xs text-muted-foreground">Scope (not currently supported)</Label>
             <Input
               value={scopeFilter}
               onChange={(e) => setScopeFilter(e.target.value)}
               placeholder="Filter by scope..."
               className="mt-1"
+              disabled
             />
           </div>
lib/hooks/use-mastra.ts (1)

16-31: Missing fetcher in useEffect dependency array causes stale closures.

The refetch callback depends on fetcher, but the useEffect only uses deps which doesn't include fetcher. If the fetcher function changes identity, the effect won't re-run with the new fetcher. Additionally, ESLint will flag deps as a non-standard dependency spread.

   const refetch = useCallback(async () => {
     setLoading(true)
     setError(null)
     try {
       const result = await fetcher()
       setData(result)
     } catch (err) {
       setError(err instanceof Error ? err : new Error(String(err)))
     } finally {
       setLoading(false)
     }
-  }, [fetcher])
+  }, [fetcher, ...deps])

   useEffect(() => {
     refetch()
-  }, deps)
+  // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [refetch])

   return { data, loading, error, refetch }

Note: This requires callers to memoize their fetcher functions to prevent infinite re-renders. As per coding guidelines, ensure a complete dependency array in useEffect hooks.

♻️ Duplicate comments (1)
lib/hooks/use-mastra.ts (1)

152-206: Consider extracting message content normalization to reduce duplication.

The content extraction logic (lines 167-182) is identical to lib/hooks/use-dashboard-queries.ts (lines 254-267). This should be extracted to a shared utility as noted in the other file's review.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51ce4ee and 689c88a.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (52)
  • .eslintignore (1 hunks)
  • .github/agents/4.1-Beast.agent.md (1 hunks)
  • .github/agents/Architect.agent.md (1 hunks)
  • .github/agents/Code.Reviewer.agent.md (1 hunks)
  • .github/agents/Thinking-Beast-Mode.agent.md (2 hunks)
  • .github/agents/accessibility.agent.md (1 hunks)
  • .github/agents/adr-generator.agent.md (1 hunks)
  • .github/agents/critical-thinking.agent.md (1 hunks)
  • .github/agents/debug.agent.md (1 hunks)
  • .github/agents/expert-nextjs-developer.agent.md (1 hunks)
  • .github/agents/expert-react-frontend-engineer.agent.md (1 hunks)
  • .github/agents/prd.agent.md (1 hunks)
  • .github/agents/research-technical-spike.agent.md (1 hunks)
  • .github/agents/task-planner.agent.md (1 hunks)
  • .github/agents/task-researcher.agent.md (1 hunks)
  • .github/agents/technical-content-evaluator.agent (1).md (1 hunks)
  • .github/agents/technical-content-evaluator.agent.md (1 hunks)
  • .github/commands/code-review-generic.instructions.md (1 hunks)
  • .github/copilot-instructions.md (1 hunks)
  • .github/instructions/github-actions-ci-cd-best-practices.instructions.md (1 hunks)
  • AGENTS.md (4 hunks)
  • README.md (6 hunks)
  • app/dashboard/agents/_components/agent-details.tsx (4 hunks)
  • app/dashboard/agents/_components/agent-evals-tab.tsx (0 hunks)
  • app/dashboard/agents/_components/agent-list-item.tsx (1 hunks)
  • app/dashboard/agents/_components/agent-list.tsx (1 hunks)
  • app/dashboard/agents/_components/agent-tab.tsx (1 hunks)
  • app/dashboard/agents/_components/index.ts (1 hunks)
  • app/dashboard/memory/page.tsx (5 hunks)
  • app/dashboard/telemetry/page.tsx (3 hunks)
  • app/dashboard/workflows/page.tsx (6 hunks)
  • eslint.config.cjs (1 hunks)
  • lib/auth-dev.ts (1 hunks)
  • lib/auth.ts (1 hunks)
  • lib/client-stream-to-ai-sdk.ts (3 hunks)
  • lib/hooks/use-dashboard-queries.ts (16 hunks)
  • lib/hooks/use-mastra.ts (10 hunks)
  • lib/mastra-client.ts (2 hunks)
  • lib/types/mastra-api.ts (4 hunks)
  • package.json (7 hunks)
  • src/mastra/index.ts (3 hunks)
  • src/mastra/tools/code-analysis.tool.ts (8 hunks)
  • src/mastra/tools/code-search.tool.ts (5 hunks)
  • src/mastra/tools/data-file-manager.ts (2 hunks)
  • src/mastra/tools/data-processing-tools.ts (9 hunks)
  • src/mastra/tools/diff-review.tool.ts (5 hunks)
  • src/mastra/tools/find-references.tool.ts (11 hunks)
  • src/mastra/tools/find-symbol.tool.ts (10 hunks)
  • src/mastra/tools/multi-string-edit.tool.ts (5 hunks)
  • src/mastra/tools/semantic-utils.ts (15 hunks)
  • src/mastra/tools/web-scraper-tool.ts (18 hunks)
  • src/mastra/types/excalidraw-to-svg.d.ts (2 hunks)
💤 Files with no reviewable changes (1)
  • app/dashboard/agents/_components/agent-evals-tab.tsx
🧰 Additional context used
📓 Path-based instructions (19)
**/app/**

📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)

Use the app/ directory structure for route handlers, server components, and client components (Next.js 13+). Prefer this over the pages/ directory for new projects.

Files:

  • app/dashboard/agents/_components/agent-list-item.tsx
  • app/dashboard/agents/_components/agent-tab.tsx
  • app/dashboard/agents/_components/index.ts
  • app/dashboard/agents/_components/agent-list.tsx
  • app/dashboard/memory/page.tsx
  • app/dashboard/telemetry/page.tsx
  • app/dashboard/agents/_components/agent-details.tsx
  • app/dashboard/workflows/page.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)

**/*.{js,jsx,ts,tsx}: Use next/dynamic for dynamic imports to load components only when needed, improving initial load time.
Use next/image component for automatic image optimization, including lazy loading and responsive images.
Use React.memo to prevent unnecessary re-renders of components.
Use the <Link prefetch> tag to prefetch pages that are likely to be visited.
Use getServerSideProps, getStaticProps, or server components for fetching data on the server-side.
Use SWR or React Query for client-side data fetching and caching.
Use CSS Modules, Styled Components, or Tailwind CSS for component-level styling. Prefer Tailwind CSS for rapid development.
Use React Context, Zustand, Jotai, or Recoil for managing global state. Avoid Redux unless necessary.
Use react-hook-form for managing forms and validation.
Only fetch the data that is needed by the component to avoid over-fetching.
Avoid long-running synchronous operations in the main thread to prevent blocking.
Always use setState or hooks to update state instead of mutating state directly.
Include a complete dependency array in useEffect hooks to prevent unexpected behavior.
Avoid writing server-side code in client components to prevent exposing secrets or causing unexpected behavior.
Use try...catch blocks for handling errors in asynchronous operations.
Implement error boundary components using getDerivedStateFromError or componentDidCatch lifecycle methods.
Sanitize user input to prevent Cross-Site Scripting (XSS) attacks. Be especially careful when rendering HTML directly from user input.
Store authentication tokens in HTTP-only cookies or local storage securely.
Implement role-based access control to restrict access to sensitive resources.
Clean up event listeners and timers in useEffect hooks to avoid memory leaks.
Only update state when necessary to reduce the number of re-renders and improve performance.
Use immutable data structures and avoid mutating data directly to prevent unexpected...

Files:

  • app/dashboard/agents/_components/agent-list-item.tsx
  • lib/auth-dev.ts
  • src/mastra/tools/multi-string-edit.tool.ts
  • app/dashboard/agents/_components/agent-tab.tsx
  • app/dashboard/agents/_components/index.ts
  • lib/mastra-client.ts
  • src/mastra/tools/data-file-manager.ts
  • lib/auth.ts
  • app/dashboard/agents/_components/agent-list.tsx
  • src/mastra/index.ts
  • src/mastra/tools/code-search.tool.ts
  • lib/client-stream-to-ai-sdk.ts
  • app/dashboard/memory/page.tsx
  • app/dashboard/telemetry/page.tsx
  • lib/types/mastra-api.ts
  • src/mastra/tools/diff-review.tool.ts
  • app/dashboard/agents/_components/agent-details.tsx
  • src/mastra/tools/find-symbol.tool.ts
  • app/dashboard/workflows/page.tsx
  • src/mastra/tools/find-references.tool.ts
  • src/mastra/tools/web-scraper-tool.ts
  • src/mastra/tools/semantic-utils.ts
  • lib/hooks/use-mastra.ts
  • lib/hooks/use-dashboard-queries.ts
  • src/mastra/tools/code-analysis.tool.ts
  • src/mastra/tools/data-processing-tools.ts
  • src/mastra/types/excalidraw-to-svg.d.ts
app/**/*.{tsx,ts}

📄 CodeRabbit inference engine (app/AGENTS.md)

app/**/*.{tsx,ts}: Use Tailwind CSS 4 with oklch color variables for styling in Next.js App Router pages and layouts
Use React 19 latest features in component implementations within the app directory

Files:

  • app/dashboard/agents/_components/agent-list-item.tsx
  • app/dashboard/agents/_components/agent-tab.tsx
  • app/dashboard/agents/_components/index.ts
  • app/dashboard/agents/_components/agent-list.tsx
  • app/dashboard/memory/page.tsx
  • app/dashboard/telemetry/page.tsx
  • app/dashboard/agents/_components/agent-details.tsx
  • app/dashboard/workflows/page.tsx
app/dashboard/**/*.{ts,tsx}

📄 CodeRabbit inference engine (app/dashboard/AGENTS.md)

app/dashboard/**/*.{ts,tsx}: Use custom React hooks from lib/hooks/use-mastra.ts to wrap MastraClient for data fetching (e.g., useAgents(), useAgent(id), useWorkflows(), useTools(), etc.) in dashboard pages
Use action hooks for dashboard mutations (e.g., useExecuteTool(), useCreateMemoryThread(), useUpdateWorkingMemory(), useVectorQuery(), useScoreTraces()) instead of direct MastraClient calls

Files:

  • app/dashboard/agents/_components/agent-list-item.tsx
  • app/dashboard/agents/_components/agent-tab.tsx
  • app/dashboard/agents/_components/index.ts
  • app/dashboard/agents/_components/agent-list.tsx
  • app/dashboard/memory/page.tsx
  • app/dashboard/telemetry/page.tsx
  • app/dashboard/agents/_components/agent-details.tsx
  • app/dashboard/workflows/page.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never commit API keys or secrets to the repository; use maskSensitiveMessageData() helper from src/mastra/config/pg-storage.ts when logging

**/*.{ts,tsx}: Document interface and type definitions with TSDoc comments explaining their purpose and usage context
Document interface properties with /** */ comments explaining each field's purpose and constraints
Document generic type parameters with @template tags explaining what each type parameter represents
Use type guards with comments explaining the runtime validation logic being performed
Document advanced/complex TypeScript types with explanatory comments about their purpose and use cases

Files:

  • app/dashboard/agents/_components/agent-list-item.tsx
  • lib/auth-dev.ts
  • src/mastra/tools/multi-string-edit.tool.ts
  • app/dashboard/agents/_components/agent-tab.tsx
  • app/dashboard/agents/_components/index.ts
  • lib/mastra-client.ts
  • src/mastra/tools/data-file-manager.ts
  • lib/auth.ts
  • app/dashboard/agents/_components/agent-list.tsx
  • src/mastra/index.ts
  • src/mastra/tools/code-search.tool.ts
  • lib/client-stream-to-ai-sdk.ts
  • app/dashboard/memory/page.tsx
  • app/dashboard/telemetry/page.tsx
  • lib/types/mastra-api.ts
  • src/mastra/tools/diff-review.tool.ts
  • app/dashboard/agents/_components/agent-details.tsx
  • src/mastra/tools/find-symbol.tool.ts
  • app/dashboard/workflows/page.tsx
  • src/mastra/tools/find-references.tool.ts
  • src/mastra/tools/web-scraper-tool.ts
  • src/mastra/tools/semantic-utils.ts
  • lib/hooks/use-mastra.ts
  • lib/hooks/use-dashboard-queries.ts
  • src/mastra/tools/code-analysis.tool.ts
  • src/mastra/tools/data-processing-tools.ts
  • src/mastra/types/excalidraw-to-svg.d.ts
app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Next.js 16 App Router with React 19 for frontend development in the app/ directory

Files:

  • app/dashboard/agents/_components/agent-list-item.tsx
  • app/dashboard/agents/_components/agent-tab.tsx
  • app/dashboard/agents/_components/index.ts
  • app/dashboard/agents/_components/agent-list.tsx
  • app/dashboard/memory/page.tsx
  • app/dashboard/telemetry/page.tsx
  • app/dashboard/agents/_components/agent-details.tsx
  • app/dashboard/workflows/page.tsx
{app,ui,src/components}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Tailwind CSS 4 with oklch color variables for styling in UI components

Files:

  • app/dashboard/agents/_components/agent-list-item.tsx
  • app/dashboard/agents/_components/agent-tab.tsx
  • app/dashboard/agents/_components/index.ts
  • app/dashboard/agents/_components/agent-list.tsx
  • app/dashboard/memory/page.tsx
  • app/dashboard/telemetry/page.tsx
  • app/dashboard/agents/_components/agent-details.tsx
  • app/dashboard/workflows/page.tsx
{app,src/components}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

{app,src/components}/**/*.{ts,tsx}: Use shadcn/ui base components (34 components) located in ui/ directory for common UI elements
Use AI Elements library (30 components) from src/components/ai-elements/ for chat, reasoning, and canvas UIs

Files:

  • app/dashboard/agents/_components/agent-list-item.tsx
  • app/dashboard/agents/_components/agent-tab.tsx
  • app/dashboard/agents/_components/index.ts
  • app/dashboard/agents/_components/agent-list.tsx
  • app/dashboard/memory/page.tsx
  • app/dashboard/telemetry/page.tsx
  • app/dashboard/agents/_components/agent-details.tsx
  • app/dashboard/workflows/page.tsx
**/*.{ts,tsx,js,jsx,py,java,cs,rb,go,rs,cpp,c,h,hpp,swift,kotlin,php,scala,clj,groovy,lua,sh,bash}

📄 CodeRabbit inference engine (.github/instructions/self-explanatory-code-commenting.instructions.md)

**/*.{ts,tsx,js,jsx,py,java,cs,rb,go,rs,cpp,c,h,hpp,swift,kotlin,php,scala,clj,groovy,lua,sh,bash}: Write code that speaks for itself. Comment only when necessary to explain WHY, not WHAT. Avoid obvious comments that state what the code literally does.
Avoid redundant comments that simply repeat what the code is doing
Keep comments accurate and up-to-date with code changes. Remove or update outdated comments that no longer match the implementation.
Write comments for complex business logic that explain the WHY behind specific calculations or business rules
Document non-obvious algorithms with comments explaining the algorithm choice and its reasoning
Add comments explaining what regex patterns match, especially for complex patterns
Document API constraints, rate limits, gotchas, and external dependencies with explanatory comments
Avoid commenting out dead code. Use version control instead of maintaining commented code blocks.
Do not maintain code change history or modification logs as comments. Rely on git history and commit messages instead.
Avoid decorative divider comments (e.g., lines of equals signs or asterisks) for section separation
Ensure comments are placed appropriately above or adjacent to the code they describe
Write comments using proper grammar, spelling, and professional language
Prefer self-documenting code with clear variable/function names over adding comments to explain unclear code

Files:

  • app/dashboard/agents/_components/agent-list-item.tsx
  • lib/auth-dev.ts
  • src/mastra/tools/multi-string-edit.tool.ts
  • app/dashboard/agents/_components/agent-tab.tsx
  • app/dashboard/agents/_components/index.ts
  • lib/mastra-client.ts
  • src/mastra/tools/data-file-manager.ts
  • lib/auth.ts
  • app/dashboard/agents/_components/agent-list.tsx
  • src/mastra/index.ts
  • src/mastra/tools/code-search.tool.ts
  • lib/client-stream-to-ai-sdk.ts
  • app/dashboard/memory/page.tsx
  • app/dashboard/telemetry/page.tsx
  • lib/types/mastra-api.ts
  • src/mastra/tools/diff-review.tool.ts
  • app/dashboard/agents/_components/agent-details.tsx
  • src/mastra/tools/find-symbol.tool.ts
  • app/dashboard/workflows/page.tsx
  • src/mastra/tools/find-references.tool.ts
  • src/mastra/tools/web-scraper-tool.ts
  • src/mastra/tools/semantic-utils.ts
  • lib/hooks/use-mastra.ts
  • lib/hooks/use-dashboard-queries.ts
  • src/mastra/tools/code-analysis.tool.ts
  • src/mastra/tools/data-processing-tools.ts
  • src/mastra/types/excalidraw-to-svg.d.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/instructions/self-explanatory-code-commenting.instructions.md)

**/*.{ts,tsx,js,jsx}: Document public APIs with TSDoc/JSDoc comments including parameter descriptions, return types, examples, and thrown exceptions
Add TSDoc comments to configuration constants and environment variables explaining their source, reasoning, or constraints
Use TSDoc annotation tags (TODO, FIXME, HACK, NOTE, WARNING, PERF, SECURITY, BUG, REFACTOR, DEPRECATED) to mark special comments
Include file headers with @fileoverview, @author, @copyright, and @license tags to document file purpose and ownership
Document function parameters with @param tags, return values with @returns tags, and exceptions with @throws tags in TSDoc comments
Use @see tags in TSDoc comments to reference related functions, methods, or documentation
Include @example tags in public API documentation with code examples showing typical usage

Files:

  • app/dashboard/agents/_components/agent-list-item.tsx
  • lib/auth-dev.ts
  • src/mastra/tools/multi-string-edit.tool.ts
  • app/dashboard/agents/_components/agent-tab.tsx
  • app/dashboard/agents/_components/index.ts
  • lib/mastra-client.ts
  • src/mastra/tools/data-file-manager.ts
  • lib/auth.ts
  • app/dashboard/agents/_components/agent-list.tsx
  • src/mastra/index.ts
  • src/mastra/tools/code-search.tool.ts
  • lib/client-stream-to-ai-sdk.ts
  • app/dashboard/memory/page.tsx
  • app/dashboard/telemetry/page.tsx
  • lib/types/mastra-api.ts
  • src/mastra/tools/diff-review.tool.ts
  • app/dashboard/agents/_components/agent-details.tsx
  • src/mastra/tools/find-symbol.tool.ts
  • app/dashboard/workflows/page.tsx
  • src/mastra/tools/find-references.tool.ts
  • src/mastra/tools/web-scraper-tool.ts
  • src/mastra/tools/semantic-utils.ts
  • lib/hooks/use-mastra.ts
  • lib/hooks/use-dashboard-queries.ts
  • src/mastra/tools/code-analysis.tool.ts
  • src/mastra/tools/data-processing-tools.ts
  • src/mastra/types/excalidraw-to-svg.d.ts
**/*.{js,ts}

📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)

Use parameterized queries or an ORM to prevent SQL injection attacks.

Files:

  • lib/auth-dev.ts
  • src/mastra/tools/multi-string-edit.tool.ts
  • app/dashboard/agents/_components/index.ts
  • lib/mastra-client.ts
  • src/mastra/tools/data-file-manager.ts
  • lib/auth.ts
  • src/mastra/index.ts
  • src/mastra/tools/code-search.tool.ts
  • lib/client-stream-to-ai-sdk.ts
  • lib/types/mastra-api.ts
  • src/mastra/tools/diff-review.tool.ts
  • src/mastra/tools/find-symbol.tool.ts
  • src/mastra/tools/find-references.tool.ts
  • src/mastra/tools/web-scraper-tool.ts
  • src/mastra/tools/semantic-utils.ts
  • lib/hooks/use-mastra.ts
  • lib/hooks/use-dashboard-queries.ts
  • src/mastra/tools/code-analysis.tool.ts
  • src/mastra/tools/data-processing-tools.ts
  • src/mastra/types/excalidraw-to-svg.d.ts
src/mastra/tools/**/*.ts

📄 CodeRabbit inference engine (src/mastra/AGENTS.md)

src/mastra/tools/**/*.ts: Use the createTool pattern with Zod schemas when adding new tools under src/mastra/tools
Use explicit Zod schemas for every tool input/output

src/mastra/tools/**/*.ts: Use Zod schemas for strict validation of tool inputs and outputs in all Mastra tools
Implement tools using the createTool({ id, inputSchema, outputSchema, execute }) pattern
Organize tools into categories: Financial (Polygon, Finnhub, AlphaVantage), Research (SerpAPI, ArXiv), Data (CSV, JSON), RAG (chunking, embeddings)

Files:

  • src/mastra/tools/multi-string-edit.tool.ts
  • src/mastra/tools/data-file-manager.ts
  • src/mastra/tools/code-search.tool.ts
  • src/mastra/tools/diff-review.tool.ts
  • src/mastra/tools/find-symbol.tool.ts
  • src/mastra/tools/find-references.tool.ts
  • src/mastra/tools/web-scraper-tool.ts
  • src/mastra/tools/semantic-utils.ts
  • src/mastra/tools/code-analysis.tool.ts
  • src/mastra/tools/data-processing-tools.ts
src/mastra/{tools,workflows}/**/*.ts

📄 CodeRabbit inference engine (src/mastra/AGENTS.md)

Use RuntimeContext to enforce access control in tools and workflows

Files:

  • src/mastra/tools/multi-string-edit.tool.ts
  • src/mastra/tools/data-file-manager.ts
  • src/mastra/tools/code-search.tool.ts
  • src/mastra/tools/diff-review.tool.ts
  • src/mastra/tools/find-symbol.tool.ts
  • src/mastra/tools/find-references.tool.ts
  • src/mastra/tools/web-scraper-tool.ts
  • src/mastra/tools/semantic-utils.ts
  • src/mastra/tools/code-analysis.tool.ts
  • src/mastra/tools/data-processing-tools.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Run eslint with --max-warnings=0 on src/**/*.{ts,tsx} to enforce linting standards

Files:

  • src/mastra/tools/multi-string-edit.tool.ts
  • src/mastra/tools/data-file-manager.ts
  • src/mastra/index.ts
  • src/mastra/tools/code-search.tool.ts
  • src/mastra/tools/diff-review.tool.ts
  • src/mastra/tools/find-symbol.tool.ts
  • src/mastra/tools/find-references.tool.ts
  • src/mastra/tools/web-scraper-tool.ts
  • src/mastra/tools/semantic-utils.ts
  • src/mastra/tools/code-analysis.tool.ts
  • src/mastra/tools/data-processing-tools.ts
  • src/mastra/types/excalidraw-to-svg.d.ts
src/mastra/**/*

📄 CodeRabbit inference engine (src/AGENTS.md)

mastra modules can import from utils, but must not import from app or cli (except types)

Files:

  • src/mastra/tools/multi-string-edit.tool.ts
  • src/mastra/tools/data-file-manager.ts
  • src/mastra/index.ts
  • src/mastra/tools/code-search.tool.ts
  • src/mastra/tools/diff-review.tool.ts
  • src/mastra/tools/find-symbol.tool.ts
  • src/mastra/tools/find-references.tool.ts
  • src/mastra/tools/web-scraper-tool.ts
  • src/mastra/tools/semantic-utils.ts
  • src/mastra/tools/code-analysis.tool.ts
  • src/mastra/tools/data-processing-tools.ts
  • src/mastra/types/excalidraw-to-svg.d.ts
**/*.md

📄 CodeRabbit inference engine (.github/instructions/markdown.instructions.md)

**/*.md: Use appropriate heading levels (H2, H3, etc.) to structure markdown content. Do not use H1 headings, as these will be generated from the title. Use ## for H2 and ### for H3 in a hierarchical manner. Recommend restructuring if content includes H4 or higher levels.
Use bullet points (with -) or numbered lists (with 1.) for lists in markdown. Indent nested lists with two spaces and ensure proper indentation and spacing.
Use fenced code blocks (triple backticks) for code snippets in markdown. Specify the language after the opening backticks for syntax highlighting (e.g., csharp).
Use proper markdown syntax for links: [link text](URL). Ensure that link text is descriptive and URLs are valid and accessible.
Use proper markdown syntax for images: ![alt text](image URL). Include a brief description of the image in the alt text for accessibility.
Use markdown tables (with | delimiters) for tabular data. Ensure proper formatting, alignment, and inclusion of headers.
Limit line length to 80 characters in markdown for readability. Use soft line breaks for long paragraphs.
Use appropriate whitespace in markdown to separate sections and improve readability. Use blank lines between sections and avoid excessive whitespace.
Include YAML front matter at the beginning of markdown files with required metadata fields: post_title, author1, post_slug, microsoft_alias, featured_image, categories (from /categories.txt), tags, ai_note, summary, and post_date.

Files:

  • README.md
  • AGENTS.md
src/mastra/index.ts

📄 CodeRabbit inference engine (src/AGENTS.md)

Enforce registration pattern in mastra/index.ts for AI orchestration modules composition

Files:

  • src/mastra/index.ts
**/app/**/page.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)

Represent route UIs using page.tsx or page.jsx files within the app/ directory structure.

Files:

  • app/dashboard/memory/page.tsx
  • app/dashboard/telemetry/page.tsx
  • app/dashboard/workflows/page.tsx
**/hooks/**/*.{js,ts}

📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)

Use camelCase for hook file names (e.g., useHookName.js or useHookName.ts).

Files:

  • lib/hooks/use-mastra.ts
  • lib/hooks/use-dashboard-queries.ts
🧬 Code graph analysis (8)
lib/auth-dev.ts (1)
lib/auth.ts (1)
  • signInWithPassword (10-12)
app/dashboard/memory/page.tsx (1)
lib/mastra-client.ts (1)
  • mastraClient (13-21)
app/dashboard/telemetry/page.tsx (1)
lib/hooks/use-mastra.ts (1)
  • useAITraces (232-256)
app/dashboard/agents/_components/agent-details.tsx (1)
app/dashboard/agents/_components/agent-tab.tsx (1)
  • AgentTab (12-77)
src/mastra/tools/web-scraper-tool.ts (1)
src/mastra/config/logger.ts (1)
  • log (14-18)
src/mastra/tools/semantic-utils.ts (1)
src/mastra/config/logger.ts (1)
  • log (14-18)
lib/hooks/use-mastra.ts (2)
lib/mastra-client.ts (1)
  • mastraClient (13-21)
lib/types/mastra-api.ts (1)
  • Message (140-140)
lib/hooks/use-dashboard-queries.ts (2)
lib/mastra-client.ts (1)
  • mastraClient (13-21)
lib/types/mastra-api.ts (3)
  • Agent (24-24)
  • Workflow (61-61)
  • Message (140-140)
🪛 ast-grep (0.40.0)
src/mastra/tools/multi-string-edit.tool.ts

[warning] 114-114: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(oldString, flags)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

🪛 Gitleaks (8.30.0)
.github/commands/code-review-generic.instructions.md

[high] 142-142: Found a Stripe Access Token, posing a risk to payment processing services and sensitive financial data.

(stripe-access-token)

🪛 LanguageTool
.github/instructions/github-actions-ci-cd-best-practices.instructions.md

[uncategorized] ~14-~14: The official name of this software platform is spelled with a capital “H”.
Context: ...Structure ### 1. Workflow Structure (.github/workflows/*.yml) - Principle: Wo...

(GITHUB)


[grammar] ~90-~90: Use a hyphen to join words.
Context: ... or custom actions. Always pin to a full length commit SHA for maximum security a...

(QB_NEW_EN_HYPHEN)


[grammar] ~188-~188: Use a hyphen to join words.
Context: ...rabilities are found, enforcing a secure by default posture. - Suggest adding...

(QB_NEW_EN_HYPHEN)


[grammar] ~188-~188: Use a hyphen to join words.
Context: ...ilities are found, enforcing a secure by default posture. - Suggest adding se...

(QB_NEW_EN_HYPHEN)


[style] ~205-~205: ‘exact same’ might be wordy. Consider a shorter alternative.
Context: ...ing the same code always results in the exact same image. - Image Signing: Use too...

(EN_WORDINESS_PREMIUM_EXACT_SAME)


[style] ~290-~290: As an alternative to the over-used intensifier ‘extremely’, consider replacing this phrase.
Context: ...er=blob:noneor--filter=tree:0`) for extremely large repositories, though this is often hand...

(EN_WEAK_ADJECTIVE)


[style] ~293-~293: Consider a different adjective to strengthen your wording.
Context: ...Git history (e.g., for release tagging, deep commit analysis, or git blame operati...

(DEEP_PROFOUND)


[style] ~309-~309: ‘exact same’ might be wordy. Consider a shorter alternative.
Context: ...d job to a deployment job, ensuring the exact same artifact is deployed that was built and...

(EN_WORDINESS_PREMIUM_EXACT_SAME)


[style] ~454-~454: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...and inter-workflow communication? - Are if conditions used effectively for co...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~455-~455: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...yments, branch-specific actions)? - Are all uses actions securely versioned (...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~482-~482: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...with robust flakiness mitigation? - Are performance and load tests integrated f...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~483-~483: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ications with defined thresholds? - Are all test reports (JUnit XML, HTML, cove...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[uncategorized] ~514-~514: The official name of this software platform is spelled with a capital “H”.
Context: ... debug step to print context variables (${{ toJson(github) }}, ${{ toJson(job) }}, `${{ toJson...

(GITHUB)


[style] ~546-~546: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ...ze limits per repository. If caches are very large, they might be evicted frequently. ###...

(EN_WEAK_ADJECTIVE)


[grammar] ~548-~548: Use a hyphen to join words.
Context: ...ht be evicted frequently. ### 4. Long Running Workflows or Timeouts - **Root...

(QB_NEW_EN_HYPHEN)

.github/commands/code-review-generic.instructions.md

[style] ~49-~49: Try using a synonym here to strengthen your wording.
Context: ...roup related comments**: Avoid multiple comments about the same topic ## Code Quality S...

(COMMENT_REMARK)

.github/agents/technical-content-evaluator.agent (1).md

[style] ~267-~267: ‘overall structure’ might be wordy. Consider a shorter alternative.
Context: ...e and assess appropriateness - Note the overall structure and flow - Map out the technical concep...

(EN_WORDINESS_PREMIUM_OVERALL_STRUCTURE)


[style] ~301-~301: This phrase is often redundant. Consider writing “I” unless you want to emphasize that you and not someone else will do something. Then, commas might be missing.
Context: ...filled by repository contents? 3. Would I personally pay $50 for this course as-is? 4. Would...

(I_MYSELF)

.github/agents/critical-thinking.agent.md

[style] ~23-~23: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ce, but also friendly and supportive. - Be free to argue against the engineer's as...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

.github/agents/prd.agent.md

[style] ~42-~42: This phrase is redundant. Consider writing “details”.
Context: ...ise, and concise language. - Include specific details and metrics whenever applicable. - E...

(SPECIFIC_DETAILS)

.github/agents/research-technical-spike.agent.md

[style] ~59-~59: Consider a different adjective to strengthen your wording.
Context: ...- Identify technical unknowns requiring deep investigation - Plan investigation stra...

(DEEP_PROFOUND)

.github/agents/task-researcher.agent.md

[style] ~13-~13: Consider shortening or rephrasing this to strengthen your wording.
Context: ...pilot-tracking/research/`. You MUST NOT make changes to any other files, code, or configuration...

(MAKE_CHANGES)


[style] ~19-~19: Consider a different adjective to strengthen your wording.
Context: ... these constraints: - You WILL ONLY do deep research using ALL available tools and ...

(DEEP_PROFOUND)


[style] ~67-~67: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ccinctly to guide user decision-making. You MUST help the user select ONE recommend...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~71-~71: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...NLY in ./.copilot-tracking/research/. You MUST NOT modify any source code, config...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~72-~72: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...onfigurations, or other project files. You WILL provide brief, focused updates wit...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~73-~73: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...d updates without overwhelming details. You WILL present discoveries and guide user...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~73-~73: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... user toward single solution selection. You WILL keep all conversation focused on r...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~73-~73: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ed on research activities and findings. You WILL NEVER repeat information already d...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[uncategorized] ~181-~181: The official name of this software platform is spelled with a capital “H”.
Context: ...standards and conventions - Referencing .github/instructions/ and copilot/ for estab...

(GITHUB)

.github/agents/task-planner.agent.md

[grammar] ~90-~90: Use a hyphen to join words.
Context: ...nt-disable-file -->` - Overview: One sentence task description - **Objectives...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.18.1)
.github/instructions/github-actions-ci-cd-best-practices.instructions.md

313-313: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

.github/commands/code-review-generic.instructions.md

65-65: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


92-92: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


129-129: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


161-161: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


191-191: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


245-245: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


268-268: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


268-268: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


292-292: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


293-293: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


293-293: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


320-320: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


321-321: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


321-321: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

.github/agents/debug.agent.md

34-34: Ordered list item prefix
Expected: 1; Actual: 3; Style: 1/2/3

(MD029, ol-prefix)


41-41: Ordered list item prefix
Expected: 2; Actual: 4; Style: 1/2/3

(MD029, ol-prefix)


48-48: Ordered list item prefix
Expected: 1; Actual: 5; Style: 1/2/3

(MD029, ol-prefix)


54-54: Ordered list item prefix
Expected: 2; Actual: 6; Style: 1/2/3

(MD029, ol-prefix)


61-61: Ordered list item prefix
Expected: 1; Actual: 7; Style: 1/2/3

(MD029, ol-prefix)


67-67: Ordered list item prefix
Expected: 2; Actual: 8; Style: 1/2/3

(MD029, ol-prefix)

README.md

313-313: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

.github/agents/accessibility.agent.md

149-149: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


161-161: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


220-220: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


230-230: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


240-240: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: fallthrough
  • GitHub Check: CodeQL analysis (javascript-typescript)
  • GitHub Check: Agent
  • GitHub Check: Codacy Security Scan

Comment on lines +1 to +82
---
description: 'Debug your application to find and fix a bug'
name: 'Debug Agent'
argument-hint: 'Assist in debugging applications by identifying, diagnosing, and resolving bugs through systematic analysis and testing.'
infer: true
tools: ['vscode', 'execute', 'read', 'edit', 'search', 'web', 'agent', 'lotus/*', 'mastrabeta/mastraBlog', 'mastrabeta/mastraChanges', 'mastrabeta/mastraDocs', 'mastrabeta/mastraExamples', 'mastrabeta/mastraMigration', 'multi_orchestrator/*', 'next-devtools/*', 's-ai/*', 'thoughtbox/*', 'docfork/*', 'vscode.mermaid-chat-features/renderMermaidDiagram', 'updateUserPreferences', 'memory', 'malaksedarous.copilot-context-optimizer/askAboutFile', 'malaksedarous.copilot-context-optimizer/runAndExtract', 'malaksedarous.copilot-context-optimizer/askFollowUp', 'malaksedarous.copilot-context-optimizer/researchTopic', 'malaksedarous.copilot-context-optimizer/deepResearch', 'ms-python.python/getPythonEnvironmentInfo', 'ms-python.python/getPythonExecutableCommand', 'ms-python.python/installPythonPackage', 'ms-python.python/configurePythonEnvironment', 'ms-vscode.vscode-websearchforcopilot/websearch', 'todo', 'search/changes', "search/codebase", "edit/editFiles", 'vscode/extensions', 'web/githubRepo', 'vscode/openSimpleBrowser', 'read/problems']
---

# Debug Mode Instructions

You are in debug mode. Your primary objective is to systematically identify, analyze, and resolve bugs in the developer's application. Follow this structured debugging process:

## Phase 1: Problem Assessment

1. **Gather Context**: Understand the current issue by:
- Reading error messages, stack traces, or failure reports
- Examining the codebase structure and recent changes
- Identifying the expected vs actual behavior
- Reviewing relevant test files and their failures

2. **Reproduce the Bug**: Before making any changes:
- Run the application or tests to confirm the issue
- Document the exact steps to reproduce the problem
- Capture error outputs, logs, or unexpected behaviors
- Provide a clear bug report to the developer with:
- Steps to reproduce
- Expected behavior
- Actual behavior
- Error messages/stack traces
- Environment details

## Phase 2: Investigation

3. **Root Cause Analysis**:
- Trace the code execution path leading to the bug
- Examine variable states, data flows, and control logic
- Check for common issues: null references, off-by-one errors, race conditions, incorrect assumptions
- Use search and usages tools to understand how affected components interact
- Review git history for recent changes that might have introduced the bug

4. **Hypothesis Formation**:
- Form specific hypotheses about what's causing the issue
- Prioritize hypotheses based on likelihood and impact
- Plan verification steps for each hypothesis

## Phase 3: Resolution

5. **Implement Fix**:
- Make targeted, minimal changes to address the root cause
- Ensure changes follow existing code patterns and conventions
- Add defensive programming practices where appropriate
- Consider edge cases and potential side effects

6. **Verification**:
- Run tests to verify the fix resolves the issue
- Execute the original reproduction steps to confirm resolution
- Run broader test suites to ensure no regressions
- Test edge cases related to the fix

## Phase 4: Quality Assurance
7. **Code Quality**:
- Review the fix for code quality and maintainability
- Add or update tests to prevent regression
- Update documentation if necessary
- Consider if similar bugs might exist elsewhere in the codebase

8. **Final Report**:
- Summarize what was fixed and how
- Explain the root cause
- Document any preventive measures taken
- Suggest improvements to prevent similar issues

## Debugging Guidelines
- **Be Systematic**: Follow the phases methodically, don't jump to solutions
- **Document Everything**: Keep detailed records of findings and attempts
- **Think Incrementally**: Make small, testable changes rather than large refactors
- **Consider Context**: Understand the broader system impact of changes
- **Communicate Clearly**: Provide regular updates on progress and findings
- **Stay Focused**: Address the specific bug without unnecessary changes
- **Test Thoroughly**: Verify fixes work in various scenarios and environments

Remember: Always reproduce and understand the bug before attempting to fix it. A well-understood problem is half solved.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Align debug tool naming with configured tools and fix ordered list numbering

Two things to address here:

  1. Tool name mismatch

    • The front‑matter tools list exposes read/problems (and no get_errors), while the instructions say:

      Use the get_errors tool… This tool replaces the previously used #problems tool.

    • To avoid confusion and failed tool invocations, the spec should consistently reference the actual MCP/tool identifier. If read/problems (a.k.a. #problems) is the real tool, update the narrative to use that name instead of get_errors, or add get_errors to the tools list if that is in fact a separate tool.

    This misalignment can materially impact how the Debug Agent behaves, so it’s worth fixing before relying on it.

  2. markdownlint MD029 (ordered list prefixes)

    • The numbered steps under the different phases use prefixes like 3. and 5. when starting new ordered lists, which triggers MD029 (“Expected: 1; Actual: 3/5; Style: 1/2/3”).
    • Easiest fix: restart each list at 1. (Markdown will render them correctly) or renumber them sequentially within each list.

    Example for Phase 2 and Phase 3:

    ## Phase 2: Investigation
    
    1. **Root Cause Analysis**:
       ...
    2. **Hypothesis Formation**:
       ...
    
    ## Phase 3: Resolution
    
    1. **Implement Fix**:
       ...
    2. **Verification**:
       ...

    This will satisfy markdownlint while keeping the structure the same.

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

34-34: Ordered list item prefix
Expected: 1; Actual: 3; Style: 1/2/3

(MD029, ol-prefix)


41-41: Ordered list item prefix
Expected: 2; Actual: 4; Style: 1/2/3

(MD029, ol-prefix)


48-48: Ordered list item prefix
Expected: 1; Actual: 5; Style: 1/2/3

(MD029, ol-prefix)


54-54: Ordered list item prefix
Expected: 2; Actual: 6; Style: 1/2/3

(MD029, ol-prefix)


61-61: Ordered list item prefix
Expected: 1; Actual: 7; Style: 1/2/3

(MD029, ol-prefix)


67-67: Ordered list item prefix
Expected: 2; Actual: 8; Style: 1/2/3

(MD029, ol-prefix)

🤖 Prompt for AI Agents
In .github/agents/debug.agent.md around lines 1 to 82, the front-matter tools
list and narrative are inconsistent (the tools list exposes read/problems but
the text references get_errors) and several ordered lists start at non-1 indices
triggering markdownlint MD029; fix by either adding get_errors to the tools
array if that tool actually exists, or change all narrative references from
get_errors to read/problems (and any “#problems” alias) so names match exactly;
also renumber each ordered list so they start at 1 (or restart numbering per
list) to satisfy MD029 and ensure correct rendering.

@@ -0,0 +1,586 @@
---
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check for technical-content-evaluator related files
fd -t f -e md "technical-content-evaluator" .github/agents/ 2>/dev/null || echo "Directory or files not found"

# Also check the specific file mentioned
if [ -f ".github/agents/technical-content-evaluator.agent (1).md" ]; then
    echo "File exists: .github/agents/technical-content-evaluator.agent (1).md"
    ls -lah ".github/agents/technical-content-evaluator.agent (1).md"
fi

# Check for similar files without the (1) suffix
if [ -f ".github/agents/technical-content-evaluator.agent.md" ]; then
    echo "File exists: .github/agents/technical-content-evaluator.agent.md"
    ls -lah ".github/agents/technical-content-evaluator.agent.md"
fi

# List all files in .github/agents directory
echo "---"
echo "All files in .github/agents/:"
ls -lah .github/agents/ 2>/dev/null || echo "Directory not found"

Repository: ssdeanx/AgentStack

Length of output: 2754


🏁 Script executed:

#!/bin/bash
# Compare the two files
echo "=== Comparing file sizes and first 50 lines ==="
echo "File 1: technical-content-evaluator.agent (1).md"
wc -l ".github/agents/technical-content-evaluator.agent (1).md"

echo ""
echo "File 2: technical-content-evaluator.agent.md"
wc -l ".github/agents/technical-content-evaluator.agent.md"

echo ""
echo "=== Checking if files are identical ==="
if cmp -s ".github/agents/technical-content-evaluator.agent (1).md" ".github/agents/technical-content-evaluator.agent.md"; then
    echo "Files are IDENTICAL"
else
    echo "Files are DIFFERENT"
    echo ""
    echo "=== Diff output (first differences) ==="
    diff -u ".github/agents/technical-content-evaluator.agent.md" ".github/agents/technical-content-evaluator.agent (1).md" | head -100
fi

Repository: ssdeanx/AgentStack

Length of output: 5012


Remove duplicate file with non-standard "(1)" suffix and consolidate versions.

Both technical-content-evaluator.agent (1).md and technical-content-evaluator.agent.md exist in .github/agents/. The "(1)" version (586 lines) contains newer evaluation criteria additions including enhanced code snippet validation checks and code length standards that are missing from the standard version (577 lines).

Actions:

  1. Merge the improvements from the "(1)" version into technical-content-evaluator.agent.md, specifically the additions around code snippet source file matching and code length standards (>30 lines).
  2. Delete .github/agents/technical-content-evaluator.agent (1).md.

This resolves the non-standard naming convention while preserving the improvements in the newer version.

🤖 Prompt for AI Agents
.github/agents/technical-content-evaluator.agent (1).md lines 1-1: consolidate
the duplicate into .github/agents/technical-content-evaluator.agent.md by
merging the newer additions from the "(1)" file—specifically add the enhanced
code snippet validation checks for verifying source file matching and the code
length standards (rules for snippets >30 lines) into the canonical
technical-content-evaluator.agent.md, reconcile any minor wording conflicts so
the final file contains both sets of rules, then delete
.github/agents/technical-content-evaluator.agent (1).md to remove the
non-standard filename.

Comment on lines +11 to +14
- 🎯 Always use [`#problems`] / `'read/problems'` tool for debugging, to ensure code quality.
- Never run commands without checking with `#problems` / `'read/problems'` tool first. *This is critical to avoid errors.*
- This is YOUR Internal TOOL. NOT PART OF THE USER PROJECT ITS YOUR OWN TOOL TO HELP YOU BUILD debug.
- It might `'read/problems'` files from the user project to help you debug issues.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Tighten wording around #problems / read/problems usage

The intent of these bullets is good, but the phrasing is a bit hard to parse. Consider something like:

- 🎯 Always use the `#problems` / `read/problems` tool for debugging to ensure code quality.
- Never run commands without first checking with the `#problems` / `read/problems` tool. *This is critical to avoid errors.*
- This is your internal tool, not part of the user’s project; it exists solely to help you debug.
- It may read `read/problems` files from the user project to help diagnose issues.

This keeps the same behavior but reads more clearly and professionally.

🤖 Prompt for AI Agents
.github/copilot-instructions.md lines 11-14: the bullets about `#problems` /
`read/problems` are unclear and awkwardly phrased; rewrite them to be concise
and professional while preserving intent: use a consistent backtick style for
the tool names, state that the tool should always be used for debugging, require
that commands are not run without first checking the tool, clarify it is an
internal tool not part of the user project, and note it may read `read/problems`
files from the user project to help diagnose issues.

Comment on lines +39 to +44
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-semibold">{agent.name}</h3>
<p className="text-sm text-muted-foreground mt-1">{agent.description}</p>
</div>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add null checks for optional agent fields.

Lines 42-43 access agent.name and agent.description without null checks. If these fields can be nullable, consider adding fallbacks.

Apply this diff to add defensive checks:

       <h3 className="text-lg font-semibold">{agent.name}</h3>
-        <p className="text-sm text-muted-foreground mt-1">{agent.description}</p>
+        {agent.description && (
+          <p className="text-sm text-muted-foreground mt-1">{agent.description}</p>
+        )}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In app/dashboard/agents/_components/agent-tab.tsx around lines 39 to 44, the JSX
accesses agent.name and agent.description directly which may be null/undefined;
update the rendering to use safe fallbacks or conditional rendering (e.g.,
display agent.name ?? 'Untitled Agent' and agent.description ?? '' or omit the
<p> when description is falsy) so the component never reads properties that
might be null and the UI shows a sensible default.

Comment on lines +46 to +56
<div className="grid gap-4 md:grid-cols-2">
<div>
<h4 className="text-sm font-medium mb-2">Model</h4>
<Badge variant="outline">{(agent.model as any).provider}/{(agent.model as any).name}</Badge>
</div>

<div>
<h4 className="text-sm font-medium mb-2">Status</h4>
<Badge variant="default">Active</Badge>
</div>
</div>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix unsafe type casting for model access.

Line 49 uses as any to access model properties, which bypasses type safety and could cause runtime errors if the model structure doesn't match expectations.

Consider these approaches:

Option 1: Define a proper type for the model:

+interface AgentModel {
+  provider: string;
+  name: string;
+  [key: string]: unknown;
+}
+
       <div>
         <h4 className="text-sm font-medium mb-2">Model</h4>
-        <Badge variant="outline">{(agent.model as any).provider}/{(agent.model as any).name}</Badge>
+        <Badge variant="outline">
+          {typeof agent.model === 'string' 
+            ? agent.model 
+            : `${(agent.model as AgentModel).provider}/${(agent.model as AgentModel).name}`}
+        </Badge>
       </div>

Option 2: Add defensive checks:

       <div>
         <h4 className="text-sm font-medium mb-2">Model</h4>
-        <Badge variant="outline">{(agent.model as any).provider}/{(agent.model as any).name}</Badge>
+        <Badge variant="outline">
+          {agent.model && typeof agent.model === 'object' && 'provider' in agent.model && 'name' in agent.model
+            ? `${agent.model.provider}/${agent.model.name}`
+            : String(agent.model)}
+        </Badge>
       </div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="grid gap-4 md:grid-cols-2">
<div>
<h4 className="text-sm font-medium mb-2">Model</h4>
<Badge variant="outline">{(agent.model as any).provider}/{(agent.model as any).name}</Badge>
</div>
<div>
<h4 className="text-sm font-medium mb-2">Status</h4>
<Badge variant="default">Active</Badge>
</div>
</div>
<div className="grid gap-4 md:grid-cols-2">
<div>
<h4 className="text-sm font-medium mb-2">Model</h4>
<Badge variant="outline">
{agent.model && typeof agent.model === 'object' && 'provider' in agent.model && 'name' in agent.model
? `${agent.model.provider}/${agent.model.name}`
: String(agent.model)}
</Badge>
</div>
<div>
<h4 className="text-sm font-medium mb-2">Status</h4>
<Badge variant="default">Active</Badge>
</div>
</div>
🤖 Prompt for AI Agents
In app/dashboard/agents/_components/agent-tab.tsx around lines 46 to 56, the
code unsafely casts agent.model to any to access provider and name; replace the
unsafe cast by either (A) defining a proper TypeScript interface/type for
agent.model (e.g., { provider: string; name: string } or a union of possible
shapes), update the agent prop/type to use it, and access model.provider and
model.name with full typing, or (B) add defensive runtime checks before
rendering (verify agent.model is an object and has string properties provider
and name, and render a fallback or placeholder if those checks fail) so you
avoid any usage of "as any" and prevent potential runtime errors.

Comment on lines +342 to +346
function isSymbolExported(sourceFile: SourceFile, symbolName: string): boolean {
// Check if symbol is exported
const exports = sourceFile.getExportSymbols();
return exports.some((exp: any) => exp.getName() === symbolName);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Avoid any type annotation.

The any type bypasses TypeScript's type checking. Consider using proper typing from ts-morph.

 function isSymbolExported(sourceFile: SourceFile, symbolName: string): boolean {
-  // Check if symbol is exported
   const exports = sourceFile.getExportSymbols();
-  return exports.some((exp: any) => exp.getName() === symbolName);
+  return exports.some(exp => exp.getName() === symbolName);
 }
🤖 Prompt for AI Agents
In src/mastra/tools/find-symbol.tool.ts around lines 342-346, the callback
parameter is typed as `any`; replace it with the proper ts-morph Symbol type
(e.g. import { Symbol as TsMorphSymbol } from "ts-morph" and use (exp:
TsMorphSymbol) => ...) or the exact Symbol type exported by ts-morph, and add
the necessary import if not present so TypeScript can type-check the export
symbol comparison.

Comment on lines +348 to 360
function isPythonSymbolExported(content: string, symbolName: string): boolean {
// Simple heuristic: check if symbol appears in __all__ or is imported
const lines = content.split('\n');
for (const line of lines) {
if (line.includes('__all__') && line.includes(symbolName)) {
return true;
}
if (line.trim().startsWith('from ') && line.includes(symbolName)) {
return true;
}
}
return false;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix incorrect export detection logic for Python.

The check at lines 355-357 determines if a symbol is imported from elsewhere, not if it's exported from the current module. A from X import symbolName statement means symbolName is being imported into this file, not exported from it.

Consider this corrected heuristic:

 function isPythonSymbolExported(content: string, symbolName: string): boolean {
-  // Simple heuristic: check if symbol appears in __all__ or is imported
   const lines = content.split('\n');
   for (const line of lines) {
+    // Check if symbol is explicitly listed in __all__
     if (line.includes('__all__') && line.includes(symbolName)) {
       return true;
     }
-    if (line.trim().startsWith('from ') && line.includes(symbolName)) {
-      return true;
-    }
   }
-  return false;
+  // In Python, module-level definitions without underscore prefix are typically public
+  return !symbolName.startsWith('_');
 }

This follows Python convention where names starting with _ are considered private.

🤖 Prompt for AI Agents
In src/mastra/tools/find-symbol.tool.ts around lines 348 to 360, the current
heuristic wrongly treats "from X import Y" as evidence that Y is exported from
this module; instead, update the logic to (1) remove the check for import
statements as export indicators, (2) detect exports via an explicit __all__ list
containing the symbolName, (3) consider top-level definitions (e.g., "def
symbolName(" or "class symbolName(") as exported if they do not start with an
underscore, and (4) treat names starting with "_" as private unless present in
__all__; implement these checks in that function so it returns true only when
symbolName appears in __all__ or is a top-level non-underscore def/class.

Comment on lines +75 to 130
// Create new project with better error handling
try {
log.info(`Initializing new ts-morph project for ${normalizedPath}`);

const tsConfigPath = path.join(normalizedPath, 'tsconfig.json');
const hasTsConfig = require('fs').existsSync(tsConfigPath);

// Estimate memory usage
const fileCount = project.getSourceFiles().length;
const estimatedMemoryMB = fileCount * this.MEMORY_PER_FILE_MB;

// Cache if within limits
if (estimatedMemoryMB <= this.MAX_PROJECT_MEMORY_MB) {
// Evict if needed
this.ensureCapacity(estimatedMemoryMB);

this.cache.set(normalizedPath, {
project,
lastAccess: now,
fileCount,
estimatedMemoryMB,
hitCount: 0
const project = new Project({
tsConfigFilePath: hasTsConfig === true ? tsConfigPath : undefined,
skipAddingFilesFromTsConfig: false,
skipFileDependencyResolution: true, // Better performance
skipLoadingLibFiles: true, // Skip loading lib files for better performance
});
} else {
log.warn(`Project ${normalizedPath} too large (${estimatedMemoryMB.toFixed(1)}MB) - skipping cache`);
}

return project;
// Add source files manually if no tsconfig
if (hasTsConfig === false) {
const sourceFiles = fg.sync('**/*.{ts,tsx,js,jsx}', {
cwd: normalizedPath,
ignore: ['node_modules/**', '.git/**', 'dist/**', 'build/**'],
onlyFiles: true,
absolute: true,
dot: true,
unique: true,
});
project.addSourceFilesAtPaths(sourceFiles);
}

// Estimate memory usage
const fileCount = project.getSourceFiles().length;
const estimatedMemoryMB = Math.max(fileCount * this.MEMORY_PER_FILE_MB, 10); // Minimum 10MB

// Cache if within limits
if (estimatedMemoryMB <= this.MAX_PROJECT_MEMORY_MB) {
// Evict if needed
this.ensureCapacity(estimatedMemoryMB);

this.cache.set(normalizedPath, {
project,
lastAccess: now,
fileCount,
estimatedMemoryMB,
hitCount: 0,
projectPath: normalizedPath
});

log.info(`Cached project ${normalizedPath}: ${fileCount} files, ~${estimatedMemoryMB.toFixed(1)}MB`);
} else {
log.warn(`Project ${normalizedPath} too large (${estimatedMemoryMB.toFixed(1)}MB) - skipping cache`);
}

return project;
} catch (error) {
log.error(`Failed to create project for ${normalizedPath}`, { error });
throw new Error(`Failed to initialize TypeScript project: ${error instanceof Error ? error.message : String(error)}`);
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider simplifying boolean checks.

The project creation logic is well-structured with proper error handling, performance optimizations, and memory management. However, the strict equality checks for boolean values are redundant.

Consider this refactor for cleaner code:

-      const hasTsConfig = require('fs').existsSync(tsConfigPath);
-
       const project = new Project({
-        tsConfigFilePath: hasTsConfig === true ? tsConfigPath : undefined,
+        tsConfigFilePath: hasTsConfig ? tsConfigPath : undefined,
         skipAddingFilesFromTsConfig: false,
         skipFileDependencyResolution: true,
         skipLoadingLibFiles: true,
       });

       // Add source files manually if no tsconfig
-      if (hasTsConfig === false) {
+      if (!hasTsConfig) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Create new project with better error handling
try {
log.info(`Initializing new ts-morph project for ${normalizedPath}`);
const tsConfigPath = path.join(normalizedPath, 'tsconfig.json');
const hasTsConfig = require('fs').existsSync(tsConfigPath);
// Estimate memory usage
const fileCount = project.getSourceFiles().length;
const estimatedMemoryMB = fileCount * this.MEMORY_PER_FILE_MB;
// Cache if within limits
if (estimatedMemoryMB <= this.MAX_PROJECT_MEMORY_MB) {
// Evict if needed
this.ensureCapacity(estimatedMemoryMB);
this.cache.set(normalizedPath, {
project,
lastAccess: now,
fileCount,
estimatedMemoryMB,
hitCount: 0
const project = new Project({
tsConfigFilePath: hasTsConfig === true ? tsConfigPath : undefined,
skipAddingFilesFromTsConfig: false,
skipFileDependencyResolution: true, // Better performance
skipLoadingLibFiles: true, // Skip loading lib files for better performance
});
} else {
log.warn(`Project ${normalizedPath} too large (${estimatedMemoryMB.toFixed(1)}MB) - skipping cache`);
}
return project;
// Add source files manually if no tsconfig
if (hasTsConfig === false) {
const sourceFiles = fg.sync('**/*.{ts,tsx,js,jsx}', {
cwd: normalizedPath,
ignore: ['node_modules/**', '.git/**', 'dist/**', 'build/**'],
onlyFiles: true,
absolute: true,
dot: true,
unique: true,
});
project.addSourceFilesAtPaths(sourceFiles);
}
// Estimate memory usage
const fileCount = project.getSourceFiles().length;
const estimatedMemoryMB = Math.max(fileCount * this.MEMORY_PER_FILE_MB, 10); // Minimum 10MB
// Cache if within limits
if (estimatedMemoryMB <= this.MAX_PROJECT_MEMORY_MB) {
// Evict if needed
this.ensureCapacity(estimatedMemoryMB);
this.cache.set(normalizedPath, {
project,
lastAccess: now,
fileCount,
estimatedMemoryMB,
hitCount: 0,
projectPath: normalizedPath
});
log.info(`Cached project ${normalizedPath}: ${fileCount} files, ~${estimatedMemoryMB.toFixed(1)}MB`);
} else {
log.warn(`Project ${normalizedPath} too large (${estimatedMemoryMB.toFixed(1)}MB) - skipping cache`);
}
return project;
} catch (error) {
log.error(`Failed to create project for ${normalizedPath}`, { error });
throw new Error(`Failed to initialize TypeScript project: ${error instanceof Error ? error.message : String(error)}`);
}
}
// Create new project with better error handling
try {
log.info(`Initializing new ts-morph project for ${normalizedPath}`);
const tsConfigPath = path.join(normalizedPath, 'tsconfig.json');
const hasTsConfig = require('fs').existsSync(tsConfigPath);
const project = new Project({
tsConfigFilePath: hasTsConfig ? tsConfigPath : undefined,
skipAddingFilesFromTsConfig: false,
skipFileDependencyResolution: true, // Better performance
skipLoadingLibFiles: true, // Skip loading lib files for better performance
});
// Add source files manually if no tsconfig
if (!hasTsConfig) {
const sourceFiles = fg.sync('**/*.{ts,tsx,js,jsx}', {
cwd: normalizedPath,
ignore: ['node_modules/**', '.git/**', 'dist/**', 'build/**'],
onlyFiles: true,
absolute: true,
dot: true,
unique: true,
});
project.addSourceFilesAtPaths(sourceFiles);
}
// Estimate memory usage
const fileCount = project.getSourceFiles().length;
const estimatedMemoryMB = Math.max(fileCount * this.MEMORY_PER_FILE_MB, 10); // Minimum 10MB
// Cache if within limits
if (estimatedMemoryMB <= this.MAX_PROJECT_MEMORY_MB) {
// Evict if needed
this.ensureCapacity(estimatedMemoryMB);
this.cache.set(normalizedPath, {
project,
lastAccess: now,
fileCount,
estimatedMemoryMB,
hitCount: 0,
projectPath: normalizedPath
});
log.info(`Cached project ${normalizedPath}: ${fileCount} files, ~${estimatedMemoryMB.toFixed(1)}MB`);
} else {
log.warn(`Project ${normalizedPath} too large (${estimatedMemoryMB.toFixed(1)}MB) - skipping cache`);
}
return project;
} catch (error) {
log.error(`Failed to create project for ${normalizedPath}`, { error });
throw new Error(`Failed to initialize TypeScript project: ${error instanceof Error ? error.message : String(error)}`);
}
🤖 Prompt for AI Agents
In src/mastra/tools/semantic-utils.ts around lines 75 to 130, simplify redundant
strict boolean comparisons by replacing "hasTsConfig === true" with
"hasTsConfig" and "hasTsConfig === false" with "!hasTsConfig"; also assign fs
once (e.g., const fs = require('fs'); const hasTsConfig =
fs.existsSync(tsConfigPath);) to avoid repeated require calls and make the
intent clearer.

Comment on lines +167 to +191
/**
* Parse XML content using fast-xml-parser
*/
function parseXmlContent(xmlContent: string): Record<string, unknown> {
try {
const parserOptions = {
ignoreAttributes: false,
attributeNamePrefix: '@_',
textNodeName: '#text',
parseAttributeValue: true,
trimValues: true,
ignoreDeclaration: true,
}
const parser = new XMLParser(parserOptions)
return parser.parse(xmlContent)
} catch (error) {
log.warn('XML parsing failed', {
error: error instanceof Error ? error.message : String(error),
})
throw new ScrapingError(
`XML parsing failed: ${error instanceof Error ? error.message : String(error)}`,
'XML_PARSE_ERROR'
)
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Unused function parseXmlContent.

This function is defined but never called within this file. If it's intended for external use, consider exporting it. Otherwise, remove the dead code.

#!/bin/bash
# Verify if parseXmlContent is used anywhere in the codebase
rg -n 'parseXmlContent' --type ts
🤖 Prompt for AI Agents
In src/mastra/tools/web-scraper-tool.ts around lines 167 to 191, the function
parseXmlContent is defined but never used; either export it if it should be part
of the module API or remove it to eliminate dead code. If needed externally, add
an export (named export) and update any callers to import and use it; if it was
intended to be used internally, replace inline XML parsing calls with this
function; otherwise delete the entire function and its imports/logging related
to it.

Comment on lines 2403 to 2412
switch (inputData.format) {
case 'json':
{ const jsonContent = JSON.stringify(inputData.data, null, 2)
filePath = inputData.destination
await ensureDataDir()
filePath = path.isAbsolute(inputData.destination)
? inputData.destination
: path.join(DATA_DIR, inputData.destination)
await fs.mkdir(path.dirname(filePath), { recursive: true })
await fs.writeFile(filePath, jsonContent, 'utf-8')
break }
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Missing path validation before file write.

Unlike other tools, dataExporterTool doesn't call ValidationUtils.validateFilePath() before writing. When inputData.destination is a relative path, the join with DATA_DIR should be validated to prevent path traversal.

          await ensureDataDir()
          filePath = path.isAbsolute(inputData.destination)
            ? inputData.destination
            : path.join(DATA_DIR, inputData.destination)
+         if (!ValidationUtils.validateFilePath(filePath, DATA_DIR)) {
+           throw new ScrapingError('Invalid file path', 'INVALID_FILE_PATH')
+         }
          await fs.mkdir(path.dirname(filePath), { recursive: true })
          await fs.writeFile(filePath, jsonContent, 'utf-8')
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
switch (inputData.format) {
case 'json':
{ const jsonContent = JSON.stringify(inputData.data, null, 2)
filePath = inputData.destination
await ensureDataDir()
filePath = path.isAbsolute(inputData.destination)
? inputData.destination
: path.join(DATA_DIR, inputData.destination)
await fs.mkdir(path.dirname(filePath), { recursive: true })
await fs.writeFile(filePath, jsonContent, 'utf-8')
break }
switch (inputData.format) {
case 'json':
{ const jsonContent = JSON.stringify(inputData.data, null, 2)
await ensureDataDir()
filePath = path.isAbsolute(inputData.destination)
? inputData.destination
: path.join(DATA_DIR, inputData.destination)
if (!ValidationUtils.validateFilePath(filePath, DATA_DIR)) {
throw new ScrapingError('Invalid file path', 'INVALID_FILE_PATH')
}
await fs.mkdir(path.dirname(filePath), { recursive: true })
await fs.writeFile(filePath, jsonContent, 'utf-8')
break }
🤖 Prompt for AI Agents
In src/mastra/tools/web-scraper-tool.ts around lines 2403 to 2412, the code
writes JSON to a path built from DATA_DIR and inputData.destination without
validating the resolved path, allowing path traversal; fix by constructing the
final absolute path (e.g. path.isAbsolute ? inputData.destination :
path.resolve(DATA_DIR, inputData.destination)), then call
ValidationUtils.validateFilePath(finalPath) (or equivalent validation used
elsewhere) before creating directories or writing the file; only after
validation proceed with fs.mkdir(path.dirname(finalPath), { recursive: true })
and fs.writeFile(finalPath, jsonContent, 'utf-8').

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Review continued from previous batch...

Comment on lines +148 to +158
### Live Region Announcement (SPA route change)
```html
<div aria-live="polite" aria-atomic="true" id="route-announcer" class="sr-only"></div>
<script>
function announce(text) {
const el = document.getElementById('route-announcer');
el.textContent = text;
}
// Call announce(newTitle) on route change
</script>
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Add blank lines around code blocks for markdown compliance.

Multiple fenced code blocks lack proper spacing. Lines 149, 161, 220, 230, and 240 each need blank lines before their opening triple backticks.

 ### Live Region Announcement (SPA route change)
-```html
+
+```html
 <div aria-live="polite" aria-atomic="true" id="route-announcer" class="sr-only"></div>

Apply the same fix to code blocks at lines 161, 220, 230, and 240.

As per coding guidelines, all fenced code blocks must be surrounded by blank lines (MD031).

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

149-149: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
In .github/agents/accessibility.agent.md around lines 148–158 (and also at the
other reported locations: lines 161, 220, 230, and 240), several fenced code
blocks are missing blank lines around them; to fix, add a blank line immediately
before each opening triple-backtick fence (and ensure a blank line after the
closing fence as well) so every fenced code block is surrounded by blank lines
and complies with MD031.

6. **Detail Level**:

- Use clear, precise, and concise language.
- Include specific details and metrics whenever applicable.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Minor style note: consider simplifying redundant phrase.

The phrase "specific details and metrics" is slightly redundant—either "details and metrics" or "specific details" would be clearer. This is a minor style suggestion and not required.

Consider revising to "Include details and metrics whenever applicable" or keeping "Include specific information and metrics" for slight improvement in word economy.

🧰 Tools
🪛 LanguageTool

[style] ~42-~42: This phrase is redundant. Consider writing “details”.
Context: ...ise, and concise language. - Include specific details and metrics whenever applicable. - E...

(SPECIFIC_DETAILS)

🤖 Prompt for AI Agents
.github/agents/prd.agent.md around line 42: the phrase "Include specific details
and metrics whenever applicable." is slightly redundant; change it to a simpler
wording such as "Include details and metrics whenever applicable." or "Include
specific information and metrics whenever applicable." to improve clarity and
word economy; update the line to one of those alternatives and run a quick
spell/grammar check to ensure consistency with surrounding style.


- **Frontmatter**: `---\napplyTo: '.copilot-tracking/changes/YYYYMMDD-task-description-changes.md'\n---`
- **Markdownlint disable**: `<!-- markdownlint-disable-file -->`
- **Overview**: One sentence task description
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Minor grammar note: add hyphen for compound modifier.

"One sentence task description" should be "One-sentence task description" to properly hyphenate the compound modifier.

Apply this correction:

- **Overview**: One sentence task description
+ **Overview**: One-sentence task description
🧰 Tools
🪛 LanguageTool

[grammar] ~90-~90: Use a hyphen to join words.
Context: ...nt-disable-file -->` - Overview: One sentence task description - **Objectives...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
.github/agents/task-planner.agent.md around line 90: the phrase "One sentence
task description" is missing a hyphen for the compound modifier; update it to
"One-sentence task description" to apply correct hyphenation.

Comment thread README.md
Comment on lines +239 to 243
The frontend uses `@mastra/client-js` with TanStack Query for robust state management:

```typescript
// lib/mastra-client.ts
// lib/mastra-client.ts - Base client configuration
import { MastraClient } from "@mastra/client-js";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Add blank line before code block.

The fenced code block starting at line 242 should be preceded by a blank line to comply with markdown formatting standards.

 The frontend uses `@mastra/client-js` with TanStack Query for robust state management:
 
+
 ```typescript
 // lib/mastra-client.ts - Base client configuration
 import { MastraClient } from "@mastra/client-js";

As per coding guidelines, fenced code blocks should be surrounded by blank lines.

🤖 Prompt for AI Agents
In README.md around lines 239 to 243, the fenced TypeScript code block is not
preceded by a blank line; add a single blank line before the triple-backtick
fence that begins the code block (i.e., insert one empty line between the
preceding paragraph and the ```typescript line) so the code block is properly
separated per markdown guidelines.

Comment on lines +8 to +20
const DATA_DIR = path.join(process.cwd(), './data')

/**
* Ensure the data directory exists
*/
async function ensureDataDir(): Promise<void> {
const dataPath = path.resolve(DATA_DIR)
try {
await fs.mkdir(dataPath, { recursive: true })
} catch {
// Ignore errors - directory might already exist
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Clarify or remove the unused DATA_DIR/ensureDataDir side‑effect

This tool doesn’t read or write under ./data, so eagerly creating the directory on every execution is currently a no-op filesystem side-effect. Either wire this directory into real usage (e.g., storing artifacts) or document why it must exist globally; otherwise consider dropping ensureDataDir from this tool to avoid gratuitous I/O and hidden side-effects.

🤖 Prompt for AI Agents
In src/mastra/tools/multi-string-edit.tool.ts around lines 8 to 20, the file
unconditionally defines DATA_DIR and calls ensureDataDir which creates ./data
even though the tool does not use that directory; remove the gratuitous
side-effect by either (A) deleting the DATA_DIR constant and the ensureDataDir
function and any calls to it, or (B) if the directory is intended for storing
tool artifacts, explicitly wire it into the tool (use DATA_DIR for artifact
read/write and add a short comment documenting why the directory must exist),
then keep ensureDataDir; implement one of these two options and remove any
leftover unused imports or references.

Comment on lines +69 to 76
/**
* Check if a file path is within the specified boundary for security
*/
function isPathWithinBoundary(filePath: string, boundary: string): boolean {
const resolvedPath = path.resolve(filePath)
const resolvedBoundary = path.resolve(boundary)
return resolvedPath.startsWith(resolvedBoundary + path.sep) || resolvedPath === resolvedBoundary
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd /repo && wc -l src/mastra/tools/multi-string-edit.tool.ts

Repository: ssdeanx/AgentStack

Length of output: 117


🏁 Script executed:

cd /repo && cat -n src/mastra/tools/multi-string-edit.tool.ts

Repository: ssdeanx/AgentStack

Length of output: 117


🏁 Script executed:

pwd && git ls-files | head -20

Repository: ssdeanx/AgentStack

Length of output: 739


🏁 Script executed:

wc -l /home/jailuser/git/src/mastra/tools/multi-string-edit.tool.ts && cat -n /home/jailuser/git/src/mastra/tools/multi-string-edit.tool.ts

Repository: ssdeanx/AgentStack

Length of output: 10563


🏁 Script executed:

grep -r "RuntimeContext" /home/jailuser/git/src/mastra/tools/ --include="*.ts" | head -20

Repository: ssdeanx/AgentStack

Length of output: 2508


🏁 Script executed:

grep -r "context\." /home/jailuser/git/src/mastra/tools/ --include="*.ts" | grep -v "node_modules" | head -30

Repository: ssdeanx/AgentStack

Length of output: 174


🏁 Script executed:

grep -A 10 "execute:" /home/jailuser/git/src/mastra/tools/polygon-tools.ts | head -30

Repository: ssdeanx/AgentStack

Length of output: 1036


🏁 Script executed:

grep -r "context\?.projectRoot\|context\?.workspaceRoot\|context\?.baseDir" /home/jailuser/git/src/mastra/ --include="*.ts"

Repository: ssdeanx/AgentStack

Length of output: 44


🏁 Script executed:

grep -r "interface.*Context\|type.*Context" /home/jailuser/git/src/mastra/ --include="*.ts" | grep -v "node_modules\|test" | head -20

Repository: ssdeanx/AgentStack

Length of output: 2251


🏁 Script executed:

grep -r "process.cwd()\|cwd" /home/jailuser/git/src/mastra/tools/ --include="*.ts" | grep -v "test"

Repository: ssdeanx/AgentStack

Length of output: 1662


🏁 Script executed:

grep -A 20 "export interface CodingRuntimeContext" /home/jailuser/git/src/mastra/agents/codingAgents.ts

Repository: ssdeanx/AgentStack

Length of output: 910


Enforce path boundary from trusted RuntimeContext, not user input

The isPathWithinBoundary function itself is correct, but defaultBoundary is derived from untrusted input: projectRoot ?? process.cwd() (line 229). An agent could pass projectRoot: "/" to expand the boundary and access files outside the intended restriction.

The context parameter provides access to requestContext, which should contain a trusted projectRoot from CodingRuntimeContext. Derive the effective boundary from there instead:

+    const trustedBase = context?.requestContext?.get('projectRoot') ?? process.cwd()
-    const defaultBoundary = projectRoot ?? process.cwd()
+    const defaultBoundary = projectRoot
+      ? path.resolve(trustedBase, projectRoot)
+      : trustedBase

This ensures edits remain constrained to a server-controlled root even when projectRoot is provided by the agent.

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +78 to 186
/**
* Process a single file edit operation
*/
async function processFileEdit(
edit: z.infer<typeof editOperationSchema>,
defaultBoundary: string,
dryRun: boolean,
createBackup: boolean,
appliedBackups: Map<string, string>,
writer?: { custom: (data: { type: string; data: { message: string } }) => Promise<void> }
): Promise<z.infer<typeof editResultSchema>> {
const { filePath, oldString, newString, description, useRegex, replaceAll } = edit

if (!isPathWithinBoundary(filePath, defaultBoundary)) {
return {
filePath,
status: 'failed',
reason: `Path outside project boundary: ${defaultBoundary}`,
}
}

return diffLines.join('\n')
if (!await fileExists(filePath)) {
return {
filePath,
status: 'failed',
reason: 'File does not exist',
}
}

try {
await writer?.custom({ type: 'data-tool-progress', data: { message: `📖 Reading file: ${filePath}` } });
const content = await fs.readFile(filePath, 'utf-8')
let newContent = content
let matchFound = false

if (useRegex === true) {
const flags = replaceAll === true ? 'g' : ''
const regex = new RegExp(oldString, flags)
if (regex.test(content)) {
newContent = content.replace(regex, newString)
matchFound = true
}
} else if (content.includes(oldString)) {
if (replaceAll === true) {
newContent = content.split(oldString).join(newString)
matchFound = true
} else {
const occurrences = content.split(oldString).length - 1
if (occurrences > 1) {
return {
filePath,
status: 'skipped',
reason: `Multiple occurrences found (${occurrences}). Use replaceAll: true to replace all.`,
}
}
newContent = content.replace(oldString, newString)
matchFound = true
}
}

if (!matchFound) {
return {
filePath,
status: 'skipped',
reason: 'Old string/pattern not found in file',
}
}

const diff = createPatch(
path.basename(filePath),
content,
newContent,
'original',
'modified'
)

if (dryRun) {
return {
filePath,
status: 'applied',
reason: description ?? 'Dry run - changes not written',
diff,
}
}

if (createBackup && !appliedBackups.has(filePath)) {
const backupPath = `${filePath}.bak`
await fs.copyFile(filePath, backupPath)
appliedBackups.set(filePath, backupPath)
}

await fs.writeFile(filePath, newContent, 'utf-8')

return {
filePath,
status: 'applied',
reason: description,
backup: appliedBackups.get(filePath),
diff,
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error)
return {
filePath,
status: 'failed',
reason: errorMessage,
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n src/mastra/tools/multi-string-edit.tool.ts | head -100

Repository: ssdeanx/AgentStack

Length of output: 4078


🏁 Script executed:

cat -n src/mastra/tools/multi-string-edit.tool.ts | tail -50

Repository: ssdeanx/AgentStack

Length of output: 2021


🏁 Script executed:

# Check full file size to understand scope
wc -l src/mastra/tools/multi-string-edit.tool.ts

Repository: ssdeanx/AgentStack

Length of output: 108


🏁 Script executed:

# Check if this tool is registered and how it's called
grep -r "multi-string-edit" --include="*.ts" --include="*.tsx" src/ | head -20

Repository: ssdeanx/AgentStack

Length of output: 165


🏁 Script executed:

# Check if RuntimeContext is used in this directory's tools
grep -r "RuntimeContext" src/mastra/tools/ | head -10

Repository: ssdeanx/AgentStack

Length of output: 1062


🏁 Script executed:

# Look at the tool registration to understand exposure
grep -r "createTool" src/mastra/tools/multi-string-edit.tool.ts -A 30 | tail -40

Repository: ssdeanx/AgentStack

Length of output: 1789


🏁 Script executed:

# Check if there's any AI agent prompt validation or pattern constraints
grep -r "oldString\|regex" src/mastra/agents/codingAgents.ts -B 3 -A 3

Repository: ssdeanx/AgentStack

Length of output: 44


🏁 Script executed:

# Check tool invocation patterns to understand actual input sources
grep -A 10 -B 5 "multiStringEditTool" src/mastra/agents/codingAgents.ts | head -30

Repository: ssdeanx/AgentStack

Length of output: 1143


Add input validation for regex pattern complexity to prevent ReDoS in agent-controlled regex operations

The useRegex flag allows agent-generated patterns to be directly compiled into a RegExp and executed against file contents without validation. While this tool is used exclusively through the coding agent (not exposed as a public API), a malicious or accidentally expensive pattern could cause noticeable slowdowns or timeouts on large files.

Suggested fix: Add a simple length constraint before regex compilation:

if (useRegex === true) {
  const flags = replaceAll === true ? 'g' : ''
  if (oldString.length > 512) {
    return {
      filePath,
      status: 'failed',
      reason: 'Regex pattern too long; refusing to run for safety.',
    }
  }
  const regex = new RegExp(oldString, flags)

You can adjust the threshold as needed. This is low-friction defensive hardening.

Additionally, consider adding RuntimeContext to this tool per coding guidelines for tools in src/mastra/tools, even though access control is not currently required.

🧰 Tools
🪛 ast-grep (0.40.0)

[warning] 114-114: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(oldString, flags)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

🤖 Prompt for AI Agents
In src/mastra/tools/multi-string-edit.tool.ts around lines 78 to 186, the
handler compiles agent-supplied regexes without validation which risks
ReDoS/expensive patterns; add a defensive length check (e.g. if oldString.length
> 512) before constructing new RegExp and return a failed result with a clear
reason if it exceeds the threshold, then proceed to create the RegExp only when
within limits; also consider (per guidelines) wiring in RuntimeContext to the
tool signature for future access control/auditing.

Comment on lines 231 to 238
for (const edit of edits) {
const { filePath, oldString, newString, description } = edit

if (!isPathWithinBoundary(filePath, defaultBoundary)) {
results.push({
filePath,
status: 'failed',
reason: `Path outside project boundary: ${defaultBoundary}`,
})
hasFailure = true
continue
}

if (!await fileExists(filePath)) {
results.push({
filePath,
status: 'failed',
reason: 'File does not exist',
})
hasFailure = true
continue
}

try {
const content = await fs.readFile(filePath, 'utf-8')
let newContent = content
let matchFound = false

if (edit.useRegex) {
const flags = edit.replaceAll ? 'g' : ''
const regex = new RegExp(edit.oldString, flags)
if (regex.test(content)) {
newContent = content.replace(regex, edit.newString)
matchFound = true
}
}
else if (content.includes(edit.oldString)) {
if (edit.replaceAll) {
newContent = content.split(edit.oldString).join(edit.newString)
matchFound = true
} else {
const occurrences = content.split(edit.oldString).length - 1
if (occurrences > 1) {
results.push({
filePath,
status: 'skipped',
reason: `Multiple occurrences found (${occurrences}). Use replaceAll: true to replace all.`,
})
continue
}
newContent = content.replace(edit.oldString, edit.newString)
matchFound = true
}
}

if (!matchFound) {
results.push({
filePath,
status: 'skipped',
reason: 'Old string/pattern not found in file',
})
continue
}

const diff = createPatch(path.basename(filePath), content, newContent, 'original', 'modified')

if (dryRun) {
results.push({
filePath,
status: 'applied',
reason: description ?? 'Dry run - changes not written',
diff,
})
continue
}

if (createBackup && !appliedBackups.has(filePath)) {
const backupPath = `${filePath}.bak`
await fs.copyFile(filePath, backupPath)
appliedBackups.set(filePath, backupPath)
}

await fs.writeFile(filePath, newContent, 'utf-8')

results.push({
filePath,
status: 'applied',
reason: description,
backup: appliedBackups.get(filePath),
diff,
})
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error)
results.push({
filePath,
status: 'failed',
reason: errorMessage,
})
hasFailure = true
await writer?.custom({ type: 'data-tool-progress', data: { message: `✏️ Processing edit for: ${edit.filePath}` } });
const result = await processFileEdit(edit, defaultBoundary, dryRun, createBackup, appliedBackups, writer);
results.push(result);
if (result.status === 'failed') {
hasFailure = true;
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider fail‑fast behavior and clearer “atomicity” guarantees

The main loop continues processing edits even after a failure, then rolls back all files with backups. That yields “eventual” atomicity as long as rollback succeeds, but:

  • You do extra writes and backups after the first failure.
  • A crash between later writes and rollback can leave partial edits on disk.

If you prefer stricter semantics and fewer side effects once something fails, consider short‑circuiting on first failure:

    for (const edit of edits) {
      await writer?.custom({ type: 'data-tool-progress', data: { message: `✏️ Processing edit for: ${edit.filePath}` } });
      const result = await processFileEdit(edit, defaultBoundary, dryRun, createBackup, appliedBackups, writer);
      results.push(result);
-      if (result.status === 'failed') {
-        hasFailure = true;
-      }
+      if (result.status === 'failed') {
+        hasFailure = true;
+        break;
+      }
    }

If you intentionally want “try all edits, then rollback” semantics, consider documenting that behavior in the tool description so callers don’t over-assume atomicity.

Also applies to: 240-259, 264-264

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants