Conversation
- 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.
Learn moreAll Green is an AI agent that automatically: ✅ Addresses code review comments ✅ Fixes failing CI checks ✅ Resolves merge conflicts |
There was a problem hiding this comment.
Sorry @ssdeanx, your pull request is larger than the review limit of 150000 diff characters
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings. WalkthroughThis 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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
|
🤖 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. |
|
🤖 I'm sorry @ssdeanx, but I was unable to process your request. Please see the logs for more details. |
Summary of ChangesHello @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
Using Gemini Code AssistThe 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
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 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
|
Greptile OverviewGreptile SummaryThis 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
Critical IssueThe export mapping in Additional Issues
ImpactUsers 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
Important Files ChangedFile Analysis
Sequence DiagramsequenceDiagram
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
|
| export { AgentDetails } from "./agent-details" | ||
| export { AgentToolsTab } from "./agent-tools-tab" | ||
| export { AgentEvalsTab } from "./agent-evals-tab" | ||
| export { AgentEvalsTab } from "./agent-tab" |
There was a problem hiding this 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.
| 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> |
There was a problem hiding this 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:
| <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.| * 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' |
There was a problem hiding this 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
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.There was a problem hiding this comment.
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
AgentTabcomponent with loading/error states for agent information display - Development sign-in utility (
auth-dev.ts) for local development authentication - Migration from
xmldomtofast-xml-parserfor XML parsing across data processing tools - Migration from
globtofast-globfor 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 |
| import { specGenerationWorkflow } from './workflows/spec-generation-workflow'; | ||
| import { ResearchRuntimeContext } from './agents/index'; | ||
|
|
||
| const ml = process.env.MLFLOW_EXPERIMENT_ID |
There was a problem hiding this comment.
Unused variable ml.
| import { ProjectCache, PythonParser } from './semantic-utils'; | ||
| import { Node } from 'ts-morph'; | ||
| import type { SourceFile } from 'ts-morph'; | ||
| import { Node, SyntaxKind } from 'ts-morph'; |
There was a problem hiding this comment.
Unused import SyntaxKind.
| return lines.slice(start, end).join('\n'); | ||
| } | ||
|
|
||
| function getPythonContext(lines: string[], lineIndex: number, contextLines: number): string { |
There was a problem hiding this comment.
Unused function getPythonContext.
| import { ProjectCache, PythonParser } from './semantic-utils'; | ||
| import { Node } from 'ts-morph'; | ||
| import type { SourceFile } from 'ts-morph'; | ||
| import { Node, SyntaxKind } from 'ts-morph'; |
There was a problem hiding this comment.
Unused import SyntaxKind.
| /** | ||
| * Parse XML content using fast-xml-parser | ||
| */ | ||
| function parseXmlContent(xmlContent: string): Record<string, unknown> { |
There was a problem hiding this comment.
Unused function parseXmlContent.
| if (!trimmed) {continue} | ||
| function calculateLoc(content: string): { loc: number; totalLines: number } { | ||
| const totalLines = content.split('\n').length | ||
| let sanitized = content |
There was a problem hiding this comment.
The initial value of sanitized is unused, since it is always overwritten.
There was a problem hiding this comment.
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> |
There was a problem hiding this comment.
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.
| <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()}`; |
There was a problem hiding this comment.
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.
| coverage/ | ||
| build/ | ||
| out/ | ||
| logs/ | ||
| /.vscode/ | ||
| /.mastra/ | ||
| /.kilocode/ | ||
| /.github/ | ||
| /*.log | ||
| memory-bank/ | ||
| memories/ | ||
| docs/ | ||
| components/ui/ | ||
| docker/ | ||
| coverage/ |
| {agent.description !== null && ( | ||
| <p className="text-sm text-muted-foreground">{agent.description}</p> | ||
| )} |
There was a problem hiding this comment.
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.
| {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"> | |||
There was a problem hiding this comment.
| 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 | ||
| ) |
There was a problem hiding this comment.
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.
| 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) | |
| ) |
| {agent.tools.map((tool, index) => ( | ||
| <Badge key={index} variant="secondary">{tool.name}</Badge> | ||
| ))} |
There was a problem hiding this comment.
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.
| {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())) |
There was a problem hiding this comment.
There was a problem hiding this comment.
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 theSymbolInfointerface.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: Inconsistentcontextandkindfields in precise lookup path.The precise lookup path sets
contextandkindto empty strings, while the name-based search path (line 269-270) properly populates these fields usinggetCodeContextandgetReferenceKind. 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 emptycontextandkindfields.Similar to the precise lookup path, Python references have empty
contextandkind. The unusedgetPythonContexthelper (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
ReferenceContexttype 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.writeFilepattern for security, butsiteMapExtractorToolusesfs.writeFiledirectly. 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.realpathwill fail for new files.At line 155,
fs.realpath(fullPath)is called before the file is created. For new files, this throwsENOENTbecauserealpathrequires 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
realpathif 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
handleDeleteThreadfunction deletes the thread but doesn't clearselectedThreadIdor 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: Missingfetcherin useEffect dependency array causes stale closures.The
refetchcallback depends onfetcher, but theuseEffectonly usesdepswhich doesn't includefetcher. If the fetcher function changes identity, the effect won't re-run with the new fetcher. Additionally, ESLint will flagdepsas 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
⛔ Files ignored due to path filters (1)
package-lock.jsonis 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 thepages/directory for new projects.
Files:
app/dashboard/agents/_components/agent-list-item.tsxapp/dashboard/agents/_components/agent-tab.tsxapp/dashboard/agents/_components/index.tsapp/dashboard/agents/_components/agent-list.tsxapp/dashboard/memory/page.tsxapp/dashboard/telemetry/page.tsxapp/dashboard/agents/_components/agent-details.tsxapp/dashboard/workflows/page.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)
**/*.{js,jsx,ts,tsx}: Usenext/dynamicfor dynamic imports to load components only when needed, improving initial load time.
Usenext/imagecomponent 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.
Usereact-hook-formfor 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 usesetStateor hooks to update state instead of mutating state directly.
Include a complete dependency array inuseEffecthooks to prevent unexpected behavior.
Avoid writing server-side code in client components to prevent exposing secrets or causing unexpected behavior.
Usetry...catchblocks for handling errors in asynchronous operations.
Implement error boundary components usinggetDerivedStateFromErrororcomponentDidCatchlifecycle 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 inuseEffecthooks 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.tsxlib/auth-dev.tssrc/mastra/tools/multi-string-edit.tool.tsapp/dashboard/agents/_components/agent-tab.tsxapp/dashboard/agents/_components/index.tslib/mastra-client.tssrc/mastra/tools/data-file-manager.tslib/auth.tsapp/dashboard/agents/_components/agent-list.tsxsrc/mastra/index.tssrc/mastra/tools/code-search.tool.tslib/client-stream-to-ai-sdk.tsapp/dashboard/memory/page.tsxapp/dashboard/telemetry/page.tsxlib/types/mastra-api.tssrc/mastra/tools/diff-review.tool.tsapp/dashboard/agents/_components/agent-details.tsxsrc/mastra/tools/find-symbol.tool.tsapp/dashboard/workflows/page.tsxsrc/mastra/tools/find-references.tool.tssrc/mastra/tools/web-scraper-tool.tssrc/mastra/tools/semantic-utils.tslib/hooks/use-mastra.tslib/hooks/use-dashboard-queries.tssrc/mastra/tools/code-analysis.tool.tssrc/mastra/tools/data-processing-tools.tssrc/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.tsxapp/dashboard/agents/_components/agent-tab.tsxapp/dashboard/agents/_components/index.tsapp/dashboard/agents/_components/agent-list.tsxapp/dashboard/memory/page.tsxapp/dashboard/telemetry/page.tsxapp/dashboard/agents/_components/agent-details.tsxapp/dashboard/workflows/page.tsx
app/dashboard/**/*.{ts,tsx}
📄 CodeRabbit inference engine (app/dashboard/AGENTS.md)
app/dashboard/**/*.{ts,tsx}: Use custom React hooks fromlib/hooks/use-mastra.tsto 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.tsxapp/dashboard/agents/_components/agent-tab.tsxapp/dashboard/agents/_components/index.tsapp/dashboard/agents/_components/agent-list.tsxapp/dashboard/memory/page.tsxapp/dashboard/telemetry/page.tsxapp/dashboard/agents/_components/agent-details.tsxapp/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.tsxlib/auth-dev.tssrc/mastra/tools/multi-string-edit.tool.tsapp/dashboard/agents/_components/agent-tab.tsxapp/dashboard/agents/_components/index.tslib/mastra-client.tssrc/mastra/tools/data-file-manager.tslib/auth.tsapp/dashboard/agents/_components/agent-list.tsxsrc/mastra/index.tssrc/mastra/tools/code-search.tool.tslib/client-stream-to-ai-sdk.tsapp/dashboard/memory/page.tsxapp/dashboard/telemetry/page.tsxlib/types/mastra-api.tssrc/mastra/tools/diff-review.tool.tsapp/dashboard/agents/_components/agent-details.tsxsrc/mastra/tools/find-symbol.tool.tsapp/dashboard/workflows/page.tsxsrc/mastra/tools/find-references.tool.tssrc/mastra/tools/web-scraper-tool.tssrc/mastra/tools/semantic-utils.tslib/hooks/use-mastra.tslib/hooks/use-dashboard-queries.tssrc/mastra/tools/code-analysis.tool.tssrc/mastra/tools/data-processing-tools.tssrc/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.tsxapp/dashboard/agents/_components/agent-tab.tsxapp/dashboard/agents/_components/index.tsapp/dashboard/agents/_components/agent-list.tsxapp/dashboard/memory/page.tsxapp/dashboard/telemetry/page.tsxapp/dashboard/agents/_components/agent-details.tsxapp/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.tsxapp/dashboard/agents/_components/agent-tab.tsxapp/dashboard/agents/_components/index.tsapp/dashboard/agents/_components/agent-list.tsxapp/dashboard/memory/page.tsxapp/dashboard/telemetry/page.tsxapp/dashboard/agents/_components/agent-details.tsxapp/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.tsxapp/dashboard/agents/_components/agent-tab.tsxapp/dashboard/agents/_components/index.tsapp/dashboard/agents/_components/agent-list.tsxapp/dashboard/memory/page.tsxapp/dashboard/telemetry/page.tsxapp/dashboard/agents/_components/agent-details.tsxapp/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.tsxlib/auth-dev.tssrc/mastra/tools/multi-string-edit.tool.tsapp/dashboard/agents/_components/agent-tab.tsxapp/dashboard/agents/_components/index.tslib/mastra-client.tssrc/mastra/tools/data-file-manager.tslib/auth.tsapp/dashboard/agents/_components/agent-list.tsxsrc/mastra/index.tssrc/mastra/tools/code-search.tool.tslib/client-stream-to-ai-sdk.tsapp/dashboard/memory/page.tsxapp/dashboard/telemetry/page.tsxlib/types/mastra-api.tssrc/mastra/tools/diff-review.tool.tsapp/dashboard/agents/_components/agent-details.tsxsrc/mastra/tools/find-symbol.tool.tsapp/dashboard/workflows/page.tsxsrc/mastra/tools/find-references.tool.tssrc/mastra/tools/web-scraper-tool.tssrc/mastra/tools/semantic-utils.tslib/hooks/use-mastra.tslib/hooks/use-dashboard-queries.tssrc/mastra/tools/code-analysis.tool.tssrc/mastra/tools/data-processing-tools.tssrc/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.tsxlib/auth-dev.tssrc/mastra/tools/multi-string-edit.tool.tsapp/dashboard/agents/_components/agent-tab.tsxapp/dashboard/agents/_components/index.tslib/mastra-client.tssrc/mastra/tools/data-file-manager.tslib/auth.tsapp/dashboard/agents/_components/agent-list.tsxsrc/mastra/index.tssrc/mastra/tools/code-search.tool.tslib/client-stream-to-ai-sdk.tsapp/dashboard/memory/page.tsxapp/dashboard/telemetry/page.tsxlib/types/mastra-api.tssrc/mastra/tools/diff-review.tool.tsapp/dashboard/agents/_components/agent-details.tsxsrc/mastra/tools/find-symbol.tool.tsapp/dashboard/workflows/page.tsxsrc/mastra/tools/find-references.tool.tssrc/mastra/tools/web-scraper-tool.tssrc/mastra/tools/semantic-utils.tslib/hooks/use-mastra.tslib/hooks/use-dashboard-queries.tssrc/mastra/tools/code-analysis.tool.tssrc/mastra/tools/data-processing-tools.tssrc/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.tssrc/mastra/tools/multi-string-edit.tool.tsapp/dashboard/agents/_components/index.tslib/mastra-client.tssrc/mastra/tools/data-file-manager.tslib/auth.tssrc/mastra/index.tssrc/mastra/tools/code-search.tool.tslib/client-stream-to-ai-sdk.tslib/types/mastra-api.tssrc/mastra/tools/diff-review.tool.tssrc/mastra/tools/find-symbol.tool.tssrc/mastra/tools/find-references.tool.tssrc/mastra/tools/web-scraper-tool.tssrc/mastra/tools/semantic-utils.tslib/hooks/use-mastra.tslib/hooks/use-dashboard-queries.tssrc/mastra/tools/code-analysis.tool.tssrc/mastra/tools/data-processing-tools.tssrc/mastra/types/excalidraw-to-svg.d.ts
src/mastra/tools/**/*.ts
📄 CodeRabbit inference engine (src/mastra/AGENTS.md)
src/mastra/tools/**/*.ts: Use thecreateToolpattern with Zod schemas when adding new tools undersrc/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.tssrc/mastra/tools/data-file-manager.tssrc/mastra/tools/code-search.tool.tssrc/mastra/tools/diff-review.tool.tssrc/mastra/tools/find-symbol.tool.tssrc/mastra/tools/find-references.tool.tssrc/mastra/tools/web-scraper-tool.tssrc/mastra/tools/semantic-utils.tssrc/mastra/tools/code-analysis.tool.tssrc/mastra/tools/data-processing-tools.ts
src/mastra/{tools,workflows}/**/*.ts
📄 CodeRabbit inference engine (src/mastra/AGENTS.md)
Use
RuntimeContextto enforce access control in tools and workflows
Files:
src/mastra/tools/multi-string-edit.tool.tssrc/mastra/tools/data-file-manager.tssrc/mastra/tools/code-search.tool.tssrc/mastra/tools/diff-review.tool.tssrc/mastra/tools/find-symbol.tool.tssrc/mastra/tools/find-references.tool.tssrc/mastra/tools/web-scraper-tool.tssrc/mastra/tools/semantic-utils.tssrc/mastra/tools/code-analysis.tool.tssrc/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.tssrc/mastra/tools/data-file-manager.tssrc/mastra/index.tssrc/mastra/tools/code-search.tool.tssrc/mastra/tools/diff-review.tool.tssrc/mastra/tools/find-symbol.tool.tssrc/mastra/tools/find-references.tool.tssrc/mastra/tools/web-scraper-tool.tssrc/mastra/tools/semantic-utils.tssrc/mastra/tools/code-analysis.tool.tssrc/mastra/tools/data-processing-tools.tssrc/mastra/types/excalidraw-to-svg.d.ts
src/mastra/**/*
📄 CodeRabbit inference engine (src/AGENTS.md)
mastramodules can import fromutils, but must not import fromapporcli(excepttypes)
Files:
src/mastra/tools/multi-string-edit.tool.tssrc/mastra/tools/data-file-manager.tssrc/mastra/index.tssrc/mastra/tools/code-search.tool.tssrc/mastra/tools/diff-review.tool.tssrc/mastra/tools/find-symbol.tool.tssrc/mastra/tools/find-references.tool.tssrc/mastra/tools/web-scraper-tool.tssrc/mastra/tools/semantic-utils.tssrc/mastra/tools/code-analysis.tool.tssrc/mastra/tools/data-processing-tools.tssrc/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 (with1.) 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:. 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, andpost_date.
Files:
README.mdAGENTS.md
src/mastra/index.ts
📄 CodeRabbit inference engine (src/AGENTS.md)
Enforce registration pattern in
mastra/index.tsfor 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.tsxorpage.jsxfiles within theapp/directory structure.
Files:
app/dashboard/memory/page.tsxapp/dashboard/telemetry/page.tsxapp/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.jsoruseHookName.ts).
Files:
lib/hooks/use-mastra.tslib/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
| --- | ||
| 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. |
There was a problem hiding this comment.
Align debug tool naming with configured tools and fix ordered list numbering
Two things to address here:
-
Tool name mismatch
-
The front‑matter
toolslist exposesread/problems(and noget_errors), while the instructions say:Use the
get_errorstool… This tool replaces the previously used#problemstool. -
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 ofget_errors, or addget_errorsto 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.
-
-
markdownlint MD029 (ordered list prefixes)
- The numbered steps under the different phases use prefixes like
3.and5.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.
- The numbered steps under the different phases use prefixes like
🧰 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 @@ | |||
| --- | |||
There was a problem hiding this comment.
🧩 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
fiRepository: 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:
- 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). - 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.
| - 🎯 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. |
There was a problem hiding this comment.
🧹 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.
| 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> |
There was a problem hiding this comment.
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.
| <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> |
There was a problem hiding this comment.
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.
| <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.
| function isSymbolExported(sourceFile: SourceFile, symbolName: string): boolean { | ||
| // Check if symbol is exported | ||
| const exports = sourceFile.getExportSymbols(); | ||
| return exports.some((exp: any) => exp.getName() === symbolName); | ||
| } |
There was a problem hiding this comment.
🧹 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.
| 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; | ||
| } |
There was a problem hiding this comment.
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.
| // 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)}`); | ||
| } | ||
| } |
There was a problem hiding this comment.
🧹 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.
| // 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.
| /** | ||
| * 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' | ||
| ) | ||
| } | ||
| } |
There was a problem hiding this comment.
🧹 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.
| 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 } |
There was a problem hiding this comment.
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.
| 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').
| ### 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> | ||
| ``` |
There was a problem hiding this comment.
🧹 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. |
There was a problem hiding this comment.
🧹 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 |
There was a problem hiding this comment.
🧹 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.
| 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"; |
There was a problem hiding this comment.
🧹 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.
| 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 | ||
| } | ||
| } |
There was a problem hiding this comment.
🧹 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.
| /** | ||
| * 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 | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cd /repo && wc -l src/mastra/tools/multi-string-edit.tool.tsRepository: ssdeanx/AgentStack
Length of output: 117
🏁 Script executed:
cd /repo && cat -n src/mastra/tools/multi-string-edit.tool.tsRepository: ssdeanx/AgentStack
Length of output: 117
🏁 Script executed:
pwd && git ls-files | head -20Repository: 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.tsRepository: ssdeanx/AgentStack
Length of output: 10563
🏁 Script executed:
grep -r "RuntimeContext" /home/jailuser/git/src/mastra/tools/ --include="*.ts" | head -20Repository: ssdeanx/AgentStack
Length of output: 2508
🏁 Script executed:
grep -r "context\." /home/jailuser/git/src/mastra/tools/ --include="*.ts" | grep -v "node_modules" | head -30Repository: ssdeanx/AgentStack
Length of output: 174
🏁 Script executed:
grep -A 10 "execute:" /home/jailuser/git/src/mastra/tools/polygon-tools.ts | head -30Repository: 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 -20Repository: 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.tsRepository: 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)
+ : trustedBaseThis 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.
| /** | ||
| * 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, | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n src/mastra/tools/multi-string-edit.tool.ts | head -100Repository: ssdeanx/AgentStack
Length of output: 4078
🏁 Script executed:
cat -n src/mastra/tools/multi-string-edit.tool.ts | tail -50Repository: ssdeanx/AgentStack
Length of output: 2021
🏁 Script executed:
# Check full file size to understand scope
wc -l src/mastra/tools/multi-string-edit.tool.tsRepository: 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 -20Repository: 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 -10Repository: 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 -40Repository: 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 3Repository: 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 -30Repository: 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.
| 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; | ||
| } | ||
| } |
There was a problem hiding this comment.
🧹 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

AgentTabcomponent that displays agent details including name, description, model, status, instructions, and tools.AgentTabcomponent usingLoadingSkeletonandEmptyState.auth-dev.tsto facilitate signing in as a development user using environment variables.USER_EMAILandUSER_PASSWORDenvironment variables and logs the result of the sign-in attempt.